aboutsummaryrefslogtreecommitdiff
path: root/server.c
diff options
context:
space:
mode:
authorOmar Polo <op@omarpolo.com>2021-02-09 22:30:04 +0000
committerOmar Polo <op@omarpolo.com>2021-02-09 22:30:04 +0000
commit02be96c6ddfc34e448cccd095b4f3d0efe4de8a3 (patch)
treebce70baf27334eaf46abfbb1101979db6fa9ba66 /server.c
parent2ff026b09b810efd8c52e13f0a4988c588c8ee09 (diff)
add `require client ca' rule to require certs signed by a CA
Diffstat (limited to 'server.c')
-rw-r--r--server.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/server.c b/server.c
index 6626648..1dc0d91 100644
--- a/server.c
+++ b/server.c
@@ -54,6 +54,7 @@ static void handle_handshake(int, short, void*);
static char *strip_path(char*, int);
static void fmt_sbuf(const char*, struct client*, const char*);
static int apply_block_return(struct client*);
+static int apply_require_ca(struct client*);
static void handle_open_conn(int, short, void*);
static void start_reply(struct client*, int, const char*);
static void handle_start_reply(int, short, void*);
@@ -202,6 +203,24 @@ vhost_strip(struct vhost *v, const char *path)
return v->locations[0].strip;
}
+X509_STORE *
+vhost_require_ca(struct vhost *v, const char *path)
+{
+ struct location *loc;
+
+ if (v == NULL || path == NULL)
+ return NULL;
+
+ for (loc = &v->locations[1]; loc->match != NULL; ++loc) {
+ if (loc->reqca != NULL) {
+ if (!fnmatch(loc->match, path, 0))
+ return loc->reqca;
+ }
+ }
+
+ return v->locations[0].reqca;
+}
+
static int
check_path(struct client *c, const char *path, int *fd)
{
@@ -483,6 +502,31 @@ apply_block_return(struct client *c)
return 1;
}
+/* 1 if matching `require client ca' fails (and apply it), 0 otherwise */
+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;
+}
+
static void
handle_open_conn(int fd, short ev, void *d)
{
@@ -523,6 +567,9 @@ handle_open_conn(int fd, short ev, void *d)
return;
}
+ if (apply_require_ca(c))
+ return;
+
if (apply_block_return(c))
return;