[njs] Added support for HTTPS URLs to the Fetch API.
Dmitry Volyntsev
xeioex at nginx.com
Tue Oct 5 15:08:49 UTC 2021
details: https://hg.nginx.org/njs/rev/05a313868939
branches:
changeset: 1711:05a313868939
user: Antoine Bonavita <antoine.bonavita at gmail.com>
date: Wed Sep 01 20:43:56 2021 +0200
description:
Added support for HTTPS URLs to the Fetch API.
The fetch API now accepts an extra parameters:
- verify: boolean (default true) to control server certificate
verification.
Verification process can be controlled with the following directives
from the http js and stream js modules:
- js_fetch_ciphers
- js_fetch_protocols
- js_fetch_verify_depth
- js_fetch_trusted_certificate
In collaboration with Dmitry Volyntsev.
diffstat:
nginx/ngx_http_js_module.c | 141 +++++++++++++++++++++++++-
nginx/ngx_js.h | 3 +
nginx/ngx_js_fetch.c | 236 ++++++++++++++++++++++++++++++++++++++++++-
nginx/ngx_stream_js_module.c | 141 +++++++++++++++++++++++++-
4 files changed, 514 insertions(+), 7 deletions(-)
diffs (758 lines):
diff -r 64d8d8eeebda -r 05a313868939 nginx/ngx_http_js_module.c
--- a/nginx/ngx_http_js_module.c Tue Oct 05 13:01:11 2021 +0000
+++ b/nginx/ngx_http_js_module.c Wed Sep 01 20:43:56 2021 +0200
@@ -27,6 +27,13 @@ typedef struct {
ngx_str_t header_filter;
ngx_str_t body_filter;
ngx_uint_t buffer_type;
+#if (NGX_HTTP_SSL)
+ ngx_ssl_t *ssl;
+ ngx_str_t ssl_ciphers;
+ ngx_uint_t ssl_protocols;
+ ngx_int_t ssl_verify_depth;
+ ngx_str_t ssl_trusted_certificate;
+#endif
} ngx_http_js_loc_conf_t;
@@ -222,6 +229,22 @@ static void *ngx_http_js_create_loc_conf
static char *ngx_http_js_merge_loc_conf(ngx_conf_t *cf, void *parent,
void *child);
+#if (NGX_HTTP_SSL)
+static char * ngx_http_js_set_ssl(ngx_conf_t *cf, ngx_http_js_loc_conf_t *plcf);
+#endif
+static ngx_ssl_t *ngx_http_js_ssl(njs_vm_t *vm, ngx_http_request_t *r);
+
+#if (NGX_HTTP_SSL)
+
+static ngx_conf_bitmask_t ngx_http_js_ssl_protocols[] = {
+ { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
+ { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
+ { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
+ { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 },
+ { ngx_null_string, 0 }
+};
+
+#endif
static ngx_command_t ngx_http_js_commands[] = {
@@ -281,6 +304,38 @@ static ngx_command_t ngx_http_js_comman
0,
NULL },
+#if (NGX_HTTP_SSL)
+
+ { ngx_string("js_fetch_ciphers"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_js_loc_conf_t, ssl_ciphers),
+ NULL },
+
+ { ngx_string("js_fetch_protocols"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+ ngx_conf_set_bitmask_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_js_loc_conf_t, ssl_protocols),
+ &ngx_http_js_ssl_protocols },
+
+ { ngx_string("js_fetch_verify_depth"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_num_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_js_loc_conf_t, ssl_verify_depth),
+ NULL },
+
+ { ngx_string("js_fetch_trusted_certificate"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_js_loc_conf_t, ssl_trusted_certificate),
+ NULL },
+
+#endif
+
ngx_null_command
};
@@ -657,11 +712,12 @@ static uintptr_t ngx_http_js_uptr[] = {
(uintptr_t) ngx_http_js_resolver,
(uintptr_t) ngx_http_js_resolver_timeout,
(uintptr_t) ngx_http_js_handle_event,
+ (uintptr_t) ngx_http_js_ssl,
};
static njs_vm_meta_t ngx_http_js_metas = {
- .size = 5,
+ .size = 6,
.values = ngx_http_js_uptr
};
@@ -3951,8 +4007,15 @@ ngx_http_js_create_loc_conf(ngx_conf_t *
* conf->header_filter = { 0, NULL };
* conf->body_filter = { 0, NULL };
* conf->buffer_type = NGX_JS_UNSET;
+ * conf->ssl_ciphers = { 0, NULL };
+ * conf->ssl_protocols = 0;
+ * conf->ssl_trusted_certificate = { 0, NULL };
*/
+#if (NGX_HTTP_SSL)
+ conf->ssl_verify_depth = NGX_CONF_UNSET;
+#endif
+
return conf;
}
@@ -3969,5 +4032,81 @@ ngx_http_js_merge_loc_conf(ngx_conf_t *c
ngx_conf_merge_uint_value(conf->buffer_type, prev->buffer_type,
NGX_JS_STRING);
+#if (NGX_HTTP_SSL)
+ ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT");
+
+ ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
+ (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
+ |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
+
+ ngx_conf_merge_value(conf->ssl_verify_depth, prev->ssl_verify_depth, 100);
+
+ ngx_conf_merge_str_value(conf->ssl_trusted_certificate,
+ prev->ssl_trusted_certificate, "");
+
+ return ngx_http_js_set_ssl(cf, conf);
+#else
+ return NGX_CONF_OK;
+#endif
+}
+
+
+#if (NGX_HTTP_SSL)
+
+static char *
+ngx_http_js_set_ssl(ngx_conf_t *cf, ngx_http_js_loc_conf_t *plcf)
+{
+ ngx_ssl_t *ssl;
+ ngx_pool_cleanup_t *cln;
+
+ ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
+ if (ssl == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ plcf->ssl = ssl;
+ ssl->log = cf->log;
+
+ if (ngx_ssl_create(ssl, plcf->ssl_protocols, NULL) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ cln = ngx_pool_cleanup_add(cf->pool, 0);
+ if (cln == NULL) {
+ ngx_ssl_cleanup_ctx(ssl);
+ return NGX_CONF_ERROR;
+ }
+
+ cln->handler = ngx_ssl_cleanup_ctx;
+ cln->data = ssl;
+
+ if (ngx_ssl_ciphers(NULL, ssl, &plcf->ssl_ciphers, 0) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (ngx_ssl_trusted_certificate(cf, ssl, &plcf->ssl_trusted_certificate,
+ plcf->ssl_verify_depth)
+ != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
+ }
+
return NGX_CONF_OK;
}
+
+#endif
+
+
+static ngx_ssl_t *
+ngx_http_js_ssl(njs_vm_t *vm, ngx_http_request_t *r)
+{
+#if (NGX_HTTP_SSL)
+ ngx_http_js_loc_conf_t *plcf;
+
+ plcf = ngx_http_get_module_loc_conf(r, ngx_http_js_module);
+
+ return plcf->ssl;
+#else
+ return NULL;
+#endif
+}
diff -r 64d8d8eeebda -r 05a313868939 nginx/ngx_js.h
--- a/nginx/ngx_js.h Tue Oct 05 13:01:11 2021 +0000
+++ b/nginx/ngx_js.h Wed Sep 01 20:43:56 2021 +0200
@@ -27,6 +27,7 @@ typedef ngx_resolver_t *(*ngx_external_r
njs_external_ptr_t e);
typedef ngx_msec_t (*ngx_external_resolver_timeout_pt)(njs_vm_t *vm,
njs_external_ptr_t e);
+typedef ngx_ssl_t *(*ngx_external_ssl_pt)(njs_vm_t *vm, njs_external_ptr_t e);
#define ngx_external_connection(vm, e) \
@@ -39,6 +40,8 @@ typedef ngx_msec_t (*ngx_external_resolv
((ngx_external_resolver_timeout_pt) njs_vm_meta(vm, 3))(vm, e)
#define ngx_external_event_handler(vm, e) \
((ngx_js_event_handler_pt) njs_vm_meta(vm, 4))
+#define ngx_external_ssl(vm, e) \
+ ((ngx_external_ssl_pt) njs_vm_meta(vm, 5))(vm, e)
#define ngx_js_prop(vm, type, value, start, len) \
diff -r 64d8d8eeebda -r 05a313868939 nginx/ngx_js_fetch.c
--- a/nginx/ngx_js_fetch.c Tue Oct 05 13:01:11 2021 +0000
+++ b/nginx/ngx_js_fetch.c Wed Sep 01 20:43:56 2021 +0200
@@ -2,6 +2,7 @@
/*
* Copyright (C) Dmitry Volyntsev
* Copyright (C) hongzhidao
+ * Copyright (C) Antoine Bonavita
* Copyright (C) NGINX, Inc.
*/
@@ -65,6 +66,12 @@ struct ngx_js_http_s {
njs_str_t url;
ngx_array_t headers;
+#if (NGX_SSL)
+ ngx_str_t tls_name;
+ ngx_ssl_t *ssl;
+ njs_bool_t ssl_verify;
+#endif
+
ngx_buf_t *buffer;
ngx_buf_t *chunk;
njs_chb_t chain;
@@ -142,6 +149,12 @@ static njs_int_t ngx_response_js_ext_typ
static njs_int_t ngx_response_js_ext_body(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused);
+#if (NGX_SSL)
+static void ngx_js_http_ssl_init_connection(ngx_js_http_t *http);
+static void ngx_js_http_ssl_handshake_handler(ngx_connection_t *c);
+static void ngx_js_http_ssl_handshake(ngx_js_http_t *http);
+static njs_int_t ngx_js_http_ssl_name(ngx_js_http_t *http);
+#endif
static njs_external_t ngx_js_ext_http_response_headers[] = {
@@ -344,6 +357,9 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value
static const njs_str_t buffer_size_key = njs_str("buffer_size");
static const njs_str_t body_size_key = njs_str("max_response_body_size");
static const njs_str_t method_key = njs_str("method");
+#if (NGX_SSL)
+ static const njs_str_t verify_key = njs_str("verify");
+#endif
external = njs_vm_external(vm, NJS_PROTO_ID_ANY, njs_argument(args, 0));
if (external == NULL) {
@@ -384,6 +400,17 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value
u.url.len -= 7;
u.url.data += 7;
+#if (NGX_SSL)
+ } else if (u.url.len > 8
+ && ngx_strncasecmp(u.url.data, (u_char *) "https://", 8) == 0)
+ {
+ u.url.len -= 8;
+ u.url.data += 8;
+ u.default_port = 443;
+ http->ssl = ngx_external_ssl(vm, external);
+ http->ssl_verify = 1;
+#endif
+
} else {
njs_vm_error(vm, "unsupported URL prefix");
goto fail;
@@ -432,6 +459,13 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value
{
goto fail;
}
+
+#if (NGX_SSL)
+ value = njs_vm_object_prop(vm, init, &verify_key, &lvalue);
+ if (value != NULL) {
+ http->ssl_verify = njs_value_bool(value);
+ }
+#endif
}
njs_chb_init(&http->chain, njs_vm_memory_pool(vm));
@@ -501,6 +535,11 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value
njs_chb_append_literal(&http->chain, CRLF);
}
+#if (NGX_SSL)
+ http->tls_name.data = u.host.data;
+ http->tls_name.len = u.host.len;
+#endif
+
if (body.length != 0) {
njs_chb_sprintf(&http->chain, 32, "Content-Length: %uz" CRLF CRLF,
body.length);
@@ -697,6 +736,29 @@ failed:
static void
+ngx_js_http_close_connection(ngx_connection_t *c)
+{
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "close js http connection: %d", c->fd);
+
+#if (NGX_SSL)
+ if (c->ssl) {
+ c->ssl->no_wait_shutdown = 1;
+
+ if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
+ c->ssl->handler = ngx_js_http_close_connection;
+ return;
+ }
+ }
+#endif
+
+ c->destroyed = 1;
+
+ ngx_close_connection(c);
+}
+
+
+static void
njs_js_http_destructor(njs_external_ptr_t external, njs_host_event_t host)
{
ngx_js_http_t *http;
@@ -712,7 +774,7 @@ njs_js_http_destructor(njs_external_ptr_
}
if (http->peer.connection != NULL) {
- ngx_close_connection(http->peer.connection);
+ ngx_js_http_close_connection(http->peer.connection);
http->peer.connection = NULL;
}
}
@@ -773,7 +835,7 @@ ngx_js_http_fetch_done(ngx_js_http_t *ht
"js fetch done http:%p rc:%i", http, (ngx_int_t) rc);
if (http->peer.connection != NULL) {
- ngx_close_connection(http->peer.connection);
+ ngx_js_http_close_connection(http->peer.connection);
http->peer.connection = NULL;
}
@@ -846,12 +908,169 @@ ngx_js_http_connect(ngx_js_http_t *http)
ngx_add_timer(http->peer.connection->write, http->timeout);
}
+#if (NGX_SSL)
+ if (http->ssl != NULL && http->peer.connection->ssl == NULL) {
+ ngx_js_http_ssl_init_connection(http);
+ return;
+ }
+#endif
+
if (rc == NGX_OK) {
ngx_js_http_write_handler(http->peer.connection->write);
}
}
+#if (NGX_SSL)
+
+static void
+ngx_js_http_ssl_init_connection(ngx_js_http_t *http)
+{
+ ngx_int_t rc;
+ ngx_connection_t *c;
+
+ c = http->peer.connection;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_EVENT, http->log, 0,
+ "js http secure connect %ui/%ui", http->naddr, http->naddrs);
+
+ if (ngx_ssl_create_connection(http->ssl, c, NGX_SSL_BUFFER|NGX_SSL_CLIENT)
+ != NGX_OK)
+ {
+ ngx_js_http_error(http, 0, "failed to create ssl connection");
+ return;
+ }
+
+ c->sendfile = 0;
+
+ if (ngx_js_http_ssl_name(http) != NGX_OK) {
+ ngx_js_http_error(http, 0, "failed to create ssl connection");
+ return;
+ }
+
+ c->log->action = "SSL handshaking to fetch target";
+
+ rc = ngx_ssl_handshake(c);
+
+ if (rc == NGX_AGAIN) {
+ c->data = http;
+ c->ssl->handler = ngx_js_http_ssl_handshake_handler;
+ return;
+ }
+
+ ngx_js_http_ssl_handshake(http);
+}
+
+
+static void
+ngx_js_http_ssl_handshake_handler(ngx_connection_t *c)
+{
+ ngx_js_http_t *http;
+
+ http = c->data;
+
+ http->peer.connection->write->handler = ngx_js_http_write_handler;
+ http->peer.connection->read->handler = ngx_js_http_read_handler;
+
+ ngx_js_http_ssl_handshake(http);
+}
+
+
+static void
+ngx_js_http_ssl_handshake(ngx_js_http_t *http)
+{
+ long rc;
+ ngx_connection_t *c;
+
+ c = http->peer.connection;
+
+ if (c->ssl->handshaked) {
+ if (http->ssl_verify) {
+ rc = SSL_get_verify_result(c->ssl->connection);
+
+ if (rc != X509_V_OK) {
+ ngx_log_error(NGX_LOG_ERR, c->log, 0,
+ "js http fetch SSL certificate verify "
+ "error: (%l:%s)", rc,
+ X509_verify_cert_error_string(rc));
+ goto failed;
+ }
+
+ if (ngx_ssl_check_host(c, &http->tls_name) != NGX_OK) {
+ ngx_log_error(NGX_LOG_ERR, c->log, 0,
+ "js http SSL certificate does not match \"%V\"",
+ &http->tls_name);
+ goto failed;
+ }
+ }
+
+ c->write->handler = ngx_js_http_write_handler;
+ c->read->handler = ngx_js_http_read_handler;
+
+ http->process = ngx_js_http_process_status_line;
+ ngx_js_http_write_handler(c->write);
+
+ return;
+ }
+
+failed:
+
+ ngx_js_http_next(http);
+ }
+
+
+static njs_int_t
+ngx_js_http_ssl_name(ngx_js_http_t *http)
+{
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+ u_char *p;
+
+ /* as per RFC 6066, literal IPv4 and IPv6 addresses are not permitted */
+ ngx_str_t *name = &http->tls_name;
+
+ if (name->len == 0 || *name->data == '[') {
+ goto done;
+ }
+
+ if (ngx_inet_addr(name->data, name->len) != INADDR_NONE) {
+ goto done;
+ }
+
+ /*
+ * SSL_set_tlsext_host_name() needs a null-terminated string,
+ * hence we explicitly null-terminate name here
+ */
+
+ p = ngx_pnalloc(http->pool, name->len + 1);
+ if (p == NULL) {
+ return NGX_ERROR;
+ }
+
+ (void) ngx_cpystrn(p, name->data, name->len + 1);
+
+ name->data = p;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, http->log, 0,
+ "js http SSL server name: \"%s\"", name->data);
+
+ if (SSL_set_tlsext_host_name(http->peer.connection->ssl->connection,
+ (char *) name->data)
+ == 0)
+ {
+ ngx_ssl_error(NGX_LOG_ERR, http->log, 0,
+ "SSL_set_tlsext_host_name(\"%s\") failed", name->data);
+ return NGX_ERROR;
+ }
+
+#endif
+done:
+
+ return NJS_OK;
+}
+
+#endif
+
+
static void
ngx_js_http_next(ngx_js_http_t *http)
{
@@ -863,7 +1082,7 @@ ngx_js_http_next(ngx_js_http_t *http)
}
if (http->peer.connection != NULL) {
- ngx_close_connection(http->peer.connection);
+ ngx_js_http_close_connection(http->peer.connection);
http->peer.connection = NULL;
}
@@ -891,6 +1110,13 @@ ngx_js_http_write_handler(ngx_event_t *w
return;
}
+#if (NGX_SSL)
+ if (http->ssl != NULL && http->peer.connection->ssl == NULL) {
+ ngx_js_http_ssl_init_connection(http);
+ return;
+ }
+#endif
+
b = http->buffer;
if (b == NULL) {
@@ -914,7 +1140,7 @@ ngx_js_http_write_handler(ngx_event_t *w
size = b->last - b->pos;
- n = ngx_send(c, b->pos, size);
+ n = c->send(c, b->pos, size);
if (n == NGX_ERROR) {
ngx_js_http_next(http);
@@ -980,7 +1206,7 @@ ngx_js_http_read_handler(ngx_event_t *re
b = http->buffer;
size = b->end - b->last;
- n = ngx_recv(c, b->last, size);
+ n = c->recv(c, b->last, size);
if (n > 0) {
b->last += n;
diff -r 64d8d8eeebda -r 05a313868939 nginx/ngx_stream_js_module.c
--- a/nginx/ngx_stream_js_module.c Tue Oct 05 13:01:11 2021 +0000
+++ b/nginx/ngx_stream_js_module.c Wed Sep 01 20:43:56 2021 +0200
@@ -34,6 +34,13 @@ typedef struct {
ngx_str_t access;
ngx_str_t preread;
ngx_str_t filter;
+#if (NGX_SSL)
+ ngx_ssl_t *ssl;
+ ngx_str_t ssl_ciphers;
+ ngx_uint_t ssl_protocols;
+ ngx_int_t ssl_verify_depth;
+ ngx_str_t ssl_trusted_certificate;
+#endif
} ngx_stream_js_srv_conf_t;
@@ -135,6 +142,23 @@ static char *ngx_stream_js_merge_srv_con
void *child);
static ngx_int_t ngx_stream_js_init(ngx_conf_t *cf);
+#if (NGX_SSL)
+static char * ngx_stream_js_set_ssl(ngx_conf_t *cf,
+ ngx_stream_js_srv_conf_t *pscf);
+#endif
+static ngx_ssl_t *ngx_stream_js_ssl(njs_vm_t *vm, ngx_stream_session_t *s);
+
+#if (NGX_HTTP_SSL)
+
+static ngx_conf_bitmask_t ngx_stream_js_ssl_protocols[] = {
+ { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
+ { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
+ { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
+ { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 },
+ { ngx_null_string, 0 }
+};
+
+#endif
static ngx_command_t ngx_stream_js_commands[] = {
@@ -194,6 +218,38 @@ static ngx_command_t ngx_stream_js_comm
offsetof(ngx_stream_js_srv_conf_t, filter),
NULL },
+#if (NGX_SSL)
+
+ { ngx_string("js_fetch_ciphers"),
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ offsetof(ngx_stream_js_srv_conf_t, ssl_ciphers),
+ NULL },
+
+ { ngx_string("js_fetch_protocols"),
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
+ ngx_conf_set_bitmask_slot,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ offsetof(ngx_stream_js_srv_conf_t, ssl_protocols),
+ &ngx_stream_js_ssl_protocols },
+
+ { ngx_string("js_fetch_verify_depth"),
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_num_slot,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ offsetof(ngx_stream_js_srv_conf_t, ssl_verify_depth),
+ NULL },
+
+ { ngx_string("js_fetch_trusted_certificate"),
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ offsetof(ngx_stream_js_srv_conf_t, ssl_trusted_certificate),
+ NULL },
+
+#endif
+
ngx_null_command
};
@@ -408,11 +464,12 @@ static uintptr_t ngx_stream_js_uptr[] =
(uintptr_t) ngx_stream_js_resolver,
(uintptr_t) ngx_stream_js_resolver_timeout,
(uintptr_t) ngx_stream_js_handle_event,
+ (uintptr_t) ngx_stream_js_ssl,
};
static njs_vm_meta_t ngx_stream_js_metas = {
- .size = 5,
+ .size = 6,
.values = ngx_stream_js_uptr
};
@@ -1891,8 +1948,14 @@ ngx_stream_js_create_srv_conf(ngx_conf_t
* conf->access = { 0, NULL };
* conf->preread = { 0, NULL };
* conf->filter = { 0, NULL };
+ * conf->ssl_ciphers = { 0, NULL };
+ * conf->ssl_protocols = 0;
+ * conf->ssl_trusted_certificate = { 0, NULL };
*/
+#if (NGX_SSL)
+ conf->ssl_verify_depth = NGX_CONF_UNSET;
+#endif
return conf;
}
@@ -1907,7 +1970,22 @@ ngx_stream_js_merge_srv_conf(ngx_conf_t
ngx_conf_merge_str_value(conf->preread, prev->preread, "");
ngx_conf_merge_str_value(conf->filter, prev->filter, "");
+#if (NGX_HTTP_SSL)
+ ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT");
+
+ ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
+ (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
+ |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
+
+ ngx_conf_merge_value(conf->ssl_verify_depth, prev->ssl_verify_depth, 100);
+
+ ngx_conf_merge_str_value(conf->ssl_trusted_certificate,
+ prev->ssl_trusted_certificate, "");
+
+ return ngx_stream_js_set_ssl(cf, conf);
+#else
return NGX_CONF_OK;
+#endif
}
@@ -1938,3 +2016,64 @@ ngx_stream_js_init(ngx_conf_t *cf)
return NGX_OK;
}
+
+
+#if (NGX_SSL)
+
+static char *
+ngx_stream_js_set_ssl(ngx_conf_t *cf, ngx_stream_js_srv_conf_t *pscf)
+{
+ ngx_ssl_t *ssl;
+ ngx_pool_cleanup_t *cln;
+
+ ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
+ if (ssl == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ pscf->ssl = ssl;
+ ssl->log = cf->log;
+
+ if (ngx_ssl_create(ssl, pscf->ssl_protocols, NULL) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ cln = ngx_pool_cleanup_add(cf->pool, 0);
+ if (cln == NULL) {
+ ngx_ssl_cleanup_ctx(ssl);
+ return NGX_CONF_ERROR;
+ }
+
+ cln->handler = ngx_ssl_cleanup_ctx;
+ cln->data = ssl;
+
+ if (ngx_ssl_ciphers(NULL, ssl, &pscf->ssl_ciphers, 0) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (ngx_ssl_trusted_certificate(cf, ssl, &pscf->ssl_trusted_certificate,
+ pscf->ssl_verify_depth)
+ != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
+ }
+
+ return NGX_CONF_OK;
+}
+
+#endif
+
+
+static ngx_ssl_t *
+ngx_stream_js_ssl(njs_vm_t *vm, ngx_stream_session_t *s)
+{
+#if (NGX_SSL)
+ ngx_stream_js_srv_conf_t *pscf;
+
+ pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_js_module);
+
+ return pscf->ssl;
+#else
+ return NULL;
+#endif
+}
More information about the nginx-devel
mailing list