From: Remi Tricot-Le Breton Date: Fri, 1 Oct 2021 13:36:56 +0000 (+0200) Subject: MINOR: jwt: Insert public certificates into dedicated JWT tree X-Git-Tag: v2.5-dev10~49 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=864089e0a603c733c88256ba14051e974bcff456;p=thirdparty%2Fhaproxy.git 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. --- diff --git a/include/haproxy/jwt-t.h b/include/haproxy/jwt-t.h index 6ac68b166e..4189e65065 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 b24cc28cf7..6ae6e63802 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 9f39a89fe8..2103083649 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 */