1 /* $OpenBSD: config.c,v 1.55 2021/04/09 16:43:43 eric 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 <ifaddrs.h> 27 #include <imsg.h> 28 #include <netdb.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <limits.h> 32 #include <string.h> 33 #include <unistd.h> 34 35 #include <openssl/ssl.h> 36 37 #include "smtpd.h" 38 #include "log.h" 39 #include "ssl.h" 40 41 void set_local(struct smtpd *, const char *); 42 void set_localaddrs(struct smtpd *, struct table *); 43 44 struct smtpd * 45 config_default(void) 46 { 47 struct smtpd *conf = NULL; 48 struct mta_limits *limits = NULL; 49 struct table *t = NULL; 50 char hostname[HOST_NAME_MAX+1]; 51 52 if (getmailname(hostname, sizeof hostname) == -1) 53 return NULL; 54 55 if ((conf = calloc(1, sizeof(*conf))) == NULL) 56 return conf; 57 58 (void)strlcpy(conf->sc_hostname, hostname, sizeof(conf->sc_hostname)); 59 60 conf->sc_maxsize = DEFAULT_MAX_BODY_SIZE; 61 conf->sc_subaddressing_delim = SUBADDRESSING_DELIMITER; 62 conf->sc_ttl = SMTPD_QUEUE_EXPIRY; 63 conf->sc_srs_ttl = SMTPD_QUEUE_EXPIRY / 86400; 64 65 conf->sc_mta_max_deferred = 100; 66 conf->sc_scheduler_max_inflight = 5000; 67 conf->sc_scheduler_max_schedule = 10; 68 conf->sc_scheduler_max_evp_batch_size = 256; 69 conf->sc_scheduler_max_msg_batch_size = 1024; 70 71 conf->sc_session_max_rcpt = 1000; 72 conf->sc_session_max_mails = 100; 73 74 conf->sc_mda_max_session = 50; 75 conf->sc_mda_max_user_session = 7; 76 conf->sc_mda_task_hiwat = 50; 77 conf->sc_mda_task_lowat = 30; 78 conf->sc_mda_task_release = 10; 79 80 /* Report mails delayed for more than 4 hours */ 81 conf->sc_bounce_warn[0] = 3600 * 4; 82 83 conf->sc_tables_dict = calloc(1, sizeof(*conf->sc_tables_dict)); 84 conf->sc_rules = calloc(1, sizeof(*conf->sc_rules)); 85 conf->sc_dispatchers = calloc(1, sizeof(*conf->sc_dispatchers)); 86 conf->sc_listeners = calloc(1, sizeof(*conf->sc_listeners)); 87 conf->sc_ca_dict = calloc(1, sizeof(*conf->sc_ca_dict)); 88 conf->sc_pki_dict = calloc(1, sizeof(*conf->sc_pki_dict)); 89 conf->sc_ssl_dict = calloc(1, sizeof(*conf->sc_ssl_dict)); 90 conf->sc_limits_dict = calloc(1, sizeof(*conf->sc_limits_dict)); 91 conf->sc_mda_wrappers = calloc(1, sizeof(*conf->sc_mda_wrappers)); 92 conf->sc_filter_processes_dict = calloc(1, sizeof(*conf->sc_filter_processes_dict)); 93 conf->sc_dispatcher_bounce = calloc(1, sizeof(*conf->sc_dispatcher_bounce)); 94 conf->sc_filters_dict = calloc(1, sizeof(*conf->sc_filters_dict)); 95 limits = calloc(1, sizeof(*limits)); 96 97 if (conf->sc_tables_dict == NULL || 98 conf->sc_rules == NULL || 99 conf->sc_dispatchers == NULL || 100 conf->sc_listeners == NULL || 101 conf->sc_ca_dict == NULL || 102 conf->sc_pki_dict == NULL || 103 conf->sc_ssl_dict == NULL || 104 conf->sc_limits_dict == NULL || 105 conf->sc_mda_wrappers == NULL || 106 conf->sc_filter_processes_dict == NULL || 107 conf->sc_dispatcher_bounce == NULL || 108 conf->sc_filters_dict == NULL || 109 limits == NULL) 110 goto error; 111 112 dict_init(conf->sc_dispatchers); 113 dict_init(conf->sc_mda_wrappers); 114 dict_init(conf->sc_ca_dict); 115 dict_init(conf->sc_pki_dict); 116 dict_init(conf->sc_ssl_dict); 117 dict_init(conf->sc_tables_dict); 118 dict_init(conf->sc_limits_dict); 119 dict_init(conf->sc_filter_processes_dict); 120 121 limit_mta_set_defaults(limits); 122 123 dict_xset(conf->sc_limits_dict, "default", limits); 124 125 TAILQ_INIT(conf->sc_listeners); 126 TAILQ_INIT(conf->sc_rules); 127 128 129 /* bounce dispatcher */ 130 conf->sc_dispatcher_bounce->type = DISPATCHER_BOUNCE; 131 132 /* 133 * declare special "localhost", "anyhost" and "localnames" tables 134 */ 135 set_local(conf, conf->sc_hostname); 136 137 t = table_create(conf, "static", "<anydestination>", NULL); 138 table_add(t, "*", NULL); 139 140 hostname[strcspn(hostname, ".")] = '\0'; 141 if (strcmp(conf->sc_hostname, hostname) != 0) 142 table_add(t, hostname, NULL); 143 144 table_create(conf, "getpwnam", "<getpwnam>", NULL); 145 146 return conf; 147 148 error: 149 free(conf->sc_tables_dict); 150 free(conf->sc_rules); 151 free(conf->sc_dispatchers); 152 free(conf->sc_listeners); 153 free(conf->sc_ca_dict); 154 free(conf->sc_pki_dict); 155 free(conf->sc_ssl_dict); 156 free(conf->sc_limits_dict); 157 free(conf->sc_mda_wrappers); 158 free(conf->sc_filter_processes_dict); 159 free(conf->sc_dispatcher_bounce); 160 free(conf->sc_filters_dict); 161 free(limits); 162 free(conf); 163 return NULL; 164 } 165 166 void 167 set_local(struct smtpd *conf, const char *hostname) 168 { 169 struct table *t; 170 171 t = table_create(conf, "static", "<localnames>", NULL); 172 table_add(t, "localhost", NULL); 173 table_add(t, hostname, NULL); 174 175 set_localaddrs(conf, t); 176 } 177 178 void 179 set_localaddrs(struct smtpd *conf, struct table *localnames) 180 { 181 struct ifaddrs *ifap, *p; 182 struct sockaddr_storage ss; 183 struct sockaddr_in *sain; 184 struct sockaddr_in6 *sin6; 185 struct table *t; 186 char buf[NI_MAXHOST + 5]; 187 188 t = table_create(conf, "static", "<anyhost>", NULL); 189 table_add(t, "local", NULL); 190 table_add(t, "0.0.0.0/0", NULL); 191 table_add(t, "::/0", NULL); 192 193 if (getifaddrs(&ifap) == -1) 194 fatal("getifaddrs"); 195 196 t = table_create(conf, "static", "<localhost>", NULL); 197 table_add(t, "local", NULL); 198 199 for (p = ifap; p != NULL; p = p->ifa_next) { 200 if (p->ifa_addr == NULL) 201 continue; 202 switch (p->ifa_addr->sa_family) { 203 case AF_INET: 204 sain = (struct sockaddr_in *)&ss; 205 *sain = *(struct sockaddr_in *)p->ifa_addr; 206 sain->sin_len = sizeof(struct sockaddr_in); 207 table_add(t, ss_to_text(&ss), NULL); 208 table_add(localnames, ss_to_text(&ss), NULL); 209 (void)snprintf(buf, sizeof buf, "[%s]", ss_to_text(&ss)); 210 table_add(localnames, buf, NULL); 211 break; 212 213 case AF_INET6: 214 sin6 = (struct sockaddr_in6 *)&ss; 215 *sin6 = *(struct sockaddr_in6 *)p->ifa_addr; 216 sin6->sin6_len = sizeof(struct sockaddr_in6); 217 #ifdef __KAME__ 218 if ((IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) || 219 IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr) || 220 IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr)) && 221 sin6->sin6_scope_id == 0) { 222 sin6->sin6_scope_id = ntohs( 223 *(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); 224 sin6->sin6_addr.s6_addr[2] = 0; 225 sin6->sin6_addr.s6_addr[3] = 0; 226 } 227 #endif 228 table_add(t, ss_to_text(&ss), NULL); 229 table_add(localnames, ss_to_text(&ss), NULL); 230 (void)snprintf(buf, sizeof buf, "[%s]", ss_to_text(&ss)); 231 table_add(localnames, buf, NULL); 232 (void)snprintf(buf, sizeof buf, "[ipv6:%s]", ss_to_text(&ss)); 233 table_add(localnames, buf, NULL); 234 break; 235 } 236 } 237 238 freeifaddrs(ifap); 239 } 240 241 void 242 purge_config(uint8_t what) 243 { 244 struct dispatcher *d; 245 struct listener *l; 246 struct table *t; 247 struct rule *r; 248 struct pki *p; 249 const char *k; 250 void *iter_dict; 251 252 if (what & PURGE_LISTENERS) { 253 while ((l = TAILQ_FIRST(env->sc_listeners)) != NULL) { 254 TAILQ_REMOVE(env->sc_listeners, l, entry); 255 free(l->tls_ciphers); 256 free(l->tls_protocols); 257 free(l->pki); 258 free(l); 259 } 260 free(env->sc_listeners); 261 env->sc_listeners = NULL; 262 } 263 if (what & PURGE_TABLES) { 264 while (dict_root(env->sc_tables_dict, NULL, (void **)&t)) 265 table_destroy(env, t); 266 free(env->sc_tables_dict); 267 env->sc_tables_dict = NULL; 268 } 269 if (what & PURGE_RULES) { 270 while ((r = TAILQ_FIRST(env->sc_rules)) != NULL) { 271 TAILQ_REMOVE(env->sc_rules, r, r_entry); 272 free(r); 273 } 274 free(env->sc_rules); 275 env->sc_rules = NULL; 276 } 277 if (what & PURGE_DISPATCHERS) { 278 while (dict_poproot(env->sc_dispatchers, (void **)&d)) { 279 free(d); 280 } 281 free(env->sc_dispatchers); 282 env->sc_dispatchers = NULL; 283 } 284 if (what & PURGE_PKI) { 285 while (dict_poproot(env->sc_pki_dict, (void **)&p)) { 286 freezero(p->pki_cert, p->pki_cert_len); 287 freezero(p->pki_key, p->pki_key_len); 288 EVP_PKEY_free(p->pki_pkey); 289 free(p); 290 } 291 free(env->sc_pki_dict); 292 env->sc_pki_dict = NULL; 293 } else if (what & PURGE_PKI_KEYS) { 294 iter_dict = NULL; 295 while (dict_iter(env->sc_pki_dict, &iter_dict, &k, 296 (void **)&p)) { 297 freezero(p->pki_cert, p->pki_cert_len); 298 p->pki_cert = NULL; 299 freezero(p->pki_key, p->pki_key_len); 300 p->pki_key = NULL; 301 EVP_PKEY_free(p->pki_pkey); 302 p->pki_pkey = NULL; 303 } 304 } 305 } 306 307 #ifndef CONFIG_MINIMUM 308 309 void 310 config_process(enum smtp_proc_type proc) 311 { 312 struct rlimit rl; 313 314 smtpd_process = proc; 315 setproctitle("%s", proc_title(proc)); 316 317 if (getrlimit(RLIMIT_NOFILE, &rl) == -1) 318 fatal("fdlimit: getrlimit"); 319 rl.rlim_cur = rl.rlim_max; 320 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) 321 fatal("fdlimit: setrlimit"); 322 } 323 324 void 325 config_peer(enum smtp_proc_type proc) 326 { 327 struct mproc *p; 328 329 if (proc == smtpd_process) 330 fatal("config_peers: cannot peer with oneself"); 331 332 if (proc == PROC_CONTROL) 333 p = p_control; 334 else if (proc == PROC_LKA) 335 p = p_lka; 336 else if (proc == PROC_PARENT) 337 p = p_parent; 338 else if (proc == PROC_QUEUE) 339 p = p_queue; 340 else if (proc == PROC_SCHEDULER) 341 p = p_scheduler; 342 else if (proc == PROC_DISPATCHER) 343 p = p_dispatcher; 344 else if (proc == PROC_CA) 345 p = p_ca; 346 else 347 fatalx("bad peer"); 348 349 mproc_enable(p); 350 } 351 352 #else 353 354 void config_process(enum smtp_proc_type proc) {} 355 void config_peer(enum smtp_proc_type proc) {} 356 357 #endif 358