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

Properties

Name Value
svn:keywords Id

  ViewVC Help
Powered by ViewVC 1.1.5