On Thu, Jun 20, 2019 at 07:58:10PM +0200, Bruno Flueckiger wrote:
> Hi,
> 
> The patch below adds OCSP stapling to the TLS server in relayd(8). The
> OCSP response is read from a binary encoded DER file that can be created
> using ocspcheck(8).
> 
> If a file with the same name as the certificate and private key files is
> found, its content is loaded and OCSP stapling is active. If there is no
> file or loading its content fails, OCSP stapling remains disabled.
> 
> relayd(8) uses the same mechanism it uses to find the certificate file,
> only the file name extension is different: .der instead of .pem
> 

I had this diff finished more than a month ago, but it had to wait for
the SNI diff to go in.  It is suprisingly similar to your version
except some minor difference in relay_tls_ctx_create(), the man page,
and the fact that I've decided for using ".ocsp" instead of ".der" for
the ending (as .der could be anything).

OK?

Reyk

Index: usr.sbin/relayd/config.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/config.c,v
retrieving revision 1.39
diff -u -p -u -p -r1.39 config.c
--- usr.sbin/relayd/config.c    1 Jun 2019 09:54:19 -0000       1.39
+++ usr.sbin/relayd/config.c    21 Jun 2019 11:11:05 -0000
@@ -903,6 +903,16 @@ config_setrelay(struct relayd *env, stru
                                            rlay->rl_conf.name);
                                        return (-1);
                                }
+                               if (id == PROC_RELAY &&
+                                   cert->cert_ocsp_fd != -1 &&
+                                   config_setrelayfd(ps, id, n,
+                                   cert->cert_id, cert->cert_relayid,
+                                   RELAY_FD_OCSP, cert->cert_ocsp_fd) == -1) {
+                                       log_warn("%s: fd passing failed for "
+                                           "`%s'", __func__,
+                                           rlay->rl_conf.name);
+                                       return (-1);
+                               }
                                if (id == PROC_CA &&
                                    cert->cert_key_fd != -1 &&
                                    config_setrelayfd(ps, id, n,
@@ -992,6 +1002,10 @@ config_setrelay(struct relayd *env, stru
                        close(cert->cert_key_fd);
                        cert->cert_key_fd = -1;
                }
+               if (cert->cert_ocsp_fd != -1) {
+                       close(cert->cert_ocsp_fd);
+                       cert->cert_ocsp_fd = -1;
+               }
        }
 
        return (0);
@@ -1113,6 +1127,7 @@ config_getrelayfd(struct relayd *env, st
        switch (crfd.type) {
        case RELAY_FD_CERT:
        case RELAY_FD_KEY:
+       case RELAY_FD_OCSP:
                if ((cert = cert_find(env, crfd.id)) == NULL) {
                        if ((cert = cert_add(env, crfd.id)) == NULL)
                                return (-1);
@@ -1133,6 +1148,9 @@ config_getrelayfd(struct relayd *env, st
                break;
        case RELAY_FD_KEY:
                cert->cert_key_fd = imsg->fd;
+               break;
+       case RELAY_FD_OCSP:
+               cert->cert_ocsp_fd = imsg->fd;
                break;
        case RELAY_FD_CACERT:
                rlay->rl_tls_ca_fd = imsg->fd;
Index: usr.sbin/relayd/relay.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relay.c,v
retrieving revision 1.247
diff -u -p -u -p -r1.247 relay.c
--- usr.sbin/relayd/relay.c     31 May 2019 15:15:37 -0000      1.247
+++ usr.sbin/relayd/relay.c     21 Jun 2019 11:11:06 -0000
@@ -2130,8 +2130,8 @@ relay_tls_ctx_create(struct relay *rlay)
        struct relay_cert       *cert;
        const char              *fake_key;
        int                      fake_keylen, keyfound = 0;
-       char                    *buf = NULL, *cabuf = NULL;
-       off_t                    len = 0, calen = 0;
+       char                    *buf = NULL, *cabuf = NULL, *ocspbuf = NULL;
+       off_t                    len = 0, calen = 0, ocsplen = 0;
 
        if ((tls_cfg = tls_config_new()) == NULL) {
                log_warnx("unable to allocate TLS config");
@@ -2203,6 +2203,16 @@ relay_tls_ctx_create(struct relay *rlay)
                        }
                        cert->cert_fd = -1;
 
+                       if (cert->cert_ocsp_fd != -1 &&
+                           (ocspbuf = relay_load_fd(cert->cert_ocsp_fd,
+                           &ocsplen)) == NULL) {
+                               log_warn("failed to load OCSP staplefile");
+                               goto err;
+                       }
+                       if (ocsplen == 0)
+                               purge_key(&ocspbuf, ocsplen);
+                       cert->cert_ocsp_fd = -1;
+
                        if ((fake_keylen = ssl_ctx_fake_private_key(buf, len,
                            &fake_key)) == -1) {
                                /* error already printed */
@@ -2211,7 +2221,7 @@ relay_tls_ctx_create(struct relay *rlay)
 
                        if (keyfound == 1 &&
                            tls_config_set_keypair_ocsp_mem(tls_cfg, buf, len,
-                           fake_key, fake_keylen, NULL, 0) != 0) {
+                           fake_key, fake_keylen, ocspbuf, ocsplen) != 0) {
                                log_warnx("failed to set tls certificate: %s",
                                    tls_config_error(tls_cfg));
                                goto err;
@@ -2223,13 +2233,14 @@ relay_tls_ctx_create(struct relay *rlay)
                                goto err;
 
                        if (tls_config_add_keypair_ocsp_mem(tls_cfg, buf, len,
-                           fake_key, fake_keylen, NULL, 0) != 0) {
+                           fake_key, fake_keylen, ocspbuf, ocsplen) != 0) {
                                log_warnx("failed to add tls certificate: %s",
                                    tls_config_error(tls_cfg));
                                goto err;
                        }
 
                        purge_key(&buf, len);
+                       purge_key(&ocspbuf, ocsplen);
                }
 
                if (rlay->rl_tls_cacert_fd != -1) {
@@ -2269,6 +2280,7 @@ relay_tls_ctx_create(struct relay *rlay)
 
        return (0);
  err:
+       purge_key(&ocspbuf, ocsplen);
        purge_key(&cabuf, calen);
        purge_key(&buf, len);
 
Index: usr.sbin/relayd/relayd.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relayd.c,v
retrieving revision 1.179
diff -u -p -u -p -r1.179 relayd.c
--- usr.sbin/relayd/relayd.c    31 May 2019 15:25:57 -0000      1.179
+++ usr.sbin/relayd/relayd.c    21 Jun 2019 11:11:06 -0000
@@ -605,6 +605,8 @@ purge_relay(struct relayd *env, struct r
                        close(cert->cert_fd);
                if (cert->cert_key_fd != -1)
                        close(cert->cert_key_fd);
+               if (cert->cert_ocsp_fd != -1)
+                       close(cert->cert_ocsp_fd);
                if (cert->cert_pkey != NULL)
                        EVP_PKEY_free(cert->cert_pkey);
                TAILQ_REMOVE(env->sc_certs, cert, cert_entry);
@@ -1270,6 +1272,7 @@ cert_add(struct relayd *env, objid_t id)
        cert->cert_id = id;
        cert->cert_fd = -1;
        cert->cert_key_fd = -1;
+       cert->cert_ocsp_fd = -1;
 
        TAILQ_INSERT_TAIL(env->sc_certs, cert, cert_entry);
 
@@ -1325,7 +1328,7 @@ relay_load_certfiles(struct relayd *env,
        struct protocol *proto = rlay->rl_proto;
        struct relay_cert *cert;
        int      useport = htons(rlay->rl_conf.port);
-       int      cert_fd = -1, key_fd = -1;
+       int      cert_fd = -1, key_fd = -1, ocsp_fd = -1;
 
        if (rlay->rl_conf.flags & F_TLSCLIENT) {
                if (strlen(proto->tlsca) && rlay->rl_tls_ca_fd == -1) {
@@ -1389,12 +1392,25 @@ relay_load_certfiles(struct relayd *env,
                goto fail;
        log_debug("%s: using private key %s", __func__, certfile);
 
+       if (useport) {
+               if (snprintf(certfile, sizeof(certfile),
+                   "/etc/ssl/%s:%u.ocsp", hbuf, useport) == -1)
+                       goto fail;
+       } else {
+               if (snprintf(certfile, sizeof(certfile),
+                   "/etc/ssl/%s.ocsp", hbuf) == -1)
+                       goto fail;
+       }
+       if ((ocsp_fd = open(certfile, O_RDONLY)) != -1)
+               log_debug("%s: using OCSP staple file %s", __func__, certfile);
+
        if ((cert = cert_add(env, 0)) == NULL)
                goto fail;
 
        cert->cert_relayid = rlay->rl_conf.id;
        cert->cert_fd = cert_fd;
        cert->cert_key_fd = key_fd;
+       cert->cert_ocsp_fd = ocsp_fd;
 
        return (0);
 
@@ -1403,6 +1419,8 @@ relay_load_certfiles(struct relayd *env,
                close(cert_fd);
        if (key_fd != -1)
                close(key_fd);
+       if (ocsp_fd != -1)
+               close(ocsp_fd);
 
        return (-1);
 }
Index: usr.sbin/relayd/relayd.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relayd.conf.5,v
retrieving revision 1.190
diff -u -p -u -p -r1.190 relayd.conf.5
--- usr.sbin/relayd/relayd.conf.5       31 May 2019 15:25:57 -0000      1.190
+++ usr.sbin/relayd/relayd.conf.5       21 Jun 2019 11:11:07 -0000
@@ -965,6 +965,15 @@ a keypair will be loaded using the speci
 See
 .Xr ssl 8
 for details about SSL/TLS server certificates.
+.Pp
+An optional OCSP staple file will be used during TLS handshakes with
+this server if it is found as a non-empty file in
+.Pa /etc/ssl/name:port.ocsp
+or
+.Pa /etc/ssl/name.ocsp .
+The file should contain a DER-format OCSP response retrieved from an
+OCSP server for the certificate in use, and can be created using
+ocspcheck(8).
 .It Ic no cipher-server-preference
 Prefer the client's cipher list over the server's preferences when
 choosing a cipher for the connection.
@@ -1594,6 +1603,7 @@ router "uplinks" {
 }
 .Ed
 .Sh SEE ALSO
+.Xr ocspcheck 8 ,
 .Xr relayctl 8 ,
 .Xr relayd 8 ,
 .Xr snmpd 8 ,
Index: usr.sbin/relayd/relayd.h
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relayd.h,v
retrieving revision 1.258
diff -u -p -u -p -r1.258 relayd.h
--- usr.sbin/relayd/relayd.h    31 May 2019 15:25:57 -0000      1.258
+++ usr.sbin/relayd/relayd.h    21 Jun 2019 11:11:07 -0000
@@ -141,7 +141,8 @@ enum fd_type {
        RELAY_FD_CERT   = 1,
        RELAY_FD_CACERT = 2,
        RELAY_FD_CAFILE = 3,
-       RELAY_FD_KEY    = 4
+       RELAY_FD_KEY    = 4,
+       RELAY_FD_OCSP   = 5
 };
 
 struct ctl_relayfd {
@@ -781,6 +782,7 @@ struct relay_cert {
        objid_t                  cert_relayid;
        int                      cert_fd;
        int                      cert_key_fd;
+       int                      cert_ocsp_fd;
        EVP_PKEY                *cert_pkey;
        TAILQ_ENTRY(relay_cert)  cert_entry;
 };

Reply via email to