/[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 262 - (show annotations) (download)
Wed Sep 18 23:26:17 2002 UTC (10 years, 8 months ago) by rabbi
File MIME type: text/plain
File size: 21837 byte(s)
Added closing comments for all #ifdef statements. All #endif's, as well as
nested braces, should be commented to reference their start.

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

  ViewVC Help
Powered by ViewVC 1.1.5