dispatcher.c revision 1.3
1/* $OpenBSD: dispatcher.c,v 1.3 2021/04/21 07:54:10 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 <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 43void mda_imsg(struct mproc *, struct imsg *); 44void mta_imsg(struct mproc *, struct imsg *); 45void smtp_imsg(struct mproc *, struct imsg *); 46 47static void dispatcher_shutdown(void); 48 49void 50dispatcher_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_CONF_START: 68 return; 69 case IMSG_CONF_END: 70 smtp_configure(); 71 return; 72 case IMSG_CTL_VERBOSE: 73 m_msg(&m, imsg); 74 m_get_int(&m, &v); 75 m_end(&m); 76 log_trace_verbose(v); 77 return; 78 case IMSG_CTL_PROFILE: 79 m_msg(&m, imsg); 80 m_get_int(&m, &v); 81 m_end(&m); 82 profiling = v; 83 return; 84 85 /* smtp imsg */ 86 case IMSG_SMTP_CHECK_SENDER: 87 case IMSG_SMTP_EXPAND_RCPT: 88 case IMSG_SMTP_LOOKUP_HELO: 89 case IMSG_SMTP_AUTHENTICATE: 90 case IMSG_SMTP_MESSAGE_COMMIT: 91 case IMSG_SMTP_MESSAGE_CREATE: 92 case IMSG_SMTP_MESSAGE_OPEN: 93 case IMSG_FILTER_SMTP_PROTOCOL: 94 case IMSG_FILTER_SMTP_DATA_BEGIN: 95 case IMSG_QUEUE_ENVELOPE_SUBMIT: 96 case IMSG_QUEUE_ENVELOPE_COMMIT: 97 case IMSG_QUEUE_SMTP_SESSION: 98 case IMSG_CTL_SMTP_SESSION: 99 case IMSG_CTL_PAUSE_SMTP: 100 case IMSG_CTL_RESUME_SMTP: 101 smtp_imsg(p, imsg); 102 return; 103 104 /* mta imsg */ 105 case IMSG_QUEUE_TRANSFER: 106 case IMSG_MTA_OPEN_MESSAGE: 107 case IMSG_MTA_LOOKUP_CREDENTIALS: 108 case IMSG_MTA_LOOKUP_SMARTHOST: 109 case IMSG_MTA_LOOKUP_SOURCE: 110 case IMSG_MTA_LOOKUP_HELO: 111 case IMSG_MTA_DNS_HOST: 112 case IMSG_MTA_DNS_HOST_END: 113 case IMSG_MTA_DNS_MX_PREFERENCE: 114 case IMSG_CTL_RESUME_ROUTE: 115 case IMSG_CTL_MTA_SHOW_HOSTS: 116 case IMSG_CTL_MTA_SHOW_RELAYS: 117 case IMSG_CTL_MTA_SHOW_ROUTES: 118 case IMSG_CTL_MTA_SHOW_HOSTSTATS: 119 case IMSG_CTL_MTA_BLOCK: 120 case IMSG_CTL_MTA_UNBLOCK: 121 case IMSG_CTL_MTA_SHOW_BLOCK: 122 mta_imsg(p, imsg); 123 return; 124 125 /* mda imsg */ 126 case IMSG_MDA_LOOKUP_USERINFO: 127 case IMSG_QUEUE_DELIVER: 128 case IMSG_MDA_OPEN_MESSAGE: 129 case IMSG_MDA_FORK: 130 case IMSG_MDA_DONE: 131 mda_imsg(p, imsg); 132 return; 133 default: 134 break; 135 } 136 137 errx(1, "session_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); 138} 139 140static void 141dispatcher_shutdown(void) 142{ 143 log_debug("debug: dispatcher agent exiting"); 144 _exit(0); 145} 146 147int 148dispatcher(void) 149{ 150 struct passwd *pw; 151 152 ca_engine_init(); 153 154 mda_postfork(); 155 mta_postfork(); 156 smtp_postfork(); 157 158 /* do not purge listeners and pki, they are purged 159 * in smtp_configure() 160 */ 161 purge_config(PURGE_TABLES|PURGE_RULES); 162 163 if ((pw = getpwnam(SMTPD_USER)) == NULL) 164 fatalx("unknown user " SMTPD_USER); 165 166 if (chroot(PATH_CHROOT) == -1) 167 fatal("dispatcher: chroot"); 168 if (chdir("/") == -1) 169 fatal("dispatcher: chdir(\"/\")"); 170 171 config_process(PROC_DISPATCHER); 172 173 if (setgroups(1, &pw->pw_gid) || 174 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 175 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 176 fatal("dispatcher: cannot drop privileges"); 177 178 imsg_callback = dispatcher_imsg; 179 event_init(); 180 181 mda_postprivdrop(); 182 mta_postprivdrop(); 183 smtp_postprivdrop(); 184 185 signal(SIGINT, SIG_IGN); 186 signal(SIGTERM, SIG_IGN); 187 signal(SIGPIPE, SIG_IGN); 188 signal(SIGHUP, SIG_IGN); 189 190 config_peer(PROC_PARENT); 191 config_peer(PROC_QUEUE); 192 config_peer(PROC_LKA); 193 config_peer(PROC_CONTROL); 194 config_peer(PROC_CA); 195 196 if (pledge("stdio inet unix recvfd sendfd", NULL) == -1) 197 err(1, "pledge"); 198 199 event_dispatch(); 200 fatalx("exited event loop"); 201 202 return (0); 203} 204