/[pkg-mixmaster]/trunk/Mix/Src/nym.c
ViewVC logotype

Contents of /trunk/Mix/Src/nym.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 510 - (show annotations) (download)
Mon May 5 11:03:41 2003 UTC (10 years ago) by weaselp
File MIME type: text/plain
File size: 15570 byte(s)
Respect DISTANCE setting also when selecting the final hop.  This is
important in cases where the user chooses a chain like '*,*,valiant,*'.
Previously it was possible that valiant was taken as a last hop resulting
in a chain like '....,valiant,valiant'.
1 /* Mixmaster version 3 -- (C) 1999 Anonymizer Inc.
2
3 Mixmaster may be redistributed and modified under certain conditions.
4 This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
5 ANY KIND, either express or implied. See the file COPYRIGHT for
6 details.
7
8 Create nym server messages
9 $Id: nym.c,v 1.10 2003/05/05 11:03:41 weaselp Exp $ */
10
11
12 #include "mix3.h"
13 #include "pgp.h"
14 #include <string.h>
15 #include <time.h>
16 #include <assert.h>
17
18 int nym_config(int mode, char *nym, char *nymserver, BUFFER *pseudonym,
19 char *sendchain, int sendnumcopies, BUFFER *chains,
20 BUFFER *options)
21 {
22 #ifndef USE_PGP
23 return (-1);
24 #else /* end of not USE_PGP */
25 REMAILER remailer[MAXREM];
26 int badchains[MAXREM][MAXREM];
27 KEYRING *r;
28 int maxrem;
29 int chain[20];
30 char rchain[CHAINMAX];
31 BUFFER *userid, *msg, *req, *k, *line, *ek, *eklist, *key, *pubkey, *out,
32 *oldchains;
33 int latency;
34 int err = -1;
35 int status;
36 int desttype = MSG_MAIL;
37 int rblock = 0;
38 BUFFER *nymlist, *userpass, *config;
39 LOCK *nymlock;
40
41 userid = buf_new();
42 msg = buf_new();
43 req = buf_new();
44 k = buf_new();
45 line = buf_new();
46 ek = buf_new();
47 eklist = buf_new();
48 key = buf_new();
49 pubkey = buf_new();
50 out = buf_new();
51 config = buf_new();
52 nymlist = buf_new();
53 userpass = buf_new();
54 oldchains = buf_new();
55
56 for (;;) {
57 user_pass(userpass);
58 if (user_confirmpass(userpass))
59 break;
60 user_delpass();
61 }
62
63 if (nymserver) {
64 maxrem = t1_rlist(remailer, badchains);
65 if (maxrem < 1)
66 return (-1);
67 if (chain_select(chain, nymserver, maxrem, remailer, 2, NULL) != 1)
68 return (-1);
69 if (chain[0] == 0)
70 chain[0] = chain_randfinal(MSG_MAIL, remailer, badchains, maxrem, 2, NULL, -1);
71 if (chain[0] == -1)
72 return (-1);
73 assert(strchr(nym, '@') == NULL && strchr(remailer[chain[0]].addr, '@'));
74 strcatn(nym, strchr(remailer[chain[0]].addr, '@'), LINELEN);
75 buf_appends(config, remailer[chain[0]].addr);
76 } else
77 assert(strchr(nym, '@') != NULL);
78
79 status = nymlist_getnym(nym, config->length ? NULL : config, eklist, NULL,
80 NULL, oldchains);
81 if (mode == NYM_CREATE && status == NYM_OK)
82 mode = NYM_MODIFY;
83
84 buf_appendc(userid, '<');
85 buf_appends(userid, nym);
86 buf_appendc(userid, '>');
87
88 buf_sets(req, "Config:\nFrom: ");
89 buf_append(req, nym, strchr(nym, '@') - nym);
90 buf_appends(req, "\nNym-Commands:");
91 if (mode == NYM_CREATE)
92 buf_appends(req, " create?");
93 if (mode == NYM_DELETE)
94 buf_appends(req, " delete");
95 else {
96 if (options && options->length > 0) {
97 if (!bufleft(options, " "))
98 buf_appendc(req, ' ');
99 buf_cat(req, options);
100 }
101 if (pseudonym && pseudonym->length > 0) {
102 buf_appends(req, " name=\"");
103 buf_cat(req, pseudonym);
104 buf_appendc(req, '\"');
105 }
106 }
107 buf_nl(req);
108 if (mode == NYM_CREATE) {
109 buf_appends(req, "Public-Key:\n");
110
111 getkey:
112 r = pgpdb_open(NYMSECRING, userpass, 0, PGP_TYPE_PRIVATE);
113 if (r == NULL) {
114 err = -3;
115 goto end;
116 }
117 if (r->filetype == -1)
118 r->filetype = 0;
119
120 while (pgpdb_getnext(r, key, NULL, userid) != -1)
121 if (pgp_makepubkey(key, NULL, pubkey, userpass, 0) == 0)
122 err = 0;
123 pgpdb_close(r);
124 if (err != 0) {
125 if (err == -2)
126 goto end;
127 err = -2;
128 if (pseudonym && pseudonym->length) {
129 buf_set(userid, pseudonym);
130 buf_appendc(userid, ' ');
131 } else
132 buf_clear(userid);
133 buf_appendf(userid, "<%s>", nym);
134 pgp_keygen(PGP_ES_RSA, 0, userid, userpass, NULL, NYMSECRING, 2);
135 goto getkey;
136 }
137 pgp_armor(pubkey, PGP_ARMOR_NYMKEY);
138 buf_cat(req, pubkey);
139 }
140 if (mode != NYM_DELETE) {
141 if (nymlist_read(nymlist) == -1) {
142 user_delpass();
143 err = -1;
144 goto end;
145 }
146 if (chains)
147 for (;;) {
148 err = buf_getheader(chains, k, line);
149 if (err == -1 && rblock == 0)
150 break;
151 if (err != 0 && rblock == 1) {
152 buf_setrnd(ek, 16);
153 if (t1_encrypt(desttype, msg, rchain, latency, ek, NULL) != 0) {
154 err = -2;
155 goto end;
156 }
157 encode(ek, 0);
158 buf_cat(eklist, ek);
159 buf_nl(eklist);
160 buf_appends(req, "Reply-Block:\n");
161 buf_cat(req, msg);
162 buf_clear(msg);
163 rblock = 0;
164 continue;
165 }
166 if (bufieq(k, "Chain"))
167 strncpy(rchain, line->data, sizeof(rchain));
168 else if (bufieq(k, "Latency"))
169 sscanf(line->data, "%d", &latency);
170 else if (bufieq(k, "Null"))
171 desttype = MSG_NULL, rblock = 1;
172 else {
173 buf_appendheader(msg, k, line);
174 if (bufieq(k, "To"))
175 desttype = MSG_MAIL, rblock = 1;
176 if (bufieq(k, "Newsgroups"))
177 desttype = MSG_POST, rblock = 1;
178 }
179 }
180 }
181 nymlock = lockfile(NYMDB);
182 if (nymlist_read(nymlist) == 0) {
183 nymlist_del(nymlist, nym);
184 nymlist_append(nymlist, nym, config, options, pseudonym,
185 chains ? chains : oldchains, eklist,
186 mode == NYM_DELETE ? NYM_DELETED :
187 (status == -1 ? NYM_WAITING : status));
188 nymlist_write(nymlist);
189 } else
190 err = -1;
191 unlockfile(nymlock);
192
193 #ifdef DEBUG
194 buf_write(req, stderr);
195 #endif /* DEBUG */
196 buf_clear(line);
197 buf_appendc(line, '<');
198 buf_cat(line, config);
199 buf_appendc(line, '>');
200
201 err = pgp_encrypt(PGP_ENCRYPT | PGP_SIGN | PGP_TEXT | PGP_REMAIL,
202 req, line, userid, userpass, NULL, NYMSECRING);
203 if (err != 0)
204 goto end;
205 #ifdef DEBUG
206 buf_write(req, stderr);
207 #endif /* DEBUG */
208 buf_sets(out, "To: ");
209 buf_cat(out, config);
210 buf_nl(out);
211 buf_nl(out);
212 buf_cat(out, req);
213
214 err = mix_encrypt(desttype, out, sendchain, sendnumcopies, line);
215 if (err)
216 mix_status("%s\n", line->data);
217
218 end:
219 if (strchr(nym, '@')) *strchr(nym, '@') = '\0';
220 buf_free(userid);
221 buf_free(msg);
222 buf_free(req);
223 buf_free(k);
224 buf_free(line);
225 buf_free(ek);
226 buf_free(eklist);
227 buf_free(key);
228 buf_free(pubkey);
229 buf_free(out);
230 buf_free(nymlist);
231 buf_free(userpass);
232 buf_free(oldchains);
233 buf_free(config);
234 return (err);
235 #endif /* else if USE_PGP */
236 }
237
238 int nym_encrypt(BUFFER *msg, char *nym, int type)
239 {
240 #ifndef USE_PGP
241 return (-1);
242 #else /* end of not USE_PGP */
243 BUFFER *out, *userpass, *sig, *config;
244 int err = -1;
245
246 out = buf_new();
247 userpass = buf_new();
248 sig = buf_new();
249 config = buf_new();
250
251 if (nymlist_getnym(nym, config, NULL, NULL, NULL, NULL) == NYM_OK) {
252 buf_appends(out, "From: ");
253 buf_append(out, nym, strchr(nym, '@') - nym);
254 buf_nl(out);
255 if (type == MSG_POST) {
256 buf_appends(out, "To: ");
257 buf_appends(out, MAILtoNEWS);
258 buf_nl(out);
259 }
260 buf_cat(out, msg);
261 mail_encode(out, 0);
262 buf_appendc(sig, '<');
263 buf_appends(sig, nym);
264 buf_appendc(sig, '>');
265 #ifdef DEBUG
266 buf_write(out, stderr);
267 #endif /* DEBUG */
268 user_pass(userpass);
269 err = pgp_encrypt(PGP_ENCRYPT | PGP_SIGN | PGP_TEXT | PGP_REMAIL,
270 out, config, sig, userpass, NULL, NYMSECRING);
271 if (err == 0) {
272 buf_clear(msg);
273 buf_appends(msg, "To: send");
274 buf_appends(msg, strchr(nym, '@'));
275 buf_nl(msg);
276 buf_nl(msg);
277 buf_cat(msg, out);
278 }
279 }
280 buf_free(out);
281 buf_free(config);
282 buf_free(userpass);
283 buf_free(sig);
284 return (err);
285 #endif /* else if USE_PGP */
286 }
287
288 int nym_decrypt(BUFFER *msg, char *thisnym, BUFFER *log)
289 {
290 #ifndef USE_PGP
291 return (-1);
292 #else /* end of not USE_PGP */
293 BUFFER *pgpmsg, *out, *line;
294 BUFFER *nymlist, *userpass;
295 BUFFER *decr, *sig, *mid;
296 BUFFER *name, *rblocks, *eklist, *config;
297 int decrypted = 0;
298 int err = 1;
299 long ptr;
300 char nym[LINELEN];
301 BUFFER *ek, *opt;
302 int status;
303 LOCK *nymlock;
304 time_t t;
305 struct tm *tc;
306 char timeline[LINELEN];
307
308 pgpmsg = buf_new();
309 out = buf_new();
310 line = buf_new();
311 nymlist = buf_new();
312 userpass = buf_new();
313 config = buf_new();
314 ek = buf_new();
315 decr = buf_new();
316 sig = buf_new();
317 mid = buf_new();
318 opt = buf_new();
319 name = buf_new();
320 rblocks = buf_new();
321 eklist = buf_new();
322
323 if (thisnym)
324 thisnym[0] = '\0';
325 while ((ptr = msg->ptr, err = buf_getline(msg, line)) != -1) {
326 if (bufleft(line, begin_pgpmsg)) {
327 err = -1;
328 msg->ptr = ptr;
329 pgp_dearmor(msg, pgpmsg);
330 if (pgp_isconventional(pgpmsg)) {
331 user_pass(userpass);
332 nymlock = lockfile(NYMDB);
333 if (nymlist_read(nymlist) == -1)
334 user_delpass();
335 while (nymlist_get(nymlist, nym, config, eklist, opt, name,
336 rblocks, &status) >= 0) {
337 while (buf_getline(eklist, ek) == 0) {
338 decode(ek, ek);
339 if (t1_getreply(pgpmsg, ek, 20) == 0) {
340 buf_clear(out);
341 err = pgp_decrypt(pgpmsg, userpass, sig, NULL,
342 NYMSECRING);
343 buf_sets(out, "From nymserver ");
344 if (strchr(sig->data, '[') && strchr(sig->data, ']'))
345 buf_append(out, strchr(sig->data, '[') + 1,
346 strchr(sig->data, ']') -
347 strchr(sig->data, '[') - 1);
348 else {
349 t = time(NULL);
350 tc = localtime(&t);
351 strftime(timeline, LINELEN, "%a %b %d %H:%M:%S %Y", tc);
352 buf_appends(out, timeline);
353 }
354 buf_nl(out);
355 if (err == PGP_SIGOK &&
356 bufifind(sig, config->data)) {
357 buf_appends(out, "Nym: ");
358 if (status == NYM_WAITING)
359 buf_appends(out, "confirm ");
360 buf_appends(out, nym);
361 buf_nl(out);
362 if (thisnym && status == NYM_OK)
363 strncpy(thisnym, nym, LINELEN);
364 } else
365 buf_appends(out, "Warning: Signature verification failed!\n");
366 buf_cat(out, pgpmsg);
367 decrypted = 2;
368 if (log) {
369 digest_md5(out, mid);
370 encode(mid, 0);
371 if (buffind(log, mid->data)) {
372 decrypted = -1;
373 unlockfile(nymlock);
374 goto end;
375 } else {
376 buf_cat(log, mid);
377 buf_nl(log);
378 }
379 }
380 if (status == NYM_WAITING) {
381 nymlist_del(nymlist, nym);
382 nymlist_append(nymlist, nym, config, opt,
383 name, rblocks, eklist, NYM_OK);
384 }
385 break;
386 }
387 }
388 }
389 nymlist_write(nymlist);
390 unlockfile(nymlock);
391 }
392 if (decrypted == 0) {
393 user_pass(userpass);
394 err = pgp_decrypt(pgpmsg, userpass, sig, PGPPUBRING, PGPSECRING);
395 if (err == PGP_ERR)
396 err = pgp_decrypt(pgpmsg, userpass, sig, PGPPUBRING,
397 NYMSECRING);
398 #if 0
399 if (err == PGP_PASS || err == PGP_ERR)
400 user_delpass();
401 #endif /* 0 */
402 if (err != PGP_ERR && err != PGP_PASS && err != PGP_NOMSG &&
403 err != PGP_NODATA) {
404 buf_appends(out, info_beginpgp);
405 if (err == PGP_SIGOK)
406 buf_appendf(out, " (SIGNED)\n%s%b", info_pgpsig, sig);
407 buf_nl(out);
408 buf_cat(out, pgpmsg);
409 buf_appends(out, info_endpgp);
410 buf_nl(out);
411 decrypted = 1;
412 }
413 }
414 if (decrypted == 0) {
415 buf_cat(out, line);
416 buf_nl(out);
417 }
418 } else {
419 if (bufileft(line, info_beginpgp))
420 buf_appendc(out, ' '); /* escape info line in text */
421 buf_cat(out, line);
422 buf_nl(out);
423 }
424 }
425
426 if (decrypted)
427 buf_move(msg, out);
428 else
429 buf_rewind(msg);
430 if (decrypted == 2)
431 nym_decrypt(msg, thisnym, NULL);
432 end:
433 buf_free(pgpmsg);
434 buf_free(out);
435 buf_free(line);
436 buf_free(decr);
437 buf_free(sig);
438 buf_free(mid);
439 buf_free(opt);
440 buf_free(name);
441 buf_free(config);
442 buf_free(rblocks);
443 buf_free(eklist);
444 buf_free(nymlist);
445 buf_free(userpass);
446 buf_free(ek);
447 return (decrypted);
448 #endif /* else if USE_PGP */
449 }
450
451 int nymlist_read(BUFFER *list)
452 {
453 #ifdef USE_PGP
454 BUFFER *key;
455
456 #endif /* USE_PGP */
457 FILE *f;
458 int err = 0;
459
460 buf_clear(list);
461 f = mix_openfile(NYMDB, "rb");
462 if (f != NULL) {
463 buf_read(list, f);
464 fclose(f);
465 #ifdef USE_PGP
466 key = buf_new();
467 user_pass(key);
468 if (key->length)
469 if (pgp_decrypt(list, key, NULL, NULL, NULL) < 0) {
470 buf_clear(list);
471 err = -1;
472 }
473 buf_free(key);
474 #endif /* USE_PGP */
475 }
476 return (err);
477 }
478
479 int nymlist_write(BUFFER *list)
480 {
481 #ifdef USE_PGP
482 BUFFER *key;
483
484 #endif /* USE_PGP */
485 FILE *f;
486
487 if (list->length == 0)
488 return (-1);
489
490 #ifdef USE_PGP
491 key = buf_new();
492 user_pass(key);
493 if (key->length)
494 pgp_encrypt(PGP_NCONVENTIONAL | PGP_NOARMOR, list, key, NULL, NULL, NULL,
495 NULL);
496 buf_free(key);
497 #endif /* USE_PGP */
498 f = mix_openfile(NYMDB, "wb");
499 if (f == NULL)
500 return (-1);
501 else {
502 buf_write(list, f);
503 fclose(f);
504 }
505 return (0);
506 }
507
508 int nymlist_get(BUFFER *list, char *nym, BUFFER *config, BUFFER *ek,
509 BUFFER *opt, BUFFER *name, BUFFER *chains, int *status)
510 {
511 BUFFER *line;
512 int err = -1;
513
514 line = buf_new();
515 if (ek)
516 buf_clear(ek);
517 if (opt)
518 buf_clear(opt);
519 if (name)
520 buf_clear(name);
521 if (chains)
522 buf_clear(chains);
523 if (config)
524 buf_clear(config);
525
526 for (;;) {
527 if (buf_getline(list, line) == -1)
528 goto end;
529 if (bufleft(line, "nym="))
530 break;
531 }
532 strncpy(nym, line->data + 4, LINELEN);
533
534 for (;;) {
535 if (buf_getline(list, line) == -1)
536 break;
537 if (opt && bufleft(line, "opt="))
538 line->ptr = 4, buf_rest(opt, line);
539 if (name && bufleft(line, "name="))
540 line->ptr = 5, buf_rest(name, line);
541 if (config && bufleft(line, "config="))
542 line->ptr = 7, buf_rest(config, line);
543 if (bufeq(line, "ek=")) {
544 while (buf_getline(list, line) == 0 && !bufeq(line, "end ek"))
545 if (ek) {
546 buf_cat(ek, line);
547 buf_nl(ek);
548 }
549 }
550 if (bufeq(line, "chains=")) {
551 while (buf_getline(list, line) == 0 && !bufeq(line, "end chains"))
552 if (chains) {
553 buf_cat(chains, line);
554 buf_nl(chains);
555 }
556 }
557 if (status && bufleft(line, "status="))
558 *status = line->data[7] - '0';
559 if (bufeq(line, "end")) {
560 err = 0;
561 break;
562 }
563 }
564 end:
565 buf_free(line);
566 return (err);
567 }
568
569 int nymlist_append(BUFFER *list, char *nym, BUFFER *config, BUFFER *opt,
570 BUFFER *name, BUFFER *rblocks, BUFFER *eklist, int status)
571 {
572 buf_appends(list, "nym=");
573 buf_appends(list, nym);
574 buf_nl(list);
575 buf_appends(list, "config=");
576 buf_cat(list, config);
577 buf_nl(list);
578 buf_appends(list, "status=");
579 buf_appendc(list, (byte) (status + '0'));
580 buf_nl(list);
581 if (name) {
582 buf_appends(list, "name=");
583 buf_cat(list, name);
584 buf_nl(list);
585 }
586 buf_appends(list, "opt=");
587 buf_cat(list, opt);
588 buf_nl(list);
589 buf_appends(list, "chains=\n");
590 buf_cat(list, rblocks);
591 buf_appends(list, "end chains\n");
592 buf_appends(list, "ek=\n");
593 buf_cat(list, eklist);
594 buf_appends(list, "end ek\n");
595 buf_appends(list, "end\n");
596 return (0);
597 }
598
599 int nymlist_del(BUFFER *list, char *nym)
600 {
601 BUFFER *new;
602 char thisnym[LINELEN];
603 BUFFER *config, *ek, *name, *rblocks, *opt;
604 int thisstatus;
605
606 new = buf_new();
607 config = buf_new();
608 ek = buf_new();
609 name = buf_new();
610 rblocks = buf_new();
611 opt = buf_new();
612
613 buf_rewind(list);
614 while (nymlist_get(list, thisnym, config, ek, opt, name, rblocks,
615 &thisstatus) >= 0)
616 if (!streq(nym, thisnym))
617 nymlist_append(new, thisnym, config, opt, name, rblocks, ek,
618 thisstatus);
619
620 buf_move(list, new);
621 buf_free(new);
622 buf_free(name);
623 buf_free(opt);
624 buf_free(rblocks);
625 buf_free(config);
626 buf_free(ek);
627 return (0);
628 }
629
630 int nymlist_getnym(char *nym, BUFFER *config, BUFFER *ek, BUFFER *opt,
631 BUFFER *name, BUFFER *rblocks)
632 /* "nym@nymserver.domain" or "nym@" */
633 {
634 BUFFER *nymlist, *userpass;
635 char n[LINELEN];
636 int err = -1;
637 int status;
638
639 nymlist = buf_new();
640 userpass = buf_new();
641
642 user_pass(userpass);
643 if (nymlist_read(nymlist) != -1) {
644 while (nymlist_get(nymlist, n, config, ek, opt, name, rblocks,
645 &status) >= 0)
646 if (streq(nym, n) || (nym[strlen(nym) - 1] == '@' && strleft(n, nym))) {
647 err = status;
648 strncpy(nym, n, LINELEN);
649 break;
650 }
651 }
652 buf_free(userpass);
653 buf_free(nymlist);
654 return (err);
655 }
656
657 int nymlist_getstatus(char *nym)
658 {
659 int status;
660
661 if ((status = nymlist_getnym(nym, NULL, NULL, NULL, NULL, NULL)) == 0)
662 return (status);
663 else
664 return (-1);
665 }

  ViewVC Help
Powered by ViewVC 1.1.5