1
0
mirror of https://github.com/openbsd/src.git synced 2024-12-22 07:27:59 -08:00

relayd: add support for client certificates

This feature has been requested many times over the years. Various patches
were provided by Asherah Connor, Rivo Nurges, Markus Läll and maybe others.
These patches always stalled for various reasons.

From Sören Tempel, mostly based on Asherah's latest patch.

ok florian tb
This commit is contained in:
tb 2024-10-28 19:56:18 +00:00
parent 80a776f54c
commit 92388deed9
6 changed files with 82 additions and 15 deletions

View File

@ -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__,

View File

@ -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);

View File

@ -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");

View File

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

View File

@ -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,

View File

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