mirror of
https://github.com/haproxy/haproxy.git
synced 2026-04-21 06:06:59 -04:00
MINOR: ssl: compute ca-list from deduplicate ca-file
ca-list can be extracted from ca-file already loaded in memory. This patch set ca-list from deduplicated ca-file when needed and share it in ca-file tree. As a corollary, this will prevent file access for ca-list when updating a certificate via CLI.
This commit is contained in:
parent
d4f9a60ee2
commit
129d3285a5
1 changed files with 83 additions and 1 deletions
|
|
@ -368,6 +368,7 @@ static struct {
|
|||
*/
|
||||
struct cafile_entry {
|
||||
X509_STORE *ca_store;
|
||||
STACK_OF(X509_NAME) *ca_list;
|
||||
struct ebmb_node node;
|
||||
char path[0];
|
||||
};
|
||||
|
|
@ -443,6 +444,87 @@ static int ssl_set_verify_locations_file(SSL_CTX *ctx, char *path)
|
|||
return ssl_set_cert_crl_file(store_ctx, path);
|
||||
}
|
||||
|
||||
/*
|
||||
Extract CA_list from CA_file already in tree.
|
||||
Duplicate ca_name is tracking with ebtree. It's simplify openssl compatibility.
|
||||
Return a shared ca_list: SSL_dup_CA_list must be used before set it on SSL_CTX.
|
||||
*/
|
||||
static STACK_OF(X509_NAME)* ssl_get_client_ca_file(char *path)
|
||||
{
|
||||
struct ebmb_node *eb;
|
||||
struct cafile_entry *ca_e;
|
||||
|
||||
eb = ebst_lookup(&cafile_tree, path);
|
||||
if (!eb)
|
||||
return NULL;
|
||||
ca_e = ebmb_entry(eb, struct cafile_entry, node);
|
||||
|
||||
if (ca_e->ca_list == NULL) {
|
||||
int i;
|
||||
unsigned long key;
|
||||
struct eb_root ca_name_tree = EB_ROOT;
|
||||
struct eb64_node *node, *back;
|
||||
struct {
|
||||
struct eb64_node node;
|
||||
X509_NAME *xname;
|
||||
} *ca_name;
|
||||
STACK_OF(X509_OBJECT) *objs;
|
||||
STACK_OF(X509_NAME) *skn;
|
||||
X509 *x;
|
||||
X509_NAME *xn;
|
||||
|
||||
skn = sk_X509_NAME_new_null();
|
||||
/* take x509 from cafile_tree */
|
||||
objs = X509_STORE_get0_objects(ca_e->ca_store);
|
||||
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
|
||||
x = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
|
||||
if (!x)
|
||||
continue;
|
||||
xn = X509_get_subject_name(x);
|
||||
if (!xn)
|
||||
continue;
|
||||
/* Check for duplicates. */
|
||||
key = X509_NAME_hash(xn);
|
||||
for (node = eb64_lookup(&ca_name_tree, key), ca_name = NULL;
|
||||
node && ca_name == NULL;
|
||||
node = eb64_next(node)) {
|
||||
ca_name = container_of(node, typeof(*ca_name), node);
|
||||
if (X509_NAME_cmp(xn, ca_name->xname) != 0)
|
||||
ca_name = NULL;
|
||||
}
|
||||
/* find a duplicate */
|
||||
if (ca_name)
|
||||
continue;
|
||||
ca_name = calloc(1, sizeof *ca_name);
|
||||
xn = X509_NAME_dup(xn);
|
||||
if (!ca_name ||
|
||||
!xn ||
|
||||
!sk_X509_NAME_push(skn, xn)) {
|
||||
free(ca_name);
|
||||
X509_NAME_free(xn);
|
||||
sk_X509_NAME_pop_free(skn, X509_NAME_free);
|
||||
sk_X509_NAME_free(skn);
|
||||
skn = NULL;
|
||||
break;
|
||||
}
|
||||
ca_name->node.key = key;
|
||||
ca_name->xname = xn;
|
||||
eb64_insert(&ca_name_tree, &ca_name->node);
|
||||
}
|
||||
ca_e->ca_list = skn;
|
||||
/* remove temporary ca_name tree */
|
||||
node = eb64_first(&ca_name_tree);
|
||||
while (node) {
|
||||
ca_name = container_of(node, typeof(*ca_name), node);
|
||||
back = eb64_next(node);
|
||||
eb64_delete(node);
|
||||
free(ca_name);
|
||||
node = back;
|
||||
}
|
||||
}
|
||||
return ca_e->ca_list;
|
||||
}
|
||||
|
||||
/* This memory pool is used for capturing clienthello parameters. */
|
||||
struct ssl_capture {
|
||||
unsigned long long int xxh64;
|
||||
|
|
@ -4960,7 +5042,7 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_
|
|||
}
|
||||
if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
|
||||
/* set CA names for client cert request, function returns void */
|
||||
SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
|
||||
SSL_CTX_set_client_CA_list(ctx, SSL_dup_CA_list(ssl_get_client_ca_file(ca_file)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
Loading…
Reference in a new issue