Download raw body.
[PATCH] relayd client certificate validation again
Hi!
I'm willing to revisit the patch too, if there is some interest getting
it commited now.
Rivo
On 9/30/24 20:55, Markus Läll wrote:
> Hi!
>
> When we (me and Rivo) got the patch ready and submitted it, there
> simply didn't get any replies from the maintainers. IIRC, I did try to
> direct attention to it more than once but with no success. (I also
> understand that people do this for free, so assumed they were busy
> with other things.)
>
> I still think the feature is useful, and also that adapting the patch
> to the latest version of relayd wouldn't be that difficult.
>
>
>
> On Mon, Sep 30, 2024 at 7:57 PM Sören Tempel
> <soeren@soeren-tempel.net> wrote:
>
> Hello!
>
> Is there a reason why this patch never got a review? The feature (TLS
> client certificate validation within relayd) seems to be requested
> frequently [1]. I just came across this while looking into working on
> such a patch myself.
>
> Is the feature not deemed useful, or is the patch not in a good shape?
> If the latter is the case, I would be willing to revise the patch.
>
> I would also be fine with just implementing the validation part
> without
> adding the capability to forward the validated certificate, which
> should
> shrink the patchset a bit.
>
> Cheers
> Sören
>
> [1]: https://marc.info/?t=154295268000001&r=1&w=2
> <https://marc.info/?t=154295268000001&r=1&w=2>
>
> Markus Läll <markus.l2ll@gmail.com> wrote:
> > Hi, we've got the patch ready for client certificate validation,
> cc'ing
> > related people.
> >
> > The patch adds two features:
> > 1. client certificate validation itself
> > 2. passing on certificate and select fields in HTTP headers
> >
> >
> > ## Brief description of client certificates (for whoever else is
> reading)
> >
> > Client certificates, also known as mutual authentication, are
> the reverse
> > to TLS server certificates (like letsencrypt) where the server
> > authenticates the user instead of the other way around.
> >
> > In principle client certificates work as follows:
> > - the server has keypair and a CA certificate created from this
> keypair
> > - the user has a keypair and submits their public key for
> certification (to
> > being signed by the CA)
> > - the server (relayd) has the CA certificate configured as
> 'client ca
> > "/path/to/ca.pem"'
> > - the user provides their certificate when connecting, the provided
> > certificate is validated against the CA certificate.
> >
> > How this is set up in practice is up to whoever implements the
> > infrastructure. Client certificates can be installed to
> operating systems'
> > certificate stores (Windows, macOS) where browsers can use them,
> or into
> > browsers own certificate stores (Firefox has its own), or
> specified on the
> > command line (curl, wget) etc.
> >
> >
> > ## Configuration
> >
> > To turn on client certificate validation add
> >
> > tls { client ca "/path/to/ca-cert.pem" }
> >
> > to relayd.conf.
> >
> > Add "optional" flag to make the certificate not required:
> >
> > tls { client ca "/path/to/cert.pem" optional }
> >
> > With "optional" relayd will succeed in the TLS handshake when no
> client
> > certificate is provided. But if a certificate *is* provided then
> it *must*
> > validate with the configured CA, otherwise the TLS handshake fails.
> >
> >
> > ## Pass certificate on in HTTP header
> >
> > To pass on the certificate in an url-encoded PEM:
> >
> > match header set "ANY_HEADER_NAME" value "$CLIENT_CERT_CHAIN"
> >
> > With this configuration the downstream can inspect the
> known-to-be-valid
> > certificate further (e.g extract identity or other info from x509
> > extensions).
> >
> > There was discussion privately on is there any standard for putting
> > certificates in HTTP headers, repeating the reply here as well:
> >
> > There appears to be no standard, but this is how other HTTP
> servers do it:
> > - nginx urlencodes the PEM file with $ssl_client_escaped_cert[1]
> (this is
> > what is done in this patch too). There is also the $ssl_client_cert
> > variable which adds a tab to each next new line, but this way of
> doing
> > multiline HTTP headers is deprecated[2]. There is also
> > $ssl_client_raw_cert, but the raw multiline PEM is invalid HTTP
> header;
> > - envoy also urlencodes the PEM[3];
> > - haproxy has only the binary DER, but base64 encoding it like
> > %[ssl_c_der,base64]) should result in PEM with no newlines and
> no headers;
> > - apache has the %{SSL_CLIENT_CERT} with raw (multiline) PEM[4],
> which is
> > invalid in HTTP headers, but this can be processed with the escape
> > function[5], something like "expr=3D %{escape:SSL_CLIENT_CERT}"
> >
> > [1]
> >
> https://nginx.org/en/docs/http/ngx_http_ssl_module.html#var_ssl_client_esca=
> > ped_cert
> > [2] https://tools.ietf.org/html/rfc7230#section-3.2.4
> > [3]
> >
> https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_ma=
> > n/headers#x-forwarded-client-cert
> > [4] https://httpd.apache.org/docs/current/mod/mod_ssl.html#envvars
> > [5] https://httpd.apache.org/docs/current/expr.html#functions
> >
> > In addition to extracting the entire certificate, subject and
> issuer can be
> > put to HTTP headers too for convenience:
> >
> > match header set "CS_SUBJECT" value "$CLIENT_CERT_SUBJECT"
> > match header set "CS_ISSUER" value "$CLIENT_CERT_ISSUER"
> >
> >
> >
> > --=20
> > Markus L=C3=A4ll
> >
> > On Thu, Dec 16, 2021 at 11:23 PM rivo nurges <rivo@elnit.ee> wrote:
> >
> > > Hi!
> > >
> > > Here comes the support for relayd client certificate validation.
> > > Full certificate chain, subject and issuer can be passed over
> in http
> > > headers.
> > > It supports mandatory validation and optional validation(if
> client chooses
> > > to
> > > provide certificate it will be validated).
> > >
> > > Part of my sample config.
> > >
> > > http protocol test {
> > > match header set "CS_SUBJECT" value "$CLIENT_CERT_SUBJECT"
> > > match header set "CS_ISSUER" value "$CLIENT_CERT_ISSUER"
> > > match header set "CS_CERT" value "$CLIENT_CERT_CHAIN"
> > > pass
> > > tls {client ca "/tmp/easyrsa3/pki/ca.crt" optional }
> > > }
> > >
> > > This uses code from the patches submitted by Ashe Connor.
> > >
> > > Rivo
> > >
> > > diff refs/heads/master refs/heads/relay-clc3
> > > blob - a2f1c130d6b45e3082048218c11537dca485998a
> > > blob + 5070a7d48f58403f53d818231e1676db749aa9d7
> > > --- usr.sbin/relayd/config.c
> > > +++ usr.sbin/relayd/config.c
> > > @@ -954,6 +954,15 @@ config_setrelay(struct relayd *env,
> struct relay *rl=
> > ay
> > > rlay->rl_conf.name <http://rl_conf.name>);
> > > return (-1);
> > > }
> > > + if (rlay->rl_tls_client_ca_fd
> !=3D -1 &&
> > > + config_setrelayfd(ps, id, n, 0,
> > > + rlay->rl_conf.id
> <http://rl_conf.id>,
> > > RELAY_FD_CLIENTCACERT,
> > > + rlay->rl_tls_client_ca_fd) =3D=3D -1)=
> > {
> > > + log_warn("%s: fd passing failed
> > > for "
> > > + "`%s'", __func__,
> > > + rlay->rl_conf.name <http://rl_conf.name>);
> > > + return (-1);
> > > + }
> > > /* Prevent fd exhaustion in
> the parent. */
> > > if (proc_flush_imsg(ps, id, n)
> =3D=3D -1)=
> > {
> > > log_warn("%s: failed to flush "
> > > @@ -987,6 +996,10 @@ config_setrelay(struct relayd *env,
> struct relay *rl=
> > ay
> > > close(rlay->rl_s);
> > > rlay->rl_s =3D -1;
> > > }
> > > + if (rlay->rl_tls_client_ca_fd !=3D -1) {
> > > + close(rlay->rl_tls_client_ca_fd);
> > > + rlay->rl_tls_client_ca_fd =3D -1;
> > > + }
> > > if (rlay->rl_tls_cacert_fd !=3D -1) {
> > > close(rlay->rl_tls_cacert_fd);
> > > rlay->rl_tls_cacert_fd =3D -1;
> > > @@ -1012,6 +1025,10 @@ config_setrelay(struct relayd *env,
> struct relay
> > > *rlay
> > > cert->cert_ocsp_fd =3D -1;
> > > }
> > > }
> > > + if (rlay->rl_tls_client_ca_fd !=3D -1) {
> > > + close(rlay->rl_tls_client_ca_fd);
> > > + rlay->rl_tls_client_ca_fd =3D -1;
> > > + }
> > >
> > > return (0);
> > > }
> > > @@ -1034,6 +1051,7 @@ config_getrelay(struct relayd *env,
> struct imsg
> > > *imsg)
> > > rlay->rl_s =3D imsg->fd;
> > > rlay->rl_tls_ca_fd =3D -1;
> > > rlay->rl_tls_cacert_fd =3D -1;
> > > + rlay->rl_tls_client_ca_fd =3D -1;
> > >
> > > if (ps->ps_what[privsep_process] & CONFIG_PROTOS) {
> > > if (rlay->rl_conf.proto =3D=3D EMPTY_ID)
> > > @@ -1163,6 +1181,9 @@ config_getrelayfd(struct relayd *env,
> struct imsg
> > > *ims
> > > case RELAY_FD_CAFILE:
> > > rlay->rl_tls_cacert_fd =3D imsg->fd;
> > > break;
> > > + case RELAY_FD_CLIENTCACERT:
> > > + rlay->rl_tls_client_ca_fd =3D imsg->fd;
> > > + break;
> > > }
> > >
> > > DPRINTF("%s: %s %d received relay fd %d type %d for
> relay %s",
> > > __func__,
> > > blob - 22beb857229a16e5b2c17a25a2944231d41e7e08
> > > blob + fe5e8ff4dfed10e8f09e3226bdfe33f8bc031c8e
> > > --- usr.sbin/relayd/parse.y
> > > +++ usr.sbin/relayd/parse.y
> > > @@ -172,14 +172,14 @@ typedef struct {
> > > %token CODE COOKIE DEMOTE DIGEST DISABLE ERROR EXPECT
> PASS BLOCK
> > > EXTERNAL
> > > %token FILENAME FORWARD FROM HASH HEADER HEADERLEN
> HOST HTTP ICMP
> > > INCLUDE INET
> > > %token INET6 INTERFACE INTERVAL IP KEYPAIR LABEL
> LISTEN VALUE
> > > LOADBALANCE LOG
> > > -%token LOOKUP METHOD MODE NAT NO DESTINATION NODELAY NOTHING
> ON PARENT
> > > PATH
> > > +%token LOOKUP METHOD MODE NAT NO DESTINATION NODELAY NOTHING
> ON OPTIONAL
> > > PARENT PATH
> > > %token PFTAG PORT PREFORK PRIORITY PROTO QUERYSTR
> REAL REDIRECT
> > > RELAY REMOVE
> > > %token REQUEST RESPONSE RETRY QUICK RETURN ROUNDROBIN
> ROUTE SACK
> > > SCRIPT SEND
> > > %token SESSION SOCKET SPLICE SSL STICKYADDR STRIP
> STYLE TABLE TAG
> > > TAGGED TCP
> > > %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
> > > +%token WEBSOCKETS CLIENT
> > > %token <v.string> STRING
> > > %token <v.number> NUMBER
> > > %type <v.string> context hostname interface table value
> path
> > > @@ -188,6 +188,7 @@ typedef struct {
> > > %type <v.number> opttls opttlsclient
> > > %type <v.number> redirect_proto relay_proto match
> > > %type <v.number> action ruleaf key_option
> > > +%type <v.number> clientcaopt
> > > %type <v.port> port
> > > %type <v.host> host
> > > %type <v.addr> address rulesrc ruledst addrprefix
> > > @@ -244,6 +245,10 @@ opttlsclient : /*empty*/ { $$
> =3D 0; }
> > > | WITH ssltls { $$ =3D 1; }
> > > ;
> > >
> > > +clientcaopt : /*empty*/ { $$ =3D 0; }
> > > + | OPTIONAL { $$ =3D 1; }
> > > + ;
> > > +
> > > http_type : HTTP { $$ =3D 0; }
> > > | STRING {
> > > if (strcmp("https", $1) =3D=3D 0) {
> > > @@ -1353,6 +1358,19 @@ tlsflags : SESSION TICKETS {
> proto->tickets =3D 1;=
> > }
> > > name->name =3D $2;
> > > TAILQ_INSERT_TAIL(&proto->tlscerts, name, entry);
> > > }
> > > + | CLIENT CA STRING clientcaopt {
> > > + if (strlcpy(proto->tlsclientca, $3,
> > > + sizeof(proto->tlsclientca)) >=3D
> > > + sizeof(proto->tlsclientca)) {
> > > + yyerror("tlsclientca truncated");
> > > + free($3);
> > > + YYERROR;
> > > + }
> > > + if ($4) {
> > > + proto->tlsflags |=3D
> > > TLSFLAG_CLIENT_OPTIONAL;
> > > + }
> > > + free($3);
> > > + }
> > > | NO flag {
> proto->tlsflags &=3D
> > > ~($2); }
> > > | flag {
> proto->tlsflags |=3D $1=
> > ; }
> > > ;
> > > @@ -1824,6 +1842,7 @@ relay : RELAY STRING {
> > > r->rl_conf.dstretry =3D 0;
> > > r->rl_tls_ca_fd =3D -1;
> > > r->rl_tls_cacert_fd =3D -1;
> > > + r->rl_tls_client_ca_fd =3D -1;
> > > TAILQ_INIT(&r->rl_tables);
> > > if (last_relay_id =3D=3D INT_MAX) {
> > > yyerror("too many relays
> defined");
> > > @@ -2413,6 +2432,7 @@ lookup(char *s)
> > > { "check", CHECK },
> > > { "checks", CHECKS },
> > > { "ciphers", CIPHERS },
> > > + { "client", CLIENT },
> > > { "code", CODE },
> > > { "connection", CONNECTION },
> > > { "context", CONTEXT },
> > > @@ -2458,6 +2478,7 @@ lookup(char *s)
> > > { "nodelay", NODELAY },
> > > { "nothing", NOTHING },
> > > { "on", ON },
> > > + { "optional", OPTIONAL },
> > > { "params", PARAMS },
> > > { "parent", PARENT },
> > > { "pass", PASS },
> > > @@ -3399,6 +3420,7 @@ relay_inherit(struct relay *ra, struct
> relay *rb)
> > > if (!(rb->rl_conf.flags & F_TLS)) {
> > > rb->rl_tls_cacert_fd =3D -1;
> > > rb->rl_tls_ca_fd =3D -1;
> > > + rb->rl_tls_client_ca_fd =3D -1;
> > > }
> > > TAILQ_INIT(&rb->rl_tables);
> > >
> > > blob - da4a1aa0cc1158b22506c6d81e4d36b8810c025c
> > > blob + 2d16b9d91e594a06d4b1b2bfc791c7f0c861fc57
> > > --- usr.sbin/relayd/relay.c
> > > +++ usr.sbin/relayd/relay.c
> > > @@ -2255,6 +2255,30 @@ relay_tls_ctx_create(struct relay *rlay)
> > > }
> > > rlay->rl_tls_cacert_fd =3D -1;
> > >
> > > + if (rlay->rl_tls_client_ca_fd !=3D -1) {
> > > + if ((buf =3D
> relay_load_fd(rlay->rl_tls_client_ca=
> > _fd,
> > > + &len)) =3D=3D
> > > + NULL) {
> > > + log_warn(
> > > + "failed to read tls client CA
> > > certificate");
> > > + goto err;
> > > + }
> > > +
> > > + if (tls_config_set_ca_mem(tls_cfg,
> buf, len) !=3D=
> > 0)
> > > {
> > > + log_warnx(
> > > + "failed to set tls client
> CA cert: %s=
> > ",
> > > + tls_config_error(tls_cfg));
> > > + goto err;
> > > + }
> > > + purge_key(&buf, len);
> > > +
> > > + if (rlay->rl_proto->tlsflags &
> > > TLSFLAG_CLIENT_OPTIONAL)
> > > + tls_config_verify_client_optional(tls_cfg=
> > );
> > > + else
> > > + tls_config_verify_client(tls_cfg);
> > > + }
> > > + rlay->rl_tls_client_ca_fd =3D -1;
> > > +
> > > tls =3D tls_server();
> > > if (tls =3D=3D NULL) {
> > > log_warnx("unable to allocate TLS
> context");
> > > blob - d493c238813cfc692d83f65a88d4556b2fa35b0f
> > > blob + 58ba35c16ea8d80b36796d977ad7920d3bed3a9c
> > > --- usr.sbin/relayd/relay_http.c
> > > +++ usr.sbin/relayd/relay_http.c
> > > @@ -78,6 +78,7 @@ int relay_match_actions(struct
> > > ctl_relay_event *,
> > > struct relay_table **);
> > > void relay_httpdesc_free(struct http_descriptor *);
> > > char * server_root_strip(char *, int);
> > > +char *url_encode(const char *);
> > >
> > > static struct relayd *env =3D NULL;
> > >
> > > @@ -1279,7 +1280,32 @@ relay_expand_http(struct
> ctl_relay_event *cre, char
> > > *v
> > > if (expand_string(buf, len, "$TIMEOUT", ibuf)
> !=3D 0)
> > > return (NULL);
> > > }
> > > -
> > > + if (strstr(val, "$CLIENT_CERT_") !=3D NULL &&
> > > tls_peer_cert_provided(cre->tls)) {
> > > + if (strstr(val, "$CLIENT_CERT_SUBJECT") !=3D
> NULL) {
> > > + if (expand_string(buf, len,
> > > + "$CLIENT_CERT_SUBJECT",
> > > tls_peer_cert_subject(cre->tls)) !=3D 0)
> > > + return (NULL);
> > > + }
> > > + if (strstr(val, "$CLIENT_CERT_ISSUER") !=3D
> NULL) {
> > > + if (expand_string(buf, len,
> > > + "$CLIENT_CERT_ISSUER",
> > > tls_peer_cert_issuer(cre->tls)) !=3D 0)
> > > + return (NULL);
> > > + }
> > > + if (strstr(val, "$CLIENT_CERT_CHAIN") !=3D NULL) {
> > > + const char *pem;
> > > + char *cbuf;
> > > + size_t plen;
> > > + pem =3D
> tls_peer_cert_chain_pem(cre->tls, &plen);
> > > + cbuf =3D malloc(plen);
> > > + sprintf(cbuf, "%.*s", (int)plen - 1, pem);
> > > + if (expand_string(buf, len,
> > > + "$CLIENT_CERT_CHAIN",
> url_encode(cbuf)) !=3D =
> > 0) {
> > > + free(cbuf);
> > > + return (NULL);
> > > + } else
> > > + free(cbuf);
> > > + }
> > > + }
> > > return (buf);
> > > }
> > >
> > > @@ -2045,3 +2071,27 @@ server_root_strip(char *path, int n)
> > > return (path);
> > > }
> > >
> > > +char *
> > > +url_encode(const char *src)
> > > +{
> > > + static char hex[] =3D "0123456789ABCDEF";
> > > + char *dp, *dst;
> > > + unsigned char c;
> > > +
> > > + /* We need 3 times the memory if every letter is
> encoded. */
> > > + if ((dst =3D calloc(3, strlen(src) + 1)) =3D=3D NULL)
> > > + return (NULL);
> > > +
> > > + for (dp =3D dst; *src !=3D 0; src++) {
> > > + c =3D (unsigned char) *src;
> > > + if (c =3D=3D ' ' || c =3D=3D '#' || c =3D=3D
> '%' || c =3D=
> > =3D '?' || c =3D=3D
> > > '"' ||
> > > + c =3D=3D '&' || c =3D=3D '<' || c <=3D
> 0x1f || c >=3D=
> > 0x7f) {
> > > + *dp++ =3D '%';
> > > + *dp++ =3D '%';
> > > + *dp++ =3D hex[c >> 4];
> > > + *dp++ =3D hex[c & 0x0f];
> > > + } else
> > > + *dp++ =3D *src;
> > > + }
> > > + return (dst);
> > > +}
> > > blob - 54e26e646fae5804e66d2d3cfeba68e06914ab2b
> > > blob + cd99c21d7cdaf9fc5fdc33e5a0ad886afaa9b889
> > > --- usr.sbin/relayd/relayd.c
> > > +++ usr.sbin/relayd/relayd.c
> > > @@ -1360,6 +1360,15 @@ relay_load_certfiles(struct relayd
> *env, struct
> > > relay
> > > if ((rlay->rl_conf.flags & F_TLS) =3D=3D 0)
> > > return (0);
> > >
> > > + if (strlen(proto->tlsclientca) &&
> > > + rlay->rl_tls_client_ca_fd =3D=3D -1) {
> > > + if ((rlay->rl_tls_client_ca_fd =3D
> > > + open(proto->tlsclientca, O_RDONLY)) =3D=3D -1)
> > > + return (-1);
> > > + log_debug("%s: using client ca %s", __func__,
> > > + proto->tlsclientca);
> > > + }
> > > +
> > > if (name =3D=3D NULL &&
> > > print_host(&rlay->rl_conf.ss, hbuf, sizeof(hbuf))
> =3D=3D NULL)
> > > goto fail;
> > > blob - cecbae71f87e603b3e30d4c0114bf1c60a82b52a
> > > blob + cfb7a314811730723449a5109d500014711db3ae
> > > --- usr.sbin/relayd/relayd.conf.5
> > > +++ usr.sbin/relayd/relayd.conf.5
> > > @@ -948,6 +948,13 @@ will be used (strong crypto cipher suites
> without an=
> > on
> > > See the CIPHERS section of
> > > .Xr openssl 1
> > > for information about SSL/TLS cipher suites and preference
> lists.
> > > +.It Ic client ca Ar path Op optional
> > > +Require TLS client certificates whose authenticity can be
> verified
> > > +against the CA certificate(s) in the specified file in order to
> > > +proceed beyond the TLS handshake.
> > > +If the
> > > +.Ic optional
> > > +keyword is present, the certificate is verified only if
> presented.
> > > .It Ic client-renegotiation
> > > Allow client-initiated renegotiation.
> > > To mitigate a potential DoS risk,
> > > @@ -1361,6 +1368,12 @@ The value string may contain predefined
> macros that
> > > wi
> > > at runtime:
> > > .Pp
> > > .Bl -tag -width $SERVER_ADDR -offset indent -compact
> > > +.It Ic $CLIENT_CERT_CHAIN
> > > +The certificate chain of the client certificate.
> > > +.It Ic $CLIENT_CERT_ISSUER
> > > +The issuer of the client certificate.
> > > +.It Ic $CLIENT_CERT_SUBJECT
> > > +The subject of the client certificate.
> > > .It Ic $HOST
> > > The Host header's value of the relay.
> > > .It Ic $REMOTE_ADDR
> > > blob - 2236d140f7e6b9477bac401cbcdd559db171680b
> > > blob + 2a1166599bfd57b0682c4d4bacd15d340ff9b5ad
> > > --- usr.sbin/relayd/relayd.h
> > > +++ usr.sbin/relayd/relayd.h
> > > @@ -139,11 +139,12 @@ struct ctl_relaytable {
> > > };
> > >
> > > enum fd_type {
> > > - RELAY_FD_CERT =3D 1,
> > > - RELAY_FD_CACERT =3D 2,
> > > - RELAY_FD_CAFILE =3D 3,
> > > - RELAY_FD_KEY =3D 4,
> > > - RELAY_FD_OCSP =3D 5
> > > + RELAY_FD_CERT =3D 1,
> > > + RELAY_FD_CACERT =3D 2,
> > > + RELAY_FD_CAFILE =3D 3,
> > > + RELAY_FD_KEY =3D 4,
> > > + RELAY_FD_OCSP =3D 5,
> > > + RELAY_FD_CLIENTCACERT =3D 6
> > > };
> > >
> > > struct ctl_relayfd {
> > > @@ -403,6 +404,7 @@ union hashkey {
> > > #define F_TLSINSPECT 0x04000000
> > > #define F_HASHKEY 0x08000000
> > > #define F_AGENTX_TRAPONLY 0x10000000
> > > +#define F_TLSVERIFY 0x20000000
> > >
> > > #define F_BITS
> > > \
> > > "\10\01DISABLE\02BACKUP\03USED\04DOWN\05ADD\06DEL\07CHANGED" \
> > > @@ -703,6 +705,7 @@ TAILQ_HEAD(relay_rules, relay_rule);
> > > #define TLSFLAG_VERSION 0x1f
> > > #define TLSFLAG_CIPHER_SERVER_PREF 0x20
> > > #define TLSFLAG_CLIENT_RENEG 0x40
> > > +#define TLSFLAG_CLIENT_OPTIONAL 0x80
> > > #define TLSFLAG_DEFAULT \
> > > (TLSFLAG_TLSV1_2|TLSFLAG_TLSV1_3|TLSFLAG_CIPHER_SERVER_PREF)
> > >
> > > @@ -746,6 +749,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;
> > > @@ -835,6 +839,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;
>
>
>
> --
> Markus Läll
[PATCH] relayd client certificate validation again