dispatcher.c revision 1.5
1/* $OpenBSD: dispatcher.c,v 1.5 2021/06/14 17:58:15 eric 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 <pwd.h> 20#include <signal.h> 21#include <unistd.h> 22 23#include "smtpd.h" 24#include "log.h" 25 26void mda_imsg(struct mproc *, struct imsg *); 27void mta_imsg(struct mproc *, struct imsg *); 28void smtp_imsg(struct mproc *, struct imsg *); 29 30static void dispatcher_shutdown(void); 31 32void 33dispatcher_imsg(struct mproc *p, struct imsg *imsg) 34{ 35 struct msg m; 36 int v; 37 38 if (imsg == NULL) 39 dispatcher_shutdown(); 40 41 switch (imsg->hdr.type) { 42 43 case IMSG_GETADDRINFO: 44 case IMSG_GETADDRINFO_END: 45 case IMSG_GETNAMEINFO: 46 case IMSG_RES_QUERY: 47 resolver_dispatch_result(p, imsg); 48 return; 49 50 case IMSG_CONF_START: 51 return; 52 case IMSG_CONF_END: 53 smtp_configure(); 54 return; 55 case IMSG_CTL_VERBOSE: 56 m_msg(&m, imsg); 57 m_get_int(&m, &v); 58 m_end(&m); 59 log_trace_verbose(v); 60 return; 61 case IMSG_CTL_PROFILE: 62 m_msg(&m, imsg); 63 m_get_int(&m, &v); 64 m_end(&m); 65 profiling = v; 66 return; 67 68 /* smtp imsg */ 69 case IMSG_SMTP_CHECK_SENDER: 70 case IMSG_SMTP_EXPAND_RCPT: 71 case IMSG_SMTP_LOOKUP_HELO: 72 case IMSG_SMTP_AUTHENTICATE: 73 case IMSG_SMTP_MESSAGE_COMMIT: 74 case IMSG_SMTP_MESSAGE_CREATE: 75 case IMSG_SMTP_MESSAGE_OPEN: 76 case IMSG_FILTER_SMTP_PROTOCOL: 77 case IMSG_FILTER_SMTP_DATA_BEGIN: 78 case IMSG_QUEUE_ENVELOPE_SUBMIT: 79 case IMSG_QUEUE_ENVELOPE_COMMIT: 80 case IMSG_QUEUE_SMTP_SESSION: 81 case IMSG_CTL_SMTP_SESSION: 82 case IMSG_CTL_PAUSE_SMTP: 83 case IMSG_CTL_RESUME_SMTP: 84 smtp_imsg(p, imsg); 85 return; 86 87 /* mta imsg */ 88 case IMSG_QUEUE_TRANSFER: 89 case IMSG_MTA_OPEN_MESSAGE: 90 case IMSG_MTA_LOOKUP_CREDENTIALS: 91 case IMSG_MTA_LOOKUP_SMARTHOST: 92 case IMSG_MTA_LOOKUP_SOURCE: 93 case IMSG_MTA_LOOKUP_HELO: 94 case IMSG_MTA_DNS_HOST: 95 case IMSG_MTA_DNS_HOST_END: 96 case IMSG_MTA_DNS_MX_PREFERENCE: 97 case IMSG_CTL_RESUME_ROUTE: 98 case IMSG_CTL_MTA_SHOW_HOSTS: 99 case IMSG_CTL_MTA_SHOW_RELAYS: 100 case IMSG_CTL_MTA_SHOW_ROUTES: 101 case IMSG_CTL_MTA_SHOW_HOSTSTATS: 102 case IMSG_CTL_MTA_BLOCK: 103 case IMSG_CTL_MTA_UNBLOCK: 104 case IMSG_CTL_MTA_SHOW_BLOCK: 105 mta_imsg(p, imsg); 106 return; 107 108 /* mda imsg */ 109 case IMSG_MDA_LOOKUP_USERINFO: 110 case IMSG_QUEUE_DELIVER: 111 case IMSG_MDA_OPEN_MESSAGE: 112 case IMSG_MDA_FORK: 113 case IMSG_MDA_DONE: 114 mda_imsg(p, imsg); 115 return; 116 default: 117 break; 118 } 119 120 fatalx("session_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); 121} 122 123static void 124dispatcher_shutdown(void) 125{ 126 log_debug("debug: dispatcher agent exiting"); 127 _exit(0); 128} 129 130int 131dispatcher(void) 132{ 133 struct passwd *pw; 134 135 ca_engine_init(); 136 137 mda_postfork(); 138 mta_postfork(); 139 smtp_postfork(); 140 141 /* do not purge listeners and pki, they are purged 142 * in smtp_configure() 143 */ 144 purge_config(PURGE_TABLES|PURGE_RULES); 145 146 if ((pw = getpwnam(SMTPD_USER)) == NULL) 147 fatalx("unknown user " SMTPD_USER); 148 149 if (chroot(PATH_CHROOT) == -1) 150 fatal("dispatcher: chroot"); 151 if (chdir("/") == -1) 152 fatal("dispatcher: chdir(\"/\")"); 153 154 config_process(PROC_DISPATCHER); 155 156 if (setgroups(1, &pw->pw_gid) || 157 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 158 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 159 fatal("dispatcher: cannot drop privileges"); 160 161 imsg_callback = dispatcher_imsg; 162 event_init(); 163 164 mda_postprivdrop(); 165 mta_postprivdrop(); 166 smtp_postprivdrop(); 167 168 signal(SIGINT, SIG_IGN); 169 signal(SIGTERM, SIG_IGN); 170 signal(SIGPIPE, SIG_IGN); 171 signal(SIGHUP, SIG_IGN); 172 173 config_peer(PROC_PARENT); 174 config_peer(PROC_QUEUE); 175 config_peer(PROC_LKA); 176 config_peer(PROC_CONTROL); 177 config_peer(PROC_CA); 178 179 if (pledge("stdio inet unix recvfd sendfd", NULL) == -1) 180 fatal("pledge"); 181 182 event_dispatch(); 183 fatalx("exited event loop"); 184 185 return (0); 186} 187