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 Cheers, Bruno Index: usr.sbin/relayd/config.c =================================================================== RCS file: /cvs/src/usr.sbin/relayd/config.c,v retrieving revision 1.39 diff -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 20 Jun 2019 17:37:09 -0000 @@ -913,6 +913,14 @@ config_setrelay(struct relayd *env, stru rlay->rl_conf.name); return (-1); } + if (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); + } } } @@ -992,6 +1000,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 +1125,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); @@ -1139,6 +1152,9 @@ config_getrelayfd(struct relayd *env, st break; case RELAY_FD_CAFILE: rlay->rl_tls_cacert_fd = imsg->fd; + break; + case RELAY_FD_OCSP: + cert->cert_ocsp_fd = imsg->fd; break; } Index: usr.sbin/relayd/relay.c =================================================================== RCS file: /cvs/src/usr.sbin/relayd/relay.c,v retrieving revision 1.247 diff -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 20 Jun 2019 17:37:09 -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"); @@ -2209,9 +2209,19 @@ relay_tls_ctx_create(struct relay *rlay) goto err; } + if (cert->cert_ocsp_fd == -1) + goto without; + + if ((ocspbuf = relay_load_fd(cert->cert_ocsp_fd, + &ocsplen)) == NULL) { + log_warn("failed to load ocsp staple"); + ocsplen = 0; + } + + without: 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,7 +2233,7 @@ 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; Index: usr.sbin/relayd/relayd.c =================================================================== RCS file: /cvs/src/usr.sbin/relayd/relayd.c,v retrieving revision 1.179 diff -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 20 Jun 2019 17:37:09 -0000 @@ -1270,6 +1270,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 +1326,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 +1390,32 @@ 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.der", hbuf, useport) == -1) + goto add; + } else { + if (snprintf(certfile, sizeof(certfile), + "/etc/ssl/%s.der", hbuf) == -1) + goto add; + } + if (access(certfile, F_OK) == -1) + goto add; + if ((ocsp_fd = open(certfile, O_RDONLY)) == -1) { + log_warn("%s: cannot open ocsp staple file %s", __func__, + certfile); + goto add; + } + log_debug("%s: using ocsp staple file %s", __func__, certfile); + + add: 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 +1424,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 -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 20 Jun 2019 17:37:09 -0000 @@ -948,20 +948,27 @@ The default is .Ic no edh . .It Ic keypair Ar name The relay will attempt to look up a private key in -.Pa /etc/ssl/private/name:port.key -and a public certificate in +.Pa /etc/ssl/private/name:port.key , +a public certificate in .Pa /etc/ssl/name:port.crt , +and an OCSP reponse for stapling in +.Pa /etc/ssl/name:port.der , where .Ar port is the specified port that the relay listens on. If these files are not present, the relay will continue to look in -.Pa /etc/ssl/private/name.key +.Pa /etc/ssl/private/name.key , +.Pa /etc/ssl/name.crt , and -.Pa /etc/ssl/name.crt . +.Pa /etc/ssl/name.der . This option can be specified multiple times for TLS Server Name Indication. If not specified, a keypair will be loaded using the specified IP address of the relay as .Ar name . +The OCSP response file is only required if the relay should provide OCSP +stapling. +.Xr ocspcheck 8 +can be used to create a staplefile. See .Xr ssl 8 for details about SSL/TLS server certificates. Index: usr.sbin/relayd/relayd.h =================================================================== RCS file: /cvs/src/usr.sbin/relayd/relayd.h,v retrieving revision 1.258 diff -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 20 Jun 2019 17:37:09 -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; };