/[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 449 - (show annotations) (download)
Sat Dec 28 02:05:32 2002 UTC (10 years, 4 months ago) by weaselp
File MIME type: text/plain
File size: 22143 byte(s)
Handle a pool we cannot read correctly
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.22 2002/12/28 02:05:32 weaselp 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 #include <sys/stat.h>
27 #include <sys/types.h>
28
29 #ifdef USE_PCRE
30 #include "pcre.h"
31 #endif /* USE_PCRE */
32
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 * error messages: e* *.err
49 * outgoing messages: out *.txt (to be used by external program)
50 */
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 #else /* end of SHORTNAMES */
62 return (path[0] == type[0]);
63 #endif /* else if not SHORTNAMES */
64 }
65
66 static void mv(char *name, char *newtype)
67 {
68 char old[PATHMAX], new[PATHMAX];
69
70 sprintf(old, "%s%c%s", POOLDIR, DIRSEP, name);
71 #ifdef SHORTNAMES
72 assert(strlen(name) > 4);
73 strcpy(name + strlen(name) - 3, newtype);
74 #else /* end of SHORTNAMES */
75 name[0] = newtype[0];
76 #endif /* else if not SHORTNAMES */
77 sprintf(new, "%s%c%s", POOLDIR, DIRSEP, name);
78 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 sprintf(path, "%s%c%s", POOLDIR, DIRSEP, e->d_name);
99 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 sprintf(path, "%s%c%s", POOLDIR, DIRSEP, e->d_name);
131 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 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 path[PATHMAX-1]='\0';
174 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
231 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 #if 0
257 buf_appends(msg, line);
258 #endif /* 0 */
259 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 #else /* end of not WIN32 */
285 chsize(fileno(f), 0);
286 #endif /* else if WIN32 */
287 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 if (mailbox != NULL && (strcmp(mailbox, "") != 0))
307 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 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 struct stat buf;
338 int err;
339
340 assert(strlen(type) == 3);
341 #ifdef SHORTNAMES
342 sprintf(tmpname, "%s%c%02x%02x%02x%02x.tmp", POOLDIR, DIRSEP, rnd_byte(), rnd_byte(),
343 rnd_byte(), rnd_byte());
344 strcpy(path, tmpname);
345 memcpy(path + strlen(path) - 3, type, 3);
346 #else /* end of SHORTNAMES */
347 sprintf(tmpname, "%s%ct%02x%02x%02x%02x%02x%02x%01x", POOLDIR, DIRSEP, rnd_byte(),
348 rnd_byte(), rnd_byte(), rnd_byte(), rnd_byte(),
349 rnd_byte(), rnd_byte() & 15);
350 strcpy(path, tmpname);
351 strrchr(path, DIRSEP)[1] = type[0];
352 #endif /* else if not SHORTNAMES */
353 err = stat(tmpname, &buf);
354 if (err == 0)
355 errlog(WARNING, "Overwriting file %s\n", tmpname);
356 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 if (d != NULL) {
370 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 closedir(d);
383 } else
384 errlog(WARNING, "Error reading pool dir %s\n", POOLDIR);
385 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 sprintf(path, "%s%c%s", POOLDIR, DIRSEP, e->d_name);
404 if (msg_send(path) == 1)
405 mv(e->d_name, "err");
406 }
407 }
408 closedir(d);
409 } else
410 errlog(WARNING, "Error reading pool dir %s\n", POOLDIR);
411 sendmail_end();
412 }
413
414 int process_mailin()
415 {
416 mailin(MAILIN);
417 infile_read();
418 return(0);
419 }
420
421 int create_dummy_mailout()
422 {
423 while (rnd_number(100) < OUTDUMMYP) {
424 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 int pool_send(void)
432 {
433 int size, max, i, r;
434 BUFFER *pool;
435 long int *ptr;
436
437 create_dummy_mailout();
438
439 latent_read();
440 pool = buf_new();
441 size = pool_read(pool);
442 if (size <= POOLSIZE)
443 goto end;
444
445 ptr = malloc(size * sizeof(long int));
446
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 stats_log(3);
501 } else if (type == MSG_MAIL || type == MSG_POST) {
502 err = buf_read(m, f);
503 if (err == -1)
504 goto end;
505 if (MIDDLEMAN && ! allowmessage(m)) {
506 mix2_encrypt(type, m, FORWARDTO, 1, NULL);
507 stats_log(6);
508 } else {
509 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 if (type == MSG_MAIL) {
517 err = sendmail(m, userfrom ? NULL : ANONNAME, NULL);
518 stats_log(4);
519 } else if (type == MSG_POST) {
520 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 stats_log(5);
540 }
541 } else
542 errlog(ERRORMSG, "Bad message file.\n");
543 }
544 }
545 end:
546 if (f != NULL)
547 fclose(f);
548 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 buf_appends(out, "X-Invalid: ");
593 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 }
609
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 * assumed to be the case when there is a
618 * 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 block = NULL;
645
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 buf_appends(out, "X-Invalid: ");
695 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 #endif /* 0 */
735 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 if (bufileft(line, begin_pgp) || bufileft(line, begin_key))
753 inpgp = 1;
754 if (bufileft(line, end_pgp) || bufileft(line, end_key))
755 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 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 /* 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 if (block) buf_free(block);
788 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 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 }
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 #endif /* USE_PCRE */
845
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 #endif /* not USE_PCRE_OLD */
862 );
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 #endif /* (PCRE_MAJOR == 2 && PCRE_MINOR >= 06) */
869 #if (PCRE_MAJOR >= 3)
870 0,
871 #endif /* (PCRE_MAJOR >= 3) */
872 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 #else /* end of USE_PCRE */
924 errlog(ERRORMSG, "No regexp support! Ignoring %b\n", pattern);
925 #endif /* else if not USE_PCRE */
926 } 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
952 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