From fb02161cc9c395e267668b745b79dc3157f4c515 Mon Sep 17 00:00:00 2001 From: Gilles Chehade Date: Wed, 26 Dec 2018 12:36:06 +0100 Subject: sync --- smtpd/dict.c | 9 +- smtpd/dict.h | 48 ++++++++++ smtpd/lka.c | 153 +----------------------------- smtpd/lka_filter.c | 249 +++++++++++++++++++++++++++++-------------------- smtpd/mta.c | 10 +- smtpd/mta_session.c | 209 +---------------------------------------- smtpd/parse.y | 49 +++++++++- smtpd/pony.c | 6 +- smtpd/smtp.c | 4 +- smtpd/smtp_session.c | 200 ++------------------------------------- smtpd/smtpd-api.h | 52 +---------- smtpd/smtpd.c | 14 +-- smtpd/smtpd.h | 47 +--------- smtpd/table.c | 31 ++++-- smtpd/table_db.c | 25 +++-- smtpd/table_getpwnam.c | 26 +++--- smtpd/table_proc.c | 19 ++-- smtpd/table_static.c | 26 ++++-- smtpd/tree.c | 9 +- smtpd/tree.h | 48 ++++++++++ 20 files changed, 393 insertions(+), 841 deletions(-) create mode 100644 smtpd/dict.h create mode 100644 smtpd/tree.h diff --git a/smtpd/dict.c b/smtpd/dict.c index 2d65812a..91156d5a 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 @@ -20,17 +20,12 @@ #include #include -#include /* for smtpd.h */ -#include /* for smtpd.h */ -#include /* for smtpd.h */ -#include /* for smtpd.h */ - #include #include #include #include -#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 + * Copyright (c) 2011 Gilles Chehade + * + * 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 27569d19..c08e834b 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.229 2018/12/23 16:37:53 eric Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard @@ -56,9 +56,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); @@ -69,12 +66,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; @@ -168,63 +159,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); @@ -906,88 +840,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 ea3074c5..e4d9b849 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.31 2018/12/23 15:48:16 gilles Exp $ */ /* * Copyright (c) 2018 Gilles Chehade @@ -138,6 +138,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); @@ -152,6 +153,8 @@ lka_filter_init(void) filter->phases |= (1<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: @@ -160,6 +163,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: @@ -177,8 +182,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; @@ -313,6 +326,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 @@ -323,6 +338,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 @@ -348,6 +364,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 @@ -360,6 +377,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 @@ -495,9 +513,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; @@ -518,6 +540,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; } @@ -526,6 +551,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 */ @@ -533,19 +562,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; @@ -591,7 +644,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) { @@ -607,7 +661,13 @@ 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: @@ -617,6 +677,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 @@ -741,12 +803,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_lookup(filter->config->rdns_table, NULL, key, kind, NULL) > 0) + ret = 1; + + return filter->config->not_rdns_table < 0 ? !ret : ret; } static int @@ -754,12 +817,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_lookup(filter->config->rdns_regex, NULL, key, K_REGEX, NULL) > 0) + ret = 1; + return filter->config->not_rdns_regex < 0 ? !ret : ret; } static int @@ -767,12 +830,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_lookup(filter->config->src_table, NULL, key, kind, NULL) > 0) + ret = 1; + return filter->config->not_src_table < 0 ? !ret : ret; } static int @@ -780,12 +843,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_lookup(filter->config->src_regex, NULL, key, K_REGEX, NULL) > 0) + ret = 1; + return filter->config->not_src_regex < 0 ? !ret : ret; } static int @@ -793,12 +856,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_lookup(filter->config->helo_table, NULL, key, kind, NULL) > 0) + ret = 1; + return filter->config->not_helo_table < 0 ? !ret : ret; } static int @@ -806,12 +869,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_lookup(filter->config->helo_regex, NULL, key, K_REGEX, NULL) > 0) + ret = 1; + return filter->config->not_helo_regex < 0 ? !ret : ret; } static int @@ -819,12 +882,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_lookup(filter->config->mail_from_table, NULL, key, kind, NULL) > 0) + ret = 1; + return filter->config->not_mail_from_table < 0 ? !ret : ret; } static int @@ -832,12 +895,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_lookup(filter->config->mail_from_regex, NULL, key, K_REGEX, NULL) > 0) + ret = 1; + return filter->config->not_mail_from_regex < 0 ? !ret : ret; } static int @@ -845,12 +908,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_lookup(filter->config->rcpt_to_table, NULL, key, kind, NULL) > 0) + ret = 1; + return filter->config->not_rcpt_to_table < 0 ? !ret : ret; } static int @@ -858,12 +921,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_lookup(filter->config->rcpt_to_regex, NULL, key, K_REGEX, NULL) > 0) + ret = 1; + return filter->config->not_rcpt_to_regex < 0 ? !ret : ret; } static int @@ -871,11 +934,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 @@ -884,14 +947,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 @@ -901,9 +964,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) || @@ -912,43 +975,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/mta.c b/smtpd/mta.c index b7a841d1..6958384a 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 @@ -312,14 +312,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 755ac86d..959b45e8 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 @@ -148,8 +148,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 *); @@ -242,13 +240,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; @@ -300,61 +295,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); @@ -1507,153 +1447,6 @@ mta_error(struct mta_session *s, const char *fmt, ...) free(error); } -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) { diff --git a/smtpd/parse.y b/smtpd/parse.y index 06d72d0f..bb88aa37 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 @@ -107,7 +107,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, @@ -1591,7 +1592,7 @@ FILTER STRING PROC_EXEC STRING { char buffer[128]; do { - (void)snprintf(buffer, sizeof buffer, "", last_dynproc_id++); + (void)snprintf(buffer, sizeof buffer, "", last_dynproc_id++); } while (dict_check(conf->sc_processors_dict, buffer)); if (dict_get(conf->sc_filters_dict, $2)) { @@ -1798,6 +1799,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, "", 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; @@ -1865,6 +1887,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, "", 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 abbde55e..aeb7a522 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 @@ -91,8 +91,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: @@ -117,8 +115,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/smtp.c b/smtpd/smtp.c index 61c99e5a..921d9f8a 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 @@ -66,8 +66,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 0a3d1025..f3dba8c4 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 @@ -189,8 +189,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 *); @@ -684,18 +682,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; @@ -956,47 +950,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); @@ -2174,150 +2127,6 @@ smtp_mailaddr(struct mailaddr *maddr, char *line, int mailfrom, char **args, return (1); } -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) { @@ -2821,8 +2630,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 @@ -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 1c87350d..87344b53 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 @@ -530,9 +530,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")) @@ -1972,10 +1970,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); @@ -1992,10 +1986,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 1e844880..47914bd5 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.603 2018/12/23 16:37:53 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade @@ -275,10 +275,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, @@ -295,10 +291,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, @@ -375,8 +367,8 @@ struct table_backend { void *(*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 *); + int (*lookup)(void *, struct dict *, const char *, enum table_service, char **); + int (*fetch)(void *, struct dict *, enum table_service, char **); }; @@ -1114,37 +1106,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; @@ -1654,8 +1615,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 187cb0ed..f070ab48 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.34 2018/12/23 15:53:24 eric Exp $ */ /* * Copyright (c) 2013 Eric Faurot @@ -53,6 +53,8 @@ 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; @@ -125,7 +127,7 @@ table_lookup(struct table *table, struct dict *params, const char *key, enum tab union lookup *lk) { int r; - char lkey[1024]; + char lkey[1024], *buf = NULL; if (table->t_backend->lookup == NULL) return (-1); @@ -135,9 +137,9 @@ 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->t_handle, params, lkey, kind, 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, @@ -145,8 +147,11 @@ table_lookup(struct table *table, struct dict *params, const char *key, enum tab table_backend_name(table->t_backend), 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", @@ -156,6 +161,8 @@ table_lookup(struct table *table, struct dict *params, const char *key, enum tab table->t_name, r); + free(buf); + return (r); } @@ -163,20 +170,24 @@ int table_fetch(struct table *table, struct dict *params, 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->t_handle, params, 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_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), @@ -184,6 +195,8 @@ table_fetch(struct table *table, struct dict *params, enum table_service kind, u table->t_name, r); + free(buf); + return (r); } @@ -541,7 +554,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) { diff --git a/smtpd/table_db.c b/smtpd/table_db.c index aeeed209..606c54e9 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.11 2018/12/23 15:53:24 eric Exp $ */ /* * Copyright (c) 2011 Gilles Chehade @@ -43,8 +43,8 @@ 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 int table_db_lookup(void *, struct dict *, const char *, enum table_service, char **); +static int table_db_fetch(void *, struct dict *, enum table_service, char **); static void table_db_close(void *); static char *table_db_get_entry(void *, const char *, size_t *); @@ -143,7 +143,7 @@ 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) + char **dst) { struct dbhandle *handle = hdl; struct table *table = NULL; @@ -176,15 +176,16 @@ 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(void *hdl, struct dict *params, enum table_service service, char **dst) { struct dbhandle *handle = hdl; struct table *table = handle->table; @@ -203,7 +204,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 83cbf797..046eed56 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.5 2018/12/23 15:53:24 eric Exp $ */ /* * Copyright (c) 2012 Gilles Chehade @@ -42,7 +42,7 @@ 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 *); + char **); static void table_getpwnam_close(void *); struct table_backend table_backend_getpwnam = { @@ -83,10 +83,9 @@ table_getpwnam_close(void *hdl) static int table_getpwnam_lookup(void *hdl, struct dict *params, const char *key, enum table_service kind, - union lookup *lk) + char **dst) { struct passwd *pw; - size_t s; if (kind != K_USERINFO) return -1; @@ -101,19 +100,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 27abbfe0..ab3f5404 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.8 2018/12/23 15:53:24 eric Exp $ */ /* * Copyright (c) 2013 Eric Faurot @@ -196,15 +196,14 @@ imsg_add_params(struct ibuf *buf, struct dict *params) } static int -table_proc_lookup(void *arg, struct dict *params, const char *k, enum table_service s, - union lookup *lk) +table_proc_lookup(void *arg, struct dict *params, const char *k, enum table_service s, char **dst) { struct table_proc_priv *priv = arg; 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) @@ -220,7 +219,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"); @@ -229,7 +228,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); } @@ -239,7 +240,7 @@ 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(void *arg, struct dict *params, enum table_service s, char **dst) { struct table_proc_priv *priv = arg; struct ibuf *buf; @@ -266,7 +267,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); } diff --git a/smtpd/table_static.c b/smtpd/table_static.c index 7be9cf21..352a0541 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.21 2018/12/23 15:53:24 eric Exp $ */ /* * Copyright (c) 2013 Eric Faurot @@ -43,9 +43,9 @@ 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 *); + enum table_service, char **); static int table_static_fetch(void *, struct dict *, enum table_service, - union lookup *); + char **); static void table_static_close(void *); struct table_backend table_backend_static = { @@ -216,7 +216,7 @@ table_static_close(void *hdl) static int table_static_lookup(void *hdl, struct dict *params, const char *key, - enum table_service service, union lookup *lk) + enum table_service service, char **dst) { struct table *m = hdl; char *line; @@ -251,18 +251,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) + enum table_service service, char **dst) { struct table *t = hdl; const char *k; @@ -273,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 2022ebaf..70aef047 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 @@ -19,17 +19,12 @@ #include #include -#include /* for smtpd.h */ -#include /* for smtpd.h */ -#include /* for smtpd.h */ -#include /* for smtpd.h */ - #include #include #include #include -#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 + * Copyright (c) 2011 Gilles Chehade + * + * 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 -- cgit v1.2.3-59-g8ed1b From 4e524d8c54215b970f0472da3cf06b3b8ef1700e Mon Sep 17 00:00:00 2001 From: Gilles Chehade Date: Thu, 27 Dec 2018 10:53:29 +0100 Subject: sync --- smtpd/aliases.c | 18 +++--- smtpd/lka.c | 16 ++--- smtpd/lka_filter.c | 22 +++---- smtpd/lka_session.c | 4 +- smtpd/ruleset.c | 54 +++++------------ smtpd/smtpd.h | 16 ++--- smtpd/table.c | 157 +++++++++++-------------------------------------- smtpd/table_db.c | 56 +++++++++++------- smtpd/table_getpwnam.c | 17 +++--- smtpd/table_proc.c | 49 ++++++--------- smtpd/table_static.c | 30 +++++----- 11 files changed, 165 insertions(+), 274 deletions(-) diff --git a/smtpd/aliases.c b/smtpd/aliases.c index 93d3fe68..634aa688 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 @@ -58,7 +58,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) @@ -67,7 +67,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; @@ -131,7 +131,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) @@ -141,7 +141,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) @@ -152,7 +152,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) @@ -162,7 +162,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) @@ -171,14 +171,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/lka.c b/smtpd/lka.c index c08e834b..7a6df074 100644 --- a/smtpd/lka.c +++ b/smtpd/lka.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lka.c,v 1.229 2018/12/23 16:37:53 eric Exp $ */ +/* $OpenBSD: lka.c,v 1.231 2018/12/26 20:13:43 eric Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard @@ -234,7 +234,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) @@ -282,7 +282,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) @@ -689,7 +689,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); @@ -719,7 +719,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); @@ -760,7 +760,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); @@ -790,7 +790,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); @@ -818,7 +818,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); diff --git a/smtpd/lka_filter.c b/smtpd/lka_filter.c index e4d9b849..eeba23e2 100644 --- a/smtpd/lka_filter.c +++ b/smtpd/lka_filter.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lka_filter.c,v 1.31 2018/12/23 15:48:16 gilles Exp $ */ +/* $OpenBSD: lka_filter.c,v 1.33 2018/12/26 15:55:09 eric Exp $ */ /* * Copyright (c) 2018 Gilles Chehade @@ -806,7 +806,7 @@ filter_check_rdns_table(struct filter *filter, enum table_service kind, const ch if (filter->config->rdns_table == NULL) return 0; - if (table_lookup(filter->config->rdns_table, NULL, key, kind, NULL) > 0) + if (table_match(filter->config->rdns_table, kind, key) > 0) ret = 1; return filter->config->not_rdns_table < 0 ? !ret : ret; @@ -820,7 +820,7 @@ filter_check_rdns_regex(struct filter *filter, const char *key) if (filter->config->rdns_regex == NULL) return 0; - if (table_lookup(filter->config->rdns_regex, NULL, key, K_REGEX, NULL) > 0) + if (table_match(filter->config->rdns_regex, K_REGEX, key) > 0) ret = 1; return filter->config->not_rdns_regex < 0 ? !ret : ret; } @@ -833,7 +833,7 @@ filter_check_src_table(struct filter *filter, enum table_service kind, const cha if (filter->config->src_table == NULL) return 0; - if (table_lookup(filter->config->src_table, NULL, key, kind, NULL) > 0) + if (table_match(filter->config->src_table, kind, key) > 0) ret = 1; return filter->config->not_src_table < 0 ? !ret : ret; } @@ -846,7 +846,7 @@ filter_check_src_regex(struct filter *filter, const char *key) if (filter->config->src_regex == NULL) return 0; - if (table_lookup(filter->config->src_regex, NULL, key, K_REGEX, NULL) > 0) + if (table_match(filter->config->src_regex, K_REGEX, key) > 0) ret = 1; return filter->config->not_src_regex < 0 ? !ret : ret; } @@ -859,7 +859,7 @@ filter_check_helo_table(struct filter *filter, enum table_service kind, const ch if (filter->config->helo_table == NULL) return 0; - if (table_lookup(filter->config->helo_table, NULL, key, kind, NULL) > 0) + if (table_match(filter->config->helo_table, kind, key) > 0) ret = 1; return filter->config->not_helo_table < 0 ? !ret : ret; } @@ -872,7 +872,7 @@ filter_check_helo_regex(struct filter *filter, const char *key) if (filter->config->helo_regex == NULL) return 0; - if (table_lookup(filter->config->helo_regex, NULL, key, K_REGEX, NULL) > 0) + if (table_match(filter->config->helo_regex, K_REGEX, key) > 0) ret = 1; return filter->config->not_helo_regex < 0 ? !ret : ret; } @@ -885,7 +885,7 @@ filter_check_mail_from_table(struct filter *filter, enum table_service kind, con if (filter->config->mail_from_table == NULL) return 0; - if (table_lookup(filter->config->mail_from_table, NULL, key, kind, NULL) > 0) + if (table_match(filter->config->mail_from_table, kind, key) > 0) ret = 1; return filter->config->not_mail_from_table < 0 ? !ret : ret; } @@ -898,7 +898,7 @@ filter_check_mail_from_regex(struct filter *filter, const char *key) if (filter->config->mail_from_regex == NULL) return 0; - if (table_lookup(filter->config->mail_from_regex, NULL, key, K_REGEX, NULL) > 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; } @@ -911,7 +911,7 @@ filter_check_rcpt_to_table(struct filter *filter, enum table_service kind, const if (filter->config->rcpt_to_table == NULL) return 0; - if (table_lookup(filter->config->rcpt_to_table, NULL, key, kind, NULL) > 0) + if (table_match(filter->config->rcpt_to_table, kind, key) > 0) ret = 1; return filter->config->not_rcpt_to_table < 0 ? !ret : ret; } @@ -924,7 +924,7 @@ filter_check_rcpt_to_regex(struct filter *filter, const char *key) if (filter->config->rcpt_to_regex == NULL) return 0; - if (table_lookup(filter->config->rcpt_to_regex, NULL, key, K_REGEX, NULL) > 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; } diff --git a/smtpd/lka_session.c b/smtpd/lka_session.c index 0ae31548..987a54db 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 @@ -377,7 +377,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/ruleset.c b/smtpd/ruleset.c index 7ab7755c..0d16d85d 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 @@ -33,22 +33,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) @@ -64,10 +49,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 @@ -100,10 +84,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 @@ -120,11 +103,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 @@ -141,10 +122,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 @@ -172,7 +152,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; @@ -180,7 +160,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 @@ -201,10 +181,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 @@ -225,10 +204,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/smtpd.h b/smtpd/smtpd.h index 47914bd5..6f42711a 100644 --- a/smtpd/smtpd.h +++ b/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.603 2018/12/23 16:37:53 eric Exp $ */ +/* $OpenBSD: smtpd.h,v 1.610 2018/12/27 09:30:29 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade @@ -362,13 +362,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, char **); - int (*fetch)(void *, struct dict *, enum table_service, char **); + void (*close)(struct table *); + int (*lookup)(struct table *, enum table_service, const char *, char **); + int (*fetch)(struct table *, enum table_service, char **); }; @@ -1603,9 +1604,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 *); diff --git a/smtpd/table.c b/smtpd/table.c index f070ab48..43ad9afa 100644 --- a/smtpd/table.c +++ b/smtpd/table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: table.c,v 1.34 2018/12/23 15:53:24 eric Exp $ */ +/* $OpenBSD: table.c,v 1.41 2018/12/27 09:30:29 eric Exp $ */ /* * Copyright (c) 2013 Eric Faurot @@ -51,40 +51,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; - if (!strcmp(backend, "db")) - return &table_backend_db; - 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"; - if (backend == &table_backend_db) - return "db"; - 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 * @@ -123,7 +116,13 @@ 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; @@ -137,14 +136,14 @@ 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 ? &buf : NULL); + r = table->t_backend->lookup(table, kind, lkey, lk ? &buf : NULL); 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) ? buf : "found", @@ -157,7 +156,7 @@ table_lookup(struct table *table, struct dict *params, const char *key, enum tab lk ? "lookup" : "check", lkey, table_service_name(kind), - table_backend_name(table->t_backend), + table->t_backend->name, table->t_name, r); @@ -167,7 +166,7 @@ table_lookup(struct table *table, struct dict *params, const char *key, enum tab } 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; @@ -175,12 +174,12 @@ table_fetch(struct table *table, struct dict *params, enum table_service kind, u if (table->t_backend->fetch == NULL) return (-1); - r = table->t_backend->fetch(table->t_handle, params, kind, lk ? &buf : NULL); + r = table->t_backend->fetch(table, kind, lk ? &buf : NULL); 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) ? buf : "found", @@ -191,7 +190,7 @@ table_fetch(struct table *table, struct dict *params, enum table_service kind, u 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); @@ -341,20 +340,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 @@ -667,90 +662,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]; - 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_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 606c54e9..9e71d1c3 100644 --- a/smtpd/table_db.c +++ b/smtpd/table_db.c @@ -1,4 +1,4 @@ -/* $OpenBSD: table_db.c,v 1.11 2018/12/23 15:53:24 eric Exp $ */ +/* $OpenBSD: table_db.c,v 1.17 2018/12/27 09:30:29 eric Exp $ */ /* * Copyright (c) 2011 Gilles Chehade @@ -42,16 +42,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, char **); -static int table_db_fetch(void *, struct dict *, enum table_service, char **); -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, @@ -74,7 +77,6 @@ struct dbhandle { DB *db; char pathname[PATH_MAX]; time_t mtime; - struct table *table; }; static int @@ -82,11 +84,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; } @@ -95,17 +97,33 @@ 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; @@ -122,7 +140,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; @@ -134,7 +151,7 @@ error: } static void -table_db_close(void *hdl) +table_db_close2(void *hdl) { struct dbhandle *handle = hdl; handle->db->close(handle->db); @@ -142,11 +159,10 @@ table_db_close(void *hdl) } static int -table_db_lookup(void *hdl, struct dict *params, const char *key, enum table_service service, +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; @@ -159,8 +175,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; } @@ -185,10 +200,9 @@ table_db_lookup(void *hdl, struct dict *params, const char *key, enum table_serv } static int -table_db_fetch(void *hdl, struct dict *params, enum table_service service, char **dst) +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; diff --git a/smtpd/table_getpwnam.c b/smtpd/table_getpwnam.c index 046eed56..abc4fc8f 100644 --- a/smtpd/table_getpwnam.c +++ b/smtpd/table_getpwnam.c @@ -1,4 +1,4 @@ -/* $OpenBSD: table_getpwnam.c,v 1.5 2018/12/23 15:53:24 eric Exp $ */ +/* $OpenBSD: table_getpwnam.c,v 1.11 2018/12/27 09:30:29 eric Exp $ */ /* * Copyright (c) 2012 Gilles Chehade @@ -40,12 +40,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, +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(void *); +static void table_getpwnam_close(struct table *); struct table_backend table_backend_getpwnam = { + "getpwnam", K_USERINFO, table_getpwnam_config, table_getpwnam_open, @@ -69,20 +70,20 @@ 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, +table_getpwnam_lookup(struct table *table, enum table_service kind, const char *key, char **dst) { struct passwd *pw; diff --git a/smtpd/table_proc.c b/smtpd/table_proc.c index ab3f5404..f930142f 100644 --- a/smtpd/table_proc.c +++ b/smtpd/table_proc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: table_proc.c,v 1.8 2018/12/23 15:53:24 eric Exp $ */ +/* $OpenBSD: table_proc.c,v 1.14 2018/12/27 09:30:29 eric Exp $ */ /* * Copyright (c) 2013 Eric Faurot @@ -116,7 +116,7 @@ table_proc_end(void) * API */ -static void * +static int table_proc_open(struct table *table) { struct table_proc_priv *priv; @@ -139,7 +139,9 @@ table_proc_open(struct table *table) table_proc_call(priv); table_proc_end(); - return (priv); + table->t_handle = priv; + + return (1); } static int @@ -158,47 +160,31 @@ 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, char **dst) +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; @@ -210,7 +196,7 @@ table_proc_lookup(void *arg, struct dict *params, const char *k, enum table_serv 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); @@ -240,9 +226,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, char **dst) +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; @@ -251,7 +237,7 @@ table_proc_fetch(void *arg, struct dict *params, enum table_service s, char **ds 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); @@ -279,6 +265,7 @@ table_proc_fetch(void *arg, struct dict *params, enum table_service s, char **ds } 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 352a0541..88377b3f 100644 --- a/smtpd/table_static.c +++ b/smtpd/table_static.c @@ -1,4 +1,4 @@ -/* $OpenBSD: table_static.c,v 1.21 2018/12/23 15:53:24 eric Exp $ */ +/* $OpenBSD: table_static.c,v 1.27 2018/12/27 09:30:29 eric Exp $ */ /* * Copyright (c) 2013 Eric Faurot @@ -41,14 +41,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, char **); -static int table_static_fetch(void *, struct dict *, enum table_service, +static int table_static_open(struct table *); +static int table_static_lookup(struct table *, enum table_service, const char *, char **); -static void table_static_close(void *); +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, @@ -202,23 +202,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, char **dst) +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; @@ -265,10 +265,8 @@ table_static_lookup(void *hdl, struct dict *params, const char *key, } static int -table_static_fetch(void *hdl, struct dict *params, - enum table_service service, char **dst) +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)) { -- cgit v1.2.3-59-g8ed1b