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

Contents of /branches/mixmaster_2_9_STABLE/Mix/Src/pool.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 327 - (show annotations) (download)
Wed Oct 9 20:29:44 2002 UTC (10 years, 7 months ago) by weaselp
File MIME type: text/plain
File size: 17636 byte(s)
Added closing comments for all #ifdef statements.
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.10.2.2 2002/10/09 20:29:44 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
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 pool_add(BUFFER *msg, char *type)
145 {
146 char path[PATHMAX], pathtmp[PATHMAX];
147 FILE *f;
148 int err = -1;
149
150 f = pool_new(type, pathtmp, path);
151 if (f != NULL) {
152 err = buf_write(msg, f);
153 fclose(f);
154 }
155 if (err == 0) {
156 rename(pathtmp, path);
157 errlog(DEBUGINFO, "Added %s file to pool.\n", type);
158 }
159 return (err);
160
161 }
162
163 FILE *pool_new(char *type, char *tmpname, char *path)
164 {
165 FILE *f;
166
167 assert(strlen(type) == 3);
168 #ifdef SHORTNAMES
169 sprintf(tmpname, "%s%c%02x%02x%02x%02x.tmp", POOLDIR, DIRSEP, rnd_byte(), rnd_byte(),
170 rnd_byte(), rnd_byte());
171 strcpy(path, tmpname);
172 memcpy(path + strlen(path) - 3, type, 3);
173 #else /* end of SHORTNAMES */
174 sprintf(tmpname, "%s%ct%02x%02x%02x%02x%02x%02x%01x", POOLDIR, DIRSEP, rnd_byte(),
175 rnd_byte(), rnd_byte(), rnd_byte(), rnd_byte(),
176 rnd_byte(), rnd_byte() & 15);
177 strcpy(path, tmpname);
178 strrchr(path, DIRSEP)[1] = type[0];
179 #endif /* else if not SHORTNAMES */
180 f = fopen(tmpname, "wb");
181 if (f == NULL)
182 errlog(ERRORMSG, "Error creating temporary file %s\n", tmpname);
183 return (f);
184 }
185
186 int pool_read(BUFFER *pool)
187 {
188 DIR *d;
189 struct dirent *e;
190 int size = 0;
191
192 d = opendir(POOLDIR);
193 if (d != NULL)
194 for (;;) {
195 e = readdir(d);
196 if (e == NULL)
197 break;
198 if (is(e->d_name, "msg")) {
199 if (pool != NULL) {
200 buf_appends(pool, e->d_name);
201 buf_appendc(pool, 0);
202 }
203 size++;
204 }
205 }
206 closedir(d);
207 return (size);
208 }
209
210 void pool_dosend(void)
211 {
212 DIR *d;
213 struct dirent *e;
214 char path[PATHMAX];
215
216 d = opendir(POOLDIR);
217 if (d != NULL) {
218 for (;;) {
219 e = readdir(d);
220 if (e == NULL)
221 break;
222 if (is(e->d_name, "snd")) {
223 sendmail_begin();
224 mv(e->d_name, "tmp");
225 sprintf(path, "%s%c%s", POOLDIR, DIRSEP, e->d_name);
226 if (msg_send(path) == 1)
227 mv(e->d_name, "err");
228 }
229 }
230 closedir(d);
231 }
232 sendmail_end();
233 }
234
235 int pool_send(void)
236 {
237 int size, max, i, r;
238 BUFFER *pool;
239 long int *ptr;
240
241 infile_read();
242 latent_read();
243 pool = buf_new();
244 size = pool_read(pool);
245 if (size <= POOLSIZE)
246 goto end;
247
248 ptr = malloc(size * sizeof(long int));
249
250 if (ptr == NULL)
251 goto end;
252 for (i = 0; i < size; i++) {
253 ptr[i] = pool->ptr;
254 buf_getline(pool, NULL);
255 }
256
257 max = size * RATE / 100; /* send no more than RATE % of the messages */
258 if (max < 0)
259 max = 1;
260
261 for (i = 0; i < size - POOLSIZE && i < max; i++) {
262 do
263 r = rnd_number(size); /* chose a new random message */
264 while (is(pool->data + ptr[r], "snd"));
265 mv(pool->data + ptr[r], "snd");
266 }
267 stats_out(size - --i);
268 pool_dosend();
269 free(ptr);
270
271 end:
272 buf_free(pool);
273 return (size);
274 }
275
276 int msg_send(char *name)
277 {
278 FILE *f;
279 int type = -1;
280 BUFFER *m, *addr;
281 int err = 0;
282 char line[LINELEN];
283 int userfrom = 0;
284
285 m = buf_new();
286 addr = buf_new();
287 if ((f = fopen(name, "rb")) == NULL) {
288 err = -1;
289 goto end;
290 }
291 fscanf(f, "%d %*d\n", &type);
292 if (type == INTERMEDIATE) {
293 fgets(line, sizeof(line), f);
294 buf_sets(addr, line);
295 buf_chop(addr);
296 err = buf_read(m, f);
297 if (err == -1)
298 goto end;
299 err = mix_armor(m);
300 if (err == -1)
301 goto end;
302 err = sendmail(m, REMAILERADDR, addr);
303 } else if (type == MSG_MAIL || type == MSG_POST) {
304 err = buf_read(m, f);
305 if (err == -1)
306 goto end;
307 if (MIDDLEMAN && ! allowmessage(m))
308 mix2_encrypt(type, m, FORWARDTO, 1, NULL);
309 else {
310 err = filtermsg(m);
311 if (err == 1)
312 userfrom = 1, err = 0;
313 if (err != -1) {
314 /* message has recipients */
315 errlog(DEBUGINFO, "Sending message (%ld bytes)\n", m->length);
316
317 if (type == MSG_MAIL)
318 err = sendmail(m, userfrom ? NULL : ANONNAME, NULL);
319 else if (type == MSG_POST) {
320 if (strchr(NEWS, '@') && !strchr(NEWS, ' ')) {
321 errlog(LOG, "Mailing article to %s.\n", NEWS);
322 buf_sets(addr, NEWS);
323 err = sendmail(m, userfrom ? NULL : ANONNAME, addr);
324 } else if (NEWS[0] != '\0') {
325 FILE *f;
326
327 f = openpipe(NEWS);
328 if (f == NULL)
329 goto end;
330 errlog(LOG, "Posting article.\n");
331 if (!userfrom)
332 fprintf(f, "From: %s\n", ANONNAME);
333 if (ORGANIZATION[0] != '\0')
334 fprintf(f, "Organization: %s\n", ORGANIZATION);
335 buf_write(m, f);
336 closepipe(f);
337 } else
338 errlog(NOTICE, "Rejecting news article.\n");
339 }
340 } else
341 errlog(ERRORMSG, "Bad message file.\n");
342 }
343 }
344 end:
345 if (f != NULL)
346 fclose(f);
347 if (err != 1) /* problem sending mail */
348 unlink(name);
349 buf_free(m);
350 buf_free(addr);
351 return (err);
352 }
353
354 int allowmessage(BUFFER *in)
355 /* Only called if remailer is middleman. Checks whether all Recipient
356 * addresses are in dest.allow. If yes return 1; 0 otherwhise
357 */
358 {
359 BUFFER *out, *allow, *line, *line2;
360 int err=1;
361 FILE *f;
362
363 allow = buf_new();
364 out = buf_new();
365 line = buf_new();
366 line2 = buf_new();
367
368 f = mix_openfile(DESTALLOW, "r");
369 if (f != NULL) {
370 buf_read(allow, f);
371 fclose(f);
372 }
373
374 /* Do header lines */
375 while (buf_getline(in, line) == 0) {
376 for (;;) {
377 buf_lookahead(in, line2);
378 if (!bufleft(line2, " ") && !bufleft(line2, "\t"))
379 break;
380 buf_getline(in, line2);
381 buf_cat(line, line2);
382 }
383
384 if (bufileft(line, "to:") || bufileft(line, "cc:") ||
385 bufileft(line, "bcc:") || bufileft(line, "newsgroups:"))
386 if (! doallow(line, allow))
387 err = 0;
388
389 if (line->length > 0) {
390 if (!buffind(line, ":"))
391 buf_appends(out, "X-Invalid: ");
392 buf_cat(out, line);
393 buf_nl(out);
394 }
395 }
396 buf_nl(out);
397
398 /* Rest of the message */
399 buf_append(out, in->data + in->ptr, in->length - in->ptr);
400
401 buf_move(in, out);
402 buf_free(out);
403 buf_free(allow);
404 buf_free(line);
405 buf_free(line2);
406 return (err);
407 }
408
409 int doallow(BUFFER *line, BUFFER *filter)
410 /* line is a To, CC or BCC line.
411 * problem is: there may be multiple addresses in one header
412 * line but we only want to allow if _all_ are allowed
413 *
414 * So to not send direct if we do not want, we _never_ send
415 * direct if there is more than one address: This is
416 * assumed to be the case when there is a
417 * comma in the header line.
418 *
419 * this should probably be rewritten somehwhen. therefore: FIXME
420 *
421 * returns: 1 if allowed
422 * 0 if message should be send indirectly
423 */
424 {
425 if (strchr( line->data, ',')) return 0;
426 return doblock(line, filter, 0);
427 }
428
429 int filtermsg(BUFFER *in)
430 {
431 BUFFER *out, *line, *line2, *mboundary, *block, *filter, *mid;
432 FILE *f;
433 int from = 0, dest = 0;
434 int inbinary = 0, inpgp = 0, l = 80;
435 int err = -1;
436
437 line = buf_new();
438 line2 = buf_new();
439 filter = buf_new();
440 mid = buf_new();
441 mboundary = buf_new();
442 out = buf_new();
443 block = NULL;
444
445 if (SIZELIMIT > 0 && in->length > SIZELIMIT * 1024) {
446 errlog(NOTICE, "Message rejected: %ld bytes\n", in->length);
447 goto end;
448 }
449
450 block = readdestblk( );
451 if ( !block ) block = buf_new( );
452
453 f = mix_openfile(HDRFILTER, "r");
454 if (f != NULL) {
455 buf_read(filter, f);
456 fclose(f);
457 }
458
459 f = mix_openfile(DISCLAIMFILE, "r");
460 if (f != NULL) {
461 buf_read(out, f);
462 fclose(f);
463 } else {
464 if (strfind(DISCLAIMER, "%s"))
465 buf_appendf(out, DISCLAIMER, COMPLAINTS);
466 else
467 buf_appends(out, DISCLAIMER);
468 }
469
470 while (buf_getline(in, line) == 0) {
471 for (;;) {
472 buf_lookahead(in, line2);
473 if (!bufleft(line2, " ") && !bufleft(line2, "\t"))
474 break;
475 buf_getline(in, line2);
476 buf_cat(line, line2);
477 }
478
479 if (bufileft(line, "to:") || bufileft(line, "cc:") ||
480 bufileft(line, "bcc:") || bufileft(line, "newsgroups:"))
481 if (doblock(line, block, 1) == 0)
482 dest++;
483 if (doblock(line, filter, 1) == -1)
484 goto end;
485 if (bufileft(line, "from:"))
486 from = 1;
487
488 if (bufileft(line, "content-type:") && bufileft(line, "multipart"))
489 get_parameter(line, "boundary", mboundary);
490
491 if (line->length > 0) {
492 if (!buffind(line, ":"))
493 buf_appends(out, "X-Invalid: ");
494 buf_cat(out, line);
495 buf_nl(out);
496 }
497 }
498
499 if (MID[0] != '\0' && tolower(MID[0]) != 'n') {
500 char txt[LINELEN];
501
502 digestmem_md5(in->data + in->ptr, in->length - in->ptr, mid);
503 id_encode(mid->data, txt);
504
505 if (MID[0] == '@')
506 strcatn(txt, MID, sizeof(txt));
507 else {
508 if (strchr(REMAILERADDR, '@'))
509 strcatn(txt, strchr(REMAILERADDR, '@'), sizeof(txt));
510 else if (strchr(COMPLAINTS, '@'))
511 strcatn(txt, strchr(COMPLAINTS, '@'), sizeof(txt));
512 }
513 buf_appendf(out, "Message-ID: <%s>\n", txt);
514 }
515 buf_nl(out);
516
517 if (from) {
518 /* prepend Sender line to message header */
519 buf_setf(line, "Sender: %s\n", ANONNAME);
520 buf_cat(line, out);
521 buf_move(out, line);
522
523 f = mix_openfile(FROMDSCLFILE, "r");
524 if (f != NULL) {
525 buf_read(out, f);
526 fclose(f);
527 } else
528 buf_appends(out, FROMDISCLAIMER);
529 }
530
531 #if 0
532 buf_append(out, in->data + in->ptr, in->length - in->ptr);
533 #endif /* 0 */
534 while (buf_getline(in, line) != -1) {
535 if (boundary(line, mboundary)) {
536 buf_cat(out, line);
537 buf_nl(out);
538 while (buf_getline(in, line) == 0) { /* MIME body part header */
539 err = doblock(line, filter, 1);
540 if (err == -1)
541 goto end;
542 buf_cat(out, line);
543 buf_nl(out);
544 }
545 }
546 if (BINFILTER && l > 20 && line->length == l &&
547 (bufleft(line, "M") || !buffind(line, " ")))
548 inbinary++;
549 else
550 inbinary = 0, l = line->length;
551 if (bufileft(line, begin_pgp) || bufileft(line, begin_key))
552 inpgp = 1;
553 if (bufileft(line, end_pgp) || bufileft(line, end_key))
554 inpgp = 0;
555 if (inbinary < 10 || inpgp) {
556 buf_cat(out, line);
557 buf_nl(out);
558 } else if (inbinary == 10) {
559 errlog(NOTICE, "Binary message detected.\n");
560 if (BINFILTER > 1) {
561 err = -1;
562 goto end;
563 }
564 buf_appends(out, BINDISCLAIMER);
565 buf_nl(out);
566 }
567 }
568
569 f = mix_openfile(MSGFOOTERFILE, "r");
570 if (f != NULL) {
571 buf_read(out, f);
572 fclose(f);
573 } else
574 buf_appends(out, MSGFOOTER);
575
576 /* return 1 for user supplied From line */
577 err = from;
578 if (dest == 0)
579 err = -1;
580
581 end:
582 buf_move(in, out);
583 buf_free(out);
584 buf_free(line);
585 buf_free(line2);
586 if (block) buf_free(block);
587 buf_free(filter);
588 buf_free(mid);
589 buf_free(mboundary);
590 return (err);
591 }
592
593 BUFFER *readdestblk( )
594 {
595 char *destblklst = (char *)malloc( strlen( DESTBLOCK )+1 );
596 char *destblk = NULL;
597 FILE *f;
598 BUFFER *addresses;
599 BUFFER *temp;
600 int err = 1;
601
602 addresses = buf_new( );
603 temp = buf_new( );
604
605 strcpy( destblklst, DESTBLOCK );
606
607 while ( (destblk = strtok( destblk ? NULL : destblklst, " " )) )
608 {
609 if ( (f = mix_openfile( destblk, "r" )) )
610 {
611 if ( !buf_read( temp, f ) )
612 {
613 buf_cat( addresses, temp );
614 err = 0;
615 }
616 fclose( f );
617 }
618 }
619
620 free( destblklst );
621 buf_free( temp );
622
623 if ( err ) { buf_free( addresses ); return NULL; }
624 else return addresses;
625 }
626
627 int doblock(BUFFER *line, BUFFER *filter, int logandreset)
628 /* logandreset is usually 0
629 * it is only set to 1 when called from doallow
630 * which only checks whether messages are allowed to
631 * be sent directly
632 */
633 {
634 int block = 0;
635 BUFFER *pattern, *result;
636 char *t;
637 #ifdef USE_PCRE
638 int errptr, match;
639 const char *error;
640 pcre *compiled;
641 int ovector[21];
642 char *newstr;
643 #endif /* USE_PCRE */
644
645 pattern = buf_new();
646 result = buf_new();
647 assert(filter != NULL);
648
649 buf_rewind(filter);
650 while (buf_getline(filter, pattern) != -1)
651 if (pattern->length > 0 && !bufleft(pattern, "#")) {
652 if (bufleft(pattern, "/") && (t = strchr(pattern->data + 1, '/'))
653 != NULL) {
654 #ifdef USE_PCRE
655 *t = '\0';
656 compiled = pcre_compile(pattern->data + 1, PCRE_CASELESS,
657 &error, &errptr
658 #ifndef USE_PCRE_OLD
659 ,NULL
660 #endif /* not USE_PCRE_OLD */
661 );
662 if (compiled) {
663 match = pcre_exec(compiled, NULL, line->data,
664 line->length,
665 #if (PCRE_MAJOR == 2 && PCRE_MINOR >= 06)
666 0,
667 #endif /* (PCRE_MAJOR == 2 && PCRE_MINOR >= 06) */
668 #if (PCRE_MAJOR >= 3)
669 0,
670 #endif /* (PCRE_MAJOR >= 3) */
671 0, ovector, sizeof(ovector) / sizeof(int));
672 free(compiled);
673
674 if (match < -1) {
675 *t = '/';
676 errlog(ERRORMSG, "Bad regexp %b\n", pattern);
677 }
678 else if (match >= 0) {
679 /* "/pattern/q" kills the entire message */
680 if (logandreset
681 && strlen(pattern->data + 1) + 1 < pattern->length
682 && pattern->data[pattern->length - 1] == 'q') {
683 *t = '/';
684 errlog(NOTICE,
685 "Message rejected: %b matches %b.\n", line, pattern);
686 block = -1;
687 break;
688 }
689 if (strlen(pattern->data + 1) + 1 < pattern->length
690 && pattern->data[pattern->length - 1] == '/') {
691 pattern->data[pattern->length - 1] = '\0';
692 newstr = pattern->data + strlen(pattern->data) + 1;
693 buf_reset(result);
694 buf_append(result, line->data, ovector[0]);
695 while (strchr(newstr, '$')) {
696 strchr(newstr, '$')[0] = '\0';
697 buf_appends(result, newstr);
698 newstr += strlen(newstr) + 1;
699 if (*newstr >= '1' && *newstr <= '9')
700 buf_append(result, line->data +
701 ovector[2 * (*newstr - '0')],
702 ovector[2 * (*newstr - '0') + 1] -
703 ovector[2 * (*newstr - '0')]);
704 newstr++;
705 }
706 buf_appends(result, newstr);
707 buf_appends(result, line->data + ovector[1]);
708 buf_clear(line);
709 buf_appends(line, result->data);
710 } else {
711 block = 1;
712 *t = '/';
713 if (logandreset)
714 errlog(NOTICE, "Blocked header line: %b matches %b.\n",
715 line, pattern);
716 }
717 }
718 } else {
719 *t = '/';
720 errlog(ERRORMSG, "Bad regexp %b\n", pattern);
721 }
722 #else /* end of USE_PCRE */
723 errlog(ERRORMSG, "No regexp support! Ignoring %b\n", pattern);
724 #endif /* else if not USE_PCRE */
725 } else if (bufifind(line, pattern->data)) {
726 if (logandreset )
727 errlog(NOTICE, "Blocked header line: %b matches %b.\n",
728 line, pattern);
729 block = 1;
730 }
731 }
732
733 if (logandreset && (block == 1))
734 buf_reset(line);
735
736 buf_free(pattern);
737 buf_free(result);
738 return (block);
739 }
740
741 int mix_armor(BUFFER *in)
742 {
743 BUFFER *out, *md;
744
745 md = buf_new();
746 out = buf_new();
747
748 if (in->length != 20480)
749 return (-1);
750
751 buf_sets(out, "\n::\n");
752 buf_appends(out, remailer_type);
753 buf_appends(out, VERSION);
754 buf_nl(out);
755 buf_nl(out);
756 buf_appends(out, begin_remailer);
757 buf_nl(out);
758 buf_appends(out, "20480\n");
759 digest_md5(in, md);
760 encode(md, 0);
761 buf_cat(out, md);
762 buf_nl(out);
763 encode(in, 40);
764 buf_cat(out, in);
765 buf_appends(out, end_remailer);
766 buf_nl(out);
767
768 buf_move(in, out);
769 buf_free(out);
770 buf_free(md);
771 return (0);
772 }

  ViewVC Help
Powered by ViewVC 1.1.5