diff options
-rw-r--r-- | usr.sbin/relayd/config.c | 23 | ||||
-rw-r--r-- | usr.sbin/relayd/parse.y | 17 | ||||
-rw-r--r-- | usr.sbin/relayd/relay.c | 25 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.c | 10 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.conf.5 | 7 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.h | 15 |
6 files changed, 82 insertions, 15 deletions
diff --git a/usr.sbin/relayd/config.c b/usr.sbin/relayd/config.c index 3024c0768f0..83f4ec87fc8 100644 --- a/usr.sbin/relayd/config.c +++ b/usr.sbin/relayd/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.45 2024/01/17 10:01:24 claudio Exp $ */ +/* $OpenBSD: config.c,v 1.46 2024/10/28 19:56:18 tb Exp $ */ /* * Copyright (c) 2011 - 2014 Reyk Floeter <reyk@openbsd.org> @@ -953,6 +953,15 @@ config_setrelay(struct relayd *env, struct relay *rlay) rlay->rl_conf.name); return (-1); } + if (rlay->rl_tls_client_ca_fd != -1 && + config_setrelayfd(ps, id, n, 0, + rlay->rl_conf.id, RELAY_FD_CLIENTCACERT, + rlay->rl_tls_client_ca_fd) == -1) { + log_warn("%s: fd passing failed for " + "`%s'", __func__, + rlay->rl_conf.name); + return (-1); + } /* Prevent fd exhaustion in the parent. */ if (proc_flush_imsg(ps, id, n) == -1) { log_warn("%s: failed to flush " @@ -986,6 +995,10 @@ config_setrelay(struct relayd *env, struct relay *rlay) close(rlay->rl_s); rlay->rl_s = -1; } + if (rlay->rl_tls_client_ca_fd != -1) { + close(rlay->rl_tls_client_ca_fd); + rlay->rl_tls_client_ca_fd = -1; + } if (rlay->rl_tls_cacert_fd != -1) { close(rlay->rl_tls_cacert_fd); rlay->rl_tls_cacert_fd = -1; @@ -1011,6 +1024,10 @@ config_setrelay(struct relayd *env, struct relay *rlay) cert->cert_ocsp_fd = -1; } } + if (rlay->rl_tls_client_ca_fd != -1) { + close(rlay->rl_tls_client_ca_fd); + rlay->rl_tls_client_ca_fd = -1; + } return (0); } @@ -1033,6 +1050,7 @@ config_getrelay(struct relayd *env, struct imsg *imsg) rlay->rl_s = imsg_get_fd(imsg); rlay->rl_tls_ca_fd = -1; rlay->rl_tls_cacert_fd = -1; + rlay->rl_tls_client_ca_fd = -1; if (ps->ps_what[privsep_process] & CONFIG_PROTOS) { if (rlay->rl_conf.proto == EMPTY_ID) @@ -1162,6 +1180,9 @@ config_getrelayfd(struct relayd *env, struct imsg *imsg) case RELAY_FD_CAFILE: rlay->rl_tls_cacert_fd = imsg_get_fd(imsg); break; + case RELAY_FD_CLIENTCACERT: + rlay->rl_tls_client_ca_fd = imsg->fd; + break; } DPRINTF("%s: %s %d received relay fd %d type %d for relay %s", __func__, diff --git a/usr.sbin/relayd/parse.y b/usr.sbin/relayd/parse.y index eea485c4471..fcdfb8e92e3 100644 --- a/usr.sbin/relayd/parse.y +++ b/usr.sbin/relayd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.257 2024/08/10 05:47:29 tb Exp $ */ +/* $OpenBSD: parse.y,v 1.258 2024/10/28 19:56:18 tb Exp $ */ /* * Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org> @@ -179,7 +179,7 @@ typedef struct { %token TIMEOUT TLS TO ROUTER RTLABEL TRANSPARENT URL WITH TTL RTABLE %token MATCH PARAMS RANDOM LEASTSTATES SRCHASH KEY CERTIFICATE PASSWORD ECDHE %token EDH TICKETS CONNECTION CONNECTIONS CONTEXT ERRORS STATE CHANGES CHECKS -%token WEBSOCKETS PFLOG +%token WEBSOCKETS PFLOG CLIENT %token <v.string> STRING %token <v.number> NUMBER %type <v.string> context hostname interface table value path @@ -1351,6 +1351,16 @@ tlsflags : SESSION TICKETS { proto->tickets = 1; } name->name = $2; TAILQ_INSERT_TAIL(&proto->tlscerts, name, entry); } + | CLIENT CA STRING { + if (strlcpy(proto->tlsclientca, $3, + sizeof(proto->tlsclientca)) >= + sizeof(proto->tlsclientca)) { + yyerror("tlsclientca truncated"); + free($3); + YYERROR; + } + free($3); + } | NO flag { proto->tlsflags &= ~($2); } | flag { proto->tlsflags |= $1; } ; @@ -1822,6 +1832,7 @@ relay : RELAY STRING { r->rl_conf.dstretry = 0; r->rl_tls_ca_fd = -1; r->rl_tls_cacert_fd = -1; + r->rl_tls_client_ca_fd = -1; TAILQ_INIT(&r->rl_tables); if (last_relay_id == INT_MAX) { yyerror("too many relays defined"); @@ -2411,6 +2422,7 @@ lookup(char *s) { "check", CHECK }, { "checks", CHECKS }, { "ciphers", CIPHERS }, + { "client", CLIENT }, { "code", CODE }, { "connection", CONNECTION }, { "context", CONTEXT }, @@ -3397,6 +3409,7 @@ relay_inherit(struct relay *ra, struct relay *rb) if (!(rb->rl_conf.flags & F_TLS)) { rb->rl_tls_cacert_fd = -1; rb->rl_tls_ca_fd = -1; + rb->rl_tls_client_ca_fd = -1; } TAILQ_INIT(&rb->rl_tables); diff --git a/usr.sbin/relayd/relay.c b/usr.sbin/relayd/relay.c index c29f3917152..6d0970802c5 100644 --- a/usr.sbin/relayd/relay.c +++ b/usr.sbin/relayd/relay.c @@ -1,4 +1,4 @@ -/* $OpenBSD: relay.c,v 1.259 2024/01/17 10:01:24 claudio Exp $ */ +/* $OpenBSD: relay.c,v 1.260 2024/10/28 19:56:18 tb Exp $ */ /* * Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org> @@ -2159,8 +2159,7 @@ relay_tls_ctx_create(struct relay *rlay) tls_config_insecure_noverifyname(tls_client_cfg); if (rlay->rl_tls_ca_fd != -1) { - if ((buf = relay_load_fd(rlay->rl_tls_ca_fd, &len)) == - NULL) { + if ((buf = relay_load_fd(rlay->rl_tls_ca_fd, &len)) == NULL) { log_warn("failed to read root certificates"); goto err; } @@ -2251,6 +2250,26 @@ relay_tls_ctx_create(struct relay *rlay) } rlay->rl_tls_cacert_fd = -1; + if (rlay->rl_tls_client_ca_fd != -1) { + if ((buf = relay_load_fd(rlay->rl_tls_client_ca_fd, + &len)) == NULL) { + log_warn( + "failed to read tls client CA certificate"); + goto err; + } + + if (tls_config_set_ca_mem(tls_cfg, buf, len) != 0) { + log_warnx( + "failed to set tls client CA cert: %s", + tls_config_error(tls_cfg)); + goto err; + } + purge_key(&buf, len); + + tls_config_verify_client(tls_cfg); + } + rlay->rl_tls_client_ca_fd = -1; + tls = tls_server(); if (tls == NULL) { log_warnx("unable to allocate TLS context"); diff --git a/usr.sbin/relayd/relayd.c b/usr.sbin/relayd/relayd.c index df93c9527cb..76fa9e8b043 100644 --- a/usr.sbin/relayd/relayd.c +++ b/usr.sbin/relayd/relayd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: relayd.c,v 1.191 2023/06/25 08:07:38 op Exp $ */ +/* $OpenBSD: relayd.c,v 1.192 2024/10/28 19:56:18 tb Exp $ */ /* * Copyright (c) 2007 - 2016 Reyk Floeter <reyk@openbsd.org> @@ -1359,6 +1359,14 @@ relay_load_certfiles(struct relayd *env, struct relay *rlay, const char *name) if ((rlay->rl_conf.flags & F_TLS) == 0) return (0); + if (strlen(proto->tlsclientca) && rlay->rl_tls_client_ca_fd == -1) { + if ((rlay->rl_tls_client_ca_fd = + open(proto->tlsclientca, O_RDONLY)) == -1) + return (-1); + log_debug("%s: using client ca %s", __func__, + proto->tlsclientca); + } + if (name == NULL && print_host(&rlay->rl_conf.ss, hbuf, sizeof(hbuf)) == NULL) goto fail; diff --git a/usr.sbin/relayd/relayd.conf.5 b/usr.sbin/relayd/relayd.conf.5 index 50c73cbec15..8372875b853 100644 --- a/usr.sbin/relayd/relayd.conf.5 +++ b/usr.sbin/relayd/relayd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: relayd.conf.5,v 1.210 2024/09/21 05:37:26 aisha Exp $ +.\" $OpenBSD: relayd.conf.5,v 1.211 2024/10/28 19:56:18 tb Exp $ .\" .\" Copyright (c) 2006 - 2016 Reyk Floeter <reyk@openbsd.org> .\" Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -15,7 +15,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: September 21 2024 $ +.Dd $Mdocdate: October 28 2024 $ .Dt RELAYD.CONF 5 .Os .Sh NAME @@ -954,6 +954,9 @@ will be used (strong crypto cipher suites without anonymous DH). See the CIPHERS section of .Xr openssl 1 for information about TLS cipher suites and preference lists. +.It Ic client ca Ar path +Require TLS client certificates that can be verified against the CA +certificates in the specified file. .It Ic client-renegotiation Allow client-initiated renegotiation. To mitigate a potential DoS risk, diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h index 865cf31ad69..3b5c3987f93 100644 --- a/usr.sbin/relayd/relayd.h +++ b/usr.sbin/relayd/relayd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: relayd.h,v 1.275 2024/10/08 05:28:11 jsg Exp $ */ +/* $OpenBSD: relayd.h,v 1.276 2024/10/28 19:56:18 tb Exp $ */ /* * Copyright (c) 2006 - 2016 Reyk Floeter <reyk@openbsd.org> @@ -137,11 +137,12 @@ struct ctl_relaytable { }; enum fd_type { - RELAY_FD_CERT = 1, - RELAY_FD_CACERT = 2, - RELAY_FD_CAFILE = 3, - RELAY_FD_KEY = 4, - RELAY_FD_OCSP = 5 + RELAY_FD_CERT = 1, + RELAY_FD_CACERT = 2, + RELAY_FD_CAFILE = 3, + RELAY_FD_KEY = 4, + RELAY_FD_OCSP = 5, + RELAY_FD_CLIENTCACERT = 6 }; struct ctl_relayfd { @@ -744,6 +745,7 @@ struct protocol { char tlscacert[PATH_MAX]; char tlscakey[PATH_MAX]; char *tlscapass; + char tlsclientca[PATH_MAX]; struct keynamelist tlscerts; char name[MAX_NAME_SIZE]; int tickets; @@ -833,6 +835,7 @@ struct relay { int rl_tls_ca_fd; int rl_tls_cacert_fd; + int rl_tls_client_ca_fd; EVP_PKEY *rl_tls_pkey; X509 *rl_tls_cacertx509; char *rl_tls_cakey; |