aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGilles Chehade <gilles@poolp.org>2018-12-26 12:36:06 +0100
committerGilles Chehade <gilles@poolp.org>2018-12-26 12:36:06 +0100
commitfb02161cc9c395e267668b745b79dc3157f4c515 (patch)
treeec8838a79cc386988d47d3a6207c1a48223c4e70
parentsync (diff)
downloadOpenSMTPD-fb02161cc9c395e267668b745b79dc3157f4c515.tar.xz
OpenSMTPD-fb02161cc9c395e267668b745b79dc3157f4c515.zip
sync
-rw-r--r--smtpd/dict.c9
-rw-r--r--smtpd/dict.h48
-rw-r--r--smtpd/lka.c153
-rw-r--r--smtpd/lka_filter.c249
-rw-r--r--smtpd/mta.c10
-rw-r--r--smtpd/mta_session.c209
-rw-r--r--smtpd/parse.y49
-rw-r--r--smtpd/pony.c6
-rw-r--r--smtpd/smtp.c4
-rw-r--r--smtpd/smtp_session.c200
-rw-r--r--smtpd/smtpd-api.h52
-rw-r--r--smtpd/smtpd.c14
-rw-r--r--smtpd/smtpd.h47
-rw-r--r--smtpd/table.c31
-rw-r--r--smtpd/table_db.c25
-rw-r--r--smtpd/table_getpwnam.c26
-rw-r--r--smtpd/table_proc.c19
-rw-r--r--smtpd/table_static.c26
-rw-r--r--smtpd/tree.c9
-rw-r--r--smtpd/tree.h48
20 files changed, 393 insertions, 841 deletions
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 <gilles@poolp.org>
@@ -20,17 +20,12 @@
#include <sys/types.h>
#include <sys/tree.h>
-#include <sys/socket.h> /* for smtpd.h */
-#include <sys/queue.h> /* for smtpd.h */
-#include <stdio.h> /* for smtpd.h */
-#include <imsg.h> /* for smtpd.h */
-
#include <err.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
-#include "smtpd.h"
+#include "dict.h"
struct dictentry {
SPLAY_ENTRY(dictentry) entry;
diff --git a/smtpd/dict.h b/smtpd/dict.h
new file mode 100644
index 00000000..c5d47e1a
--- /dev/null
+++ b/smtpd/dict.h
@@ -0,0 +1,48 @@
+/* $OpenBSD: dict.h,v 1.1 2018/12/23 16:06:24 gilles Exp $ */
+
+/*
+ * Copyright (c) 2013 Eric Faurot <eric@openbsd.org>
+ * Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _DICT_H_
+#define _DICT_H_
+
+SPLAY_HEAD(_dict, dictentry);
+
+struct dict {
+ struct _dict dict;
+ size_t count;
+};
+
+
+/* dict.c */
+#define dict_init(d) do { SPLAY_INIT(&((d)->dict)); (d)->count = 0; } while(0)
+#define dict_empty(d) SPLAY_EMPTY(&((d)->dict))
+#define dict_count(d) ((d)->count)
+int dict_check(struct dict *, const char *);
+void *dict_set(struct dict *, const char *, void *);
+void dict_xset(struct dict *, const char *, void *);
+void *dict_get(struct dict *, const char *);
+void *dict_xget(struct dict *, const char *);
+void *dict_pop(struct dict *, const char *);
+void *dict_xpop(struct dict *, const char *);
+int dict_poproot(struct dict *, void **);
+int dict_root(struct dict *, const char **, void **);
+int dict_iter(struct dict *, void **, const char **, void **);
+int dict_iterfrom(struct dict *, void **, const char *, const char **, void **);
+void dict_merge(struct dict *, struct dict *);
+
+#endif
diff --git a/smtpd/lka.c b/smtpd/lka.c
index 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 <pyr@openbsd.org>
@@ -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 <gilles@poolp.org>
@@ -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<<filter_config->phase);
filter->config = filter_config;
dict_set(&filters, name, filter);
+ log_trace(TRACE_FILTERS, "filters init type=builtin, name=%s, hooks=%08x",
+ name, filter->phases);
break;
case FILTER_TYPE_PROC:
@@ -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,8 +661,14 @@ filter_protocol(uint64_t reqid, enum filter_phase phase, const char *param)
fs->mail_from = xstrdup(param + 1);
*strchr(fs->mail_from, '>') = '\0';
+ param = fs->mail_from;
break;
+ case FILTER_RCPT_TO:
+ nparam = xstrdup(param + 1);
+ *strchr(nparam, '>') = '\0';
+ param = nparam;
+ break;
case FILTER_STARTTLS:
case FILTER_AUTH:
/* TBD */
@@ -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 <pyr@openbsd.org>
@@ -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 <pyr@openbsd.org>
@@ -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);
@@ -1508,153 +1448,6 @@ mta_error(struct mta_session *s, const char *fmt, ...)
}
static void
-mta_start_tls(struct mta_session *s)
-{
- struct ca_cert_req_msg req_ca_cert;
- const char *certname;
-
- if (s->relay->pki_name) {
- certname = s->relay->pki_name;
- req_ca_cert.fallback = 0;
- }
- else {
- certname = s->helo;
- req_ca_cert.fallback = 1;
- }
-
- req_ca_cert.reqid = s->id;
- (void)strlcpy(req_ca_cert.name, certname, sizeof req_ca_cert.name);
- m_compose(p_lka, IMSG_MTA_TLS_INIT, 0, 0, -1,
- &req_ca_cert, sizeof(req_ca_cert));
- tree_xset(&wait_ssl_init, s->id, s);
- s->flags |= MTA_WAIT;
- return;
-}
-
-static int
-mta_verify_certificate(struct mta_session *s)
-{
-#define MAX_CERTS 16
-#define MAX_CERT_LEN (MAX_IMSGSIZE - (IMSG_HEADER_SIZE + sizeof(req_ca_vrfy)))
- struct ca_vrfy_req_msg req_ca_vrfy;
- struct iovec iov[2];
- X509 *x;
- STACK_OF(X509) *xchain;
- const char *name;
- unsigned char *cert_der[MAX_CERTS];
- int cert_len[MAX_CERTS];
- int i, cert_count, res;
-
- res = 0;
- memset(cert_der, 0, sizeof(cert_der));
- memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy);
-
- /* Send the client certificate */
- if (s->relay->ca_name) {
- name = s->relay->ca_name;
- req_ca_vrfy.fallback = 0;
- }
- else {
- name = s->helo;
- req_ca_vrfy.fallback = 1;
- }
- if (strlcpy(req_ca_vrfy.name, name, sizeof req_ca_vrfy.name)
- >= sizeof req_ca_vrfy.name)
- return 0;
-
- x = SSL_get_peer_certificate(io_ssl(s->io));
- if (x == NULL)
- return 0;
- xchain = SSL_get_peer_cert_chain(io_ssl(s->io));
-
- /*
- * Client provided a certificate and possibly a certificate chain.
- * SMTP can't verify because it does not have the information that
- * it needs, instead it will pass the certificate and chain to the
- * lookup process and wait for a reply.
- *
- */
-
- cert_len[0] = i2d_X509(x, &cert_der[0]);
- X509_free(x);
-
- if (cert_len[0] < 0) {
- log_warnx("warn: failed to encode certificate");
- goto end;
- }
- log_debug("debug: certificate 0: len=%d", cert_len[0]);
- if (cert_len[0] > (int)MAX_CERT_LEN) {
- log_warnx("warn: certificate too long");
- goto end;
- }
-
- if (xchain) {
- cert_count = sk_X509_num(xchain);
- log_debug("debug: certificate chain len: %d", cert_count);
- if (cert_count >= MAX_CERTS) {
- log_warnx("warn: certificate chain too long");
- goto end;
- }
- }
- else
- cert_count = 0;
-
- for (i = 0; i < cert_count; ++i) {
- x = sk_X509_value(xchain, i);
- cert_len[i+1] = i2d_X509(x, &cert_der[i+1]);
- if (cert_len[i+1] < 0) {
- log_warnx("warn: failed to encode certificate");
- goto end;
- }
- log_debug("debug: certificate %i: len=%d", i+1, cert_len[i+1]);
- if (cert_len[i+1] > (int)MAX_CERT_LEN) {
- log_warnx("warn: certificate too long");
- goto end;
- }
- }
-
- tree_xset(&wait_ssl_verify, s->id, s);
- s->flags |= MTA_WAIT;
-
- /* Send the client certificate */
- req_ca_vrfy.reqid = s->id;
- req_ca_vrfy.cert_len = cert_len[0];
- req_ca_vrfy.n_chain = cert_count;
- iov[0].iov_base = &req_ca_vrfy;
- iov[0].iov_len = sizeof(req_ca_vrfy);
- iov[1].iov_base = cert_der[0];
- iov[1].iov_len = cert_len[0];
- m_composev(p_lka, IMSG_MTA_TLS_VERIFY_CERT, 0, 0, -1,
- iov, nitems(iov));
-
- memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy);
- req_ca_vrfy.reqid = s->id;
-
- /* Send the chain, one cert at a time */
- for (i = 0; i < cert_count; ++i) {
- req_ca_vrfy.cert_len = cert_len[i+1];
- iov[1].iov_base = cert_der[i+1];
- iov[1].iov_len = cert_len[i+1];
- m_composev(p_lka, IMSG_MTA_TLS_VERIFY_CHAIN, 0, 0, -1,
- iov, nitems(iov));
- }
-
- /* Tell lookup process that it can start verifying, we're done */
- memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy);
- req_ca_vrfy.reqid = s->id;
- m_compose(p_lka, IMSG_MTA_TLS_VERIFY, 0, 0, -1,
- &req_ca_vrfy, sizeof req_ca_vrfy);
-
- res = 1;
-
- end:
- for (i = 0; i < MAX_CERTS; ++i)
- free(cert_der[i]);
-
- return res;
-}
-
-static void
mta_cert_init(struct mta_session *s)
{
const char *name;
diff --git a/smtpd/parse.y b/smtpd/parse.y
index 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 <gilles@poolp.org>
@@ -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, "<dynproc:%016"PRIx64">", last_dynproc_id++);
+ (void)snprintf(buffer, sizeof buffer, "<dynproc:%08x>", last_dynproc_id++);
} while (dict_check(conf->sc_processors_dict, buffer));
if (dict_get(conf->sc_filters_dict, $2)) {
@@ -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, "<dynchain:%08x>", last_dynchain_id++);
+ } while (dict_check(conf->sc_filters_dict, buffer));
+
+ listen_opts.options |= LO_FILTER;
+ listen_opts.filtername = xstrdup(buffer);
+ filter_config = xcalloc(1, sizeof *filter_config);
+ filter_config->filter_type = FILTER_TYPE_CHAIN;
+ dict_init(&filter_config->chain_procs);
+ } '{' filter_list '}' {
+ dict_set(conf->sc_filters_dict, listen_opts.filtername, filter_config);
+ filter_config = NULL;
+ }
| MASK_SRC {
if (config_lo_mask_source(&listen_opts)) {
YYERROR;
@@ -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, "<dynchain:%08x>", last_dynchain_id++);
+ } while (dict_check(conf->sc_filters_dict, buffer));
+
+ listen_opts.options |= LO_FILTER;
+ listen_opts.filtername = xstrdup(buffer);
+ filter_config = xcalloc(1, sizeof *filter_config);
+ filter_config->filter_type = FILTER_TYPE_CHAIN;
+ dict_init(&filter_config->chain_procs);
+ } '{' filter_list '}' {
+ dict_set(conf->sc_filters_dict, listen_opts.filtername, filter_config);
+ filter_config = NULL;
+ }
| SMTPS {
if (listen_opts.options & LO_SSL) {
yyerror("TLS mode already specified");
diff --git a/smtpd/pony.c b/smtpd/pony.c
index 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 <gilles@poolp.org>
@@ -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 <gilles@poolp.org>
@@ -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 <gilles@poolp.org>
@@ -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);
@@ -2175,150 +2128,6 @@ smtp_mailaddr(struct mailaddr *maddr, char *line, int mailfrom, char **args,
}
static void
-smtp_tls_init(struct smtp_session *s)
-{
- struct ca_cert_req_msg req_ca_cert;
-
- req_ca_cert.reqid = s->id;
- if (s->listener->pki_name[0]) {
- (void)strlcpy(req_ca_cert.name, s->listener->pki_name,
- sizeof req_ca_cert.name);
- req_ca_cert.fallback = 0;
- }
- else {
- (void)strlcpy(req_ca_cert.name, s->smtpname,
- sizeof req_ca_cert.name);
- req_ca_cert.fallback = 1;
- }
- m_compose(p_lka, IMSG_SMTP_TLS_INIT, 0, 0, -1,
- &req_ca_cert, sizeof(req_ca_cert));
- tree_xset(&wait_ssl_init, s->id, s);
-}
-
-static int
-smtp_verify_certificate(struct smtp_session *s)
-{
-#define MAX_CERTS 16
-#define MAX_CERT_LEN (MAX_IMSGSIZE - (IMSG_HEADER_SIZE + sizeof(req_ca_vrfy)))
- struct ca_vrfy_req_msg req_ca_vrfy;
- struct iovec iov[2];
- X509 *x;
- STACK_OF(X509) *xchain;
- const char *name;
- unsigned char *cert_der[MAX_CERTS];
- int cert_len[MAX_CERTS];
- int i, cert_count, res;
-
- res = 0;
- memset(cert_der, 0, sizeof(cert_der));
- memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy);
-
- /* Send the client certificate */
- if (s->listener->ca_name[0]) {
- name = s->listener->ca_name;
- req_ca_vrfy.fallback = 0;
- }
- else {
- name = s->smtpname;
- req_ca_vrfy.fallback = 1;
- }
-
- if (strlcpy(req_ca_vrfy.name, name, sizeof req_ca_vrfy.name)
- >= sizeof req_ca_vrfy.name)
- return 0;
-
- x = SSL_get_peer_certificate(io_ssl(s->io));
- if (x == NULL)
- return 0;
- xchain = SSL_get_peer_cert_chain(io_ssl(s->io));
-
- /*
- * Client provided a certificate and possibly a certificate chain.
- * SMTP can't verify because it does not have the information that
- * it needs, instead it will pass the certificate and chain to the
- * lookup process and wait for a reply.
- *
- */
-
- cert_len[0] = i2d_X509(x, &cert_der[0]);
- X509_free(x);
-
- if (cert_len[0] < 0) {
- log_warnx("warn: failed to encode certificate");
- goto end;
- }
- log_debug("debug: certificate 0: len=%d", cert_len[0]);
- if (cert_len[0] > (int)MAX_CERT_LEN) {
- log_warnx("warn: certificate too long");
- goto end;
- }
-
- if (xchain) {
- cert_count = sk_X509_num(xchain);
- log_debug("debug: certificate chain len: %d", cert_count);
- if (cert_count >= MAX_CERTS) {
- log_warnx("warn: certificate chain too long");
- goto end;
- }
- }
- else
- cert_count = 0;
-
- for (i = 0; i < cert_count; ++i) {
- x = sk_X509_value(xchain, i);
- cert_len[i+1] = i2d_X509(x, &cert_der[i+1]);
- if (cert_len[i+1] < 0) {
- log_warnx("warn: failed to encode certificate");
- goto end;
- }
- log_debug("debug: certificate %i: len=%d", i+1, cert_len[i+1]);
- if (cert_len[i+1] > (int)MAX_CERT_LEN) {
- log_warnx("warn: certificate too long");
- goto end;
- }
- }
-
- tree_xset(&wait_ssl_verify, s->id, s);
-
- /* Send the client certificate */
- req_ca_vrfy.reqid = s->id;
- req_ca_vrfy.cert_len = cert_len[0];
- req_ca_vrfy.n_chain = cert_count;
- iov[0].iov_base = &req_ca_vrfy;
- iov[0].iov_len = sizeof(req_ca_vrfy);
- iov[1].iov_base = cert_der[0];
- iov[1].iov_len = cert_len[0];
- m_composev(p_lka, IMSG_SMTP_TLS_VERIFY_CERT, 0, 0, -1,
- iov, nitems(iov));
-
- memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy);
- req_ca_vrfy.reqid = s->id;
-
- /* Send the chain, one cert at a time */
- for (i = 0; i < cert_count; ++i) {
- req_ca_vrfy.cert_len = cert_len[i+1];
- iov[1].iov_base = cert_der[i+1];
- iov[1].iov_len = cert_len[i+1];
- m_composev(p_lka, IMSG_SMTP_TLS_VERIFY_CHAIN, 0, 0, -1,
- iov, nitems(iov));
- }
-
- /* Tell lookup process that it can start verifying, we're done */
- memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy);
- req_ca_vrfy.reqid = s->id;
- m_compose(p_lka, IMSG_SMTP_TLS_VERIFY, 0, 0, -1,
- &req_ca_vrfy, sizeof req_ca_vrfy);
-
- res = 1;
-
- end:
- for (i = 0; i < MAX_CERTS; ++i)
- free(cert_der[i]);
-
- return res;
-}
-
-static void
smtp_cert_init(struct smtp_session *s)
{
const char *name;
@@ -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 <eric@openbsd.org>
@@ -20,24 +20,14 @@
#ifndef _SMTPD_API_H_
#define _SMTPD_API_H_
+#include "dict.h"
+#include "tree.h"
+
struct mailaddr {
char user[SMTPD_MAXLOCALPARTSIZE];
char domain[SMTPD_MAXDOMAINPARTSIZE];
};
-SPLAY_HEAD(_dict, dictentry);
-SPLAY_HEAD(_tree, treeentry);
-
-struct tree {
- struct _tree tree;
- size_t count;
-};
-
-struct dict {
- struct _dict dict;
- size_t count;
-};
-
#define PROC_QUEUE_API_VERSION 2
enum {
@@ -244,23 +234,6 @@ msgid_to_evpid(uint32_t msgid)
return ((uint64_t)msgid << 32);
}
-/* dict.c */
-#define dict_init(d) do { SPLAY_INIT(&((d)->dict)); (d)->count = 0; } while(0)
-#define dict_empty(d) SPLAY_EMPTY(&((d)->dict))
-#define dict_count(d) ((d)->count)
-int dict_check(struct dict *, const char *);
-void *dict_set(struct dict *, const char *, void *);
-void dict_xset(struct dict *, const char *, void *);
-void *dict_get(struct dict *, const char *);
-void *dict_xget(struct dict *, const char *);
-void *dict_pop(struct dict *, const char *);
-void *dict_xpop(struct dict *, const char *);
-int dict_poproot(struct dict *, void **);
-int dict_root(struct dict *, const char **, void **);
-int dict_iter(struct dict *, void **, const char **, void **);
-int dict_iterfrom(struct dict *, void **, const char *, const char **, void **);
-void dict_merge(struct dict *, struct dict *);
-
/* esc.c */
const char *esc_code(enum enhanced_status_class, enum enhanced_status_code);
@@ -314,21 +287,4 @@ void table_api_on_fetch(int(*)(int, struct dict *, char *, size_t));
int table_api_dispatch(void);
const char *table_api_get_name(void);
-/* tree.c */
-#define tree_init(t) do { SPLAY_INIT(&((t)->tree)); (t)->count = 0; } while(0)
-#define tree_empty(t) SPLAY_EMPTY(&((t)->tree))
-#define tree_count(t) ((t)->count)
-int tree_check(struct tree *, uint64_t);
-void *tree_set(struct tree *, uint64_t, void *);
-void tree_xset(struct tree *, uint64_t, void *);
-void *tree_get(struct tree *, uint64_t);
-void *tree_xget(struct tree *, uint64_t);
-void *tree_pop(struct tree *, uint64_t);
-void *tree_xpop(struct tree *, uint64_t);
-int tree_poproot(struct tree *, uint64_t *, void **);
-int tree_root(struct tree *, uint64_t *, void **);
-int tree_iter(struct tree *, void **, uint64_t *, void **);
-int tree_iterfrom(struct tree *, void **, uint64_t, uint64_t *, void **);
-void tree_merge(struct tree *, struct tree *);
-
#endif
diff --git a/smtpd/smtpd.c b/smtpd/smtpd.c
index 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 <gilles@poolp.org>
@@ -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 <gilles@poolp.org>
@@ -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 <eric@openbsd.org>
@@ -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 <gilles@poolp.org>
@@ -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 <gilles@poolp.org>
@@ -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 <eric@openbsd.org>
@@ -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 <eric@openbsd.org>
@@ -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 <eric@openbsd.org>
@@ -19,17 +19,12 @@
#include <sys/types.h>
#include <sys/tree.h>
-#include <sys/socket.h> /* for smtpd.h */
-#include <sys/queue.h> /* for smtpd.h */
-#include <stdio.h> /* for smtpd.h */
-#include <imsg.h> /* for smtpd.h */
-
#include <err.h>
#include <inttypes.h>
#include <stdlib.h>
#include <limits.h>
-#include "smtpd.h"
+#include "tree.h"
struct treeentry {
SPLAY_ENTRY(treeentry) entry;
diff --git a/smtpd/tree.h b/smtpd/tree.h
new file mode 100644
index 00000000..3d719f09
--- /dev/null
+++ b/smtpd/tree.h
@@ -0,0 +1,48 @@
+/* $OpenBSD: tree.h,v 1.1 2018/12/23 16:06:24 gilles Exp $ */
+
+/*
+ * Copyright (c) 2013 Eric Faurot <eric@openbsd.org>
+ * Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _TREE_H_
+#define _TREE_H_
+
+SPLAY_HEAD(_tree, treeentry);
+
+struct tree {
+ struct _tree tree;
+ size_t count;
+};
+
+
+/* tree.c */
+#define tree_init(t) do { SPLAY_INIT(&((t)->tree)); (t)->count = 0; } while(0)
+#define tree_empty(t) SPLAY_EMPTY(&((t)->tree))
+#define tree_count(t) ((t)->count)
+int tree_check(struct tree *, uint64_t);
+void *tree_set(struct tree *, uint64_t, void *);
+void tree_xset(struct tree *, uint64_t, void *);
+void *tree_get(struct tree *, uint64_t);
+void *tree_xget(struct tree *, uint64_t);
+void *tree_pop(struct tree *, uint64_t);
+void *tree_xpop(struct tree *, uint64_t);
+int tree_poproot(struct tree *, uint64_t *, void **);
+int tree_root(struct tree *, uint64_t *, void **);
+int tree_iter(struct tree *, void **, uint64_t *, void **);
+int tree_iterfrom(struct tree *, void **, uint64_t, uint64_t *, void **);
+void tree_merge(struct tree *, struct tree *);
+
+#endif