/[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 331 - (hide annotations) (download)
Wed Oct 9 20:51:09 2002 UTC (10 years, 7 months ago) by weaselp
File MIME type: text/plain
File size: 14153 byte(s)
Whitespace cleanup:
for i in *.c; do cp -a $i $i.orig; sed -e 's/^        /<TAB>/' $i.orig > $i; rm $i.orig; done
for i in *.c *.h; do cp -a $i $i.orig; sed -e 's/[ <TAB>]*$//' $i.orig > $i; rm $i.orig; done
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 remailer messages
9 weaselp 331 $Id: rem.c,v 1.20.2.5 2002/10/09 20:51:08 weaselp Exp $ */
10 rabbi 1
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 weaselp 327 #else /* end of POSIX */
22 rabbi 1 #include <io.h>
23 weaselp 327 #endif /* else if not POSIX */
24 rabbi 1 #ifndef _MSC
25     #include <dirent.h>
26 weaselp 327 #endif /* not _MSC */
27 rabbi 1 #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 rabbi 41 int quoted_printable = 0; /* is this message quoted printable encoded */
51 rabbi 1
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 weaselp 331 type = REQUESTOPKEY;
106 rabbi 1 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 rabbi 62 bufieq(field, "send-to") || bufieq(field, "remix-to") ||
122 weaselp 106 bufieq(field, "encrypt-to"))
123 rabbi 1 type = CPUNKMSG;
124 rabbi 41 else if (bufieq(field, "content-transfer-encoding")
125 weaselp 331 && bufieq(content, "quoted-printable")) {
126 rabbi 41 quoted_printable = 1;
127     }
128 weaselp 331
129 rabbi 1 }
130     hdrend:
131 rabbi 41 if (quoted_printable)
132     qp_decode_message(message);
133    
134 rabbi 1 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 weaselp 120 err = buf_write_sync(msg, f);
259 rabbi 1 }
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 rabbi 11 sprintf(fname, "%s%cp%02x%02x%02x%01x.%02x", POOLDIR, DIRSEP,
272 rabbi 1 mid->data[0], mid->data[1], mid->data[2], mid->data[3] & 15,
273     packetnum);
274 weaselp 327 #else /* end of SHORTNAMES */
275 rabbi 11 sprintf(fname, "%s%cp%02x%02x%02x%02x%02x%02x%01x", POOLDIR, DIRSEP,
276 rabbi 1 packetnum, mid->data[0], mid->data[1], mid->data[2], mid->data[3],
277     mid->data[4], mid->data[5] & 15);
278 weaselp 327 #endif /* else if not SHORTNAMES */
279 rabbi 1 return (0);
280     }
281    
282     void pool_packetexp(void)
283     {
284 rabbi 72 char *path;
285 rabbi 1 DIR *d;
286     struct dirent *e;
287     struct stat sb;
288    
289     d = opendir(POOLDIR);
290 rabbi 306 errlog(DEBUGINFO, "Checking for old parts.\n");
291 rabbi 1 if (d != NULL)
292     for (;;) {
293     e = readdir(d);
294     if (e == NULL)
295     break;
296 rabbi 247 if (e->d_name[0] == 'p' || e->d_name[0] == 'e' || e->d_name[0] == 't') {
297 weaselp 331 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 rabbi 1 }
319     }
320     }
321     closedir(d);
322     }
323    
324     void logmail(char *mailbox, BUFFER *message)
325     {
326 rabbi 6 time_t t;
327     struct tm *tc;
328     char line[LINELEN];
329    
330 rabbi 1 /* 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 rabbi 66 errlog(DEBUGINFO, "Piping message to %s.\n", mailbox + 1);
340 rabbi 1 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 weaselp 116 sendmail_loop(message, NULL, content);
357 rabbi 1 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 rabbi 6 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 rabbi 1 buf_write(message, mbox);
376     fprintf(mbox, "\n");
377     unlock(mbox);
378     fclose(mbox);
379     }
380     }
381    
382     int blockrequest(BUFFER *message)
383     {
384 rabbi 59 int request = 0;
385 rabbi 1 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 weaselp 331 buf_cat(message, content);
402     /* Append the subject to the message body so destination block requests
403 rabbi 30 in the subject line work too (we process the body a few lines down) */
404 rabbi 1 while (buf_getline(message, line) != -1)
405     if (bufifind(line, "destination-block")) {
406     buf_clear(addr);
407     request = 1;
408 rabbi 52 {
409 rabbi 1 int c = 0;
410    
411     while (!strileft(line->data + line->ptr, "block"))
412     line->ptr++;
413 rabbi 52 while (c != ' ' && c != -1)
414 rabbi 1 c = tolower(buf_getc(line));
415     while (c == ' ')
416     c = buf_getc(line);
417 rabbi 52 if (c != -1)
418     do {
419     buf_appendc(addr, c);
420     c = buf_getc(line);
421     } while (c > ' ');
422 rabbi 48 }
423 rabbi 55 if (addr->length == 0) {
424 rabbi 54 rfc822_addr (from, addr);
425 rabbi 55 buf_chop(addr);
426     }
427 rabbi 1 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 rabbi 59 if (line->length == 0) {
439     errlog(LOG, "Nothing to block after rfc822_addr().\n");
440 rabbi 1 } else
441 rabbi 59 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 weaselp 331 strcpy( destblklst, DESTBLOCK );
446     destblk = strtok( destblklst, " " );
447     f = mix_openfile( destblk, "a" );
448     free( destblklst );
449 rabbi 59 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 rabbi 1 }
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 rabbi 82 idlog_t idbuf;
479     long fpi = sizeof(idlog_t), fpo = sizeof(idlog_t);
480 rabbi 1
481     if (IDEXP == 0)
482     return (0);
483    
484     b = buf_new();
485 rabbi 82 f = mix_openfile(IDLOG, "rb+");
486 rabbi 1 if (f == NULL)
487     return (-1);
488     i = lockfile(IDLOG);
489     now = time(NULL);
490 rabbi 82 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 rabbi 248 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 rabbi 82 {
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 rabbi 1 }
516 rabbi 82 #ifdef _MSC
517     chsize(fileno(f),fpo);
518 weaselp 327 #else /* end of _MSC */
519 rabbi 82 ftruncate(fileno(f),fpo);
520 weaselp 327 #endif /* else if not _MSC */
521 rabbi 1 fclose(f);
522     unlockfile(i);
523 rabbi 73 buf_free(b);
524 rabbi 1 return (0);
525     }

  ViewVC Help
Powered by ViewVC 1.1.5