summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--auto/ssltls14
-rw-r--r--docs/changes.xml6
-rw-r--r--src/nxt_conf_validation.c46
-rw-r--r--src/nxt_openssl.c114
-rw-r--r--src/nxt_router.c90
-rw-r--r--src/nxt_tls.h6
6 files changed, 215 insertions, 61 deletions
diff --git a/auto/ssltls b/auto/ssltls
index f034b758..f9363dde 100644
--- a/auto/ssltls
+++ b/auto/ssltls
@@ -52,6 +52,20 @@ if [ $NXT_OPENSSL = YES ]; then
$echo
exit 1;
fi
+
+
+ nxt_feature="OpenSSL SSL_CONF_cmd()"
+ nxt_feature_name=NXT_HAVE_OPENSSL_CONF_CMD
+ nxt_feature_run=
+ nxt_feature_incs=
+ nxt_feature_libs="$NXT_OPENSSL_LIBS"
+ nxt_feature_test="#include <openssl/ssl.h>
+
+ int main() {
+ SSL_CONF_cmd(NULL, NULL, NULL);
+ return 0;
+ }"
+ . auto/feature
fi
diff --git a/docs/changes.xml b/docs/changes.xml
index cbe6269a..2dcaf4dd 100644
--- a/docs/changes.xml
+++ b/docs/changes.xml
@@ -39,6 +39,12 @@ PHP added to the default MIME type list.
<change type="feature">
<para>
+arbitrary configuration of TLS connections via OpenSSL commands.
+</para>
+</change>
+
+<change type="feature">
+<para>
multiple "targets" in Python applications.
</para>
</change>
diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c
index 14066fb0..06ae2847 100644
--- a/src/nxt_conf_validation.c
+++ b/src/nxt_conf_validation.c
@@ -89,6 +89,10 @@ static nxt_int_t nxt_conf_vldt_listener(nxt_conf_validation_t *vldt,
#if (NXT_TLS)
static nxt_int_t nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt,
nxt_conf_value_t *value, void *data);
+#if (NXT_HAVE_OPENSSL_CONF_CMD)
+static nxt_int_t nxt_conf_vldt_object_conf_commands(nxt_conf_validation_t *vldt,
+ nxt_conf_value_t *value, void *data);
+#endif
static nxt_int_t nxt_conf_vldt_certificate_element(nxt_conf_validation_t *vldt,
nxt_conf_value_t *value);
#endif
@@ -363,7 +367,17 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[] = {
{
.name = nxt_string("certificate"),
.type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
+ .flags = NXT_CONF_VLDT_REQUIRED,
.validator = nxt_conf_vldt_certificate,
+ }, {
+ .name = nxt_string("conf_commands"),
+ .type = NXT_CONF_VLDT_OBJECT,
+#if (NXT_HAVE_OPENSSL_CONF_CMD)
+ .validator = nxt_conf_vldt_object_conf_commands,
+#else
+ .validator = nxt_conf_vldt_unsupported,
+ .u.string = "conf_commands",
+#endif
},
NXT_CONF_VLDT_END
@@ -1971,6 +1985,38 @@ nxt_conf_vldt_certificate_element(nxt_conf_validation_t *vldt,
return NXT_OK;
}
+
+#if (NXT_HAVE_OPENSSL_CONF_CMD)
+
+static nxt_int_t
+nxt_conf_vldt_object_conf_commands(nxt_conf_validation_t *vldt,
+ nxt_conf_value_t *value, void *data)
+{
+ uint32_t index;
+ nxt_int_t ret;
+ nxt_str_t name;
+ nxt_conf_value_t *member;
+
+ index = 0;
+
+ for ( ;; ) {
+ member = nxt_conf_next_object_member(value, &name, &index);
+
+ if (member == NULL) {
+ break;
+ }
+
+ ret = nxt_conf_vldt_type(vldt, &name, member, NXT_CONF_VLDT_STRING);
+ if (ret != NXT_OK) {
+ return ret;
+ }
+ }
+
+ return NXT_OK;
+}
+
+#endif
+
#endif
diff --git a/src/nxt_openssl.c b/src/nxt_openssl.c
index af4dc24a..2fd5d1bf 100644
--- a/src/nxt_openssl.c
+++ b/src/nxt_openssl.c
@@ -5,6 +5,7 @@
*/
#include <nxt_main.h>
+#include <nxt_conf.h>
#include <openssl/ssl.h>
#include <openssl/conf.h>
#include <openssl/err.h>
@@ -42,9 +43,14 @@ static unsigned long nxt_openssl_thread_id(void);
static void nxt_openssl_locks_free(void);
#endif
static nxt_int_t nxt_openssl_server_init(nxt_task_t *task,
- nxt_tls_conf_t *conf, nxt_mp_t *mp, nxt_bool_t last);
+ nxt_tls_conf_t *conf, nxt_mp_t *mp, nxt_conf_value_t *conf_cmds,
+ nxt_bool_t last);
static nxt_int_t nxt_openssl_chain_file(nxt_task_t *task, SSL_CTX *ctx,
nxt_tls_conf_t *conf, nxt_mp_t *mp, nxt_bool_t single);
+#if (NXT_HAVE_OPENSSL_CONF_CMD)
+static nxt_int_t nxt_ssl_conf_commands(nxt_task_t *task, SSL_CTX *ctx,
+ nxt_conf_value_t *value, nxt_mp_t *mp);
+#endif
static nxt_uint_t nxt_openssl_cert_get_names(nxt_task_t *task, X509 *cert,
nxt_tls_conf_t *conf, nxt_mp_t *mp);
static nxt_int_t nxt_openssl_bundle_hash_test(nxt_lvlhsh_query_t *lhq,
@@ -260,7 +266,7 @@ nxt_openssl_locks_free(void)
static nxt_int_t
nxt_openssl_server_init(nxt_task_t *task, nxt_tls_conf_t *conf,
- nxt_mp_t *mp, nxt_bool_t last)
+ nxt_mp_t *mp, nxt_conf_value_t *conf_cmds, nxt_bool_t last)
{
SSL_CTX *ctx;
const char *ciphers, *ca_certificate;
@@ -320,6 +326,7 @@ nxt_openssl_server_init(nxt_task_t *task, nxt_tls_conf_t *conf,
goto fail;
}
*/
+
ciphers = (conf->ciphers != NULL) ? conf->ciphers : "HIGH:!aNULL:!MD5";
if (SSL_CTX_set_cipher_list(ctx, ciphers) == 0) {
@@ -329,6 +336,14 @@ nxt_openssl_server_init(nxt_task_t *task, nxt_tls_conf_t *conf,
goto fail;
}
+#if (NXT_HAVE_OPENSSL_CONF_CMD)
+ if (conf_cmds != NULL
+ && nxt_ssl_conf_commands(task, ctx, conf_cmds, mp) != NXT_OK)
+ {
+ goto fail;
+ }
+#endif
+
SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
if (conf->ca_certificate != NULL) {
@@ -484,6 +499,89 @@ clean:
}
+#if (NXT_HAVE_OPENSSL_CONF_CMD)
+
+static nxt_int_t
+nxt_ssl_conf_commands(nxt_task_t *task, SSL_CTX *ctx, nxt_conf_value_t *conf,
+ nxt_mp_t *mp)
+{
+ int ret;
+ char *zcmd, *zvalue;
+ uint32_t index;
+ nxt_str_t cmd, value;
+ SSL_CONF_CTX *cctx;
+ nxt_conf_value_t *member;
+
+ cctx = SSL_CONF_CTX_new();
+ if (nxt_slow_path(cctx == NULL)) {
+ nxt_openssl_log_error(task, NXT_LOG_ALERT,
+ "SSL_CONF_CTX_new() failed");
+ return NXT_ERROR;
+ }
+
+ SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE
+ | SSL_CONF_FLAG_SERVER
+ | SSL_CONF_FLAG_CERTIFICATE
+ | SSL_CONF_FLAG_SHOW_ERRORS);
+
+ SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
+
+ index = 0;
+
+ for ( ;; ) {
+ member = nxt_conf_next_object_member(conf, &cmd, &index);
+ if (nxt_slow_path(member == NULL)) {
+ break;
+ }
+
+ nxt_conf_get_string(member, &value);
+
+ zcmd = nxt_str_cstrz(mp, &cmd);
+ zvalue = nxt_str_cstrz(mp, &value);
+
+ if (nxt_slow_path(zcmd == NULL || zvalue == NULL)) {
+ goto fail;
+ }
+
+ ret = SSL_CONF_cmd(cctx, zcmd, zvalue);
+ if (ret == -2) {
+ nxt_openssl_log_error(task, NXT_LOG_ERR,
+ "unknown command \"%s\" in "
+ "\"conf_commands\" option", zcmd);
+ goto fail;
+ }
+
+ if (ret <= 0) {
+ nxt_openssl_log_error(task, NXT_LOG_ERR,
+ "invalid value \"%s\" for command \"%s\" "
+ "in \"conf_commands\" option",
+ zvalue, zcmd);
+ goto fail;
+ }
+
+ nxt_debug(task, "SSL_CONF_cmd(\"%s\", \"%s\")", zcmd, zvalue);
+ }
+
+ if (SSL_CONF_CTX_finish(cctx) != 1) {
+ nxt_openssl_log_error(task, NXT_LOG_ALERT,
+ "SSL_CONF_finish() failed");
+ goto fail;
+ }
+
+ SSL_CONF_CTX_free(cctx);
+
+ return NXT_OK;
+
+fail:
+
+ SSL_CONF_CTX_free(cctx);
+
+ return NXT_ERROR;
+}
+
+#endif
+
+
static nxt_uint_t
nxt_openssl_cert_get_names(nxt_task_t *task, X509 *cert, nxt_tls_conf_t *conf,
nxt_mp_t *mp)
@@ -550,7 +648,7 @@ nxt_openssl_cert_get_names(nxt_task_t *task, X509 *cert, nxt_tls_conf_t *conf,
NULL, 0);
if (len <= 0) {
nxt_log(task, NXT_LOG_WARN, "certificate \"%V\" has neither "
- "Subject Alternative Name nor Common Name", bundle->name);
+ "Subject Alternative Name nor Common Name", &bundle->name);
return NXT_OK;
}
@@ -629,7 +727,7 @@ nxt_openssl_bundle_hash_insert(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh,
if (item->name.length == 0 || item->name.start[0] != '.') {
nxt_log(task, NXT_LOG_WARN, "ignored invalid name \"%V\" "
"in certificate \"%V\": missing \".\" "
- "after wildcard symbol", &str, item->bundle->name);
+ "after wildcard symbol", &str, &item->bundle->name);
return NXT_OK;
}
}
@@ -644,7 +742,7 @@ nxt_openssl_bundle_hash_insert(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh,
ret = nxt_lvlhsh_insert(lvlhsh, &lhq);
if (nxt_fast_path(ret == NXT_OK)) {
nxt_debug(task, "name \"%V\" for certificate \"%V\" is inserted",
- &str, item->bundle->name);
+ &str, &item->bundle->name);
return NXT_OK;
}
@@ -653,7 +751,7 @@ nxt_openssl_bundle_hash_insert(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh,
if (old->bundle != item->bundle) {
nxt_log(task, NXT_LOG_WARN, "ignored duplicate name \"%V\" "
"in certificate \"%V\", identical name appears in \"%V\"",
- &str, old->bundle->name, item->bundle->name);
+ &str, &old->bundle->name, &item->bundle->name);
old->bundle = item->bundle;
}
@@ -730,8 +828,8 @@ nxt_openssl_servername(SSL *s, int *ad, void *arg)
if (bundle != NULL) {
nxt_debug(c->socket.task, "new tls context found for \"%V\": \"%V\" "
- "(old: \"%V\")", &str, bundle->name,
- conf->bundle->name);
+ "(old: \"%V\")", &str, &bundle->name,
+ &conf->bundle->name);
if (bundle != conf->bundle) {
if (SSL_set_SSL_CTX(s, bundle->ctx) == NULL) {
diff --git a/src/nxt_router.c b/src/nxt_router.c
index 122fd523..015ae226 100644
--- a/src/nxt_router.c
+++ b/src/nxt_router.c
@@ -41,8 +41,11 @@ typedef struct {
#if (NXT_TLS)
typedef struct {
- nxt_str_t name;
- nxt_socket_conf_t *conf;
+ nxt_str_t name;
+ nxt_socket_conf_t *socket_conf;
+ nxt_router_temp_conf_t *temp_conf;
+ nxt_conf_value_t *conf_cmds;
+ nxt_bool_t last;
nxt_queue_link_t link; /* for nxt_socket_conf_t.tls */
} nxt_router_tlssock_t;
@@ -117,12 +120,11 @@ static void nxt_router_listen_socket_ready(nxt_task_t *task,
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_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);
+ nxt_conf_value_t *value, nxt_socket_conf_t *skcf,
+ nxt_conf_value_t * conf_cmds);
#endif
static void nxt_router_app_rpc_create(nxt_task_t *task,
nxt_router_temp_conf_t *tmcf, nxt_app_t *app);
@@ -954,8 +956,10 @@ nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data)
tls = nxt_queue_link_data(qlk, nxt_router_tlssock_t, link);
- nxt_router_tls_rpc_create(task, tmcf, tls,
- nxt_queue_is_empty(&tmcf->tls));
+ tls->last = nxt_queue_is_empty(&tmcf->tls);
+
+ nxt_cert_store_get(task, &tls->name, tmcf->mem_pool,
+ nxt_router_tls_rpc_handler, tls);
return;
}
#endif
@@ -1337,7 +1341,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_router_t *router;
nxt_app_joint_t *app_joint;
#if (NXT_TLS)
- nxt_conf_value_t *certificate;
+ nxt_conf_value_t *certificate, *conf_cmds;
#endif
nxt_conf_value_t *conf, *http, *value, *websocket;
nxt_conf_value_t *applications, *application;
@@ -1358,6 +1362,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
static nxt_str_t access_log_path = nxt_string("/access_log");
#if (NXT_TLS)
static nxt_str_t certificate_path = nxt_string("/tls/certificate");
+ static nxt_str_t conf_commands_path = nxt_string("/tls/conf_commands");
#endif
static nxt_str_t static_path = nxt_string("/settings/http/static");
static nxt_str_t websocket_path = nxt_string("/settings/http/websocket");
@@ -1736,6 +1741,8 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
certificate = nxt_conf_get_path(listener, &certificate_path);
if (certificate != NULL) {
+ conf_cmds = nxt_conf_get_path(listener, &conf_commands_path);
+
if (nxt_conf_type(certificate) == NXT_CONF_ARRAY) {
n = nxt_conf_array_elements_count(certificate);
@@ -1744,7 +1751,8 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_assert(value != NULL);
- ret = nxt_router_conf_tls_insert(tmcf, value, skcf);
+ ret = nxt_router_conf_tls_insert(tmcf, value, skcf,
+ conf_cmds);
if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
}
@@ -1752,7 +1760,8 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
} else {
/* NXT_CONF_STRING */
- ret = nxt_router_conf_tls_insert(tmcf, certificate, skcf);
+ ret = nxt_router_conf_tls_insert(tmcf, certificate, skcf,
+ conf_cmds);
if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
}
@@ -1846,25 +1855,20 @@ fail:
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_conf_value_t *value, nxt_socket_conf_t *skcf,
+ nxt_conf_value_t *conf_cmds)
{
- 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));
+ tls = nxt_mp_get(tmcf->mem_pool, 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;
- }
+ tls->socket_conf = skcf;
+ tls->conf_cmds = conf_cmds;
+ tls->temp_conf = tmcf;
+ nxt_conf_get_string(value, &tls->name);
nxt_queue_insert_tail(&tmcf->tls, &tls->link);
@@ -2428,42 +2432,20 @@ nxt_router_listen_socket_error(nxt_task_t *task, nxt_port_recv_msg_t *msg,
#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_bool_t last)
-{
- nxt_socket_rpc_t *rpc;
-
- rpc = nxt_mp_alloc(tmcf->mem_pool, sizeof(nxt_socket_rpc_t));
- if (rpc == NULL) {
- nxt_router_conf_error(task, 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);
-}
-
-
-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_tlssock_t *tls;
nxt_tls_bundle_conf_t *bundle;
nxt_router_temp_conf_t *tmcf;
nxt_debug(task, "tls rpc handler");
- rpc = data;
- tmcf = rpc->temp_conf;
+ tls = data;
+ tmcf = tls->temp_conf;
if (msg == NULL || msg->port_msg.type == _NXT_PORT_MSG_RPC_ERROR) {
goto fail;
@@ -2471,17 +2453,17 @@ nxt_router_tls_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
mp = tmcf->router_conf->mem_pool;
- if (rpc->socket_conf->tls == NULL){
+ if (tls->socket_conf->tls == NULL){
tlscf = nxt_mp_zget(mp, sizeof(nxt_tls_conf_t));
if (nxt_slow_path(tlscf == NULL)) {
goto fail;
}
tlscf->no_wait_shutdown = 1;
- rpc->socket_conf->tls = tlscf;
+ tls->socket_conf->tls = tlscf;
} else {
- tlscf = rpc->socket_conf->tls;
+ tlscf = tls->socket_conf->tls;
}
bundle = nxt_mp_get(mp, sizeof(nxt_tls_bundle_conf_t));
@@ -2489,12 +2471,16 @@ nxt_router_tls_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
goto fail;
}
- bundle->name = rpc->name;
+ if (nxt_slow_path(nxt_str_dup(mp, &bundle->name, &tls->name) == NULL)) {
+ goto fail;
+ }
+
bundle->chain_file = msg->fd[0];
bundle->next = tlscf->bundle;
tlscf->bundle = bundle;
- ret = task->thread->runtime->tls->server_init(task, tlscf, mp, rpc->last);
+ ret = task->thread->runtime->tls->server_init(task, tlscf, mp,
+ tls->conf_cmds, tls->last);
if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
}
diff --git a/src/nxt_tls.h b/src/nxt_tls.h
index 2a29f3ca..63c49ee4 100644
--- a/src/nxt_tls.h
+++ b/src/nxt_tls.h
@@ -8,6 +8,9 @@
#define _NXT_TLS_H_INCLUDED_
+#include <nxt_conf.h>
+
+
/*
* The SSL/TLS libraries lack vector I/O interface yet add noticeable
* overhead to each SSL/TLS record so buffering allows to decrease the
@@ -32,6 +35,7 @@ typedef struct {
nxt_int_t (*server_init)(nxt_task_t *task,
nxt_tls_conf_t *conf, nxt_mp_t *mp,
+ nxt_conf_value_t *conf_cmds,
nxt_bool_t last);
void (*server_free)(nxt_task_t *task,
nxt_tls_conf_t *conf);
@@ -49,7 +53,7 @@ struct nxt_tls_bundle_conf_s {
void *ctx;
nxt_fd_t chain_file;
- nxt_str_t *name;
+ nxt_str_t name;
nxt_tls_bundle_conf_t *next;
};