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; };