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