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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 183 - (show annotations) (download)
Mon Aug 26 18:08:05 2002 UTC (10 years, 9 months ago) by weaselp
File MIME type: text/plain
File size: 27119 byte(s)
Previosly when we ran Mixmaster in daemon mode and injected mail either
via pop3 or the MAILIN method (reading a Maildir or an mbox), Mixmaster
only processed remailer-xxx requests at SENDPOOLTIME intervalls.

It might be in the interest of an operator to have a high SENDPOOLTIME -
like say an hour or two - to provide better security to their user.

However it is also important to answer remailer-xxx requests in a timely
manner.

This conflict of interests can be solved by adding yet another config
option: MAILINTIME.

MAILINTIME specifies the amount of time between reading MAILIN and
processing those mails (as well as those injected via POP3). Processing
here means to answer -xxx requests and to add remailer mails to the
pool.

This is also done implicitly whenever Mixmaster is about to process its
pool or just fetched mail via pop3.
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 Mixmaster initialization, configuration
9 $Id: mix.c,v 1.17 2002/08/26 18:08:05 weaselp Exp $ */
10
11
12 #include "mix3.h"
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <stdarg.h>
17 #include <ctype.h>
18 #include <time.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #ifdef POSIX
22 #include <signal.h>
23 #include <unistd.h>
24 #include <pwd.h>
25 #include <sys/utsname.h>
26 #else
27 #include <io.h>
28 #include <direct.h>
29 #endif
30 #ifdef WIN32
31 #include <windows.h>
32 #endif
33 #include <assert.h>
34 #include "menu.h"
35
36 int buf_vappendf(BUFFER *b, char *fmt, va_list args);
37
38 /** filenames ************************************************************/
39 char MIXCONF[PATHMAX];
40 char DISCLAIMFILE[PATHMAX];
41 char FROMDSCLFILE[PATHMAX];
42 char MSGFOOTERFILE[PATHMAX];
43 char POP3CONF[PATHMAX];
44 char HELPFILE[PATHMAX];
45 char ABUSEFILE[PATHMAX];
46 char REPLYFILE[PATHMAX];
47 char USAGEFILE[PATHMAX];
48 char USAGELOG[PATHMAX];
49 char BLOCKFILE[PATHMAX];
50 char ADMKEYFILE[PATHMAX];
51 char KEYFILE[PATHMAX];
52 char PGPKEY[PATHMAX];
53 char DSAPARAMS[PATHMAX];
54 char DHPARAMS[PATHMAX];
55 char MIXRAND[PATHMAX];
56 char SECRING[PATHMAX];
57 char PUBRING[PATHMAX];
58 char IDLOG[PATHMAX];
59 char STATS[PATHMAX];
60 char DESTBLOCK[PATHMAX];
61 char DESTALLOW[PATHMAX];
62 char SOURCEBLOCK[PATHMAX];
63 char HDRFILTER[PATHMAX];
64 char REGULAR[PATHMAX];
65 char POOL[PATHMAX];
66 char TYPE1LIST[PATHMAX];
67 char TYPE2REL[PATHMAX];
68 char TYPE2LIST[PATHMAX];
69
70 char PGPREMPUBRING[PATHMAX];
71 char PGPREMPUBASC[PATHMAX];
72 char PGPREMSECRING[PATHMAX];
73 char NYMSECRING[PATHMAX];
74 char NYMDB[PATHMAX];
75
76
77 /** config ***************************************************************/
78
79 char MIXDIR[PATHMAX];
80 char POOLDIR[PATHMAX];
81
82 /* programs */
83 char SENDMAIL[LINELEN];
84 char SENDANONMAIL[LINELEN];
85 char NEWS[LINELEN];
86 char TYPE1[LINELEN];
87
88 /* addresses */
89 char MAILtoNEWS[LINELEN];
90 char REMAILERNAME[LINELEN];
91 char ANONNAME[LINELEN];
92 char REMAILERADDR[LINELEN];
93 char ANONADDR[LINELEN];
94 char COMPLAINTS[LINELEN];
95 int AUTOREPLY;
96 char SMTPRELAY[LINELEN];
97
98 #ifdef USE_SOCK
99 char HELONAME[LINELEN];
100 char ENVFROM[LINELEN];
101 int POP3DEL;
102 int POP3SIZELIMIT;
103 long POP3TIME;
104
105 #endif
106
107 char SHORTNAME[LINELEN];
108
109 /* remailer configuration */
110 int REMAIL;
111 int MIX;
112 int PGP;
113 int UNENCRYPTED;
114 int REMIX;
115 int REPGP;
116
117 int POOLSIZE;
118 int RATE;
119 int MIDDLEMAN;
120 int AUTOBLOCK;
121 char FORWARDTO[LINELEN];
122 int SIZELIMIT; /* maximal size of remailed messages */
123 int INFLATEMAX; /* maximal size of Inflate: padding */
124 int MAXRANDHOPS;
125 int BINFILTER; /* filter binary attachments? */
126 int LISTSUPPORTED; /* list supported remailers in remailer-conf reply? */
127 long PACKETEXP; /* Expiration time for old packets */
128 long IDEXP; /* 0 = no ID log !! */
129 long SENDPOOLTIME; /* frequency for sending pool messages */
130 long MAILINTIME; /* frequency for processing MAILIN mail */
131
132 char ERRLOG[LINELEN];
133 char ADDRESS[LINELEN];
134 char NAME[LINELEN];
135
136 char ORGANIZATION[LINELEN];
137 char MID[LINELEN];
138
139 /* client config */
140 int NUMCOPIES;
141 char CHAIN[LINELEN];
142 int VERBOSE;
143 int DISTANCE;
144 int MINREL;
145 int RELFINAL;
146 long MAXLAT;
147 char PGPPUBRING[PATHMAX];
148 char PGPSECRING[PATHMAX];
149 char PASSPHRASE[LINELEN];
150 char MAILIN[PATHMAX];
151 char MAILBOX[PATHMAX];
152 char MAILABUSE[PATHMAX];
153 char MAILBLOCK[PATHMAX];
154 char MAILUSAGE[PATHMAX];
155 char MAILANON[PATHMAX];
156 char MAILERROR[PATHMAX];
157 char MAILBOUNCE[PATHMAX];
158
159 static int rereadconfig = 0;
160 static int terminatedaemon = 0;
161
162 #if defined(S_IFDIR) && !defined(S_ISDIR)
163 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
164 #endif
165
166 static int mixdir(char *d, int create)
167 {
168 int err;
169 struct stat buf;
170
171 if (d != MIXDIR)
172 strncpy(MIXDIR, d, PATHMAX);
173 if (MIXDIR[strlen(MIXDIR) - 1] == DIRSEP)
174 MIXDIR[strlen(MIXDIR) - 1] = '\0';
175 err = stat(MIXDIR, &buf);
176 if (err == -1) {
177 if (create) {
178 #ifndef POSIX
179 err = mkdir(MIXDIR);
180 #else
181 err = mkdir(MIXDIR, S_IRWXU);
182 #endif
183 if (err == 0)
184 errlog(NOTICE, "Creating directory %s.\n", MIXDIR);
185 } else
186 err = 1;
187 } else if (!S_ISDIR(buf.st_mode))
188 err = -1;
189 if (err == 0)
190 strcatn(MIXDIR, DIRSEPSTR, PATHMAX);
191 return (err);
192 }
193
194 void whoami(char *addr, char *defaultname)
195 {
196 char *p = NULL;
197
198 #if defined(HAVE_GETDOMAINNAME) || (defined(HAVE_GETHOSTNAME) && ! defined(HAVE_UNAME))
199 char line[LINELEN];
200
201 #endif
202 #ifdef HAVE_UNAME
203 struct utsname uts;
204
205 #endif
206 #ifdef POSIX
207 p = getlogin();
208 #endif
209 if (p == NULL)
210 strcpy(addr, defaultname);
211 else
212 strncpy(addr, p, LINELEN);
213
214 strcatn(addr, "@", LINELEN);
215 #ifdef HAVE_UNAME
216 if (uname(&uts) != -1)
217 strcatn(addr, uts.nodename, LINELEN);
218 #elif defined(HAVE_GETHOSTNAME)
219 if (gethostname(line, LINELEN) == 0)
220 strcatn(addr, line, LINELEN);
221 #endif
222 if (addr[strlen(addr) - 1] == '@')
223 strcatn(addr, SHORTNAME, LINELEN);
224
225 if (strchr(strchr(addr, '@'), '.') == NULL) {
226 #ifdef HAVE_GETDOMAINNAME
227 if (getdomainname(line, LINELEN) == 0 && !streq(line, "(none)")) {
228 strcatn(addr, ".", LINELEN);
229 strcatn(addr, line, LINELEN);
230 }
231 #endif
232 }
233 }
234
235 #define read_conf(t) readconfline(line, #t, sizeof(#t)-1, t)
236
237 static int readconfline(char *line, char *name, int namelen, char *var)
238 {
239 if (strncmp(line, name, namelen) == 0 &&
240 (isspace(line[namelen]) || line[namelen] == '=')) {
241 line += namelen;
242 if (*line == '=')
243 line++;
244 while (isspace(*line))
245 line++;
246 if (line[0] == '\n' || line[0] == '\0') /* leave default */
247 return (1);
248 strncpy(var, line, LINELEN);
249 if (var[strlen(var) - 1] == '\n')
250 var[strlen(var) - 1] = '\0';
251 return (1);
252 } else
253 return (0);
254 }
255
256 #define read_conf_i(t) readiconfline(line, #t, sizeof(#t)-1, &t)
257
258 static int readiconfline(char *line, char *name, int namelen, int *var)
259 {
260 if (strncmp(line, name, namelen) == 0 &&
261 (isspace(line[namelen]) || line[namelen] == '=')) {
262 line += namelen;
263 if (*line == '=')
264 line++;
265 while (isspace(*line))
266 line++;
267 if (line[0] == '\n' || line[0] == '\0') /* leave default */
268 return (1);
269 switch (tolower(line[0])) {
270 case 'n':
271 *var = 0;
272 break;
273 case 'y':
274 *var = 1;
275 break;
276 case 'x':
277 *var = 2;
278 break;
279 default:
280 sscanf(line, "%d", var);
281 }
282 return (1);
283 } else
284 return (0);
285 }
286
287 #define read_conf_t(t) readtconfline(line, #t, sizeof(#t)-1, &t)
288
289 static int readtconfline(char *line, char *name, int namelen, long *var)
290 {
291 char *linenext;
292 int mod = 0;
293 long l = 0;
294 long n;
295
296 if (strncmp(line, name, namelen) == 0 &&
297 (isspace(line[namelen]) || line[namelen] == '=')) {
298 line += namelen;
299 if (*line == '=')
300 line++;
301 for (;; line++) {
302 n = strtol(line, &linenext, 10);
303 if (linenext == line)
304 break;
305 line = linenext;
306 mod = 1;
307 assert(line != NULL);
308 while (isspace(*line))
309 line++;
310 switch (tolower(*line)) {
311 case 'd':
312 l += 24 * 60 * 60 * n;
313 break;
314 case 'm':
315 l += 60 * n;
316 break;
317 case 'h':
318 default:
319 l += 60 * 60 * n;
320 break;
321 }
322 }
323 if (mod)
324 *var = l;
325 return (1);
326 } else
327 return (0);
328 }
329
330 void mix_setdefaults()
331 {
332 #define strnncpy(a,b) strncpy(a, b, sizeof(a)); a[sizeof(a)-1] = '\0'
333
334 strnncpy(MIXCONF , DEFAULT_MIXCONF);
335 strnncpy(DISCLAIMFILE , DEFAULT_DISCLAIMFILE);
336 strnncpy(FROMDSCLFILE , DEFAULT_FROMDSCLFILE);
337 strnncpy(MSGFOOTERFILE, DEFAULT_MSGFOOTERFILE);
338 strnncpy(POP3CONF , DEFAULT_POP3CONF);
339 strnncpy(HELPFILE , DEFAULT_HELPFILE);
340 strnncpy(ABUSEFILE , DEFAULT_ABUSEFILE);
341 strnncpy(REPLYFILE , DEFAULT_REPLYFILE);
342 strnncpy(USAGEFILE , DEFAULT_USAGEFILE);
343 strnncpy(USAGELOG , DEFAULT_USAGELOG);
344 strnncpy(BLOCKFILE , DEFAULT_BLOCKFILE);
345 strnncpy(ADMKEYFILE , DEFAULT_ADMKEYFILE);
346 strnncpy(KEYFILE , DEFAULT_KEYFILE);
347 strnncpy(PGPKEY , DEFAULT_PGPKEY);
348 strnncpy(DSAPARAMS , DEFAULT_DSAPARAMS);
349 strnncpy(DHPARAMS , DEFAULT_DHPARAMS);
350 strnncpy(MIXRAND , DEFAULT_MIXRAND);
351 strnncpy(SECRING , DEFAULT_SECRING);
352 strnncpy(PUBRING , DEFAULT_PUBRING);
353 strnncpy(IDLOG , DEFAULT_IDLOG);
354 strnncpy(STATS , DEFAULT_STATS);
355 strnncpy(DESTBLOCK , DEFAULT_DESTBLOCK);
356 strnncpy(DESTALLOW , DEFAULT_DESTALLOW);
357 strnncpy(SOURCEBLOCK , DEFAULT_SOURCEBLOCK);
358 strnncpy(HDRFILTER , DEFAULT_HDRFILTER);
359 strnncpy(REGULAR , DEFAULT_REGULAR);
360 strnncpy(POOL , DEFAULT_POOL);
361 strnncpy(TYPE1LIST , DEFAULT_TYPE1LIST);
362 strnncpy(TYPE2REL , DEFAULT_TYPE2REL);
363 strnncpy(TYPE2LIST , DEFAULT_TYPE2LIST);
364
365 strnncpy(PGPREMPUBRING, DEFAULT_PGPREMPUBRING);
366 strnncpy(PGPREMPUBASC , DEFAULT_PGPREMPUBASC);
367 strnncpy(PGPREMSECRING, DEFAULT_PGPREMSECRING);
368 strnncpy(NYMSECRING , DEFAULT_NYMSECRING);
369 strnncpy(NYMDB , DEFAULT_NYMDB);
370
371
372 strnncpy(MIXDIR , "");
373 strnncpy(POOLDIR , "");
374
375 /* programs */
376 #ifdef WIN32
377 strnncpy(SENDMAIL , "outfile");
378 #else
379 strnncpy(SENDMAIL , "/usr/lib/sendmail -t");
380 #endif
381 strnncpy(SENDANONMAIL , "");
382 strnncpy(NEWS , "");
383 strnncpy(TYPE1 , "");
384
385 /* addresses */
386 strnncpy(MAILtoNEWS , "mail2news@anon.lcs.mit.edu");
387 strnncpy(REMAILERNAME , "Anonymous Remailer");
388 strnncpy(ANONNAME , "Anonymous");
389 strnncpy(REMAILERADDR , "");
390 strnncpy(ANONADDR , "");
391 strnncpy(COMPLAINTS , "");
392 strnncpy(SMTPRELAY , "");
393 AUTOREPLY = 0;
394
395 #ifdef USE_SOCK
396 strnncpy(HELONAME , "");
397 strnncpy(ENVFROM , "");
398 POP3DEL = 0;
399 POP3SIZELIMIT = 0;
400 POP3TIME = 60 * 60;
401
402 #endif
403
404 strnncpy(SHORTNAME , "");
405
406 /* configuration */
407 REMAIL = 0;
408 MIX = 1;
409 PGP = 1;
410 UNENCRYPTED = 0;
411 REMIX = 1;
412 REPGP = 1;
413
414 POOLSIZE = 0;
415 RATE = 100;
416 MIDDLEMAN = 0;
417 AUTOBLOCK = 1;
418 strnncpy(FORWARDTO, "*");
419 SIZELIMIT = 0; /* maximal size of remailed messages */
420 INFLATEMAX = 50; /* maximal size of Inflate: padding */
421 MAXRANDHOPS = 20;
422 BINFILTER = 0; /* filter binary attachments? */
423 LISTSUPPORTED = 1; /* list supported remailers in remailer-conf reply? */
424 PACKETEXP = 7 * SECONDSPERDAY; /* Expiration time for old packets */
425 IDEXP = 7 * SECONDSPERDAY; /* 0 = no ID log !! */
426 SENDPOOLTIME = 60 * 60; /* frequency for sending pool messages */
427 MAILINTIME = 5 * 60; /* frequency for processing MAILIN mail */
428
429 strnncpy(ERRLOG , "");
430 strnncpy(ADDRESS , "");
431 strnncpy(NAME , "");
432
433 strnncpy(ORGANIZATION, "Anonymous Posting Service");
434 strnncpy(MID , "y");
435
436 /* client config */
437 NUMCOPIES = 1;
438 strnncpy(CHAIN, "*,*,*,*");
439 VERBOSE = 2;
440 DISTANCE = 2;
441 MINREL = 98;
442 RELFINAL = 99;
443 MAXLAT = 36 * 60 * 60;
444 strnncpy(PGPPUBRING, "");
445 strnncpy(PGPSECRING, "");
446 #ifdef COMPILEDPASS
447 strnncpy(PASSPHRASE, COMPILEDPASS);
448 #else
449 strnncpy(PASSPHRASE, "");
450 #endif
451 strnncpy(MAILIN , "");
452 strnncpy(MAILBOX , "mbox");
453 strnncpy(MAILABUSE , "");
454 strnncpy(MAILBLOCK , "");
455 #ifdef WIN32
456 strnncpy(MAILUSAGE , "nul:");
457 strnncpy(MAILANON , "nul:");
458 strnncpy(MAILERROR , "nul:");
459 #else
460 strnncpy(MAILUSAGE , "/dev/null");
461 strnncpy(MAILANON , "/dev/null");
462 strnncpy(MAILERROR , "/dev/null");
463 #endif
464 strnncpy(MAILBOUNCE, "");
465 }
466
467 int mix_configline(char *line)
468 {
469 return (read_conf(ADDRESS) || read_conf(NAME) ||
470 read_conf(SHORTNAME) || read_conf(REMAILERADDR) ||
471 read_conf(ANONADDR) || read_conf(REMAILERNAME) ||
472 read_conf(ANONNAME) || read_conf(COMPLAINTS) ||
473 read_conf_i(AUTOREPLY) || read_conf(SMTPRELAY) ||
474 #ifdef USE_SOCK
475 read_conf(HELONAME) || read_conf(ENVFROM) ||
476 #endif
477 read_conf(SENDMAIL) || read_conf(SENDANONMAIL) ||
478 read_conf_i(REMAIL) || read_conf_i(MIX) ||
479 read_conf_i(PGP) || read_conf_i(UNENCRYPTED) ||
480 read_conf_i(REMIX) || read_conf(NEWS) ||
481 read_conf_i(REPGP) ||
482 read_conf(MAILtoNEWS) || read_conf(ERRLOG) ||
483 read_conf(ORGANIZATION) || read_conf(MID) ||
484 read_conf(TYPE1) || read_conf_i(POOLSIZE) ||
485 read_conf_i(RATE) || read_conf_i(MIDDLEMAN) ||
486 read_conf_i(AUTOBLOCK) || read_conf(FORWARDTO) ||
487 read_conf_i(SIZELIMIT) || read_conf_i(INFLATEMAX) ||
488 read_conf_i(MAXRANDHOPS) || read_conf_i(BINFILTER) ||
489 read_conf_i(LISTSUPPORTED) ||
490 read_conf_t(PACKETEXP) || read_conf_t(IDEXP) ||
491 read_conf_t(SENDPOOLTIME) || read_conf_i(NUMCOPIES) ||
492 read_conf_t(MAILINTIME) ||
493 read_conf(CHAIN) || read_conf_i(VERBOSE) ||
494 read_conf_i(DISTANCE) || read_conf_i(MINREL) ||
495 read_conf_i(RELFINAL) || read_conf_t(MAXLAT) ||
496 read_conf(PGPPUBRING) || read_conf(PGPSECRING) ||
497 read_conf(PASSPHRASE) ||
498 #ifdef USE_SOCK
499 read_conf_i(POP3DEL) || read_conf_i(POP3SIZELIMIT) ||
500 read_conf_t(POP3TIME) ||
501 #endif
502 read_conf(MAILBOX) || read_conf(MAILABUSE) ||
503 read_conf(MAILBLOCK) || read_conf(MAILUSAGE) ||
504 read_conf(MAILANON) || read_conf(MAILERROR) ||
505 read_conf(MAILBOUNCE) || read_conf(MAILIN) ||
506
507 read_conf(DISCLAIMFILE) || read_conf(FROMDSCLFILE) ||
508 read_conf(MSGFOOTERFILE) ||
509 read_conf(POP3CONF) || read_conf(HELPFILE) ||
510 read_conf(ABUSEFILE) || read_conf(REPLYFILE) ||
511 read_conf(USAGEFILE) || read_conf(USAGELOG) ||
512 read_conf(BLOCKFILE) || read_conf(ADMKEYFILE) ||
513 read_conf(KEYFILE) || read_conf(PGPKEY) ||
514 read_conf(DSAPARAMS) || read_conf(DHPARAMS) ||
515 read_conf(MIXRAND) || read_conf(SECRING) ||
516 read_conf(PUBRING) || read_conf(IDLOG) ||
517 read_conf(STATS) || read_conf(DESTBLOCK) ||
518 read_conf(DESTALLOW) || read_conf(SOURCEBLOCK) ||
519 read_conf(HDRFILTER) || read_conf(REGULAR) ||
520 read_conf(POOL) || read_conf(TYPE1LIST) ||
521 read_conf(TYPE2REL) || read_conf(TYPE2LIST) ||
522 read_conf(PGPREMPUBRING) || read_conf(PGPREMPUBASC) ||
523 read_conf(PGPREMSECRING) || read_conf(NYMSECRING) ||
524 read_conf(NYMDB) );
525 }
526
527 static int mix_config(void)
528 {
529 char *d;
530 FILE *f;
531 char line[PATHMAX];
532 int err = -1;
533 #ifdef POSIX
534 struct passwd *pw;
535 #endif
536 struct stat buf;
537 #ifdef HAVE_UNAME
538 struct utsname uts;
539 #endif
540 #ifdef WIN32
541 HKEY regsw, reg, regpgp;
542 DWORD type, len;
543 int rkey = 0;
544 #endif
545
546 mix_setdefaults();
547
548 #ifdef POSIX
549 pw = getpwuid(getuid());
550 #endif
551
552 #ifdef WIN32
553 RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, &regsw);
554 len=sizeof(line);
555 if (err == -1 &&
556 RegOpenKeyEx(regsw, "Mixmaster", 0, KEY_QUERY_VALUE, &reg) == 0) {
557 if (RegQueryValueEx(reg, "MixDir", 0, &type, line, &len) == 0)
558 err = mixdir(line, 1);
559 RegCloseKey(reg);
560 }
561 #endif
562
563 if (err == -1 && (d = getenv("MIXPATH")) != NULL)
564 err = mixdir(d, 1);
565
566 #ifdef SPOOL
567 if (err == -1 && strlen(SPOOL) > 0)
568 err = mixdir(SPOOL, 0);
569 #endif
570
571 #ifdef POSIX
572 if (err == -1 && pw != NULL) {
573 strncpy(line, pw->pw_dir, PATHMAX);
574 line[PATHMAX-1] = '\0';
575 if (line[strlen(line) - 1] != DIRSEP)
576 strcatn(line, DIRSEPSTR, PATHMAX);
577 strcatn(line, HOMEMIXDIR, PATHMAX);
578 err = mixdir(line, 1);
579 }
580 #endif
581
582 if (err == -1) {
583 getcwd(MIXDIR, PATHMAX);
584 mixdir(MIXDIR, 0);
585 }
586
587 mixfile(POOLDIR, POOL);
588 if (POOLDIR[strlen(POOLDIR) - 1] == DIRSEP)
589 POOLDIR[strlen(POOLDIR) - 1] = '\0';
590 if (stat(POOLDIR, &buf) != 0)
591 if
592 #ifndef POSIX
593 (mkdir(POOLDIR) != 0)
594 #else
595 (mkdir(POOLDIR, S_IRWXU) == -1)
596 #endif
597 strncpy(POOLDIR, MIXDIR, PATHMAX);
598
599 #ifdef GLOBALMIXCONF
600 f = mix_openfile(GLOBALMIXCONF, "r");
601 if (f != NULL) {
602 while (fgets(line, LINELEN, f) != NULL)
603 if (line[0] > ' ' && line[0] != '#')
604 mix_configline(line);
605 fclose(f);
606 }
607 #endif
608 f = mix_openfile(MIXCONF, "r");
609 if (f != NULL) {
610 while (fgets(line, LINELEN, f) != NULL)
611 if (line[0] > ' ' && line[0] != '#')
612 mix_configline(line);
613 fclose(f);
614 }
615 if (IDEXP > 0 && IDEXP < 5 * SECONDSPERDAY)
616 IDEXP = 5 * SECONDSPERDAY;
617 if (MAXRANDHOPS > 20)
618 MAXRANDHOPS = 20;
619
620 if (strchr(SHORTNAME, '.'))
621 *strchr(SHORTNAME, '.') = '\0';
622 if (strchr(SHORTNAME, ' '))
623 *strchr(SHORTNAME, ' ') = '\0';
624 #ifdef HAVE_UNAME
625 if (SHORTNAME[0] == '\0' && uname(&uts) != -1)
626 strncpy(SHORTNAME, uts.nodename, LINELEN);
627 #elif defined(HAVE_GETHOSTNAME)
628 if (SHORTNAME[0] == '\0')
629 gethostname(SHORTNAME, LINELEN);
630 #endif
631 if (SHORTNAME[0] == '\0')
632 strcpy(SHORTNAME, "unknown");
633
634 if (ADDRESS[0] == '\0')
635 whoami(ADDRESS, "user");
636
637 #ifdef HAVE_GECOS
638 if (NAME[0] == '\0' && pw != NULL)
639 strcatn(NAME, pw->pw_gecos, sizeof(NAME));
640 #endif
641
642 if (REMAILERADDR[0] == '\0')
643 strncpy(REMAILERADDR, ADDRESS, LINELEN);
644
645 if (COMPLAINTS[0] == '\0')
646 strncpy(COMPLAINTS, REMAILERADDR, LINELEN);
647
648 if (strchr(REMAILERNAME, '@') == NULL) {
649 strcatn(REMAILERNAME, " <", LINELEN);
650 strcatn(REMAILERNAME, REMAILERADDR, LINELEN);
651 strcatn(REMAILERNAME, ">", LINELEN);
652 }
653 if (strchr(ANONNAME, '@') == NULL && ANONADDR[0] != '\0') {
654 strcatn(ANONNAME, " <", LINELEN);
655 strcatn(ANONNAME, ANONADDR, LINELEN);
656 strcatn(ANONNAME, ">", LINELEN);
657 }
658 if (strchr(ANONNAME, '@') == NULL) {
659 strcatn(ANONNAME, " <", LINELEN);
660 strcatn(ANONNAME, REMAILERADDR, LINELEN);
661 strcatn(ANONNAME, ">", LINELEN);
662 }
663 #ifndef USE_PGP
664 if (TYPE1[0] == '\0')
665 PGP = 0;
666 #endif
667 #ifndef USE_RSA
668 MIX = 0;
669 #endif
670
671 #ifdef WIN32
672 if (RegOpenKeyEx(regsw, "PGP", 0, KEY_ALL_ACCESS, &regpgp) == 0)
673 rkey++;
674 if (rkey && RegOpenKeyEx(regpgp, "PGPlib", 0, KEY_QUERY_VALUE, &reg) == 0)
675 rkey++;
676 if (PGPPUBRING[0] == '\0' && rkey == 2) {
677 len = PATHMAX;
678 RegQueryValueEx(reg, "PubRing", 0, &type, PGPPUBRING, &len);
679 }
680 if (PGPSECRING[0] == '\0' && rkey == 2) {
681 len = PATHMAX;
682 RegQueryValueEx(reg, "SecRing", 0, &type, PGPSECRING, &len);
683 }
684 if (rkey == 2)
685 RegCloseKey(reg);
686 if (rkey)
687 RegCloseKey(regpgp);
688 RegCloseKey(regsw);
689 #endif
690
691 if (PGPPUBRING[0] == '\0') {
692 char *d;
693
694 if ((d = getenv("HOME")) != NULL) {
695 strcpy(PGPPUBRING, d);
696 strcatn(PGPPUBRING, "/.pgp/", PATHMAX);
697 }
698 strcatn(PGPPUBRING, "pubring.pkr", PATHMAX);
699 if (stat(PGPPUBRING, &buf) == -1)
700 strcpy(strrchr(PGPPUBRING, '.'), ".pgp");
701 }
702 if (PGPSECRING[0] == '\0') {
703 char *d;
704
705 if ((d = getenv("HOME")) != NULL) {
706 strcpy(PGPSECRING, d);
707 strcatn(PGPSECRING, "/.pgp/", PATHMAX);
708 }
709 strcatn(PGPSECRING, "secring.skr", PATHMAX);
710 if (stat(PGPSECRING, &buf) == -1)
711 strcpy(strrchr(PGPSECRING, '.'), ".pgp");
712 }
713 if (streq(NEWS, "mail-to-news"))
714 strncpy(NEWS, MAILtoNEWS, sizeof(NEWS));
715
716 if (f == NULL) {
717 #ifndef GLOBALMIXCONF
718 /* Only write the config file in non systemwide installation */
719 f = mix_openfile(MIXCONF, "w");
720 if (f == NULL)
721 errlog(WARNING, "Can't open %s%s!\n", MIXDIR, MIXCONF);
722 else {
723 fprintf(f, "# mix.cfg - mixmaster configuration file\n");
724 fprintf(f, "NAME %s\n", NAME);
725 fprintf(f, "ADDRESS %s\n", ADDRESS);
726 fprintf(f, "\n# edit to set up a remailer:\n");
727 fprintf(f, "REMAIL n\n");
728 fprintf(f, "SHORTNAME %s\n", SHORTNAME);
729 fprintf(f, "REMAILERADDR %s\n", REMAILERADDR);
730 fprintf(f, "COMPLAINTS %s\n", COMPLAINTS);
731 fclose(f);
732 }
733 #endif
734 REMAIL = 0;
735 }
736
737 return (0);
738 }
739
740 /** Library initialization: ******************************************/
741
742 static int initialized = 0;
743
744 int mix_init(char *mixdir)
745 {
746 if (!initialized) {
747 if (mixdir)
748 strncpy(MIXDIR, mixdir, LINELEN);
749 mix_config();
750 #if defined(USE_SOCK) && defined(WIN32)
751 sock_init();
752 #endif
753 /* atexit (mix_exit); */
754 initialized = 1;
755 }
756
757 if (rnd_init() == -1)
758 rnd_seed();
759 return(0);
760 }
761
762 void mix_exit(void)
763 {
764 if (!initialized)
765 return;
766 rnd_final();
767 #if defined(USE_SOCK) && defined(WIN32)
768 sock_exit();
769 #endif
770 initialized=0;
771 }
772
773 int mix_regular(int force)
774 {
775 FILE *f;
776 long now, tpool = 0, tpop3 = 0, tdaily = 0, tmailin = 0;
777 int ret = 0;
778
779 mix_init(NULL);
780 now = time(NULL);
781
782 f = mix_openfile(REGULAR, "r+");
783 if (f != NULL) {
784 lock(f);
785 fscanf(f, "%ld %ld %ld %ld", &tpool, &tpop3, &tdaily, &tmailin);
786 if (now - tpool >= SENDPOOLTIME)
787 force |= FORCE_POOL | FORCE_MAILIN;
788 #ifdef USE_SOCK
789 if (now - tpop3 >= POP3TIME)
790 force |= FORCE_POP3 | FORCE_MAILIN;
791 #endif
792 if (now - tdaily >= SECONDSPERDAY)
793 force |= FORCE_DAILY;
794 if (now - tmailin >= MAILINTIME)
795 force |= FORCE_MAILIN;
796 if (force & FORCE_POOL)
797 tpool = now;
798 if (force & FORCE_POP3)
799 tpop3 = now;
800 if (force & FORCE_DAILY)
801 tdaily = now;
802 if (force & FORCE_MAILIN)
803 tmailin = now;
804 rewind(f);
805 fprintf(f, "%ld %ld %ld %ld\n", tpool, tpop3, tdaily, tmailin);
806 unlock(f);
807 fclose(f);
808 } else {
809 force = FORCE_POOL | FORCE_POP3 | FORCE_DAILY | FORCE_MAILIN;
810 f = mix_openfile(REGULAR, "w+");
811 if (f != NULL) {
812 lock(f);
813 fprintf(f, "%ld %ld %ld %ld\n", now, now, now, now);
814 unlock(f);
815 fclose(f);
816 } else
817 errlog(ERRORMSG, "Can't create %s!\n", REGULAR);
818 }
819
820 if (force & FORCE_DAILY)
821 mix_daily(), ret = 1;
822 #ifdef USE_SOCK
823 if (force & FORCE_POP3)
824 pop3get();
825 #endif
826 if (force & FORCE_MAILIN)
827 ret = process_mailin();
828 if (force & FORCE_POOL)
829 ret = pool_send();
830
831 return (ret);
832 }
833
834 int mix_daily(void)
835 {
836 idexp();
837 pool_packetexp();
838 stats(NULL);
839 keymgt(0);
840 return (0);
841 }
842
843 /** Handle signals SIGHUP, SIGINT, and SIGTERM
844 This signal handler gets called if the daemon
845 process receives one of SIGHUP, SIGINT, or SIGTERM.
846 It then sets either rereadconfig of terminatedaemon
847 to true depending on the signal received.
848
849 @author PP
850 @return nothing
851 */
852 void sighandler(int signal) {
853 if (signal == SIGHUP)
854 rereadconfig = 1;
855 else if (signal == SIGINT || signal == SIGTERM)
856 terminatedaemon = 1;
857 };
858
859 /** Set the signal handler for SIGHUP, SIGINT and SIGTERM
860 This function registers signal handlers so that
861 we can react on signals send by the user in daemon
862 mode. SIGHUP will instruct mixmaster to reload its
863 configuration while SIGINT and SIGTERM will instruct
864 it to shut down. Mixmaster will finish the current
865 pool run before it terminates.
866
867 @param restart Whether or not system calls should be
868 restarted. Usually we want this, the
869 only excetion is the sleep() in the
870 daemon mail loop.
871 @author PP
872 @return -1 if calling sigaction failed, 0 on
873 no error
874 */
875 int setsignalhandler(int restart)
876 {
877 #ifdef POSIX
878 struct sigaction hdl;
879 int err = 0;
880
881 memset(&hdl, 0, sizeof(hdl));
882 hdl.sa_handler = sighandler;
883 hdl.sa_flags = restart ? SA_RESTART : 0;
884
885 if (sigaction(SIGHUP, &hdl, NULL))
886 err = -1;
887 if (sigaction(SIGINT, &hdl, NULL))
888 err = -1;
889 if (sigaction(SIGTERM, &hdl, NULL))
890 err = -1;
891 return (err);
892 #else /* POSIX */
893 return(0);
894 #endif /* POSIX */
895 }
896
897 #ifdef WIN32
898 /* Try to detect if we are the service or not...
899 seems there is no easy reliable way */
900 int is_nt_service(void)
901 {
902 static int issvc = -1;
903 #ifdef WIN32SERVICE
904 STARTUPINFO StartupInfo;
905 OSVERSIONINFO VersionInfo;
906 DWORD dwsize;
907
908 if (issvc != -1) /* do it only once */
909 return issvc;
910
911 VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
912 if (GetVersionEx(&VersionInfo))
913 if (VersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
914 return issvc = 0; /* not NT - not the service */
915
916 if (!GetConsoleTitle(&VersionInfo,sizeof(VersionInfo)))
917 /* reuse VersionInfo to save memory */
918 return issvc = 1; /* have no console - we are the service probably */
919
920 GetStartupInfo(&StartupInfo);
921 if (StartupInfo.lpDesktop[0] == 0)
922 return issvc = 1; /* have no desktop - we are the service probably */
923
924 if (_fileno(stdin) == -1 && _fileno(stdout) == -1 && _fileno(stderr) == -1)
925 return issvc = 1; /* have no stdin,stderr,stdout - probably service */
926 #endif // WIN32SERVICE
927
928 return issvc = 0; // assume not the service
929 } // is_nt_service
930
931 HANDLE hMustTerminate = NULL;
932 void set_nt_exit_event(HANDLE h_svc_exit_event)
933 {
934 hMustTerminate = h_svc_exit_event;
935 } // set_nt_exit_event
936
937 #endif // WIN32
938
939 int mix_daemon(void)
940 {
941 long t, slept;
942 t = (MAILINTIME < SENDPOOLTIME && (MAILIN != NULL && (strcmp(MAILIN, "") != 0))) ? MAILINTIME : SENDPOOLTIME;
943 #ifdef USE_SOCK
944 if (POP3TIME < t)
945 t = POP3TIME;
946 #endif
947 slept = t;
948
949 setsignalhandler(1); /* set signal handlers and restart any interrupted system calls */
950 for(;;) {
951 if (terminatedaemon)
952 exit(0);
953 if (rereadconfig) {
954 rereadconfig = 0;
955 mix_config();
956 t = (MAILINTIME < SENDPOOLTIME && (MAILIN != NULL && (strcmp(MAILIN, "") != 0))) ? MAILINTIME : SENDPOOLTIME;
957 #ifdef USE_SOCK
958 if (POP3TIME < t)
959 t = POP3TIME;
960 #endif
961 }
962 if (slept >= t) {
963 mix_regular(0);
964 slept = 0;
965 }
966
967 if (!terminatedaemon && !rereadconfig) {
968 setsignalhandler(0); /* set signal handlers; don't restart system calls */
969 #ifdef WIN32
970 #ifdef WIN32SERVICE
971 if (hMustTerminate) {
972 if (WaitForSingleObject(hMustTerminate, t * 1000) == WAIT_OBJECT_0) {
973 CloseHandle(hMustTerminate);
974 return 0;
975 }
976 } else
977 #endif
978 Sleep(t * 1000);
979 #else
980 slept += (t - slept) - sleep(t - slept);
981 #endif
982 setsignalhandler(1); /* set signal handlers and restart any interrupted system calls */
983 }
984 }
985 }
986
987 /** error ***************************************************************/
988
989 void errlog(int type, char *fmt,...)
990 {
991 va_list args;
992 BUFFER *msg;
993 FILE *e = NULL;
994 time_t t;
995 struct tm *tc;
996 char line[LINELEN];
997 int p;
998 char err[6][8] =
999 {"", "Error", "Warning", "Notice", "Info", "Info"};
1000
1001 if ((VERBOSE == 0 && type != ERRORMSG) || (type == LOG && VERBOSE < 2)
1002 || (type == DEBUGINFO && VERBOSE < 3))
1003 return;
1004
1005 t = time(NULL);
1006 tc = localtime(&t);
1007 strftime(line, LINELEN, "[%Y-%m-%d %H:%M:%S] ", tc);
1008
1009 msg = buf_new();
1010 buf_appends(msg, line);
1011 p = msg->length;
1012 buf_appendf(msg, "%s: ", err[type]);
1013 va_start(args, fmt);
1014 buf_vappendf(msg, fmt, args);
1015 va_end(args);
1016
1017 if (streq(ERRLOG, "stdout"))
1018 e = stdout;
1019 else if (streq(ERRLOG, "stderr"))
1020 e = stderr;
1021
1022 if (e == NULL && (ERRLOG[0] == '\0' ||
1023 (e = mix_openfile(ERRLOG, "a")) == NULL))
1024 mix_status("%s", msg->data + p);
1025 else {
1026 buf_write(msg, e);
1027 if (e != stderr && e != stdout) {
1028 fclose(e);
1029 /* duplicate the error message on screen */
1030 mix_status("%s", msg->data + p);
1031 }
1032 }
1033 buf_free(msg);
1034 }
1035
1036 static char statusline[BUFSIZE] = "";
1037
1038 void mix_status(char *fmt,...)
1039 {
1040 va_list args;
1041
1042 if (fmt != NULL) {
1043 va_start(args, fmt);
1044 #ifdef _MSC
1045 _vsnprintf(statusline, sizeof(statusline) - 1, fmt, args);
1046 #else
1047 vsnprintf(statusline, sizeof(statusline) - 1, fmt, args);
1048 #endif
1049 va_end(args);
1050 }
1051 #ifdef USE_NCURSES
1052 if (menu_initialized) {
1053 cl(LINES - 2, 10);
1054 printw("%s", statusline);
1055 refresh();
1056 } else
1057 #endif
1058 {
1059 fprintf(stderr, "%s", statusline);
1060 }
1061 }
1062
1063 void mix_genericerror(void)
1064 {
1065 if (streq(statusline, "") || strfind(statusline, "...") ||
1066 strifind(statusline, "generating"))
1067 mix_status("Failed!");
1068 else
1069 mix_status(NULL);
1070 }

  ViewVC Help
Powered by ViewVC 1.1.5