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

Contents of /trunk/Mix/Src/rem.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (hide annotations) (download)
Fri Nov 2 20:57:03 2001 UTC (11 years, 6 months ago) by rabbi
File MIME type: text/plain
File size: 12111 byte(s)
Writes correct message time to mbox. Contributed by Disastry.
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 rabbi 6 $Id: rem.c,v 1.2 2001/11/02 20:57:03 rabbi 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     #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    
51     mix_init(NULL);
52     field = buf_new();
53     content = buf_new();
54     to = buf_new();
55     replyto = buf_new();
56     reply = buf_new();
57     block = buf_new();
58     subject = buf_new();
59     buf_sets(subject, "Subject: Re: your mail");
60    
61     buf_rewind(message);
62    
63     f = mix_openfile(SOURCEBLOCK, "r");
64     if (f != NULL) {
65     buf_read(block, f);
66     fclose(f);
67     }
68     for (;;) {
69     err = buf_getheader(message, field, content);
70     if (err == 1) {
71     /* "::" marks for additional header lines */
72     while (buf_lookahead(message, field) == 1)
73     buf_getheader(message, field, content);
74     if (isline(field, HDRMARK))
75     continue;
76     else
77     goto hdrend;
78     }
79     if (err == -1)
80     goto hdrend;
81    
82     if ((bufieq(field, "from") || bufieq(field, "sender") || bufieq(field,"received")) &&
83     doblock(content, block, 1) != 0)
84     goto end;
85    
86     if (bufieq(field, "to"))
87     buf_cat(to, content);
88     else if (bufieq(field, "from") && replyto->length == 0)
89     /* reply to From address if no Reply-To header present */
90     buf_set(replyto, content);
91     else if (bufieq(field, "reply-to"))
92     buf_set(replyto, content);
93     else if (MIX && bufieq(field, "remailer-type") &&
94     bufileft(content, "mixmaster"))
95     type = MIXMSG;
96     else if (bufieq(field, "subject")) {
97     if (bufieq(content, "help") || bufieq(content, "remailer-help"))
98     type = REQUESTHELP;
99     else if (bufieq(content, "remailer-stats"))
100     type = REQUESTSTATS;
101     else if (bufieq(content, "remailer-key"))
102     type = REQUESTKEY;
103     else if (bufieq(content, "remailer-adminkey"))
104     type = REQUESTOPKEY;
105     else if (bufieq(content, "remailer-conf"))
106     type = REQUESTCONF;
107     else if (bufileft(content, "destination-block"))
108     type = BLOCKREQUEST;
109     else {
110     buf_sets(subject, "Subject: ");
111     if (!bufileft(content, "re:"))
112     buf_appends(subject, "Re: ");
113     buf_cat(subject, content);
114     }
115     } else if (bufieq(field, "test-to") || bufieq(field, "encrypted") ||
116     bufieq(field, "anon-to") ||
117     bufieq(field, "request-remailing-to") ||
118     bufieq(field, "remail-to") || bufieq(field, "anon-post-to") ||
119     bufieq(field, "post-to") || bufieq(field, "anon-send-to") ||
120     bufieq(field, "send-to") || bufieq(field, "remix-to"))
121     type = CPUNKMSG;
122     }
123     hdrend:
124     if (type > 0 && REMAIL == 0)
125     type = DISABLED;
126     switch (type) {
127     case REQUESTHELP:
128     if (sendinfofile(HELPFILE, NULL, replyto, NULL) == -1)
129     errlog(WARNING, "No help file available.\n");
130     break;
131     case REQUESTKEY:
132     err = key(reply);
133     if (err == 0)
134     err = sendmail(reply, REMAILERNAME, replyto);
135     break;
136     case REQUESTOPKEY:
137     err = adminkey(reply);
138     if (err == 0)
139     err = sendmail(reply, REMAILERNAME, replyto);
140     break;
141     case REQUESTSTATS:
142     err = stats(reply);
143     if (err == 0)
144     err = sendmail(reply, REMAILERNAME, replyto);
145     break;
146     case REQUESTCONF:
147     err = conf(reply);
148     if (err == 0)
149     err = sendmail(reply, REMAILERNAME, replyto);
150     break;
151     case CPUNKMSG:
152     err = t1_decrypt(message);
153     if (err != 0) {
154     errlog(LOG, "Invalid type 1 message from %b\n", replyto);
155     sendinfofile(USAGEFILE, USAGELOG, replyto, NULL);
156     logmail(err == -2 ? MAILUSAGE : MAILERROR, message);
157     }
158     break;
159     case MIXMSG:
160     err = t2_decrypt(message);
161     if (err == -1) {
162     errlog(LOG, "Invalid type 2 message from %b\n", replyto);
163     sendinfofile(USAGEFILE, USAGELOG, replyto, NULL);
164     logmail(MAILERROR, message);
165     }
166     break;
167     case BLOCKREQUEST:
168     blockrequest(message);
169     logmail(MAILBLOCK, message);
170     break;
171     case DISABLED:
172     errlog(ERRORMSG, "Remailer is disabled.\n");
173     buf_sets(reply, "Subject: remailer error\n\nThe remailer is disabled.\n");
174     sendmail(reply, REMAILERNAME, replyto);
175     logmail(MAILERROR, message);
176     break;
177     default:
178     if (strifind
179     (replyto->data, "mailer-daemon")) {
180     errlog(LOG, "Bounce mail from %b\n", replyto);
181     logmail(MAILBOUNCE, message);
182     } else if (bufifind(to, REMAILERADDR) && blockrequest(message))
183     logmail(MAILBLOCK, message);
184     else if (!AUTOREPLY)
185     logmail(MAILBOX, message);
186     else if (bufifind(to, REMAILERADDR)) {
187     errlog(LOG, "Non-remailer message from %b\n", replyto);
188     sendinfofile(USAGEFILE, USAGELOG, replyto, NULL);
189     logmail(MAILUSAGE, message);
190     } else if (bufifind(to, COMPLAINTS)) {
191     errlog(WARNING, "Abuse complaint from %b\n", replyto);
192     sendinfofile(ABUSEFILE, NULL, replyto, subject);
193     logmail(MAILABUSE, message);
194     } else if (ANONADDR[0] && bufifind(to, ANONADDR)) {
195     errlog(LOG, "Reply to anonymous message from %b\n", replyto);
196     sendinfofile(REPLYFILE, NULL, replyto, subject);
197     logmail(MAILANON, message);
198     } else {
199     errlog(DEBUGINFO, "Mail from %b\n", replyto);
200     logmail(MAILBOX, message);
201     }
202     err = 1;
203     }
204     end:
205     buf_free(field);
206     buf_free(content);
207     buf_free(to);
208     buf_free(replyto);
209     buf_free(reply);
210     buf_free(block);
211     buf_free(subject);
212     return (err);
213     }
214    
215     int t2_decrypt(BUFFER *in)
216     {
217     int err = 0;
218     BUFFER *msg;
219    
220     msg = buf_new();
221     do {
222     err = mix_dearmor(in, msg);
223     if (err != -1) {
224     if (v3_magic(msg->data))
225     err = mix3_decrypt(msg);
226     else
227     err = mix2_decrypt(msg);
228     }
229     }
230     while (in->ptr + 1000 < in->length); /* accept several packets in one message */
231    
232     buf_free(msg);
233     return (err);
234     }
235    
236     int mix_pool(BUFFER *msg, int type, long latent)
237     {
238     char path[PATHMAX], pathtmp[PATHMAX];
239     FILE *f;
240     int err = -1;
241    
242     f = pool_new(latent > 0 ? "lat" : "msg", pathtmp, path);
243     if (f != NULL) {
244     if (latent > 0)
245     fprintf(f, "%d %ld\n", type, latent + time(NULL));
246     else
247     fprintf(f, "%d 0\n", type);
248     err = buf_write(msg, f);
249     fclose(f);
250     }
251     if (err == 0) {
252     rename(pathtmp, path);
253     errlog(DEBUGINFO, "Added message to pool.\n");
254     }
255     return (err);
256     }
257    
258     int pool_packetfile(char *fname, BUFFER *mid, int packetnum)
259     /* create a filename */
260     {
261     #ifdef SHORTNAMES
262     sprintf(fname, "%s/p%02x%02x%02x%01x.%02x", POOLDIR,
263     mid->data[0], mid->data[1], mid->data[2], mid->data[3] & 15,
264     packetnum);
265     #else
266     sprintf(fname, "%s/p%02x%02x%02x%02x%02x%02x%01x", POOLDIR,
267     packetnum, mid->data[0], mid->data[1], mid->data[2], mid->data[3],
268     mid->data[4], mid->data[5] & 15);
269     #endif
270     return (0);
271     }
272    
273     void pool_packetexp(void)
274     {
275     DIR *d;
276     struct dirent *e;
277     struct stat sb;
278    
279     d = opendir(POOLDIR);
280     if (d != NULL)
281     for (;;) {
282     e = readdir(d);
283     if (e == NULL)
284     break;
285     if (e->d_name[0] == 'p') {
286     if (stat(e->d_name, &sb) == 0 &&
287     time(NULL) - sb.st_mtime > PACKETEXP) {
288     errlog(NOTICE, "Expiring partial message %s.\n",
289     e->d_name);
290     unlink(e->d_name);
291     }
292     }
293     }
294     closedir(d);
295     }
296    
297     void logmail(char *mailbox, BUFFER *message)
298     {
299 rabbi 6 time_t t;
300     struct tm *tc;
301     char line[LINELEN];
302    
303 rabbi 1 /* mailbox is "|program", "user@host", "stdout" or "filename" */
304     buf_rewind(message);
305     if (mailbox[0] == '\0') /* default action */
306     mailbox = MAILBOX;
307     if (strieq(mailbox, "stdout"))
308     buf_write(message, stdout);
309     else if (mailbox[0] == '|') {
310     FILE *p;
311    
312     errlog(DEBUGINFO, "Piping message to %s.", mailbox + 1);
313     p = openpipe(mailbox + 1);
314     if (p != NULL) {
315     buf_write(message, p);
316     closepipe(p);
317     }
318     } else if (strchr(mailbox, '@')) {
319     BUFFER *field, *content;
320    
321     field = buf_new();
322     content = buf_new();
323     while (buf_getheader(message, field, content) == 0)
324     if (bufieq(field, "x-loop") && bufifind(content, REMAILERADDR)) {
325     errlog(WARNING, "Loop detected! Message not sent to %s.\n", mailbox);
326     goto isloop;
327     }
328     buf_sets(content, mailbox);
329     sendmail(message, NULL, content);
330     isloop:
331     buf_free(field);
332     buf_free(content);
333     } else {
334     FILE *mbox;
335    
336     mbox = mix_openfile(mailbox, "a");
337     if (mbox == NULL) {
338     errlog(ERRORMSG, "Can't write to mail folder %s\n", mailbox);
339     return;
340     }
341     lock(mbox);
342 rabbi 6 if (!bufileft(message, "From ")) {
343     t = time(NULL);
344     tc = localtime(&t);
345     strftime(line, LINELEN, "From Mixmaster %a %b %d %H:%M:%S %Y\n", tc);
346     fprintf(mbox, line);
347     }
348 rabbi 1 buf_write(message, mbox);
349     fprintf(mbox, "\n");
350     unlock(mbox);
351     fclose(mbox);
352     }
353     }
354    
355     int blockrequest(BUFFER *message)
356     {
357     int request = 0, domain;
358     BUFFER *from, *line, *field, *content, *addr;
359     FILE *f;
360     char *destblklst = (char *)malloc( strlen(DESTBLOCK)+1 );
361     char *destblk;
362    
363     from = buf_new();
364     line = buf_new();
365     field = buf_new();
366     content = buf_new();
367     addr = buf_new();
368    
369     buf_rewind(message);
370     while (buf_getheader(message, field, content) == 0)
371     if (bufieq(field, "from"))
372     buf_set(from, content);
373     else if (bufieq(field, "subject"))
374     buf_cat(message, content);
375     while (buf_getline(message, line) != -1)
376     if (bufifind(line, "destination-block")) {
377     buf_clear(addr);
378     request = 1;
379     if (buffind(line, "@")) {
380     int c = 0;
381    
382     while (!strileft(line->data + line->ptr, "block"))
383     line->ptr++;
384     while (c != ' ')
385     c = tolower(buf_getc(line));
386     while (c == ' ')
387     c = buf_getc(line);
388     do {
389     buf_appendc(addr, c);
390     c = buf_getc(line);
391     } while (c > ' ');
392     } else
393     buf_set(addr, from);
394     if (bufieq(addr, REMAILERADDR)) {
395     errlog(LOG, "Ignoring blocking request for %b from %b.\n", addr, from);
396     return (2);
397     }
398     if (buf_ieq(addr, from))
399     errlog(NOTICE, "Blocking request for %b\n", addr);
400     else
401     errlog(NOTICE, "Blocking request for %b from %b\n", addr, from);
402     if (AUTOBLOCK) {
403     domain = 0;
404     if (addr->data[0] == '@') {
405     domain = 1;
406     buf_sets(line, "postmaster");
407     buf_cat(line, addr);
408     buf_move(addr, line);
409     }
410     buf_clear(line);
411     rfc822_addr(addr, line);
412     if (strchr(line->data, '@') && strchr(strchr(line->data, '@'), '.')) {
413     strcpy( destblklst, DESTBLOCK );
414     destblk = strtok( destblklst, " " );
415     f = mix_openfile( destblk, "a" );
416     free( destblklst );
417     if (f != NULL) {
418     lock(f);
419     sendinfofile(BLOCKFILE, NULL, line, NULL);
420     if (line->length) {
421     if (domain)
422     fprintf(f, "%s", line->data + sizeof("postmaster") - 1);
423     else
424     fprintf(f, "%s", line->data);
425     } else
426     errlog(NOTICE, "%b already blocked.\n", addr);
427     unlock(f);
428     fclose(f);
429     } else
430     errlog(ERRORMSG, "Can't write to %s.\n", DESTBLOCK);
431     } else
432     errlog(WARNING, "Invalid address not added to %s: %b\n", DESTBLOCK,
433     addr);
434     }
435     }
436     return (request);
437     }
438    
439    
440     int idexp(void)
441     {
442     FILE *f;
443     BUFFER *b;
444     long now, then;
445     char line[LINELEN];
446     LOCK *i;
447    
448     if (IDEXP == 0)
449     return (0);
450    
451     b = buf_new();
452     f = mix_openfile(IDLOG, "r");
453     if (f == NULL)
454     return (-1);
455     i = lockfile(IDLOG);
456     now = time(NULL);
457     fgets(line, sizeof(line), f); /* replace first line */
458     while (fgets(line, sizeof(line), f) != NULL) {
459     sscanf(line, "%*s %ld", &then);
460     if (now - then < IDEXP)
461     buf_appends(b, line);
462     }
463     fclose(f);
464     f = mix_openfile(IDLOG, "w");
465     if (f != NULL) {
466     fprintf(f, "expired %ld\n", now - IDEXP);
467     buf_write(b, f);
468     fclose(f);
469     }
470     unlockfile(i);
471     return (0);
472     }

  ViewVC Help
Powered by ViewVC 1.1.5