mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-05-06 17:58:01 +00:00
MINOR: ssl: Ckch instance rebuild and cleanup factorization in CLI handler
The process of rebuilding a ckch_instance when a certificate is updated through a cli command will be roughly the same when a ca-file is updated so this factorization will avoid code duplication.
This commit is contained in:
parent
38c999b11c
commit
bfadc02f34
185
src/ssl_ckch.c
185
src/ssl_ckch.c
@ -1536,6 +1536,112 @@ static void cli_release_commit_cert(struct appctx *appctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Rebuild a new instance 'new_inst' based on an old instance 'ckchi' and a
|
||||||
|
* specific ckch_store.
|
||||||
|
* Returns 0 in case of success, 1 otherwise.
|
||||||
|
*/
|
||||||
|
static int ckch_inst_rebuild(struct ckch_store *ckch_store, struct ckch_inst *ckchi,
|
||||||
|
struct ckch_inst **new_inst, char **err)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
int errcode = 0;
|
||||||
|
struct sni_ctx *sc0, *sc0s;
|
||||||
|
char **sni_filter = NULL;
|
||||||
|
int fcount = 0;
|
||||||
|
|
||||||
|
if (ckchi->crtlist_entry) {
|
||||||
|
sni_filter = ckchi->crtlist_entry->filters;
|
||||||
|
fcount = ckchi->crtlist_entry->fcount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ckchi->is_server_instance)
|
||||||
|
errcode |= ckch_inst_new_load_srv_store(ckch_store->path, ckch_store, new_inst, err);
|
||||||
|
else
|
||||||
|
errcode |= ckch_inst_new_load_store(ckch_store->path, ckch_store, ckchi->bind_conf, ckchi->ssl_conf, sni_filter, fcount, new_inst, err);
|
||||||
|
|
||||||
|
if (errcode & ERR_CODE)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* if the previous ckchi was used as the default */
|
||||||
|
if (ckchi->is_default)
|
||||||
|
(*new_inst)->is_default = 1;
|
||||||
|
|
||||||
|
(*new_inst)->is_server_instance = ckchi->is_server_instance;
|
||||||
|
(*new_inst)->server = ckchi->server;
|
||||||
|
/* Create a new SSL_CTX and link it to the new instance. */
|
||||||
|
if ((*new_inst)->is_server_instance) {
|
||||||
|
retval = ssl_sock_prep_srv_ctx_and_inst(ckchi->server, (*new_inst)->ctx, (*new_inst));
|
||||||
|
if (retval)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create the link to the crtlist_entry */
|
||||||
|
(*new_inst)->crtlist_entry = ckchi->crtlist_entry;
|
||||||
|
|
||||||
|
/* we need to initialize the SSL_CTX generated */
|
||||||
|
/* this iterate on the newly generated SNIs in the new instance to prepare their SSL_CTX */
|
||||||
|
list_for_each_entry_safe(sc0, sc0s, &(*new_inst)->sni_ctx, by_ckch_inst) {
|
||||||
|
if (!sc0->order) { /* we initialized only the first SSL_CTX because it's the same in the other sni_ctx's */
|
||||||
|
errcode |= ssl_sock_prep_ctx_and_inst(ckchi->bind_conf, ckchi->ssl_conf, sc0->ctx, *new_inst, err);
|
||||||
|
if (errcode & ERR_CODE)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load all the new SNIs of a newly built ckch instance in the trees, or replace
|
||||||
|
* a server's main ckch instance.
|
||||||
|
*/
|
||||||
|
static void __ssl_sock_load_new_ckch_instance(struct ckch_inst *ckchi)
|
||||||
|
{
|
||||||
|
/* The bind_conf will be null on server ckch_instances. */
|
||||||
|
if (ckchi->is_server_instance) {
|
||||||
|
int i;
|
||||||
|
/* a lock is needed here since we have to free the SSL cache */
|
||||||
|
HA_RWLOCK_WRLOCK(SSL_SERVER_LOCK, &ckchi->server->ssl_ctx.lock);
|
||||||
|
/* free the server current SSL_CTX */
|
||||||
|
SSL_CTX_free(ckchi->server->ssl_ctx.ctx);
|
||||||
|
/* Actual ssl context update */
|
||||||
|
SSL_CTX_up_ref(ckchi->ctx);
|
||||||
|
ckchi->server->ssl_ctx.ctx = ckchi->ctx;
|
||||||
|
ckchi->server->ssl_ctx.inst = ckchi;
|
||||||
|
|
||||||
|
/* flush the session cache of the server */
|
||||||
|
for (i = 0; i < global.nbthread; i++) {
|
||||||
|
ha_free(&ckchi->server->ssl_ctx.reused_sess[i].ptr);
|
||||||
|
}
|
||||||
|
HA_RWLOCK_WRUNLOCK(SSL_SERVER_LOCK, &ckchi->server->ssl_ctx.lock);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
|
||||||
|
ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
|
||||||
|
HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete a ckch instance that was replaced after a CLI command.
|
||||||
|
*/
|
||||||
|
static void __ckch_inst_free_locked(struct ckch_inst *ckchi)
|
||||||
|
{
|
||||||
|
if (ckchi->is_server_instance) {
|
||||||
|
/* no lock for servers */
|
||||||
|
ckch_inst_free(ckchi);
|
||||||
|
} else {
|
||||||
|
struct bind_conf __maybe_unused *bind_conf = ckchi->bind_conf;
|
||||||
|
|
||||||
|
HA_RWLOCK_WRLOCK(SNI_LOCK, &bind_conf->sni_lock);
|
||||||
|
ckch_inst_free(ckchi);
|
||||||
|
HA_RWLOCK_WRUNLOCK(SNI_LOCK, &bind_conf->sni_lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function tries to create the new ckch_inst and their SNIs
|
* This function tries to create the new ckch_inst and their SNIs
|
||||||
*/
|
*/
|
||||||
@ -1545,11 +1651,9 @@ static int cli_io_handler_commit_cert(struct appctx *appctx)
|
|||||||
int y = 0;
|
int y = 0;
|
||||||
char *err = NULL;
|
char *err = NULL;
|
||||||
int errcode = 0;
|
int errcode = 0;
|
||||||
int retval = 0;
|
|
||||||
struct ckch_store *old_ckchs, *new_ckchs = NULL;
|
struct ckch_store *old_ckchs, *new_ckchs = NULL;
|
||||||
struct ckch_inst *ckchi, *ckchis;
|
struct ckch_inst *ckchi, *ckchis;
|
||||||
struct buffer *trash = alloc_trash_chunk();
|
struct buffer *trash = alloc_trash_chunk();
|
||||||
struct sni_ctx *sc0, *sc0s;
|
|
||||||
struct crtlist_entry *entry;
|
struct crtlist_entry *entry;
|
||||||
|
|
||||||
if (trash == NULL)
|
if (trash == NULL)
|
||||||
@ -1593,8 +1697,6 @@ static int cli_io_handler_commit_cert(struct appctx *appctx)
|
|||||||
/* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
|
/* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
|
||||||
list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
|
list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
|
||||||
struct ckch_inst *new_inst;
|
struct ckch_inst *new_inst;
|
||||||
char **sni_filter = NULL;
|
|
||||||
int fcount = 0;
|
|
||||||
|
|
||||||
/* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
|
/* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
|
||||||
if (y >= 10) {
|
if (y >= 10) {
|
||||||
@ -1603,46 +1705,9 @@ static int cli_io_handler_commit_cert(struct appctx *appctx)
|
|||||||
goto yield;
|
goto yield;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ckchi->crtlist_entry) {
|
if (ckch_inst_rebuild(new_ckchs, ckchi, &new_inst, &err))
|
||||||
sni_filter = ckchi->crtlist_entry->filters;
|
|
||||||
fcount = ckchi->crtlist_entry->fcount;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ckchi->is_server_instance)
|
|
||||||
errcode |= ckch_inst_new_load_srv_store(new_ckchs->path, new_ckchs, &new_inst, &err);
|
|
||||||
else
|
|
||||||
errcode |= ckch_inst_new_load_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, sni_filter, fcount, &new_inst, &err);
|
|
||||||
|
|
||||||
if (errcode & ERR_CODE)
|
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* if the previous ckchi was used as the default */
|
|
||||||
if (ckchi->is_default)
|
|
||||||
new_inst->is_default = 1;
|
|
||||||
|
|
||||||
new_inst->is_server_instance = ckchi->is_server_instance;
|
|
||||||
new_inst->server = ckchi->server;
|
|
||||||
/* Create a new SSL_CTX and link it to the new instance. */
|
|
||||||
if (new_inst->is_server_instance) {
|
|
||||||
retval = ssl_sock_prep_srv_ctx_and_inst(ckchi->server, new_inst->ctx, new_inst);
|
|
||||||
if (retval)
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create the link to the crtlist_entry */
|
|
||||||
new_inst->crtlist_entry = ckchi->crtlist_entry;
|
|
||||||
|
|
||||||
/* we need to initialize the SSL_CTX generated */
|
|
||||||
/* this iterate on the newly generated SNIs in the new instance to prepare their SSL_CTX */
|
|
||||||
list_for_each_entry_safe(sc0, sc0s, &new_inst->sni_ctx, by_ckch_inst) {
|
|
||||||
if (!sc0->order) { /* we initialized only the first SSL_CTX because it's the same in the other sni_ctx's */
|
|
||||||
errcode |= ssl_sock_prep_ctx_and_inst(ckchi->bind_conf, ckchi->ssl_conf, sc0->ctx, sc0->ckch_inst, &err);
|
|
||||||
if (errcode & ERR_CODE)
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* display one dot per new instance */
|
/* display one dot per new instance */
|
||||||
chunk_appendf(trash, ".");
|
chunk_appendf(trash, ".");
|
||||||
/* link the new ckch_inst to the duplicate */
|
/* link the new ckch_inst to the duplicate */
|
||||||
@ -1677,44 +1742,12 @@ static int cli_io_handler_commit_cert(struct appctx *appctx)
|
|||||||
|
|
||||||
/* First, we insert every new SNIs in the trees, also replace the default_ctx */
|
/* First, we insert every new SNIs in the trees, also replace the default_ctx */
|
||||||
list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
|
list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
|
||||||
/* The bind_conf will be null on server ckch_instances. */
|
__ssl_sock_load_new_ckch_instance(ckchi);
|
||||||
if (ckchi->is_server_instance) {
|
|
||||||
int i;
|
|
||||||
/* a lock is needed here since we have to free the SSL cache */
|
|
||||||
HA_RWLOCK_WRLOCK(SSL_SERVER_LOCK, &ckchi->server->ssl_ctx.lock);
|
|
||||||
/* free the server current SSL_CTX */
|
|
||||||
SSL_CTX_free(ckchi->server->ssl_ctx.ctx);
|
|
||||||
/* Actual ssl context update */
|
|
||||||
SSL_CTX_up_ref(ckchi->ctx);
|
|
||||||
ckchi->server->ssl_ctx.ctx = ckchi->ctx;
|
|
||||||
ckchi->server->ssl_ctx.inst = ckchi;
|
|
||||||
|
|
||||||
/* flush the session cache of the server */
|
|
||||||
for (i = 0; i < global.nbthread; i++)
|
|
||||||
ha_free(&ckchi->server->ssl_ctx.reused_sess[i].ptr);
|
|
||||||
|
|
||||||
HA_RWLOCK_WRUNLOCK(SSL_SERVER_LOCK, &ckchi->server->ssl_ctx.lock);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
|
|
||||||
ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
|
|
||||||
HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* delete the old sni_ctx, the old ckch_insts and the ckch_store */
|
/* delete the old sni_ctx, the old ckch_insts and the ckch_store */
|
||||||
list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
|
list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
|
||||||
|
__ckch_inst_free_locked(ckchi);
|
||||||
if (ckchi->is_server_instance) {
|
|
||||||
/* no lock for servers */
|
|
||||||
ckch_inst_free(ckchi);
|
|
||||||
} else {
|
|
||||||
struct bind_conf __maybe_unused *bind_conf = ckchi->bind_conf;
|
|
||||||
|
|
||||||
HA_RWLOCK_WRLOCK(SNI_LOCK, &bind_conf->sni_lock);
|
|
||||||
ckch_inst_free(ckchi);
|
|
||||||
HA_RWLOCK_WRUNLOCK(SNI_LOCK, &bind_conf->sni_lock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Replace the old ckchs by the new one */
|
/* Replace the old ckchs by the new one */
|
||||||
|
Loading…
Reference in New Issue
Block a user