1 /* $OpenBSD: smtpd.c,v 1.52 2009/04/03 05:20:17 oga Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> 5 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/types.h> 21 #include <sys/queue.h> 22 #include <sys/tree.h> 23 #include <sys/param.h> 24 #include <sys/socket.h> 25 #include <sys/wait.h> 26 #include <sys/stat.h> 27 #include <sys/uio.h> 28 #include <sys/resource.h> 29 30 #include <bsd_auth.h> 31 #include <err.h> 32 #include <errno.h> 33 #include <event.h> 34 #include <fcntl.h> 35 #include <login_cap.h> 36 #include <paths.h> 37 #include <paths.h> 38 #include <pwd.h> 39 #include <regex.h> 40 #include <signal.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <sysexits.h> 45 #include <time.h> 46 #include <unistd.h> 47 48 #include <keynote.h> 49 50 #include "smtpd.h" 51 52 __dead void usage(void); 53 void parent_shutdown(void); 54 void parent_send_config(int, short, void *); 55 void parent_dispatch_lka(int, short, void *); 56 void parent_dispatch_mda(int, short, void *); 57 void parent_dispatch_mfa(int, short, void *); 58 void parent_dispatch_smtp(int, short, void *); 59 void parent_dispatch_control(int, short, void *); 60 void parent_sig_handler(int, short, void *); 61 int parent_open_message_file(struct batch *); 62 int parent_mailbox_init(struct passwd *, char *); 63 int parent_mailbox_open(char *, struct passwd *, struct batch *); 64 int parent_filename_open(char *, struct passwd *, struct batch *); 65 int parent_mailfile_rename(struct batch *, struct path *); 66 int parent_maildir_open(char *, struct passwd *, struct batch *); 67 int parent_maildir_init(struct passwd *, char *); 68 int parent_external_mda(char *, struct passwd *, struct batch *); 69 int parent_forward_open(char *); 70 int check_child(pid_t, const char *); 71 int setup_spool(uid_t, gid_t); 72 73 extern char **environ; 74 75 pid_t lka_pid = 0; 76 pid_t mfa_pid = 0; 77 pid_t queue_pid = 0; 78 pid_t mda_pid = 0; 79 pid_t mta_pid = 0; 80 pid_t control_pid = 0; 81 pid_t smtp_pid = 0; 82 pid_t runner_pid = 0; 83 84 struct s_parent s_parent; 85 86 int __b64_pton(char const *, unsigned char *, size_t); 87 88 __dead void 89 usage(void) 90 { 91 extern char *__progname; 92 93 fprintf(stderr, "usage: %s [-dnv] [-D macro=value] " 94 "[-f file]\n", __progname); 95 exit(1); 96 } 97 98 void 99 parent_shutdown(void) 100 { 101 u_int i; 102 pid_t pid; 103 pid_t pids[] = { 104 lka_pid, 105 mfa_pid, 106 queue_pid, 107 mda_pid, 108 mta_pid, 109 control_pid, 110 smtp_pid, 111 runner_pid 112 }; 113 114 for (i = 0; i < sizeof(pids) / sizeof(pid); i++) 115 if (pids[i]) 116 kill(pids[i], SIGTERM); 117 118 do { 119 if ((pid = wait(NULL)) == -1 && 120 errno != EINTR && errno != ECHILD) 121 fatal("wait"); 122 } while (pid != -1 || (pid == -1 && errno == EINTR)); 123 124 log_info("terminating"); 125 exit(0); 126 } 127 128 void 129 parent_send_config(int fd, short event, void *p) 130 { 131 struct smtpd *env = p; 132 struct iovec iov[3]; 133 struct listener *l; 134 struct ssl *s; 135 136 log_debug("parent_send_config: configuring smtp"); 137 imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_CONF_START, 138 0, 0, -1, NULL, 0); 139 140 SPLAY_FOREACH(s, ssltree, &env->sc_ssl) { 141 iov[0].iov_base = s; 142 iov[0].iov_len = sizeof(*s); 143 iov[1].iov_base = s->ssl_cert; 144 iov[1].iov_len = s->ssl_cert_len; 145 iov[2].iov_base = s->ssl_key; 146 iov[2].iov_len = s->ssl_key_len; 147 148 imsg_composev(env->sc_ibufs[PROC_SMTP], IMSG_CONF_SSL, 0, 0, -1, 149 iov, sizeof(iov)/sizeof(iov[0])); 150 } 151 152 TAILQ_FOREACH(l, &env->sc_listeners, entry) { 153 smtp_listener_setup(env, l); 154 imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_CONF_LISTENER, 155 0, 0, l->fd, l, sizeof(*l)); 156 } 157 imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_CONF_END, 158 0, 0, -1, NULL, 0); 159 } 160 161 void 162 parent_dispatch_lka(int fd, short event, void *p) 163 { 164 struct smtpd *env = p; 165 struct imsgbuf *ibuf; 166 struct imsg imsg; 167 ssize_t n; 168 169 ibuf = env->sc_ibufs[PROC_LKA]; 170 switch (event) { 171 case EV_READ: 172 if ((n = imsg_read(ibuf)) == -1) 173 fatal("imsg_read_error"); 174 if (n == 0) { 175 /* this pipe is dead, so remove the event handler */ 176 event_del(&ibuf->ev); 177 event_loopexit(NULL); 178 return; 179 } 180 break; 181 case EV_WRITE: 182 if (msgbuf_write(&ibuf->w) == -1) 183 fatal("msgbuf_write"); 184 imsg_event_add(ibuf); 185 return; 186 default: 187 fatalx("unknown event"); 188 } 189 190 for (;;) { 191 if ((n = imsg_get(ibuf, &imsg)) == -1) 192 fatal("parent_dispatch_lka: imsg_read error"); 193 if (n == 0) 194 break; 195 196 switch (imsg.hdr.type) { 197 case IMSG_PARENT_FORWARD_OPEN: { 198 int ret; 199 struct forward_req *fwreq; 200 201 fwreq = imsg.data; 202 ret = parent_forward_open(fwreq->pw_name); 203 fwreq->status = 0; 204 if (ret == -1) { 205 if (errno == ENOENT) 206 fwreq->status = 1; 207 } 208 imsg_compose(ibuf, IMSG_PARENT_FORWARD_OPEN, 0, 0, ret, fwreq, sizeof(*fwreq)); 209 break; 210 } 211 default: 212 log_warnx("parent_dispatch_lka: got imsg %d", 213 imsg.hdr.type); 214 fatalx("parent_dispatch_lka: unexpected imsg"); 215 } 216 imsg_free(&imsg); 217 } 218 imsg_event_add(ibuf); 219 } 220 221 void 222 parent_dispatch_mfa(int fd, short event, void *p) 223 { 224 struct smtpd *env = p; 225 struct imsgbuf *ibuf; 226 struct imsg imsg; 227 ssize_t n; 228 229 ibuf = env->sc_ibufs[PROC_MFA]; 230 switch (event) { 231 case EV_READ: 232 if ((n = imsg_read(ibuf)) == -1) 233 fatal("imsg_read_error"); 234 if (n == 0) { 235 /* this pipe is dead, so remove the event handler */ 236 event_del(&ibuf->ev); 237 event_loopexit(NULL); 238 return; 239 } 240 break; 241 case EV_WRITE: 242 if (msgbuf_write(&ibuf->w) == -1) 243 fatal("msgbuf_write"); 244 imsg_event_add(ibuf); 245 return; 246 default: 247 fatalx("unknown event"); 248 } 249 250 for (;;) { 251 if ((n = imsg_get(ibuf, &imsg)) == -1) 252 fatal("parent_dispatch_lka: imsg_read error"); 253 if (n == 0) 254 break; 255 256 switch (imsg.hdr.type) { 257 default: 258 log_warnx("parent_dispatch_mfa: got imsg %d", 259 imsg.hdr.type); 260 fatalx("parent_dispatch_mfa: unexpected imsg"); 261 } 262 imsg_free(&imsg); 263 } 264 imsg_event_add(ibuf); 265 } 266 267 void 268 parent_dispatch_mda(int fd, short event, void *p) 269 { 270 struct smtpd *env = p; 271 struct imsgbuf *ibuf; 272 struct imsg imsg; 273 ssize_t n; 274 275 ibuf = env->sc_ibufs[PROC_MDA]; 276 switch (event) { 277 case EV_READ: 278 if ((n = imsg_read(ibuf)) == -1) 279 fatal("imsg_read_error"); 280 if (n == 0) { 281 /* this pipe is dead, so remove the event handler */ 282 event_del(&ibuf->ev); 283 event_loopexit(NULL); 284 return; 285 } 286 break; 287 case EV_WRITE: 288 if (msgbuf_write(&ibuf->w) == -1) 289 fatal("msgbuf_write"); 290 imsg_event_add(ibuf); 291 return; 292 default: 293 fatalx("unknown event"); 294 } 295 296 for (;;) { 297 if ((n = imsg_get(ibuf, &imsg)) == -1) 298 fatal("parent_dispatch_mda: imsg_read error"); 299 if (n == 0) 300 break; 301 302 switch (imsg.hdr.type) { 303 case IMSG_PARENT_MAILBOX_OPEN: { 304 struct batch *batchp; 305 struct path *path; 306 struct passwd *pw; 307 char *pw_name; 308 char *file; 309 u_int8_t i; 310 int desc; 311 struct action_handler { 312 enum action_type action; 313 int (*handler)(char *, struct passwd *, struct batch *); 314 } action_hdl_table[] = { 315 { A_MBOX, parent_mailbox_open }, 316 { A_MAILDIR, parent_maildir_open }, 317 { A_EXT, parent_external_mda }, 318 { A_FILENAME, parent_filename_open } 319 }; 320 321 batchp = imsg.data; 322 path = &batchp->message.recipient; 323 if (batchp->type & T_DAEMON_BATCH) { 324 path = &batchp->message.sender; 325 } 326 327 for (i = 0; i < sizeof(action_hdl_table) / sizeof(struct action_handler); ++i) 328 if (action_hdl_table[i].action == path->rule.r_action) 329 break; 330 if (i == sizeof(action_hdl_table) / sizeof(struct action_handler)) 331 fatalx("parent_dispatch_mda: unknown action"); 332 333 file = path->rule.r_value.path; 334 pw_name = path->pw_name; 335 if (path->rule.r_action == A_FILENAME) { 336 file = path->u.filename; 337 pw_name = SMTPD_USER; 338 } 339 340 errno = 0; 341 pw = safe_getpwnam(pw_name); 342 if (pw == NULL) { 343 if (errno) 344 batchp->message.status |= S_MESSAGE_TEMPFAILURE; 345 else 346 batchp->message.status |= S_MESSAGE_PERMFAILURE; 347 imsg_compose(ibuf, IMSG_MDA_MAILBOX_FILE, 0, 0, 348 -1, batchp, sizeof(struct batch)); 349 break; 350 } 351 352 if (setegid(pw->pw_gid) || seteuid(pw->pw_uid)) 353 fatal("privdrop failed"); 354 355 desc = action_hdl_table[i].handler(file, pw, batchp); 356 imsg_compose(ibuf, IMSG_MDA_MAILBOX_FILE, 0, 0, 357 desc, batchp, sizeof(struct batch)); 358 359 if (setegid(0) || seteuid(0)) 360 fatal("privdrop failed"); 361 362 break; 363 } 364 case IMSG_PARENT_MESSAGE_OPEN: { 365 struct batch *batchp; 366 int desc; 367 368 batchp = imsg.data; 369 desc = parent_open_message_file(batchp); 370 371 imsg_compose(ibuf, IMSG_MDA_MESSAGE_FILE, 0, 0, 372 desc, batchp, sizeof(struct batch)); 373 374 break; 375 } 376 case IMSG_PARENT_MAILBOX_RENAME: { 377 struct batch *batchp; 378 struct path *path; 379 struct passwd *pw; 380 381 batchp = imsg.data; 382 path = &batchp->message.recipient; 383 if (batchp->type & T_DAEMON_BATCH) { 384 path = &batchp->message.sender; 385 } 386 387 pw = safe_getpwnam(path->pw_name); 388 if (pw == NULL) 389 break; 390 391 if (seteuid(pw->pw_uid) == -1) 392 fatal("privdrop failed"); 393 394 parent_mailfile_rename(batchp, path); 395 396 if (seteuid(0) == -1) 397 fatal("privraise failed"); 398 399 break; 400 } 401 default: 402 log_warnx("parent_dispatch_mfa: got imsg %d", 403 imsg.hdr.type); 404 fatalx("parent_dispatch_mda: unexpected imsg"); 405 } 406 imsg_free(&imsg); 407 } 408 imsg_event_add(ibuf); 409 } 410 411 void 412 parent_dispatch_smtp(int fd, short event, void *p) 413 { 414 struct smtpd *env = p; 415 struct imsgbuf *ibuf; 416 struct imsg imsg; 417 ssize_t n; 418 419 ibuf = env->sc_ibufs[PROC_SMTP]; 420 switch (event) { 421 case EV_READ: 422 if ((n = imsg_read(ibuf)) == -1) 423 fatal("imsg_read_error"); 424 if (n == 0) { 425 /* this pipe is dead, so remove the event handler */ 426 event_del(&ibuf->ev); 427 event_loopexit(NULL); 428 return; 429 } 430 break; 431 case EV_WRITE: 432 if (msgbuf_write(&ibuf->w) == -1) 433 fatal("msgbuf_write"); 434 imsg_event_add(ibuf); 435 return; 436 default: 437 fatalx("unknown event"); 438 } 439 440 for (;;) { 441 if ((n = imsg_get(ibuf, &imsg)) == -1) 442 fatal("parent_dispatch_smtp: imsg_read error"); 443 if (n == 0) 444 break; 445 446 switch (imsg.hdr.type) { 447 case IMSG_PARENT_SEND_CONFIG: { 448 parent_send_config(-1, -1, env); 449 break; 450 } 451 case IMSG_PARENT_AUTHENTICATE: { 452 struct session_auth_req *req; 453 struct session_auth_reply reply; 454 char buf[1024]; 455 char *user; 456 char *pass; 457 int len; 458 459 req = (struct session_auth_req *)imsg.data; 460 461 reply.session_id = req->session_id; 462 reply.value = 0; 463 464 /* String is not NUL terminated, leave room. */ 465 if ((len = kn_decode_base64(req->buffer, buf, 466 sizeof(buf) - 1)) == -1) 467 goto out; 468 /* buf is a byte string, NUL terminate. */ 469 buf[len] = '\0'; 470 471 /* 472 * Skip "foo" in "foo\0user\0pass", if present. 473 */ 474 user = memchr(buf, '\0', len); 475 if (user == NULL || user >= buf + len - 2) 476 goto out; 477 user++; /* skip NUL */ 478 479 pass = memchr(user, '\0', len - (user - buf)); 480 if (pass == NULL || pass >= buf + len - 2) 481 goto out; 482 pass++; /* skip NUL */ 483 484 if (auth_userokay(user, NULL, "auth-smtp", pass)) 485 reply.value = 1; 486 487 out: 488 imsg_compose(ibuf, IMSG_PARENT_AUTHENTICATE, 0, 0, 489 -1, &reply, sizeof(reply)); 490 491 break; 492 } 493 default: 494 log_warnx("parent_dispatch_smtp: got imsg %d", 495 imsg.hdr.type); 496 fatalx("parent_dispatch_smtp: unexpected imsg"); 497 } 498 imsg_free(&imsg); 499 } 500 imsg_event_add(ibuf); 501 } 502 503 void 504 parent_dispatch_control(int sig, short event, void *p) 505 { 506 struct smtpd *env = p; 507 struct imsgbuf *ibuf; 508 struct imsg imsg; 509 ssize_t n; 510 511 ibuf = env->sc_ibufs[PROC_CONTROL]; 512 switch (event) { 513 case EV_READ: 514 if ((n = imsg_read(ibuf)) == -1) 515 fatal("imsg_read_error"); 516 if (n == 0) { 517 /* this pipe is dead, so remove the event handler */ 518 event_del(&ibuf->ev); 519 event_loopexit(NULL); 520 return; 521 } 522 break; 523 case EV_WRITE: 524 if (msgbuf_write(&ibuf->w) == -1) 525 fatal("msgbuf_write"); 526 imsg_event_add(ibuf); 527 return; 528 default: 529 fatalx("unknown event"); 530 } 531 532 for (;;) { 533 if ((n = imsg_get(ibuf, &imsg)) == -1) 534 fatal("parent_dispatch_control: imsg_read error"); 535 if (n == 0) 536 break; 537 538 switch (imsg.hdr.type) { 539 case IMSG_STATS: { 540 struct stats *s; 541 542 s = imsg.data; 543 s->u.parent = s_parent; 544 imsg_compose(ibuf, IMSG_STATS, 0, 0, -1, s, sizeof(*s)); 545 break; 546 } 547 default: 548 log_warnx("parent_dispatch_control: got imsg %d", 549 imsg.hdr.type); 550 fatalx("parent_dispatch_control: unexpected imsg"); 551 } 552 imsg_free(&imsg); 553 } 554 imsg_event_add(ibuf); 555 } 556 557 void 558 parent_sig_handler(int sig, short event, void *p) 559 { 560 int i; 561 int die = 0; 562 pid_t pid; 563 struct mdaproc *mdaproc; 564 struct mdaproc lookup; 565 struct smtpd *env = p; 566 struct { pid_t p; const char *s; } procs[] = { 567 { lka_pid, "lookup agent" }, 568 { mfa_pid, "mail filter agent" }, 569 { queue_pid, "mail queue" }, 570 { mda_pid, "mail delivery agent" }, 571 { mta_pid, "mail transfer agent" }, 572 { control_pid, "control process" }, 573 { smtp_pid, "smtp server" }, 574 { runner_pid, "runner" }, 575 { 0, NULL }, 576 }; 577 578 switch (sig) { 579 case SIGTERM: 580 case SIGINT: 581 die = 1; 582 /* FALLTHROUGH */ 583 case SIGCHLD: 584 for (i = 0; procs[i].s != NULL; i++) 585 if (check_child(procs[i].p, procs[i].s)) { 586 procs[i].p = 0; 587 die = 1; 588 } 589 if (die) 590 parent_shutdown(); 591 592 do { 593 int status; 594 595 pid = waitpid(-1, &status, WNOHANG); 596 if (pid > 0) { 597 lookup.pid = pid; 598 mdaproc = SPLAY_FIND(mdaproctree, &env->mdaproc_queue, &lookup); 599 if (mdaproc == NULL) 600 fatalx("unexpected SIGCHLD"); 601 602 if (WIFEXITED(status) && !WIFSIGNALED(status)) { 603 switch (WEXITSTATUS(status)) { 604 case EX_OK: 605 log_debug("DEBUG: external mda reported success"); 606 break; 607 case EX_TEMPFAIL: 608 log_debug("DEBUG: external mda reported temporary failure"); 609 break; 610 default: 611 log_warnx("external mda returned %d", WEXITSTATUS(status)); 612 } 613 } 614 else { 615 log_warnx("external mda terminated abnormally"); 616 } 617 618 SPLAY_REMOVE(mdaproctree, &env->mdaproc_queue, 619 mdaproc); 620 free(mdaproc); 621 } 622 } while (pid > 0 || (pid == -1 && errno == EINTR)); 623 624 break; 625 default: 626 fatalx("unexpected signal"); 627 } 628 } 629 630 int 631 main(int argc, char *argv[]) 632 { 633 int c; 634 int debug; 635 int opts; 636 const char *conffile = CONF_FILE; 637 struct smtpd env; 638 struct event ev_sigint; 639 struct event ev_sigterm; 640 struct event ev_sigchld; 641 struct event ev_sighup; 642 struct timeval tv; 643 struct rlimit rl; 644 struct peer peers[] = { 645 { PROC_CONTROL, parent_dispatch_control }, 646 { PROC_LKA, parent_dispatch_lka }, 647 { PROC_MDA, parent_dispatch_mda }, 648 { PROC_MFA, parent_dispatch_mfa }, 649 { PROC_SMTP, parent_dispatch_smtp }, 650 }; 651 652 opts = 0; 653 debug = 0; 654 655 log_init(1); 656 657 while ((c = getopt(argc, argv, "dD:nf:v")) != -1) { 658 switch (c) { 659 case 'd': 660 debug = 2; 661 break; 662 case 'D': 663 if (cmdline_symset(optarg) < 0) 664 log_warnx("could not parse macro definition %s", 665 optarg); 666 break; 667 case 'n': 668 debug = 2; 669 opts |= SMTPD_OPT_NOACTION; 670 break; 671 case 'f': 672 conffile = optarg; 673 break; 674 case 'v': 675 opts |= SMTPD_OPT_VERBOSE; 676 break; 677 default: 678 usage(); 679 } 680 } 681 682 argv += optind; 683 argc -= optind; 684 685 if (parse_config(&env, conffile, opts)) 686 exit(1); 687 688 if (env.sc_opts & SMTPD_OPT_NOACTION) { 689 fprintf(stderr, "configuration OK\n"); 690 exit(0); 691 } 692 693 /* check for root privileges */ 694 if (geteuid()) 695 errx(1, "need root privileges"); 696 697 if ((env.sc_pw = getpwnam(SMTPD_USER)) == NULL) 698 errx(1, "unknown user %s", SMTPD_USER); 699 endpwent(); 700 701 if (!setup_spool(env.sc_pw->pw_uid, 0)) 702 errx(1, "invalid directory permissions"); 703 704 log_init(debug); 705 706 if (!debug) 707 if (daemon(0, 0) == -1) 708 err(1, "failed to daemonize"); 709 710 log_info("startup%s", (debug > 1)?" [debug mode]":""); 711 712 if (getrlimit(RLIMIT_NOFILE, &rl) == -1) 713 fatal("smtpd: failed to get resource limit"); 714 715 log_debug("smtpd: max open files %lld", rl.rlim_max); 716 717 /* 718 * Allow the maximum number of open file descriptors for this 719 * login class (which should be the class "daemon" by default). 720 */ 721 rl.rlim_cur = rl.rlim_max; 722 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) 723 fatal("smtpd: failed to set resource limit"); 724 725 env.sc_maxconn = (rl.rlim_cur / 4) * 3; 726 log_debug("smtpd: will accept at most %d clients", env.sc_maxconn); 727 728 env.sc_instances[PROC_PARENT] = 1; 729 env.sc_instances[PROC_LKA] = 1; 730 env.sc_instances[PROC_MFA] = 1; 731 env.sc_instances[PROC_QUEUE] = 1; 732 env.sc_instances[PROC_MDA] = 1; 733 env.sc_instances[PROC_MTA] = 1; 734 env.sc_instances[PROC_SMTP] = 1; 735 env.sc_instances[PROC_CONTROL] = 1; 736 env.sc_instances[PROC_RUNNER] = 1; 737 738 init_peers(&env); 739 740 /* start subprocesses */ 741 lka_pid = lka(&env); 742 mfa_pid = mfa(&env); 743 queue_pid = queue(&env); 744 mda_pid = mda(&env); 745 mta_pid = mta(&env); 746 smtp_pid = smtp(&env); 747 control_pid = control(&env); 748 runner_pid = runner(&env); 749 750 setproctitle("parent"); 751 SPLAY_INIT(&env.mdaproc_queue); 752 753 s_parent.start = time(NULL); 754 755 event_init(); 756 757 signal_set(&ev_sigint, SIGINT, parent_sig_handler, &env); 758 signal_set(&ev_sigterm, SIGTERM, parent_sig_handler, &env); 759 signal_set(&ev_sigchld, SIGCHLD, parent_sig_handler, &env); 760 signal_set(&ev_sighup, SIGHUP, parent_sig_handler, &env); 761 signal_add(&ev_sigint, NULL); 762 signal_add(&ev_sigterm, NULL); 763 signal_add(&ev_sigchld, NULL); 764 signal_add(&ev_sighup, NULL); 765 signal(SIGPIPE, SIG_IGN); 766 767 config_pipes(&env, peers, 5); 768 config_peers(&env, peers, 5); 769 770 evtimer_set(&env.sc_ev, parent_send_config, &env); 771 bzero(&tv, sizeof(tv)); 772 evtimer_add(&env.sc_ev, &tv); 773 774 event_dispatch(); 775 776 return (0); 777 } 778 779 780 int 781 check_child(pid_t pid, const char *pname) 782 { 783 int status; 784 785 if (waitpid(pid, &status, WNOHANG) > 0) { 786 if (WIFEXITED(status)) { 787 log_warnx("check_child: lost child: %s exited", pname); 788 return (1); 789 } 790 if (WIFSIGNALED(status)) { 791 log_warnx("check_child: lost child: %s terminated; " 792 "signal %d", pname, WTERMSIG(status)); 793 return (1); 794 } 795 } 796 797 return (0); 798 } 799 800 int 801 setup_spool(uid_t uid, gid_t gid) 802 { 803 unsigned int n; 804 char *paths[] = { PATH_INCOMING, PATH_ENQUEUE, PATH_QUEUE, 805 PATH_RUNQUEUE, PATH_RUNQUEUELOW, 806 PATH_RUNQUEUEHIGH, PATH_PURGE }; 807 char pathname[MAXPATHLEN]; 808 struct stat sb; 809 int ret; 810 811 if (! bsnprintf(pathname, sizeof(pathname), "%s", PATH_SPOOL)) 812 fatal("snprintf"); 813 814 if (stat(pathname, &sb) == -1) { 815 if (errno != ENOENT) { 816 warn("stat: %s", pathname); 817 return 0; 818 } 819 820 if (mkdir(pathname, 0711) == -1) { 821 warn("mkdir: %s", pathname); 822 return 0; 823 } 824 825 if (chown(pathname, 0, 0) == -1) { 826 warn("chown: %s", pathname); 827 return 0; 828 } 829 830 if (stat(pathname, &sb) == -1) 831 err(1, "stat: %s", pathname); 832 } 833 834 /* check if it's a directory */ 835 if (!S_ISDIR(sb.st_mode)) { 836 warnx("%s is not a directory", pathname); 837 return 0; 838 } 839 840 /* check that it is owned by uid/gid */ 841 if (sb.st_uid != 0 || sb.st_gid != 0) { 842 warnx("%s must be owned by root:wheel", pathname); 843 return 0; 844 } 845 846 /* check permission */ 847 if ((sb.st_mode & (S_IRUSR|S_IWUSR|S_IXUSR)) != (S_IRUSR|S_IWUSR|S_IXUSR) || 848 (sb.st_mode & (S_IRGRP|S_IWGRP|S_IXGRP)) != S_IXGRP || 849 (sb.st_mode & (S_IROTH|S_IWOTH|S_IXOTH)) != S_IXOTH) { 850 warnx("%s must be rwx--x--x (0711)", pathname); 851 return 0; 852 } 853 854 ret = 1; 855 for (n = 0; n < sizeof(paths)/sizeof(paths[0]); n++) { 856 if (! bsnprintf(pathname, sizeof(pathname), "%s%s", PATH_SPOOL, 857 paths[n])) 858 fatal("snprintf"); 859 860 if (stat(pathname, &sb) == -1) { 861 if (errno != ENOENT) { 862 warn("stat: %s", pathname); 863 ret = 0; 864 continue; 865 } 866 867 if (mkdir(pathname, 0700) == -1) { 868 ret = 0; 869 warn("mkdir: %s", pathname); 870 } 871 872 if (chown(pathname, uid, gid) == -1) { 873 ret = 0; 874 warn("chown: %s", pathname); 875 } 876 877 if (stat(pathname, &sb) == -1) 878 err(1, "stat: %s", pathname); 879 } 880 881 /* check if it's a directory */ 882 if (!S_ISDIR(sb.st_mode)) { 883 ret = 0; 884 warnx("%s is not a directory", pathname); 885 } 886 887 /* check that it is owned by uid/gid */ 888 if (sb.st_uid != uid) { 889 ret = 0; 890 warnx("%s is not owned by uid %d", pathname, uid); 891 } 892 if (sb.st_gid != gid) { 893 ret = 0; 894 warnx("%s is not owned by gid %d", pathname, gid); 895 } 896 897 /* check permission */ 898 if ((sb.st_mode & (S_IRUSR|S_IWUSR|S_IXUSR)) != (S_IRUSR|S_IWUSR|S_IXUSR) || 899 (sb.st_mode & (S_IRGRP|S_IWGRP|S_IXGRP)) || 900 (sb.st_mode & (S_IROTH|S_IWOTH|S_IXOTH))) { 901 ret = 0; 902 warnx("%s must be rwx------ (0700)", pathname); 903 } 904 } 905 return ret; 906 } 907 908 void 909 imsg_event_add(struct imsgbuf *ibuf) 910 { 911 if (ibuf->handler == NULL) { 912 imsg_flush(ibuf); 913 return; 914 } 915 916 ibuf->events = EV_READ; 917 if (ibuf->w.queued) 918 ibuf->events |= EV_WRITE; 919 920 event_del(&ibuf->ev); 921 event_set(&ibuf->ev, ibuf->fd, ibuf->events, ibuf->handler, ibuf->data); 922 event_add(&ibuf->ev, NULL); 923 } 924 925 int 926 parent_open_message_file(struct batch *batchp) 927 { 928 int fd; 929 char pathname[MAXPATHLEN]; 930 u_int16_t hval; 931 struct message *messagep; 932 933 messagep = &batchp->message; 934 hval = queue_hash(messagep->message_id); 935 936 if (! bsnprintf(pathname, sizeof(pathname), "%s%s/%d/%s/message", 937 PATH_SPOOL, PATH_QUEUE, hval, batchp->message_id)) { 938 batchp->message.status |= S_MESSAGE_PERMFAILURE; 939 return -1; 940 } 941 942 fd = open(pathname, O_RDONLY); 943 return fd; 944 } 945 946 int 947 parent_mailbox_init(struct passwd *pw, char *pathname) 948 { 949 int fd; 950 int ret = 1; 951 int mode = O_CREAT|O_EXCL; 952 953 /* user cannot create mailbox */ 954 if (seteuid(0) == -1) 955 fatal("privraise failed"); 956 957 errno = 0; 958 fd = open(pathname, mode, 0600); 959 960 if (fd == -1) { 961 if (errno != EEXIST) 962 ret = 0; 963 } 964 965 if (fd != -1) { 966 if (fchown(fd, pw->pw_uid, 0) == -1) 967 fatal("fchown"); 968 close(fd); 969 } 970 971 if (seteuid(pw->pw_uid) == -1) 972 fatal("privdropfailed"); 973 974 return ret; 975 } 976 977 int 978 parent_mailbox_open(char *path, struct passwd *pw, struct batch *batchp) 979 { 980 pid_t pid; 981 int pipefd[2]; 982 struct mdaproc *mdaproc; 983 char sender[MAX_PATH_SIZE]; 984 985 /* This can never happen, but better safe than sorry. */ 986 if (! bsnprintf(sender, MAX_PATH_SIZE, "%s@%s", 987 batchp->message.sender.user, 988 batchp->message.sender.domain)) { 989 batchp->message.status |= S_MESSAGE_PERMFAILURE; 990 return -1; 991 } 992 993 if (! parent_mailbox_init(pw, path)) { 994 batchp->message.status |= S_MESSAGE_TEMPFAILURE; 995 return -1; 996 } 997 998 log_debug("executing mail.local"); 999 1000 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) == -1) { 1001 batchp->message.status |= S_MESSAGE_PERMFAILURE; 1002 return -1; 1003 } 1004 1005 /* raise privileges because mail.local needs root to 1006 * deliver to user mailboxes. 1007 */ 1008 if (seteuid(0) == -1) 1009 fatal("privraise failed"); 1010 1011 pid = fork(); 1012 if (pid == -1) { 1013 close(pipefd[0]); 1014 close(pipefd[1]); 1015 batchp->message.status |= S_MESSAGE_PERMFAILURE; 1016 return -1; 1017 } 1018 1019 if (pid == 0) { 1020 setproctitle("mail.local"); 1021 1022 close(pipefd[0]); 1023 close(STDOUT_FILENO); 1024 close(STDERR_FILENO); 1025 dup2(pipefd[1], 0); 1026 1027 execlp(PATH_MAILLOCAL, "mail.local", "-f", sender, pw->pw_name, (void *)NULL); 1028 _exit(1); 1029 } 1030 1031 if (seteuid(pw->pw_uid) == -1) 1032 fatal("privdrop failed"); 1033 1034 mdaproc = calloc(1, sizeof (struct mdaproc)); 1035 if (mdaproc == NULL) 1036 fatal("calloc"); 1037 mdaproc->pid = pid; 1038 1039 SPLAY_INSERT(mdaproctree, &batchp->env->mdaproc_queue, mdaproc); 1040 1041 close(pipefd[1]); 1042 return pipefd[0]; 1043 } 1044 1045 int 1046 parent_maildir_init(struct passwd *pw, char *root) 1047 { 1048 u_int8_t i; 1049 char pathname[MAXPATHLEN]; 1050 char *subdir[] = { "/", "/tmp", "/cur", "/new" }; 1051 1052 for (i = 0; i < sizeof (subdir) / sizeof (char *); ++i) { 1053 if (! bsnprintf(pathname, sizeof(pathname), "%s%s", root, 1054 subdir[i])) 1055 return 0; 1056 if (mkdir(pathname, 0700) == -1) 1057 if (errno != EEXIST) 1058 return 0; 1059 } 1060 1061 return 1; 1062 } 1063 1064 int 1065 parent_maildir_open(char *path, struct passwd *pw, struct batch *batchp) 1066 { 1067 int fd; 1068 char tmp[MAXPATHLEN]; 1069 int mode = O_CREAT|O_RDWR|O_TRUNC|O_SYNC; 1070 1071 if (! parent_maildir_init(pw, path)) { 1072 batchp->message.status |= S_MESSAGE_TEMPFAILURE; 1073 return -1; 1074 } 1075 1076 if (! bsnprintf(tmp, sizeof(tmp), "%s/tmp/%s", path, 1077 batchp->message.message_uid)) { 1078 batchp->message.status |= S_MESSAGE_TEMPFAILURE; 1079 return -1; 1080 } 1081 1082 fd = open(tmp, mode, 0600); 1083 if (fd == -1) { 1084 batchp->message.status |= S_MESSAGE_TEMPFAILURE; 1085 return -1; 1086 } 1087 1088 return fd; 1089 } 1090 1091 int 1092 parent_mailfile_rename(struct batch *batchp, struct path *path) 1093 { 1094 char srcpath[MAXPATHLEN]; 1095 char dstpath[MAXPATHLEN]; 1096 1097 if (! bsnprintf(srcpath, sizeof(srcpath), "%s/tmp/%s", 1098 path->rule.r_value.path, batchp->message.message_uid) || 1099 ! bsnprintf(dstpath, sizeof(dstpath), "%s/new/%s", 1100 path->rule.r_value.path, batchp->message.message_uid)) 1101 return 0; 1102 1103 if (rename(srcpath, dstpath) == -1) { 1104 if (unlink(srcpath) == -1) 1105 fatal("unlink"); 1106 batchp->message.status |= S_MESSAGE_TEMPFAILURE; 1107 return 0; 1108 } 1109 1110 return 1; 1111 } 1112 1113 int 1114 parent_external_mda(char *path, struct passwd *pw, struct batch *batchp) 1115 { 1116 pid_t pid; 1117 int pipefd[2]; 1118 arglist args; 1119 char *word; 1120 struct mdaproc *mdaproc; 1121 char *envp[2]; 1122 1123 log_debug("executing filter as user: %s", pw->pw_name); 1124 1125 if (pipe(pipefd) == -1) { 1126 if (errno == ENFILE) { 1127 log_warn("parent_external_mda: pipe"); 1128 batchp->message.status |= S_MESSAGE_TEMPFAILURE; 1129 return -1; 1130 } 1131 fatal("parent_external_mda: pipe"); 1132 } 1133 1134 pid = fork(); 1135 if (pid == -1) { 1136 log_warn("parent_external_mda: fork"); 1137 close(pipefd[0]); 1138 close(pipefd[1]); 1139 batchp->message.status |= S_MESSAGE_TEMPFAILURE; 1140 return -1; 1141 } 1142 1143 if (pid == 0) { 1144 setproctitle("external MDA"); 1145 1146 if (seteuid(0) == -1) 1147 fatal("privraise failed"); 1148 if (setgroups(1, &pw->pw_gid) || 1149 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 1150 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 1151 fatal("cannot drop privileges"); 1152 1153 bzero(&args, sizeof(args)); 1154 while ((word = strsep(&path, " \t")) != NULL) 1155 if (*word != '\0') 1156 addargs(&args, "%s", word); 1157 1158 if (setsid() == -1) 1159 fatal("setsid"); 1160 1161 if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) 1162 fatal("signal"); 1163 1164 if (dup2(pipefd[0], STDIN_FILENO) == -1) 1165 fatal("dup2"); 1166 1167 if (chdir(pw->pw_dir) == -1 && chdir("/") == -1) 1168 fatal("chdir"); 1169 1170 if (closefrom(STDERR_FILENO + 1) == -1) 1171 fatal("closefrom"); 1172 1173 envp[0] = "PATH=" _PATH_DEFPATH; 1174 envp[1] = (char *)NULL; 1175 environ = envp; 1176 1177 execvp(args.list[0], args.list); 1178 _exit(1); 1179 } 1180 1181 mdaproc = calloc(1, sizeof (struct mdaproc)); 1182 if (mdaproc == NULL) 1183 fatal("calloc"); 1184 mdaproc->pid = pid; 1185 1186 SPLAY_INSERT(mdaproctree, &batchp->env->mdaproc_queue, mdaproc); 1187 1188 close(pipefd[0]); 1189 return pipefd[1]; 1190 } 1191 1192 int 1193 parent_filename_open(char *path, struct passwd *pw, struct batch *batchp) 1194 { 1195 int fd; 1196 int mode = O_CREAT|O_APPEND|O_RDWR|O_SYNC|O_NONBLOCK; 1197 1198 fd = open(path, mode, 0600); 1199 if (fd == -1) { 1200 /* XXX - this needs to be discussed ... */ 1201 switch (errno) { 1202 case ENOTDIR: 1203 case ENOENT: 1204 case EACCES: 1205 case ELOOP: 1206 case EROFS: 1207 case EDQUOT: 1208 case EINTR: 1209 case EIO: 1210 case EMFILE: 1211 case ENFILE: 1212 case ENOSPC: 1213 batchp->message.status |= S_MESSAGE_TEMPFAILURE; 1214 break; 1215 case EWOULDBLOCK: 1216 goto lockfail; 1217 default: 1218 batchp->message.status |= S_MESSAGE_PERMFAILURE; 1219 } 1220 return -1; 1221 } 1222 1223 if (flock(fd, LOCK_EX|LOCK_NB) == -1) { 1224 if (errno == EWOULDBLOCK) 1225 goto lockfail; 1226 fatal("flock"); 1227 } 1228 1229 return fd; 1230 1231 lockfail: 1232 if (fd != -1) 1233 close(fd); 1234 1235 batchp->message.status |= S_MESSAGE_TEMPFAILURE|S_MESSAGE_LOCKFAILURE; 1236 return -1; 1237 } 1238 1239 int 1240 parent_forward_open(char *username) 1241 { 1242 struct passwd *pw; 1243 struct stat sb; 1244 char pathname[MAXPATHLEN]; 1245 int fd; 1246 1247 pw = safe_getpwnam(username); 1248 if (pw == NULL) 1249 return -1; 1250 1251 if (! bsnprintf(pathname, sizeof (pathname), "%s/.forward", pw->pw_dir)) 1252 return -1; 1253 1254 fd = open(pathname, O_RDONLY); 1255 if (fd == -1) { 1256 if (errno == ENOENT) 1257 goto err; 1258 return -1; 1259 } 1260 1261 /* make sure ~/ is not writable by anyone but owner */ 1262 if (stat(pw->pw_dir, &sb) == -1) 1263 goto errlog; 1264 1265 if (sb.st_uid != pw->pw_uid || sb.st_mode & (S_IWGRP|S_IWOTH)) 1266 goto errlog; 1267 1268 /* make sure ~/.forward is not writable by anyone but owner */ 1269 if (fstat(fd, &sb) == -1) 1270 goto errlog; 1271 1272 if (sb.st_uid != pw->pw_uid || sb.st_mode & (S_IWGRP|S_IWOTH)) 1273 goto errlog; 1274 1275 return fd; 1276 1277 errlog: 1278 log_info("cannot process forward file for user %s due to wrong permissions", username); 1279 1280 err: 1281 return -1; 1282 } 1283 1284 int 1285 mdaproc_cmp(struct mdaproc *s1, struct mdaproc *s2) 1286 { 1287 if (s1->pid < s2->pid) 1288 return (-1); 1289 1290 if (s1->pid > s2->pid) 1291 return (1); 1292 1293 return (0); 1294 } 1295 1296 SPLAY_GENERATE(mdaproctree, mdaproc, mdaproc_nodes, mdaproc_cmp); 1297