/[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 500 - (hide annotations) (download)
Sat May 3 05:31:07 2003 UTC (10 years ago) by weaselp
File MIME type: text/plain
File size: 15563 byte(s)
Mixmaster now uses broken-chain info from stats. I hope this doesn't break any
Nym functionality.
1 rabbi 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 weaselp 500 $Id: nym.c,v 1.9 2003/05/03 05:31:07 weaselp Exp $ */
10 rabbi 1
11    
12     #include "mix3.h"
13     #include "pgp.h"
14     #include <string.h>
15 rabbi 6 #include <time.h>
16 rabbi 1 #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 rabbi 262 #else /* end of not USE_PGP */
25 rabbi 1 REMAILER remailer[MAXREM];
26 weaselp 500 int badchains[MAXREM][MAXREM];
27 rabbi 1 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 weaselp 500 maxrem = t1_rlist(remailer, badchains);
65 rabbi 1 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 weaselp 500 chain[0] = chain_randfinal(MSG_MAIL, remailer, badchains, maxrem, 2, -1);
71 rabbi 1 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 weaselp 285 r = pgpdb_open(NYMSECRING, userpass, 0, PGP_TYPE_PRIVATE);
113 rabbi 1 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 weaselp 284 pgpdb_close(r);
124 rabbi 1 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 weaselp 182 pgp_armor(pubkey, PGP_ARMOR_NYMKEY);
138 rabbi 1 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 rabbi 262 #endif /* DEBUG */
196 rabbi 1 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 rabbi 262 #endif /* DEBUG */
208 rabbi 1 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 rabbi 262 #endif /* else if USE_PGP */
236 rabbi 1 }
237    
238     int nym_encrypt(BUFFER *msg, char *nym, int type)
239     {
240     #ifndef USE_PGP
241     return (-1);
242 rabbi 262 #else /* end of not USE_PGP */
243 rabbi 1 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 rabbi 262 #endif /* DEBUG */
268 rabbi 1 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 rabbi 262 #endif /* else if USE_PGP */
286 rabbi 1 }
287    
288     int nym_decrypt(BUFFER *msg, char *thisnym, BUFFER *log)
289     {
290     #ifndef USE_PGP
291     return (-1);
292 rabbi 262 #else /* end of not USE_PGP */
293 rabbi 1 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 rabbi 6 time_t t;
305     struct tm *tc;
306     char timeline[LINELEN];
307 rabbi 1
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 rabbi 6 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 rabbi 1 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 rabbi 262 #endif /* 0 */
402 rabbi 1 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 rabbi 262 #endif /* else if USE_PGP */
449 rabbi 1 }
450    
451     int nymlist_read(BUFFER *list)
452     {
453     #ifdef USE_PGP
454     BUFFER *key;
455    
456 rabbi 262 #endif /* USE_PGP */
457 rabbi 1 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 weaselp 332 buf_free(key);
474 rabbi 262 #endif /* USE_PGP */
475 rabbi 1 }
476     return (err);
477     }
478    
479     int nymlist_write(BUFFER *list)
480     {
481     #ifdef USE_PGP
482     BUFFER *key;
483    
484 rabbi 262 #endif /* USE_PGP */
485 rabbi 1 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 rabbi 262 #endif /* USE_PGP */
498 rabbi 1 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