Commit Diff
Diff:
280fd79b8f5d42097d2a1a315338559261cb1e74
ba94a608a89110740cb24ef098c476c84d371918
Commit:
ba94a608a89110740cb24ef098c476c84d371918
Tree:
79202a1a949a3187b6f35997a43772c77b4dda08
Author:
Omar Polo <op@omarpolo.com>
Date:
Tue Jan 4 23:14:34 2022 UTC
Message:
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.
commit - 280fd79b8f5d42097d2a1a315338559261cb1e74
commit + ba94a608a89110740cb24ef098c476c84d371918
blob - 92f6985ae691b1d31f5aeb3421516ef2e02af9d9
blob + 9e8415dc232bc054d956e379bc1b53808ba25c9d
--- gmid.h
+++ gmid.h
@@ -112,6 +112,7 @@ struct proxy {
size_t certlen;
uint8_t *key;
size_t keylen;
+ X509_STORE *reqca;
TAILQ_ENTRY(proxy) proxies;
};
blob - 43a7b15c80d3c94252642ca2f81c727b4f53f720
blob + 57cf3f5c72c7f07008879881d2a19bf18cb0cbb0
--- parse.y
+++ parse.y
@@ -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;
}
blob - 991e126f99721dd111e9225158cbba52b7557d6a
blob + 2faf79278168b55fb373c3e5b5cce7f9b8c0e898
--- server.c
+++ server.c
@@ -628,6 +628,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 */
@@ -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 @@ apply_require_ca(struct client *c)
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
Omar Polo