summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/relayd/config.c23
-rw-r--r--usr.sbin/relayd/parse.y17
-rw-r--r--usr.sbin/relayd/relay.c25
-rw-r--r--usr.sbin/relayd/relayd.c10
-rw-r--r--usr.sbin/relayd/relayd.conf.57
-rw-r--r--usr.sbin/relayd/relayd.h15
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;