Improve the cert_*() interface. Use the return value to tell whether
authoreric <eric@openbsd.org>
Tue, 11 Dec 2018 07:25:57 +0000 (07:25 +0000)
committereric <eric@openbsd.org>
Tue, 11 Dec 2018 07:25:57 +0000 (07:25 +0000)
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
usr.sbin/smtpd/smtpd.h

index a716004..05aff41 100644 (file)
@@ -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]);
index a3cdcb4..dfb8aac 100644 (file)
@@ -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 <gilles@poolp.org>
 #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];