1 /* $OpenBSD: config.c,v 1.53 2021/01/19 09:16:20 claudio 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); 256 } 257 free(env->sc_listeners); 258 env->sc_listeners = NULL; 259 } 260 if (what & PURGE_TABLES) { 261 while (dict_root(env->sc_tables_dict, NULL, (void **)&t)) 262 table_destroy(env, t); 263 free(env->sc_tables_dict); 264 env->sc_tables_dict = NULL; 265 } 266 if (what & PURGE_RULES) { 267 while ((r = TAILQ_FIRST(env->sc_rules)) != NULL) { 268 TAILQ_REMOVE(env->sc_rules, r, r_entry); 269 free(r); 270 } 271 free(env->sc_rules); 272 env->sc_rules = NULL; 273 } 274 if (what & PURGE_DISPATCHERS) { 275 while (dict_poproot(env->sc_dispatchers, (void **)&d)) { 276 free(d); 277 } 278 free(env->sc_dispatchers); 279 env->sc_dispatchers = NULL; 280 } 281 if (what & PURGE_PKI) { 282 while (dict_poproot(env->sc_pki_dict, (void **)&p)) { 283 freezero(p->pki_cert, p->pki_cert_len); 284 freezero(p->pki_key, p->pki_key_len); 285 EVP_PKEY_free(p->pki_pkey); 286 free(p); 287 } 288 free(env->sc_pki_dict); 289 env->sc_pki_dict = NULL; 290 } else if (what & PURGE_PKI_KEYS) { 291 iter_dict = NULL; 292 while (dict_iter(env->sc_pki_dict, &iter_dict, &k, 293 (void **)&p)) { 294 freezero(p->pki_cert, p->pki_cert_len); 295 p->pki_cert = NULL; 296 freezero(p->pki_key, p->pki_key_len); 297 p->pki_key = NULL; 298 EVP_PKEY_free(p->pki_pkey); 299 p->pki_pkey = NULL; 300 } 301 } 302 } 303 304 #ifndef CONFIG_MINIMUM 305 306 void 307 config_process(enum smtp_proc_type proc) 308 { 309 struct rlimit rl; 310 311 smtpd_process = proc; 312 setproctitle("%s", proc_title(proc)); 313 314 if (getrlimit(RLIMIT_NOFILE, &rl) == -1) 315 fatal("fdlimit: getrlimit"); 316 rl.rlim_cur = rl.rlim_max; 317 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) 318 fatal("fdlimit: setrlimit"); 319 } 320 321 void 322 config_peer(enum smtp_proc_type proc) 323 { 324 struct mproc *p; 325 326 if (proc == smtpd_process) 327 fatal("config_peers: cannot peer with oneself"); 328 329 if (proc == PROC_CONTROL) 330 p = p_control; 331 else if (proc == PROC_LKA) 332 p = p_lka; 333 else if (proc == PROC_PARENT) 334 p = p_parent; 335 else if (proc == PROC_QUEUE) 336 p = p_queue; 337 else if (proc == PROC_SCHEDULER) 338 p = p_scheduler; 339 else if (proc == PROC_DISPATCHER) 340 p = p_dispatcher; 341 else if (proc == PROC_CA) 342 p = p_ca; 343 else 344 fatalx("bad peer"); 345 346 mproc_enable(p); 347 } 348 349 #else 350 351 void config_process(enum smtp_proc_type proc) {} 352 void config_peer(enum smtp_proc_type proc) {} 353 354 #endif 355