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.
This commit is contained in:
Remi Tricot-Le Breton 2021-10-01 15:36:56 +02:00 committed by William Lallemand
parent e0d3c00086
commit 864089e0a6
3 changed files with 53 additions and 0 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */