From 90087f07a7cfffe10b4958e13558a0052f85691d Mon Sep 17 00:00:00 2001 From: Gilles Chehade Date: Fri, 22 May 2020 14:35:02 +0200 Subject: Revert "moving smtpd to usr.sbin/smtpd to ease cherry-picking of upstream" This reverts commit 90620a574d8824e5b2aa18709f2d5b5b6bb3cb38. --- smtpd/config.c | 350 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 smtpd/config.c (limited to 'smtpd/config.c') diff --git a/smtpd/config.c b/smtpd/config.c new file mode 100644 index 00000000..8fe983d6 --- /dev/null +++ b/smtpd/config.c @@ -0,0 +1,350 @@ +/* $OpenBSD: config.c,v 1.51 2019/12/18 10:00:39 gilles Exp $ */ + +/* + * Copyright (c) 2008 Pierre-Yves Ritschard + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "includes.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "smtpd.h" +#include "log.h" +#include "ssl.h" + +void set_local(struct smtpd *, const char *); +void set_localaddrs(struct smtpd *, struct table *); + +struct smtpd * +config_default(void) +{ + struct smtpd *conf = NULL; + struct mta_limits *limits = NULL; + struct table *t = NULL; + char hostname[HOST_NAME_MAX+1]; + + if (getmailname(hostname, sizeof hostname) == -1) + return NULL; + + if ((conf = calloc(1, sizeof(*conf))) == NULL) + return conf; + + (void)strlcpy(conf->sc_hostname, hostname, sizeof(conf->sc_hostname)); + + conf->sc_maxsize = DEFAULT_MAX_BODY_SIZE; + conf->sc_subaddressing_delim = SUBADDRESSING_DELIMITER; + conf->sc_ttl = SMTPD_QUEUE_EXPIRY; + conf->sc_srs_ttl = SMTPD_QUEUE_EXPIRY / 86400; + + conf->sc_mta_max_deferred = 100; + conf->sc_scheduler_max_inflight = 5000; + conf->sc_scheduler_max_schedule = 10; + conf->sc_scheduler_max_evp_batch_size = 256; + conf->sc_scheduler_max_msg_batch_size = 1024; + + conf->sc_session_max_rcpt = 1000; + conf->sc_session_max_mails = 100; + + conf->sc_mda_max_session = 50; + conf->sc_mda_max_user_session = 7; + conf->sc_mda_task_hiwat = 50; + conf->sc_mda_task_lowat = 30; + conf->sc_mda_task_release = 10; + + /* Report mails delayed for more than 4 hours */ + conf->sc_bounce_warn[0] = 3600 * 4; + + conf->sc_tables_dict = calloc(1, sizeof(*conf->sc_tables_dict)); + conf->sc_rules = calloc(1, sizeof(*conf->sc_rules)); + conf->sc_dispatchers = calloc(1, sizeof(*conf->sc_dispatchers)); + conf->sc_listeners = calloc(1, sizeof(*conf->sc_listeners)); + conf->sc_ca_dict = calloc(1, sizeof(*conf->sc_ca_dict)); + conf->sc_pki_dict = calloc(1, sizeof(*conf->sc_pki_dict)); + conf->sc_ssl_dict = calloc(1, sizeof(*conf->sc_ssl_dict)); + conf->sc_limits_dict = calloc(1, sizeof(*conf->sc_limits_dict)); + conf->sc_mda_wrappers = calloc(1, sizeof(*conf->sc_mda_wrappers)); + conf->sc_filter_processes_dict = calloc(1, sizeof(*conf->sc_filter_processes_dict)); + conf->sc_dispatcher_bounce = calloc(1, sizeof(*conf->sc_dispatcher_bounce)); + conf->sc_filters_dict = calloc(1, sizeof(*conf->sc_filters_dict)); + limits = calloc(1, sizeof(*limits)); + + if (conf->sc_tables_dict == NULL || + conf->sc_rules == NULL || + conf->sc_dispatchers == NULL || + conf->sc_listeners == NULL || + conf->sc_ca_dict == NULL || + conf->sc_pki_dict == NULL || + conf->sc_ssl_dict == NULL || + conf->sc_limits_dict == NULL || + conf->sc_mda_wrappers == NULL || + conf->sc_filter_processes_dict == NULL || + conf->sc_dispatcher_bounce == NULL || + conf->sc_filters_dict == NULL || + limits == NULL) + goto error; + + dict_init(conf->sc_dispatchers); + dict_init(conf->sc_mda_wrappers); + dict_init(conf->sc_ca_dict); + dict_init(conf->sc_pki_dict); + dict_init(conf->sc_ssl_dict); + dict_init(conf->sc_tables_dict); + dict_init(conf->sc_limits_dict); + dict_init(conf->sc_filter_processes_dict); + + limit_mta_set_defaults(limits); + + dict_xset(conf->sc_limits_dict, "default", limits); + + TAILQ_INIT(conf->sc_listeners); + TAILQ_INIT(conf->sc_rules); + + + /* bounce dispatcher */ + conf->sc_dispatcher_bounce->type = DISPATCHER_BOUNCE; + + /* + * declare special "localhost", "anyhost" and "localnames" tables + */ + set_local(conf, conf->sc_hostname); + + t = table_create(conf, "static", "", NULL); + table_add(t, "*", NULL); + + hostname[strcspn(hostname, ".")] = '\0'; + if (strcmp(conf->sc_hostname, hostname) != 0) + table_add(t, hostname, NULL); + + table_create(conf, "getpwnam", "", NULL); + + return conf; + +error: + free(conf->sc_tables_dict); + free(conf->sc_rules); + free(conf->sc_dispatchers); + free(conf->sc_listeners); + free(conf->sc_ca_dict); + free(conf->sc_pki_dict); + free(conf->sc_ssl_dict); + free(conf->sc_limits_dict); + free(conf->sc_mda_wrappers); + free(conf->sc_filter_processes_dict); + free(conf->sc_dispatcher_bounce); + free(conf->sc_filters_dict); + free(limits); + free(conf); + return NULL; +} + +void +set_local(struct smtpd *conf, const char *hostname) +{ + struct table *t; + + t = table_create(conf, "static", "", NULL); + table_add(t, "localhost", NULL); + table_add(t, hostname, NULL); + + set_localaddrs(conf, t); +} + +void +set_localaddrs(struct smtpd *conf, struct table *localnames) +{ + struct ifaddrs *ifap, *p; + struct sockaddr_storage ss; + struct sockaddr_in *sain; + struct sockaddr_in6 *sin6; + struct table *t; + char buf[NI_MAXHOST + 5]; + + t = table_create(conf, "static", "", NULL); + table_add(t, "local", NULL); + table_add(t, "0.0.0.0/0", NULL); + table_add(t, "::/0", NULL); + + if (getifaddrs(&ifap) == -1) + fatal("getifaddrs"); + + t = table_create(conf, "static", "", NULL); + table_add(t, "local", NULL); + + for (p = ifap; p != NULL; p = p->ifa_next) { + if (p->ifa_addr == NULL) + continue; + switch (p->ifa_addr->sa_family) { + case AF_INET: + sain = (struct sockaddr_in *)&ss; + *sain = *(struct sockaddr_in *)p->ifa_addr; +#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN + sain->sin_len = sizeof(struct sockaddr_in); +#endif + table_add(t, ss_to_text(&ss), NULL); + table_add(localnames, ss_to_text(&ss), NULL); + (void)snprintf(buf, sizeof buf, "[%s]", ss_to_text(&ss)); + table_add(localnames, buf, NULL); + break; + + case AF_INET6: + sin6 = (struct sockaddr_in6 *)&ss; + *sin6 = *(struct sockaddr_in6 *)p->ifa_addr; +#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN + sin6->sin6_len = sizeof(struct sockaddr_in6); +#endif + table_add(t, ss_to_text(&ss), NULL); + table_add(localnames, ss_to_text(&ss), NULL); + (void)snprintf(buf, sizeof buf, "[%s]", ss_to_text(&ss)); + table_add(localnames, buf, NULL); + (void)snprintf(buf, sizeof buf, "[ipv6:%s]", ss_to_text(&ss)); + table_add(localnames, buf, NULL); + break; + } + } + + freeifaddrs(ifap); +} + +void +purge_config(uint8_t what) +{ + struct dispatcher *d; + struct listener *l; + struct table *t; + struct rule *r; + struct pki *p; + const char *k; + void *iter_dict; + + if (what & PURGE_LISTENERS) { + while ((l = TAILQ_FIRST(env->sc_listeners)) != NULL) { + TAILQ_REMOVE(env->sc_listeners, l, entry); + free(l); + } + free(env->sc_listeners); + env->sc_listeners = NULL; + } + if (what & PURGE_TABLES) { + while (dict_root(env->sc_tables_dict, NULL, (void **)&t)) + table_destroy(env, t); + free(env->sc_tables_dict); + env->sc_tables_dict = NULL; + } + if (what & PURGE_RULES) { + while ((r = TAILQ_FIRST(env->sc_rules)) != NULL) { + TAILQ_REMOVE(env->sc_rules, r, r_entry); + free(r); + } + free(env->sc_rules); + env->sc_rules = NULL; + } + if (what & PURGE_DISPATCHERS) { + while (dict_poproot(env->sc_dispatchers, (void **)&d)) { + free(d); + } + free(env->sc_dispatchers); + env->sc_dispatchers = NULL; + } + if (what & PURGE_PKI) { + while (dict_poproot(env->sc_pki_dict, (void **)&p)) { + freezero(p->pki_cert, p->pki_cert_len); + freezero(p->pki_key, p->pki_key_len); + EVP_PKEY_free(p->pki_pkey); + free(p); + } + free(env->sc_pki_dict); + env->sc_pki_dict = NULL; + } else if (what & PURGE_PKI_KEYS) { + iter_dict = NULL; + while (dict_iter(env->sc_pki_dict, &iter_dict, &k, + (void **)&p)) { + freezero(p->pki_cert, p->pki_cert_len); + p->pki_cert = NULL; + freezero(p->pki_key, p->pki_key_len); + p->pki_key = NULL; + EVP_PKEY_free(p->pki_pkey); + p->pki_pkey = NULL; + } + } +} + +#ifndef CONFIG_MINIMUM + +void +config_process(enum smtp_proc_type proc) +{ + struct rlimit rl; + + smtpd_process = proc; + setproctitle("%s", proc_title(proc)); + + if (getrlimit(RLIMIT_NOFILE, &rl) == -1) + fatal("fdlimit: getrlimit"); + rl.rlim_cur = rl.rlim_max; + if (setrlimit(RLIMIT_NOFILE, &rl) == -1) + if (errno != EINVAL) + fatal("fdlimit: setrlimit"); +} + +void +config_peer(enum smtp_proc_type proc) +{ + struct mproc *p; + + if (proc == smtpd_process) + fatal("config_peers: cannot peer with oneself"); + + if (proc == PROC_CONTROL) + p = p_control; + else if (proc == PROC_LKA) + p = p_lka; + else if (proc == PROC_PARENT) + p = p_parent; + else if (proc == PROC_QUEUE) + p = p_queue; + else if (proc == PROC_SCHEDULER) + p = p_scheduler; + else if (proc == PROC_PONY) + p = p_pony; + else if (proc == PROC_CA) + p = p_ca; + else + fatalx("bad peer"); + + mproc_enable(p); +} + +#else + +void config_process(enum smtp_proc_type proc) {} +void config_peer(enum smtp_proc_type proc) {} + +#endif -- cgit v1.2.3-59-g8ed1b