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