Latest update - GitHub fd0848b (1.29.3)

This commit is contained in:
2025-11-03 21:09:28 +09:00
parent 602334da65
commit d42d1aa241
32 changed files with 1132 additions and 182 deletions
+41
View File
@@ -0,0 +1,41 @@
---
name: F5 CLA
on:
issue_comment:
types: [created]
pull_request_target:
types: [opened, closed, synchronize]
permissions: read-all
jobs:
f5-cla:
name: F5 CLA
runs-on: ubuntu-24.04
permissions:
actions: write
pull-requests: write
statuses: write
steps:
- name: Run F5 Contributor License Agreement (CLA) assistant
if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have hereby read the F5 CLA and agree to its terms') || github.event_name == 'pull_request_target'
uses: contributor-assistant/github-action@ca4a40a7d1004f18d9960b404b97e5f30a505a08 # v2.6.1
with:
# Path to the CLA document.
path-to-document: https://github.com/f5/f5-cla/blob/main/docs/f5_cla.md
# Custom CLA messages.
custom-notsigned-prcomment: '🎉 Thank you for your contribution! It appears you have not yet signed the [F5 Contributor License Agreement (CLA)](https://github.com/f5/f5-cla/blob/main/docs/f5_cla.md), which is required for your changes to be incorporated into an F5 Open Source Software (OSS) project. Please kindly read the [F5 CLA](https://github.com/f5/f5-cla/blob/main/docs/f5_cla.md) and reply on a new comment with the following text to agree:'
custom-pr-sign-comment: 'I have hereby read the F5 CLA and agree to its terms'
custom-allsigned-prcomment: '✅ All required contributors have signed the F5 CLA for this PR. Thank you!'
# Remote repository storing CLA signatures.
remote-organization-name: f5
remote-repository-name: f5-cla-data
# Branch where CLA signatures are stored.
branch: main
path-to-signatures: signatures/signatures.json
# Comma separated list of usernames for maintainers or any other individuals who should not be prompted for a CLA.
# NOTE: You will want to edit the usernames to suit your project needs.
allowlist: bot*
# Do not lock PRs after a merge.
lock-pullrequest-aftermerge: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PERSONAL_ACCESS_TOKEN: ${{ secrets.F5_CLA_TOKEN }}
+153 -2
View File
@@ -5,6 +5,157 @@
<change_log title="nginx"> <change_log title="nginx">
<changes ver="1.29.3" date="2025-10-28">
<change type="feature">
<para lang="ru">
директивы add_header_inherit и add_trailer_inherit.
</para>
<para lang="en">
the "add_header_inherit" and "add_trailer_inherit" directives.
</para>
</change>
<change type="feature">
<para lang="ru">
переменные $request_port и $is_request_port.
</para>
<para lang="en">
the $request_port and $is_request_port variables.
</para>
</change>
<change type="feature">
<para lang="ru">
переменные $ssl_sigalg и $ssl_client_sigalg.
</para>
<para lang="en">
the $ssl_sigalg and $ssl_client_sigalg variables.
</para>
</change>
<change type="feature">
<para lang="ru">
параметр volatile директивы geo.
</para>
<para lang="en">
the "volatile" parameter of the "geo" directive.
</para>
</change>
<change type="feature">
<para lang="ru">
теперь сжатие сертификатов доступно с BoringSSL.
</para>
<para lang="en">
now certificate compression is available with BoringSSL.
</para>
</change>
<change type="bugfix">
<para lang="ru">
теперь сжатие сертификатов запрещено при включенном OCSP stapling.
</para>
<para lang="en">
now certificate compression is disabled with OCSP stapling.
</para>
</change>
</changes>
<changes ver="1.29.2" date="2025-10-07">
<change type="feature">
<para lang="ru">
теперь nginx можно собрать с AWS-LC.<br/>
Спасибо Samuel Chiang.
</para>
<para lang="en">
now nginx can be built with AWS-LC.<br/>
Thanks Samuel Chiang.
</para>
</change>
<change type="bugfix">
<para lang="ru">
теперь директива ssl_protocols работает
в виртуальном сервере, отличном от сервера по умолчанию,
при использовании OpenSSL 1.1.1 и новее.
</para>
<para lang="en">
now the "ssl_protocols" directive works
in a virtual server different from the default server
when using OpenSSL 1.1.1 or newer.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при использовании TLSv1.3 с OpenSSL и клиентских сертификатов
SSL handshake всегда завершался ошибкой
при восстановлении сессии с другим значением SNI;
ошибка появилась в 1.27.4.
</para>
<para lang="en">
SSL handshake always failed
when using TLSv1.3 with OpenSSL and client certificates
and resuming a session with a different SNI value;
the bug had appeared in 1.27.4.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при использовании QUIC и директивы ssl_reject_handshake
в логах могли появляться сообщения
"ignoring stale global SSL error";
ошибка появилась в 1.29.0.<br/>
Спасибо Владимиру Хомутову.
</para>
<para lang="en">
the "ignoring stale global SSL error"
alerts might appear in logs
when using QUIC and the "ssl_reject_handshake" directive;
the bug had appeared in 1.29.0.<br/>
Thanks to Vladimir Homutov.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в обработке delta-seconds
в строке "Cache-Control" в заголовке ответа бэкенда.
</para>
<para lang="en">
in delta-seconds processing
in the "Cache-Control" backend response header line.
</para>
</change>
<change type="bugfix">
<para lang="ru">
команда XCLIENT не использовала кодировку xtext.<br/>
Спасибо Igor Morgenstern из Aisle Research.
</para>
<para lang="en">
an XCLIENT command didn't use the xtext encoding.<br/>
Thanks to Igor Morgenstern of Aisle Research.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в кешировании SSL-сертификатов во время переконфигурации.
</para>
<para lang="en">
in SSL certificate caching during reconfiguration.
</para>
</change>
</changes>
<changes ver="1.29.1" date="2025-08-13"> <changes ver="1.29.1" date="2025-08-13">
<change type="security"> <change type="security">
@@ -8736,7 +8887,7 @@ Thanks to Piotr Sikora.
Спасибо Piotr Sikora. Спасибо Piotr Sikora.
</para> </para>
<para lang="en"> <para lang="en">
now nginx can be build with BoringSSL and LibreSSL.<br/> now nginx can be built with BoringSSL and LibreSSL.<br/>
Thanks to Piotr Sikora. Thanks to Piotr Sikora.
</para> </para>
</change> </change>
@@ -26019,7 +26170,7 @@ the ECONNABORTED error log level was changed to "error" from "crit".
модуль ngx_http_perl_module не собирался без модуля ngx_http_ssi_filter_module. модуль ngx_http_perl_module не собирался без модуля ngx_http_ssi_filter_module.
</para> </para>
<para lang="en"> <para lang="en">
the ngx_http_perl_module could not be build without the ngx_http_perl_module could not be built without
the ngx_http_ssi_filter_module. the ngx_http_ssi_filter_module.
</para> </para>
</change> </change>
+2 -2
View File
@@ -6,9 +6,9 @@ TEMP = tmp
CC = cl CC = cl
OBJS = objs.msvc8 OBJS = objs.msvc8
OPENSSL = openssl-3.5.2 OPENSSL = openssl-3.5.4
ZLIB = zlib-1.3.1 ZLIB = zlib-1.3.1
PCRE = pcre2-10.45 PCRE = pcre2-10.46
release: export release: export
+1 -1
View File
@@ -3,7 +3,7 @@ make -f misc/GNUmakefile release
the required tools: the required tools:
*) xsltproc to build CHANGES, *) xsltproc to build CHANGES,
*) xslscript.pl ( http://hg.nginx.org/xslscript ) to build XSLTs *) xslscript.pl ( https://github.com/nginx/xslscript ) to build XSLTs
from XSLScript sources. from XSLScript sources.
+2 -2
View File
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_ #define _NGINX_H_INCLUDED_
#define nginx_version 1029002 #define nginx_version 1029003
#define NGINX_VERSION "1.29.2" #define NGINX_VERSION "1.29.3"
#define NGINX_VER "nginx/" NGINX_VERSION " by Hakase" #define NGINX_VER "nginx/" NGINX_VERSION " by Hakase"
#ifndef NGINX_SERVER #ifndef NGINX_SERVER
+29 -3
View File
@@ -1494,8 +1494,9 @@ ngx_utf8_cpystrn(u_char *dst, u_char *src, size_t n, size_t len)
uintptr_t uintptr_t
ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type) ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
{ {
ngx_uint_t n; u_char prefix;
uint32_t *escape; uint32_t *escape;
ngx_uint_t n;
static u_char hex[] = "0123456789ABCDEF"; static u_char hex[] = "0123456789ABCDEF";
/* /*
@@ -1633,11 +1634,36 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
/* mail_auth is the same as memcached */ /* mail_auth is the same as memcached */
/* " ", "+", "=", not allowed */
static uint32_t mail_xtext[] = {
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
0x20000801, /* 0010 0000 0000 0000 0000 1000 0000 0001 */
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
};
static uint32_t *map[] = static uint32_t *map[] =
{ uri, args, uri_component, html, refresh, memcached, memcached }; { uri, args, uri_component, html, refresh, memcached, memcached,
mail_xtext };
static u_char map_char[] =
{ '%', '%', '%', '%', '%', '%', '%', '+' };
escape = map[type]; escape = map[type];
prefix = map_char[type];
if (dst == NULL) { if (dst == NULL) {
@@ -1658,7 +1684,7 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
while (size) { while (size) {
if (escape[*src >> 5] & (1U << (*src & 0x1f))) { if (escape[*src >> 5] & (1U << (*src & 0x1f))) {
*dst++ = '%'; *dst++ = prefix;
*dst++ = hex[*src >> 4]; *dst++ = hex[*src >> 4];
*dst++ = hex[*src & 0xf]; *dst++ = hex[*src & 0xf];
src++; src++;
+1
View File
@@ -203,6 +203,7 @@ u_char *ngx_utf8_cpystrn(u_char *dst, u_char *src, size_t n, size_t len);
#define NGX_ESCAPE_REFRESH 4 #define NGX_ESCAPE_REFRESH 4
#define NGX_ESCAPE_MEMCACHED 5 #define NGX_ESCAPE_MEMCACHED 5
#define NGX_ESCAPE_MAIL_AUTH 6 #define NGX_ESCAPE_MAIL_AUTH 6
#define NGX_ESCAPE_MAIL_XTEXT 7
#define NGX_UNESCAPE_URI 1 #define NGX_UNESCAPE_URI 1
#define NGX_UNESCAPE_REDIRECT 2 #define NGX_UNESCAPE_REDIRECT 2
+406 -6
View File
@@ -9,6 +9,10 @@
#include <ngx_core.h> #include <ngx_core.h>
#include <ngx_event.h> #include <ngx_event.h>
#if (NGX_ZLIB && defined TLSEXT_cert_compression_zlib)
#include <zlib.h>
#endif
#define NGX_SSL_PASSWORD_BUFFER_SIZE 4096 #define NGX_SSL_PASSWORD_BUFFER_SIZE 4096
@@ -19,6 +23,13 @@ typedef struct {
static ngx_inline ngx_int_t ngx_ssl_cert_already_in_hash(void); static ngx_inline ngx_int_t ngx_ssl_cert_already_in_hash(void);
#if (NGX_ZLIB && defined TLSEXT_cert_compression_zlib)
static int ngx_ssl_cert_compression_callback(ngx_ssl_conn_t *ssl_conn,
CBB *out, const uint8_t *in, size_t in_len);
static void *ngx_ssl_cert_compression_alloc(void *opaque, u_int items,
u_int size);
static void ngx_ssl_cert_compression_free(void *opaque, void *address);
#endif
static int ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store); static int ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where,
int ret); int ret);
@@ -128,6 +139,8 @@ int ngx_ssl_ticket_keys_index;
int ngx_ssl_ocsp_index; int ngx_ssl_ocsp_index;
int ngx_ssl_index; int ngx_ssl_index;
int ngx_ssl_certificate_name_index; int ngx_ssl_certificate_name_index;
int ngx_ssl_certificate_comp_index;
int ngx_ssl_client_hello_arg_index;
u_char ngx_ssl_session_buffer[NGX_SSL_MAX_SESSION_SIZE]; u_char ngx_ssl_session_buffer[NGX_SSL_MAX_SESSION_SIZE];
@@ -270,6 +283,21 @@ ngx_ssl_init(ngx_log_t *log)
return NGX_ERROR; return NGX_ERROR;
} }
ngx_ssl_certificate_comp_index = X509_get_ex_new_index(0, NULL, NULL, NULL,
NULL);
if (ngx_ssl_certificate_comp_index == -1) {
ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed");
return NGX_ERROR;
}
ngx_ssl_client_hello_arg_index = SSL_CTX_get_ex_new_index(0, NULL, NULL,
NULL, NULL);
if (ngx_ssl_client_hello_arg_index == -1) {
ngx_ssl_error(NGX_LOG_ALERT, log, 0,
"SSL_CTX_get_ex_new_index() failed");
return NGX_ERROR;
}
return NGX_OK; return NGX_OK;
} }
@@ -449,10 +477,18 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
{ {
char *err; char *err;
X509 *x509, **elm; X509 *x509, **elm;
u_long n;
EVP_PKEY *pkey; EVP_PKEY *pkey;
ngx_uint_t mask;
STACK_OF(X509) *chain; STACK_OF(X509) *chain;
chain = ngx_ssl_cache_fetch(cf, NGX_SSL_CACHE_CERT, &err, cert, NULL); mask = 0;
elm = NULL;
retry:
chain = ngx_ssl_cache_fetch(cf, NGX_SSL_CACHE_CERT | mask,
&err, cert, NULL);
if (chain == NULL) { if (chain == NULL) {
if (err != NULL) { if (err != NULL) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
@@ -492,6 +528,7 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
} }
} }
if (elm == NULL) {
elm = ngx_array_push(&ssl->certs); elm = ngx_array_push(&ssl->certs);
if (elm == NULL) { if (elm == NULL) {
X509_free(x509); X509_free(x509);
@@ -499,6 +536,10 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
return NGX_ERROR; return NGX_ERROR;
} }
} else {
X509_free(*elm);
}
*elm = x509; *elm = x509;
/* /*
@@ -519,11 +560,21 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
} }
#else #else
{
int n;
/* SSL_CTX_set0_chain() is only available in OpenSSL 1.0.2+ */ /* SSL_CTX_set0_chain() is only available in OpenSSL 1.0.2+ */
#ifdef SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS
/* OpenSSL 1.0.1+ */
SSL_CTX_clear_extra_chain_certs(ssl->ctx);
#else
if (ssl->ctx->extra_certs) {
sk_X509_pop_free(ssl->ctx->extra_certs, X509_free);
ssl->ctx->extra_certs = NULL;
}
#endif
n = sk_X509_num(chain); n = sk_X509_num(chain);
while (n--) { while (n--) {
@@ -539,10 +590,11 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
} }
sk_X509_free(chain); sk_X509_free(chain);
}
#endif #endif
pkey = ngx_ssl_cache_fetch(cf, NGX_SSL_CACHE_PKEY, &err, key, passwords); pkey = ngx_ssl_cache_fetch(cf, NGX_SSL_CACHE_PKEY | mask,
&err, key, passwords);
if (pkey == NULL) { if (pkey == NULL) {
if (err != NULL) { if (err != NULL) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
@@ -554,9 +606,23 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
} }
if (SSL_CTX_use_PrivateKey(ssl->ctx, pkey) == 0) { if (SSL_CTX_use_PrivateKey(ssl->ctx, pkey) == 0) {
EVP_PKEY_free(pkey);
/* there can be mismatched pairs on uneven cache update */
n = ERR_peek_last_error();
if (ERR_GET_LIB(n) == ERR_LIB_X509
&& ERR_GET_REASON(n) == X509_R_KEY_VALUES_MISMATCH
&& mask == 0)
{
ERR_clear_error();
mask = NGX_SSL_CACHE_INVALIDATE;
goto retry;
}
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_use_PrivateKey(\"%s\") failed", key->data); "SSL_CTX_use_PrivateKey(\"%s\") failed", key->data);
EVP_PKEY_free(pkey);
return NGX_ERROR; return NGX_ERROR;
} }
@@ -682,6 +748,18 @@ ngx_ssl_certificate_compression(ngx_conf_t *cf, ngx_ssl_t *ssl,
SSL_CTX_clear_options(ssl->ctx, SSL_OP_NO_TX_CERTIFICATE_COMPRESSION); SSL_CTX_clear_options(ssl->ctx, SSL_OP_NO_TX_CERTIFICATE_COMPRESSION);
#elif (NGX_ZLIB && defined TLSEXT_cert_compression_zlib)
if (SSL_CTX_add_cert_compression_alg(ssl->ctx, TLSEXT_cert_compression_zlib,
ngx_ssl_cert_compression_callback,
NULL)
== 0)
{
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_add_cert_compression_alg() failed");
return NGX_ERROR;
}
#else #else
ngx_log_error(NGX_LOG_WARN, ssl->log, 0, ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
@@ -694,6 +772,155 @@ ngx_ssl_certificate_compression(ngx_conf_t *cf, ngx_ssl_t *ssl,
} }
#if (NGX_ZLIB && defined TLSEXT_cert_compression_zlib)
static int
ngx_ssl_cert_compression_callback(ngx_ssl_conn_t *ssl_conn, CBB *out,
const uint8_t *in, size_t in_len)
{
int rc;
X509 *cert;
u_char *p;
z_stream zstream;
ngx_str_t *comp, tmp;
ngx_pool_t *pool;
ngx_connection_t *c;
#ifdef OPENSSL_IS_BORINGSSL
{
SSL_CTX *ssl_ctx;
ngx_ssl_t *ssl;
/* BoringSSL doesn't have certificate slots, we take the last set */
ssl_ctx = SSL_get_SSL_CTX(ssl_conn);
ssl = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_index);
cert = ((X509 **) ssl->certs.elts)[ssl->certs.nelts - 1];
}
#else
/*
* AWS-LC saves leaf certificate in SSL to associate with SSL_CTX,
* see https://github.com/aws/aws-lc/commit/e1ba2b3e5
*/
cert = SSL_get_certificate(ssl_conn);
#endif
comp = X509_get_ex_data(cert, ngx_ssl_certificate_comp_index);
if (comp != NULL) {
return CBB_add_bytes(out, comp->data, comp->len);
}
c = ngx_ssl_get_connection(ssl_conn);
pool = ngx_create_pool(256, c->log);
if (pool == NULL) {
return 0;
}
pool->log = c->log;
ngx_memzero(&zstream, sizeof(z_stream));
zstream.zalloc = ngx_ssl_cert_compression_alloc;
zstream.zfree = ngx_ssl_cert_compression_free;
zstream.opaque = pool;
rc = deflateInit(&zstream, Z_DEFAULT_COMPRESSION);
if (rc != Z_OK) {
ngx_log_error(NGX_LOG_ALERT, c->log, 0, "deflateInit() failed: %d", rc);
goto error;
}
tmp.len = deflateBound(&zstream, in_len);
tmp.data = ngx_palloc(pool, tmp.len);
if (tmp.data == NULL) {
goto error;
}
zstream.next_in = (u_char *) in;
zstream.avail_in = in_len;
zstream.next_out = tmp.data;
zstream.avail_out = tmp.len;
rc = deflate(&zstream, Z_FINISH);
if (rc != Z_STREAM_END) {
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
"deflate(Z_FINISH) failed: %d", rc);
goto error;
}
tmp.len -= zstream.avail_out;
rc = deflateEnd(&zstream);
if (rc != Z_OK) {
ngx_log_error(NGX_LOG_ALERT, c->log, 0, "deflateEnd() failed: %d", rc);
goto error;
}
p = ngx_alloc(sizeof(ngx_str_t) + tmp.len, c->log);
if (p == NULL) {
goto error;
}
comp = (ngx_str_t *) p;
comp->len = tmp.len;
comp->data = p + sizeof(ngx_str_t);
ngx_memcpy(comp->data, tmp.data, tmp.len);
if (X509_set_ex_data(cert, ngx_ssl_certificate_comp_index, p) == 0) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_set_ex_data() failed");
ngx_free(p);
}
rc = CBB_add_bytes(out, tmp.data, tmp.len);
ngx_destroy_pool(pool);
return rc;
error:
ngx_destroy_pool(pool);
return 0;
}
static void *
ngx_ssl_cert_compression_alloc(void *opaque, u_int items, u_int size)
{
ngx_pool_t *pool = opaque;
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pool->log, 0,
"cert compression alloc: n:%ud s:%ud", items, size);
return ngx_palloc(pool, items * size);
}
static void
ngx_ssl_cert_compression_free(void *opaque, void *address)
{
#if 0
ngx_pool_t *pool = opaque;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pool->log, 0,
"cert compression free: %p", address);
#endif
}
#endif
ngx_int_t ngx_int_t
ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers, ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers,
ngx_uint_t prefer_server_ciphers) ngx_uint_t prefer_server_ciphers)
@@ -1645,6 +1872,118 @@ ngx_ssl_new_client_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
} }
void
ngx_ssl_set_client_hello_callback(SSL_CTX *ssl_ctx,
ngx_ssl_client_hello_arg *cb)
{
#ifdef SSL_CLIENT_HELLO_SUCCESS
SSL_CTX_set_client_hello_cb(ssl_ctx, ngx_ssl_client_hello_callback, NULL);
SSL_CTX_set_ex_data(ssl_ctx, ngx_ssl_client_hello_arg_index, cb);
#elif defined OPENSSL_IS_BORINGSSL
SSL_CTX_set_select_certificate_cb(ssl_ctx, ngx_ssl_select_certificate);
SSL_CTX_set_ex_data(ssl_ctx, ngx_ssl_client_hello_arg_index, cb);
#endif
}
#ifdef SSL_CLIENT_HELLO_SUCCESS
int
ngx_ssl_client_hello_callback(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
{
u_char *p;
size_t len;
ngx_int_t rc;
ngx_str_t host;
ngx_connection_t *c;
ngx_ssl_client_hello_arg *cb;
c = ngx_ssl_get_connection(ssl_conn);
cb = SSL_CTX_get_ex_data(c->ssl->session_ctx,
ngx_ssl_client_hello_arg_index);
if (SSL_client_hello_get0_ext(ssl_conn, TLSEXT_TYPE_server_name,
(const unsigned char **) &p, &len)
== 0)
{
ngx_str_null(&host);
goto done;
}
/*
* RFC 6066 mandates non-zero HostName length, we follow OpenSSL.
* No more than one ServerName is expected.
*/
if (len < 5
|| (size_t) (p[0] << 8) + p[1] + 2 != len
|| p[2] != TLSEXT_NAMETYPE_host_name
|| (size_t) (p[3] << 8) + p[4] + 2 + 3 != len)
{
*ad = SSL_AD_DECODE_ERROR;
return SSL_CLIENT_HELLO_ERROR;
}
len -= 5;
p += 5;
if (len > TLSEXT_MAXLEN_host_name || ngx_strlchr(p, p + len, '\0')) {
*ad = SSL_AD_UNRECOGNIZED_NAME;
return SSL_CLIENT_HELLO_ERROR;
}
host.len = len;
host.data = p;
done:
rc = cb->servername(ssl_conn, ad, &host);
if (rc == SSL_TLSEXT_ERR_ALERT_FATAL) {
return SSL_CLIENT_HELLO_ERROR;
}
return SSL_CLIENT_HELLO_SUCCESS;
}
#elif defined OPENSSL_IS_BORINGSSL
enum ssl_select_cert_result_t ngx_ssl_select_certificate(
const SSL_CLIENT_HELLO *client_hello)
{
int ad;
ngx_int_t rc;
ngx_ssl_conn_t *ssl_conn;
ngx_connection_t *c;
ngx_ssl_client_hello_arg *cb;
ssl_conn = client_hello->ssl;
c = ngx_ssl_get_connection(ssl_conn);
cb = SSL_CTX_get_ex_data(c->ssl->session_ctx,
ngx_ssl_client_hello_arg_index);
/*
* BoringSSL sends a hardcoded "handshake_failure" alert on errors,
* we use it to map SSL_AD_INTERNAL_ERROR. To preserve other alert
* values, error handling is postponed to the servername callback.
*/
rc = cb->servername(ssl_conn, &ad, NULL);
if (rc == SSL_TLSEXT_ERR_ALERT_FATAL && ad == SSL_AD_INTERNAL_ERROR) {
return ssl_select_cert_error;
}
return ssl_select_cert_success;
}
#endif
ngx_int_t ngx_int_t
ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags) ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
{ {
@@ -4831,10 +5170,19 @@ ngx_ssl_cleanup_ctx(void *data)
ngx_ssl_t *ssl = data; ngx_ssl_t *ssl = data;
X509 *cert; X509 *cert;
u_char *p;
ngx_uint_t i; ngx_uint_t i;
for (i = 0; i < ssl->certs.nelts; i++) { for (i = 0; i < ssl->certs.nelts; i++) {
cert = ((X509 **) ssl->certs.elts)[i]; cert = ((X509 **) ssl->certs.elts)[i];
p = X509_get_ex_data(cert, ngx_ssl_certificate_comp_index);
if (p) {
ngx_free(p);
X509_set_ex_data(cert, ngx_ssl_certificate_comp_index, NULL);
}
X509_free(cert); X509_free(cert);
} }
@@ -5231,6 +5579,32 @@ ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
} }
ngx_int_t
ngx_ssl_get_sigalg(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
{
#ifdef SSL_get0_signature_name
const char *name;
if (SSL_get0_signature_name(c->ssl->connection, &name)) {
s->len = ngx_strlen(name);
s->data = ngx_pnalloc(pool, s->len);
if (s->data == NULL) {
return NGX_ERROR;
}
ngx_memcpy(s->data, name, s->len);
return NGX_OK;
}
#endif
s->len = 0;
return NGX_OK;
}
ngx_int_t ngx_int_t
ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
{ {
@@ -5976,6 +6350,32 @@ ngx_ssl_parse_time(
} }
ngx_int_t
ngx_ssl_get_client_sigalg(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
{
#ifdef SSL_get0_peer_signature_name
const char *name;
if (SSL_get0_peer_signature_name(c->ssl->connection, &name)) {
s->len = ngx_strlen(name);
s->data = ngx_pnalloc(pool, s->len);
if (s->data == NULL) {
return NGX_ERROR;
}
ngx_memcpy(s->data, name, s->len);
return NGX_OK;
}
#endif
s->len = 0;
return NGX_OK;
}
static void * static void *
ngx_openssl_create_conf(ngx_cycle_t *cycle) ngx_openssl_create_conf(ngx_cycle_t *cycle)
{ {
+23 -8
View File
@@ -26,14 +26,6 @@
#include <openssl/engine.h> #include <openssl/engine.h>
#endif #endif
#include <openssl/evp.h> #include <openssl/evp.h>
#if (NGX_QUIC)
#ifdef OPENSSL_IS_BORINGSSL
#include <openssl/hkdf.h>
#include <openssl/chacha.h>
#else
#include <openssl/kdf.h>
#endif
#endif
#include <openssl/hmac.h> #include <openssl/hmac.h>
#ifndef OPENSSL_NO_OCSP #ifndef OPENSSL_NO_OCSP
#include <openssl/ocsp.h> #include <openssl/ocsp.h>
@@ -161,6 +153,7 @@ struct ngx_ssl_connection_s {
unsigned in_ocsp:1; unsigned in_ocsp:1;
unsigned early_preread:1; unsigned early_preread:1;
unsigned write_blocked:1; unsigned write_blocked:1;
unsigned sni_accepted:1;
ngx_ssl_dyn_rec_t dyn_rec; ngx_ssl_dyn_rec_t dyn_rec;
ngx_msec_t dyn_rec_last_write; ngx_msec_t dyn_rec_last_write;
@@ -211,6 +204,13 @@ typedef struct {
} ngx_ssl_session_cache_t; } ngx_ssl_session_cache_t;
typedef int (*ngx_ssl_servername_pt)(ngx_ssl_conn_t *, int *, void *);
typedef struct {
ngx_ssl_servername_pt servername;
} ngx_ssl_client_hello_arg;
#define NGX_SSL_SSLv2 0x0002 #define NGX_SSL_SSLv2 0x0002
#define NGX_SSL_SSLv3 0x0004 #define NGX_SSL_SSLv3 0x0004
#define NGX_SSL_TLSv1 0x0008 #define NGX_SSL_TLSv1 0x0008
@@ -300,6 +300,15 @@ ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_array_t *paths); ngx_array_t *paths);
ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data);
void ngx_ssl_set_client_hello_callback(SSL_CTX *ssl_ctx,
ngx_ssl_client_hello_arg *cb);
#ifdef SSL_CLIENT_HELLO_SUCCESS
int ngx_ssl_client_hello_callback(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg);
#elif defined OPENSSL_IS_BORINGSSL
enum ssl_select_cert_result_t ngx_ssl_select_certificate(
const SSL_CLIENT_HELLO *client_hello);
#endif
ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c,
ngx_uint_t flags); ngx_uint_t flags);
@@ -333,6 +342,8 @@ ngx_int_t ngx_ssl_get_curve(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s); ngx_str_t *s);
ngx_int_t ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_int_t ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s); ngx_str_t *s);
ngx_int_t ngx_ssl_get_sigalg(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s);
ngx_int_t ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_int_t ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s); ngx_str_t *s);
ngx_int_t ngx_ssl_get_session_reused(ngx_connection_t *c, ngx_pool_t *pool, ngx_int_t ngx_ssl_get_session_reused(ngx_connection_t *c, ngx_pool_t *pool,
@@ -369,6 +380,8 @@ ngx_int_t ngx_ssl_get_client_v_end(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s); ngx_str_t *s);
ngx_int_t ngx_ssl_get_client_v_remain(ngx_connection_t *c, ngx_pool_t *pool, ngx_int_t ngx_ssl_get_client_v_remain(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s); ngx_str_t *s);
ngx_int_t ngx_ssl_get_client_sigalg(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s);
ngx_int_t ngx_ssl_handshake(ngx_connection_t *c); ngx_int_t ngx_ssl_handshake(ngx_connection_t *c);
@@ -396,6 +409,8 @@ extern int ngx_ssl_ticket_keys_index;
extern int ngx_ssl_ocsp_index; extern int ngx_ssl_ocsp_index;
extern int ngx_ssl_index; extern int ngx_ssl_index;
extern int ngx_ssl_certificate_name_index; extern int ngx_ssl_certificate_name_index;
extern int ngx_ssl_certificate_comp_index;
extern int ngx_ssl_client_hello_arg_index;
extern u_char ngx_ssl_session_buffer[NGX_SSL_MAX_SESSION_SIZE]; extern u_char ngx_ssl_session_buffer[NGX_SSL_MAX_SESSION_SIZE];
+14 -1
View File
@@ -193,6 +193,7 @@ ngx_ssl_cache_fetch(ngx_conf_t *cf, ngx_uint_t index, char **err,
time_t mtime; time_t mtime;
uint32_t hash; uint32_t hash;
ngx_int_t rc; ngx_int_t rc;
ngx_uint_t invalidate;
ngx_file_uniq_t uniq; ngx_file_uniq_t uniq;
ngx_file_info_t fi; ngx_file_info_t fi;
ngx_ssl_cache_t *cache, *old_cache; ngx_ssl_cache_t *cache, *old_cache;
@@ -202,10 +203,17 @@ ngx_ssl_cache_fetch(ngx_conf_t *cf, ngx_uint_t index, char **err,
*err = NULL; *err = NULL;
invalidate = index & NGX_SSL_CACHE_INVALIDATE;
index &= ~NGX_SSL_CACHE_INVALIDATE;
if (ngx_ssl_cache_init_key(cf->pool, index, path, &id) != NGX_OK) { if (ngx_ssl_cache_init_key(cf->pool, index, path, &id) != NGX_OK) {
return NULL; return NULL;
} }
if (id.type == NGX_SSL_CACHE_DATA) {
invalidate = 0;
}
cache = (ngx_ssl_cache_t *) ngx_get_conf(cf->cycle->conf_ctx, cache = (ngx_ssl_cache_t *) ngx_get_conf(cf->cycle->conf_ctx,
ngx_openssl_cache_module); ngx_openssl_cache_module);
@@ -215,9 +223,14 @@ ngx_ssl_cache_fetch(ngx_conf_t *cf, ngx_uint_t index, char **err,
cn = ngx_ssl_cache_lookup(cache, type, &id, hash); cn = ngx_ssl_cache_lookup(cache, type, &id, hash);
if (cn != NULL) { if (cn != NULL) {
if (!invalidate) {
return type->ref(err, cn->value); return type->ref(err, cn->value);
} }
type->free(cn->value);
ngx_rbtree_delete(&cache->rbtree, &cn->node);
}
value = NULL; value = NULL;
if (id.type == NGX_SSL_CACHE_PATH if (id.type == NGX_SSL_CACHE_PATH
@@ -236,7 +249,7 @@ ngx_ssl_cache_fetch(ngx_conf_t *cf, ngx_uint_t index, char **err,
old_cache = ngx_ssl_cache_get_old_conf(cf->cycle); old_cache = ngx_ssl_cache_get_old_conf(cf->cycle);
if (old_cache && old_cache->inheritable) { if (old_cache && old_cache->inheritable && !invalidate) {
cn = ngx_ssl_cache_lookup(old_cache, type, &id, hash); cn = ngx_ssl_cache_lookup(old_cache, type, &id, hash);
if (cn != NULL) { if (cn != NULL) {
+2 -1
View File
@@ -18,7 +18,8 @@
#elif (defined SSL_R_MISSING_QUIC_TRANSPORT_PARAMETERS_EXTENSION) #elif (defined SSL_R_MISSING_QUIC_TRANSPORT_PARAMETERS_EXTENSION)
#define NGX_QUIC_QUICTLS_API 1 #define NGX_QUIC_QUICTLS_API 1
#elif (defined OPENSSL_IS_BORINGSSL || defined LIBRESSL_VERSION_NUMBER) #elif (defined OPENSSL_IS_BORINGSSL || defined OPENSSL_IS_AWSLC \
|| defined LIBRESSL_VERSION_NUMBER)
#define NGX_QUIC_BORINGSSL_API 1 #define NGX_QUIC_BORINGSSL_API 1
#else #else
+21 -15
View File
@@ -8,6 +8,12 @@
#include <ngx_core.h> #include <ngx_core.h>
#include <ngx_event.h> #include <ngx_event.h>
#include <ngx_event_quic_connection.h> #include <ngx_event_quic_connection.h>
#if (NGX_QUIC_BORINGSSL_EVP_API)
#include <openssl/hkdf.h>
#include <openssl/chacha.h>
#else
#include <openssl/kdf.h>
#endif
/* RFC 9001, 5.4.1. Header Protection Application: 5-byte mask */ /* RFC 9001, 5.4.1. Header Protection Application: 5-byte mask */
@@ -33,7 +39,7 @@ static uint64_t ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask,
static ngx_int_t ngx_quic_crypto_open(ngx_quic_secret_t *s, ngx_str_t *out, static ngx_int_t ngx_quic_crypto_open(ngx_quic_secret_t *s, ngx_str_t *out,
const u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log); const u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log);
#ifndef OPENSSL_IS_BORINGSSL #if !(NGX_QUIC_BORINGSSL_EVP_API)
static ngx_int_t ngx_quic_crypto_common(ngx_quic_secret_t *s, ngx_str_t *out, static ngx_int_t ngx_quic_crypto_common(ngx_quic_secret_t *s, ngx_str_t *out,
const u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log); const u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log);
#endif #endif
@@ -58,7 +64,7 @@ ngx_quic_ciphers(ngx_uint_t id, ngx_quic_ciphers_t *ciphers)
switch (id) { switch (id) {
case TLS1_3_CK_AES_128_GCM_SHA256: case TLS1_3_CK_AES_128_GCM_SHA256:
#ifdef OPENSSL_IS_BORINGSSL #if (NGX_QUIC_BORINGSSL_EVP_API)
ciphers->c = EVP_aead_aes_128_gcm(); ciphers->c = EVP_aead_aes_128_gcm();
#else #else
ciphers->c = EVP_aes_128_gcm(); ciphers->c = EVP_aes_128_gcm();
@@ -69,7 +75,7 @@ ngx_quic_ciphers(ngx_uint_t id, ngx_quic_ciphers_t *ciphers)
break; break;
case TLS1_3_CK_AES_256_GCM_SHA384: case TLS1_3_CK_AES_256_GCM_SHA384:
#ifdef OPENSSL_IS_BORINGSSL #if (NGX_QUIC_BORINGSSL_EVP_API)
ciphers->c = EVP_aead_aes_256_gcm(); ciphers->c = EVP_aead_aes_256_gcm();
#else #else
ciphers->c = EVP_aes_256_gcm(); ciphers->c = EVP_aes_256_gcm();
@@ -80,12 +86,12 @@ ngx_quic_ciphers(ngx_uint_t id, ngx_quic_ciphers_t *ciphers)
break; break;
case TLS1_3_CK_CHACHA20_POLY1305_SHA256: case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
#ifdef OPENSSL_IS_BORINGSSL #if (NGX_QUIC_BORINGSSL_EVP_API)
ciphers->c = EVP_aead_chacha20_poly1305(); ciphers->c = EVP_aead_chacha20_poly1305();
#else #else
ciphers->c = EVP_chacha20_poly1305(); ciphers->c = EVP_chacha20_poly1305();
#endif #endif
#ifdef OPENSSL_IS_BORINGSSL #if (NGX_QUIC_BORINGSSL_EVP_API)
ciphers->hp = (const EVP_CIPHER *) EVP_aead_chacha20_poly1305(); ciphers->hp = (const EVP_CIPHER *) EVP_aead_chacha20_poly1305();
#else #else
ciphers->hp = EVP_chacha20(); ciphers->hp = EVP_chacha20();
@@ -94,7 +100,7 @@ ngx_quic_ciphers(ngx_uint_t id, ngx_quic_ciphers_t *ciphers)
len = 32; len = 32;
break; break;
#ifndef OPENSSL_IS_BORINGSSL #if !(NGX_QUIC_BORINGSSL_EVP_API)
case TLS1_3_CK_AES_128_CCM_SHA256: case TLS1_3_CK_AES_128_CCM_SHA256:
ciphers->c = EVP_aes_128_ccm(); ciphers->c = EVP_aes_128_ccm();
ciphers->hp = EVP_aes_128_ctr(); ciphers->hp = EVP_aes_128_ctr();
@@ -263,7 +269,7 @@ static ngx_int_t
ngx_hkdf_expand(u_char *out_key, size_t out_len, const EVP_MD *digest, ngx_hkdf_expand(u_char *out_key, size_t out_len, const EVP_MD *digest,
const uint8_t *prk, size_t prk_len, const u_char *info, size_t info_len) const uint8_t *prk, size_t prk_len, const u_char *info, size_t info_len)
{ {
#ifdef OPENSSL_IS_BORINGSSL #if (NGX_QUIC_BORINGSSL_EVP_API)
if (HKDF_expand(out_key, out_len, digest, prk, prk_len, info, info_len) if (HKDF_expand(out_key, out_len, digest, prk, prk_len, info, info_len)
== 0) == 0)
@@ -325,7 +331,7 @@ ngx_hkdf_extract(u_char *out_key, size_t *out_len, const EVP_MD *digest,
const u_char *secret, size_t secret_len, const u_char *salt, const u_char *secret, size_t secret_len, const u_char *salt,
size_t salt_len) size_t salt_len)
{ {
#ifdef OPENSSL_IS_BORINGSSL #if (NGX_QUIC_BORINGSSL_EVP_API)
if (HKDF_extract(out_key, out_len, digest, secret, secret_len, salt, if (HKDF_extract(out_key, out_len, digest, secret, secret_len, salt,
salt_len) salt_len)
@@ -388,7 +394,7 @@ ngx_quic_crypto_init(const ngx_quic_cipher_t *cipher, ngx_quic_secret_t *s,
ngx_quic_md_t *key, ngx_int_t enc, ngx_log_t *log) ngx_quic_md_t *key, ngx_int_t enc, ngx_log_t *log)
{ {
#ifdef OPENSSL_IS_BORINGSSL #if (NGX_QUIC_BORINGSSL_EVP_API)
EVP_AEAD_CTX *ctx; EVP_AEAD_CTX *ctx;
ctx = EVP_AEAD_CTX_new(cipher, key->data, key->len, ctx = EVP_AEAD_CTX_new(cipher, key->data, key->len,
@@ -448,7 +454,7 @@ static ngx_int_t
ngx_quic_crypto_open(ngx_quic_secret_t *s, ngx_str_t *out, const u_char *nonce, ngx_quic_crypto_open(ngx_quic_secret_t *s, ngx_str_t *out, const u_char *nonce,
ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log) ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log)
{ {
#ifdef OPENSSL_IS_BORINGSSL #if (NGX_QUIC_BORINGSSL_EVP_API)
if (EVP_AEAD_CTX_open(s->ctx, out->data, &out->len, out->len, nonce, if (EVP_AEAD_CTX_open(s->ctx, out->data, &out->len, out->len, nonce,
s->iv.len, in->data, in->len, ad->data, ad->len) s->iv.len, in->data, in->len, ad->data, ad->len)
!= 1) != 1)
@@ -468,7 +474,7 @@ ngx_int_t
ngx_quic_crypto_seal(ngx_quic_secret_t *s, ngx_str_t *out, const u_char *nonce, ngx_quic_crypto_seal(ngx_quic_secret_t *s, ngx_str_t *out, const u_char *nonce,
ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log) ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log)
{ {
#ifdef OPENSSL_IS_BORINGSSL #if (NGX_QUIC_BORINGSSL_EVP_API)
if (EVP_AEAD_CTX_seal(s->ctx, out->data, &out->len, out->len, nonce, if (EVP_AEAD_CTX_seal(s->ctx, out->data, &out->len, out->len, nonce,
s->iv.len, in->data, in->len, ad->data, ad->len) s->iv.len, in->data, in->len, ad->data, ad->len)
!= 1) != 1)
@@ -484,7 +490,7 @@ ngx_quic_crypto_seal(ngx_quic_secret_t *s, ngx_str_t *out, const u_char *nonce,
} }
#ifndef OPENSSL_IS_BORINGSSL #if !(NGX_QUIC_BORINGSSL_EVP_API)
static ngx_int_t static ngx_int_t
ngx_quic_crypto_common(ngx_quic_secret_t *s, ngx_str_t *out, ngx_quic_crypto_common(ngx_quic_secret_t *s, ngx_str_t *out,
@@ -563,7 +569,7 @@ void
ngx_quic_crypto_cleanup(ngx_quic_secret_t *s) ngx_quic_crypto_cleanup(ngx_quic_secret_t *s)
{ {
if (s->ctx) { if (s->ctx) {
#ifdef OPENSSL_IS_BORINGSSL #if (NGX_QUIC_BORINGSSL_EVP_API)
EVP_AEAD_CTX_free(s->ctx); EVP_AEAD_CTX_free(s->ctx);
#else #else
EVP_CIPHER_CTX_free(s->ctx); EVP_CIPHER_CTX_free(s->ctx);
@@ -579,7 +585,7 @@ ngx_quic_crypto_hp_init(const EVP_CIPHER *cipher, ngx_quic_secret_t *s,
{ {
EVP_CIPHER_CTX *ctx; EVP_CIPHER_CTX *ctx;
#ifdef OPENSSL_IS_BORINGSSL #if (NGX_QUIC_BORINGSSL_EVP_API)
if (cipher == (EVP_CIPHER *) EVP_aead_chacha20_poly1305()) { if (cipher == (EVP_CIPHER *) EVP_aead_chacha20_poly1305()) {
/* no EVP interface */ /* no EVP interface */
s->hp_ctx = NULL; s->hp_ctx = NULL;
@@ -615,7 +621,7 @@ ngx_quic_crypto_hp(ngx_quic_secret_t *s, u_char *out, u_char *in,
ctx = s->hp_ctx; ctx = s->hp_ctx;
#ifdef OPENSSL_IS_BORINGSSL #if (NGX_QUIC_BORINGSSL_EVP_API)
uint32_t cnt; uint32_t cnt;
if (ctx == NULL) { if (ctx == NULL) {
+3 -1
View File
@@ -22,10 +22,12 @@
#define NGX_QUIC_MAX_MD_SIZE 48 #define NGX_QUIC_MAX_MD_SIZE 48
#ifdef OPENSSL_IS_BORINGSSL #if (defined OPENSSL_IS_BORINGSSL || defined OPENSSL_IS_AWSLC)
#define NGX_QUIC_BORINGSSL_EVP_API 1
#define ngx_quic_cipher_t EVP_AEAD #define ngx_quic_cipher_t EVP_AEAD
#define ngx_quic_crypto_ctx_t EVP_AEAD_CTX #define ngx_quic_crypto_ctx_t EVP_AEAD_CTX
#else #else
#define NGX_QUIC_BORINGSSL_EVP_API 0
#define ngx_quic_cipher_t EVP_CIPHER #define ngx_quic_cipher_t EVP_CIPHER
#define ngx_quic_crypto_ctx_t EVP_CIPHER_CTX #define ngx_quic_crypto_ctx_t EVP_CIPHER_CTX
#endif #endif
+13 -8
View File
@@ -695,30 +695,35 @@ ngx_quic_handshake(ngx_connection_t *c)
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
if (qc->error) {
return NGX_ERROR;
}
if (n <= 0) { if (n <= 0) {
sslerr = SSL_get_error(ssl_conn, n); sslerr = SSL_get_error(ssl_conn, n);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d",
sslerr); sslerr);
if (sslerr != SSL_ERROR_WANT_READ) {
if (c->ssl->handshake_rejected) { if (c->ssl->handshake_rejected) {
ngx_connection_error(c, 0, "handshake rejected"); ngx_connection_error(c, 0, "handshake rejected");
ERR_clear_error(); ERR_clear_error();
return NGX_ERROR; return NGX_ERROR;
} }
if (qc->error) {
ngx_connection_error(c, 0, "SSL_do_handshake() failed");
ERR_clear_error();
return NGX_ERROR;
}
if (sslerr != SSL_ERROR_WANT_READ) {
ngx_ssl_connection_error(c, sslerr, 0, "SSL_do_handshake() failed"); ngx_ssl_connection_error(c, sslerr, 0, "SSL_do_handshake() failed");
return NGX_ERROR; return NGX_ERROR;
} }
} }
if (qc->error) {
ngx_connection_error(c, 0, "SSL_do_handshake() failed");
return NGX_ERROR;
}
if (!SSL_is_init_finished(ssl_conn)) { if (!SSL_is_init_finished(ssl_conn)) {
if (ngx_quic_keys_available(qc->keys, NGX_QUIC_ENCRYPTION_EARLY_DATA, 0) if (ngx_quic_keys_available(qc->keys, NGX_QUIC_ENCRYPTION_EARLY_DATA, 0)
&& qc->client_tp_done) && qc->client_tp_done)
@@ -968,7 +973,7 @@ ngx_quic_init_connection(ngx_connection_t *c)
} }
#endif #endif
#ifdef OPENSSL_IS_BORINGSSL #if (defined OPENSSL_IS_BORINGSSL || defined OPENSSL_IS_AWSLC)
if (SSL_set_quic_early_data_context(ssl_conn, p, clen) == 0) { if (SSL_set_quic_early_data_context(ssl_conn, p, clen) == 0) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
"quic SSL_set_quic_early_data_context() failed"); "quic SSL_set_quic_early_data_context() failed");
@@ -66,7 +66,9 @@ ngx_http_chunked_header_filter(ngx_http_request_t *r)
|| r->headers_out.status == NGX_HTTP_NO_CONTENT || r->headers_out.status == NGX_HTTP_NO_CONTENT
|| r->headers_out.status < NGX_HTTP_OK || r->headers_out.status < NGX_HTTP_OK
|| r != r->main || r != r->main
|| r->method == NGX_HTTP_HEAD) || r->method == NGX_HTTP_HEAD
|| (r->method == NGX_HTTP_CONNECT
&& r->headers_out.status < NGX_HTTP_SPECIAL_RESPONSE))
{ {
return ngx_http_next_header_filter(r); return ngx_http_next_header_filter(r);
} }
+12
View File
@@ -63,6 +63,7 @@ typedef struct {
unsigned allow_binary_include:1; unsigned allow_binary_include:1;
unsigned binary_include:1; unsigned binary_include:1;
unsigned proxy_recursive:1; unsigned proxy_recursive:1;
unsigned no_cacheable:1;
} ngx_http_geo_conf_ctx_t; } ngx_http_geo_conf_ctx_t;
@@ -463,6 +464,7 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+ sizeof(ngx_http_variable_value_t) + sizeof(ngx_http_variable_value_t)
+ 0x10000 * sizeof(ngx_http_geo_range_t *); + 0x10000 * sizeof(ngx_http_geo_range_t *);
ctx.allow_binary_include = 1; ctx.allow_binary_include = 1;
ctx.no_cacheable = 0;
save = *cf; save = *cf;
cf->pool = pool; cf->pool = pool;
@@ -478,6 +480,10 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
goto failed; goto failed;
} }
if (ctx.no_cacheable) {
var->flags |= NGX_HTTP_VAR_NOCACHEABLE;
}
geo->proxies = ctx.proxies; geo->proxies = ctx.proxies;
geo->proxy_recursive = ctx.proxy_recursive; geo->proxy_recursive = ctx.proxy_recursive;
@@ -623,6 +629,12 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
rv = NGX_CONF_OK; rv = NGX_CONF_OK;
goto done; goto done;
} }
else if (ngx_strcmp(value[0].data, "volatile") == 0) {
ctx->no_cacheable = 1;
rv = NGX_CONF_OK;
goto done;
}
} }
if (cf->args->nelts != 2) { if (cf->args->nelts != 2) {
@@ -10,6 +10,11 @@
#include <ngx_http.h> #include <ngx_http.h>
#define NGX_HTTP_HEADERS_INHERIT_OFF 0
#define NGX_HTTP_HEADERS_INHERIT_ON 1
#define NGX_HTTP_HEADERS_INHERIT_MERGE 2
typedef struct ngx_http_header_val_s ngx_http_header_val_t; typedef struct ngx_http_header_val_s ngx_http_header_val_t;
typedef ngx_int_t (*ngx_http_set_header_pt)(ngx_http_request_t *r, typedef ngx_int_t (*ngx_http_set_header_pt)(ngx_http_request_t *r,
@@ -49,6 +54,8 @@ typedef struct {
ngx_http_complex_value_t *expires_value; ngx_http_complex_value_t *expires_value;
ngx_array_t *headers; ngx_array_t *headers;
ngx_array_t *trailers; ngx_array_t *trailers;
ngx_uint_t headers_inherit;
ngx_uint_t trailers_inherit;
} ngx_http_headers_conf_t; } ngx_http_headers_conf_t;
@@ -97,6 +104,14 @@ static ngx_http_set_header_t ngx_http_set_headers[] = {
}; };
static ngx_conf_enum_t ngx_http_headers_inherit[] = {
{ ngx_string("off"), NGX_HTTP_HEADERS_INHERIT_OFF },
{ ngx_string("on"), NGX_HTTP_HEADERS_INHERIT_ON },
{ ngx_string("merge"), NGX_HTTP_HEADERS_INHERIT_MERGE },
{ ngx_null_string, 0 }
};
static ngx_command_t ngx_http_headers_filter_commands[] = { static ngx_command_t ngx_http_headers_filter_commands[] = {
{ ngx_string("expires"), { ngx_string("expires"),
@@ -123,6 +138,22 @@ static ngx_command_t ngx_http_headers_filter_commands[] = {
offsetof(ngx_http_headers_conf_t, trailers), offsetof(ngx_http_headers_conf_t, trailers),
NULL }, NULL },
{ ngx_string("add_header_inherit"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,
ngx_conf_set_enum_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_headers_conf_t, headers_inherit),
&ngx_http_headers_inherit },
{ ngx_string("add_trailer_inherit"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,
ngx_conf_set_enum_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_headers_conf_t, trailers_inherit),
&ngx_http_headers_inherit },
ngx_null_command ngx_null_command
}; };
@@ -657,6 +688,8 @@ ngx_http_headers_create_conf(ngx_conf_t *cf)
*/ */
conf->expires = NGX_HTTP_EXPIRES_UNSET; conf->expires = NGX_HTTP_EXPIRES_UNSET;
conf->headers_inherit = NGX_CONF_UNSET_UINT;
conf->trailers_inherit = NGX_CONF_UNSET_UINT;
return conf; return conf;
} }
@@ -668,6 +701,8 @@ ngx_http_headers_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_headers_conf_t *prev = parent; ngx_http_headers_conf_t *prev = parent;
ngx_http_headers_conf_t *conf = child; ngx_http_headers_conf_t *conf = child;
ngx_http_header_val_t *hv;
if (conf->expires == NGX_HTTP_EXPIRES_UNSET) { if (conf->expires == NGX_HTTP_EXPIRES_UNSET) {
conf->expires = prev->expires; conf->expires = prev->expires;
conf->expires_time = prev->expires_time; conf->expires_time = prev->expires_time;
@@ -678,12 +713,43 @@ ngx_http_headers_merge_conf(ngx_conf_t *cf, void *parent, void *child)
} }
} }
ngx_conf_merge_uint_value(conf->headers_inherit, prev->headers_inherit,
NGX_HTTP_HEADERS_INHERIT_ON);
ngx_conf_merge_uint_value(conf->trailers_inherit, prev->trailers_inherit,
NGX_HTTP_HEADERS_INHERIT_ON);
if (conf->headers_inherit != NGX_HTTP_HEADERS_INHERIT_OFF
&& prev->headers)
{
if (conf->headers == NULL) { if (conf->headers == NULL) {
conf->headers = prev->headers; conf->headers = prev->headers;
} else if (conf->headers_inherit == NGX_HTTP_HEADERS_INHERIT_MERGE) {
hv = ngx_array_push_n(conf->headers, prev->headers->nelts);
if (hv == NULL) {
return NGX_CONF_ERROR;
} }
ngx_memcpy(hv, prev->headers->elts,
sizeof(ngx_http_header_val_t) * prev->headers->nelts);
}
}
if (conf->trailers_inherit != NGX_HTTP_HEADERS_INHERIT_OFF
&& prev->trailers)
{
if (conf->trailers == NULL) { if (conf->trailers == NULL) {
conf->trailers = prev->trailers; conf->trailers = prev->trailers;
} else if (conf->trailers_inherit == NGX_HTTP_HEADERS_INHERIT_MERGE) {
hv = ngx_array_push_n(conf->trailers, prev->trailers->nelts);
if (hv == NULL) {
return NGX_CONF_ERROR;
}
ngx_memcpy(hv, prev->trailers->elts,
sizeof(ngx_http_header_val_t) * prev->trailers->nelts);
}
} }
return NGX_CONF_OK; return NGX_CONF_OK;
+1 -1
View File
@@ -490,7 +490,7 @@ ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (value[i].len == 0) { if (value[i].len == 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"index \"%V\" in \"index\" directive is invalid", "index \"%V\" in \"index\" directive is invalid",
&value[1]); &value[i]);
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
+19 -3
View File
@@ -237,7 +237,7 @@ static ngx_command_t ngx_http_ssl_commands[] = {
NULL }, NULL },
{ ngx_string("ssl_ocsp"), { ngx_string("ssl_ocsp"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_enum_slot, ngx_conf_set_enum_slot,
NGX_HTTP_SRV_CONF_OFFSET, NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_ssl_srv_conf_t, ocsp), offsetof(ngx_http_ssl_srv_conf_t, ocsp),
@@ -393,6 +393,9 @@ static ngx_http_variable_t ngx_http_ssl_vars[] = {
{ ngx_string("ssl_curves"), NULL, ngx_http_ssl_variable, { ngx_string("ssl_curves"), NULL, ngx_http_ssl_variable,
(uintptr_t) ngx_ssl_get_curves, NGX_HTTP_VAR_CHANGEABLE, 0 }, (uintptr_t) ngx_ssl_get_curves, NGX_HTTP_VAR_CHANGEABLE, 0 },
{ ngx_string("ssl_sigalg"), NULL, ngx_http_ssl_variable,
(uintptr_t) ngx_ssl_get_sigalg, NGX_HTTP_VAR_CHANGEABLE, 0 },
{ ngx_string("ssl_session_id"), NULL, ngx_http_ssl_variable, { ngx_string("ssl_session_id"), NULL, ngx_http_ssl_variable,
(uintptr_t) ngx_ssl_get_session_id, NGX_HTTP_VAR_CHANGEABLE, 0 }, (uintptr_t) ngx_ssl_get_session_id, NGX_HTTP_VAR_CHANGEABLE, 0 },
@@ -450,6 +453,9 @@ static ngx_http_variable_t ngx_http_ssl_vars[] = {
{ ngx_string("ssl_client_v_remain"), NULL, ngx_http_ssl_variable, { ngx_string("ssl_client_v_remain"), NULL, ngx_http_ssl_variable,
(uintptr_t) ngx_ssl_get_client_v_remain, NGX_HTTP_VAR_CHANGEABLE, 0 }, (uintptr_t) ngx_ssl_get_client_v_remain, NGX_HTTP_VAR_CHANGEABLE, 0 },
{ ngx_string("ssl_client_sigalg"), NULL, ngx_http_ssl_variable,
(uintptr_t) ngx_ssl_get_client_sigalg, NGX_HTTP_VAR_CHANGEABLE, 0 },
ngx_http_null_variable ngx_http_null_variable
}; };
@@ -803,6 +809,10 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
cln->data = &conf->ssl; cln->data = &conf->ssl;
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
{
static ngx_ssl_client_hello_arg cb = { ngx_http_ssl_servername };
ngx_ssl_set_client_hello_callback(conf->ssl.ctx, &cb);
if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx, if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
ngx_http_ssl_servername) ngx_http_ssl_servername)
@@ -813,7 +823,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
"dynamically to an OpenSSL library which has no tlsext support, " "dynamically to an OpenSSL library which has no tlsext support, "
"therefore SNI is not available"); "therefore SNI is not available");
} }
}
#endif #endif
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
@@ -956,13 +966,19 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
if (conf->stapling) { if (conf->stapling) {
if (conf->certificate_compression) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"\"ssl_stapling\" is incompatible with "
"\"ssl_certificate_compression\"");
return NGX_CONF_ERROR;
}
if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file, if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file,
&conf->stapling_responder, conf->stapling_verify) &conf->stapling_responder, conf->stapling_verify)
!= NGX_OK) != NGX_OK)
{ {
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
} }
if (ngx_ssl_early_data(cf, &conf->ssl, conf->early_data) != NGX_OK) { if (ngx_ssl_early_data(cf, &conf->ssl, conf->early_data) != NGX_OK) {
+1
View File
@@ -206,6 +206,7 @@ typedef struct {
#if (NGX_PCRE) #if (NGX_PCRE)
unsigned captures:1; unsigned captures:1;
#endif #endif
unsigned allow_connect:1;
ngx_http_core_loc_conf_t **named_locations; ngx_http_core_loc_conf_t **named_locations;
} ngx_http_core_srv_conf_t; } ngx_http_core_srv_conf_t;
+44 -1
View File
@@ -111,6 +111,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
sw_schema, sw_schema,
sw_schema_slash, sw_schema_slash,
sw_schema_slash_slash, sw_schema_slash_slash,
sw_spaces_before_host,
sw_host_start, sw_host_start,
sw_host, sw_host,
sw_host_end, sw_host_end,
@@ -158,6 +159,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
if (ch == ' ') { if (ch == ' ') {
r->method_end = p - 1; r->method_end = p - 1;
m = r->request_start; m = r->request_start;
state = sw_spaces_before_uri;
switch (p - m) { switch (p - m) {
@@ -247,6 +249,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
if (ngx_str7_cmp(m, 'C', 'O', 'N', 'N', 'E', 'C', 'T', ' ')) if (ngx_str7_cmp(m, 'C', 'O', 'N', 'N', 'E', 'C', 'T', ' '))
{ {
r->method = NGX_HTTP_CONNECT; r->method = NGX_HTTP_CONNECT;
state = sw_spaces_before_host;
} }
break; break;
@@ -269,7 +272,6 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
break; break;
} }
state = sw_spaces_before_uri;
break; break;
} }
@@ -345,6 +347,14 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
} }
break; break;
case sw_spaces_before_host:
if (ch == ' ') {
break;
}
/* fall through */
case sw_host_start: case sw_host_start:
r->host_start = p; r->host_start = p;
@@ -375,6 +385,15 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
r->host_end = p; r->host_end = p;
if (r->method == NGX_HTTP_CONNECT) {
if (ch == ':') {
state = sw_port;
break;
}
return NGX_HTTP_PARSE_INVALID_REQUEST;
}
switch (ch) { switch (ch) {
case ':': case ':':
state = sw_port; state = sw_port;
@@ -446,9 +465,23 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
case sw_port: case sw_port:
if (ch >= '0' && ch <= '9') { if (ch >= '0' && ch <= '9') {
if (r->port >= 6553 && (r->port > 6553 || (ch - '0') > 5)) {
return NGX_HTTP_PARSE_INVALID_REQUEST;
}
r->port = r->port * 10 + (ch - '0');
break; break;
} }
if (r->method == NGX_HTTP_CONNECT) {
if (ch == ' ') {
state = sw_http_09;
break;
}
return NGX_HTTP_PARSE_INVALID_REQUEST;
}
switch (ch) { switch (ch) {
case '/': case '/':
r->uri_start = p; r->uri_start = p;
@@ -684,6 +717,16 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
case sw_http_HTTP: case sw_http_HTTP:
switch (ch) { switch (ch) {
case '/': case '/':
/*
* use single "/" from request line to preserve pointers,
* if request line will be copied to large client buffer
*/
if (r->method == NGX_HTTP_CONNECT) {
r->uri_start = p;
r->uri_end = p + 1;
}
state = sw_first_major_digit; state = sw_first_major_digit;
break; break;
default: default:
+46 -31
View File
@@ -891,8 +891,27 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
return SSL_TLSEXT_ERR_ALERT_FATAL; return SSL_TLSEXT_ERR_ALERT_FATAL;
} }
if (c->ssl->sni_accepted) {
return SSL_TLSEXT_ERR_OK;
}
if (c->ssl->handshake_rejected) {
*ad = SSL_AD_UNRECOGNIZED_NAME;
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
hc = c->data; hc = c->data;
if (arg != NULL) {
host = *(ngx_str_t *) arg;
if (host.data == NULL) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
"SSL server name: null");
goto done;
}
} else {
servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name); servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
if (servername == NULL) { if (servername == NULL) {
@@ -901,17 +920,17 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
goto done; goto done;
} }
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
"SSL server name: \"%s\"", servername);
host.len = ngx_strlen(servername); host.len = ngx_strlen(servername);
host.data = (u_char *) servername;
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
"SSL server name: \"%V\"", &host);
if (host.len == 0) { if (host.len == 0) {
goto done; goto done;
} }
host.data = (u_char *) servername;
rc = ngx_http_validate_host(&host, c->pool, 1); rc = ngx_http_validate_host(&host, c->pool, 1);
if (rc == NGX_ERROR) { if (rc == NGX_ERROR) {
@@ -933,31 +952,6 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
goto done; goto done;
} }
sscf = ngx_http_get_module_srv_conf(cscf->ctx, ngx_http_ssl_module);
#if (defined TLS1_3_VERSION \
&& !defined LIBRESSL_VERSION_NUMBER && !defined OPENSSL_IS_BORINGSSL)
/*
* SSL_SESSION_get0_hostname() is only available in OpenSSL 1.1.1+,
* but servername being negotiated in every TLSv1.3 handshake
* is only returned in OpenSSL 1.1.1+ as well
*/
if (sscf->verify) {
const char *hostname;
hostname = SSL_SESSION_get0_hostname(SSL_get0_session(ssl_conn));
if (hostname != NULL && ngx_strcmp(hostname, servername) != 0) {
c->ssl->handshake_rejected = 1;
*ad = SSL_AD_ACCESS_DENIED;
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
}
#endif
hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t)); hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t));
if (hc->ssl_servername == NULL) { if (hc->ssl_servername == NULL) {
goto error; goto error;
@@ -971,6 +965,8 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
ngx_set_connection_log(c, clcf->error_log); ngx_set_connection_log(c, clcf->error_log);
sscf = ngx_http_get_module_srv_conf(cscf->ctx, ngx_http_ssl_module);
c->ssl->buffer_size = sscf->buffer_size; c->ssl->buffer_size = sscf->buffer_size;
if (sscf->ssl.ctx) { if (sscf->ssl.ctx) {
@@ -1019,6 +1015,7 @@ done:
return SSL_TLSEXT_ERR_ALERT_FATAL; return SSL_TLSEXT_ERR_ALERT_FATAL;
} }
c->ssl->sni_accepted = 1;
return SSL_TLSEXT_ERR_OK; return SSL_TLSEXT_ERR_OK;
error: error:
@@ -1849,6 +1846,7 @@ static ngx_int_t
ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
ngx_uint_t offset) ngx_uint_t offset)
{ {
u_char *p;
ngx_int_t rc; ngx_int_t rc;
ngx_str_t host; ngx_str_t host;
@@ -1891,6 +1889,17 @@ ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
r->headers_in.server = host; r->headers_in.server = host;
p = ngx_strlchr(h->value.data + host.len,
h->value.data + h->value.len, ':');
if (p) {
rc = ngx_atoi(p + 1, h->value.data + h->value.len - p - 1);
if (rc > 0 && rc < 65536) {
r->port = rc;
}
}
return NGX_OK; return NGX_OK;
} }
@@ -1988,6 +1997,8 @@ ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
static ngx_int_t static ngx_int_t
ngx_http_process_request_header(ngx_http_request_t *r) ngx_http_process_request_header(ngx_http_request_t *r)
{ {
ngx_http_core_srv_conf_t *cscf;
if (r->headers_in.server.len == 0 if (r->headers_in.server.len == 0
&& ngx_http_set_virtual_server(r, &r->headers_in.server) && ngx_http_set_virtual_server(r, &r->headers_in.server)
== NGX_ERROR) == NGX_ERROR)
@@ -2056,7 +2067,11 @@ ngx_http_process_request_header(ngx_http_request_t *r)
} }
} }
if (r->method == NGX_HTTP_CONNECT) { cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
if (r->method == NGX_HTTP_CONNECT
&& (r->http_version != NGX_HTTP_VERSION_11 || !cscf->allow_connect))
{
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"client sent CONNECT method"); "client sent CONNECT method");
ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED); ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
+2
View File
@@ -461,6 +461,8 @@ struct ngx_http_request_s {
ngx_http_cleanup_t *cleanup; ngx_http_cleanup_t *cleanup;
in_port_t port;
unsigned count:16; unsigned count:16;
unsigned subrequests:8; unsigned subrequests:8;
unsigned blocked:8; unsigned blocked:8;
+49 -34
View File
@@ -116,6 +116,10 @@ static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r,
static ngx_int_t static ngx_int_t
ngx_http_upstream_process_cache_control(ngx_http_request_t *r, ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset); ngx_table_elt_t *h, ngx_uint_t offset);
#if (NGX_HTTP_CACHE)
static ngx_int_t ngx_http_upstream_process_delta_seconds(u_char *p,
u_char *last);
#endif
static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset); ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_upstream_process_expires(ngx_http_request_t *r, static ngx_int_t ngx_http_upstream_process_expires(ngx_http_request_t *r,
@@ -5066,18 +5070,9 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
} }
if (p) { if (p) {
n = 0; n = ngx_http_upstream_process_delta_seconds(p + offset, last);
for (p += offset; p < last; p++) {
if (*p == ',' || *p == ';' || *p == ' ') {
break;
}
if (*p >= '0' && *p <= '9') {
n = n * 10 + (*p - '0');
continue;
}
if (n == NGX_ERROR) {
u->cacheable = 0; u->cacheable = 0;
return NGX_OK; return NGX_OK;
} }
@@ -5087,7 +5082,8 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
return NGX_OK; return NGX_OK;
} }
r->cache->valid_sec = ngx_time() + n; r->cache->valid_sec = ngx_min((ngx_uint_t) ngx_time() + n,
NGX_MAX_INT_T_VALUE);
u->headers_in.expired = 0; u->headers_in.expired = 0;
} }
@@ -5097,18 +5093,9 @@ extensions:
23 - 1); 23 - 1);
if (p) { if (p) {
n = 0; n = ngx_http_upstream_process_delta_seconds(p + 23, last);
for (p += 23; p < last; p++) {
if (*p == ',' || *p == ';' || *p == ' ') {
break;
}
if (*p >= '0' && *p <= '9') {
n = n * 10 + (*p - '0');
continue;
}
if (n == NGX_ERROR) {
u->cacheable = 0; u->cacheable = 0;
return NGX_OK; return NGX_OK;
} }
@@ -5120,18 +5107,9 @@ extensions:
p = ngx_strlcasestrn(start, last, (u_char *) "stale-if-error=", 15 - 1); p = ngx_strlcasestrn(start, last, (u_char *) "stale-if-error=", 15 - 1);
if (p) { if (p) {
n = 0; n = ngx_http_upstream_process_delta_seconds(p + 15, last);
for (p += 15; p < last; p++) {
if (*p == ',' || *p == ';' || *p == ' ') {
break;
}
if (*p >= '0' && *p <= '9') {
n = n * 10 + (*p - '0');
continue;
}
if (n == NGX_ERROR) {
u->cacheable = 0; u->cacheable = 0;
return NGX_OK; return NGX_OK;
} }
@@ -5145,6 +5123,41 @@ extensions:
} }
#if (NGX_HTTP_CACHE)
static ngx_int_t
ngx_http_upstream_process_delta_seconds(u_char *p, u_char *last)
{
ngx_int_t n, cutoff, cutlim;
cutoff = NGX_MAX_INT_T_VALUE / 10;
cutlim = NGX_MAX_INT_T_VALUE % 10;
n = 0;
for ( /* void */ ; p < last; p++) {
if (*p == ',' || *p == ';' || *p == ' ') {
break;
}
if (*p < '0' || *p > '9') {
return NGX_ERROR;
}
if (n >= cutoff && (n > cutoff || *p - '0' > cutlim)) {
n = NGX_MAX_INT_T_VALUE;
break;
}
n = n * 10 + (*p - '0');
}
return n;
}
#endif
static ngx_int_t static ngx_int_t
ngx_http_upstream_process_expires(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_http_upstream_process_expires(ngx_http_request_t *r, ngx_table_elt_t *h,
ngx_uint_t offset) ngx_uint_t offset)
@@ -6885,6 +6898,7 @@ ngx_http_upstream_set_local(ngx_http_request_t *r, ngx_http_upstream_t *u,
} }
if (val.len == 0) { if (val.len == 0) {
u->peer.local = NULL;
return NGX_OK; return NGX_OK;
} }
@@ -6901,6 +6915,7 @@ ngx_http_upstream_set_local(ngx_http_request_t *r, ngx_http_upstream_t *u,
if (rc != NGX_OK) { if (rc != NGX_OK) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"invalid local address \"%V\"", &val); "invalid local address \"%V\"", &val);
u->peer.local = NULL;
return NGX_OK; return NGX_OK;
} }
+1 -1
View File
@@ -253,7 +253,7 @@ typedef struct {
ngx_str_t module; ngx_str_t module;
NGX_COMPAT_BEGIN(2) NGX_COMPAT_BEGIN(6)
NGX_COMPAT_END NGX_COMPAT_END
} ngx_http_upstream_conf_t; } ngx_http_upstream_conf_t;
+55
View File
@@ -71,6 +71,10 @@ static ngx_int_t ngx_http_variable_scheme(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data); ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_https(ngx_http_request_t *r, static ngx_int_t ngx_http_variable_https(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data); ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_request_port(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_is_request_port(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static void ngx_http_variable_set_args(ngx_http_request_t *r, static void ngx_http_variable_set_args(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data); ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r, static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r,
@@ -231,6 +235,12 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
{ ngx_string("https"), NULL, ngx_http_variable_https, 0, 0, 0 }, { ngx_string("https"), NULL, ngx_http_variable_https, 0, 0, 0 },
{ ngx_string("request_port"), NULL,
ngx_http_variable_request_port, 0, 0, 0 },
{ ngx_string("is_request_port"), NULL,
ngx_http_variable_is_request_port, 0, 0, 0 },
{ ngx_string("request_uri"), NULL, ngx_http_variable_request, { ngx_string("request_uri"), NULL, ngx_http_variable_request,
offsetof(ngx_http_request_t, unparsed_uri), 0, 0 }, offsetof(ngx_http_request_t, unparsed_uri), 0, 0 },
@@ -1540,6 +1550,51 @@ ngx_http_variable_https(ngx_http_request_t *r,
} }
static ngx_int_t
ngx_http_variable_request_port(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
ngx_uint_t port;
v->len = 0;
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
if (v->data == NULL) {
return NGX_ERROR;
}
port = r->port;
if (port > 0 && port < 65536) {
v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
}
return NGX_OK;
}
static ngx_int_t
ngx_http_variable_is_request_port(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
if (r->port == 0) {
*v = ngx_http_variable_null_value;
return NGX_OK;
}
v->len = 1;
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
v->data = (u_char *) ":";
return NGX_OK;
}
static void static void
ngx_http_variable_set_args(ngx_http_request_t *r, ngx_http_variable_set_args(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data) ngx_http_variable_value_t *v, uintptr_t data)
+11
View File
@@ -3527,6 +3527,7 @@ ngx_http_v2_parse_scheme(ngx_http_request_t *r, ngx_str_t *value)
static ngx_int_t static ngx_int_t
ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value) ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value)
{ {
u_char *p;
ngx_int_t rc; ngx_int_t rc;
if (r->host_start) { if (r->host_start) {
@@ -3561,6 +3562,16 @@ ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value)
r->headers_in.server = *value; r->headers_in.server = *value;
p = ngx_strlchr(r->host_start + value->len, r->host_end, ':');
if (p) {
rc = ngx_atoi(p + 1, r->host_end - p - 1);
if (rc > 0 && rc < 65536) {
r->port = rc;
}
}
return NGX_OK; return NGX_OK;
} }
+10
View File
@@ -979,6 +979,16 @@ ngx_http_v3_init_pseudo_headers(ngx_http_request_t *r)
} }
r->headers_in.server = host; r->headers_in.server = host;
p = ngx_strlchr(r->host_start + host.len, r->host_end, ':');
if (p) {
rc = ngx_atoi(p + 1, r->host_end - p - 1);
if (rc > 0 && rc < 65536) {
r->port = rc;
}
}
} }
if (ngx_list_init(&r->headers_in.headers, r->pool, 20, if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
+12
View File
@@ -531,6 +531,7 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
ngx_int_t rc; ngx_int_t rc;
ngx_str_t line, auth, encoded; ngx_str_t line, auth, encoded;
ngx_buf_t *b; ngx_buf_t *b;
uintptr_t n;
ngx_connection_t *c; ngx_connection_t *c;
ngx_mail_session_t *s; ngx_mail_session_t *s;
ngx_mail_proxy_conf_t *pcf; ngx_mail_proxy_conf_t *pcf;
@@ -627,6 +628,10 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
CRLF) - 1 CRLF) - 1
+ s->connection->addr_text.len + s->login.len + s->host.len; + s->connection->addr_text.len + s->login.len + s->host.len;
n = ngx_escape_uri(NULL, s->login.data, s->login.len,
NGX_ESCAPE_MAIL_XTEXT);
line.len += n * 2;
#if (NGX_HAVE_INET6) #if (NGX_HAVE_INET6)
if (s->connection->sockaddr->sa_family == AF_INET6) { if (s->connection->sockaddr->sa_family == AF_INET6) {
line.len += sizeof("IPV6:") - 1; line.len += sizeof("IPV6:") - 1;
@@ -654,7 +659,14 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
if (s->login.len && !pcf->smtp_auth) { if (s->login.len && !pcf->smtp_auth) {
p = ngx_cpymem(p, " LOGIN=", sizeof(" LOGIN=") - 1); p = ngx_cpymem(p, " LOGIN=", sizeof(" LOGIN=") - 1);
if (n == 0) {
p = ngx_copy(p, s->login.data, s->login.len); p = ngx_copy(p, s->login.data, s->login.len);
} else {
p = (u_char *) ngx_escape_uri(p, s->login.data, s->login.len,
NGX_ESCAPE_MAIL_XTEXT);
}
} }
p = ngx_cpymem(p, " NAME=", sizeof(" NAME=") - 1); p = ngx_cpymem(p, " NAME=", sizeof(" NAME=") - 1);
+12
View File
@@ -61,6 +61,7 @@ typedef struct {
unsigned outside_entries:1; unsigned outside_entries:1;
unsigned allow_binary_include:1; unsigned allow_binary_include:1;
unsigned binary_include:1; unsigned binary_include:1;
unsigned no_cacheable:1;
} ngx_stream_geo_conf_ctx_t; } ngx_stream_geo_conf_ctx_t;
@@ -433,6 +434,7 @@ ngx_stream_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+ sizeof(ngx_stream_variable_value_t) + sizeof(ngx_stream_variable_value_t)
+ 0x10000 * sizeof(ngx_stream_geo_range_t *); + 0x10000 * sizeof(ngx_stream_geo_range_t *);
ctx.allow_binary_include = 1; ctx.allow_binary_include = 1;
ctx.no_cacheable = 0;
save = *cf; save = *cf;
cf->pool = pool; cf->pool = pool;
@@ -448,6 +450,10 @@ ngx_stream_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
goto failed; goto failed;
} }
if (ctx.no_cacheable) {
var->flags |= NGX_STREAM_VAR_NOCACHEABLE;
}
if (ctx.ranges) { if (ctx.ranges) {
if (ctx.high.low && !ctx.binary_include) { if (ctx.high.low && !ctx.binary_include) {
@@ -583,6 +589,12 @@ ngx_stream_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
goto done; goto done;
} }
else if (ngx_strcmp(value[0].data, "volatile") == 0) {
ctx->no_cacheable = 1;
rv = NGX_CONF_OK;
goto done;
}
} }
if (cf->args->nelts != 2) { if (cf->args->nelts != 2) {
+2
View File
@@ -680,6 +680,7 @@ ngx_stream_proxy_set_local(ngx_stream_session_t *s, ngx_stream_upstream_t *u,
} }
if (val.len == 0) { if (val.len == 0) {
u->peer.local = NULL;
return NGX_OK; return NGX_OK;
} }
@@ -696,6 +697,7 @@ ngx_stream_proxy_set_local(ngx_stream_session_t *s, ngx_stream_upstream_t *u,
if (rc != NGX_OK) { if (rc != NGX_OK) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"invalid local address \"%V\"", &val); "invalid local address \"%V\"", &val);
u->peer.local = NULL;
return NGX_OK; return NGX_OK;
} }
+47 -32
View File
@@ -239,7 +239,7 @@ static ngx_command_t ngx_stream_ssl_commands[] = {
NULL }, NULL },
{ ngx_string("ssl_ocsp"), { ngx_string("ssl_ocsp"),
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_enum_slot, ngx_conf_set_enum_slot,
NGX_STREAM_SRV_CONF_OFFSET, NGX_STREAM_SRV_CONF_OFFSET,
offsetof(ngx_stream_ssl_srv_conf_t, ocsp), offsetof(ngx_stream_ssl_srv_conf_t, ocsp),
@@ -357,6 +357,9 @@ static ngx_stream_variable_t ngx_stream_ssl_vars[] = {
{ ngx_string("ssl_curves"), NULL, ngx_stream_ssl_variable, { ngx_string("ssl_curves"), NULL, ngx_stream_ssl_variable,
(uintptr_t) ngx_ssl_get_curves, NGX_STREAM_VAR_CHANGEABLE, 0 }, (uintptr_t) ngx_ssl_get_curves, NGX_STREAM_VAR_CHANGEABLE, 0 },
{ ngx_string("ssl_sigalg"), NULL, ngx_stream_ssl_variable,
(uintptr_t) ngx_ssl_get_sigalg, NGX_STREAM_VAR_CHANGEABLE, 0 },
{ ngx_string("ssl_session_id"), NULL, ngx_stream_ssl_variable, { ngx_string("ssl_session_id"), NULL, ngx_stream_ssl_variable,
(uintptr_t) ngx_ssl_get_session_id, NGX_STREAM_VAR_CHANGEABLE, 0 }, (uintptr_t) ngx_ssl_get_session_id, NGX_STREAM_VAR_CHANGEABLE, 0 },
@@ -404,6 +407,9 @@ static ngx_stream_variable_t ngx_stream_ssl_vars[] = {
{ ngx_string("ssl_client_v_remain"), NULL, ngx_stream_ssl_variable, { ngx_string("ssl_client_v_remain"), NULL, ngx_stream_ssl_variable,
(uintptr_t) ngx_ssl_get_client_v_remain, NGX_STREAM_VAR_CHANGEABLE, 0 }, (uintptr_t) ngx_ssl_get_client_v_remain, NGX_STREAM_VAR_CHANGEABLE, 0 },
{ ngx_string("ssl_client_sigalg"), NULL, ngx_stream_ssl_variable,
(uintptr_t) ngx_ssl_get_client_sigalg, NGX_STREAM_VAR_CHANGEABLE, 0 },
ngx_stream_null_variable ngx_stream_null_variable
}; };
@@ -555,8 +561,27 @@ ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
return SSL_TLSEXT_ERR_ALERT_FATAL; return SSL_TLSEXT_ERR_ALERT_FATAL;
} }
if (c->ssl->sni_accepted) {
return SSL_TLSEXT_ERR_OK;
}
if (c->ssl->handshake_rejected) {
*ad = SSL_AD_UNRECOGNIZED_NAME;
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
s = c->data; s = c->data;
if (arg) {
host = *(ngx_str_t *) arg;
if (host.data == NULL) {
ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
"SSL server name: null");
goto done;
}
} else {
servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name); servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
if (servername == NULL) { if (servername == NULL) {
@@ -565,17 +590,17 @@ ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
goto done; goto done;
} }
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
"SSL server name: \"%s\"", servername);
host.len = ngx_strlen(servername); host.len = ngx_strlen(servername);
host.data = (u_char *) servername;
}
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
"SSL server name: \"%V\"", &host);
if (host.len == 0) { if (host.len == 0) {
goto done; goto done;
} }
host.data = (u_char *) servername;
rc = ngx_stream_validate_host(&host, c->pool, 1); rc = ngx_stream_validate_host(&host, c->pool, 1);
if (rc == NGX_ERROR) { if (rc == NGX_ERROR) {
@@ -596,35 +621,12 @@ ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
goto done; goto done;
} }
sscf = ngx_stream_get_module_srv_conf(cscf->ctx, ngx_stream_ssl_module);
#if (defined TLS1_3_VERSION \
&& !defined LIBRESSL_VERSION_NUMBER && !defined OPENSSL_IS_BORINGSSL)
/*
* SSL_SESSION_get0_hostname() is only available in OpenSSL 1.1.1+,
* but servername being negotiated in every TLSv1.3 handshake
* is only returned in OpenSSL 1.1.1+ as well
*/
if (sscf->verify) {
const char *hostname;
hostname = SSL_SESSION_get0_hostname(SSL_get0_session(ssl_conn));
if (hostname != NULL && ngx_strcmp(hostname, servername) != 0) {
c->ssl->handshake_rejected = 1;
*ad = SSL_AD_ACCESS_DENIED;
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
}
#endif
s->srv_conf = cscf->ctx->srv_conf; s->srv_conf = cscf->ctx->srv_conf;
ngx_set_connection_log(c, cscf->error_log); ngx_set_connection_log(c, cscf->error_log);
sscf = ngx_stream_get_module_srv_conf(cscf->ctx, ngx_stream_ssl_module);
if (sscf->ssl.ctx) { if (sscf->ssl.ctx) {
if (SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx) == NULL) { if (SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx) == NULL) {
goto error; goto error;
@@ -663,6 +665,7 @@ done:
return SSL_TLSEXT_ERR_ALERT_FATAL; return SSL_TLSEXT_ERR_ALERT_FATAL;
} }
c->ssl->sni_accepted = 1;
return SSL_TLSEXT_ERR_OK; return SSL_TLSEXT_ERR_OK;
error: error:
@@ -1002,8 +1005,14 @@ ngx_stream_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
cln->data = &conf->ssl; cln->data = &conf->ssl;
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
{
static ngx_ssl_client_hello_arg cb = { ngx_stream_ssl_servername };
ngx_ssl_set_client_hello_callback(conf->ssl.ctx, &cb);
SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx, SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
ngx_stream_ssl_servername); ngx_stream_ssl_servername);
}
#endif #endif
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
@@ -1148,13 +1157,19 @@ ngx_stream_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
if (conf->stapling) { if (conf->stapling) {
if (conf->certificate_compression) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"\"ssl_stapling\" is incompatible with "
"\"ssl_certificate_compression\"");
return NGX_CONF_ERROR;
}
if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file, if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file,
&conf->stapling_responder, conf->stapling_verify) &conf->stapling_responder, conf->stapling_verify)
!= NGX_OK) != NGX_OK)
{ {
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
} }
if (ngx_ssl_conf_commands(cf, &conf->ssl, conf->conf_commands) != NGX_OK) { if (ngx_ssl_conf_commands(cf, &conf->ssl, conf->conf_commands) != NGX_OK) {