/[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 327 - (show annotations) (download)
Wed Oct 9 20:29:44 2002 UTC (10 years, 8 months ago) by weaselp
File MIME type: text/plain
File size: 14359 byte(s)
Added closing comments for all #ifdef statements.
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.4 2002/10/09 20:29:44 weaselp 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
25 #include <dirent.h>
26 #endif /* not _MSC */
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");
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 /* end of _MSC */
519 ftruncate(fileno(f),fpo);
520 #endif /* else if not _MSC */
521 fclose(f);
522 unlockfile(i);
523 buf_free(b);
524 return (0);
525 }

  ViewVC Help
Powered by ViewVC 1.1.5