/[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 68 - (hide annotations) (download)
Sat Mar 9 02:45:34 2002 UTC (11 years, 2 months ago) by rabbi
File MIME type: text/plain
File size: 12854 byte(s)
Partial packets were not being removed from the pool directory after
expiring. This was due to a bug in rem.c, function pool_packetexp(), which
tried to unlink() the file name (which was not in the current working
directory).

We now supply the full path to the expired packet file.

Also modified .cvsignore to ignore pcre cruft.
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 68 $Id: rem.c,v 1.14 2002/03/09 02:45:34 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 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     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 rabbi 62 bufieq(field, "send-to") || bufieq(field, "remix-to") ||
122     bufieq(field, "encrypt-to"))
123 rabbi 1 type = CPUNKMSG;
124 rabbi 41 else if (bufieq(field, "content-transfer-encoding")
125     && bufieq(content, "quoted-printable")) {
126     quoted_printable = 1;
127     }
128    
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     err = buf_write(msg, f);
259     fclose(f);
260     }
261     if (err == 0) {
262     rename(pathtmp, path);
263     errlog(DEBUGINFO, "Added message to pool.\n");
264     }
265     return (err);
266     }
267    
268     int pool_packetfile(char *fname, BUFFER *mid, int packetnum)
269     /* create a filename */
270     {
271     #ifdef SHORTNAMES
272 rabbi 11 sprintf(fname, "%s%cp%02x%02x%02x%01x.%02x", POOLDIR, DIRSEP,
273 rabbi 1 mid->data[0], mid->data[1], mid->data[2], mid->data[3] & 15,
274     packetnum);
275     #else
276 rabbi 11 sprintf(fname, "%s%cp%02x%02x%02x%02x%02x%02x%01x", POOLDIR, DIRSEP,
277 rabbi 1 packetnum, mid->data[0], mid->data[1], mid->data[2], mid->data[3],
278     mid->data[4], mid->data[5] & 15);
279     #endif
280     return (0);
281     }
282    
283     void pool_packetexp(void)
284     {
285 rabbi 68 char path[PATHMAX];
286 rabbi 1 DIR *d;
287     struct dirent *e;
288     struct stat sb;
289    
290     d = opendir(POOLDIR);
291     if (d != NULL)
292     for (;;) {
293     e = readdir(d);
294     if (e == NULL)
295     break;
296     if (e->d_name[0] == 'p') {
297     if (stat(e->d_name, &sb) == 0 &&
298     time(NULL) - sb.st_mtime > PACKETEXP) {
299     errlog(NOTICE, "Expiring partial message %s.\n",
300     e->d_name);
301 rabbi 68 strncpy(path, POOLDIR, PATHMAX);
302     strncat(path, DIRSEPSTR, PATHMAX);
303     strncat(path, e->d_name, PATHMAX);
304     unlink(path);
305 rabbi 1 }
306     }
307     }
308     closedir(d);
309     }
310    
311     void logmail(char *mailbox, BUFFER *message)
312     {
313 rabbi 6 time_t t;
314     struct tm *tc;
315     char line[LINELEN];
316    
317 rabbi 1 /* mailbox is "|program", "user@host", "stdout" or "filename" */
318     buf_rewind(message);
319     if (mailbox[0] == '\0') /* default action */
320     mailbox = MAILBOX;
321     if (strieq(mailbox, "stdout"))
322     buf_write(message, stdout);
323     else if (mailbox[0] == '|') {
324     FILE *p;
325    
326 rabbi 66 errlog(DEBUGINFO, "Piping message to %s.\n", mailbox + 1);
327 rabbi 1 p = openpipe(mailbox + 1);
328     if (p != NULL) {
329     buf_write(message, p);
330     closepipe(p);
331     }
332     } else if (strchr(mailbox, '@')) {
333     BUFFER *field, *content;
334    
335     field = buf_new();
336     content = buf_new();
337     while (buf_getheader(message, field, content) == 0)
338     if (bufieq(field, "x-loop") && bufifind(content, REMAILERADDR)) {
339     errlog(WARNING, "Loop detected! Message not sent to %s.\n", mailbox);
340     goto isloop;
341     }
342     buf_sets(content, mailbox);
343     sendmail(message, NULL, content);
344     isloop:
345     buf_free(field);
346     buf_free(content);
347     } else {
348     FILE *mbox;
349    
350     mbox = mix_openfile(mailbox, "a");
351     if (mbox == NULL) {
352     errlog(ERRORMSG, "Can't write to mail folder %s\n", mailbox);
353     return;
354     }
355     lock(mbox);
356 rabbi 6 if (!bufileft(message, "From ")) {
357     t = time(NULL);
358     tc = localtime(&t);
359     strftime(line, LINELEN, "From Mixmaster %a %b %d %H:%M:%S %Y\n", tc);
360     fprintf(mbox, line);
361     }
362 rabbi 1 buf_write(message, mbox);
363     fprintf(mbox, "\n");
364     unlock(mbox);
365     fclose(mbox);
366     }
367     }
368    
369     int blockrequest(BUFFER *message)
370     {
371 rabbi 59 int request = 0;
372 rabbi 1 BUFFER *from, *line, *field, *content, *addr;
373     FILE *f;
374     char *destblklst = (char *)malloc( strlen(DESTBLOCK)+1 );
375     char *destblk;
376    
377     from = buf_new();
378     line = buf_new();
379     field = buf_new();
380     content = buf_new();
381     addr = buf_new();
382    
383     buf_rewind(message);
384     while (buf_getheader(message, field, content) == 0)
385     if (bufieq(field, "from"))
386     buf_set(from, content);
387     else if (bufieq(field, "subject"))
388 rabbi 30 buf_cat(message, content);
389     /* Append the subject to the message body so destination block requests
390     in the subject line work too (we process the body a few lines down) */
391 rabbi 1 while (buf_getline(message, line) != -1)
392     if (bufifind(line, "destination-block")) {
393     buf_clear(addr);
394     request = 1;
395 rabbi 52 {
396 rabbi 1 int c = 0;
397    
398     while (!strileft(line->data + line->ptr, "block"))
399     line->ptr++;
400 rabbi 52 while (c != ' ' && c != -1)
401 rabbi 1 c = tolower(buf_getc(line));
402     while (c == ' ')
403     c = buf_getc(line);
404 rabbi 52 if (c != -1)
405     do {
406     buf_appendc(addr, c);
407     c = buf_getc(line);
408     } while (c > ' ');
409 rabbi 48 }
410 rabbi 55 if (addr->length == 0) {
411 rabbi 54 rfc822_addr (from, addr);
412 rabbi 55 buf_chop(addr);
413     }
414 rabbi 1 if (bufieq(addr, REMAILERADDR)) {
415     errlog(LOG, "Ignoring blocking request for %b from %b.\n", addr, from);
416     return (2);
417     }
418     if (buf_ieq(addr, from))
419     errlog(NOTICE, "Blocking request for %b\n", addr);
420     else
421     errlog(NOTICE, "Blocking request for %b from %b\n", addr, from);
422     if (AUTOBLOCK) {
423     buf_clear(line);
424     rfc822_addr(addr, line);
425 rabbi 59 if (line->length == 0) {
426     errlog(LOG, "Nothing to block after rfc822_addr().\n");
427 rabbi 1 } else
428 rabbi 59 if (bufleft(line, "/")) {
429     errlog(LOG, "Ignoring blocking request: %b is a regex.\n", addr);
430     } else {
431     if (strchr(line->data, '@') && strchr(strchr(line->data, '@'), '.')) {
432     strcpy( destblklst, DESTBLOCK );
433     destblk = strtok( destblklst, " " );
434     f = mix_openfile( destblk, "a" );
435     free( destblklst );
436     if (f != NULL) {
437     lock(f);
438    
439     buf_chop(line);
440     sendinfofile(BLOCKFILE, NULL, line, NULL);
441     if (line->length) {
442     fprintf(f, "%s\n", line->data);
443     } else
444     errlog(NOTICE, "%b already blocked.\n", addr);
445     unlock(f);
446     fclose(f);
447     } else
448     errlog(ERRORMSG, "Can't write to %s.\n", DESTBLOCK);
449     } else
450     errlog(WARNING, "Invalid address not added to %s: %b\n", DESTBLOCK,
451     addr);
452     }
453 rabbi 1 }
454     }
455     return (request);
456     }
457    
458    
459     int idexp(void)
460     {
461     FILE *f;
462     BUFFER *b;
463     long now, then;
464     char line[LINELEN];
465     LOCK *i;
466    
467     if (IDEXP == 0)
468     return (0);
469    
470     b = buf_new();
471     f = mix_openfile(IDLOG, "r");
472     if (f == NULL)
473     return (-1);
474     i = lockfile(IDLOG);
475     now = time(NULL);
476     fgets(line, sizeof(line), f); /* replace first line */
477     while (fgets(line, sizeof(line), f) != NULL) {
478     sscanf(line, "%*s %ld", &then);
479     if (now - then < IDEXP)
480     buf_appends(b, line);
481     }
482     fclose(f);
483     f = mix_openfile(IDLOG, "w");
484     if (f != NULL) {
485     fprintf(f, "expired %ld\n", now - IDEXP);
486     buf_write(b, f);
487     fclose(f);
488     }
489     unlockfile(i);
490     return (0);
491     }

  ViewVC Help
Powered by ViewVC 1.1.5