Mercurial > masqmail
comparison src/masqmail.c @ 409:6874a4f265c1
Broke long lines.
author | markus schnalke <meillo@marmaro.de> |
---|---|
date | Wed, 29 Feb 2012 11:03:46 +0100 |
parents | cdd16614c1f5 |
children | 0430194f7ef8 |
comparison
equal
deleted
inserted
replaced
408:f609a05ddff8 | 409:6874a4f265c1 |
---|---|
64 sigterm_in_progress = 1; | 64 sigterm_in_progress = 1; |
65 | 65 |
66 if (pidfile) { | 66 if (pidfile) { |
67 uid_t uid = geteuid(); | 67 uid_t uid = geteuid(); |
68 if (seteuid(0) != 0) { | 68 if (seteuid(0) != 0) { |
69 logwrite(LOG_ALERT, "sigterm_handler: could not set euid to %d: %s\n", 0, strerror(errno)); | 69 logwrite(LOG_ALERT, "sigterm_handler: could not set " |
70 "euid to %d: %s\n", | |
71 0, strerror(errno)); | |
70 } | 72 } |
71 if (unlink(pidfile) != 0) | 73 if (unlink(pidfile) != 0) |
72 logwrite(LOG_WARNING, "could not delete pid file %s: %s\n", pidfile, strerror(errno)); | 74 logwrite(LOG_WARNING, |
75 "could not delete pid file %s: %s\n", | |
76 pidfile, strerror(errno)); | |
73 seteuid(uid); /* we exit anyway after this, just to be sure */ | 77 seteuid(uid); /* we exit anyway after this, just to be sure */ |
74 } | 78 } |
75 | 79 |
76 signal(sig, SIG_DFL); | 80 signal(sig, SIG_DFL); |
77 raise(sig); | 81 raise(sig); |
109 fprintf(fptr, "%d\n", getpid()); | 113 fprintf(fptr, "%d\n", getpid()); |
110 fclose(fptr); | 114 fclose(fptr); |
111 pidfile = strdup(name); | 115 pidfile = strdup(name); |
112 return TRUE; | 116 return TRUE; |
113 } | 117 } |
114 logwrite(LOG_WARNING, "could not write pid file: %s\n", strerror(errno)); | 118 logwrite(LOG_WARNING, "could not write pid file: %s\n", |
119 strerror(errno)); | |
115 return FALSE; | 120 return FALSE; |
116 } | 121 } |
117 | 122 |
118 /* on -bd or if -q has an argument */ | 123 /* on -bd or if -q has an argument */ |
119 static void | 124 static void |
122 guint pid; | 127 guint pid; |
123 | 128 |
124 /* daemon */ | 129 /* daemon */ |
125 if (!conf.run_as_user) { | 130 if (!conf.run_as_user) { |
126 if ((conf.orig_uid != 0) && (conf.orig_uid != conf.mail_uid)) { | 131 if ((conf.orig_uid != 0) && (conf.orig_uid != conf.mail_uid)) { |
127 fprintf(stderr, "must be root or %s for daemon.\n", DEF_MAIL_USER); | 132 fprintf(stderr, "must be root or %s for daemon.\n", |
133 DEF_MAIL_USER); | |
128 exit(1); | 134 exit(1); |
129 } | 135 } |
130 } | 136 } |
131 | 137 |
132 /* reparent to init only if init is not already the parent */ | 138 /* reparent to init only if init is not already the parent */ |
154 fclose(stdout); | 160 fclose(stdout); |
155 fclose(stderr); | 161 fclose(stderr); |
156 logopen(); | 162 logopen(); |
157 | 163 |
158 logwrite(LOG_NOTICE, "%s %s daemon starting\n", PACKAGE, VERSION); | 164 logwrite(LOG_NOTICE, "%s %s daemon starting\n", PACKAGE, VERSION); |
159 listen_port(do_listen ? conf.listen_addresses : NULL, queue_interval, argv); | 165 listen_port(do_listen ? conf.listen_addresses : NULL, |
166 queue_interval, argv); | |
160 } | 167 } |
161 | 168 |
162 /* -bs or called as smtpd or in.smtpd */ | 169 /* -bs or called as smtpd or in.smtpd */ |
163 static void | 170 static void |
164 mode_smtp() | 171 mode_smtp() |
196 message *msg = create_message(); | 203 message *msg = create_message(); |
197 gint i; | 204 gint i; |
198 pid_t pid; | 205 pid_t pid; |
199 | 206 |
200 if (return_path && !is_privileged_user(conf.orig_uid)) { | 207 if (return_path && !is_privileged_user(conf.orig_uid)) { |
201 fprintf(stderr, "must be root, %s or in group %s for setting return path.\n", DEF_MAIL_USER, DEF_MAIL_GROUP); | 208 fprintf(stderr, "must be root, %s or in group %s for " |
209 "setting return path.\n", | |
210 DEF_MAIL_USER, DEF_MAIL_GROUP); | |
202 exit(1); | 211 exit(1); |
203 } | 212 } |
204 | 213 |
205 if (!conf.run_as_user) { | 214 if (!conf.run_as_user) { |
206 set_euidgid(conf.orig_uid, conf.orig_gid, NULL, NULL); | 215 set_euidgid(conf.orig_uid, conf.orig_gid, NULL, NULL); |
210 | 219 |
211 msg->received_prot = PROT_LOCAL; | 220 msg->received_prot = PROT_LOCAL; |
212 | 221 |
213 /* warn if -t option and cmdline addr args */ | 222 /* warn if -t option and cmdline addr args */ |
214 if (addr_cnt && (accept_flags & ACC_RCPT_FROM_HEAD)) { | 223 if (addr_cnt && (accept_flags & ACC_RCPT_FROM_HEAD)) { |
215 logwrite(LOG_ALERT, "command line address arguments are now *added* to the mail header\\\n"); | 224 logwrite(LOG_ALERT, "command line address arguments are " |
216 logwrite(LOG_ALERT, " recipient addresses (instead of substracted) when -t is given.\\\n"); | 225 "now *added* to the mail header\\\n"); |
226 logwrite(LOG_ALERT, " recipient addresses (instead of " | |
227 "substracted) when -t is given.\\\n"); | |
217 logwrite(LOG_ALERT, " this changed with version 0.3.1\n"); | 228 logwrite(LOG_ALERT, " this changed with version 0.3.1\n"); |
218 } | 229 } |
219 | 230 |
220 for (i = 0; i < addr_cnt; i++) { | 231 for (i = 0; i < addr_cnt; i++) { |
221 if (addresses[i][0] == '|') { | 232 if (addresses[i][0] == '|') { |
222 logwrite(LOG_ALERT, "no pipe allowed as recipient address: %s\n", addresses[i]); | 233 logwrite(LOG_ALERT, "no pipe allowed as recipient " |
234 "address: %s\n", addresses[i]); | |
223 /* should we better ignore this one addr? */ | 235 /* should we better ignore this one addr? */ |
224 exit(1); | 236 exit(1); |
225 } | 237 } |
226 msg->rcpt_list = g_list_append(msg->rcpt_list, create_address_qualified(addresses[i], TRUE, conf.host_name)); | 238 msg->rcpt_list = g_list_append(msg->rcpt_list, |
239 create_address_qualified(addresses[i], | |
240 TRUE, conf.host_name)); | |
227 } | 241 } |
228 | 242 |
229 /* -f option */ | 243 /* -f option */ |
230 msg->return_path = return_path; | 244 msg->return_path = return_path; |
231 | 245 |
257 fprintf(stderr, "Could not write spool file\n"); | 271 fprintf(stderr, "Could not write spool file\n"); |
258 exit(1); | 272 exit(1); |
259 } | 273 } |
260 | 274 |
261 /* here the mail is queued and thus in our responsibility */ | 275 /* here the mail is queued and thus in our responsibility */ |
262 logwrite(LOG_NOTICE, "%s <= %s with %s\n", msg->uid, addr_string(msg->return_path), prot_names[PROT_LOCAL]); | 276 logwrite(LOG_NOTICE, "%s <= %s with %s\n", msg->uid, |
277 addr_string(msg->return_path), prot_names[PROT_LOCAL]); | |
263 | 278 |
264 if (conf.do_queue) { | 279 if (conf.do_queue) { |
265 /* we're finished as we only need to queue it */ | 280 /* we're finished as we only need to queue it */ |
266 return; | 281 return; |
267 } | 282 } |
268 | 283 |
269 /* deliver at once */ | 284 /* deliver at once */ |
270 if ((pid = fork()) < 0) { | 285 if ((pid = fork()) < 0) { |
271 logwrite(LOG_ALERT, "could not fork for delivery, id = %s\n", msg->uid); | 286 logwrite(LOG_ALERT, "could not fork for delivery, id = %s\n", |
287 msg->uid); | |
272 } else if (pid == 0) { | 288 } else if (pid == 0) { |
273 conf.do_verbose = FALSE; | 289 conf.do_verbose = FALSE; |
274 fclose(stdin); | 290 fclose(stdin); |
275 fclose(stdout); | 291 fclose(stdout); |
276 fclose(stderr); | 292 fclose(stderr); |
319 return ok; | 335 return ok; |
320 } | 336 } |
321 | 337 |
322 struct passwd *pw = getpwuid(conf.orig_uid); | 338 struct passwd *pw = getpwuid(conf.orig_uid); |
323 if (!pw) { | 339 if (!pw) { |
324 fprintf(stderr, "could not find a passwd entry for uid %d: %s\n", | 340 fprintf(stderr, "could not find a passwd entry for " |
325 conf.orig_uid, strerror(errno)); | 341 "uid %d: %s\n", |
342 conf.orig_uid, strerror(errno)); | |
326 return FALSE; | 343 return FALSE; |
327 } | 344 } |
328 | 345 |
329 /* non-privileged users may only delete their own messages */ | 346 /* non-privileged users may only delete their own messages */ |
330 for (; *id; id++) { | 347 for (; *id; id++) { |
331 message *msg = msg_spool_read(*id); | 348 message *msg = msg_spool_read(*id); |
332 | 349 |
333 fprintf(stderr, "id: %s\n", *id); | 350 fprintf(stderr, "id: %s\n", *id); |
334 | 351 |
335 if (!msg->ident) { | 352 if (!msg->ident) { |
336 fprintf(stderr, "message %s does not have an ident\n", *id); | 353 fprintf(stderr, "message %s does not have an ident\n", |
354 *id); | |
337 continue; | 355 continue; |
338 } | 356 } |
339 if (strcmp(pw->pw_name, msg->ident) != 0) { | 357 if (strcmp(pw->pw_name, msg->ident) != 0) { |
340 fprintf(stderr, "you do not own message id %s\n", *id); | 358 fprintf(stderr, "you do not own message id %s\n", *id); |
341 continue; | 359 continue; |
342 } | 360 } |
343 | 361 |
344 if (msg->received_host || (msg->received_prot != PROT_LOCAL)) { | 362 if (msg->received_host || (msg->received_prot != PROT_LOCAL)) { |
345 fprintf(stderr, "message %s was not received locally\n", *id); | 363 fprintf(stderr, "message %s was not received " |
364 "locally\n", *id); | |
346 continue; | 365 continue; |
347 } | 366 } |
348 | 367 |
349 ok = queue_delete(*id); | 368 ok = queue_delete(*id); |
350 } | 369 } |
364 ret = queue_run(); | 383 ret = queue_run(); |
365 } | 384 } |
366 | 385 |
367 if (do_runq_online) { | 386 if (do_runq_online) { |
368 if (route_name) { | 387 if (route_name) { |
369 conf.online_query = g_strdup_printf("/bin/echo %s", route_name); | 388 conf.online_query = g_strdup_printf("/bin/echo %s", |
389 route_name); | |
370 } | 390 } |
371 /* | 391 /* |
372 ** TODO: change behavior of `-qo without argument'? | 392 ** TODO: change behavior of `-qo without argument'? |
373 ** Because that behavior is included in -q. | 393 ** Because that behavior is included in -q. |
374 */ | 394 */ |
396 | 416 |
397 void | 417 void |
398 set_mode(enum mta_mode mode) | 418 set_mode(enum mta_mode mode) |
399 { | 419 { |
400 if (mta_mode && mta_mode!=mode) { | 420 if (mta_mode && mta_mode!=mode) { |
401 fprintf(stderr, "operation mode was already specified (%d vs. %d)\n", mta_mode, mode); | 421 fprintf(stderr, "operation mode was already specified " |
422 "(%d vs. %d)\n", mta_mode, mode); | |
402 exit(1); | 423 exit(1); |
403 } | 424 } |
404 | 425 |
405 mta_mode = mode; | 426 mta_mode = mode; |
406 return; | 427 return; |
489 get_optarg(argv, &arg, opt+1); | 510 get_optarg(argv, &arg, opt+1); |
490 | 511 |
491 } else if (strncmp(opt, "C", 1) == 0) { | 512 } else if (strncmp(opt, "C", 1) == 0) { |
492 conf_file = get_optarg(argv, &arg, opt+1); | 513 conf_file = get_optarg(argv, &arg, opt+1); |
493 if (!conf_file) { | 514 if (!conf_file) { |
494 fprintf(stderr, "-C requires a filename as argument.\n"); | 515 fprintf(stderr, "-C requires filename arg.\n"); |
495 exit(1); | 516 exit(1); |
496 } | 517 } |
497 | 518 |
498 } else if (strncmp(opt, "d", 1) == 0) { | 519 } else if (strncmp(opt, "d", 1) == 0) { |
499 if (getuid() != 0) { | 520 if (getuid() != 0) { |
500 fprintf(stderr, "only root may set the debug level.\n"); | 521 fprintf(stderr, "only root may set the " |
522 "debug level.\n"); | |
501 exit(1); | 523 exit(1); |
502 } | 524 } |
503 char *lvl = get_optarg(argv, &arg, opt+1); | 525 char *lvl = get_optarg(argv, &arg, opt+1); |
504 if (!lvl) { | 526 if (!lvl) { |
505 fprintf(stderr, "-d requires a number argument.\n"); | 527 fprintf(stderr, "-d requires number arg.\n"); |
506 exit(1); | 528 exit(1); |
507 } | 529 } |
508 debug_level = atoi(lvl); | 530 debug_level = atoi(lvl); |
509 | 531 |
510 } else if (strncmp(opt, "f", 1) == 0) { | 532 } else if (strncmp(opt, "f", 1) == 0) { |
511 /* set return path */ | 533 /* set return path */ |
512 gchar *address = get_optarg(argv, &arg, opt+1); | 534 gchar *address = get_optarg(argv, &arg, opt+1); |
513 if (!address) { | 535 if (!address) { |
514 fprintf(stderr, "-f requires an address argument\n"); | 536 fprintf(stderr, "-f requires address arg.\n"); |
515 exit(1); | 537 exit(1); |
516 } | 538 } |
517 f_address = g_strdup(address); | 539 f_address = g_strdup(address); |
518 | 540 |
519 } else if (strncmp(opt, "F", 1) == 0) { | 541 } else if (strncmp(opt, "F", 1) == 0) { |
520 full_sender_name = get_optarg(argv, &arg, opt+1); | 542 full_sender_name = get_optarg(argv, &arg, opt+1); |
521 if (!full_sender_name) { | 543 if (!full_sender_name) { |
522 fprintf(stderr, "-F requires a name argument\n"); | 544 fprintf(stderr, "-F requires name arg.\n"); |
523 exit(1); | 545 exit(1); |
524 } | 546 } |
525 | 547 |
526 } else if (strcmp(opt, "i") == 0) { | 548 } else if (strcmp(opt, "i") == 0) { |
527 opt_i = TRUE; | 549 opt_i = TRUE; |
548 do_runq_online = TRUE; | 570 do_runq_online = TRUE; |
549 /* can be NULL, then we use online detection method */ | 571 /* can be NULL, then we use online detection method */ |
550 /* TODO: behavior might change if it is NULL */ | 572 /* TODO: behavior might change if it is NULL */ |
551 route_name = get_optarg(argv, &arg, opt+2); | 573 route_name = get_optarg(argv, &arg, opt+2); |
552 if (!route_name) { | 574 if (!route_name) { |
553 fprintf(stderr, "Please do not use -qo without argument anymore; use -q instead.\n"); | 575 fprintf(stderr, "Please do not use -qo " |
554 fprintf(stderr, "The behavior for -qo without argument is likely to change.\n"); | 576 "without argument anymore; " |
577 "use -q instead.\n"); | |
578 fprintf(stderr, "The behavior for -qo without " | |
579 "argument is likely to " | |
580 "change.\n"); | |
555 } | 581 } |
556 | 582 |
557 } else if (strncmp(opt, "q", 1) == 0) { | 583 } else if (strncmp(opt, "q", 1) == 0) { |
558 /* must be after the `qo' check */ | 584 /* must be after the `qo' check */ |
559 gchar *optarg; | 585 gchar *optarg; |
560 | 586 |
561 optarg = get_optarg(argv, &arg, opt+1); | 587 optarg = get_optarg(argv, &arg, opt+1); |
562 if (optarg) { | 588 if (optarg) { |
563 /* not just one single queue run but regular runs */ | 589 /* do regular queue runs */ |
564 set_mode(MODE_DAEMON); | 590 set_mode(MODE_DAEMON); |
565 queue_interval = time_interval(optarg); | 591 queue_interval = time_interval(optarg); |
566 } else { | 592 } else { |
593 /* do a single queue run */ | |
567 set_mode(MODE_RUNQUEUE); | 594 set_mode(MODE_RUNQUEUE); |
568 do_runq = TRUE; | 595 do_runq = TRUE; |
569 } | 596 } |
570 | 597 |
571 } else if (strcmp(opt, "t") == 0) { | 598 } else if (strcmp(opt, "t") == 0) { |
629 */ | 656 */ |
630 if ((strcmp(conf_file, CONF_FILE) != 0) && (conf.orig_uid != 0)) { | 657 if ((strcmp(conf_file, CONF_FILE) != 0) && (conf.orig_uid != 0)) { |
631 conf.run_as_user = TRUE; | 658 conf.run_as_user = TRUE; |
632 set_euidgid(conf.orig_uid, conf.orig_gid, NULL, NULL); | 659 set_euidgid(conf.orig_uid, conf.orig_gid, NULL, NULL); |
633 if (setgid(conf.orig_gid)) { | 660 if (setgid(conf.orig_gid)) { |
634 logwrite(LOG_ALERT, "could not set gid to %d: %s\n", conf.orig_gid, strerror(errno)); | 661 logwrite(LOG_ALERT, "could not set gid to %d: %s\n", |
662 conf.orig_gid, strerror(errno)); | |
635 exit(1); | 663 exit(1); |
636 } | 664 } |
637 if (setuid(conf.orig_uid)) { | 665 if (setuid(conf.orig_uid)) { |
638 logwrite(LOG_ALERT, "could not set uid to %d: %s\n", conf.orig_uid, strerror(errno)); | 666 logwrite(LOG_ALERT, "could not set uid to %d: %s\n", |
667 conf.orig_uid, strerror(errno)); | |
639 exit(1); | 668 exit(1); |
640 } | 669 } |
641 } | 670 } |
642 | 671 |
643 conf.log_dir = LOG_DIR; | 672 conf.log_dir = LOG_DIR; |
644 conf.debug_level = debug_level; /* for debuggin during read_conf() */ | 673 conf.debug_level = debug_level; /* for debuggin during read_conf() */ |
645 /* FIXME: fails if we run as user */ | 674 /* FIXME: fails if we run as user */ |
646 logopen(); | 675 logopen(); |
647 if (!read_conf(conf_file)) { | 676 if (!read_conf(conf_file)) { |
648 logwrite(LOG_ALERT, "SHUTTING DOWN due to problems reading config\n"); | 677 logwrite(LOG_ALERT, "SHUTTING DOWN due to problems reading " |
678 "config\n"); | |
649 exit(5); | 679 exit(5); |
650 } | 680 } |
651 logclose(); | 681 logclose(); |
652 | 682 |
653 if (do_queue) { | 683 if (do_queue) { |
670 */ | 700 */ |
671 chdir("/"); | 701 chdir("/"); |
672 | 702 |
673 if (!conf.run_as_user) { | 703 if (!conf.run_as_user) { |
674 if (setgid(0) != 0) { | 704 if (setgid(0) != 0) { |
675 fprintf(stderr, "could not set gid to 0. Is the setuid bit set? : %s\n", strerror(errno)); | 705 fprintf(stderr, "could not set gid to 0. " |
706 "Is the setuid bit set? : %s\n", | |
707 strerror(errno)); | |
676 exit(1); | 708 exit(1); |
677 } | 709 } |
678 if (setuid(0) != 0) { | 710 if (setuid(0) != 0) { |
679 fprintf(stderr, "could not gain root privileges. Is the setuid bit set? : %s\n", strerror(errno)); | 711 fprintf(stderr, "could not gain root privileges. " |
712 "Is the setuid bit set? : %s\n", | |
713 strerror(errno)); | |
680 exit(1); | 714 exit(1); |
681 } | 715 } |
682 } | 716 } |
683 | 717 |
684 if (!logopen()) { | 718 if (!logopen()) { |
697 } | 731 } |
698 } | 732 } |
699 DEBUG(5) debugf("queue_interval = %d\n", queue_interval); | 733 DEBUG(5) debugf("queue_interval = %d\n", queue_interval); |
700 | 734 |
701 if (f_address) { | 735 if (f_address) { |
702 return_path = create_address_qualified(f_address, TRUE, conf.host_name); | 736 return_path = create_address_qualified(f_address, TRUE, |
737 conf.host_name); | |
703 g_free(f_address); | 738 g_free(f_address); |
704 if (!return_path) { | 739 if (!return_path) { |
705 fprintf(stderr, "invalid RFC821 address: %s\n", f_address); | 740 fprintf(stderr, "invalid RFC821 address: %s\n", |
741 f_address); | |
706 exit(1); | 742 exit(1); |
707 } | 743 } |
708 } | 744 } |
709 | 745 |
710 switch (mta_mode) { | 746 switch (mta_mode) { |
732 exit(manipulate_queue(M_cmd, &argv[arg]) ? 0 : 1); | 768 exit(manipulate_queue(M_cmd, &argv[arg]) ? 0 : 1); |
733 break; | 769 break; |
734 | 770 |
735 case MODE_ACCEPT: | 771 case MODE_ACCEPT: |
736 { | 772 { |
737 guint accept_flags = (opt_t ? ACC_RCPT_FROM_HEAD : 0) | 773 guint accept_flags = 0; |
738 | (opt_i ? ACC_DOT_IGNORE : ACC_NODOT_RELAX); | 774 accept_flags |= (opt_t ? ACC_RCPT_FROM_HEAD : 0); |
739 mode_accept(return_path, full_sender_name, accept_flags, &(argv[arg]), argc - arg); | 775 accept_flags |= (opt_i ? |
776 ACC_DOT_IGNORE : ACC_NODOT_RELAX); | |
777 mode_accept(return_path, full_sender_name, | |
778 accept_flags, argv + arg, argc - arg); | |
740 exit(0); | 779 exit(0); |
741 } | 780 } |
742 break; | 781 break; |
743 | 782 |
744 default: | 783 default: |