/[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 1 - (hide annotations) (download)
Wed Oct 31 08:19:51 2001 UTC (11 years, 6 months ago) by rabbi
File MIME type: text/plain
File size: 12067 byte(s)
Initial revision
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     $Id: rem1.c,v 1.1 2001/10/31 08:19:53 rabbi Exp $ */
10    
11    
12     #include "mix3.h"
13     #include <ctype.h>
14     #include <time.h>
15     #include <string.h>
16    
17     static int t1msg(BUFFER *in, int hdr);
18    
19     int isline(BUFFER *line, char *text)
20     {
21     int i;
22    
23     if (!bufileft(line, text))
24     return (0);
25    
26     for (i = strlen(text); i < line->length; i++)
27     if (!isspace(line->data[i]))
28     return(0);
29     return(1);
30     }
31    
32     int t1_decrypt(BUFFER *in)
33     {
34     int ret;
35    
36     buf_rewind(in);
37     if (TYPE1[0] == '\0')
38     ret = t1msg(in, 1);
39     else {
40     FILE *f;
41    
42     f = openpipe(TYPE1);
43     if (f == NULL)
44     return -1;
45     buf_write(in, f);
46     ret = closepipe(f);
47     }
48     if (ret == 0)
49     stats_log(1);
50     return (ret);
51     }
52    
53     #ifdef USE_IDEA
54     void t1_esub(BUFFER *esub, BUFFER *subject)
55     {
56     BUFFER *iv, *out;
57     char hex[33];
58    
59     iv = buf_new();
60     out = buf_new();
61    
62     buf_appendrnd(iv, 8);
63     id_encode(iv->data, hex);
64     buf_append(out, hex, 16);
65    
66     digest_md5(esub, esub);
67     digest_md5(subject, subject);
68     buf_ideacrypt(subject, esub, iv, ENCRYPT);
69     id_encode(subject->data, hex);
70     buf_appends(out, hex);
71     buf_move(subject, out);
72     buf_free(iv);
73     buf_free(out);
74     }
75     #endif
76    
77     #define N(X) (isdigit(X) ? (X)-'0' : 0)
78    
79     static int readnum(BUFFER *b, int f)
80     {
81     int num = 0;
82    
83     if (b->length > 0)
84     sscanf(b->data, "%d", &num);
85     num *= f;
86     if (strchr(b->data, 'r'))
87     num = rnd_number(num) + 1;
88     return (num);
89     }
90    
91     static int t1msg(BUFFER *in, int hdr)
92     /* hdr = 1: mail header, hdr = 2: pasted header, hdr = 0: ignore */
93     {
94     BUFFER *field, *content, *line;
95     BUFFER *cutmarks, *to, *newsgroups, *ek, *ekdes, *ekcast, *esub, *subject;
96     BUFFER *temp, *header, *out;
97     BUFFER *test, *testto, *remixto;
98     int err = 0;
99     int encrypted = 0;
100     int type = -1;
101     int latent = 0;
102     int remix = 0;
103     int inflate = 0;
104    
105     field = buf_new();
106     content = buf_new();
107     line = buf_new();
108     to = buf_new();
109     remixto = buf_new();
110     cutmarks = buf_new();
111     newsgroups = buf_new();
112     ek = buf_new();
113     ekdes = buf_new();
114     ekcast = buf_new();
115     esub = buf_new();
116     subject = buf_new();
117     temp = buf_new();
118     header = buf_new();
119     out = buf_new();
120     test = buf_new();
121     testto = buf_new();
122    
123     if (REMIX == 1)
124     remix = 2;
125     if (!UNENCRYPTED)
126     encrypted = -1;
127    
128     header:
129     while (buf_getheader(in, field, content) == 0) {
130     if (header->length == 0 && bufieq(content, ":")) /* HDRMARK */
131     hdr = 2;
132    
133     if (bufieq(field, "test-to"))
134     buf_set(testto, content);
135     else if (PGP && bufieq(field, "encrypted"))
136     encrypted = 1;
137     else if (bufieq(field, "remix-to")) {
138     remix = 1;
139     buf_set(remixto, content);
140     if (type == -1)
141     type = MSG_MAIL;
142     } else if (bufieq(field, "anon-to") ||
143     bufieq(field, "request-remailing-to") ||
144     bufieq(field, "remail-to") ||
145     bufieq(field, "anon-send-to")) {
146     if (bufieq(field, "remail-to"))
147     remix = 0;
148     if (to->length > 0)
149     buf_appendc(to, ',');
150     buf_cat(to, content);
151     if (type == -1)
152     type = MSG_MAIL;
153     } else if (bufieq(field, "anon-post-to") || bufieq(field, "post-to")) {
154     if (newsgroups->length > 0)
155     buf_appendc(newsgroups, ',');
156     buf_cat(newsgroups, content);
157     type = MSG_POST;
158     } else if (bufieq(field, "cutmarks"))
159     buf_set(cutmarks, content);
160     else if (bufieq(field, "latent-time")) {
161     byte *q;
162     int l;
163    
164     q = content->data;
165     l = strlen(q);
166     latent = 0;
167     if (q[0] == '+')
168     q++;
169     if (l >= 5 && q[2] == ':')
170     latent = 600 * N(q[0]) + 60 * N(q[1]) + 10 * N(q[3]) + N(q[4]);
171     else if (l >= 4 && q[1] == ':')
172     latent = 60 * N(q[0]) + 10 * N(q[2]) + N(q[3]);
173     else if (l >= 3 && q[0] == ':')
174     latent = 10 * N(q[1]) + N(q[2]);
175     if (!bufleft(content, "+")) {
176     time_t now;
177    
178     time(&now);
179     latent -= localtime(&now)->tm_hour * 60;
180     if (latent < 0)
181     latent += 24 * 60;
182     }
183     if (q[l - 1] == 'r')
184     latent = rnd_number(latent);
185     } else if (bufieq(field, "null"))
186     type = MSG_NULL;
187     else if (bufieq(field, "encrypt-key") || bufieq(field, "encrypt-idea"))
188     buf_set(ek, content);
189     else if (bufieq(field, "encrypt-des") || bufieq(field, "encrypt-3des"))
190     buf_set(ekdes, content);
191     else if (bufieq(field, "encrypt-cast") || bufieq(field, "encrypt-cast5"))
192     buf_set(ekcast, content);
193     else if (bufieq(field, "encrypt-subject"))
194     buf_set(esub, content);
195     else if (bufieq(field, "inflate")) {
196     inflate = readnum(content, 1024);
197     if (inflate > INFLATEMAX * 1024)
198     inflate = INFLATEMAX * 1024;
199     } else if (bufieq(field, "rand-hop")) {
200     int randhops, i;
201     randhops = readnum(content, 1);
202     if (randhops > MAXRANDHOPS)
203     randhops = MAXRANDHOPS;
204     buf_clear(temp);
205     if (remixto->length)
206     buf_move(temp, remixto);
207     for (i = 0; i < randhops; i++) {
208     if (remixto->length > 0)
209     buf_appendc(remixto, ',');
210     buf_appendc(remixto, '*');
211     }
212     if (temp->length) {
213     buf_appendc(remixto, ',');
214     buf_cat(remixto, temp);
215     }
216     }
217     #if USE_NSUB
218     else if (bufieq(field, "subject"))
219     buf_set(subject, content);
220     #endif
221     }
222    
223     if (cutmarks->length > 0) {
224     BUFFER *cut;
225    
226     cut = buf_new();
227     buf_clear(temp);
228    
229     while ((err = buf_getline(in, line)) != -1 && !buf_eq(line, cutmarks)) {
230     buf_cat(temp, line);
231     buf_nl(temp);
232     }
233     while (err != -1) {
234     err = buf_getline(in, line);
235     if (err == -1 || buf_eq(line, cutmarks)) {
236     t1msg(cut, 0);
237     buf_clear(cut);
238     } else {
239     buf_cat(cut, line);
240     buf_nl(cut);
241     }
242     }
243     buf_move(in, temp);
244     buf_clear(cutmarks);
245     }
246     if (encrypted == 1) {
247     #ifdef USE_PGP
248     err = pgp_dearmor(in, temp);
249     if (err == 0) {
250     BUFFER *pass;
251    
252     pass = buf_new();
253     buf_sets(pass, PASSPHRASE);
254     err = pgp_decrypt(temp, pass, NULL, NULL, NULL);
255     buf_free(pass);
256     }
257     if (err != -1 && temp->length == 0) {
258     errlog(ERRORMSG, "Empty PGP message.\n");
259     err = -1;
260     goto end;
261     }
262     if (err != -1) {
263     buf_rest(temp, in); /* dangerous, but required for reply blocks */
264     buf_move(in, temp);
265     encrypted = 0;
266     hdr = 0;
267     goto header;
268     }
269     #endif
270     if (testto->length == 0)
271     errlog(ERRORMSG, "Can't decrypt PGP message.\n");
272     buf_appends(test, "Can't decrypt PGP message.\n");
273     }
274     while ((err = buf_lookahead(in, line)) == 1)
275     buf_getline(in, line);
276     #if 0
277     if (err == -1)
278     goto end;
279     #endif
280    
281     if (isline(line, HDRMARK) && (hdr == 0 || hdr == 1)) {
282     buf_getline(in, NULL);
283     hdr = 2;
284     goto header;
285     } else if (isline(line, HASHMARK)) {
286     buf_getline(in, NULL);
287     for (;;) {
288     if (buf_lookahead(in, line) == 0 && bufileft(line, "subject:")) {
289     buf_getheader(in, field, content);
290     buf_set(subject, content);
291     }
292     if (buf_getline(in, line) != 0)
293     break;
294     buf_cat(header, line);
295     buf_nl(header);
296     }
297     }
298     if (encrypted == -1) {
299     if (testto->length == 0)
300     errlog(LOG, "Unencrypted message detected.\n");
301     buf_appends(test, "Unencrypted message detected.\n");
302     err = -2;
303     goto end;
304     }
305     if (type == MSG_POST && subject->length == 0)
306     buf_sets(subject, "(no subject)");
307    
308     if (to->length > 0)
309     buf_appendf(out, "To: %b\n", to);
310     else if (remixto->length > 0)
311     buf_appendf(out, "To: %b\n", remixto);
312     if (newsgroups->length > 0)
313     buf_appendf(out, "Newsgroups: %b\n", newsgroups);
314     if (subject->length > 0) {
315     #ifdef USE_IDEA
316     if (esub->length > 0)
317     t1_esub(esub, subject);
318     #endif
319     buf_appendf(out, "Subject: %b\n", subject);
320     }
321     buf_cat(out, header);
322     buf_nl(out);
323    
324     #if 0
325     inflate -= in->length;
326     #endif
327     if (inflate > 0) {
328     buf_setrnd(temp, inflate * 3 / 4);
329     encode(temp, 64);
330     buf_appends(in, "\n-----BEGIN GARBAGE-----\n");
331     buf_cat(in, temp);
332     buf_appends(in, "-----END GARBAGE-----\n");
333     }
334    
335     if (!(ek->length || ekdes->length || ekcast->length))
336     buf_rest(out, in);
337     else {
338     err = 0;
339     buf_clear(temp);
340     while (buf_getline(in, line) != -1) {
341     if (isline(line, EKMARK)) {
342     buf_cat(out, temp);
343     buf_clear(temp);
344     buf_rest(temp, in);
345     break;
346     }
347     else {
348     buf_cat(temp, line);
349     buf_nl(temp);
350     }
351     }
352     #ifdef USE_PGP
353     if (ekcast->length) {
354     err = pgp_encrypt(PGP_CONVCAST | PGP_TEXT, temp, ekcast, NULL, NULL,
355     NULL, NULL);
356     buf_clear(ekcast);
357     }
358     if (ekdes->length) {
359     err = pgp_encrypt(PGP_CONV3DES | PGP_TEXT, temp, ekdes, NULL, NULL,
360     NULL, NULL);
361     buf_clear(ekdes);
362     }
363     if (ek->length) {
364     err = pgp_encrypt(PGP_CONVENTIONAL | PGP_TEXT, temp, ek, NULL, NULL,
365     NULL, NULL);
366     buf_clear(ek);
367     }
368     buf_appends(out, EKMARK);
369     buf_nl(out);
370     buf_cat(out, temp);
371     #else
372     err = -1;
373     #endif
374     }
375    
376     if (type == -1) {
377     buf_appends(test, "No destination.\n");
378     err = -1;
379     }
380    
381     end:
382     if (testto->length) {
383     BUFFER *report;
384     int i;
385    
386     report = buf_new();
387     buf_sets(report,
388     "Subject: remailer test report\n\nThis is an automated response to the test message you sent to ");
389     buf_appends(report, SHORTNAME);
390     buf_appends(report, ".\nYour test message results follow:\n\n");
391     buf_appends(report, remailer_type);
392     buf_appends(report, VERSION);
393     buf_appends(report, "\n\n");
394     if (err == 0) {
395     err = filtermsg(out);
396     if (err == -1)
397     buf_appends(report, "This remailer cannot deliver the message.\n\n");
398     else {
399     buf_appends(report, "Valid ");
400     buf_appends(report, type == MSG_POST ? "Usenet" : "mail");
401     buf_appends(report, " message.\n");
402     if (remixto->length) {
403     if (remix && MIX)
404     buf_appends(report, "Delivery via Mixmaster: ");
405     else if (remix)
406     buf_appends(report, "Error! Can't remix: ");
407     else
408     buf_appends(report, "Delivery via Cypherpunk remailer: ");
409     buf_cat(report, remixto);
410     buf_nl(report);
411     }
412     else if (type == MSG_POST && strchr(NEWS, '@') && !strchr(NEWS, ' ')) {
413     buf_appendf(report, "News gateway: %s\n", NEWS);
414     }
415     buf_appends(report,
416     "\n=========================================================================\nThe first 20 lines of the message follow:\n");
417     if (err != 1)
418     buf_appendf(report, "From: %s\n", ANONNAME);
419     if (type == MSG_POST && ORGANIZATION[0] != '\0')
420     buf_appendf(report, "Organization: %s\n", ORGANIZATION);
421     }
422     for (i = 0; i < 20 && buf_getline(out, test) != -1; i++)
423     buf_cat(report, test), buf_nl(report);
424     } else {
425     buf_appends(report, "The remailer message is invalid.\n\n");
426     if (test->length) {
427     buf_appends(report, "The following error occurred: ");
428     buf_cat(report, test);
429     buf_nl(report);
430     }
431     }
432     buf_appends(report,
433     "=========================================================================\nThe first 20 lines of your message to the remailer follow:\n");
434     buf_rewind(in);
435     for (i = 0; i < 20 && buf_getline(in, test) != -1; i++)
436     buf_cat(report, test), buf_nl(report);
437    
438     sendmail(report, REMAILERNAME, testto);
439     err = 0;
440     buf_free(report);
441     } else if (err == 0 && type != MSG_NULL) {
442     err = 1;
443     if (bufieq(to, REMAILERADDR)) /* don't remix to ourselves */
444     remix = 0;
445     if (remix && remixto->length == 0)
446     buf_set(remixto, to);
447     if (remix)
448     err = mix_encrypt(type, out, remixto->data, 1, line);
449     if (err != 0) {
450     if (remix == 1)
451     errlog(NOTICE, "Can't remix -- %b\n", line);
452     else {
453     if (remixto->length)
454     err = t1_encrypt(type, out, remixto->data, 0, 0, line);
455     if (err != 0)
456     err = mix_pool(out, type, latent * 60);
457     }
458     }
459     }
460    
461     buf_free(field);
462     buf_free(content);
463     buf_free(line);
464     buf_free(to);
465     buf_free(remixto);
466     buf_free(newsgroups);
467     buf_free(subject);
468     buf_free(ek);
469     buf_free(ekcast);
470     buf_free(ekdes);
471     buf_free(esub);
472     buf_free(cutmarks);
473     buf_free(temp);
474     buf_free(out);
475     buf_free(header);
476     buf_free(test);
477     buf_free(testto);
478     return (err);
479     }

  ViewVC Help
Powered by ViewVC 1.1.5