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

  ViewVC Help
Powered by ViewVC 1.1.5