summaryrefslogtreecommitdiff
path: root/usr.sbin/smtpd/cert.c
diff options
context:
space:
mode:
authorEric Faurot <eric@cvs.openbsd.org>2018-12-11 07:25:58 +0000
committerEric Faurot <eric@cvs.openbsd.org>2018-12-11 07:25:58 +0000
commit43280a78c4413aee0280f177010c660771f50f2a (patch)
tree19cdd492fec61259d0b6de6107bff7156aa1be5a /usr.sbin/smtpd/cert.c
parent3e11e8bf1454cbcfe7cba2f7935d6ddf0f21cc78 (diff)
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@
Diffstat (limited to 'usr.sbin/smtpd/cert.c')
-rw-r--r--usr.sbin/smtpd/cert.c51
1 files changed, 29 insertions, 22 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 <eric@openbsd.org>
@@ -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]);