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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 497 - (hide annotations) (download)
Tue Apr 29 12:03:32 2003 UTC (10 years ago) by weaselp
File MIME type: text/plain
File size: 14965 byte(s)
If remix was enabled and we had a Type-I Anon-Post-To request we accidently
randhoped it via the configured default remailing chain (default: *,*,*,*).
Fixed (closes: #729494).
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     Process Cypherpunk remailer messages
9 weaselp 497 $Id: rem1.c,v 1.9 2003/04/29 12:03:32 weaselp Exp $ */
10 rabbi 1
11    
12     #include "mix3.h"
13     #include <ctype.h>
14     #include <time.h>
15     #include <string.h>
16 weaselp 477 #include <assert.h>
17     #include <stdlib.h>
18 rabbi 1
19     static int t1msg(BUFFER *in, int hdr);
20    
21     int isline(BUFFER *line, char *text)
22     {
23     int i;
24    
25     if (!bufileft(line, text))
26     return (0);
27    
28     for (i = strlen(text); i < line->length; i++)
29     if (!isspace(line->data[i]))
30     return(0);
31     return(1);
32     }
33    
34     int t1_decrypt(BUFFER *in)
35     {
36     int ret;
37    
38     buf_rewind(in);
39     if (TYPE1[0] == '\0')
40     ret = t1msg(in, 1);
41     else {
42     FILE *f;
43    
44     f = openpipe(TYPE1);
45     if (f == NULL)
46     return -1;
47     buf_write(in, f);
48     ret = closepipe(f);
49     }
50     if (ret == 0)
51     stats_log(1);
52     return (ret);
53     }
54    
55     #ifdef USE_IDEA
56     void t1_esub(BUFFER *esub, BUFFER *subject)
57     {
58     BUFFER *iv, *out;
59     char hex[33];
60    
61     iv = buf_new();
62     out = buf_new();
63    
64     buf_appendrnd(iv, 8);
65     id_encode(iv->data, hex);
66     buf_append(out, hex, 16);
67    
68     digest_md5(esub, esub);
69     digest_md5(subject, subject);
70     buf_ideacrypt(subject, esub, iv, ENCRYPT);
71     id_encode(subject->data, hex);
72     buf_appends(out, hex);
73     buf_move(subject, out);
74     buf_free(iv);
75     buf_free(out);
76     }
77 rabbi 262 #endif /* USE_IDEA */
78 rabbi 1
79     #define N(X) (isdigit(X) ? (X)-'0' : 0)
80    
81     static int readnum(BUFFER *b, int f)
82     {
83     int num = 0;
84    
85     if (b->length > 0)
86     sscanf(b->data, "%d", &num);
87     num *= f;
88     if (strchr(b->data, 'r'))
89     num = rnd_number(num) + 1;
90     return (num);
91     }
92    
93 weaselp 477 static int readdate(BUFFER *b)
94     {
95     int num = -1;
96    
97     if (b->length > 0)
98     num = parsedate(b->data);
99     return (num);
100     }
101    
102     static int reached_maxcount(BUFFER *md, int maxcount)
103     {
104     FILE *f;
105     char temp[LINELEN];
106     int count = 0;
107     int err = 0;
108     long then;
109     time_t now = time(NULL);
110    
111     assert(md->length > 0);
112    
113     encode(md, 0);
114    
115     f = mix_openfile(PGPMAXCOUNT, "a+"); /* create file if it does not exist */
116     fseek(f,0,SEEK_SET);
117     if (f == NULL) {
118     errlog(ERRORMSG, "Can't open %s!\n", PGPMAXCOUNT);
119     return (-1);
120     }
121     lock(f);
122     while (fgets(temp, sizeof(temp), f) != NULL)
123     if (sscanf(temp, "%ld", &then) &&
124     (then >= now - SECONDSPERDAY) &&
125     strstr (temp, md->data))
126     count++;
127    
128     if (count > maxcount)
129     err = 1;
130     else
131     fprintf(f, "%ld %s\n", (long) time(NULL), md->data);
132    
133     unlock(f);
134     fclose(f);
135     return (err);
136     }
137    
138 rabbi 1 static int t1msg(BUFFER *in, int hdr)
139     /* hdr = 1: mail header, hdr = 2: pasted header, hdr = 0: ignore */
140     {
141     BUFFER *field, *content, *line;
142     BUFFER *cutmarks, *to, *newsgroups, *ek, *ekdes, *ekcast, *esub, *subject;
143     BUFFER *temp, *header, *out;
144     BUFFER *test, *testto, *remixto;
145 weaselp 477 BUFFER *digest;
146 rabbi 1 int err = 0;
147     int encrypted = 0;
148     int type = -1;
149     int latent = 0;
150 rabbi 62 int remix = 0, repgp = 0;
151 rabbi 1 int inflate = 0;
152 weaselp 477 int maxsize = -1;
153     int maxcount = -1;
154     int maxdate = -2; /* -2 not used, -1 parse error */
155 rabbi 1
156     field = buf_new();
157     content = buf_new();
158     line = buf_new();
159     to = buf_new();
160     remixto = buf_new();
161     cutmarks = buf_new();
162     newsgroups = buf_new();
163     ek = buf_new();
164     ekdes = buf_new();
165     ekcast = buf_new();
166     esub = buf_new();
167     subject = buf_new();
168     temp = buf_new();
169     header = buf_new();
170     out = buf_new();
171     test = buf_new();
172     testto = buf_new();
173 weaselp 477 digest = buf_new();
174 rabbi 1
175     if (REMIX == 1)
176     remix = 2;
177     if (!UNENCRYPTED)
178     encrypted = -1;
179    
180     header:
181     while (buf_getheader(in, field, content) == 0) {
182     if (header->length == 0 && bufieq(content, ":")) /* HDRMARK */
183     hdr = 2;
184    
185     if (bufieq(field, "test-to"))
186     buf_set(testto, content);
187     else if (PGP && bufieq(field, "encrypted"))
188     encrypted = 1;
189     else if (bufieq(field, "remix-to")) {
190 rabbi 62 remix = 1; repgp = 0;
191 rabbi 1 buf_set(remixto, content);
192     if (type == -1)
193     type = MSG_MAIL;
194 rabbi 62 } else if (bufieq(field, "encrypt-to")) {
195     repgp = remix = 1;
196     buf_set(remixto, content);
197     if (type == -1)
198     type = MSG_MAIL;
199 rabbi 1 } else if (bufieq(field, "anon-to") ||
200     bufieq(field, "request-remailing-to") ||
201     bufieq(field, "remail-to") ||
202     bufieq(field, "anon-send-to")) {
203     if (bufieq(field, "remail-to"))
204 rabbi 62 repgp = remix = 0;
205 rabbi 1 if (to->length > 0)
206     buf_appendc(to, ',');
207     buf_cat(to, content);
208     if (type == -1)
209     type = MSG_MAIL;
210     } else if (bufieq(field, "anon-post-to") || bufieq(field, "post-to")) {
211     if (newsgroups->length > 0)
212     buf_appendc(newsgroups, ',');
213     buf_cat(newsgroups, content);
214     type = MSG_POST;
215     } else if (bufieq(field, "cutmarks"))
216     buf_set(cutmarks, content);
217     else if (bufieq(field, "latent-time")) {
218     byte *q;
219     int l;
220    
221     q = content->data;
222     l = strlen(q);
223     latent = 0;
224     if (q[0] == '+')
225     q++;
226     if (l >= 5 && q[2] == ':')
227     latent = 600 * N(q[0]) + 60 * N(q[1]) + 10 * N(q[3]) + N(q[4]);
228     else if (l >= 4 && q[1] == ':')
229     latent = 60 * N(q[0]) + 10 * N(q[2]) + N(q[3]);
230     else if (l >= 3 && q[0] == ':')
231     latent = 10 * N(q[1]) + N(q[2]);
232     if (!bufleft(content, "+")) {
233     time_t now;
234    
235     time(&now);
236     latent -= localtime(&now)->tm_hour * 60;
237     if (latent < 0)
238     latent += 24 * 60;
239     }
240     if (q[l - 1] == 'r')
241     latent = rnd_number(latent);
242     } else if (bufieq(field, "null"))
243     type = MSG_NULL;
244     else if (bufieq(field, "encrypt-key") || bufieq(field, "encrypt-idea"))
245     buf_set(ek, content);
246     else if (bufieq(field, "encrypt-des") || bufieq(field, "encrypt-3des"))
247     buf_set(ekdes, content);
248     else if (bufieq(field, "encrypt-cast") || bufieq(field, "encrypt-cast5"))
249     buf_set(ekcast, content);
250     else if (bufieq(field, "encrypt-subject"))
251     buf_set(esub, content);
252     else if (bufieq(field, "inflate")) {
253     inflate = readnum(content, 1024);
254     if (inflate > INFLATEMAX * 1024)
255     inflate = INFLATEMAX * 1024;
256     } else if (bufieq(field, "rand-hop")) {
257     int randhops, i;
258     randhops = readnum(content, 1);
259     if (randhops > MAXRANDHOPS)
260     randhops = MAXRANDHOPS;
261     buf_clear(temp);
262     if (remixto->length)
263     buf_move(temp, remixto);
264     for (i = 0; i < randhops; i++) {
265     if (remixto->length > 0)
266     buf_appendc(remixto, ',');
267     buf_appendc(remixto, '*');
268     }
269     if (temp->length) {
270     buf_appendc(remixto, ',');
271     buf_cat(remixto, temp);
272     }
273 weaselp 477 } else if (bufieq(field, "max-size") || bufieq(field, "maxsize"))
274     maxsize = readnum(content, 1024);
275     else if (bufieq(field, "max-count") || bufieq(field, "maxcount"))
276     maxcount = readnum(content, 1);
277     else if (bufieq(field, "max-date") || bufieq(field, "maxdate"))
278     maxdate = readdate(content);
279 rabbi 1 #if USE_NSUB
280     else if (bufieq(field, "subject"))
281     buf_set(subject, content);
282 rabbi 262 #endif /* USE_NSUB */
283 rabbi 1 }
284    
285     if (cutmarks->length > 0) {
286     BUFFER *cut;
287    
288     cut = buf_new();
289     buf_clear(temp);
290    
291     while ((err = buf_getline(in, line)) != -1 && !buf_eq(line, cutmarks)) {
292     buf_cat(temp, line);
293     buf_nl(temp);
294     }
295     while (err != -1) {
296     err = buf_getline(in, line);
297     if (err == -1 || buf_eq(line, cutmarks)) {
298     t1msg(cut, 0);
299     buf_clear(cut);
300     } else {
301     buf_cat(cut, line);
302     buf_nl(cut);
303     }
304     }
305     buf_move(in, temp);
306     buf_clear(cutmarks);
307     }
308     if (encrypted == 1) {
309     #ifdef USE_PGP
310     err = pgp_dearmor(in, temp);
311     if (err == 0) {
312     BUFFER *pass;
313 weaselp 477 digest_sha1(temp, digest);
314 rabbi 1
315     pass = buf_new();
316 rabbi 102 buf_sets(pass, PASSPHRASE);
317 rabbi 1 err = pgp_decrypt(temp, pass, NULL, NULL, NULL);
318     buf_free(pass);
319     }
320     if (err != -1 && temp->length == 0) {
321     errlog(ERRORMSG, "Empty PGP message.\n");
322     err = -1;
323     goto end;
324     }
325     if (err != -1) {
326     buf_rest(temp, in); /* dangerous, but required for reply blocks */
327     buf_move(in, temp);
328     encrypted = 0;
329     hdr = 0;
330     goto header;
331     }
332 rabbi 262 #endif /* USE_PGP */
333 rabbi 1 if (testto->length == 0)
334     errlog(ERRORMSG, "Can't decrypt PGP message.\n");
335     buf_appends(test, "Can't decrypt PGP message.\n");
336     }
337     while ((err = buf_lookahead(in, line)) == 1)
338     buf_getline(in, line);
339     #if 0
340     if (err == -1)
341     goto end;
342 rabbi 262 #endif /* 0 */
343 rabbi 1
344     if (isline(line, HDRMARK) && (hdr == 0 || hdr == 1)) {
345     buf_getline(in, NULL);
346     hdr = 2;
347     goto header;
348     } else if (isline(line, HASHMARK)) {
349     buf_getline(in, NULL);
350     for (;;) {
351     if (buf_lookahead(in, line) == 0 && bufileft(line, "subject:")) {
352     buf_getheader(in, field, content);
353     buf_set(subject, content);
354     }
355     if (buf_getline(in, line) != 0)
356     break;
357     buf_cat(header, line);
358     buf_nl(header);
359     }
360     }
361     if (encrypted == -1) {
362     if (testto->length == 0)
363     errlog(LOG, "Unencrypted message detected.\n");
364     buf_appends(test, "Unencrypted message detected.\n");
365     err = -2;
366     goto end;
367     }
368 weaselp 477 if (maxdate == -1) {
369     if (testto->length == 0)
370     errlog(LOG, "Could not parse Max-Date: header.\n");
371     buf_appends(test, "Could not parse Max-Date: header.\n");
372     err = -2;
373     goto end;
374     } else if (maxdate >= 0 && maxdate <= time(NULL)) {
375     if (testto->length == 0)
376     errlog(LOG, "Message is expired.\n");
377     buf_appends(test, "Message is expired.\n");
378     err = -2;
379     goto end;
380     }
381     if (maxsize >= 0 && in->length >= maxsize) {
382     if (testto->length == 0)
383     errlog(LOG, "Message Size exceeds Max-Size.\n");
384     buf_appends(test, "Message Size exceeds Max-Size.\n");
385     err = -2;
386     goto end;
387     }
388     if (maxcount >= 0) {
389     if (digest->length == 0) {
390     if (testto->length == 0)
391     errlog(LOG, "Max-Count yet not encrypted.\n");
392     buf_appends(test, "Max-Count yet not encrypted.\n");
393     err = -2;
394     goto end;
395     }
396     if (reached_maxcount(digest, maxcount)) {
397     if (testto->length == 0)
398     errlog(LOG, "Max-Count reached - discarding message.\n");
399     buf_appends(test, "Max-Count reached - discarding message.\n");
400     err = -2;
401     goto end;
402     }
403     }
404    
405 rabbi 1 if (type == MSG_POST && subject->length == 0)
406     buf_sets(subject, "(no subject)");
407    
408     if (to->length > 0)
409     buf_appendf(out, "To: %b\n", to);
410     else if (remixto->length > 0)
411     buf_appendf(out, "To: %b\n", remixto);
412     if (newsgroups->length > 0)
413     buf_appendf(out, "Newsgroups: %b\n", newsgroups);
414     if (subject->length > 0) {
415     #ifdef USE_IDEA
416     if (esub->length > 0)
417     t1_esub(esub, subject);
418 rabbi 262 #endif /* USE_IDEA */
419 rabbi 1 buf_appendf(out, "Subject: %b\n", subject);
420     }
421     buf_cat(out, header);
422     buf_nl(out);
423    
424     #if 0
425     inflate -= in->length;
426 rabbi 262 #endif /* 0 */
427 rabbi 1 if (inflate > 0) {
428     buf_setrnd(temp, inflate * 3 / 4);
429     encode(temp, 64);
430     buf_appends(in, "\n-----BEGIN GARBAGE-----\n");
431     buf_cat(in, temp);
432     buf_appends(in, "-----END GARBAGE-----\n");
433     }
434    
435     if (!(ek->length || ekdes->length || ekcast->length))
436     buf_rest(out, in);
437     else {
438     err = 0;
439     buf_clear(temp);
440     while (buf_getline(in, line) != -1) {
441     if (isline(line, EKMARK)) {
442     buf_cat(out, temp);
443     buf_clear(temp);
444     buf_rest(temp, in);
445     break;
446     }
447     else {
448     buf_cat(temp, line);
449     buf_nl(temp);
450     }
451     }
452     #ifdef USE_PGP
453     if (ekcast->length) {
454     err = pgp_encrypt(PGP_CONVCAST | PGP_TEXT, temp, ekcast, NULL, NULL,
455     NULL, NULL);
456     buf_clear(ekcast);
457     }
458     if (ekdes->length) {
459     err = pgp_encrypt(PGP_CONV3DES | PGP_TEXT, temp, ekdes, NULL, NULL,
460     NULL, NULL);
461     buf_clear(ekdes);
462     }
463     if (ek->length) {
464     err = pgp_encrypt(PGP_CONVENTIONAL | PGP_TEXT, temp, ek, NULL, NULL,
465     NULL, NULL);
466     buf_clear(ek);
467     }
468     buf_appends(out, EKMARK);
469     buf_nl(out);
470     buf_cat(out, temp);
471 rabbi 262 #else /* end of USE_PGP */
472 rabbi 1 err = -1;
473 rabbi 262 #endif /* Else if not USE_PGP */
474 rabbi 1 }
475    
476     if (type == -1) {
477     buf_appends(test, "No destination.\n");
478     err = -1;
479     }
480    
481     end:
482     if (testto->length) {
483     BUFFER *report;
484     int i;
485    
486     report = buf_new();
487     buf_sets(report,
488     "Subject: remailer test report\n\nThis is an automated response to the test message you sent to ");
489     buf_appends(report, SHORTNAME);
490     buf_appends(report, ".\nYour test message results follow:\n\n");
491     buf_appends(report, remailer_type);
492     buf_appends(report, VERSION);
493     buf_appends(report, "\n\n");
494     if (err == 0) {
495     err = filtermsg(out);
496     if (err == -1)
497     buf_appends(report, "This remailer cannot deliver the message.\n\n");
498     else {
499     buf_appends(report, "Valid ");
500     buf_appends(report, type == MSG_POST ? "Usenet" : "mail");
501     buf_appends(report, " message.\n");
502     if (remixto->length) {
503     if (remix && MIX)
504     buf_appends(report, "Delivery via Mixmaster: ");
505     else if (remix)
506     buf_appends(report, "Error! Can't remix: ");
507     else
508     buf_appends(report, "Delivery via Cypherpunk remailer: ");
509     buf_cat(report, remixto);
510     buf_nl(report);
511     }
512     else if (type == MSG_POST && strchr(NEWS, '@') && !strchr(NEWS, ' ')) {
513     buf_appendf(report, "News gateway: %s\n", NEWS);
514     }
515     buf_appends(report,
516     "\n=========================================================================\nThe first 20 lines of the message follow:\n");
517     if (err != 1)
518     buf_appendf(report, "From: %s\n", ANONNAME);
519     if (type == MSG_POST && ORGANIZATION[0] != '\0')
520     buf_appendf(report, "Organization: %s\n", ORGANIZATION);
521     }
522     for (i = 0; i < 20 && buf_getline(out, test) != -1; i++)
523     buf_cat(report, test), buf_nl(report);
524     } else {
525     buf_appends(report, "The remailer message is invalid.\n\n");
526     if (test->length) {
527     buf_appends(report, "The following error occurred: ");
528     buf_cat(report, test);
529     buf_nl(report);
530     }
531     }
532     buf_appends(report,
533     "=========================================================================\nThe first 20 lines of your message to the remailer follow:\n");
534     buf_rewind(in);
535     for (i = 0; i < 20 && buf_getline(in, test) != -1; i++)
536     buf_cat(report, test), buf_nl(report);
537    
538     sendmail(report, REMAILERNAME, testto);
539     err = 0;
540     buf_free(report);
541     } else if (err == 0 && type != MSG_NULL) {
542     err = 1;
543     if (bufieq(to, REMAILERADDR)) /* don't remix to ourselves */
544     remix = 0;
545 rabbi 62 if (remix && remixto->length == 0)
546     buf_set(remixto, to);
547 weaselp 497 if (remix && !repgp && remixto->length != 0)
548 rabbi 62 err = mix_encrypt(type, out, remixto->data, 1, line);
549     if (err != 0) {
550     if (remix == 1 && !repgp)
551     errlog(NOTICE, "Can't remix -- %b\n", line);
552     else {
553     if (remixto->length)
554     err = t1_encrypt(type, out, remixto->data, 0, 0, line);
555     if (err != 0 && repgp)
556     errlog(NOTICE, "Can't repgp -- %b\n", line);
557     else
558 rabbi 1 err = mix_pool(out, type, latent * 60);
559     }
560     }
561     }
562    
563     buf_free(field);
564     buf_free(content);
565     buf_free(line);
566     buf_free(to);
567     buf_free(remixto);
568     buf_free(newsgroups);
569     buf_free(subject);
570     buf_free(ek);
571     buf_free(ekcast);
572     buf_free(ekdes);
573     buf_free(esub);
574     buf_free(cutmarks);
575     buf_free(temp);
576     buf_free(out);
577     buf_free(header);
578     buf_free(test);
579     buf_free(testto);
580 weaselp 477 buf_free(digest);
581 rabbi 1 return (err);
582     }

  ViewVC Help
Powered by ViewVC 1.1.5