Added ability to configure multiple certificates on a listener.

The certificate is selected by matching the arriving SNI to the common name and
the alternatives names.  If no certificate matches the name, the first bundle in
the array is chosen.
This commit is contained in:
Andrey Suvorov
2021-03-24 13:19:36 -07:00
parent d62192738f
commit d2b0882d89
5 changed files with 525 additions and 69 deletions

View File

@@ -51,8 +51,10 @@ typedef struct {
typedef struct {
nxt_str_t *name;
nxt_socket_conf_t *socket_conf;
nxt_router_temp_conf_t *temp_conf;
nxt_bool_t last;
} nxt_socket_rpc_t;
@@ -116,9 +118,11 @@ static void nxt_router_listen_socket_error(nxt_task_t *task,
nxt_port_recv_msg_t *msg, void *data);
#if (NXT_TLS)
static void nxt_router_tls_rpc_create(nxt_task_t *task,
nxt_router_temp_conf_t *tmcf, nxt_router_tlssock_t *tls);
nxt_router_temp_conf_t *tmcf, nxt_router_tlssock_t *tls, nxt_bool_t last);
static void nxt_router_tls_rpc_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg, void *data);
static nxt_int_t nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf,
nxt_conf_value_t *value, nxt_socket_conf_t *skcf);
#endif
static void nxt_router_app_rpc_create(nxt_task_t *task,
nxt_router_temp_conf_t *tmcf, nxt_app_t *app);
@@ -944,14 +948,15 @@ nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data)
}
#if (NXT_TLS)
qlk = nxt_queue_first(&tmcf->tls);
qlk = nxt_queue_last(&tmcf->tls);
if (qlk != nxt_queue_tail(&tmcf->tls)) {
if (qlk != nxt_queue_head(&tmcf->tls)) {
nxt_queue_remove(qlk);
tls = nxt_queue_link_data(qlk, nxt_router_tlssock_t, link);
nxt_router_tls_rpc_create(task, tmcf, tls);
nxt_router_tls_rpc_create(task, tmcf, tls,
nxt_queue_is_empty(&tmcf->tls));
return;
}
#endif
@@ -990,7 +995,7 @@ nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data)
nxt_router_apps_sort(task, router, tmcf);
nxt_router_apps_hash_use(task, rtcf, 1);
nxt_router_apps_hash_use(task, rtcf, 1);
nxt_router_engines_post(router, tmcf);
@@ -1332,6 +1337,9 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_port_t *port;
nxt_router_t *router;
nxt_app_joint_t *app_joint;
#if (NXT_TLS)
nxt_conf_value_t *certificate;
#endif
nxt_conf_value_t *conf, *http, *value, *websocket;
nxt_conf_value_t *applications, *application;
nxt_conf_value_t *listeners, *listener;
@@ -1343,9 +1351,6 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_router_app_conf_t apcf;
nxt_router_access_log_t *access_log;
nxt_router_listener_conf_t lscf;
#if (NXT_TLS)
nxt_router_tlssock_t *tls;
#endif
static nxt_str_t http_path = nxt_string("/settings/http");
static nxt_str_t applications_path = nxt_string("/applications");
@@ -1729,20 +1734,30 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
}
#if (NXT_TLS)
value = nxt_conf_get_path(listener, &certificate_path);
certificate = nxt_conf_get_path(listener, &certificate_path);
if (value != NULL) {
nxt_conf_get_string(value, &name);
if (certificate != NULL) {
if (nxt_conf_type(certificate) == NXT_CONF_ARRAY) {
n = nxt_conf_array_elements_count(certificate);
tls = nxt_mp_get(mp, sizeof(nxt_router_tlssock_t));
if (nxt_slow_path(tls == NULL)) {
goto fail;
for (i = 0; i < n; i++) {
value = nxt_conf_get_array_element(certificate, i);
nxt_assert(value != NULL);
ret = nxt_router_conf_tls_insert(tmcf, value, skcf);
if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
}
}
} else {
/* NXT_CONF_STRING */
ret = nxt_router_conf_tls_insert(tmcf, certificate, skcf);
if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
}
}
tls->name = name;
tls->conf = skcf;
nxt_queue_insert_tail(&tmcf->tls, &tls->link);
}
#endif
@@ -1828,6 +1843,38 @@ fail:
}
#if (NXT_TLS)
static nxt_int_t
nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf,
nxt_conf_value_t *value, nxt_socket_conf_t *skcf)
{
nxt_mp_t *mp;
nxt_str_t str;
nxt_router_tlssock_t *tls;
mp = tmcf->router_conf->mem_pool;
tls = nxt_mp_get(mp, sizeof(nxt_router_tlssock_t));
if (nxt_slow_path(tls == NULL)) {
return NXT_ERROR;
}
tls->conf = skcf;
nxt_conf_get_string(value, &str);
if (nxt_slow_path(nxt_str_dup(mp, &tls->name, &str) == NULL)) {
return NXT_ERROR;
}
nxt_queue_insert_tail(&tmcf->tls, &tls->link);
return NXT_OK;
}
#endif
static nxt_int_t
nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf,
nxt_conf_value_t *conf)
@@ -2383,7 +2430,7 @@ nxt_router_listen_socket_error(nxt_task_t *task, nxt_port_recv_msg_t *msg,
static void
nxt_router_tls_rpc_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_router_tlssock_t *tls)
nxt_router_tlssock_t *tls, nxt_bool_t last)
{
nxt_socket_rpc_t *rpc;
@@ -2393,8 +2440,10 @@ nxt_router_tls_rpc_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
return;
}
rpc->name = &tls->name;
rpc->socket_conf = tls->conf;
rpc->temp_conf = tmcf;
rpc->last = last;
nxt_cert_store_get(task, &tls->name, tmcf->mem_pool,
nxt_router_tls_rpc_handler, rpc);
@@ -2405,11 +2454,12 @@ static void
nxt_router_tls_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
void *data)
{
nxt_mp_t *mp;
nxt_int_t ret;
nxt_tls_conf_t *tlscf;
nxt_socket_rpc_t *rpc;
nxt_router_temp_conf_t *tmcf;
nxt_mp_t *mp;
nxt_int_t ret;
nxt_tls_conf_t *tlscf;
nxt_socket_rpc_t *rpc;
nxt_tls_bundle_conf_t *bundle;
nxt_router_temp_conf_t *tmcf;
nxt_debug(task, "tls rpc handler");
@@ -2422,20 +2472,33 @@ nxt_router_tls_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
mp = tmcf->router_conf->mem_pool;
tlscf = nxt_mp_zget(mp, sizeof(nxt_tls_conf_t));
if (nxt_slow_path(tlscf == NULL)) {
if (rpc->socket_conf->tls == NULL){
tlscf = nxt_mp_zget(mp, sizeof(nxt_tls_conf_t));
if (nxt_slow_path(tlscf == NULL)) {
goto fail;
}
rpc->socket_conf->tls = tlscf;
} else {
tlscf = rpc->socket_conf->tls;
}
bundle = nxt_mp_get(mp, sizeof(nxt_tls_bundle_conf_t));
if (nxt_slow_path(bundle == NULL)) {
goto fail;
}
tlscf->chain_file = msg->fd[0];
bundle->name = rpc->name;
bundle->chain_file = msg->fd[0];
bundle->next = tlscf->bundle;
tlscf->bundle = bundle;
ret = task->thread->runtime->tls->server_init(task, tlscf);
ret = task->thread->runtime->tls->server_init(task, tlscf, mp, rpc->last);
if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
}
rpc->socket_conf->tls = tlscf;
nxt_work_queue_add(&task->thread->engine->fast_work_queue,
nxt_router_conf_apply, task, tmcf, NULL);
return;