From 864089e0a603c733c88256ba14051e974bcff456 Mon Sep 17 00:00:00 2001 From: Remi Tricot-Le Breton Date: Fri, 1 Oct 2021 15:36:56 +0200 Subject: [PATCH] MINOR: jwt: Insert public certificates into dedicated JWT tree A JWT signed with the RSXXX or ESXXX algorithm (RSA or ECDSA) requires a public certificate to be verified and to ensure it is valid. Those certificates must not be read on disk at runtime so we need a caching mechanism into which those certificates will be loaded during init. This is done through a dedicated ebtree that is filled during configuration parsing. The path to the public certificates will need to be explicitely mentioned in the configuration so that certificates can be loaded as early as possible. This tree is different from the ckch one because ckch entries are much bigger than the public certificates used in JWT validation process. --- include/haproxy/jwt-t.h | 6 ++++++ include/haproxy/jwt.h | 1 + src/jwt.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/include/haproxy/jwt-t.h b/include/haproxy/jwt-t.h index 6ac68b1..4189e65 100644 --- a/include/haproxy/jwt-t.h +++ b/include/haproxy/jwt-t.h @@ -61,6 +61,12 @@ enum jwt_elt { JWT_ELT_SIG, JWT_ELT_MAX }; + +struct jwt_cert_tree_entry { + EVP_PKEY *pkey; + struct ebmb_node node; + char path[VAR_ARRAY]; +}; #endif /* USE_OPENSSL */ diff --git a/include/haproxy/jwt.h b/include/haproxy/jwt.h index b24cc28..6ae6e63 100644 --- a/include/haproxy/jwt.h +++ b/include/haproxy/jwt.h @@ -28,6 +28,7 @@ #ifdef USE_OPENSSL enum jwt_alg jwt_parse_alg(const char *alg_str, unsigned int alg_len); int jwt_tokenize(const struct buffer *jwt, struct jwt_item *items, unsigned int *item_num); +int jwt_tree_load_cert(char *path, int pathlen, char **err); #endif /* USE_OPENSSL */ #endif /* _HAPROXY_JWT_H */ diff --git a/src/jwt.c b/src/jwt.c index 9f39a89..2103083 100644 --- a/src/jwt.c +++ b/src/jwt.c @@ -21,6 +21,9 @@ #ifdef USE_OPENSSL +/* Tree into which the public certificates used to validate JWTs will be stored. */ +static struct eb_root jwt_cert_tree = EB_ROOT_UNIQUE; + /* * The possible algorithm strings that can be found in a JWS's JOSE header are * defined in section 3.1 of RFC7518. @@ -120,4 +123,47 @@ int jwt_tokenize(const struct buffer *jwt, struct jwt_item *items, unsigned int return (ptr != jwt_end); } +/* + * Parse a public certificate and insert it into the jwt_cert_tree. + * Returns 0 in case of success. + */ +int jwt_tree_load_cert(char *path, int pathlen, char **err) +{ + int retval = -1; + struct jwt_cert_tree_entry *entry = NULL; + EVP_PKEY *pkey = NULL; + BIO *bio = NULL; + + bio = BIO_new(BIO_s_file()); + if (!bio) { + memprintf(err, "%sunable to allocate memory (BIO).\n", err && *err ? *err : ""); + goto end; + } + + if (BIO_read_filename(bio, path) == 1) { + + pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); + + if (!pkey) { + memprintf(err, "%sfile not found (%s)\n", err && *err ? *err : "", path); + goto end; + } + + entry = calloc(1, sizeof(*entry) + pathlen + 1); + if (!entry) { + memprintf(err, "%sunable to allocate memory (jwt_cert_tree_entry).\n", err && *err ? *err : ""); + goto end; + } + + memcpy(entry->path, path, pathlen + 1); + entry->pkey = pkey; + + ebst_insert(&jwt_cert_tree, &entry->node); + retval = 0; + } + +end: + BIO_free(bio); + return retval; +} #endif /* USE_OPENSSL */ -- 1.7.10.4