/[pkg-mixmaster]/branches/mixmaster_2_9_STABLE/Mix/Src/rem.c
ViewVC logotype

Contents of /branches/mixmaster_2_9_STABLE/Mix/Src/rem.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 525 - (show annotations) (download)
Sun Jun 1 23:39:11 2003 UTC (9 years, 11 months ago) by rabbi
File MIME type: text/plain
File size: 15454 byte(s)
Windows buld support changes.
1 /* Mixmaster version 2.9 -- (C) 1999 - 2002 Anonymizer Inc. and others.
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 remailer messages
9 $Id: rem.c,v 1.20.2.10 2003/06/01 23:39:10 rabbi Exp $ */
10
11
12 #include "mix3.h"
13 #include <stdlib.h>
14 #include <string.h>
15 #include <time.h>
16 #include <ctype.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #ifdef POSIX
20 #include <unistd.h>
21 #else /* end of POSIX */
22 #include <io.h>
23 #endif /* else if not POSIX */
24 #ifndef _MSC_VER
25 #include <dirent.h>
26 #endif /* not _MSC_VER */
27 #include <assert.h>
28
29 int blockrequest(BUFFER *message);
30
31 #define REQUESTHELP 100
32 #define REQUESTSTATS 101
33 #define REQUESTKEY 200
34 #define REQUESTCONF 201
35 #define REQUESTOPKEY 202
36 #define BLOCKREQUEST 666
37 #define DISABLED 99
38
39 #define CPUNKMSG 1
40 #define MIXMSG 2
41
42 int mix_decrypt(BUFFER *message)
43 {
44 int type = 0;
45 BUFFER *field, *content;
46 BUFFER *to, *subject, *replyto, *reply;
47 FILE *f;
48 BUFFER *block;
49 int err = 0;
50 int quoted_printable = 0; /* is this message quoted printable encoded */
51
52 mix_init(NULL);
53 field = buf_new();
54 content = buf_new();
55 to = buf_new();
56 replyto = buf_new();
57 reply = buf_new();
58 block = buf_new();
59 subject = buf_new();
60 buf_sets(subject, "Subject: Re: your mail");
61
62 buf_rewind(message);
63
64 f = mix_openfile(SOURCEBLOCK, "r");
65 if (f != NULL) {
66 buf_read(block, f);
67 fclose(f);
68 }
69 for (;;) {
70 err = buf_getheader(message, field, content);
71 if (err == 1) {
72 /* "::" marks for additional header lines */
73 while (buf_lookahead(message, field) == 1)
74 buf_getheader(message, field, content);
75 if (isline(field, HDRMARK))
76 continue;
77 else
78 goto hdrend;
79 }
80 if (err == -1)
81 goto hdrend;
82
83 if ((bufieq(field, "from") || bufieq(field, "sender") || bufieq(field,"received")) &&
84 doblock(content, block, 1) != 0)
85 goto end;
86
87 if (bufieq(field, "to"))
88 buf_cat(to, content);
89 else if (bufieq(field, "from") && replyto->length == 0)
90 /* reply to From address if no Reply-To header present */
91 buf_set(replyto, content);
92 else if (bufieq(field, "reply-to"))
93 buf_set(replyto, content);
94 else if (MIX && bufieq(field, "remailer-type") &&
95 bufileft(content, "mixmaster"))
96 type = MIXMSG;
97 else if (bufieq(field, "subject")) {
98 if (bufieq(content, "help") || bufieq(content, "remailer-help"))
99 type = REQUESTHELP;
100 else if (bufieq(content, "remailer-stats"))
101 type = REQUESTSTATS;
102 else if (bufieq(content, "remailer-key"))
103 type = REQUESTKEY;
104 else if (bufieq(content, "remailer-adminkey"))
105 type = REQUESTOPKEY;
106 else if (bufieq(content, "remailer-conf"))
107 type = REQUESTCONF;
108 else if (bufileft(content, "destination-block"))
109 type = BLOCKREQUEST;
110 else {
111 buf_sets(subject, "Subject: ");
112 if (!bufileft(content, "re:"))
113 buf_appends(subject, "Re: ");
114 buf_cat(subject, content);
115 }
116 } else if (bufieq(field, "test-to") || bufieq(field, "encrypted") ||
117 bufieq(field, "anon-to") ||
118 bufieq(field, "request-remailing-to") ||
119 bufieq(field, "remail-to") || bufieq(field, "anon-post-to") ||
120 bufieq(field, "post-to") || bufieq(field, "anon-send-to") ||
121 bufieq(field, "send-to") || bufieq(field, "remix-to") ||
122 bufieq(field, "encrypt-to"))
123 type = CPUNKMSG;
124 else if (bufieq(field, "content-transfer-encoding")
125 && bufieq(content, "quoted-printable")) {
126 quoted_printable = 1;
127 }
128
129 }
130 hdrend:
131 if (quoted_printable)
132 qp_decode_message(message);
133
134 if (type > 0 && REMAIL == 0)
135 type = DISABLED;
136 switch (type) {
137 case REQUESTHELP:
138 if (sendinfofile(HELPFILE, NULL, replyto, NULL) == -1)
139 errlog(WARNING, "No help file available.\n");
140 break;
141 case REQUESTKEY:
142 err = key(reply);
143 if (err == 0)
144 err = sendmail(reply, REMAILERNAME, replyto);
145 break;
146 case REQUESTOPKEY:
147 err = adminkey(reply);
148 if (err == 0)
149 err = sendmail(reply, REMAILERNAME, replyto);
150 break;
151 case REQUESTSTATS:
152 err = stats(reply);
153 if (err == 0)
154 err = sendmail(reply, REMAILERNAME, replyto);
155 break;
156 case REQUESTCONF:
157 err = conf(reply);
158 if (err == 0)
159 err = sendmail(reply, REMAILERNAME, replyto);
160 break;
161 case CPUNKMSG:
162 err = t1_decrypt(message);
163 if (err != 0) {
164 errlog(LOG, "Invalid type 1 message from %b\n", replyto);
165 sendinfofile(USAGEFILE, USAGELOG, replyto, NULL);
166 logmail(err == -2 ? MAILUSAGE : MAILERROR, message);
167 }
168 break;
169 case MIXMSG:
170 err = t2_decrypt(message);
171 if (err == -1) {
172 errlog(LOG, "Invalid type 2 message from %b\n", replyto);
173 sendinfofile(USAGEFILE, USAGELOG, replyto, NULL);
174 logmail(MAILERROR, message);
175 }
176 break;
177 case BLOCKREQUEST:
178 blockrequest(message);
179 logmail(MAILBLOCK, message);
180 break;
181 case DISABLED:
182 errlog(ERRORMSG, "Remailer is disabled.\n");
183 buf_sets(reply, "Subject: remailer error\n\nThe remailer is disabled.\n");
184 sendmail(reply, REMAILERNAME, replyto);
185 logmail(MAILERROR, message);
186 break;
187 default:
188 if (strifind
189 (replyto->data, "mailer-daemon")) {
190 errlog(LOG, "Bounce mail from %b\n", replyto);
191 logmail(MAILBOUNCE, message);
192 } else if (bufifind(to, REMAILERADDR) && blockrequest(message))
193 logmail(MAILBLOCK, message);
194 else if (!AUTOREPLY)
195 logmail(MAILBOX, message);
196 else if (bufifind(to, REMAILERADDR)) {
197 errlog(LOG, "Non-remailer message from %b\n", replyto);
198 sendinfofile(USAGEFILE, USAGELOG, replyto, NULL);
199 logmail(MAILUSAGE, message);
200 } else if (bufifind(to, COMPLAINTS)) {
201 errlog(WARNING, "Abuse complaint from %b\n", replyto);
202 sendinfofile(ABUSEFILE, NULL, replyto, subject);
203 logmail(MAILABUSE, message);
204 } else if (ANONADDR[0] && bufifind(to, ANONADDR)) {
205 errlog(LOG, "Reply to anonymous message from %b\n", replyto);
206 sendinfofile(REPLYFILE, NULL, replyto, subject);
207 logmail(MAILANON, message);
208 } else {
209 errlog(DEBUGINFO, "Mail from %b\n", replyto);
210 logmail(MAILBOX, message);
211 }
212 err = 1;
213 }
214 end:
215 buf_free(field);
216 buf_free(content);
217 buf_free(to);
218 buf_free(replyto);
219 buf_free(reply);
220 buf_free(block);
221 buf_free(subject);
222 return (err);
223 }
224
225 int t2_decrypt(BUFFER *in)
226 {
227 int err = 0;
228 BUFFER *msg;
229
230 msg = buf_new();
231 do {
232 err = mix_dearmor(in, msg);
233 if (err != -1) {
234 if (v3_magic(msg->data))
235 err = mix3_decrypt(msg);
236 else
237 err = mix2_decrypt(msg);
238 }
239 }
240 while (in->ptr + 1000 < in->length); /* accept several packets in one message */
241
242 buf_free(msg);
243 return (err);
244 }
245
246 int mix_pool(BUFFER *msg, int type, long latent)
247 {
248 char path[PATHMAX], pathtmp[PATHMAX];
249 FILE *f;
250 int err = -1;
251
252 f = pool_new(latent > 0 ? "lat" : "msg", pathtmp, path);
253 if (f != NULL) {
254 if (latent > 0)
255 fprintf(f, "%d %ld\n", type, latent + time(NULL));
256 else
257 fprintf(f, "%d 0\n", type);
258 err = buf_write_sync(msg, f);
259 }
260 if (err == 0) {
261 rename(pathtmp, path);
262 errlog(DEBUGINFO, "Added message to pool.\n");
263 }
264 return (err);
265 }
266
267 int pool_packetfile(char *fname, BUFFER *mid, int packetnum)
268 /* create a filename */
269 {
270 #ifdef SHORTNAMES
271 sprintf(fname, "%s%cp%02x%02x%02x%01x.%02x", POOLDIR, DIRSEP,
272 mid->data[0], mid->data[1], mid->data[2], mid->data[3] & 15,
273 packetnum);
274 #else /* end of SHORTNAMES */
275 sprintf(fname, "%s%cp%02x%02x%02x%02x%02x%02x%01x", POOLDIR, DIRSEP,
276 packetnum, mid->data[0], mid->data[1], mid->data[2], mid->data[3],
277 mid->data[4], mid->data[5] & 15);
278 #endif /* else if not SHORTNAMES */
279 return (0);
280 }
281
282 void pool_packetexp(void)
283 {
284 char *path;
285 DIR *d;
286 struct dirent *e;
287 struct stat sb;
288
289 d = opendir(POOLDIR);
290 errlog(DEBUGINFO, "Checking for old parts.\n");
291 if (d != NULL)
292 for (;;) {
293 e = readdir(d);
294 if (e == NULL)
295 break;
296 if (e->d_name[0] == 'p' || e->d_name[0] == 'e' || e->d_name[0] == 't') {
297 path=malloc(strlen(POOLDIR)+strlen(e->d_name)+strlen(DIRSEPSTR)+1);
298 if (path) {
299 strcpy(path, POOLDIR);
300 strcat(path, DIRSEPSTR);
301 strcat(path, e->d_name);
302 if (stat(path, &sb) == 0 && time(NULL) - sb.st_mtime > PACKETEXP) {
303 if (e->d_name[0] == 'p') {
304 errlog(NOTICE, "Expiring incomplete partial message %s.\n",
305 e->d_name);
306 }
307 else if (e->d_name[0] == 'e') {
308 errlog(NOTICE, "Expiring old error message %s.\n",
309 e->d_name);
310 }
311 else if (e->d_name[0] == 't') {
312 errlog(NOTICE, "Expiring moldy temporary message %s.\n",
313 e->d_name);
314 }
315 unlink(path);
316 }
317 free(path);
318 }
319 }
320 }
321 closedir(d);
322 }
323
324 void logmail(char *mailbox, BUFFER *message)
325 {
326 time_t t;
327 struct tm *tc;
328 char line[LINELEN];
329
330 /* mailbox is "|program", "user@host", "stdout" or "filename" */
331 buf_rewind(message);
332 if (mailbox[0] == '\0') /* default action */
333 mailbox = MAILBOX;
334 if (strieq(mailbox, "stdout"))
335 buf_write(message, stdout);
336 else if (mailbox[0] == '|') {
337 FILE *p;
338
339 errlog(DEBUGINFO, "Piping message to %s.\n", mailbox + 1);
340 p = openpipe(mailbox + 1);
341 if (p != NULL) {
342 buf_write(message, p);
343 closepipe(p);
344 }
345 } else if (strchr(mailbox, '@')) {
346 BUFFER *field, *content;
347
348 field = buf_new();
349 content = buf_new();
350 while (buf_getheader(message, field, content) == 0)
351 if (bufieq(field, "x-loop") && bufifind(content, REMAILERADDR)) {
352 errlog(WARNING, "Loop detected! Message not sent to %s.\n", mailbox);
353 goto isloop;
354 }
355 buf_sets(content, mailbox);
356 sendmail_loop(message, NULL, content);
357 isloop:
358 buf_free(field);
359 buf_free(content);
360 } else {
361 FILE *mbox;
362
363 mbox = mix_openfile(mailbox, "a");
364 if (mbox == NULL) {
365 errlog(ERRORMSG, "Can't write to mail folder %s\n", mailbox);
366 return;
367 }
368 lock(mbox);
369 if (!bufileft(message, "From ")) {
370 t = time(NULL);
371 tc = localtime(&t);
372 strftime(line, LINELEN, "From Mixmaster %a %b %d %H:%M:%S %Y\n", tc);
373 fprintf(mbox, line);
374 }
375 buf_write(message, mbox);
376 fprintf(mbox, "\n\n");
377 unlock(mbox);
378 fclose(mbox);
379 }
380 }
381
382 int blockrequest(BUFFER *message)
383 {
384 int request = 0, num, i;
385 BUFFER *from, *line, *field, *content, *addr, *remailer_addr, *copy_addr;
386 REMAILER remailer[MAXREM];
387 FILE *f;
388 char *destblklst = (char *)malloc( strlen(DESTBLOCK)+1 );
389 char *destblk;
390
391 from = buf_new();
392 line = buf_new();
393 field = buf_new();
394 content = buf_new();
395 addr = buf_new();
396 remailer_addr = buf_new();
397 copy_addr = buf_new();
398
399 if (destblklst == NULL) {
400 errlog(ERRORMSG, "Can't malloc %n bytes for destblklst.\n", strlen(DESTBLOCK)+1);
401 goto end;
402 };
403
404 buf_rewind(message);
405 while (buf_getheader(message, field, content) == 0)
406 if (bufieq(field, "from"))
407 buf_set(from, content);
408 else if (bufieq(field, "subject"))
409 buf_cat(message, content);
410 /* Append the subject to the message body so destination block requests
411 in the subject line work too (we process the body a few lines down) */
412 while (buf_getline(message, line) != -1)
413 if (bufifind(line, "destination-block")) {
414 buf_clear(addr);
415 request = 1;
416 {
417 int c = 0;
418
419 while (!strileft(line->data + line->ptr, "block"))
420 line->ptr++;
421 while (c != ' ' && c != -1)
422 c = tolower(buf_getc(line));
423 while (c == ' ')
424 c = buf_getc(line);
425 if (c != -1)
426 do {
427 buf_appendc(addr, c);
428 c = buf_getc(line);
429 } while (c > ' ');
430 }
431 if (addr->length == 0) {
432 rfc822_addr (from, addr);
433 buf_chop(addr);
434 }
435 /* Check whether somebody wants us to block ourselves */
436 buf_set(copy_addr, addr);
437 buf_sets(remailer_addr, REMAILERADDR);
438 if (doblock(remailer_addr, copy_addr, 1)) {
439 errlog(LOG, "Ignoring blocking request for %b from %b.\n", addr, from);
440 request = 2;
441 goto end;
442 }
443 /* Check if some evil person tries to block a known type II remailer */
444 num = mix2_rlist(remailer);
445 for (i = 0; i < num; i++) {
446 buf_sets(remailer_addr, remailer[i].addr);
447 if (doblock(remailer_addr, copy_addr, 1)) {
448 errlog(LOG, "Ignoring blocking request for %b from %b.\n", addr, from);
449 request = 2;
450 goto end;
451 }
452 }
453 /* Check if some evil person tries to block a known type I remailer */
454 num = t1_rlist(remailer);
455 for (i = 0; i < num; i++) {
456 buf_sets(remailer_addr, remailer[i].addr);
457 if (doblock(remailer_addr, copy_addr, 1)) {
458 errlog(LOG, "Ignoring blocking request for %b from %b.\n", addr, from);
459 request = 2;
460 goto end;
461 }
462 }
463
464 if (buf_ieq(addr, from))
465 errlog(NOTICE, "Blocking request for %b\n", addr);
466 else
467 errlog(NOTICE, "Blocking request for %b from %b\n", addr, from);
468 if (AUTOBLOCK) {
469 buf_clear(line);
470 rfc822_addr(addr, line);
471 if (line->length == 0) {
472 errlog(LOG, "Nothing to block after rfc822_addr().\n");
473 } else
474 if (bufleft(line, "/")) {
475 errlog(LOG, "Ignoring blocking request: %b is a regex.\n", addr);
476 } else {
477 if (strchr(line->data, '@') && strchr(strchr(line->data, '@'), '.')) {
478 strcpy( destblklst, DESTBLOCK );
479 destblk = strtok( destblklst, " " );
480 f = mix_openfile( destblk, "a" );
481 if (f != NULL) {
482 lock(f);
483
484 buf_chop(line);
485 sendinfofile(BLOCKFILE, NULL, line, NULL);
486 if (line->length) {
487 fprintf(f, "%s\n", line->data);
488 } else
489 errlog(NOTICE, "%b already blocked.\n", addr);
490 unlock(f);
491 fclose(f);
492 } else
493 errlog(ERRORMSG, "Can't write to %s.\n", DESTBLOCK);
494 } else
495 errlog(WARNING, "Invalid address not added to %s: %b\n", DESTBLOCK,
496 addr);
497 }
498 }
499 }
500
501 end:
502 free( destblklst );
503 buf_free(from);
504 buf_free(line);
505 buf_free(field);
506 buf_free(content);
507 buf_free(addr);
508 buf_free(remailer_addr);
509 buf_free(copy_addr);
510
511 return (request);
512 }
513
514
515 int idexp(void)
516 {
517 FILE *f;
518 BUFFER *b;
519 long now, then;
520 LOCK *i;
521 idlog_t idbuf;
522 long fpi = sizeof(idlog_t), fpo = sizeof(idlog_t);
523
524 if (IDEXP == 0)
525 return (0);
526
527 b = buf_new();
528 f = mix_openfile(IDLOG, "rb+");
529 if (f == NULL)
530 return (-1);
531 i = lockfile(IDLOG);
532 now = time(NULL);
533 if (fread(&idbuf, 1, sizeof(idlog_t), f) != sizeof(idlog_t)) { /* replace first line */
534 fclose(f);
535 unlockfile(i);
536 return (-1);
537 }
538 then = idbuf.time;
539 memset(idbuf.id,0,sizeof(idbuf.id));
540 idbuf.time = now - IDEXP;
541 fseek(f,0,SEEK_SET);
542 fwrite(&idbuf,1,sizeof(idlog_t),f);
543 fseek(f,fpi,SEEK_SET); /* this fseek does nothing, but MSVC CRT happilly reads past EOF (!!!) if we do not fseek here :-/ */
544 while (fread(&idbuf, 1, sizeof(idlog_t), f) == sizeof(idlog_t)) {
545 fpi+=sizeof(idlog_t);
546 then = idbuf.time;
547 if (now - then < IDEXP &&
548 now - then > - SECONDSPERDAY * 180 )
549 /* also expire packets that are dated more than half a year in the future.
550 * That way we get rid of invalid packets introduced by the switch to a
551 * binary id.log. */
552 {
553 fseek(f,fpo,SEEK_SET);
554 fwrite(&idbuf,1,sizeof(idlog_t),f);
555 fpo += sizeof(idlog_t);
556 fseek(f,fpi,SEEK_SET);
557 }
558 }
559 #ifdef _MSC_VER
560 chsize(fileno(f),fpo);
561 #else /* end of _MSC_VER */
562 ftruncate(fileno(f),fpo);
563 #endif /* else if not _MSC_VER */
564 fclose(f);
565 unlockfile(i);
566 buf_free(b);
567 return (0);
568 }

  ViewVC Help
Powered by ViewVC 1.1.5