1 /* $OpenBSD: mta.c,v 1.132 2012/05/11 12:12:02 eric Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> 5 * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> 6 * Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net> 7 * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include <sys/types.h> 23 #include <sys/queue.h> 24 #include <sys/tree.h> 25 #include <sys/param.h> 26 #include <sys/socket.h> 27 28 #include <ctype.h> 29 #include <err.h> 30 #include <errno.h> 31 #include <event.h> 32 #include <imsg.h> 33 #include <inttypes.h> 34 #include <netdb.h> 35 #include <pwd.h> 36 #include <signal.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <time.h> 41 #include <unistd.h> 42 43 #include "smtpd.h" 44 #include "log.h" 45 46 static void mta_imsg(struct imsgev *, struct imsg *); 47 static void mta_shutdown(void); 48 static void mta_sig_handler(int, short, void *); 49 50 static void 51 mta_imsg(struct imsgev *iev, struct imsg *imsg) 52 { 53 struct ssl *ssl; 54 55 log_imsg(PROC_MTA, iev->proc, imsg); 56 57 if (iev->proc == PROC_QUEUE) { 58 switch (imsg->hdr.type) { 59 case IMSG_BATCH_CREATE: 60 case IMSG_BATCH_APPEND: 61 case IMSG_BATCH_CLOSE: 62 case IMSG_QUEUE_MESSAGE_FD: 63 mta_session_imsg(iev, imsg); 64 return; 65 } 66 } 67 68 if (iev->proc == PROC_LKA) { 69 switch (imsg->hdr.type) { 70 case IMSG_LKA_SECRET: 71 case IMSG_DNS_HOST: 72 case IMSG_DNS_HOST_END: 73 case IMSG_DNS_PTR: 74 mta_session_imsg(iev, imsg); 75 return; 76 } 77 } 78 79 if (iev->proc == PROC_PARENT) { 80 switch (imsg->hdr.type) { 81 case IMSG_CONF_START: 82 if (env->sc_flags & SMTPD_CONFIGURING) 83 return; 84 env->sc_flags |= SMTPD_CONFIGURING; 85 env->sc_ssl = calloc(1, sizeof *env->sc_ssl); 86 if (env->sc_ssl == NULL) 87 fatal(NULL); 88 return; 89 90 case IMSG_CONF_SSL: 91 if (!(env->sc_flags & SMTPD_CONFIGURING)) 92 return; 93 ssl = calloc(1, sizeof *ssl); 94 if (ssl == NULL) 95 fatal(NULL); 96 *ssl = *(struct ssl *)imsg->data; 97 ssl->ssl_cert = strdup((char *)imsg->data + 98 sizeof *ssl); 99 if (ssl->ssl_cert == NULL) 100 fatal(NULL); 101 ssl->ssl_key = strdup((char *)imsg->data + 102 sizeof *ssl + ssl->ssl_cert_len); 103 if (ssl->ssl_key == NULL) 104 fatal(NULL); 105 SPLAY_INSERT(ssltree, env->sc_ssl, ssl); 106 return; 107 108 case IMSG_CONF_END: 109 if (!(env->sc_flags & SMTPD_CONFIGURING)) 110 return; 111 env->sc_flags &= ~SMTPD_CONFIGURING; 112 return; 113 114 case IMSG_CTL_VERBOSE: 115 log_verbose(*(int *)imsg->data); 116 return; 117 } 118 } 119 120 errx(1, "mta_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); 121 } 122 123 static void 124 mta_sig_handler(int sig, short event, void *p) 125 { 126 switch (sig) { 127 case SIGINT: 128 case SIGTERM: 129 mta_shutdown(); 130 break; 131 default: 132 fatalx("mta_sig_handler: unexpected signal"); 133 } 134 } 135 136 static void 137 mta_shutdown(void) 138 { 139 log_info("mail transfer agent exiting"); 140 _exit(0); 141 } 142 143 pid_t 144 mta(void) 145 { 146 pid_t pid; 147 148 struct passwd *pw; 149 struct event ev_sigint; 150 struct event ev_sigterm; 151 152 struct peer peers[] = { 153 { PROC_PARENT, imsg_dispatch }, 154 { PROC_QUEUE, imsg_dispatch }, 155 { PROC_LKA, imsg_dispatch } 156 }; 157 158 switch (pid = fork()) { 159 case -1: 160 fatal("mta: cannot fork"); 161 case 0: 162 break; 163 default: 164 return (pid); 165 } 166 167 ssl_init(); 168 purge_config(PURGE_EVERYTHING); 169 170 pw = env->sc_pw; 171 if (chroot(pw->pw_dir) == -1) 172 fatal("mta: chroot"); 173 if (chdir("/") == -1) 174 fatal("mta: chdir(\"/\")"); 175 176 smtpd_process = PROC_MTA; 177 setproctitle("%s", env->sc_title[smtpd_process]); 178 179 if (setgroups(1, &pw->pw_gid) || 180 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 181 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 182 fatal("mta: cannot drop privileges"); 183 184 imsg_callback = mta_imsg; 185 event_init(); 186 187 signal_set(&ev_sigint, SIGINT, mta_sig_handler, NULL); 188 signal_set(&ev_sigterm, SIGTERM, mta_sig_handler, NULL); 189 signal_add(&ev_sigint, NULL); 190 signal_add(&ev_sigterm, NULL); 191 signal(SIGPIPE, SIG_IGN); 192 signal(SIGHUP, SIG_IGN); 193 194 config_pipes(peers, nitems(peers)); 195 config_peers(peers, nitems(peers)); 196 197 SPLAY_INIT(&env->mta_sessions); 198 199 if (event_dispatch() < 0) 200 fatal("event_dispatch"); 201 mta_shutdown(); 202 203 return (0); 204 } 205