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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 592 - (hide annotations) (download)
Mon Sep 29 01:06:54 2003 UTC (9 years, 8 months ago) by weaselp
File MIME type: text/plain
File size: 22146 byte(s)
Ignore 'No reliable remailers' problems when randhopping messages in middleman
mode.  That is better than dropping them.
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     Send messages from pool
9 weaselp 592 $Id: pool.c,v 1.23 2003/09/29 01:06:54 weaselp Exp $ */
10 rabbi 1
11     #include "mix3.h"
12     #include <stdlib.h>
13     #include <string.h>
14     #include <ctype.h>
15     #include <sys/types.h>
16     #include <time.h>
17     #ifdef POSIX
18     #include <unistd.h>
19 rabbi 262 #else /* end of POSIX */
20 rabbi 1 #include <io.h>
21 rabbi 262 #endif /* else if not POSIX */
22 rabbi 1 #ifndef _MSC
23     #include <dirent.h>
24 rabbi 262 #endif /* not _MSC */
25 rabbi 1 #include <assert.h>
26 weaselp 387 #include <sys/stat.h>
27     #include <sys/types.h>
28 rabbi 1
29     #ifdef USE_PCRE
30     #include "pcre.h"
31 rabbi 262 #endif /* USE_PCRE */
32 rabbi 1
33     int msg_send(char *name);
34    
35     int mix_send(void)
36     {
37     return (mix_regular(FORCE_POOL));
38     }
39    
40     /* Message pool: Unix DOS
41     * latent messages: l* *.lat
42     * pooled messages: m* *.msg
43     * messages to be sent: s* *.snd
44     * temporary files: t* *.tmp
45     * files in user editor: x*
46     * incoming mail: i* *.inf
47     * partial messages: p* p*.*
48 rabbi 18 * error messages: e* *.err
49 rabbi 74 * outgoing messages: out *.txt (to be used by external program)
50 rabbi 1 */
51    
52     static int is(char *path, char *type)
53     {
54     #ifdef SHORTNAMES
55     int s;
56    
57     s = strlen(path);
58     if (s <= 4)
59     return 0;
60     return (path[s - 4] == '.' && streq(path + s - 3, type));
61 rabbi 262 #else /* end of SHORTNAMES */
62 rabbi 1 return (path[0] == type[0]);
63 rabbi 262 #endif /* else if not SHORTNAMES */
64 rabbi 1 }
65    
66     static void mv(char *name, char *newtype)
67     {
68     char old[PATHMAX], new[PATHMAX];
69    
70 rabbi 11 sprintf(old, "%s%c%s", POOLDIR, DIRSEP, name);
71 rabbi 1 #ifdef SHORTNAMES
72     assert(strlen(name) > 4);
73     strcpy(name + strlen(name) - 3, newtype);
74 rabbi 262 #else /* end of SHORTNAMES */
75 rabbi 1 name[0] = newtype[0];
76 rabbi 262 #endif /* else if not SHORTNAMES */
77 rabbi 11 sprintf(new, "%s%c%s", POOLDIR, DIRSEP, name);
78 rabbi 1 rename(old, new);
79     }
80    
81     int latent_read(void)
82     {
83     char path[PATHMAX];
84     DIR *d;
85     FILE *f;
86     struct dirent *e;
87     int size = 0;
88     long now, then;
89    
90     now = time(NULL);
91     d = opendir(POOLDIR);
92     if (d != NULL)
93     for (;;) {
94     e = readdir(d);
95     if (e == NULL)
96     break;
97     if (is(e->d_name, "lat")) {
98 rabbi 11 sprintf(path, "%s%c%s", POOLDIR, DIRSEP, e->d_name);
99 rabbi 1 f = fopen(path, "rb");
100     if (f != NULL) {
101     fscanf(f, "%*d %ld\n", &then);
102     fclose(f);
103     if (now > then)
104     mv(e->d_name, "msg");
105     }
106     }
107     }
108     closedir(d);
109     return (size);
110     }
111    
112     int infile_read(void)
113     {
114     char path[PATHMAX];
115     BUFFER *msg;
116     DIR *d;
117     FILE *f;
118     struct dirent *e;
119     int size = 0;
120    
121     msg = buf_new();
122     d = opendir(POOLDIR);
123     if (d != NULL)
124     for (;;) {
125     e = readdir(d);
126     if (e == NULL)
127     break;
128     if (is(e->d_name, "inf")) {
129     mv(e->d_name, "tmp");
130 rabbi 11 sprintf(path, "%s%c%s", POOLDIR, DIRSEP, e->d_name);
131 rabbi 1 f = fopen(path, "rb");
132     if (f != NULL) {
133     buf_clear(msg);
134     buf_read(msg, f);
135     fclose(f);
136     unlink(path);
137     mix_decrypt(msg);
138     }
139     }
140     }
141     closedir(d);
142     buf_free(msg);
143     return (size);
144     }
145    
146 weaselp 163 int mailin_maildir_one(char *dir)
147     /** Read mails from one directory
148     This function reads all files from the directory passed and passes
149     them on to mix_decrypt(). Each file is unlinked when its is read.
150    
151     @param dir The directory in which files are to be read. No path finding
152     voodoo is done to the path; It's passed it opendir() as is.
153     @author PP
154     @return Number of files read
155     */
156     {
157     BUFFER *msg;
158     DIR *d;
159     FILE *f;
160     struct dirent *e;
161     int size = 0;
162     char path[PATHMAX];
163    
164     msg = buf_new();
165     d = opendir(dir);
166     if (d != NULL)
167     for (;;) {
168     e = readdir(d);
169     if (e == NULL)
170     break;
171     if (e->d_name[0] != '.') {
172     sprintf(path, "%s%c%s", dir, DIRSEP, e->d_name);
173 weaselp 332 path[PATHMAX-1]='\0';
174 weaselp 163 f = fopen(path, "rb");
175     if (f != NULL) {
176     buf_clear(msg);
177     buf_read(msg, f);
178     fclose(f);
179     unlink(path);
180     mix_decrypt(msg);
181     size++;
182     }
183     }
184     }
185     closedir(d);
186     buf_free(msg);
187     return (size);
188     }
189    
190     int mailin_maildir(char *maildir)
191     /** Read mails from a mail folder in Maildir format
192     Reads all files from the Maildir using mailin_maildir_one().
193     All mails are removed after this function returns.
194    
195     @param maildir The Maildir to open. mixfile() is called to normalize the path.
196     @author PP
197     @return 0
198     */
199     {
200     char normalized[PATHMAX];
201     char path[PATHMAX];
202    
203     mixfile(normalized, maildir);
204     sprintf(path, "%s%c%s", normalized, DIRSEP, "new");
205     path[PATHMAX-1]='\0';
206     mailin_maildir_one(path);
207     sprintf(path, "%s%c%s", normalized, DIRSEP, "cur");
208     path[PATHMAX-1]='\0';
209     mailin_maildir_one(path);
210     return (0);
211     }
212    
213     int mailin_mbox(char *path)
214     /** Read mails from a mail folder in mbox format
215     Reads all messages from the mbox filder passes as an argument. Mails are
216     handed over to mix_decrypt. After all mails have been read the mailbox
217     is truncated to zero size i.e. all mails are deleted. The mbox is
218     locked using lock() and unlock() during this operation.
219    
220     @param maildir Path to the mbox mail folder.
221     @author PP
222     @return 0 on sucess, other on error
223     */
224     {
225     char line[LINELEN];
226     FILE *f;
227     int state, eof;
228     BUFFER *msg;
229     int err=0;
230 weaselp 332
231 weaselp 163 msg = buf_new();
232    
233     f = mix_openfile(path, "r+");
234     if (f != NULL) {
235     if (lock(f) != 0) {
236     /* Locking failed */
237     err = 1;
238     goto end;
239     }
240     /* State machine
241     * 1 - Look for the first ^From_ line
242     * 2 - add messages as they come
243     */
244     state = 1;
245     eof = 0;
246     for(;;) {
247     if (fgets(line, sizeof(line), f) == NULL)
248     eof = 1;
249    
250     switch (state) {
251     case 1:
252     /* Initial state - Looking for first appearance of From_ */
253     if (eof)
254     goto end_state;
255     if (strleft(line, "From ")) {
256 rabbi 221 #if 0
257     buf_appends(msg, line);
258 rabbi 262 #endif /* 0 */
259 weaselp 163 state = 2;
260     break;
261     };
262     break;
263     case 2:
264     /* Within one mail - Adding lines to mail until we encounter another From_ or eof */
265     if (eof || strleft(line, "From ")) {
266     mix_decrypt(msg);
267     buf_clear(msg);
268     }
269     if (eof)
270     goto end_state;
271     if (!strleft(line, "From "))
272     buf_appends(msg, line);
273     break;
274     default:
275     assert(0);
276     err=1;
277     goto end_state;
278     }
279     }
280     end_state:
281     #ifndef WIN32
282     rewind(f);
283     ftruncate(fileno(f), 0);
284 rabbi 262 #else /* end of not WIN32 */
285 weaselp 163 chsize(fileno(f), 0);
286 rabbi 262 #endif /* else if WIN32 */
287 weaselp 163 unlock(f);
288     fclose(f);
289     }
290     end:
291     buf_free(msg);
292     return (err);
293     }
294    
295     /** Process MAILIN if applicable
296     If MAILIN is defined this function calls either mailin_maildir() or
297     mailin_mbox() depending on whether the last character of MAILIN
298     is DIRSEP.
299    
300     @param mailbox Path to the mbox or Maildir mail folder.
301     @author PP
302     @return 0 on sucess, other on error
303     */
304     int mailin(char *mailbox)
305     {
306 weaselp 181 if (mailbox != NULL && (strcmp(mailbox, "") != 0))
307 weaselp 163 if (mailbox[strlen(mailbox)-1] == DIRSEP)
308     return mailin_maildir(mailbox);
309     else
310     return mailin_mbox(mailbox);
311     else
312     return 0;
313     };
314    
315 rabbi 1 int pool_add(BUFFER *msg, char *type)
316     {
317     char path[PATHMAX], pathtmp[PATHMAX];
318     FILE *f;
319     int err = -1;
320    
321     f = pool_new(type, pathtmp, path);
322     if (f != NULL) {
323     err = buf_write(msg, f);
324     fclose(f);
325     }
326     if (err == 0) {
327     rename(pathtmp, path);
328     errlog(DEBUGINFO, "Added %s file to pool.\n", type);
329     }
330     return (err);
331    
332     }
333    
334     FILE *pool_new(char *type, char *tmpname, char *path)
335     {
336     FILE *f;
337 weaselp 387 struct stat buf;
338     int err;
339 rabbi 1
340     assert(strlen(type) == 3);
341     #ifdef SHORTNAMES
342 rabbi 11 sprintf(tmpname, "%s%c%02x%02x%02x%02x.tmp", POOLDIR, DIRSEP, rnd_byte(), rnd_byte(),
343 rabbi 1 rnd_byte(), rnd_byte());
344     strcpy(path, tmpname);
345     memcpy(path + strlen(path) - 3, type, 3);
346 rabbi 262 #else /* end of SHORTNAMES */
347 rabbi 11 sprintf(tmpname, "%s%ct%02x%02x%02x%02x%02x%02x%01x", POOLDIR, DIRSEP, rnd_byte(),
348 rabbi 1 rnd_byte(), rnd_byte(), rnd_byte(), rnd_byte(),
349     rnd_byte(), rnd_byte() & 15);
350     strcpy(path, tmpname);
351 rabbi 11 strrchr(path, DIRSEP)[1] = type[0];
352 rabbi 262 #endif /* else if not SHORTNAMES */
353 weaselp 387 err = stat(tmpname, &buf);
354     if (err == 0)
355     errlog(WARNING, "Overwriting file %s\n", tmpname);
356 rabbi 1 f = fopen(tmpname, "wb");
357     if (f == NULL)
358     errlog(ERRORMSG, "Error creating temporary file %s\n", tmpname);
359     return (f);
360     }
361    
362     int pool_read(BUFFER *pool)
363     {
364     DIR *d;
365     struct dirent *e;
366     int size = 0;
367    
368     d = opendir(POOLDIR);
369 weaselp 449 if (d != NULL) {
370 rabbi 1 for (;;) {
371     e = readdir(d);
372     if (e == NULL)
373     break;
374     if (is(e->d_name, "msg")) {
375     if (pool != NULL) {
376     buf_appends(pool, e->d_name);
377     buf_appendc(pool, 0);
378     }
379     size++;
380     }
381     }
382 weaselp 449 closedir(d);
383     } else
384     errlog(WARNING, "Error reading pool dir %s\n", POOLDIR);
385 rabbi 1 return (size);
386     }
387    
388     void pool_dosend(void)
389     {
390     DIR *d;
391     struct dirent *e;
392     char path[PATHMAX];
393    
394     d = opendir(POOLDIR);
395     if (d != NULL) {
396     for (;;) {
397     e = readdir(d);
398     if (e == NULL)
399     break;
400     if (is(e->d_name, "snd")) {
401     sendmail_begin();
402     mv(e->d_name, "tmp");
403 rabbi 11 sprintf(path, "%s%c%s", POOLDIR, DIRSEP, e->d_name);
404 rabbi 1 if (msg_send(path) == 1)
405     mv(e->d_name, "err");
406     }
407     }
408     closedir(d);
409 weaselp 449 } else
410     errlog(WARNING, "Error reading pool dir %s\n", POOLDIR);
411 rabbi 1 sendmail_end();
412     }
413    
414 weaselp 183 int process_mailin()
415     {
416     mailin(MAILIN);
417     infile_read();
418     return(0);
419     }
420    
421 rabbi 218 int create_dummy_mailout()
422     {
423 rabbi 220 while (rnd_number(100) < OUTDUMMYP) {
424 rabbi 218 errlog(DEBUGINFO, "Generating dummy message with outgoing mail.\n");
425     if (mix_encrypt(MSG_NULL, NULL, NULL, 1, NULL) == -1)
426     return -1;
427     }
428     return 0;
429     }
430    
431 rabbi 1 int pool_send(void)
432     {
433     int size, max, i, r;
434     BUFFER *pool;
435 weaselp 120 long int *ptr;
436 rabbi 1
437 rabbi 218 create_dummy_mailout();
438    
439 rabbi 1 latent_read();
440     pool = buf_new();
441     size = pool_read(pool);
442     if (size <= POOLSIZE)
443     goto end;
444    
445 weaselp 120 ptr = malloc(size * sizeof(long int));
446 rabbi 1
447     if (ptr == NULL)
448     goto end;
449     for (i = 0; i < size; i++) {
450     ptr[i] = pool->ptr;
451     buf_getline(pool, NULL);
452     }
453    
454     max = size * RATE / 100; /* send no more than RATE % of the messages */
455     if (max < 0)
456     max = 1;
457    
458     for (i = 0; i < size - POOLSIZE && i < max; i++) {
459     do
460     r = rnd_number(size); /* chose a new random message */
461     while (is(pool->data + ptr[r], "snd"));
462     mv(pool->data + ptr[r], "snd");
463     }
464     stats_out(size - --i);
465     pool_dosend();
466     free(ptr);
467    
468     end:
469     buf_free(pool);
470     return (size);
471     }
472    
473     int msg_send(char *name)
474     {
475     FILE *f;
476     int type = -1;
477     BUFFER *m, *addr;
478     int err = 0;
479     char line[LINELEN];
480     int userfrom = 0;
481    
482     m = buf_new();
483     addr = buf_new();
484     if ((f = fopen(name, "rb")) == NULL) {
485     err = -1;
486     goto end;
487     }
488     fscanf(f, "%d %*d\n", &type);
489     if (type == INTERMEDIATE) {
490     fgets(line, sizeof(line), f);
491     buf_sets(addr, line);
492     buf_chop(addr);
493     err = buf_read(m, f);
494     if (err == -1)
495     goto end;
496     err = mix_armor(m);
497     if (err == -1)
498     goto end;
499     err = sendmail(m, REMAILERADDR, addr);
500 weaselp 392 stats_log(3);
501 rabbi 1 } else if (type == MSG_MAIL || type == MSG_POST) {
502     err = buf_read(m, f);
503     if (err == -1)
504     goto end;
505 weaselp 392 if (MIDDLEMAN && ! allowmessage(m)) {
506 weaselp 592 mix2_encrypt(type, m, FORWARDTO, 1, 1, NULL);
507 weaselp 392 stats_log(6);
508     } else {
509 rabbi 1 err = filtermsg(m);
510     if (err == 1)
511     userfrom = 1, err = 0;
512     if (err != -1) {
513     /* message has recipients */
514     errlog(DEBUGINFO, "Sending message (%ld bytes)\n", m->length);
515    
516 weaselp 392 if (type == MSG_MAIL) {
517 rabbi 1 err = sendmail(m, userfrom ? NULL : ANONNAME, NULL);
518 weaselp 392 stats_log(4);
519     } else if (type == MSG_POST) {
520 rabbi 1 if (strchr(NEWS, '@') && !strchr(NEWS, ' ')) {
521     errlog(LOG, "Mailing article to %s.\n", NEWS);
522     buf_sets(addr, NEWS);
523     err = sendmail(m, userfrom ? NULL : ANONNAME, addr);
524     } else if (NEWS[0] != '\0') {
525     FILE *f;
526    
527     f = openpipe(NEWS);
528     if (f == NULL)
529     goto end;
530     errlog(LOG, "Posting article.\n");
531     if (!userfrom)
532     fprintf(f, "From: %s\n", ANONNAME);
533     if (ORGANIZATION[0] != '\0')
534     fprintf(f, "Organization: %s\n", ORGANIZATION);
535     buf_write(m, f);
536     closepipe(f);
537     } else
538     errlog(NOTICE, "Rejecting news article.\n");
539 weaselp 392 stats_log(5);
540 rabbi 1 }
541     } else
542     errlog(ERRORMSG, "Bad message file.\n");
543     }
544     }
545 rabbi 61 end:
546 rabbi 47 if (f != NULL)
547     fclose(f);
548 rabbi 1 if (err != 1) /* problem sending mail */
549     unlink(name);
550     buf_free(m);
551     buf_free(addr);
552     return (err);
553     }
554    
555     int allowmessage(BUFFER *in)
556     /* Only called if remailer is middleman. Checks whether all Recipient
557     * addresses are in dest.allow. If yes return 1; 0 otherwhise
558     */
559     {
560     BUFFER *out, *allow, *line, *line2;
561     int err=1;
562     FILE *f;
563    
564     allow = buf_new();
565     out = buf_new();
566     line = buf_new();
567     line2 = buf_new();
568    
569     f = mix_openfile(DESTALLOW, "r");
570     if (f != NULL) {
571     buf_read(allow, f);
572     fclose(f);
573     }
574    
575     /* Do header lines */
576     while (buf_getline(in, line) == 0) {
577     for (;;) {
578     buf_lookahead(in, line2);
579     if (!bufleft(line2, " ") && !bufleft(line2, "\t"))
580     break;
581     buf_getline(in, line2);
582     buf_cat(line, line2);
583     }
584    
585     if (bufileft(line, "to:") || bufileft(line, "cc:") ||
586     bufileft(line, "bcc:") || bufileft(line, "newsgroups:"))
587     if (! doallow(line, allow))
588     err = 0;
589    
590     if (line->length > 0) {
591     if (!buffind(line, ":"))
592 weaselp 332 buf_appends(out, "X-Invalid: ");
593 rabbi 1 buf_cat(out, line);
594     buf_nl(out);
595     }
596     }
597     buf_nl(out);
598    
599     /* Rest of the message */
600     buf_append(out, in->data + in->ptr, in->length - in->ptr);
601    
602     buf_move(in, out);
603     buf_free(out);
604     buf_free(allow);
605     buf_free(line);
606     buf_free(line2);
607     return (err);
608 weaselp 121 }
609 rabbi 1
610     int doallow(BUFFER *line, BUFFER *filter)
611     /* line is a To, CC or BCC line.
612     * problem is: there may be multiple addresses in one header
613     * line but we only want to allow if _all_ are allowed
614     *
615     * So to not send direct if we do not want, we _never_ send
616     * direct if there is more than one address: This is
617 weaselp 332 * assumed to be the case when there is a
618 rabbi 1 * comma in the header line.
619     *
620     * this should probably be rewritten somehwhen. therefore: FIXME
621     *
622     * returns: 1 if allowed
623     * 0 if message should be send indirectly
624     */
625     {
626     if (strchr( line->data, ',')) return 0;
627     return doblock(line, filter, 0);
628     }
629    
630     int filtermsg(BUFFER *in)
631     {
632     BUFFER *out, *line, *line2, *mboundary, *block, *filter, *mid;
633     FILE *f;
634     int from = 0, dest = 0;
635     int inbinary = 0, inpgp = 0, l = 80;
636     int err = -1;
637    
638     line = buf_new();
639     line2 = buf_new();
640     filter = buf_new();
641     mid = buf_new();
642     mboundary = buf_new();
643     out = buf_new();
644 rabbi 5 block = NULL;
645 rabbi 1
646     if (SIZELIMIT > 0 && in->length > SIZELIMIT * 1024) {
647     errlog(NOTICE, "Message rejected: %ld bytes\n", in->length);
648     goto end;
649     }
650    
651     block = readdestblk( );
652     if ( !block ) block = buf_new( );
653    
654     f = mix_openfile(HDRFILTER, "r");
655     if (f != NULL) {
656     buf_read(filter, f);
657     fclose(f);
658     }
659    
660     f = mix_openfile(DISCLAIMFILE, "r");
661     if (f != NULL) {
662     buf_read(out, f);
663     fclose(f);
664     } else {
665     if (strfind(DISCLAIMER, "%s"))
666     buf_appendf(out, DISCLAIMER, COMPLAINTS);
667     else
668     buf_appends(out, DISCLAIMER);
669     }
670    
671     while (buf_getline(in, line) == 0) {
672     for (;;) {
673     buf_lookahead(in, line2);
674     if (!bufleft(line2, " ") && !bufleft(line2, "\t"))
675     break;
676     buf_getline(in, line2);
677     buf_cat(line, line2);
678     }
679    
680     if (bufileft(line, "to:") || bufileft(line, "cc:") ||
681     bufileft(line, "bcc:") || bufileft(line, "newsgroups:"))
682     if (doblock(line, block, 1) == 0)
683     dest++;
684     if (doblock(line, filter, 1) == -1)
685     goto end;
686     if (bufileft(line, "from:"))
687     from = 1;
688    
689     if (bufileft(line, "content-type:") && bufileft(line, "multipart"))
690     get_parameter(line, "boundary", mboundary);
691    
692     if (line->length > 0) {
693     if (!buffind(line, ":"))
694 weaselp 332 buf_appends(out, "X-Invalid: ");
695 rabbi 1 buf_cat(out, line);
696     buf_nl(out);
697     }
698     }
699    
700     if (MID[0] != '\0' && tolower(MID[0]) != 'n') {
701     char txt[LINELEN];
702    
703     digestmem_md5(in->data + in->ptr, in->length - in->ptr, mid);
704     id_encode(mid->data, txt);
705    
706     if (MID[0] == '@')
707     strcatn(txt, MID, sizeof(txt));
708     else {
709     if (strchr(REMAILERADDR, '@'))
710     strcatn(txt, strchr(REMAILERADDR, '@'), sizeof(txt));
711     else if (strchr(COMPLAINTS, '@'))
712     strcatn(txt, strchr(COMPLAINTS, '@'), sizeof(txt));
713     }
714     buf_appendf(out, "Message-ID: <%s>\n", txt);
715     }
716     buf_nl(out);
717    
718     if (from) {
719     /* prepend Sender line to message header */
720     buf_setf(line, "Sender: %s\n", ANONNAME);
721     buf_cat(line, out);
722     buf_move(out, line);
723    
724     f = mix_openfile(FROMDSCLFILE, "r");
725     if (f != NULL) {
726     buf_read(out, f);
727     fclose(f);
728     } else
729     buf_appends(out, FROMDISCLAIMER);
730     }
731    
732     #if 0
733     buf_append(out, in->data + in->ptr, in->length - in->ptr);
734 rabbi 262 #endif /* 0 */
735 rabbi 1 while (buf_getline(in, line) != -1) {
736     if (boundary(line, mboundary)) {
737     buf_cat(out, line);
738     buf_nl(out);
739     while (buf_getline(in, line) == 0) { /* MIME body part header */
740     err = doblock(line, filter, 1);
741     if (err == -1)
742     goto end;
743     buf_cat(out, line);
744     buf_nl(out);
745     }
746     }
747     if (BINFILTER && l > 20 && line->length == l &&
748     (bufleft(line, "M") || !buffind(line, " ")))
749     inbinary++;
750     else
751     inbinary = 0, l = line->length;
752 rabbi 50 if (bufileft(line, begin_pgp) || bufileft(line, begin_key))
753 rabbi 1 inpgp = 1;
754 rabbi 50 if (bufileft(line, end_pgp) || bufileft(line, end_key))
755 rabbi 1 inpgp = 0;
756     if (inbinary < 10 || inpgp) {
757     buf_cat(out, line);
758     buf_nl(out);
759     } else if (inbinary == 10) {
760     errlog(NOTICE, "Binary message detected.\n");
761     if (BINFILTER > 1) {
762     err = -1;
763     goto end;
764     }
765     buf_appends(out, BINDISCLAIMER);
766     buf_nl(out);
767     }
768     }
769    
770 weaselp 166 f = mix_openfile(MSGFOOTERFILE, "r");
771     if (f != NULL) {
772     buf_read(out, f);
773     fclose(f);
774     } else
775     buf_appends(out, MSGFOOTER);
776    
777 rabbi 1 /* return 1 for user supplied From line */
778     err = from;
779     if (dest == 0)
780     err = -1;
781    
782     end:
783     buf_move(in, out);
784     buf_free(out);
785     buf_free(line);
786     buf_free(line2);
787 rabbi 5 if (block) buf_free(block);
788 rabbi 1 buf_free(filter);
789     buf_free(mid);
790     buf_free(mboundary);
791     return (err);
792     }
793    
794     BUFFER *readdestblk( )
795     {
796     char *destblklst = (char *)malloc( strlen( DESTBLOCK )+1 );
797     char *destblk = NULL;
798     FILE *f;
799     BUFFER *addresses;
800     BUFFER *temp;
801     int err = 1;
802    
803     addresses = buf_new( );
804     temp = buf_new( );
805    
806     strcpy( destblklst, DESTBLOCK );
807    
808     while ( (destblk = strtok( destblk ? NULL : destblklst, " " )) )
809     {
810 weaselp 332 if ( (f = mix_openfile( destblk, "r" )) )
811     {
812     if ( !buf_read( temp, f ) )
813     {
814     buf_cat( addresses, temp );
815     err = 0;
816     }
817     fclose( f );
818     }
819 rabbi 1 }
820    
821     free( destblklst );
822     buf_free( temp );
823    
824     if ( err ) { buf_free( addresses ); return NULL; }
825     else return addresses;
826     }
827    
828     int doblock(BUFFER *line, BUFFER *filter, int logandreset)
829     /* logandreset is usually 0
830     * it is only set to 1 when called from doallow
831     * which only checks whether messages are allowed to
832     * be sent directly
833     */
834     {
835     int block = 0;
836     BUFFER *pattern, *result;
837     char *t;
838     #ifdef USE_PCRE
839     int errptr, match;
840     const char *error;
841     pcre *compiled;
842     int ovector[21];
843     char *newstr;
844 rabbi 262 #endif /* USE_PCRE */
845 rabbi 1
846     pattern = buf_new();
847     result = buf_new();
848     assert(filter != NULL);
849    
850     buf_rewind(filter);
851     while (buf_getline(filter, pattern) != -1)
852     if (pattern->length > 0 && !bufleft(pattern, "#")) {
853     if (bufleft(pattern, "/") && (t = strchr(pattern->data + 1, '/'))
854     != NULL) {
855     #ifdef USE_PCRE
856     *t = '\0';
857     compiled = pcre_compile(pattern->data + 1, PCRE_CASELESS,
858     &error, &errptr
859     #ifndef USE_PCRE_OLD
860     ,NULL
861 rabbi 262 #endif /* not USE_PCRE_OLD */
862 rabbi 1 );
863     if (compiled) {
864     match = pcre_exec(compiled, NULL, line->data,
865     line->length,
866     #if (PCRE_MAJOR == 2 && PCRE_MINOR >= 06)
867     0,
868 rabbi 262 #endif /* (PCRE_MAJOR == 2 && PCRE_MINOR >= 06) */
869 rabbi 1 #if (PCRE_MAJOR >= 3)
870     0,
871 rabbi 262 #endif /* (PCRE_MAJOR >= 3) */
872 rabbi 1 0, ovector, sizeof(ovector) / sizeof(int));
873     free(compiled);
874    
875     if (match < -1) {
876     *t = '/';
877     errlog(ERRORMSG, "Bad regexp %b\n", pattern);
878     }
879     else if (match >= 0) {
880     /* "/pattern/q" kills the entire message */
881     if (logandreset
882     && strlen(pattern->data + 1) + 1 < pattern->length
883     && pattern->data[pattern->length - 1] == 'q') {
884     *t = '/';
885     errlog(NOTICE,
886     "Message rejected: %b matches %b.\n", line, pattern);
887     block = -1;
888     break;
889     }
890     if (strlen(pattern->data + 1) + 1 < pattern->length
891     && pattern->data[pattern->length - 1] == '/') {
892     pattern->data[pattern->length - 1] = '\0';
893     newstr = pattern->data + strlen(pattern->data) + 1;
894     buf_reset(result);
895     buf_append(result, line->data, ovector[0]);
896     while (strchr(newstr, '$')) {
897     strchr(newstr, '$')[0] = '\0';
898     buf_appends(result, newstr);
899     newstr += strlen(newstr) + 1;
900     if (*newstr >= '1' && *newstr <= '9')
901     buf_append(result, line->data +
902     ovector[2 * (*newstr - '0')],
903     ovector[2 * (*newstr - '0') + 1] -
904     ovector[2 * (*newstr - '0')]);
905     newstr++;
906     }
907     buf_appends(result, newstr);
908     buf_appends(result, line->data + ovector[1]);
909     buf_clear(line);
910     buf_appends(line, result->data);
911     } else {
912     block = 1;
913     *t = '/';
914     if (logandreset)
915     errlog(NOTICE, "Blocked header line: %b matches %b.\n",
916     line, pattern);
917     }
918     }
919     } else {
920     *t = '/';
921     errlog(ERRORMSG, "Bad regexp %b\n", pattern);
922     }
923 rabbi 262 #else /* end of USE_PCRE */
924 rabbi 1 errlog(ERRORMSG, "No regexp support! Ignoring %b\n", pattern);
925 rabbi 262 #endif /* else if not USE_PCRE */
926 rabbi 1 } else if (bufifind(line, pattern->data)) {
927     if (logandreset )
928     errlog(NOTICE, "Blocked header line: %b matches %b.\n",
929     line, pattern);
930     block = 1;
931     }
932     }
933    
934     if (logandreset && (block == 1))
935     buf_reset(line);
936    
937     buf_free(pattern);
938     buf_free(result);
939     return (block);
940     }
941    
942     int mix_armor(BUFFER *in)
943     {
944     BUFFER *out, *md;
945    
946     md = buf_new();
947     out = buf_new();
948    
949     if (in->length != 20480)
950     return (-1);
951 weaselp 332
952 rabbi 1 buf_sets(out, "\n::\n");
953     buf_appends(out, remailer_type);
954     buf_appends(out, VERSION);
955     buf_nl(out);
956     buf_nl(out);
957     buf_appends(out, begin_remailer);
958     buf_nl(out);
959     buf_appends(out, "20480\n");
960     digest_md5(in, md);
961     encode(md, 0);
962     buf_cat(out, md);
963     buf_nl(out);
964     encode(in, 40);
965     buf_cat(out, in);
966     buf_appends(out, end_remailer);
967     buf_nl(out);
968    
969     buf_move(in, out);
970     buf_free(out);
971     buf_free(md);
972     return (0);
973     }

  ViewVC Help
Powered by ViewVC 1.1.5