From 08135f135b2b67d59058f6c4d9afac795b2cecca Mon Sep 17 00:00:00 2001 From: eric Date: Tue, 11 Dec 2018 07:25:57 +0000 Subject: [PATCH] Improve the cert_*() interface. Use the return value to tell whether the request is pending (waiting for an async event) or not. Success or failure is always reported through the callback function. ok gilles@ --- usr.sbin/smtpd/cert.c | 51 ++++++++++++++++++++++++------------------ usr.sbin/smtpd/smtpd.h | 8 ++++++- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/usr.sbin/smtpd/cert.c b/usr.sbin/smtpd/cert.c index a716004414f..05aff4181b1 100644 --- a/usr.sbin/smtpd/cert.c +++ b/usr.sbin/smtpd/cert.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cert.c,v 1.1 2018/12/07 08:05:59 eric Exp $ */ +/* $OpenBSD: cert.c,v 1.2 2018/12/11 07:25:57 eric Exp $ */ /* * Copyright (c) 2018 Eric Faurot @@ -77,8 +77,10 @@ cert_init(const char *name, int fallback, void (*cb)(void *, int, struct request *req; req = calloc(1, sizeof(*req)); - if (req == NULL) - return -1; + if (req == NULL) { + cb(arg, CA_FAIL, NULL, NULL, 0); + return 0; + } while (req->id == 0 || SPLAY_FIND(cert_reqtree, &reqs, req)) req->id = arc4random(); req->cb_get_certificate = cb; @@ -90,7 +92,7 @@ cert_init(const char *name, int fallback, void (*cb)(void *, int, m_add_int(p_cert, fallback); m_close(p_cert); - return 0; + return 1; } int @@ -102,14 +104,20 @@ cert_verify(const void *ssl, const char *name, int fallback, STACK_OF(X509) *xchain; unsigned char *cert_der[MAX_CERTS]; int cert_len[MAX_CERTS]; - int i, cert_count, res; + int i, cert_count, ret; - res = -1; + x = SSL_get_peer_certificate(ssl); + if (x == NULL) { + cb(arg, CERT_NOCERT); + return 0; + } + + ret = 0; memset(cert_der, 0, sizeof(cert_der)); req = calloc(1, sizeof(*req)); if (req == NULL) - return -1; + goto end; while (req->id == 0 || SPLAY_FIND(cert_reqtree, &reqs, req)) req->id = arc4random(); req->cb_verify = cb; @@ -126,14 +134,11 @@ cert_verify(const void *ssl, const char *name, int fallback, } for (i = 0; i < cert_count; ++i) { - if (i == 0) - x = SSL_get_peer_certificate(ssl); - else - x = sk_X509_value(xchain, i - 1); - - if (x == NULL) { - log_warnx("warn: failed to retreive certificate"); - goto end; + if (i != 0) { + if ((x = sk_X509_value(xchain, i - 1)) == NULL) { + log_warnx("warn: failed to retrieve certificate"); + goto end; + } } cert_len[i] = i2d_X509(x, &cert_der[i]); @@ -165,18 +170,20 @@ cert_verify(const void *ssl, const char *name, int fallback, m_add_int(p_cert, fallback); m_close(p_cert); - res = 0; + ret = 1; end: for (i = 0; i < MAX_CERTS; ++i) free(cert_der[i]); - if (res == -1) { - SPLAY_REMOVE(cert_reqtree, &reqs, req); + if (ret == 0) { + if (req) + SPLAY_REMOVE(cert_reqtree, &reqs, req); free(req); + cb(arg, CERT_ERROR); } - return res; + return ret; } @@ -317,11 +324,11 @@ cert_do_verify(struct session *s, const char *name, int fallback) cafile = ca ? ca->ca_cert_file : CA_FILE; if (ca == NULL && !fallback) - res = CA_FAIL; + res = CERT_NOCA; else if (!cert_X509_verify(s, cafile, NULL)) - res = CA_FAIL; + res = CERT_INVALID; else - res = CA_OK; + res = CERT_OK; for (i = 0; i < s->cert_count; ++i) free(s->cert[i]); diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index a3cdcb4952a..dfb8aac8e5d 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.585 2018/12/09 18:05:20 gilles Exp $ */ +/* $OpenBSD: smtpd.h,v 1.586 2018/12/11 07:25:57 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade @@ -100,6 +100,12 @@ #define P_NEWALIASES 0 #define P_MAKEMAP 1 +#define CERT_ERROR -1 +#define CERT_OK 0 +#define CERT_NOCA 1 +#define CERT_NOCERT 2 +#define CERT_INVALID 3 + struct userinfo { char username[SMTPD_VUSERNAME_SIZE]; char directory[PATH_MAX]; -- 2.20.1