diff options
author | Gilles Chehade <gilles@poolp.org> | 2018-12-27 10:54:44 +0100 |
---|---|---|
committer | Gilles Chehade <gilles@poolp.org> | 2018-12-27 10:54:44 +0100 |
commit | 995cc445c2dc0228ef8a31d88d2bc13d3c608311 (patch) | |
tree | f34c145f0219157938f7eb2738d43b3dec368c40 | |
parent | Merge branch 'master' into portable (diff) | |
parent | sync (diff) | |
download | OpenSMTPD-995cc445c2dc0228ef8a31d88d2bc13d3c608311.tar.xz OpenSMTPD-995cc445c2dc0228ef8a31d88d2bc13d3c608311.zip |
Merge branch 'master' into portable
-rw-r--r-- | smtpd/aliases.c | 18 | ||||
-rw-r--r-- | smtpd/dict.c | 9 | ||||
-rw-r--r-- | smtpd/dict.h | 48 | ||||
-rw-r--r-- | smtpd/lka.c | 167 | ||||
-rw-r--r-- | smtpd/lka_filter.c | 249 | ||||
-rw-r--r-- | smtpd/lka_session.c | 4 | ||||
-rw-r--r-- | smtpd/mta.c | 10 | ||||
-rw-r--r-- | smtpd/mta_session.c | 209 | ||||
-rw-r--r-- | smtpd/parse.y | 49 | ||||
-rw-r--r-- | smtpd/pony.c | 6 | ||||
-rw-r--r-- | smtpd/ruleset.c | 54 | ||||
-rw-r--r-- | smtpd/smtp.c | 4 | ||||
-rw-r--r-- | smtpd/smtp_session.c | 200 | ||||
-rw-r--r-- | smtpd/smtpd-api.h | 52 | ||||
-rw-r--r-- | smtpd/smtpd.c | 14 | ||||
-rw-r--r-- | smtpd/smtpd.h | 57 | ||||
-rw-r--r-- | smtpd/table.c | 204 | ||||
-rw-r--r-- | smtpd/table_db.c | 73 | ||||
-rw-r--r-- | smtpd/table_getpwnam.c | 41 | ||||
-rw-r--r-- | smtpd/table_proc.c | 62 | ||||
-rw-r--r-- | smtpd/table_static.c | 48 | ||||
-rw-r--r-- | smtpd/tree.c | 9 | ||||
-rw-r--r-- | smtpd/tree.h | 48 |
23 files changed, 528 insertions, 1107 deletions
diff --git a/smtpd/aliases.c b/smtpd/aliases.c index be350897..0ce4c7ec 100644 --- a/smtpd/aliases.c +++ b/smtpd/aliases.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aliases.c,v 1.73 2018/06/16 19:41:26 gilles Exp $ */ +/* $OpenBSD: aliases.c,v 1.75 2018/12/26 20:13:43 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org> @@ -65,7 +65,7 @@ aliases_get(struct expand *expand, const char *username) /* first, check if entry has a user-part tag */ pbuf = strchr(buf, *env->sc_subaddressing_delim); if (pbuf) { - ret = table_lookup(mapping, NULL, buf, K_ALIAS, &lk); + ret = table_lookup(mapping, K_ALIAS, buf, &lk); if (ret < 0) return (-1); if (ret) @@ -74,7 +74,7 @@ aliases_get(struct expand *expand, const char *username) } /* no user-part tag, try looking up user */ - ret = table_lookup(mapping, NULL, buf, K_ALIAS, &lk); + ret = table_lookup(mapping, K_ALIAS, buf, &lk); if (ret <= 0) return ret; @@ -138,7 +138,7 @@ aliases_virtual_get(struct expand *expand, const struct mailaddr *maddr) if (!bsnprintf(buf, sizeof(buf), "%s%c%s@%s", user, *env->sc_subaddressing_delim, tag, domain)) return 0; - ret = table_lookup(mapping, NULL, buf, K_ALIAS, &lk); + ret = table_lookup(mapping, K_ALIAS, buf, &lk); if (ret < 0) return (-1); if (ret) @@ -148,7 +148,7 @@ aliases_virtual_get(struct expand *expand, const struct mailaddr *maddr) /* then, check if entry exists without user-part tag */ if (!bsnprintf(buf, sizeof(buf), "%s@%s", user, domain)) return 0; - ret = table_lookup(mapping, NULL, buf, K_ALIAS, &lk); + ret = table_lookup(mapping, K_ALIAS, buf, &lk); if (ret < 0) return (-1); if (ret) @@ -159,7 +159,7 @@ aliases_virtual_get(struct expand *expand, const struct mailaddr *maddr) if (!bsnprintf(buf, sizeof(buf), "%s%c%s", user, *env->sc_subaddressing_delim, tag)) return 0; - ret = table_lookup(mapping, NULL, buf, K_ALIAS, &lk); + ret = table_lookup(mapping, K_ALIAS, buf, &lk); if (ret < 0) return (-1); if (ret) @@ -169,7 +169,7 @@ aliases_virtual_get(struct expand *expand, const struct mailaddr *maddr) /* Failed ? We lookup for username only */ if (!bsnprintf(buf, sizeof(buf), "%s", user)) return 0; - ret = table_lookup(mapping, NULL, buf, K_ALIAS, &lk); + ret = table_lookup(mapping, K_ALIAS, buf, &lk); if (ret < 0) return (-1); if (ret) @@ -178,14 +178,14 @@ aliases_virtual_get(struct expand *expand, const struct mailaddr *maddr) if (!bsnprintf(buf, sizeof(buf), "@%s", domain)) return 0; /* Failed ? We lookup for catch all for virtual domain */ - ret = table_lookup(mapping, NULL, buf, K_ALIAS, &lk); + ret = table_lookup(mapping, K_ALIAS, buf, &lk); if (ret < 0) return (-1); if (ret) goto expand; /* Failed ? We lookup for a *global* catch all */ - ret = table_lookup(mapping, NULL, "@", K_ALIAS, &lk); + ret = table_lookup(mapping, K_ALIAS, "@", &lk); if (ret <= 0) return (ret); diff --git a/smtpd/dict.c b/smtpd/dict.c index d5998052..e660f0a5 100644 --- a/smtpd/dict.c +++ b/smtpd/dict.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dict.c,v 1.5 2015/01/20 17:37:54 deraadt Exp $ */ +/* $OpenBSD: dict.c,v 1.6 2018/12/23 16:06:24 gilles Exp $ */ /* * Copyright (c) 2012 Gilles Chehade <gilles@poolp.org> @@ -22,17 +22,12 @@ #include <sys/types.h> #include <sys/tree.h> -#include <sys/socket.h> /* for smtpd.h */ -#include <sys/queue.h> /* for smtpd.h */ -#include <stdio.h> /* for smtpd.h */ -#include <imsg.h> /* for smtpd.h */ - #include <err.h> #include <stdlib.h> #include <string.h> #include <limits.h> -#include "smtpd.h" +#include "dict.h" struct dictentry { SPLAY_ENTRY(dictentry) entry; diff --git a/smtpd/dict.h b/smtpd/dict.h new file mode 100644 index 00000000..c5d47e1a --- /dev/null +++ b/smtpd/dict.h @@ -0,0 +1,48 @@ +/* $OpenBSD: dict.h,v 1.1 2018/12/23 16:06:24 gilles Exp $ */ + +/* + * Copyright (c) 2013 Eric Faurot <eric@openbsd.org> + * Copyright (c) 2011 Gilles Chehade <gilles@poolp.org> + * + * 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. + */ + +#ifndef _DICT_H_ +#define _DICT_H_ + +SPLAY_HEAD(_dict, dictentry); + +struct dict { + struct _dict dict; + size_t count; +}; + + +/* dict.c */ +#define dict_init(d) do { SPLAY_INIT(&((d)->dict)); (d)->count = 0; } while(0) +#define dict_empty(d) SPLAY_EMPTY(&((d)->dict)) +#define dict_count(d) ((d)->count) +int dict_check(struct dict *, const char *); +void *dict_set(struct dict *, const char *, void *); +void dict_xset(struct dict *, const char *, void *); +void *dict_get(struct dict *, const char *); +void *dict_xget(struct dict *, const char *); +void *dict_pop(struct dict *, const char *); +void *dict_xpop(struct dict *, const char *); +int dict_poproot(struct dict *, void **); +int dict_root(struct dict *, const char **, void **); +int dict_iter(struct dict *, void **, const char **, void **); +int dict_iterfrom(struct dict *, void **, const char *, const char **, void **); +void dict_merge(struct dict *, struct dict *); + +#endif diff --git a/smtpd/lka.c b/smtpd/lka.c index 519fb1d7..0291d49b 100644 --- a/smtpd/lka.c +++ b/smtpd/lka.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lka.c,v 1.228 2018/12/21 14:33:52 gilles Exp $ */ +/* $OpenBSD: lka.c,v 1.231 2018/12/26 20:13:43 eric Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -60,9 +60,6 @@ static int lka_userinfo(const char *, const char *, struct userinfo *); static int lka_addrname(const char *, const struct sockaddr *, struct addrname *); static int lka_mailaddrmap(const char *, const char *, const struct mailaddr *); -static int lka_X509_verify(struct ca_vrfy_req_msg *, const char *, const char *); -static void lka_certificate_verify(enum imsg_type, struct ca_vrfy_req_msg *); -static void lka_certificate_verify_resume(enum imsg_type, struct ca_vrfy_req_msg *); static void proc_timeout(int fd, short event, void *p); @@ -73,12 +70,6 @@ lka_imsg(struct mproc *p, struct imsg *imsg) { struct table *table; int ret; - struct pki *pki; - struct iovec iov[2]; - static struct ca_vrfy_req_msg *req_ca_vrfy = NULL; - struct ca_vrfy_req_msg *req_ca_vrfy_chain; - struct ca_cert_req_msg *req_ca_cert; - struct ca_cert_resp_msg resp_ca_cert; struct sockaddr_storage ss; struct userinfo userinfo; struct addrname addrname; @@ -172,63 +163,6 @@ lka_imsg(struct mproc *p, struct imsg *imsg) m_close(p); return; - case IMSG_SMTP_TLS_INIT: - case IMSG_MTA_TLS_INIT: - req_ca_cert = imsg->data; - resp_ca_cert.reqid = req_ca_cert->reqid; - - xlowercase(buf, req_ca_cert->name, sizeof(buf)); - log_debug("debug: lka: looking up pki \"%s\"", buf); - pki = dict_get(env->sc_pki_dict, buf); - if (pki == NULL) - if (req_ca_cert->fallback) - pki = dict_get(env->sc_pki_dict, "*"); - if (pki == NULL) { - resp_ca_cert.status = CA_FAIL; - m_compose(p, imsg->hdr.type, 0, 0, -1, &resp_ca_cert, - sizeof(resp_ca_cert)); - return; - } - resp_ca_cert.status = CA_OK; - resp_ca_cert.cert_len = pki->pki_cert_len; - (void)strlcpy(resp_ca_cert.name, pki->pki_name, sizeof resp_ca_cert.name); - iov[0].iov_base = &resp_ca_cert; - iov[0].iov_len = sizeof(resp_ca_cert); - iov[1].iov_base = pki->pki_cert; - iov[1].iov_len = pki->pki_cert_len; - m_composev(p, imsg->hdr.type, 0, 0, -1, iov, nitems(iov)); - return; - - case IMSG_SMTP_TLS_VERIFY_CERT: - case IMSG_MTA_TLS_VERIFY_CERT: - req_ca_vrfy = xmemdup(imsg->data, sizeof *req_ca_vrfy); - req_ca_vrfy->cert = xmemdup((char *)imsg->data + - sizeof *req_ca_vrfy, req_ca_vrfy->cert_len); - req_ca_vrfy->chain_cert = xcalloc(req_ca_vrfy->n_chain, - sizeof (unsigned char *)); - req_ca_vrfy->chain_cert_len = xcalloc(req_ca_vrfy->n_chain, - sizeof (off_t)); - return; - - case IMSG_SMTP_TLS_VERIFY_CHAIN: - case IMSG_MTA_TLS_VERIFY_CHAIN: - if (req_ca_vrfy == NULL) - fatalx("lka:ca_vrfy: chain without a certificate"); - req_ca_vrfy_chain = imsg->data; - req_ca_vrfy->chain_cert[req_ca_vrfy->chain_offset] = xmemdup((char *)imsg->data + - sizeof *req_ca_vrfy_chain, req_ca_vrfy_chain->cert_len); - req_ca_vrfy->chain_cert_len[req_ca_vrfy->chain_offset] = req_ca_vrfy_chain->cert_len; - req_ca_vrfy->chain_offset++; - return; - - case IMSG_SMTP_TLS_VERIFY: - case IMSG_MTA_TLS_VERIFY: - if (req_ca_vrfy == NULL) - fatalx("lka:ca_vrfy: verify without a certificate"); - lka_certificate_verify(imsg->hdr.type, req_ca_vrfy); - req_ca_vrfy = NULL; - return; - case IMSG_SMTP_AUTHENTICATE: m_msg(&m, imsg); m_get_id(&m, &reqid); @@ -304,7 +238,7 @@ lka_imsg(struct mproc *p, struct imsg *imsg) m_add_int(p, LKA_TEMPFAIL); } else { - ret = table_fetch(table, NULL, K_SOURCE, &lk); + ret = table_fetch(table, K_SOURCE, &lk); if (ret == -1) m_add_int(p, LKA_TEMPFAIL); else if (ret == 0) @@ -352,7 +286,7 @@ lka_imsg(struct mproc *p, struct imsg *imsg) m_add_int(p, LKA_TEMPFAIL); } else { - ret = table_fetch(table, NULL, K_RELAYHOST, &lk); + ret = table_fetch(table, K_RELAYHOST, &lk); if (ret == -1) m_add_int(p, LKA_TEMPFAIL); else if (ret == 0) @@ -759,7 +693,7 @@ lka_authenticate(const char *tablename, const char *user, const char *password) return (LKA_TEMPFAIL); } - switch (table_lookup(table, NULL, user, K_CREDENTIALS, &lk)) { + switch (table_lookup(table, K_CREDENTIALS, user, &lk)) { case -1: log_warnx("warn: user credentials lookup fail for %s:%s", tablename, user); @@ -789,7 +723,7 @@ lka_credentials(const char *tablename, const char *label, char *dst, size_t sz) dst[0] = '\0'; - switch (table_lookup(table, NULL, label, K_CREDENTIALS, &lk)) { + switch (table_lookup(table, K_CREDENTIALS, label, &lk)) { case -1: log_warnx("warn: credentials lookup fail for %s:%s", tablename, label); @@ -830,7 +764,7 @@ lka_userinfo(const char *tablename, const char *username, struct userinfo *res) return (LKA_TEMPFAIL); } - switch (table_lookup(table, NULL, username, K_USERINFO, &lk)) { + switch (table_lookup(table, K_USERINFO, username, &lk)) { case -1: log_warnx("warn: failure during userinfo lookup %s:%s", tablename, username); @@ -860,7 +794,7 @@ lka_addrname(const char *tablename, const struct sockaddr *sa, return (LKA_TEMPFAIL); } - switch (table_lookup(table, NULL, source, K_ADDRNAME, &lk)) { + switch (table_lookup(table, K_ADDRNAME, source, &lk)) { case -1: log_warnx("warn: failure during helo lookup %s:%s", tablename, source); @@ -888,7 +822,7 @@ lka_mailaddrmap(const char *tablename, const char *username, const struct mailad return (LKA_TEMPFAIL); } - switch (table_lookup(table, NULL, username, K_MAILADDRMAP, &lk)) { + switch (table_lookup(table, K_MAILADDRMAP, username, &lk)) { case -1: log_warnx("warn: failure during mailaddrmap lookup %s:%s", tablename, username); @@ -910,88 +844,3 @@ lka_mailaddrmap(const char *tablename, const char *username, const struct mailad } return (LKA_OK); } - -static int -lka_X509_verify(struct ca_vrfy_req_msg *vrfy, - const char *CAfile, const char *CRLfile) -{ - X509 *x509; - X509 *x509_tmp; - STACK_OF(X509) *x509_chain; - const unsigned char *d2i; - size_t i; - int ret = 0; - const char *errstr; - - x509 = NULL; - x509_tmp = NULL; - x509_chain = NULL; - - d2i = vrfy->cert; - if (d2i_X509(&x509, &d2i, vrfy->cert_len) == NULL) { - x509 = NULL; - goto end; - } - - if (vrfy->n_chain) { - x509_chain = sk_X509_new_null(); - for (i = 0; i < vrfy->n_chain; ++i) { - d2i = vrfy->chain_cert[i]; - if (d2i_X509(&x509_tmp, &d2i, vrfy->chain_cert_len[i]) == NULL) - goto end; - sk_X509_insert(x509_chain, x509_tmp, i); - x509_tmp = NULL; - } - } - if (!ca_X509_verify(x509, x509_chain, CAfile, NULL, &errstr)) - log_debug("debug: lka: X509 verify: %s", errstr); - else - ret = 1; - -end: - X509_free(x509); - X509_free(x509_tmp); - if (x509_chain) - sk_X509_pop_free(x509_chain, X509_free); - - return ret; -} - -static void -lka_certificate_verify(enum imsg_type type, struct ca_vrfy_req_msg *req) -{ - lka_certificate_verify_resume(type, req); -} - -static void -lka_certificate_verify_resume(enum imsg_type type, struct ca_vrfy_req_msg *req) -{ - struct ca_vrfy_resp_msg resp; - struct ca *sca; - const char *cafile; - size_t i; - - resp.reqid = req->reqid; - sca = dict_get(env->sc_ca_dict, req->name); - if (sca == NULL) - if (req->fallback) - sca = dict_get(env->sc_ca_dict, "*"); - cafile = sca ? sca->ca_cert_file : CA_FILE; - - if (sca == NULL && !req->fallback) - resp.status = CA_FAIL; - else if (!lka_X509_verify(req, cafile, NULL)) - resp.status = CA_FAIL; - else - resp.status = CA_OK; - - m_compose(p_pony, type, 0, 0, -1, &resp, - sizeof resp); - - for (i = 0; i < req->n_chain; ++i) - free(req->chain_cert[i]); - free(req->chain_cert); - free(req->chain_cert_len); - free(req->cert); - free(req); -} diff --git a/smtpd/lka_filter.c b/smtpd/lka_filter.c index d6916e86..4135de19 100644 --- a/smtpd/lka_filter.c +++ b/smtpd/lka_filter.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lka_filter.c,v 1.28 2018/12/22 13:09:05 gilles Exp $ */ +/* $OpenBSD: lka_filter.c,v 1.33 2018/12/26 15:55:09 eric Exp $ */ /* * Copyright (c) 2018 Gilles Chehade <gilles@poolp.org> @@ -140,6 +140,7 @@ lka_filter_init(void) struct filter *filter; struct filter_config *filter_config; size_t i; + char buffer[LINE_MAX]; /* for traces */ dict_init(&filters); dict_init(&filter_chains); @@ -154,6 +155,8 @@ lka_filter_init(void) filter->phases |= (1<<filter_config->phase); filter->config = filter_config; dict_set(&filters, name, filter); + log_trace(TRACE_FILTERS, "filters init type=builtin, name=%s, hooks=%08x", + name, filter->phases); break; case FILTER_TYPE_PROC: @@ -162,6 +165,8 @@ lka_filter_init(void) filter->proc = filter_config->proc; filter->config = filter_config; dict_set(&filters, name, filter); + log_trace(TRACE_FILTERS, "filters init type=proc, name=%s, proc=%s", + name, filter_config->proc); break; case FILTER_TYPE_CHAIN: @@ -179,8 +184,16 @@ lka_filter_init(void) filter->chain = xcalloc(filter_config->chain_size, sizeof(void **)); filter->chain_size = filter_config->chain_size; filter->config = filter_config; - for (i = 0; i < filter->chain_size; ++i) + + buffer[0] = '\0'; + for (i = 0; i < filter->chain_size; ++i) { filter->chain[i] = dict_xget(&filters, filter_config->chain[i]); + if (i) + (void)strlcat(buffer, ", ", sizeof buffer); + (void)strlcat(buffer, filter->chain[i]->name, sizeof buffer); + } + log_trace(TRACE_FILTERS, "filters init type=chain, name=%s { %s }", name, buffer); + dict_set(&filters, name, filter); break; @@ -315,6 +328,8 @@ lka_filter_begin(uint64_t reqid, fs->rdns = xstrdup(rdns); fs->fcrdns = fcrdns; tree_xset(&sessions, fs->id, fs); + + log_trace(TRACE_FILTERS, "%016"PRIx64" filters session-begin", reqid); } void @@ -325,6 +340,7 @@ lka_filter_end(uint64_t reqid) fs = tree_xpop(&sessions, reqid); free(fs->rdns); free(fs); + log_trace(TRACE_FILTERS, "%016"PRIx64" filters session-end", reqid); } void @@ -350,6 +366,7 @@ end: m_add_id(p_pony, reqid); m_add_int(p_pony, fd != -1 ? 1 : 0); m_close(p_pony); + log_trace(TRACE_FILTERS, "%016"PRIx64" filters data-begin fd=%d", reqid, fd); } void @@ -362,6 +379,7 @@ lka_filter_data_end(uint64_t reqid) io_free(fs->io); fs->io = NULL; } + log_trace(TRACE_FILTERS, "%016"PRIx64" filters data-end", reqid); } static void @@ -497,9 +515,13 @@ filter_protocol_internal(struct filter_session *fs, uint64_t *token, uint64_t re struct filter_chain *filter_chain; struct filter_entry *filter_entry; struct filter *filter; + const char *phase_name = filter_execs[phase].phase_name; + int resume = 1; - if (!*token) + if (!*token) { fs->phase = phase; + resume = 0; + } /* XXX - this sanity check requires a protocol change, stub for now */ phase = fs->phase; @@ -520,6 +542,9 @@ filter_protocol_internal(struct filter_session *fs, uint64_t *token, uint64_t re /* no filter_entry, we either had none or reached end of chain */ if (filter_entry == NULL) { + log_trace(TRACE_FILTERS, "%016"PRIx64" filters protocol phase=%s, resume=%s, " + "action=proceed", + fs->id, phase_name, resume ? "y" : "n"); filter_result_proceed(reqid); return; } @@ -528,6 +553,10 @@ filter_protocol_internal(struct filter_session *fs, uint64_t *token, uint64_t re *token = filter_entry->id; filter = dict_get(&filters, filter_entry->name); if (filter->proc) { + log_trace(TRACE_FILTERS, "%016"PRIx64" filters protocol phase=%s, " + "resume=%s, action=deferred, filter=%s", + fs->id, phase_name, resume ? "y" : "n", + filter->name); filter_protocol_query(filter, filter_entry->id, reqid, filter_execs[fs->phase].phase_name, param); return; /* deferred response */ @@ -535,19 +564,43 @@ filter_protocol_internal(struct filter_session *fs, uint64_t *token, uint64_t re if (filter_execs[fs->phase].func(fs, filter, reqid, param)) { if (filter->config->rewrite) { - filter_result_rewrite(reqid, filter->config->rewrite); + log_trace(TRACE_FILTERS, "%016"PRIx64" filters protocol phase=%s, " + "resume=%s, action=rewrite, filter=%s, query=%s, response=%s", + fs->id, phase_name, resume ? "y" : "n", + filter->name, + param, + filter->config->rewrite); + filter_result_rewrite(reqid, filter->config->rewrite); return; } else if (filter->config->disconnect) { + log_trace(TRACE_FILTERS, "%016"PRIx64" filters protocol phase=%s, " + "resume=%s, action=disconnect, filter=%s, query=%s, response=%s", + fs->id, phase_name, resume ? "y" : "n", + filter->name, + param, + filter->config->disconnect); filter_result_disconnect(reqid, filter->config->disconnect); return; } else { + log_trace(TRACE_FILTERS, "%016"PRIx64" filters protocol phase=%s, " + "resume=%s, action=reject, filter=%s, query=%s, response=%s", + fs->id, phase_name, resume ? "y" : "n", + filter->name, + param, + filter->config->reject); filter_result_reject(reqid, filter->config->reject); return; } } + log_trace(TRACE_FILTERS, "%016"PRIx64" filters protocol phase=%s, " + "resume=%s, action=proceed, filter=%s, query=%s", + fs->id, phase_name, resume ? "y" : "n", + filter->name, + param); + /* filter_entry resulted in proceed, try next filter */ filter_protocol_internal(fs, token, reqid, phase, param); return; @@ -593,7 +646,8 @@ filter_protocol(uint64_t reqid, enum filter_phase phase, const char *param) { struct filter_session *fs; uint64_t token = 0; - + char *nparam = NULL; + fs = tree_xget(&sessions, reqid); switch (phase) { @@ -609,8 +663,14 @@ filter_protocol(uint64_t reqid, enum filter_phase phase, const char *param) fs->mail_from = xstrdup(param + 1); *strchr(fs->mail_from, '>') = '\0'; + param = fs->mail_from; break; + case FILTER_RCPT_TO: + nparam = xstrdup(param + 1); + *strchr(nparam, '>') = '\0'; + param = nparam; + break; case FILTER_STARTTLS: case FILTER_AUTH: /* TBD */ @@ -619,6 +679,8 @@ filter_protocol(uint64_t reqid, enum filter_phase phase, const char *param) break; } filter_protocol_internal(fs, &token, reqid, phase, param); + if (nparam) + free(nparam); } static void @@ -743,12 +805,13 @@ filter_check_rdns_table(struct filter *filter, enum table_service kind, const ch { int ret = 0; - if (filter->config->rdns_table) { - if (table_lookup(filter->config->rdns_table, NULL, key, kind, NULL) > 0) - ret = 1; - ret = filter->config->not_rdns_table < 0 ? !ret : ret; - } - return ret; + if (filter->config->rdns_table == NULL) + return 0; + + if (table_match(filter->config->rdns_table, kind, key) > 0) + ret = 1; + + return filter->config->not_rdns_table < 0 ? !ret : ret; } static int @@ -756,12 +819,12 @@ filter_check_rdns_regex(struct filter *filter, const char *key) { int ret = 0; - if (filter->config->rdns_regex) { - if (table_lookup(filter->config->rdns_regex, NULL, key, K_REGEX, NULL) > 0) - ret = 1; - ret = filter->config->not_rdns_regex < 0 ? !ret : ret; - } - return ret; + if (filter->config->rdns_regex == NULL) + return 0; + + if (table_match(filter->config->rdns_regex, K_REGEX, key) > 0) + ret = 1; + return filter->config->not_rdns_regex < 0 ? !ret : ret; } static int @@ -769,12 +832,12 @@ filter_check_src_table(struct filter *filter, enum table_service kind, const cha { int ret = 0; - if (filter->config->src_table) { - if (table_lookup(filter->config->src_table, NULL, key, kind, NULL) > 0) - ret = 1; - ret = filter->config->not_src_table < 0 ? !ret : ret; - } - return ret; + if (filter->config->src_table == NULL) + return 0; + + if (table_match(filter->config->src_table, kind, key) > 0) + ret = 1; + return filter->config->not_src_table < 0 ? !ret : ret; } static int @@ -782,12 +845,12 @@ filter_check_src_regex(struct filter *filter, const char *key) { int ret = 0; - if (filter->config->src_regex) { - if (table_lookup(filter->config->src_regex, NULL, key, K_REGEX, NULL) > 0) - ret = 1; - ret = filter->config->not_src_regex < 0 ? !ret : ret; - } - return ret; + if (filter->config->src_regex == NULL) + return 0; + + if (table_match(filter->config->src_regex, K_REGEX, key) > 0) + ret = 1; + return filter->config->not_src_regex < 0 ? !ret : ret; } static int @@ -795,12 +858,12 @@ filter_check_helo_table(struct filter *filter, enum table_service kind, const ch { int ret = 0; - if (filter->config->helo_table) { - if (table_lookup(filter->config->helo_table, NULL, key, kind, NULL) > 0) - ret = 1; - ret = filter->config->not_helo_table < 0 ? !ret : ret; - } - return ret; + if (filter->config->helo_table == NULL) + return 0; + + if (table_match(filter->config->helo_table, kind, key) > 0) + ret = 1; + return filter->config->not_helo_table < 0 ? !ret : ret; } static int @@ -808,12 +871,12 @@ filter_check_helo_regex(struct filter *filter, const char *key) { int ret = 0; - if (filter->config->helo_regex) { - if (table_lookup(filter->config->helo_regex, NULL, key, K_REGEX, NULL) > 0) - ret = 1; - ret = filter->config->not_helo_regex < 0 ? !ret : ret; - } - return ret; + if (filter->config->helo_regex == NULL) + return 0; + + if (table_match(filter->config->helo_regex, K_REGEX, key) > 0) + ret = 1; + return filter->config->not_helo_regex < 0 ? !ret : ret; } static int @@ -821,12 +884,12 @@ filter_check_mail_from_table(struct filter *filter, enum table_service kind, con { int ret = 0; - if (filter->config->mail_from_table) { - if (table_lookup(filter->config->mail_from_table, NULL, key, kind, NULL) > 0) - ret = 1; - ret = filter->config->not_mail_from_table < 0 ? !ret : ret; - } - return ret; + if (filter->config->mail_from_table == NULL) + return 0; + + if (table_match(filter->config->mail_from_table, kind, key) > 0) + ret = 1; + return filter->config->not_mail_from_table < 0 ? !ret : ret; } static int @@ -834,12 +897,12 @@ filter_check_mail_from_regex(struct filter *filter, const char *key) { int ret = 0; - if (filter->config->mail_from_regex) { - if (table_lookup(filter->config->mail_from_regex, NULL, key, K_REGEX, NULL) > 0) - ret = 1; - ret = filter->config->not_mail_from_regex < 0 ? !ret : ret; - } - return ret; + if (filter->config->mail_from_regex == NULL) + return 0; + + if (table_match(filter->config->mail_from_regex, K_REGEX, key) > 0) + ret = 1; + return filter->config->not_mail_from_regex < 0 ? !ret : ret; } static int @@ -847,12 +910,12 @@ filter_check_rcpt_to_table(struct filter *filter, enum table_service kind, const { int ret = 0; - if (filter->config->rcpt_to_table) { - if (table_lookup(filter->config->rcpt_to_table, NULL, key, kind, NULL) > 0) - ret = 1; - ret = filter->config->not_rcpt_to_table < 0 ? !ret : ret; - } - return ret; + if (filter->config->rcpt_to_table == NULL) + return 0; + + if (table_match(filter->config->rcpt_to_table, kind, key) > 0) + ret = 1; + return filter->config->not_rcpt_to_table < 0 ? !ret : ret; } static int @@ -860,12 +923,12 @@ filter_check_rcpt_to_regex(struct filter *filter, const char *key) { int ret = 0; - if (filter->config->rcpt_to_regex) { - if (table_lookup(filter->config->rcpt_to_regex, NULL, key, K_REGEX, NULL) > 0) - ret = 1; - ret = filter->config->not_rcpt_to_regex < 0 ? !ret : ret; - } - return ret; + if (filter->config->rcpt_to_regex == NULL) + return 0; + + if (table_match(filter->config->rcpt_to_regex, K_REGEX, key) > 0) + ret = 1; + return filter->config->not_rcpt_to_regex < 0 ? !ret : ret; } static int @@ -873,11 +936,11 @@ filter_check_fcrdns(struct filter *filter, int fcrdns) { int ret = 0; - if (filter->config->fcrdns) { - ret = fcrdns == 0; - ret = filter->config->not_fcrdns < 0 ? !ret : ret; - } - return ret; + if (!filter->config->fcrdns) + return 0; + + ret = fcrdns == 0; + return filter->config->not_fcrdns < 0 ? !ret : ret; } static int @@ -886,14 +949,14 @@ filter_check_rdns(struct filter *filter, const char *hostname) int ret = 0; struct netaddr netaddr; - if (filter->config->rdns) { - /* if text_to_netaddress succeeds, - * we don't have an rDNS so the filter should match - */ - ret = text_to_netaddr(&netaddr, hostname); - ret = filter->config->not_rdns < 0 ? !ret : ret; - } - return ret; + if (!filter->config->rdns) + return 0; + + /* if text_to_netaddress succeeds, + * we don't have an rDNS so the filter should match + */ + ret = text_to_netaddr(&netaddr, hostname); + return filter->config->not_rdns < 0 ? !ret : ret; } static int @@ -903,9 +966,9 @@ filter_builtins_notimpl(struct filter_session *fs, struct filter *filter, uint64 } static int -filter_builtins_global(struct filter_session *fs, struct filter *filter, uint64_t reqid, const char *param) +filter_builtins_global(struct filter_session *fs, struct filter *filter, uint64_t reqid) { - if (filter_check_fcrdns(filter, fs->fcrdns) || + return filter_check_fcrdns(filter, fs->fcrdns) || filter_check_rdns(filter, fs->rdns) || filter_check_rdns_table(filter, K_DOMAIN, fs->rdns) || filter_check_rdns_regex(filter, fs->rdns) || @@ -914,43 +977,31 @@ filter_builtins_global(struct filter_session *fs, struct filter *filter, uint64_ filter_check_helo_table(filter, K_DOMAIN, fs->helo) || filter_check_helo_regex(filter, fs->helo) || filter_check_mail_from_table(filter, K_MAILADDR, fs->mail_from) || - filter_check_mail_from_regex(filter, fs->mail_from)) - return 1; - return 0; + filter_check_mail_from_regex(filter, fs->mail_from); } static int filter_builtins_connect(struct filter_session *fs, struct filter *filter, uint64_t reqid, const char *param) { - return filter_builtins_global(fs, filter, reqid, param); + return filter_builtins_global(fs, filter, reqid); } static int filter_builtins_helo(struct filter_session *fs, struct filter *filter, uint64_t reqid, const char *param) { - return filter_builtins_global(fs, filter, reqid, param); + return filter_builtins_global(fs, filter, reqid); } static int filter_builtins_mail_from(struct filter_session *fs, struct filter *filter, uint64_t reqid, const char *param) { - return filter_builtins_global(fs, filter, reqid, param); + return filter_builtins_global(fs, filter, reqid); } static int filter_builtins_rcpt_to(struct filter_session *fs, struct filter *filter, uint64_t reqid, const char *param) { - int ret = 0; - char *rcpt_to; - - rcpt_to = xstrdup(param + 1); - *strchr(rcpt_to, '>') = '\0'; - - if (filter_builtins_global(fs, filter, reqid, param) || - filter_check_rcpt_to_table(filter, K_MAILADDR, rcpt_to) || - filter_check_rcpt_to_regex(filter, rcpt_to)) - ret = 1; - - free(rcpt_to); - return ret; + return filter_builtins_global(fs, filter, reqid) || + filter_check_rcpt_to_table(filter, K_MAILADDR, param) || + filter_check_rcpt_to_regex(filter, param); } diff --git a/smtpd/lka_session.c b/smtpd/lka_session.c index bca6ad31..0ab78368 100644 --- a/smtpd/lka_session.c +++ b/smtpd/lka_session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lka_session.c,v 1.88 2018/11/01 18:01:51 gilles Exp $ */ +/* $OpenBSD: lka_session.c,v 1.90 2018/12/26 20:13:43 eric Exp $ */ /* * Copyright (c) 2011 Gilles Chehade <gilles@poolp.org> @@ -379,7 +379,7 @@ lka_expand(struct lka_session *lks, struct rule *rule, struct expandnode *xn) *tag++ = '\0'; userbase = table_find(env, dsp->u.local.table_userbase, NULL); - r = table_lookup(userbase, NULL, xn->u.user, K_USERINFO, &lk); + r = table_lookup(userbase, K_USERINFO, xn->u.user, &lk); if (r == -1) { log_trace(TRACE_EXPAND, "expand: lka_expand: " "backend error while searching user"); diff --git a/smtpd/mta.c b/smtpd/mta.c index a1e0c030..ec1be548 100644 --- a/smtpd/mta.c +++ b/smtpd/mta.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mta.c,v 1.226 2018/09/24 16:14:34 eric Exp $ */ +/* $OpenBSD: mta.c,v 1.227 2018/12/23 16:37:53 eric Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -315,14 +315,6 @@ mta_imsg(struct mproc *p, struct imsg *imsg) mta_on_preference(relay, preference); return; - case IMSG_MTA_TLS_INIT: - mta_session_imsg(p, imsg); - return; - - case IMSG_MTA_TLS_VERIFY: - mta_session_imsg(p, imsg); - return; - case IMSG_CTL_RESUME_ROUTE: u64 = *((uint64_t *)imsg->data); if (u64) diff --git a/smtpd/mta_session.c b/smtpd/mta_session.c index 655c205f..628b0ed1 100644 --- a/smtpd/mta_session.c +++ b/smtpd/mta_session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mta_session.c,v 1.114 2018/12/17 11:14:56 eric Exp $ */ +/* $OpenBSD: mta_session.c,v 1.115 2018/12/23 16:37:53 eric Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -150,8 +150,6 @@ static void mta_send(struct mta_session *, char *, ...); static ssize_t mta_queue_data(struct mta_session *); static void mta_response(struct mta_session *, char *); static const char * mta_strstate(int); -static void mta_start_tls(struct mta_session *); -static int mta_verify_certificate(struct mta_session *); static void mta_cert_init(struct mta_session *); static void mta_cert_init_cb(void *, int, const char *, const void *, size_t); static void mta_cert_verify(struct mta_session *); @@ -244,13 +242,10 @@ mta_session(struct mta_relay *relay, struct mta_route *route) void mta_session_imsg(struct mproc *p, struct imsg *imsg) { - struct ca_vrfy_resp_msg *resp_ca_vrfy; - struct ca_cert_resp_msg *resp_ca_cert; struct mta_session *s; struct msg m; uint64_t reqid; const char *name; - void *ssl; int status; struct stat sb; @@ -302,61 +297,6 @@ mta_session_imsg(struct mproc *p, struct imsg *imsg) mta_enter_state(s, MTA_MAIL); return; - case IMSG_MTA_TLS_INIT: - resp_ca_cert = imsg->data; - s = mta_tree_pop(&wait_ssl_init, resp_ca_cert->reqid); - if (s == NULL) - return; - - if (resp_ca_cert->status == CA_FAIL) { - if (s->relay->pki_name) { - log_info("%016"PRIx64" mta " - "closing reason=ca-failure", - s->id); - mta_free(s); - return; - } - else { - ssl = ssl_mta_init(NULL, NULL, 0, env->sc_tls_ciphers); - if (ssl == NULL) - fatal("mta: ssl_mta_init"); - io_start_tls(s->io, ssl); - return; - } - } - - resp_ca_cert = xmemdup(imsg->data, sizeof *resp_ca_cert); - resp_ca_cert->cert = xstrdup((char *)imsg->data + - sizeof *resp_ca_cert); - ssl = ssl_mta_init(resp_ca_cert->name, - resp_ca_cert->cert, resp_ca_cert->cert_len, env->sc_tls_ciphers); - if (ssl == NULL) - fatal("mta: ssl_mta_init"); - io_start_tls(s->io, ssl); - - freezero(resp_ca_cert->cert, resp_ca_cert->cert_len); - free(resp_ca_cert); - return; - - case IMSG_MTA_TLS_VERIFY: - resp_ca_vrfy = imsg->data; - s = mta_tree_pop(&wait_ssl_verify, resp_ca_vrfy->reqid); - if (s == NULL) - return; - - if (resp_ca_vrfy->status == CA_OK) - s->flags |= MTA_TLS_VERIFIED; - else if (s->relay->flags & RELAY_TLS_VERIFY) { - errno = 0; - mta_error(s, "SSL certificate check failed"); - mta_free(s); - return; - } - - mta_tls_verified(s); - io_resume(s->io, IO_IN); - return; - case IMSG_MTA_LOOKUP_HELO: m_msg(&m, imsg); m_get_id(&m, &reqid); @@ -1510,153 +1450,6 @@ mta_error(struct mta_session *s, const char *fmt, ...) } static void -mta_start_tls(struct mta_session *s) -{ - struct ca_cert_req_msg req_ca_cert; - const char *certname; - - if (s->relay->pki_name) { - certname = s->relay->pki_name; - req_ca_cert.fallback = 0; - } - else { - certname = s->helo; - req_ca_cert.fallback = 1; - } - - req_ca_cert.reqid = s->id; - (void)strlcpy(req_ca_cert.name, certname, sizeof req_ca_cert.name); - m_compose(p_lka, IMSG_MTA_TLS_INIT, 0, 0, -1, - &req_ca_cert, sizeof(req_ca_cert)); - tree_xset(&wait_ssl_init, s->id, s); - s->flags |= MTA_WAIT; - return; -} - -static int -mta_verify_certificate(struct mta_session *s) -{ -#define MAX_CERTS 16 -#define MAX_CERT_LEN (MAX_IMSGSIZE - (IMSG_HEADER_SIZE + sizeof(req_ca_vrfy))) - struct ca_vrfy_req_msg req_ca_vrfy; - struct iovec iov[2]; - X509 *x; - STACK_OF(X509) *xchain; - const char *name; - unsigned char *cert_der[MAX_CERTS]; - int cert_len[MAX_CERTS]; - int i, cert_count, res; - - res = 0; - memset(cert_der, 0, sizeof(cert_der)); - memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy); - - /* Send the client certificate */ - if (s->relay->ca_name) { - name = s->relay->ca_name; - req_ca_vrfy.fallback = 0; - } - else { - name = s->helo; - req_ca_vrfy.fallback = 1; - } - if (strlcpy(req_ca_vrfy.name, name, sizeof req_ca_vrfy.name) - >= sizeof req_ca_vrfy.name) - return 0; - - x = SSL_get_peer_certificate(io_ssl(s->io)); - if (x == NULL) - return 0; - xchain = SSL_get_peer_cert_chain(io_ssl(s->io)); - - /* - * Client provided a certificate and possibly a certificate chain. - * SMTP can't verify because it does not have the information that - * it needs, instead it will pass the certificate and chain to the - * lookup process and wait for a reply. - * - */ - - cert_len[0] = i2d_X509(x, &cert_der[0]); - X509_free(x); - - if (cert_len[0] < 0) { - log_warnx("warn: failed to encode certificate"); - goto end; - } - log_debug("debug: certificate 0: len=%d", cert_len[0]); - if (cert_len[0] > (int)MAX_CERT_LEN) { - log_warnx("warn: certificate too long"); - goto end; - } - - if (xchain) { - cert_count = sk_X509_num(xchain); - log_debug("debug: certificate chain len: %d", cert_count); - if (cert_count >= MAX_CERTS) { - log_warnx("warn: certificate chain too long"); - goto end; - } - } - else - cert_count = 0; - - for (i = 0; i < cert_count; ++i) { - x = sk_X509_value(xchain, i); - cert_len[i+1] = i2d_X509(x, &cert_der[i+1]); - if (cert_len[i+1] < 0) { - log_warnx("warn: failed to encode certificate"); - goto end; - } - log_debug("debug: certificate %i: len=%d", i+1, cert_len[i+1]); - if (cert_len[i+1] > (int)MAX_CERT_LEN) { - log_warnx("warn: certificate too long"); - goto end; - } - } - - tree_xset(&wait_ssl_verify, s->id, s); - s->flags |= MTA_WAIT; - - /* Send the client certificate */ - req_ca_vrfy.reqid = s->id; - req_ca_vrfy.cert_len = cert_len[0]; - req_ca_vrfy.n_chain = cert_count; - iov[0].iov_base = &req_ca_vrfy; - iov[0].iov_len = sizeof(req_ca_vrfy); - iov[1].iov_base = cert_der[0]; - iov[1].iov_len = cert_len[0]; - m_composev(p_lka, IMSG_MTA_TLS_VERIFY_CERT, 0, 0, -1, - iov, nitems(iov)); - - memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy); - req_ca_vrfy.reqid = s->id; - - /* Send the chain, one cert at a time */ - for (i = 0; i < cert_count; ++i) { - req_ca_vrfy.cert_len = cert_len[i+1]; - iov[1].iov_base = cert_der[i+1]; - iov[1].iov_len = cert_len[i+1]; - m_composev(p_lka, IMSG_MTA_TLS_VERIFY_CHAIN, 0, 0, -1, - iov, nitems(iov)); - } - - /* Tell lookup process that it can start verifying, we're done */ - memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy); - req_ca_vrfy.reqid = s->id; - m_compose(p_lka, IMSG_MTA_TLS_VERIFY, 0, 0, -1, - &req_ca_vrfy, sizeof req_ca_vrfy); - - res = 1; - - end: - for (i = 0; i < MAX_CERTS; ++i) - free(cert_der[i]); - - return res; -} - -static void mta_cert_init(struct mta_session *s) { const char *name; diff --git a/smtpd/parse.y b/smtpd/parse.y index 539faf6d..7424cd3c 100644 --- a/smtpd/parse.y +++ b/smtpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.246 2018/12/22 13:09:05 gilles Exp $ */ +/* $OpenBSD: parse.y,v 1.248 2018/12/23 15:49:04 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org> @@ -113,7 +113,8 @@ struct dispatcher *dispatcher; struct rule *rule; struct processor *processor; struct filter_config *filter_config; -static uint64_t last_dynproc_id = 1; +static uint32_t last_dynchain_id = 1; +static uint32_t last_dynproc_id = 1; enum listen_options { LO_FAMILY = 0x000001, @@ -1597,7 +1598,7 @@ FILTER STRING PROC_EXEC STRING { char buffer[128]; do { - (void)snprintf(buffer, sizeof buffer, "<dynproc:%016"PRIx64">", last_dynproc_id++); + (void)snprintf(buffer, sizeof buffer, "<dynproc:%08x>", last_dynproc_id++); } while (dict_check(conf->sc_processors_dict, buffer)); if (dict_get(conf->sc_filters_dict, $2)) { @@ -1804,6 +1805,27 @@ opt_sock_listen : FILTER STRING { listen_opts.options |= LO_FILTER; listen_opts.filtername = $2; } + | FILTER { + char buffer[128]; + + if (listen_opts.options & LO_FILTER) { + yyerror("filter already specified"); + YYERROR; + } + + do { + (void)snprintf(buffer, sizeof buffer, "<dynchain:%08x>", last_dynchain_id++); + } while (dict_check(conf->sc_filters_dict, buffer)); + + listen_opts.options |= LO_FILTER; + listen_opts.filtername = xstrdup(buffer); + filter_config = xcalloc(1, sizeof *filter_config); + filter_config->filter_type = FILTER_TYPE_CHAIN; + dict_init(&filter_config->chain_procs); + } '{' filter_list '}' { + dict_set(conf->sc_filters_dict, listen_opts.filtername, filter_config); + filter_config = NULL; + } | MASK_SRC { if (config_lo_mask_source(&listen_opts)) { YYERROR; @@ -1871,6 +1893,27 @@ opt_if_listen : INET4 { listen_opts.options |= LO_FILTER; listen_opts.filtername = $2; } + | FILTER { + char buffer[128]; + + if (listen_opts.options & LO_FILTER) { + yyerror("filter already specified"); + YYERROR; + } + + do { + (void)snprintf(buffer, sizeof buffer, "<dynchain:%08x>", last_dynchain_id++); + } while (dict_check(conf->sc_filters_dict, buffer)); + + listen_opts.options |= LO_FILTER; + listen_opts.filtername = xstrdup(buffer); + filter_config = xcalloc(1, sizeof *filter_config); + filter_config->filter_type = FILTER_TYPE_CHAIN; + dict_init(&filter_config->chain_procs); + } '{' filter_list '}' { + dict_set(conf->sc_filters_dict, listen_opts.filtername, filter_config); + filter_config = NULL; + } | SMTPS { if (listen_opts.options & LO_SSL) { yyerror("TLS mode already specified"); diff --git a/smtpd/pony.c b/smtpd/pony.c index 75742fa7..238f0244 100644 --- a/smtpd/pony.c +++ b/smtpd/pony.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pony.c,v 1.25 2018/12/11 13:40:30 gilles Exp $ */ +/* $OpenBSD: pony.c,v 1.26 2018/12/23 16:37:53 eric Exp $ */ /* * Copyright (c) 2014 Gilles Chehade <gilles@poolp.org> @@ -93,8 +93,6 @@ pony_imsg(struct mproc *p, struct imsg *imsg) case IMSG_SMTP_EXPAND_RCPT: case IMSG_SMTP_LOOKUP_HELO: case IMSG_SMTP_AUTHENTICATE: - case IMSG_SMTP_TLS_INIT: - case IMSG_SMTP_TLS_VERIFY: case IMSG_SMTP_MESSAGE_COMMIT: case IMSG_SMTP_MESSAGE_CREATE: case IMSG_SMTP_MESSAGE_OPEN: @@ -119,8 +117,6 @@ pony_imsg(struct mproc *p, struct imsg *imsg) case IMSG_MTA_DNS_HOST: case IMSG_MTA_DNS_HOST_END: case IMSG_MTA_DNS_MX_PREFERENCE: - case IMSG_MTA_TLS_INIT: - case IMSG_MTA_TLS_VERIFY: case IMSG_CTL_RESUME_ROUTE: case IMSG_CTL_MTA_SHOW_HOSTS: case IMSG_CTL_MTA_SHOW_RELAYS: diff --git a/smtpd/ruleset.c b/smtpd/ruleset.c index 8fbeec01..715cc8d8 100644 --- a/smtpd/ruleset.c +++ b/smtpd/ruleset.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ruleset.c,v 1.38 2018/12/22 08:54:02 gilles Exp $ */ +/* $OpenBSD: ruleset.c,v 1.41 2018/12/26 17:37:15 eric Exp $ */ /* * Copyright (c) 2009 Gilles Chehade <gilles@poolp.org> @@ -35,22 +35,7 @@ #include "smtpd.h" #include "log.h" - -static int -ruleset_match_table_lookup(struct table *table, const char *key, enum table_service service) -{ - switch (table_lookup(table, NULL, key, service, NULL)) { - case 1: - return 1; - case -1: - log_warnx("warn: failure to perform a table lookup on table %s", - table->t_name); - return -1; - default: - break; - } - return 0; -} +#define MATCH_RESULT(r, neg) ((r) == -1 ? -1 : ((neg) < 0 ? !(r) : (r))) static int ruleset_match_tag(struct rule *r, const struct envelope *evp) @@ -66,10 +51,9 @@ ruleset_match_tag(struct rule *r, const struct envelope *evp) service = K_REGEX; table = table_find(env, r->table_tag, NULL); - if ((ret = ruleset_match_table_lookup(table, evp->tag, service)) < 0) - return ret; + ret = table_match(table, service, evp->tag); - return r->flag_tag < 0 ? !ret : ret; + return MATCH_RESULT(ret, r->flag_tag); } static int @@ -102,10 +86,9 @@ ruleset_match_from(struct rule *r, const struct envelope *evp) service = K_REGEX; table = table_find(env, r->table_from, NULL); - if ((ret = ruleset_match_table_lookup(table, key, service)) < 0) - return -1; + ret = table_match(table, service, key); - return r->flag_from < 0 ? !ret : ret; + return MATCH_RESULT(ret, r->flag_from); } static int @@ -122,11 +105,9 @@ ruleset_match_to(struct rule *r, const struct envelope *evp) service = K_REGEX; table = table_find(env, r->table_for, NULL); - if ((ret = ruleset_match_table_lookup(table, evp->dest.domain, - service)) < 0) - return -1; + ret = table_match(table, service, evp->dest.domain); - return r->flag_for < 0 ? !ret : ret; + return MATCH_RESULT(ret, r->flag_for); } static int @@ -143,10 +124,9 @@ ruleset_match_smtp_helo(struct rule *r, const struct envelope *evp) service = K_REGEX; table = table_find(env, r->table_smtp_helo, NULL); - if ((ret = ruleset_match_table_lookup(table, evp->helo, service)) < 0) - return -1; + ret = table_match(table, service, evp->helo); - return r->flag_smtp_helo < 0 ? !ret : ret; + return MATCH_RESULT(ret, r->flag_smtp_helo); } static int @@ -174,7 +154,7 @@ ruleset_match_smtp_auth(struct rule *r, const struct envelope *evp) /* * table = table_find(m->from_table, NULL); * key = evp->username; - * return ruleset_match_table_lookup(table, key, K_CREDENTIALS); + * return table_match(table, K_CREDENTIALS, key); */ return -1; @@ -182,7 +162,7 @@ ruleset_match_smtp_auth(struct rule *r, const struct envelope *evp) else ret = 1; - return r->flag_smtp_auth < 0 ? !ret : ret; + return MATCH_RESULT(ret, r->flag_smtp_auth); } static int @@ -203,10 +183,9 @@ ruleset_match_smtp_mail_from(struct rule *r, const struct envelope *evp) return -1; table = table_find(env, r->table_smtp_mail_from, NULL); - if ((ret = ruleset_match_table_lookup(table, key, service)) < 0) - return -1; + ret = table_match(table, service, key); - return r->flag_smtp_mail_from < 0 ? !ret : ret; + return MATCH_RESULT(ret, r->flag_smtp_mail_from); } static int @@ -227,10 +206,9 @@ ruleset_match_smtp_rcpt_to(struct rule *r, const struct envelope *evp) return -1; table = table_find(env, r->table_smtp_rcpt_to, NULL); - if ((ret = ruleset_match_table_lookup(table, key, service)) < 0) - return -1; + ret = table_match(table, service, key); - return r->flag_smtp_rcpt_to < 0 ? !ret : ret; + return MATCH_RESULT(ret, r->flag_smtp_rcpt_to); } struct rule * diff --git a/smtpd/smtp.c b/smtpd/smtp.c index fc8253f3..a0ab898b 100644 --- a/smtpd/smtp.c +++ b/smtpd/smtp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtp.c,v 1.163 2018/12/11 13:40:30 gilles Exp $ */ +/* $OpenBSD: smtp.c,v 1.164 2018/12/23 16:37:53 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org> @@ -71,8 +71,6 @@ smtp_imsg(struct mproc *p, struct imsg *imsg) case IMSG_SMTP_EXPAND_RCPT: case IMSG_SMTP_LOOKUP_HELO: case IMSG_SMTP_AUTHENTICATE: - case IMSG_SMTP_TLS_INIT: - case IMSG_SMTP_TLS_VERIFY: case IMSG_FILTER_SMTP_PROTOCOL: case IMSG_FILTER_SMTP_DATA_BEGIN: smtp_session_imsg(p, imsg); diff --git a/smtpd/smtp_session.c b/smtpd/smtp_session.c index a166d8c9..2a258a65 100644 --- a/smtpd/smtp_session.c +++ b/smtpd/smtp_session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtp_session.c,v 1.379 2018/12/21 14:41:41 gilles Exp $ */ +/* $OpenBSD: smtp_session.c,v 1.381 2018/12/26 11:29:13 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org> @@ -195,8 +195,6 @@ static void smtp_rfc4954_auth_plain(struct smtp_session *, char *); static void smtp_rfc4954_auth_login(struct smtp_session *, char *); static void smtp_free(struct smtp_session *, const char *); static const char *smtp_strstate(int); -static void smtp_tls_init(struct smtp_session *); -static int smtp_verify_certificate(struct smtp_session *); static void smtp_cert_init(struct smtp_session *); static void smtp_cert_init_cb(void *, int, const char *, const void *, size_t); static void smtp_cert_verify(struct smtp_session *); @@ -690,18 +688,14 @@ smtp_getaddrinfo_cb(void *arg, int gaierrno, struct addrinfo *ai0) void smtp_session_imsg(struct mproc *p, struct imsg *imsg) { - struct ca_cert_resp_msg *resp_ca_cert; - struct ca_vrfy_resp_msg *resp_ca_vrfy; struct smtp_session *s; struct smtp_rcpt *rcpt; - void *ssl; char user[LOGIN_NAME_MAX]; struct msg m; const char *line, *helo; uint64_t reqid, evpid; uint32_t msgid; int status, success; - void *ssl_ctx; int filter_response; const char *filter_param; uint8_t i; @@ -962,47 +956,6 @@ smtp_session_imsg(struct mproc *p, struct imsg *imsg) smtp_enter_state(s, STATE_HELO); return; - case IMSG_SMTP_TLS_INIT: - resp_ca_cert = imsg->data; - s = tree_xpop(&wait_ssl_init, resp_ca_cert->reqid); - - if (resp_ca_cert->status == CA_FAIL) { - log_info("%016"PRIx64" smtp disconnected " - "reason=ca-failure", - s->id); - smtp_free(s, "CA failure"); - return; - } - - resp_ca_cert = xmemdup(imsg->data, sizeof *resp_ca_cert); - resp_ca_cert->cert = xstrdup((char *)imsg->data + - sizeof *resp_ca_cert); - ssl_ctx = dict_get(env->sc_ssl_dict, resp_ca_cert->name); - ssl = ssl_smtp_init(ssl_ctx, s->listener->flags & F_TLS_VERIFY); - io_set_read(s->io); - io_start_tls(s->io, ssl); - - freezero(resp_ca_cert->cert, resp_ca_cert->cert_len); - free(resp_ca_cert); - return; - - case IMSG_SMTP_TLS_VERIFY: - resp_ca_vrfy = imsg->data; - s = tree_xpop(&wait_ssl_verify, resp_ca_vrfy->reqid); - - if (resp_ca_vrfy->status == CA_OK) - s->flags |= SF_VERIFIED; - else if (s->listener->flags & F_TLS_VERIFY) { - log_info("%016"PRIx64" smtp " - "disconnected reason=cert-check-failed", - s->id); - smtp_free(s, "SSL certificate check failed"); - return; - } - smtp_tls_verified(s); - io_resume(s->io, IO_IN); - return; - case IMSG_FILTER_SMTP_PROTOCOL: m_msg(&m, imsg); m_get_id(&m, &reqid); @@ -2181,150 +2134,6 @@ smtp_mailaddr(struct mailaddr *maddr, char *line, int mailfrom, char **args, } static void -smtp_tls_init(struct smtp_session *s) -{ - struct ca_cert_req_msg req_ca_cert; - - req_ca_cert.reqid = s->id; - if (s->listener->pki_name[0]) { - (void)strlcpy(req_ca_cert.name, s->listener->pki_name, - sizeof req_ca_cert.name); - req_ca_cert.fallback = 0; - } - else { - (void)strlcpy(req_ca_cert.name, s->smtpname, - sizeof req_ca_cert.name); - req_ca_cert.fallback = 1; - } - m_compose(p_lka, IMSG_SMTP_TLS_INIT, 0, 0, -1, - &req_ca_cert, sizeof(req_ca_cert)); - tree_xset(&wait_ssl_init, s->id, s); -} - -static int -smtp_verify_certificate(struct smtp_session *s) -{ -#define MAX_CERTS 16 -#define MAX_CERT_LEN (MAX_IMSGSIZE - (IMSG_HEADER_SIZE + sizeof(req_ca_vrfy))) - struct ca_vrfy_req_msg req_ca_vrfy; - struct iovec iov[2]; - X509 *x; - STACK_OF(X509) *xchain; - const char *name; - unsigned char *cert_der[MAX_CERTS]; - int cert_len[MAX_CERTS]; - int i, cert_count, res; - - res = 0; - memset(cert_der, 0, sizeof(cert_der)); - memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy); - - /* Send the client certificate */ - if (s->listener->ca_name[0]) { - name = s->listener->ca_name; - req_ca_vrfy.fallback = 0; - } - else { - name = s->smtpname; - req_ca_vrfy.fallback = 1; - } - - if (strlcpy(req_ca_vrfy.name, name, sizeof req_ca_vrfy.name) - >= sizeof req_ca_vrfy.name) - return 0; - - x = SSL_get_peer_certificate(io_ssl(s->io)); - if (x == NULL) - return 0; - xchain = SSL_get_peer_cert_chain(io_ssl(s->io)); - - /* - * Client provided a certificate and possibly a certificate chain. - * SMTP can't verify because it does not have the information that - * it needs, instead it will pass the certificate and chain to the - * lookup process and wait for a reply. - * - */ - - cert_len[0] = i2d_X509(x, &cert_der[0]); - X509_free(x); - - if (cert_len[0] < 0) { - log_warnx("warn: failed to encode certificate"); - goto end; - } - log_debug("debug: certificate 0: len=%d", cert_len[0]); - if (cert_len[0] > (int)MAX_CERT_LEN) { - log_warnx("warn: certificate too long"); - goto end; - } - - if (xchain) { - cert_count = sk_X509_num(xchain); - log_debug("debug: certificate chain len: %d", cert_count); - if (cert_count >= MAX_CERTS) { - log_warnx("warn: certificate chain too long"); - goto end; - } - } - else - cert_count = 0; - - for (i = 0; i < cert_count; ++i) { - x = sk_X509_value(xchain, i); - cert_len[i+1] = i2d_X509(x, &cert_der[i+1]); - if (cert_len[i+1] < 0) { - log_warnx("warn: failed to encode certificate"); - goto end; - } - log_debug("debug: certificate %i: len=%d", i+1, cert_len[i+1]); - if (cert_len[i+1] > (int)MAX_CERT_LEN) { - log_warnx("warn: certificate too long"); - goto end; - } - } - - tree_xset(&wait_ssl_verify, s->id, s); - - /* Send the client certificate */ - req_ca_vrfy.reqid = s->id; - req_ca_vrfy.cert_len = cert_len[0]; - req_ca_vrfy.n_chain = cert_count; - iov[0].iov_base = &req_ca_vrfy; - iov[0].iov_len = sizeof(req_ca_vrfy); - iov[1].iov_base = cert_der[0]; - iov[1].iov_len = cert_len[0]; - m_composev(p_lka, IMSG_SMTP_TLS_VERIFY_CERT, 0, 0, -1, - iov, nitems(iov)); - - memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy); - req_ca_vrfy.reqid = s->id; - - /* Send the chain, one cert at a time */ - for (i = 0; i < cert_count; ++i) { - req_ca_vrfy.cert_len = cert_len[i+1]; - iov[1].iov_base = cert_der[i+1]; - iov[1].iov_len = cert_len[i+1]; - m_composev(p_lka, IMSG_SMTP_TLS_VERIFY_CHAIN, 0, 0, -1, - iov, nitems(iov)); - } - - /* Tell lookup process that it can start verifying, we're done */ - memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy); - req_ca_vrfy.reqid = s->id; - m_compose(p_lka, IMSG_SMTP_TLS_VERIFY, 0, 0, -1, - &req_ca_vrfy, sizeof req_ca_vrfy); - - res = 1; - - end: - for (i = 0; i < MAX_CERTS; ++i) - free(cert_der[i]); - - return res; -} - -static void smtp_cert_init(struct smtp_session *s) { const char *name; @@ -2827,8 +2636,11 @@ static int smtp_tx_filtered_dataline(struct smtp_tx *tx, const char *line) { if (!strcmp(line, ".")) { - if (tx->error) - return 1; + /* XXX - this needs to be handled properly */ + /* + * if (tx->error) + * return 1; + */ line = NULL; } else { diff --git a/smtpd/smtpd-api.h b/smtpd/smtpd-api.h index 00f62071..f83edd05 100644 --- a/smtpd/smtpd-api.h +++ b/smtpd/smtpd-api.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd-api.h,v 1.35 2018/11/01 10:47:46 gilles Exp $ */ +/* $OpenBSD: smtpd-api.h,v 1.36 2018/12/23 16:06:24 gilles Exp $ */ /* * Copyright (c) 2013 Eric Faurot <eric@openbsd.org> @@ -20,24 +20,14 @@ #ifndef _SMTPD_API_H_ #define _SMTPD_API_H_ +#include "dict.h" +#include "tree.h" + struct mailaddr { char user[SMTPD_MAXLOCALPARTSIZE]; char domain[SMTPD_MAXDOMAINPARTSIZE]; }; -SPLAY_HEAD(_dict, dictentry); -SPLAY_HEAD(_tree, treeentry); - -struct tree { - struct _tree tree; - size_t count; -}; - -struct dict { - struct _dict dict; - size_t count; -}; - #define PROC_QUEUE_API_VERSION 2 enum { @@ -244,23 +234,6 @@ msgid_to_evpid(uint32_t msgid) return ((uint64_t)msgid << 32); } -/* dict.c */ -#define dict_init(d) do { SPLAY_INIT(&((d)->dict)); (d)->count = 0; } while(0) -#define dict_empty(d) SPLAY_EMPTY(&((d)->dict)) -#define dict_count(d) ((d)->count) -int dict_check(struct dict *, const char *); -void *dict_set(struct dict *, const char *, void *); -void dict_xset(struct dict *, const char *, void *); -void *dict_get(struct dict *, const char *); -void *dict_xget(struct dict *, const char *); -void *dict_pop(struct dict *, const char *); -void *dict_xpop(struct dict *, const char *); -int dict_poproot(struct dict *, void **); -int dict_root(struct dict *, const char **, void **); -int dict_iter(struct dict *, void **, const char **, void **); -int dict_iterfrom(struct dict *, void **, const char *, const char **, void **); -void dict_merge(struct dict *, struct dict *); - /* esc.c */ const char *esc_code(enum enhanced_status_class, enum enhanced_status_code); @@ -314,21 +287,4 @@ void table_api_on_fetch(int(*)(int, struct dict *, char *, size_t)); int table_api_dispatch(void); const char *table_api_get_name(void); -/* tree.c */ -#define tree_init(t) do { SPLAY_INIT(&((t)->tree)); (t)->count = 0; } while(0) -#define tree_empty(t) SPLAY_EMPTY(&((t)->tree)) -#define tree_count(t) ((t)->count) -int tree_check(struct tree *, uint64_t); -void *tree_set(struct tree *, uint64_t, void *); -void tree_xset(struct tree *, uint64_t, void *); -void *tree_get(struct tree *, uint64_t); -void *tree_xget(struct tree *, uint64_t); -void *tree_pop(struct tree *, uint64_t); -void *tree_xpop(struct tree *, uint64_t); -int tree_poproot(struct tree *, uint64_t *, void **); -int tree_root(struct tree *, uint64_t *, void **); -int tree_iter(struct tree *, void **, uint64_t *, void **); -int tree_iterfrom(struct tree *, void **, uint64_t, uint64_t *, void **); -void tree_merge(struct tree *, struct tree *); - #endif diff --git a/smtpd/smtpd.c b/smtpd/smtpd.c index 97f4742d..2347afa4 100644 --- a/smtpd/smtpd.c +++ b/smtpd/smtpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.c,v 1.313 2018/12/13 17:07:13 gilles Exp $ */ +/* $OpenBSD: smtpd.c,v 1.315 2018/12/23 16:37:53 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org> @@ -584,9 +584,7 @@ main(int argc, char *argv[]) tracing |= TRACE_IO; else if (!strcmp(optarg, "smtp")) tracing |= TRACE_SMTP; - else if (!strcmp(optarg, "mfa") || - !strcmp(optarg, "filter") || - !strcmp(optarg, "filters")) + else if (!strcmp(optarg, "filters")) tracing |= TRACE_FILTERS; else if (!strcmp(optarg, "mta") || !strcmp(optarg, "transfer")) @@ -2027,10 +2025,6 @@ imsg_to_str(int type) CASE(IMSG_MTA_LOOKUP_SMARTHOST); CASE(IMSG_MTA_OPEN_MESSAGE); CASE(IMSG_MTA_SCHEDULE); - CASE(IMSG_MTA_TLS_INIT); - CASE(IMSG_MTA_TLS_VERIFY_CERT); - CASE(IMSG_MTA_TLS_VERIFY_CHAIN); - CASE(IMSG_MTA_TLS_VERIFY); CASE(IMSG_SCHED_ENVELOPE_BOUNCE); CASE(IMSG_SCHED_ENVELOPE_DELIVER); @@ -2047,10 +2041,6 @@ imsg_to_str(int type) CASE(IMSG_SMTP_CHECK_SENDER); CASE(IMSG_SMTP_EXPAND_RCPT); CASE(IMSG_SMTP_LOOKUP_HELO); - CASE(IMSG_SMTP_TLS_INIT); - CASE(IMSG_SMTP_TLS_VERIFY_CERT); - CASE(IMSG_SMTP_TLS_VERIFY_CHAIN); - CASE(IMSG_SMTP_TLS_VERIFY); CASE(IMSG_SMTP_REQ_CONNECT); CASE(IMSG_SMTP_REQ_HELO); diff --git a/smtpd/smtpd.h b/smtpd/smtpd.h index 74a2c150..dc819276 100644 --- a/smtpd/smtpd.h +++ b/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.601 2018/12/22 13:09:05 gilles Exp $ */ +/* $OpenBSD: smtpd.h,v 1.610 2018/12/27 09:30:29 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org> @@ -301,10 +301,6 @@ enum imsg_type { IMSG_MTA_LOOKUP_SMARTHOST, IMSG_MTA_OPEN_MESSAGE, IMSG_MTA_SCHEDULE, - IMSG_MTA_TLS_INIT, - IMSG_MTA_TLS_VERIFY_CERT, - IMSG_MTA_TLS_VERIFY_CHAIN, - IMSG_MTA_TLS_VERIFY, IMSG_SCHED_ENVELOPE_BOUNCE, IMSG_SCHED_ENVELOPE_DELIVER, @@ -321,10 +317,6 @@ enum imsg_type { IMSG_SMTP_CHECK_SENDER, IMSG_SMTP_EXPAND_RCPT, IMSG_SMTP_LOOKUP_HELO, - IMSG_SMTP_TLS_INIT, - IMSG_SMTP_TLS_VERIFY_CERT, - IMSG_SMTP_TLS_VERIFY_CHAIN, - IMSG_SMTP_TLS_VERIFY, IMSG_SMTP_REQ_CONNECT, IMSG_SMTP_REQ_HELO, @@ -396,13 +388,14 @@ struct table { }; struct table_backend { + const char *name; const unsigned int services; int (*config)(struct table *); - void *(*open)(struct table *); + int (*open)(struct table *); int (*update)(struct table *); - void (*close)(void *); - int (*lookup)(void *, struct dict *, const char *, enum table_service, union lookup *); - int (*fetch)(void *, struct dict *, enum table_service, union lookup *); + void (*close)(struct table *); + int (*lookup)(struct table *, enum table_service, const char *, char **); + int (*fetch)(struct table *, enum table_service, char **); }; @@ -1140,37 +1133,6 @@ enum mda_resp_status { MDA_PERMFAIL }; -struct ca_cert_req_msg { - uint64_t reqid; - char name[HOST_NAME_MAX+1]; - int fallback; -}; - -struct ca_cert_resp_msg { - uint64_t reqid; - enum ca_resp_status status; - char name[HOST_NAME_MAX+1]; - char *cert; - off_t cert_len; -}; - -struct ca_vrfy_req_msg { - uint64_t reqid; - char name[HOST_NAME_MAX+1]; - int fallback; - unsigned char *cert; - off_t cert_len; - size_t n_chain; - size_t chain_offset; - unsigned char **chain_cert; - off_t *chain_cert_len; -}; - -struct ca_vrfy_resp_msg { - uint64_t reqid; - enum ca_resp_status status; -}; - struct msg_walkinfo { struct event ev; uint32_t msgid; @@ -1668,9 +1630,10 @@ void table_close(struct table *); int table_check_use(struct table *, uint32_t, uint32_t); int table_check_type(struct table *, uint32_t); int table_check_service(struct table *, uint32_t); -int table_lookup(struct table *, struct dict *, const char *, enum table_service, +int table_match(struct table *, enum table_service, const char *); +int table_lookup(struct table *, enum table_service, const char *, union lookup *); -int table_fetch(struct table *, struct dict *, enum table_service, union lookup *); +int table_fetch(struct table *, enum table_service, union lookup *); void table_destroy(struct smtpd *, struct table *); void table_add(struct table *, const char *, const char *); int table_domain_match(const char *, const char *); @@ -1680,8 +1643,6 @@ int table_regex_match(const char *, const char *); void table_open_all(struct smtpd *); void table_dump_all(struct smtpd *); void table_close_all(struct smtpd *); -int table_parse_lookup(enum table_service, const char *, const char *, - union lookup *); /* to.c */ diff --git a/smtpd/table.c b/smtpd/table.c index 37249abd..a5d4b272 100644 --- a/smtpd/table.c +++ b/smtpd/table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: table.c,v 1.33 2018/12/21 21:35:29 gilles Exp $ */ +/* $OpenBSD: table.c,v 1.41 2018/12/27 09:30:29 eric Exp $ */ /* * Copyright (c) 2013 Eric Faurot <eric@openbsd.org> @@ -55,42 +55,33 @@ extern struct table_backend table_backend_getpwnam; extern struct table_backend table_backend_proc; static const char * table_service_name(enum table_service); -static const char * table_backend_name(struct table_backend *); -static const char * table_dump_lookup(enum table_service, union lookup *); +static int table_parse_lookup(enum table_service, const char *, const char *, + union lookup *); static int parse_sockaddr(struct sockaddr *, int, const char *); static unsigned int last_table_id = 0; +static struct table_backend *backends[] = { + &table_backend_static, + &table_backend_db, + &table_backend_getpwnam, + &table_backend_proc, + NULL +}; + struct table_backend * table_backend_lookup(const char *backend) { - if (!strcmp(backend, "static") || !strcmp(backend, "file")) - return &table_backend_static; -#ifdef HAVE_DB_API - if (!strcmp(backend, "db")) - return &table_backend_db; -#endif - if (!strcmp(backend, "getpwnam")) - return &table_backend_getpwnam; - if (!strcmp(backend, "proc")) - return &table_backend_proc; - return NULL; -} + int i; -static const char * -table_backend_name(struct table_backend *backend) -{ - if (backend == &table_backend_static) - return "static"; -#ifdef HAVE_DB_API - if (backend == &table_backend_db) - return "db"; -#endif - if (backend == &table_backend_getpwnam) - return "getpwnam"; - if (backend == &table_backend_proc) - return "proc"; - return "???"; + if (!strcmp(backend, "file")) + backend = "static"; + + for (i = 0; backends[i]; i++) + if (!strcmp(backends[i]->name, backend)) + return (backends[i]); + + return NULL; } static const char * @@ -129,11 +120,17 @@ table_find(struct smtpd *conf, const char *name, const char *tag) } int -table_lookup(struct table *table, struct dict *params, const char *key, enum table_service kind, +table_match(struct table *table, enum table_service kind, const char *key) +{ + return table_lookup(table, kind, key, NULL); +} + +int +table_lookup(struct table *table, enum table_service kind, const char *key, union lookup *lk) { int r; - char lkey[1024]; + char lkey[1024], *buf = NULL; if (table->t_backend->lookup == NULL) return (-1); @@ -143,55 +140,66 @@ table_lookup(struct table *table, struct dict *params, const char *key, enum tab return -1; } - r = table->t_backend->lookup(table->t_handle, params, lkey, kind, lk); + r = table->t_backend->lookup(table, kind, lkey, lk ? &buf : NULL); - if (r == 1) + if (r == 1) { log_trace(TRACE_LOOKUP, "lookup: %s \"%s\" as %s in table %s:%s -> %s%s%s", lk ? "lookup" : "check", lkey, table_service_name(kind), - table_backend_name(table->t_backend), + table->t_backend->name, table->t_name, lk ? "\"" : "", - (lk) ? table_dump_lookup(kind, lk): "found", + (lk) ? buf : "found", lk ? "\"" : ""); + if (buf) + r = table_parse_lookup(kind, lkey, buf, lk); + } else log_trace(TRACE_LOOKUP, "lookup: %s \"%s\" as %s in table %s:%s -> %d", lk ? "lookup" : "check", lkey, table_service_name(kind), - table_backend_name(table->t_backend), + table->t_backend->name, table->t_name, r); + free(buf); + return (r); } int -table_fetch(struct table *table, struct dict *params, enum table_service kind, union lookup *lk) +table_fetch(struct table *table, enum table_service kind, union lookup *lk) { int r; + char *buf = NULL; if (table->t_backend->fetch == NULL) return (-1); - r = table->t_backend->fetch(table->t_handle, params, kind, lk); + r = table->t_backend->fetch(table, kind, lk ? &buf : NULL); - if (r == 1) + if (r == 1) { log_trace(TRACE_LOOKUP, "lookup: fetch %s from table %s:%s -> %s%s%s", table_service_name(kind), - table_backend_name(table->t_backend), + table->t_backend->name, table->t_name, lk ? "\"" : "", - (lk) ? table_dump_lookup(kind, lk): "found", + (lk) ? buf : "found", lk ? "\"" : ""); + if (buf) + r = table_parse_lookup(kind, NULL, buf, lk); + } else log_trace(TRACE_LOOKUP, "lookup: fetch %s from table %s:%s -> %d", table_service_name(kind), - table_backend_name(table->t_backend), + table->t_backend->name, table->t_name, r); + free(buf); + return (r); } @@ -336,20 +344,16 @@ table_check_use(struct table *t, uint32_t tmask, uint32_t smask) int table_open(struct table *t) { - t->t_handle = NULL; if (t->t_backend->open == NULL) return (1); - t->t_handle = t->t_backend->open(t); - if (t->t_handle == NULL) - return (0); - return (1); + return (t->t_backend->open(t)); } void table_close(struct table *t) { if (t->t_backend->close) - t->t_backend->close(t->t_handle); + t->t_backend->close(t); } int @@ -549,7 +553,7 @@ table_close_all(struct smtpd *conf) table_close(t); } -int +static int table_parse_lookup(enum table_service service, const char *key, const char *line, union lookup *lk) { @@ -662,108 +666,6 @@ table_parse_lookup(enum table_service service, const char *key, } } -static const char * -table_dump_lookup(enum table_service s, union lookup *lk) -{ - static char buf[LINE_MAX]; - struct maddrnode *mn; - int ret; - - switch (s) { - case K_NONE: - break; - - case K_ALIAS: - expand_to_text(lk->expand, buf, sizeof(buf)); - break; - - case K_DOMAIN: - ret = snprintf(buf, sizeof(buf), "%s", lk->domain.name); - if (ret == -1 || (size_t)ret >= sizeof (buf)) - goto err; - break; - - case K_CREDENTIALS: - ret = snprintf(buf, sizeof(buf), "%s:%s", - lk->creds.username, lk->creds.password); - if (ret == -1 || (size_t)ret >= sizeof (buf)) - goto err; - break; - - case K_NETADDR: - ret = snprintf(buf, sizeof(buf), "%s/%d", - sockaddr_to_text((struct sockaddr *)&lk->netaddr.ss), - lk->netaddr.bits); - if (ret == -1 || (size_t)ret >= sizeof (buf)) - goto err; - break; - - case K_USERINFO: - ret = snprintf(buf, sizeof(buf), "%s:%d:%d:%s", - lk->userinfo.username, - lk->userinfo.uid, - lk->userinfo.gid, - lk->userinfo.directory); - if (ret == -1 || (size_t)ret >= sizeof (buf)) - goto err; - break; - - case K_SOURCE: - ret = snprintf(buf, sizeof(buf), "%s", - ss_to_text(&lk->source.addr)); - if (ret == -1 || (size_t)ret >= sizeof (buf)) - goto err; - break; - - case K_MAILADDR: - ret = snprintf(buf, sizeof(buf), "%s@%s", - lk->mailaddr.user, - lk->mailaddr.domain); - if (ret == -1 || (size_t)ret >= sizeof (buf)) - goto err; - break; - - case K_MAILADDRMAP: - buf[0] = '\0'; - TAILQ_FOREACH(mn, &lk->maddrmap->queue, entries) { - (void)strlcat(buf, mn->mailaddr.user, sizeof(buf)); - (void)strlcat(buf, "@", sizeof(buf)); - ret = strlcat(buf, mn->mailaddr.domain, sizeof(buf)); - - if (mn != TAILQ_LAST(&lk->maddrmap->queue, xmaddr)) - ret = strlcat(buf, ", ", sizeof(buf)); - - if (ret >= sizeof(buf)) { - strlcpy(buf + sizeof(buf) - 4, "...", 4); - break; - } - } - break; - - case K_ADDRNAME: - ret = snprintf(buf, sizeof(buf), "%s", - lk->addrname.name); - if (ret == -1 || (size_t)ret >= sizeof (buf)) - goto err; - break; - - case K_RELAYHOST: - if (strlcpy(buf, lk->relayhost, sizeof(buf)) >= sizeof(buf)) - goto err; - break; - - default: - (void)strlcpy(buf, "???", sizeof(buf)); - break; - } - - return (buf); - -err: - return (NULL); -} - - static int parse_sockaddr(struct sockaddr *sa, int family, const char *str) { diff --git a/smtpd/table_db.c b/smtpd/table_db.c index 4ef23f71..cd2263fe 100644 --- a/smtpd/table_db.c +++ b/smtpd/table_db.c @@ -1,4 +1,4 @@ -/* $OpenBSD: table_db.c,v 1.10 2018/05/31 21:06:12 gilles Exp $ */ +/* $OpenBSD: table_db.c,v 1.17 2018/12/27 09:30:29 eric Exp $ */ /* * Copyright (c) 2011 Gilles Chehade <gilles@poolp.org> @@ -49,16 +49,19 @@ /* db(3) backend */ static int table_db_config(struct table *); static int table_db_update(struct table *); -static void *table_db_open(struct table *); -static int table_db_lookup(void *, struct dict *, const char *, enum table_service, union lookup *); -static int table_db_fetch(void *, struct dict *, enum table_service, union lookup *); -static void table_db_close(void *); +static int table_db_open(struct table *); +static void *table_db_open2(struct table *); +static int table_db_lookup(struct table *, enum table_service, const char *, char **); +static int table_db_fetch(struct table *, enum table_service, char **); +static void table_db_close(struct table *); +static void table_db_close2(void *); static char *table_db_get_entry(void *, const char *, size_t *); static char *table_db_get_entry_match(void *, const char *, size_t *, int(*)(const char *, const char *)); struct table_backend table_backend_db = { + "db", K_ALIAS|K_CREDENTIALS|K_DOMAIN|K_NETADDR|K_USERINFO|K_SOURCE|K_MAILADDR|K_ADDRNAME|K_MAILADDRMAP, table_db_config, table_db_open, @@ -81,7 +84,6 @@ struct dbhandle { DB *db; char pathname[PATH_MAX]; time_t mtime; - struct table *table; }; static int @@ -89,11 +91,11 @@ table_db_config(struct table *table) { struct dbhandle *handle; - handle = table_db_open(table); + handle = table_db_open2(table); if (handle == NULL) return 0; - table_db_close(handle); + table_db_close2(handle); return 1; } @@ -102,18 +104,34 @@ table_db_update(struct table *table) { struct dbhandle *handle; - handle = table_db_open(table); + handle = table_db_open2(table); if (handle == NULL) return 0; - table_db_close(table->t_handle); + table_db_close2(table->t_handle); table->t_handle = handle; return 1; } -static void * +static int table_db_open(struct table *table) { + table->t_handle = table_db_open2(table); + if (table->t_handle == NULL) + return 0; + return 1; +} + +static void +table_db_close(struct table *table) +{ + table_db_close2(table->t_handle); + table->t_handle = NULL; +} + +static void * +table_db_open2(struct table *table) +{ struct dbhandle *handle; struct stat sb; @@ -129,7 +147,6 @@ table_db_open(struct table *table) handle->db = dbopen(table->t_config, O_RDONLY, 0600, DB_HASH, NULL); if (handle->db == NULL) goto error; - handle->table = table; return handle; @@ -141,7 +158,7 @@ error: } static void -table_db_close(void *hdl) +table_db_close2(void *hdl) { struct dbhandle *handle = hdl; handle->db->close(handle->db); @@ -149,11 +166,10 @@ table_db_close(void *hdl) } static int -table_db_lookup(void *hdl, struct dict *params, const char *key, enum table_service service, - union lookup *lk) +table_db_lookup(struct table *table, enum table_service service, const char *key, + char **dst) { - struct dbhandle *handle = hdl; - struct table *table = NULL; + struct dbhandle *handle = table->t_handle; char *line; size_t len = 0; int ret; @@ -166,8 +182,7 @@ table_db_lookup(void *hdl, struct dict *params, const char *key, enum table_serv /* DB has changed, close and reopen */ if (sb.st_mtime != handle->mtime) { - table = handle->table; - table_db_update(handle->table); + table_db_update(table); handle = table->t_handle; } @@ -183,18 +198,18 @@ table_db_lookup(void *hdl, struct dict *params, const char *key, enum table_serv return 0; ret = 1; - if (lk) - ret = table_parse_lookup(service, key, line, lk); - free(line); + if (dst) + *dst = line; + else + free(line); return ret; } static int -table_db_fetch(void *hdl, struct dict *params, enum table_service service, union lookup *lk) +table_db_fetch(struct table *table, enum table_service service, char **dst) { - struct dbhandle *handle = hdl; - struct table *table = handle->table; + struct dbhandle *handle = table->t_handle; DBT dbk; DBT dbd; int r; @@ -210,7 +225,13 @@ table_db_fetch(void *hdl, struct dict *params, enum table_service service, union return 0; } - return table_parse_lookup(service, NULL, dbk.data, lk); + if (dst) { + *dst = strdup(dbk.data); + if (*dst == NULL) + return -1; + } + + return 1; } diff --git a/smtpd/table_getpwnam.c b/smtpd/table_getpwnam.c index 87b0a54c..b0a9e8cf 100644 --- a/smtpd/table_getpwnam.c +++ b/smtpd/table_getpwnam.c @@ -1,4 +1,4 @@ -/* $OpenBSD: table_getpwnam.c,v 1.4 2015/01/20 17:37:54 deraadt Exp $ */ +/* $OpenBSD: table_getpwnam.c,v 1.11 2018/12/27 09:30:29 eric Exp $ */ /* * Copyright (c) 2012 Gilles Chehade <gilles@poolp.org> @@ -42,12 +42,13 @@ /* getpwnam(3) backend */ static int table_getpwnam_config(struct table *); static int table_getpwnam_update(struct table *); -static void *table_getpwnam_open(struct table *); -static int table_getpwnam_lookup(void *, struct dict *, const char *, enum table_service, - union lookup *); -static void table_getpwnam_close(void *); +static int table_getpwnam_open(struct table *); +static int table_getpwnam_lookup(struct table *, enum table_service, const char *, + char **); +static void table_getpwnam_close(struct table *); struct table_backend table_backend_getpwnam = { + "getpwnam", K_USERINFO, table_getpwnam_config, table_getpwnam_open, @@ -71,24 +72,23 @@ table_getpwnam_update(struct table *table) return 1; } -static void * +static int table_getpwnam_open(struct table *table) { - return table; + return 1; } static void -table_getpwnam_close(void *hdl) +table_getpwnam_close(struct table *table) { return; } static int -table_getpwnam_lookup(void *hdl, struct dict *params, const char *key, enum table_service kind, - union lookup *lk) +table_getpwnam_lookup(struct table *table, enum table_service kind, const char *key, + char **dst) { struct passwd *pw; - size_t s; if (kind != K_USERINFO) return -1; @@ -103,19 +103,16 @@ table_getpwnam_lookup(void *hdl, struct dict *params, const char *key, enum tabl return -1; return 0; } - if (lk == NULL) + if (dst == NULL) return 1; - lk->userinfo.uid = pw->pw_uid; - lk->userinfo.gid = pw->pw_gid; - s = strlcpy(lk->userinfo.username, pw->pw_name, - sizeof(lk->userinfo.username)); - if (s >= sizeof(lk->userinfo.username)) - return (-1); - s = strlcpy(lk->userinfo.directory, pw->pw_dir, - sizeof(lk->userinfo.directory)); - if (s >= sizeof(lk->userinfo.directory)) - return (-1); + if (asprintf(dst, "%d:%d:%s", + pw->pw_uid, + pw->pw_gid, + pw->pw_dir) == -1) { + *dst = NULL; + return -1; + } return (1); } diff --git a/smtpd/table_proc.c b/smtpd/table_proc.c index fcf4ffcb..c29bcf86 100644 --- a/smtpd/table_proc.c +++ b/smtpd/table_proc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: table_proc.c,v 1.7 2018/05/31 21:06:12 gilles Exp $ */ +/* $OpenBSD: table_proc.c,v 1.14 2018/12/27 09:30:29 eric Exp $ */ /* * Copyright (c) 2013 Eric Faurot <eric@openbsd.org> @@ -120,7 +120,7 @@ table_proc_end(void) * API */ -static void * +static int table_proc_open(struct table *table) { struct table_proc_priv *priv; @@ -143,7 +143,9 @@ table_proc_open(struct table *table) table_proc_call(priv); table_proc_end(); - return (priv); + table->t_handle = priv; + + return (1); } static int @@ -162,60 +164,43 @@ table_proc_update(struct table *table) } static void -table_proc_close(void *arg) +table_proc_close(struct table *table) { - struct table_proc_priv *priv = arg; + struct table_proc_priv *priv = table->t_handle; imsg_compose(&priv->ibuf, PROC_TABLE_CLOSE, 0, 0, -1, NULL, 0); imsg_flush(&priv->ibuf); + + table->t_handle = NULL; } static int -imsg_add_params(struct ibuf *buf, struct dict *params) +imsg_add_params(struct ibuf *buf) { - size_t count; - const char *key; - char *value; - void *iter; - - count = 0; - if (params) - count = dict_count(params); + size_t count = 0; if (imsg_add(buf, &count, sizeof(count)) == -1) return (-1); - if (count == 0) - return (0); - - iter = NULL; - while (dict_iter(params, &iter, &key, (void **)&value)) { - if (imsg_add(buf, key, strlen(key) + 1) == -1) - return (-1); - if (imsg_add(buf, value, strlen(value) + 1) == -1) - return (-1); - } - return (0); } static int -table_proc_lookup(void *arg, struct dict *params, const char *k, enum table_service s, - union lookup *lk) +table_proc_lookup(struct table *table, enum table_service s, const char *k, char **dst) { - struct table_proc_priv *priv = arg; + struct table_proc_priv *priv = table->t_handle; struct ibuf *buf; int r; buf = imsg_create(&priv->ibuf, - lk ? PROC_TABLE_LOOKUP : PROC_TABLE_CHECK, 0, 0, + dst ? PROC_TABLE_LOOKUP : PROC_TABLE_CHECK, 0, 0, sizeof(s) + strlen(k) + 1); if (buf == NULL) return (-1); if (imsg_add(buf, &s, sizeof(s)) == -1) return (-1); - if (imsg_add_params(buf, params) == -1) + if (imsg_add_params(buf) == -1) return (-1); if (imsg_add(buf, k, strlen(k) + 1) == -1) return (-1); @@ -224,7 +209,7 @@ table_proc_lookup(void *arg, struct dict *params, const char *k, enum table_serv table_proc_call(priv); table_proc_read(&r, sizeof(r)); - if (r == 1 && lk) { + if (r == 1 && dst) { if (rlen == 0) { log_warnx("warn: table-proc: empty response"); fatalx("table-proc: exiting"); @@ -233,7 +218,9 @@ table_proc_lookup(void *arg, struct dict *params, const char *k, enum table_serv log_warnx("warn: table-proc: not NUL-terminated"); fatalx("table-proc: exiting"); } - r = table_parse_lookup(s, k, rdata, lk); + *dst = strdup(rdata); + if (*dst == NULL) + r = -1; table_proc_read(NULL, rlen); } @@ -243,9 +230,9 @@ table_proc_lookup(void *arg, struct dict *params, const char *k, enum table_serv } static int -table_proc_fetch(void *arg, struct dict *params, enum table_service s, union lookup *lk) +table_proc_fetch(struct table *table, enum table_service s, char **dst) { - struct table_proc_priv *priv = arg; + struct table_proc_priv *priv = table->t_handle; struct ibuf *buf; int r; @@ -254,7 +241,7 @@ table_proc_fetch(void *arg, struct dict *params, enum table_service s, union loo return (-1); if (imsg_add(buf, &s, sizeof(s)) == -1) return (-1); - if (imsg_add_params(buf, params) == -1) + if (imsg_add_params(buf) == -1) return (-1); imsg_close(&priv->ibuf, buf); @@ -270,7 +257,9 @@ table_proc_fetch(void *arg, struct dict *params, enum table_service s, union loo log_warnx("warn: table-proc: not NUL-terminated"); fatalx("table-proc: exiting"); } - r = table_parse_lookup(s, NULL, rdata, lk); + *dst = strdup(rdata); + if (*dst == NULL) + r = -1; table_proc_read(NULL, rlen); } @@ -280,6 +269,7 @@ table_proc_fetch(void *arg, struct dict *params, enum table_service s, union loo } struct table_backend table_backend_proc = { + "proc", K_ANY, NULL, table_proc_open, diff --git a/smtpd/table_static.c b/smtpd/table_static.c index 3a19e7e2..9f57f761 100644 --- a/smtpd/table_static.c +++ b/smtpd/table_static.c @@ -1,4 +1,4 @@ -/* $OpenBSD: table_static.c,v 1.20 2018/11/01 10:47:46 gilles Exp $ */ +/* $OpenBSD: table_static.c,v 1.27 2018/12/27 09:30:29 eric Exp $ */ /* * Copyright (c) 2013 Eric Faurot <eric@openbsd.org> @@ -43,14 +43,14 @@ /* static backend */ static int table_static_config(struct table *); static int table_static_update(struct table *); -static void *table_static_open(struct table *); -static int table_static_lookup(void *, struct dict *, const char *, - enum table_service, union lookup *); -static int table_static_fetch(void *, struct dict *, enum table_service, - union lookup *); -static void table_static_close(void *); +static int table_static_open(struct table *); +static int table_static_lookup(struct table *, enum table_service, const char *, + char **); +static int table_static_fetch(struct table *, enum table_service, char **); +static void table_static_close(struct table *); struct table_backend table_backend_static = { + "static", K_ALIAS|K_CREDENTIALS|K_DOMAIN|K_NETADDR|K_USERINFO| K_SOURCE|K_MAILADDR|K_ADDRNAME|K_MAILADDRMAP|K_RELAYHOST| K_STRING|K_REGEX, @@ -204,23 +204,23 @@ err: return 0; } -static void * +static int table_static_open(struct table *table) { - return table; + table->t_handle = table; + return 1; } static void -table_static_close(void *hdl) +table_static_close(struct table *table) { - return; + table->t_handle = NULL; } static int -table_static_lookup(void *hdl, struct dict *params, const char *key, - enum table_service service, union lookup *lk) +table_static_lookup(struct table *m, enum table_service service, const char *key, + char **dst) { - struct table *m = hdl; char *line; int ret; int (*match)(const char *, const char *) = NULL; @@ -253,20 +253,22 @@ table_static_lookup(void *hdl, struct dict *params, const char *key, break; } - if (lk == NULL) + if (dst == NULL) return ret ? 1 : 0; if (ret == 0) return 0; - return table_parse_lookup(service, key, line, lk); + *dst = strdup(line); + if (*dst == NULL) + return -1; + + return 1; } static int -table_static_fetch(void *hdl, struct dict *params, - enum table_service service, union lookup *lk) +table_static_fetch(struct table *t, enum table_service service, char **dst) { - struct table *t = hdl; const char *k; if (!dict_iter(&t->t_dict, &t->t_iter, &k, (void **)NULL)) { @@ -275,8 +277,12 @@ table_static_fetch(void *hdl, struct dict *params, return 0; } - if (lk == NULL) + if (dst == NULL) return 1; - return table_parse_lookup(service, NULL, k, lk); + *dst = strdup(k); + if (*dst == NULL) + return -1; + + return 1; } diff --git a/smtpd/tree.c b/smtpd/tree.c index 03ba8d15..1d720a59 100644 --- a/smtpd/tree.c +++ b/smtpd/tree.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tree.c,v 1.5 2015/01/20 17:37:54 deraadt Exp $ */ +/* $OpenBSD: tree.c,v 1.6 2018/12/23 16:06:24 gilles Exp $ */ /* * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> @@ -21,17 +21,12 @@ #include <sys/types.h> #include <sys/tree.h> -#include <sys/socket.h> /* for smtpd.h */ -#include <sys/queue.h> /* for smtpd.h */ -#include <stdio.h> /* for smtpd.h */ -#include <imsg.h> /* for smtpd.h */ - #include <err.h> #include <inttypes.h> #include <stdlib.h> #include <limits.h> -#include "smtpd.h" +#include "tree.h" struct treeentry { SPLAY_ENTRY(treeentry) entry; diff --git a/smtpd/tree.h b/smtpd/tree.h new file mode 100644 index 00000000..3d719f09 --- /dev/null +++ b/smtpd/tree.h @@ -0,0 +1,48 @@ +/* $OpenBSD: tree.h,v 1.1 2018/12/23 16:06:24 gilles Exp $ */ + +/* + * Copyright (c) 2013 Eric Faurot <eric@openbsd.org> + * Copyright (c) 2011 Gilles Chehade <gilles@poolp.org> + * + * 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. + */ + +#ifndef _TREE_H_ +#define _TREE_H_ + +SPLAY_HEAD(_tree, treeentry); + +struct tree { + struct _tree tree; + size_t count; +}; + + +/* tree.c */ +#define tree_init(t) do { SPLAY_INIT(&((t)->tree)); (t)->count = 0; } while(0) +#define tree_empty(t) SPLAY_EMPTY(&((t)->tree)) +#define tree_count(t) ((t)->count) +int tree_check(struct tree *, uint64_t); +void *tree_set(struct tree *, uint64_t, void *); +void tree_xset(struct tree *, uint64_t, void *); +void *tree_get(struct tree *, uint64_t); +void *tree_xget(struct tree *, uint64_t); +void *tree_pop(struct tree *, uint64_t); +void *tree_xpop(struct tree *, uint64_t); +int tree_poproot(struct tree *, uint64_t *, void **); +int tree_root(struct tree *, uint64_t *, void **); +int tree_iter(struct tree *, void **, uint64_t *, void **); +int tree_iterfrom(struct tree *, void **, uint64_t, uint64_t *, void **); +void tree_merge(struct tree *, struct tree *); + +#endif |