/[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 - (show 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 /* 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.9 2003/04/29 12:03:32 weaselp Exp $ */
10
11
12 #include "mix3.h"
13 #include <ctype.h>
14 #include <time.h>
15 #include <string.h>
16 #include <assert.h>
17 #include <stdlib.h>
18
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 #endif /* USE_IDEA */
78
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 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 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 BUFFER *digest;
146 int err = 0;
147 int encrypted = 0;
148 int type = -1;
149 int latent = 0;
150 int remix = 0, repgp = 0;
151 int inflate = 0;
152 int maxsize = -1;
153 int maxcount = -1;
154 int maxdate = -2; /* -2 not used, -1 parse error */
155
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 digest = buf_new();
174
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 remix = 1; repgp = 0;
191 buf_set(remixto, content);
192 if (type == -1)
193 type = MSG_MAIL;
194 } else if (bufieq(field, "encrypt-to")) {
195 repgp = remix = 1;
196 buf_set(remixto, content);
197 if (type == -1)
198 type = MSG_MAIL;
199 } 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 repgp = remix = 0;
205 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 } 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 #if USE_NSUB
280 else if (bufieq(field, "subject"))
281 buf_set(subject, content);
282 #endif /* USE_NSUB */
283 }
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 digest_sha1(temp, digest);
314
315 pass = buf_new();
316 buf_sets(pass, PASSPHRASE);
317 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 #endif /* USE_PGP */
333 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 #endif /* 0 */
343
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 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 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 #endif /* USE_IDEA */
419 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 #endif /* 0 */
427 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 #else /* end of USE_PGP */
472 err = -1;
473 #endif /* Else if not USE_PGP */
474 }
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 if (remix && remixto->length == 0)
546 buf_set(remixto, to);
547 if (remix && !repgp && remixto->length != 0)
548 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 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 buf_free(digest);
581 return (err);
582 }

  ViewVC Help
Powered by ViewVC 1.1.5