1 /* $OpenBSD: config.c,v 1.31 2014/05/01 15:50:20 reyk Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.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 #include <sys/resource.h> 24 25 #include <event.h> 26 #include <imsg.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <unistd.h> 31 32 #include <openssl/ssl.h> 33 34 #include "smtpd.h" 35 #include "log.h" 36 #include "ssl.h" 37 38 extern int profiling; 39 40 static int pipes[PROC_COUNT][PROC_COUNT]; 41 42 void 43 purge_config(uint8_t what) 44 { 45 struct listener *l; 46 struct table *t; 47 struct rule *r; 48 struct pki *p; 49 const char *k; 50 void *iter_dict; 51 52 if (what & PURGE_LISTENERS) { 53 while ((l = TAILQ_FIRST(env->sc_listeners)) != NULL) { 54 TAILQ_REMOVE(env->sc_listeners, l, entry); 55 free(l); 56 } 57 free(env->sc_listeners); 58 env->sc_listeners = NULL; 59 } 60 if (what & PURGE_TABLES) { 61 while (dict_root(env->sc_tables_dict, NULL, (void **)&t)) 62 table_destroy(t); 63 free(env->sc_tables_dict); 64 env->sc_tables_dict = NULL; 65 } 66 if (what & PURGE_RULES) { 67 while ((r = TAILQ_FIRST(env->sc_rules)) != NULL) { 68 TAILQ_REMOVE(env->sc_rules, r, r_entry); 69 free(r); 70 } 71 free(env->sc_rules); 72 env->sc_rules = NULL; 73 } 74 if (what & PURGE_PKI) { 75 while (dict_poproot(env->sc_pki_dict, (void **)&p)) { 76 explicit_bzero(p->pki_cert, p->pki_cert_len); 77 free(p->pki_cert); 78 if (p->pki_key) { 79 explicit_bzero(p->pki_key, p->pki_key_len); 80 free(p->pki_key); 81 } 82 if (p->pki_pkey) 83 EVP_PKEY_free(p->pki_pkey); 84 free(p); 85 } 86 free(env->sc_pki_dict); 87 env->sc_pki_dict = NULL; 88 } else if (what & PURGE_PKI_KEYS) { 89 iter_dict = NULL; 90 while (dict_iter(env->sc_pki_dict, &iter_dict, &k, 91 (void **)&p)) { 92 explicit_bzero(p->pki_cert, p->pki_cert_len); 93 free(p->pki_cert); 94 p->pki_cert = NULL; 95 if (p->pki_key) { 96 explicit_bzero(p->pki_key, p->pki_key_len); 97 free(p->pki_key); 98 p->pki_key = NULL; 99 } 100 if (p->pki_pkey) 101 EVP_PKEY_free(p->pki_pkey); 102 p->pki_pkey = NULL; 103 } 104 } 105 } 106 107 void 108 init_pipes(void) 109 { 110 int i, j, sockpair[2]; 111 112 for (i = 0; i < PROC_COUNT; i++) 113 for (j = i + 1; j < PROC_COUNT; j++) { 114 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, 115 sockpair) == -1) 116 fatal("socketpair"); 117 pipes[i][j] = sockpair[0]; 118 pipes[j][i] = sockpair[1]; 119 session_socket_blockmode(pipes[i][j], BM_NONBLOCK); 120 session_socket_blockmode(pipes[j][i], BM_NONBLOCK); 121 } 122 } 123 124 void 125 config_process(enum smtp_proc_type proc) 126 { 127 struct rlimit rl; 128 129 smtpd_process = proc; 130 setproctitle("%s", proc_title(proc)); 131 132 if (getrlimit(RLIMIT_NOFILE, &rl) == -1) 133 fatal("fdlimit: getrlimit"); 134 rl.rlim_cur = rl.rlim_max; 135 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) 136 fatal("fdlimit: setrlimit"); 137 } 138 139 void 140 config_peer(enum smtp_proc_type proc) 141 { 142 struct mproc *p; 143 144 if (proc == smtpd_process) 145 fatal("config_peers: cannot peer with oneself"); 146 147 p = xcalloc(1, sizeof *p, "config_peer"); 148 p->proc = proc; 149 p->name = xstrdup(proc_name(proc), "config_peer"); 150 p->handler = imsg_dispatch; 151 152 mproc_init(p, pipes[smtpd_process][proc]); 153 mproc_enable(p); 154 pipes[smtpd_process][proc] = -1; 155 156 if (proc == PROC_CONTROL) 157 p_control = p; 158 else if (proc == PROC_LKA) 159 p_lka = p; 160 else if (proc == PROC_PARENT) 161 p_parent = p; 162 else if (proc == PROC_QUEUE) 163 p_queue = p; 164 else if (proc == PROC_SCHEDULER) 165 p_scheduler = p; 166 else if (proc == PROC_PONY) 167 p_pony = p; 168 else if (proc == PROC_CA) 169 p_ca = p; 170 else 171 fatalx("bad peer"); 172 } 173 174 static void process_stat_event(int, short, void *); 175 176 void 177 config_done(void) 178 { 179 static struct event ev; 180 struct timeval tv; 181 unsigned int i, j; 182 183 for (i = 0; i < PROC_COUNT; i++) { 184 for (j = 0; j < PROC_COUNT; j++) { 185 if (i == j || pipes[i][j] == -1) 186 continue; 187 close(pipes[i][j]); 188 pipes[i][j] = -1; 189 } 190 } 191 192 if (smtpd_process == PROC_CONTROL) 193 return; 194 195 if (!(profiling & PROFILE_BUFFERS)) 196 return; 197 198 evtimer_set(&ev, process_stat_event, &ev); 199 tv.tv_sec = 0; 200 tv.tv_usec = 0; 201 evtimer_add(&ev, &tv); 202 } 203 204 static void 205 process_stat(struct mproc *p) 206 { 207 char buf[1024]; 208 struct stat_value value; 209 210 if (p == NULL) 211 return; 212 213 value.type = STAT_COUNTER; 214 (void)snprintf(buf, sizeof buf, "buffer.%s.%s", 215 proc_name(smtpd_process), 216 proc_name(p->proc)); 217 value.u.counter = p->bytes_queued_max; 218 p->bytes_queued_max = p->bytes_queued; 219 stat_set(buf, &value); 220 } 221 222 static void 223 process_stat_event(int fd, short ev, void *arg) 224 { 225 struct event *e = arg; 226 struct timeval tv; 227 228 process_stat(p_control); 229 process_stat(p_lka); 230 process_stat(p_parent); 231 process_stat(p_queue); 232 process_stat(p_scheduler); 233 process_stat(p_pony); 234 process_stat(p_ca); 235 236 tv.tv_sec = 1; 237 tv.tv_usec = 0; 238 evtimer_add(e, &tv); 239 } 240