add `require client ca' for proxy blocks

refactor the code that calls validate_against_ca into an helper
function to reuse it in both apply_require_ca and (optionally) in
apply_reverse_proxy.
This commit is contained in:
Omar Polo 2022-01-04 23:14:34 +00:00
parent 280fd79b8f
commit ba94a608a8
3 changed files with 32 additions and 15 deletions

1
gmid.h
View File

@ -112,6 +112,7 @@ struct proxy {
size_t certlen;
uint8_t *key;
size_t keylen;
X509_STORE *reqca;
TAILQ_ENTRY(proxy) proxies;
};

View File

@ -351,6 +351,13 @@ proxy_opt : CERT string {
free(proxy->host);
parsehp($2, &proxy->host, &proxy->port, "1965");
}
| REQUIRE CLIENT CA string {
only_once(proxy->reqca, "require client ca");
ensure_absolute_path($4);
if ((proxy->reqca = load_ca($4)) == NULL)
yyerror("couldn't load ca cert: %s", $4);
free($4);
}
| USE_TLS bool {
proxy->notls = !$2;
}

View File

@ -630,6 +630,26 @@ matched_proxy(struct client *c)
return NULL;
}
static int
check_matching_certificate(X509_STORE *store, struct client *c)
{
const uint8_t *cert;
size_t len;
if (!tls_peer_cert_provided(c->ctx)) {
start_reply(c, CLIENT_CERT_REQ, "client certificate required");
return 1;
}
cert = tls_peer_cert_chain_pem(c->ctx, &len);
if (!validate_against_ca(store, cert, len)) {
start_reply(c, CERT_NOT_AUTH, "certificate not authorised");
return 1;
}
return 0;
}
/* 1 if matching a proxy relay-to (and apply it), 0 otherwise */
static int
apply_reverse_proxy(struct client *c)
@ -642,6 +662,9 @@ apply_reverse_proxy(struct client *c)
c->proxy = p;
if (p->reqca != NULL && check_matching_certificate(p->reqca, c))
return 1;
log_debug(c, "opening proxy connection for %s:%s",
p->host, p->port);
@ -680,24 +703,10 @@ static int
apply_require_ca(struct client *c)
{
X509_STORE *store;
const uint8_t *cert;
size_t len;
if ((store = vhost_require_ca(c->host, c->iri.path)) == NULL)
return 0;
if (!tls_peer_cert_provided(c->ctx)) {
start_reply(c, CLIENT_CERT_REQ, "client certificate required");
return 1;
}
cert = tls_peer_cert_chain_pem(c->ctx, &len);
if (!validate_against_ca(store, cert, len)) {
start_reply(c, CERT_NOT_AUTH, "certificate not authorised");
return 1;
}
return 0;
return check_matching_certificate(store, c);
}
static size_t