/[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 306 - (show annotations) (download)
Fri Oct 4 23:49:17 2002 UTC (10 years, 7 months ago) by rabbi
File MIME type: text/plain
File size: 14205 byte(s)
I've back-ported most of the important changes since 2.9b38 to the -STABLE branch.
I've only applied the changes I think are unlikely to break anything. This needs to be tested (and the diff'd reviewed) before we proceed.

If anyone feels I've left out anything that should really be in 2.9, please speak up.
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 remailer messages
9 $Id: rem.c,v 1.20.2.3 2002/10/04 23:49:16 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
22 #include <io.h>
23 #endif
24 #ifndef _MSC
25 #include <dirent.h>
26 #endif
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
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
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");
377 unlock(mbox);
378 fclose(mbox);
379 }
380 }
381
382 int blockrequest(BUFFER *message)
383 {
384 int request = 0;
385 BUFFER *from, *line, *field, *content, *addr;
386 FILE *f;
387 char *destblklst = (char *)malloc( strlen(DESTBLOCK)+1 );
388 char *destblk;
389
390 from = buf_new();
391 line = buf_new();
392 field = buf_new();
393 content = buf_new();
394 addr = buf_new();
395
396 buf_rewind(message);
397 while (buf_getheader(message, field, content) == 0)
398 if (bufieq(field, "from"))
399 buf_set(from, content);
400 else if (bufieq(field, "subject"))
401 buf_cat(message, content);
402 /* Append the subject to the message body so destination block requests
403 in the subject line work too (we process the body a few lines down) */
404 while (buf_getline(message, line) != -1)
405 if (bufifind(line, "destination-block")) {
406 buf_clear(addr);
407 request = 1;
408 {
409 int c = 0;
410
411 while (!strileft(line->data + line->ptr, "block"))
412 line->ptr++;
413 while (c != ' ' && c != -1)
414 c = tolower(buf_getc(line));
415 while (c == ' ')
416 c = buf_getc(line);
417 if (c != -1)
418 do {
419 buf_appendc(addr, c);
420 c = buf_getc(line);
421 } while (c > ' ');
422 }
423 if (addr->length == 0) {
424 rfc822_addr (from, addr);
425 buf_chop(addr);
426 }
427 if (bufieq(addr, REMAILERADDR)) {
428 errlog(LOG, "Ignoring blocking request for %b from %b.\n", addr, from);
429 return (2);
430 }
431 if (buf_ieq(addr, from))
432 errlog(NOTICE, "Blocking request for %b\n", addr);
433 else
434 errlog(NOTICE, "Blocking request for %b from %b\n", addr, from);
435 if (AUTOBLOCK) {
436 buf_clear(line);
437 rfc822_addr(addr, line);
438 if (line->length == 0) {
439 errlog(LOG, "Nothing to block after rfc822_addr().\n");
440 } else
441 if (bufleft(line, "/")) {
442 errlog(LOG, "Ignoring blocking request: %b is a regex.\n", addr);
443 } else {
444 if (strchr(line->data, '@') && strchr(strchr(line->data, '@'), '.')) {
445 strcpy( destblklst, DESTBLOCK );
446 destblk = strtok( destblklst, " " );
447 f = mix_openfile( destblk, "a" );
448 free( destblklst );
449 if (f != NULL) {
450 lock(f);
451
452 buf_chop(line);
453 sendinfofile(BLOCKFILE, NULL, line, NULL);
454 if (line->length) {
455 fprintf(f, "%s\n", line->data);
456 } else
457 errlog(NOTICE, "%b already blocked.\n", addr);
458 unlock(f);
459 fclose(f);
460 } else
461 errlog(ERRORMSG, "Can't write to %s.\n", DESTBLOCK);
462 } else
463 errlog(WARNING, "Invalid address not added to %s: %b\n", DESTBLOCK,
464 addr);
465 }
466 }
467 }
468 return (request);
469 }
470
471
472 int idexp(void)
473 {
474 FILE *f;
475 BUFFER *b;
476 long now, then;
477 LOCK *i;
478 idlog_t idbuf;
479 long fpi = sizeof(idlog_t), fpo = sizeof(idlog_t);
480
481 if (IDEXP == 0)
482 return (0);
483
484 b = buf_new();
485 f = mix_openfile(IDLOG, "rb+");
486 if (f == NULL)
487 return (-1);
488 i = lockfile(IDLOG);
489 now = time(NULL);
490 if (fread(&idbuf, 1, sizeof(idlog_t), f) != sizeof(idlog_t)) { /* replace first line */
491 fclose(f);
492 unlockfile(i);
493 return (-1);
494 }
495 then = idbuf.time;
496 memset(idbuf.id,0,sizeof(idbuf.id));
497 idbuf.time = now - IDEXP;
498 fseek(f,0,SEEK_SET);
499 fwrite(&idbuf,1,sizeof(idlog_t),f);
500 fseek(f,fpi,SEEK_SET); /* this fseek does nothing, but MSVC CRT happilly reads past EOF (!!!) if we do not fseek here :-/ */
501 while (fread(&idbuf, 1, sizeof(idlog_t), f) == sizeof(idlog_t)) {
502 fpi+=sizeof(idlog_t);
503 then = idbuf.time;
504 if (now - then < IDEXP &&
505 now - then > - SECONDSPERDAY * 180 )
506 /* also expire packets that are dated more than half a year in the future.
507 * That way we get rid of invalid packets introduced by the switch to a
508 * binary id.log. */
509 {
510 fseek(f,fpo,SEEK_SET);
511 fwrite(&idbuf,1,sizeof(idlog_t),f);
512 fpo += sizeof(idlog_t);
513 fseek(f,fpi,SEEK_SET);
514 }
515 }
516 #ifdef _MSC
517 chsize(fileno(f),fpo);
518 #else
519 ftruncate(fileno(f),fpo);
520 #endif
521 fclose(f);
522 unlockfile(i);
523 buf_free(b);
524 return (0);
525 }

  ViewVC Help
Powered by ViewVC 1.1.5