1 /* $OpenBSD: dispatcher.c,v 1.1 2020/12/31 08:27:15 martijn Exp $ */ 2 3 /* 4 * Copyright (c) 2014 Gilles Chehade <gilles@poolp.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/queue.h> 21 #include <sys/tree.h> 22 #include <sys/socket.h> 23 24 #include <ctype.h> 25 #include <err.h> 26 #include <errno.h> 27 #include <event.h> 28 #include <imsg.h> 29 #include <inttypes.h> 30 #include <pwd.h> 31 #include <signal.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <time.h> 36 #include <unistd.h> 37 #include <limits.h> 38 #include <grp.h> 39 40 #include "smtpd.h" 41 #include "log.h" 42 43 void mda_imsg(struct mproc *, struct imsg *); 44 void mta_imsg(struct mproc *, struct imsg *); 45 void smtp_imsg(struct mproc *, struct imsg *); 46 47 static void dispatcher_shutdown(void); 48 49 void 50 dispatcher_imsg(struct mproc *p, struct imsg *imsg) 51 { 52 struct msg m; 53 int v; 54 55 if (imsg == NULL) 56 dispatcher_shutdown(); 57 58 switch (imsg->hdr.type) { 59 60 case IMSG_GETADDRINFO: 61 case IMSG_GETADDRINFO_END: 62 case IMSG_GETNAMEINFO: 63 case IMSG_RES_QUERY: 64 resolver_dispatch_result(p, imsg); 65 return; 66 67 case IMSG_CERT_INIT: 68 case IMSG_CERT_VERIFY: 69 cert_dispatch_result(p, imsg); 70 return; 71 72 case IMSG_CONF_START: 73 return; 74 case IMSG_CONF_END: 75 smtp_configure(); 76 return; 77 case IMSG_CTL_VERBOSE: 78 m_msg(&m, imsg); 79 m_get_int(&m, &v); 80 m_end(&m); 81 log_trace_verbose(v); 82 return; 83 case IMSG_CTL_PROFILE: 84 m_msg(&m, imsg); 85 m_get_int(&m, &v); 86 m_end(&m); 87 profiling = v; 88 return; 89 90 /* smtp imsg */ 91 case IMSG_SMTP_CHECK_SENDER: 92 case IMSG_SMTP_EXPAND_RCPT: 93 case IMSG_SMTP_LOOKUP_HELO: 94 case IMSG_SMTP_AUTHENTICATE: 95 case IMSG_SMTP_MESSAGE_COMMIT: 96 case IMSG_SMTP_MESSAGE_CREATE: 97 case IMSG_SMTP_MESSAGE_OPEN: 98 case IMSG_FILTER_SMTP_PROTOCOL: 99 case IMSG_FILTER_SMTP_DATA_BEGIN: 100 case IMSG_QUEUE_ENVELOPE_SUBMIT: 101 case IMSG_QUEUE_ENVELOPE_COMMIT: 102 case IMSG_QUEUE_SMTP_SESSION: 103 case IMSG_CTL_SMTP_SESSION: 104 case IMSG_CTL_PAUSE_SMTP: 105 case IMSG_CTL_RESUME_SMTP: 106 smtp_imsg(p, imsg); 107 return; 108 109 /* mta imsg */ 110 case IMSG_QUEUE_TRANSFER: 111 case IMSG_MTA_OPEN_MESSAGE: 112 case IMSG_MTA_LOOKUP_CREDENTIALS: 113 case IMSG_MTA_LOOKUP_SMARTHOST: 114 case IMSG_MTA_LOOKUP_SOURCE: 115 case IMSG_MTA_LOOKUP_HELO: 116 case IMSG_MTA_DNS_HOST: 117 case IMSG_MTA_DNS_HOST_END: 118 case IMSG_MTA_DNS_MX_PREFERENCE: 119 case IMSG_CTL_RESUME_ROUTE: 120 case IMSG_CTL_MTA_SHOW_HOSTS: 121 case IMSG_CTL_MTA_SHOW_RELAYS: 122 case IMSG_CTL_MTA_SHOW_ROUTES: 123 case IMSG_CTL_MTA_SHOW_HOSTSTATS: 124 case IMSG_CTL_MTA_BLOCK: 125 case IMSG_CTL_MTA_UNBLOCK: 126 case IMSG_CTL_MTA_SHOW_BLOCK: 127 mta_imsg(p, imsg); 128 return; 129 130 /* mda imsg */ 131 case IMSG_MDA_LOOKUP_USERINFO: 132 case IMSG_QUEUE_DELIVER: 133 case IMSG_MDA_OPEN_MESSAGE: 134 case IMSG_MDA_FORK: 135 case IMSG_MDA_DONE: 136 mda_imsg(p, imsg); 137 return; 138 default: 139 break; 140 } 141 142 errx(1, "session_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); 143 } 144 145 static void 146 dispatcher_shutdown(void) 147 { 148 log_debug("debug: dispatcher agent exiting"); 149 _exit(0); 150 } 151 152 int 153 dispatcher(void) 154 { 155 struct passwd *pw; 156 157 mda_postfork(); 158 mta_postfork(); 159 smtp_postfork(); 160 161 /* do not purge listeners and pki, they are purged 162 * in smtp_configure() 163 */ 164 purge_config(PURGE_TABLES|PURGE_RULES); 165 166 if ((pw = getpwnam(SMTPD_USER)) == NULL) 167 fatalx("unknown user " SMTPD_USER); 168 169 if (chroot(PATH_CHROOT) == -1) 170 fatal("dispatcher: chroot"); 171 if (chdir("/") == -1) 172 fatal("dispatcher: chdir(\"/\")"); 173 174 config_process(PROC_DISPATCHER); 175 176 if (setgroups(1, &pw->pw_gid) || 177 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 178 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 179 fatal("dispatcher: cannot drop privileges"); 180 181 imsg_callback = dispatcher_imsg; 182 event_init(); 183 184 mda_postprivdrop(); 185 mta_postprivdrop(); 186 smtp_postprivdrop(); 187 188 signal(SIGINT, SIG_IGN); 189 signal(SIGTERM, SIG_IGN); 190 signal(SIGPIPE, SIG_IGN); 191 signal(SIGHUP, SIG_IGN); 192 193 config_peer(PROC_PARENT); 194 config_peer(PROC_QUEUE); 195 config_peer(PROC_LKA); 196 config_peer(PROC_CONTROL); 197 config_peer(PROC_CA); 198 199 ca_engine_init(); 200 201 if (pledge("stdio inet unix recvfd sendfd", NULL) == -1) 202 err(1, "pledge"); 203 204 event_dispatch(); 205 fatalx("exited event loop"); 206 207 return (0); 208 } 209