Merged with the default branch.

This commit is contained in:
Sergey Kandaurov 2022-10-20 16:41:36 +04:00
commit de23dc786b
15 changed files with 899 additions and 147 deletions

View File

@ -6,7 +6,7 @@
all:
cd $(OPENSSL)
perl Configure VC-WIN32 no-shared \
perl Configure VC-WIN32 no-shared no-threads \
--prefix="%cd%/openssl" \
--openssldir="%cd%/openssl/ssl" \
$(OPENSSL_OPT)

View File

@ -5,6 +5,120 @@
<change_log title="nginx">
<changes ver="1.23.2" date="2022-10-19">
<change type="security">
<para lang="ru">
обработка специально созданного mp4-файла модулем ngx_http_mp4_module
могла приводить к падению рабочего процесса,
отправке клиенту части содержимого памяти рабочего процесса,
а также потенциально могла иметь другие последствия
(CVE-2022-41741, CVE-2022-41742).
</para>
<para lang="en">
processing of a specially crafted mp4 file by the ngx_http_mp4_module
might cause a worker process crash,
worker process memory disclosure,
or might have potential other impact
(CVE-2022-41741, CVE-2022-41742).
</para>
</change>
<change type="feature">
<para lang="ru">
переменные "$proxy_protocol_tlv_...".
</para>
<para lang="en">
the "$proxy_protocol_tlv_..." variables.
</para>
</change>
<change type="feature">
<para lang="ru">
ключи шифрования TLS session tickets теперь автоматически меняются
при использовании разделяемой памяти в ssl_session_cache.
</para>
<para lang="en">
TLS session tickets encryption keys are now automatically rotated
when using shared memory in the "ssl_session_cache" directive.
</para>
</change>
<change type="change">
<para lang="ru">
уровень логгирования ошибок SSL "bad record type"
понижен с уровня crit до info.<br/>
Спасибо Murilo Andrade.
</para>
<para lang="en">
the logging level of the "bad record type" SSL errors
has been lowered from "crit" to "info".<br/>
Thanks to Murilo Andrade.
</para>
</change>
<change type="change">
<para lang="ru">
теперь при использовании разделяемой памяти в ssl_session_cache
сообщения "could not allocate new session"
логгируются на уровне warn вместо alert
и не чаще одного раза в секунду.
</para>
<para lang="en">
now when using shared memory in the "ssl_session_cache" directive
the "could not allocate new session" errors
are logged at the "warn" level instead of "alert"
and not more often than once per second.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx/Windows не собирался с OpenSSL 3.0.x.
</para>
<para lang="en">
nginx/Windows could not be built with OpenSSL 3.0.x.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в логгировании ошибок протокола PROXY.<br/>
Спасибо Сергею Брестеру.
</para>
<para lang="en">
in logging of the PROXY protocol errors.<br/>
Thanks to Sergey Brester.
</para>
</change>
<change type="workaround">
<para lang="ru">
при использовании TLSv1.3 с OpenSSL
разделяемая память из ssl_session_cache расходовалась
в том числе на сессии, использующие TLS session tickets.
</para>
<para lang="en">
shared memory from the "ssl_session_cache" directive
was spent on sessions using TLS session tickets
when using TLSv1.3 with OpenSSL.
</para>
</change>
<change type="workaround">
<para lang="ru">
таймаут, заданный с помощью директивы ssl_session_timeout,
не работал при использовании TLSv1.3 с OpenSSL или BoringSSL.
</para>
<para lang="en">
timeout specified with the "ssl_session_timeout" directive
did not work when using TLSv1.3 with OpenSSL or BoringSSL.
</para>
</change>
</changes>
<changes ver="1.23.1" date="2022-07-19">
<change type="feature">

View File

@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
#define nginx_version 1023001
#define NGINX_VERSION "1.23.1"
#define nginx_version 1023002
#define NGINX_VERSION "1.23.2"
#define NGINX_VER "nginx/" NGINX_VERSION
#ifdef NGX_BUILD

View File

@ -13,7 +13,15 @@
#define NGX_PROXY_PROTOCOL_AF_INET6 2
#define ngx_proxy_protocol_parse_uint16(p) ((p)[0] << 8 | (p)[1])
#define ngx_proxy_protocol_parse_uint16(p) \
( ((uint16_t) (p)[0] << 8) \
+ ( (p)[1]) )
#define ngx_proxy_protocol_parse_uint32(p) \
( ((uint32_t) (p)[0] << 24) \
+ ( (p)[1] << 16) \
+ ( (p)[2] << 8) \
+ ( (p)[3]) )
typedef struct {
@ -40,12 +48,52 @@ typedef struct {
} ngx_proxy_protocol_inet6_addrs_t;
typedef struct {
u_char type;
u_char len[2];
} ngx_proxy_protocol_tlv_t;
typedef struct {
u_char client;
u_char verify[4];
} ngx_proxy_protocol_tlv_ssl_t;
typedef struct {
ngx_str_t name;
ngx_uint_t type;
} ngx_proxy_protocol_tlv_entry_t;
static u_char *ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p,
u_char *last, ngx_str_t *addr);
static u_char *ngx_proxy_protocol_read_port(u_char *p, u_char *last,
in_port_t *port, u_char sep);
static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf,
u_char *last);
static ngx_int_t ngx_proxy_protocol_lookup_tlv(ngx_connection_t *c,
ngx_str_t *tlvs, ngx_uint_t type, ngx_str_t *value);
static ngx_proxy_protocol_tlv_entry_t ngx_proxy_protocol_tlv_entries[] = {
{ ngx_string("alpn"), 0x01 },
{ ngx_string("authority"), 0x02 },
{ ngx_string("unique_id"), 0x05 },
{ ngx_string("ssl"), 0x20 },
{ ngx_string("netns"), 0x30 },
{ ngx_null_string, 0x00 }
};
static ngx_proxy_protocol_tlv_entry_t ngx_proxy_protocol_tlv_ssl_entries[] = {
{ ngx_string("version"), 0x21 },
{ ngx_string("cn"), 0x22 },
{ ngx_string("cipher"), 0x23 },
{ ngx_string("sig_alg"), 0x24 },
{ ngx_string("key_alg"), 0x25 },
{ ngx_null_string, 0x00 }
};
u_char *
@ -139,8 +187,14 @@ skip:
invalid:
for (p = buf; p < last; p++) {
if (*p == CR || *p == LF) {
break;
}
}
ngx_log_error(NGX_LOG_ERR, c->log, 0,
"broken header: \"%*s\"", (size_t) (last - buf), buf);
"broken header: \"%*s\"", (size_t) (p - buf), buf);
return NULL;
}
@ -412,11 +466,147 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
&pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port);
if (buf < end) {
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
"PROXY protocol v2 %z bytes of tlv ignored", end - buf);
pp->tlvs.data = ngx_pnalloc(c->pool, end - buf);
if (pp->tlvs.data == NULL) {
return NULL;
}
ngx_memcpy(pp->tlvs.data, buf, end - buf);
pp->tlvs.len = end - buf;
}
c->proxy_protocol = pp;
return end;
}
ngx_int_t
ngx_proxy_protocol_get_tlv(ngx_connection_t *c, ngx_str_t *name,
ngx_str_t *value)
{
u_char *p;
size_t n;
uint32_t verify;
ngx_str_t ssl, *tlvs;
ngx_int_t rc, type;
ngx_proxy_protocol_tlv_ssl_t *tlv_ssl;
ngx_proxy_protocol_tlv_entry_t *te;
if (c->proxy_protocol == NULL) {
return NGX_DECLINED;
}
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
"PROXY protocol v2 get tlv \"%V\"", name);
te = ngx_proxy_protocol_tlv_entries;
tlvs = &c->proxy_protocol->tlvs;
p = name->data;
n = name->len;
if (n >= 4 && p[0] == 's' && p[1] == 's' && p[2] == 'l' && p[3] == '_') {
rc = ngx_proxy_protocol_lookup_tlv(c, tlvs, 0x20, &ssl);
if (rc != NGX_OK) {
return rc;
}
if (ssl.len < sizeof(ngx_proxy_protocol_tlv_ssl_t)) {
return NGX_ERROR;
}
p += 4;
n -= 4;
if (n == 6 && ngx_strncmp(p, "verify", 6) == 0) {
tlv_ssl = (ngx_proxy_protocol_tlv_ssl_t *) ssl.data;
verify = ngx_proxy_protocol_parse_uint32(tlv_ssl->verify);
value->data = ngx_pnalloc(c->pool, NGX_INT32_LEN);
if (value->data == NULL) {
return NGX_ERROR;
}
value->len = ngx_sprintf(value->data, "%uD", verify)
- value->data;
return NGX_OK;
}
ssl.data += sizeof(ngx_proxy_protocol_tlv_ssl_t);
ssl.len -= sizeof(ngx_proxy_protocol_tlv_ssl_t);
te = ngx_proxy_protocol_tlv_ssl_entries;
tlvs = &ssl;
}
if (n >= 2 && p[0] == '0' && p[1] == 'x') {
type = ngx_hextoi(p + 2, n - 2);
if (type == NGX_ERROR) {
ngx_log_error(NGX_LOG_ERR, c->log, 0,
"invalid PROXY protocol TLV \"%V\"", name);
return NGX_ERROR;
}
return ngx_proxy_protocol_lookup_tlv(c, tlvs, type, value);
}
for ( /* void */ ; te->type; te++) {
if (te->name.len == n && ngx_strncmp(te->name.data, p, n) == 0) {
return ngx_proxy_protocol_lookup_tlv(c, tlvs, te->type, value);
}
}
ngx_log_error(NGX_LOG_ERR, c->log, 0,
"unknown PROXY protocol TLV \"%V\"", name);
return NGX_DECLINED;
}
static ngx_int_t
ngx_proxy_protocol_lookup_tlv(ngx_connection_t *c, ngx_str_t *tlvs,
ngx_uint_t type, ngx_str_t *value)
{
u_char *p;
size_t n, len;
ngx_proxy_protocol_tlv_t *tlv;
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
"PROXY protocol v2 lookup tlv:%02xi", type);
p = tlvs->data;
n = tlvs->len;
while (n) {
if (n < sizeof(ngx_proxy_protocol_tlv_t)) {
ngx_log_error(NGX_LOG_ERR, c->log, 0, "broken PROXY protocol TLV");
return NGX_ERROR;
}
tlv = (ngx_proxy_protocol_tlv_t *) p;
len = ngx_proxy_protocol_parse_uint16(tlv->len);
p += sizeof(ngx_proxy_protocol_tlv_t);
n -= sizeof(ngx_proxy_protocol_tlv_t);
if (n < len) {
ngx_log_error(NGX_LOG_ERR, c->log, 0, "broken PROXY protocol TLV");
return NGX_ERROR;
}
if (tlv->type == type) {
value->data = p;
value->len = len;
return NGX_OK;
}
p += len;
n -= len;
}
return NGX_DECLINED;
}

View File

@ -21,6 +21,7 @@ struct ngx_proxy_protocol_s {
ngx_str_t dst_addr;
in_port_t src_port;
in_port_t dst_port;
ngx_str_t tlvs;
};
@ -28,6 +29,8 @@ u_char *ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf,
u_char *last);
u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf,
u_char *last);
ngx_int_t ngx_proxy_protocol_get_tlv(ngx_connection_t *c, ngx_str_t *name,
ngx_str_t *value);
#endif /* _NGX_PROXY_PROTOCOL_H_INCLUDED_ */

View File

@ -231,9 +231,8 @@ ngx_iocp_del_connection(ngx_connection_t *c, ngx_uint_t flags)
}
static
ngx_int_t ngx_iocp_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
ngx_uint_t flags)
static ngx_int_t
ngx_iocp_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
{
int rc;
u_int key;
@ -356,7 +355,7 @@ ngx_iocp_create_conf(ngx_cycle_t *cycle)
cf = ngx_palloc(cycle->pool, sizeof(ngx_iocp_conf_t));
if (cf == NULL) {
return NGX_CONF_ERROR;
return NULL;
}
cf->threads = NGX_CONF_UNSET;

View File

@ -71,10 +71,11 @@ static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
static int ngx_ssl_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
HMAC_CTX *hctx, int enc);
static void ngx_ssl_session_ticket_keys_cleanup(void *data);
static ngx_int_t ngx_ssl_rotate_ticket_keys(SSL_CTX *ssl_ctx, ngx_log_t *log);
static void ngx_ssl_ticket_keys_cleanup(void *data);
#endif
#ifndef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
@ -131,7 +132,7 @@ ngx_module_t ngx_openssl_module = {
int ngx_ssl_connection_index;
int ngx_ssl_server_conf_index;
int ngx_ssl_session_cache_index;
int ngx_ssl_session_ticket_keys_index;
int ngx_ssl_ticket_keys_index;
int ngx_ssl_ocsp_index;
int ngx_ssl_certificate_index;
int ngx_ssl_next_certificate_index;
@ -208,9 +209,9 @@ ngx_ssl_init(ngx_log_t *log)
return NGX_ERROR;
}
ngx_ssl_session_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL,
NULL, NULL);
if (ngx_ssl_session_ticket_keys_index == -1) {
ngx_ssl_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
NULL);
if (ngx_ssl_ticket_keys_index == -1) {
ngx_ssl_error(NGX_LOG_ALERT, log, 0,
"SSL_CTX_get_ex_new_index() failed");
return NGX_ERROR;
@ -1083,6 +1084,53 @@ ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret)
}
}
#endif
#ifdef TLS1_3_VERSION
if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP
&& SSL_version(ssl_conn) == TLS1_3_VERSION)
{
time_t now, time, timeout, conf_timeout;
SSL_SESSION *sess;
/*
* OpenSSL with TLSv1.3 updates the session creation time on
* session resumption and keeps the session timeout unmodified,
* making it possible to maintain the session forever, bypassing
* client certificate expiration and revocation. To make sure
* session timeouts are actually used, we now update the session
* creation time and reduce the session timeout accordingly.
*
* BoringSSL with TLSv1.3 ignores configured session timeouts
* and uses a hardcoded timeout instead, 7 days. So we update
* session timeout to the configured value as soon as a session
* is created.
*/
c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
sess = SSL_get0_session(ssl_conn);
if (!c->ssl->session_timeout_set && sess) {
c->ssl->session_timeout_set = 1;
now = ngx_time();
time = SSL_SESSION_get_time(sess);
timeout = SSL_SESSION_get_timeout(sess);
conf_timeout = SSL_CTX_get_timeout(c->ssl->session_ctx);
timeout = ngx_min(timeout, conf_timeout);
if (now - time >= timeout) {
SSL_SESSION_set1_id_context(sess, (unsigned char *) "", 0);
} else {
SSL_SESSION_set_time(sess, now);
SSL_SESSION_set_timeout(sess, timeout - (now - time));
}
}
}
#endif
if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
@ -1426,9 +1474,9 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE);
#if SSL_CTRL_SET_ECDH_AUTO
#ifdef SSL_CTRL_SET_ECDH_AUTO
/* not needed in OpenSSL 1.1.0+ */
SSL_CTX_set_ecdh_auto(ssl->ctx, 1);
(void) SSL_CTX_set_ecdh_auto(ssl->ctx, 1);
#endif
if (ngx_strcmp(name->data, "auto") == 0) {
@ -1769,7 +1817,7 @@ ngx_ssl_handshake(ngx_connection_t *c)
#endif
#endif
#ifdef BIO_get_ktls_send
#if (defined BIO_get_ktls_send && !NGX_WIN32)
if (BIO_get_ktls_send(SSL_get_wbio(c->ssl->connection)) == 1) {
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
@ -1914,7 +1962,7 @@ ngx_ssl_try_early_data(ngx_connection_t *c)
c->read->ready = 1;
c->write->ready = 1;
#ifdef BIO_get_ktls_send
#if (defined BIO_get_ktls_send && !NGX_WIN32)
if (BIO_get_ktls_send(SSL_get_wbio(c->ssl->connection)) == 1) {
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
@ -2943,7 +2991,7 @@ ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size)
static ssize_t
ngx_ssl_sendfile(ngx_connection_t *c, ngx_buf_t *file, size_t size)
{
#ifdef BIO_get_ktls_send
#if (defined BIO_get_ktls_send && !NGX_WIN32)
int sslerr, flags;
ssize_t n;
@ -3429,6 +3477,9 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
#endif
#ifdef SSL_R_VERSION_TOO_LOW
|| n == SSL_R_VERSION_TOO_LOW /* 396 */
#endif
#ifdef SSL_R_BAD_RECORD_TYPE
|| n == SSL_R_BAD_RECORD_TYPE /* 443 */
#endif
|| n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
#ifdef SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE
@ -3774,6 +3825,12 @@ ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data)
ngx_queue_init(&cache->expire_queue);
cache->ticket_keys[0].expire = 0;
cache->ticket_keys[1].expire = 0;
cache->ticket_keys[2].expire = 0;
cache->fail_time = 0;
len = sizeof(" in SSL session shared cache \"\"") + shm_zone->shm.name.len;
shpool->log_ctx = ngx_slab_alloc(shpool, len);
@ -3792,16 +3849,16 @@ ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data)
/*
* The length of the session id is 16 bytes for SSLv2 sessions and
* between 1 and 32 bytes for SSLv3/TLSv1, typically 32 bytes.
* It seems that the typical length of the external ASN1 representation
* of a session is 118 or 119 bytes for SSLv3/TSLv1.
* between 1 and 32 bytes for SSLv3 and TLS, typically 32 bytes.
* Typical length of the external ASN1 representation of a session
* is about 150 bytes plus SNI server name.
*
* Thus on 32-bit platforms we allocate separately an rbtree node,
* a session id, and an ASN1 representation, they take accordingly
* 64, 32, and 128 bytes.
* On 32-bit platforms we allocate an rbtree node, a session id, and
* an ASN1 representation in a single allocation, it typically takes
* 256 bytes.
*
* On 64-bit platforms we allocate separately an rbtree node + session_id,
* and an ASN1 representation, they take accordingly 128 and 128 bytes.
* and an ASN1 representation, they take accordingly 128 and 256 bytes.
*
* OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
* so they are outside the code locked by shared pool mutex
@ -3811,7 +3868,8 @@ static int
ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
{
int len;
u_char *p, *id, *cached_sess, *session_id;
u_char *p, *session_id;
size_t n;
uint32_t hash;
SSL_CTX *ssl_ctx;
unsigned int session_id_length;
@ -3822,17 +3880,42 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
ngx_ssl_session_cache_t *cache;
u_char buf[NGX_SSL_MAX_SESSION_SIZE];
#ifdef TLS1_3_VERSION
/*
* OpenSSL tries to save TLSv1.3 sessions into session cache
* even when using tickets for stateless session resumption,
* "because some applications just want to know about the creation
* of a session"; do not cache such sessions
*/
if (SSL_version(ssl_conn) == TLS1_3_VERSION
&& (SSL_get_options(ssl_conn) & SSL_OP_NO_TICKET) == 0)
{
return 0;
}
#endif
len = i2d_SSL_SESSION(sess, NULL);
/* do not cache too big session */
if (len > (int) NGX_SSL_MAX_SESSION_SIZE) {
if (len > NGX_SSL_MAX_SESSION_SIZE) {
return 0;
}
p = buf;
i2d_SSL_SESSION(sess, &p);
session_id = (u_char *) SSL_SESSION_get_id(sess, &session_id_length);
/* do not cache sessions with too long session id */
if (session_id_length > 32) {
return 0;
}
c = ngx_ssl_get_connection(ssl_conn);
ssl_ctx = c->ssl->session_ctx;
@ -3846,23 +3929,13 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
/* drop one or two expired sessions */
ngx_ssl_expire_sessions(cache, shpool, 1);
cached_sess = ngx_slab_alloc_locked(shpool, len);
#if (NGX_PTR_SIZE == 8)
n = sizeof(ngx_ssl_sess_id_t);
#else
n = offsetof(ngx_ssl_sess_id_t, session) + len;
#endif
if (cached_sess == NULL) {
/* drop the oldest non-expired session and try once more */
ngx_ssl_expire_sessions(cache, shpool, 0);
cached_sess = ngx_slab_alloc_locked(shpool, len);
if (cached_sess == NULL) {
sess_id = NULL;
goto failed;
}
}
sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
sess_id = ngx_slab_alloc_locked(shpool, n);
if (sess_id == NULL) {
@ -3870,41 +3943,34 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
ngx_ssl_expire_sessions(cache, shpool, 0);
sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
sess_id = ngx_slab_alloc_locked(shpool, n);
if (sess_id == NULL) {
goto failed;
}
}
session_id = (u_char *) SSL_SESSION_get_id(sess, &session_id_length);
#if (NGX_PTR_SIZE == 8)
id = sess_id->sess_id;
sess_id->session = ngx_slab_alloc_locked(shpool, len);
#else
id = ngx_slab_alloc_locked(shpool, session_id_length);
if (id == NULL) {
if (sess_id->session == NULL) {
/* drop the oldest non-expired session and try once more */
ngx_ssl_expire_sessions(cache, shpool, 0);
id = ngx_slab_alloc_locked(shpool, session_id_length);
sess_id->session = ngx_slab_alloc_locked(shpool, len);
if (id == NULL) {
if (sess_id->session == NULL) {
goto failed;
}
}
#endif
ngx_memcpy(cached_sess, buf, len);
ngx_memcpy(id, session_id, session_id_length);
ngx_memcpy(sess_id->session, buf, len);
ngx_memcpy(sess_id->id, session_id, session_id_length);
hash = ngx_crc32_short(session_id, session_id_length);
@ -3914,9 +3980,7 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
sess_id->node.key = hash;
sess_id->node.data = (u_char) session_id_length;
sess_id->id = id;
sess_id->len = len;
sess_id->session = cached_sess;
sess_id->expire = ngx_time() + SSL_CTX_get_timeout(ssl_ctx);
@ -3930,18 +3994,17 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
failed:
if (cached_sess) {
ngx_slab_free_locked(shpool, cached_sess);
}
if (sess_id) {
ngx_slab_free_locked(shpool, sess_id);
}
ngx_shmtx_unlock(&shpool->mutex);
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
"could not allocate new session%s", shpool->log_ctx);
if (cache->fail_time != ngx_time()) {
cache->fail_time = ngx_time();
ngx_log_error(NGX_LOG_WARN, c->log, 0,
"could not allocate new session%s", shpool->log_ctx);
}
return 0;
}
@ -4027,9 +4090,10 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
ngx_rbtree_delete(&cache->session_rbtree, node);
ngx_explicit_memzero(sess_id->session, sess_id->len);
#if (NGX_PTR_SIZE == 8)
ngx_slab_free_locked(shpool, sess_id->session);
#if (NGX_PTR_SIZE == 4)
ngx_slab_free_locked(shpool, sess_id->id);
#endif
ngx_slab_free_locked(shpool, sess_id);
@ -4117,9 +4181,10 @@ ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
ngx_rbtree_delete(&cache->session_rbtree, node);
ngx_explicit_memzero(sess_id->session, sess_id->len);
#if (NGX_PTR_SIZE == 8)
ngx_slab_free_locked(shpool, sess_id->session);
#if (NGX_PTR_SIZE == 4)
ngx_slab_free_locked(shpool, sess_id->id);
#endif
ngx_slab_free_locked(shpool, sess_id);
@ -4166,9 +4231,10 @@ ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
ngx_rbtree_delete(&cache->session_rbtree, &sess_id->node);
ngx_explicit_memzero(sess_id->session, sess_id->len);
#if (NGX_PTR_SIZE == 8)
ngx_slab_free_locked(shpool, sess_id->session);
#if (NGX_PTR_SIZE == 4)
ngx_slab_free_locked(shpool, sess_id->id);
#endif
ngx_slab_free_locked(shpool, sess_id);
}
@ -4222,23 +4288,25 @@ ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
ngx_int_t
ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
{
u_char buf[80];
size_t size;
ssize_t n;
ngx_str_t *path;
ngx_file_t file;
ngx_uint_t i;
ngx_array_t *keys;
ngx_file_info_t fi;
ngx_pool_cleanup_t *cln;
ngx_ssl_session_ticket_key_t *key;
u_char buf[80];
size_t size;
ssize_t n;
ngx_str_t *path;
ngx_file_t file;
ngx_uint_t i;
ngx_array_t *keys;
ngx_file_info_t fi;
ngx_pool_cleanup_t *cln;
ngx_ssl_ticket_key_t *key;
if (paths == NULL) {
if (paths == NULL
&& SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_session_cache_index) == NULL)
{
return NGX_OK;
}
keys = ngx_array_create(cf->pool, paths->nelts,
sizeof(ngx_ssl_session_ticket_key_t));
keys = ngx_array_create(cf->pool, paths ? paths->nelts : 3,
sizeof(ngx_ssl_ticket_key_t));
if (keys == NULL) {
return NGX_ERROR;
}
@ -4248,9 +4316,41 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
return NGX_ERROR;
}
cln->handler = ngx_ssl_session_ticket_keys_cleanup;
cln->handler = ngx_ssl_ticket_keys_cleanup;
cln->data = keys;
if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_ticket_keys_index, keys) == 0) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_set_ex_data() failed");
return NGX_ERROR;
}
if (SSL_CTX_set_tlsext_ticket_key_cb(ssl->ctx, ngx_ssl_ticket_key_callback)
== 0)
{
ngx_log_error(NGX_LOG_WARN, cf->log, 0,
"nginx was built with Session Tickets support, however, "
"now it is linked dynamically to an OpenSSL library "
"which has no tlsext support, therefore Session Tickets "
"are not available");
return NGX_OK;
}
if (paths == NULL) {
/* placeholder for keys in shared memory */
key = ngx_array_push_n(keys, 3);
key[0].shared = 1;
key[0].expire = 0;
key[1].shared = 1;
key[1].expire = 0;
key[2].shared = 1;
key[2].expire = 0;
return NGX_OK;
}
path = paths->elts;
for (i = 0; i < paths->nelts; i++) {
@ -4305,6 +4405,9 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
goto failed;
}
key->shared = 0;
key->expire = 1;
if (size == 48) {
key->size = 48;
ngx_memcpy(key->name, buf, 16);
@ -4326,25 +4429,6 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
ngx_explicit_memzero(&buf, 80);
}
if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_ticket_keys_index, keys)
== 0)
{
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_set_ex_data() failed");
return NGX_ERROR;
}
if (SSL_CTX_set_tlsext_ticket_key_cb(ssl->ctx,
ngx_ssl_session_ticket_key_callback)
== 0)
{
ngx_log_error(NGX_LOG_WARN, cf->log, 0,
"nginx was built with Session Tickets support, however, "
"now it is linked dynamically to an OpenSSL library "
"which has no tlsext support, therefore Session Tickets "
"are not available");
}
return NGX_OK;
failed:
@ -4361,29 +4445,33 @@ failed:
static int
ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
ngx_ssl_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
HMAC_CTX *hctx, int enc)
{
size_t size;
SSL_CTX *ssl_ctx;
ngx_uint_t i;
ngx_array_t *keys;
ngx_connection_t *c;
ngx_ssl_session_ticket_key_t *key;
const EVP_MD *digest;
const EVP_CIPHER *cipher;
size_t size;
SSL_CTX *ssl_ctx;
ngx_uint_t i;
ngx_array_t *keys;
ngx_connection_t *c;
ngx_ssl_ticket_key_t *key;
const EVP_MD *digest;
const EVP_CIPHER *cipher;
c = ngx_ssl_get_connection(ssl_conn);
ssl_ctx = c->ssl->session_ctx;
if (ngx_ssl_rotate_ticket_keys(ssl_ctx, c->log) != NGX_OK) {
return -1;
}
#ifdef OPENSSL_NO_SHA256
digest = EVP_sha1();
#else
digest = EVP_sha256();
#endif
keys = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_ticket_keys_index);
keys = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_ticket_keys_index);
if (keys == NULL) {
return -1;
}
@ -4394,7 +4482,7 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
/* encrypt session ticket */
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"ssl session ticket encrypt, key: \"%*xs\" (%s session)",
"ssl ticket encrypt, key: \"%*xs\" (%s session)",
(size_t) 16, key[0].name,
SSL_session_reused(ssl_conn) ? "reused" : "new");
@ -4441,7 +4529,7 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
}
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"ssl session ticket decrypt, key: \"%*xs\" not found",
"ssl ticket decrypt, key: \"%*xs\" not found",
(size_t) 16, name);
return 0;
@ -4449,7 +4537,7 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
found:
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"ssl session ticket decrypt, key: \"%*xs\"%s",
"ssl ticket decrypt, key: \"%*xs\"%s",
(size_t) 16, key[i].name, (i == 0) ? " (default)" : "");
if (key[i].size == 48) {
@ -4486,7 +4574,7 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
/* renew if non-default key */
if (i != 0) {
if (i != 0 && key[i].expire) {
return 2;
}
@ -4495,13 +4583,142 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
}
static ngx_int_t
ngx_ssl_rotate_ticket_keys(SSL_CTX *ssl_ctx, ngx_log_t *log)
{
time_t now, expire;
ngx_array_t *keys;
ngx_shm_zone_t *shm_zone;
ngx_slab_pool_t *shpool;
ngx_ssl_ticket_key_t *key;
ngx_ssl_session_cache_t *cache;
u_char buf[80];
keys = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_ticket_keys_index);
if (keys == NULL) {
return NGX_OK;
}
key = keys->elts;
if (!key[0].shared) {
return NGX_OK;
}
/*
* if we don't need to update expiration of the current key
* and the previous key is still needed, don't sync with shared
* memory to save some work; in the worst case other worker process
* will switch to the next key, but this process will still be able
* to decrypt tickets encrypted with it
*/
now = ngx_time();
expire = now + SSL_CTX_get_timeout(ssl_ctx);
if (key[0].expire >= expire && key[1].expire >= now) {
return NGX_OK;
}
shm_zone = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_cache_index);
cache = shm_zone->data;
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
ngx_shmtx_lock(&shpool->mutex);
key = cache->ticket_keys;
if (key[0].expire == 0) {
/* initialize the current key */
if (RAND_bytes(buf, 80) != 1) {
ngx_ssl_error(NGX_LOG_ALERT, log, 0, "RAND_bytes() failed");
ngx_shmtx_unlock(&shpool->mutex);
return NGX_ERROR;
}
key[0].shared = 1;
key[0].expire = expire;
key[0].size = 80;
ngx_memcpy(key[0].name, buf, 16);
ngx_memcpy(key[0].hmac_key, buf + 16, 32);
ngx_memcpy(key[0].aes_key, buf + 48, 32);
ngx_explicit_memzero(&buf, 80);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
"ssl ticket key: \"%*xs\"",
(size_t) 16, key[0].name);
/*
* copy the current key to the next key, as initialization of
* the previous key will replace the current key with the next
* key
*/
key[2] = key[0];
}
if (key[1].expire < now) {
/*
* if the previous key is no longer needed (or not initialized),
* replace it with the current key, replace the current key with
* the next key, and generate new next key
*/
key[1] = key[0];
key[0] = key[2];
if (RAND_bytes(buf, 80) != 1) {
ngx_ssl_error(NGX_LOG_ALERT, log, 0, "RAND_bytes() failed");
ngx_shmtx_unlock(&shpool->mutex);
return NGX_ERROR;
}
key[2].shared = 1;
key[2].expire = 0;
key[2].size = 80;
ngx_memcpy(key[2].name, buf, 16);
ngx_memcpy(key[2].hmac_key, buf + 16, 32);
ngx_memcpy(key[2].aes_key, buf + 48, 32);
ngx_explicit_memzero(&buf, 80);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
"ssl ticket key: \"%*xs\"",
(size_t) 16, key[2].name);
}
/*
* update expiration of the current key: it is going to be needed
* at least till the session being created expires
*/
if (expire > key[0].expire) {
key[0].expire = expire;
}
/* sync keys to the worker process memory */
ngx_memcpy(keys->elts, cache->ticket_keys,
2 * sizeof(ngx_ssl_ticket_key_t));
ngx_shmtx_unlock(&shpool->mutex);
return NGX_OK;
}
static void
ngx_ssl_session_ticket_keys_cleanup(void *data)
ngx_ssl_ticket_keys_cleanup(void *data)
{
ngx_array_t *keys = data;
ngx_explicit_memzero(keys->elts,
keys->nelts * sizeof(ngx_ssl_session_ticket_key_t));
keys->nelts * sizeof(ngx_ssl_ticket_key_t));
}
#else

View File

@ -122,6 +122,7 @@ struct ngx_ssl_connection_s {
unsigned no_send_shutdown:1;
unsigned shutdown_without_free:1;
unsigned handshake_buffer_set:1;
unsigned session_timeout_set:1;
unsigned try_early_data:1;
unsigned in_early:1;
unsigned in_ocsp:1;
@ -142,37 +143,37 @@ typedef struct ngx_ssl_sess_id_s ngx_ssl_sess_id_t;
struct ngx_ssl_sess_id_s {
ngx_rbtree_node_t node;
u_char *id;
size_t len;
u_char *session;
ngx_queue_t queue;
time_t expire;
u_char id[32];
#if (NGX_PTR_SIZE == 8)
void *stub;
u_char sess_id[32];
u_char *session;
#else
u_char session[1];
#endif
};
typedef struct {
u_char name[16];
u_char hmac_key[32];
u_char aes_key[32];
time_t expire;
unsigned size:8;
unsigned shared:1;
} ngx_ssl_ticket_key_t;
typedef struct {
ngx_rbtree_t session_rbtree;
ngx_rbtree_node_t sentinel;
ngx_queue_t expire_queue;
ngx_ssl_ticket_key_t ticket_keys[3];
time_t fail_time;
} ngx_ssl_session_cache_t;
#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
typedef struct {
size_t size;
u_char name[16];
u_char hmac_key[32];
u_char aes_key[32];
} ngx_ssl_session_ticket_key_t;
#endif
#define NGX_SSL_SSLv2 0x0002
#define NGX_SSL_SSLv3 0x0004
#define NGX_SSL_TLSv1 0x0008
@ -212,10 +213,12 @@ ngx_int_t ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder,
ngx_uint_t depth, ngx_shm_zone_t *shm_zone);
ngx_int_t ngx_ssl_ocsp_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_resolver_t *resolver, ngx_msec_t resolver_timeout);
ngx_int_t ngx_ssl_ocsp_validate(ngx_connection_t *c);
ngx_int_t ngx_ssl_ocsp_get_status(ngx_connection_t *c, const char **s);
void ngx_ssl_ocsp_cleanup(ngx_connection_t *c);
ngx_int_t ngx_ssl_ocsp_cache_init(ngx_shm_zone_t *shm_zone, void *data);
ngx_array_t *ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file);
ngx_array_t *ngx_ssl_preserve_passwords(ngx_conf_t *cf,
ngx_array_t *passwords);
@ -322,7 +325,7 @@ void ngx_ssl_cleanup_ctx(void *data);
extern int ngx_ssl_connection_index;
extern int ngx_ssl_server_conf_index;
extern int ngx_ssl_session_cache_index;
extern int ngx_ssl_session_ticket_keys_index;
extern int ngx_ssl_ticket_keys_index;
extern int ngx_ssl_ocsp_index;
extern int ngx_ssl_certificate_index;
extern int ngx_ssl_next_certificate_index;

View File

@ -1121,6 +1121,12 @@ ngx_http_mp4_read_ftyp_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
return NGX_ERROR;
}
if (mp4->ftyp_atom.buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 ftyp atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size;
ftyp_atom = ngx_palloc(mp4->request->pool, atom_size);
@ -1179,6 +1185,12 @@ ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
return NGX_DECLINED;
}
if (mp4->moov_atom.buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 moov atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
conf = ngx_http_get_module_loc_conf(mp4->request, ngx_http_mp4_module);
if (atom_data_size > mp4->buffer_size) {
@ -1246,6 +1258,12 @@ ngx_http_mp4_read_mdat_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 mdat atom");
if (mp4->mdat_atom.buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 mdat atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
data = &mp4->mdat_data_buf;
data->file = &mp4->file;
data->in_file = 1;
@ -1372,6 +1390,12 @@ ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 mvhd atom");
if (mp4->mvhd_atom.buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 mvhd atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
atom_header = ngx_mp4_atom_header(mp4);
mvhd_atom = (ngx_mp4_mvhd_atom_t *) atom_header;
mvhd64_atom = (ngx_mp4_mvhd64_atom_t *) atom_header;
@ -1637,6 +1661,13 @@ ngx_http_mp4_read_tkhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size;
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_TKHD_ATOM].buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 tkhd atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
trak->tkhd_size = atom_size;
trak->movie_duration = duration;
@ -1676,6 +1707,12 @@ ngx_http_mp4_read_mdia_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_MDIA_ATOM].buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 mdia atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
atom = &trak->mdia_atom_buf;
atom->temporary = 1;
atom->pos = atom_header;
@ -1799,6 +1836,13 @@ ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size;
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_MDHD_ATOM].buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 mdhd atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
trak->mdhd_size = atom_size;
trak->timescale = timescale;
trak->duration = duration;
@ -1862,6 +1906,12 @@ ngx_http_mp4_read_hdlr_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_HDLR_ATOM].buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 hdlr atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
atom = &trak->hdlr_atom_buf;
atom->temporary = 1;
atom->pos = atom_header;
@ -1890,6 +1940,12 @@ ngx_http_mp4_read_minf_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_MINF_ATOM].buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 minf atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
atom = &trak->minf_atom_buf;
atom->temporary = 1;
atom->pos = atom_header;
@ -1933,6 +1989,15 @@ ngx_http_mp4_read_vmhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_VMHD_ATOM].buf
|| trak->out[NGX_HTTP_MP4_SMHD_ATOM].buf)
{
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 vmhd/smhd atom in \"%s\"",
mp4->file.name.data);
return NGX_ERROR;
}
atom = &trak->vmhd_atom_buf;
atom->temporary = 1;
atom->pos = atom_header;
@ -1964,6 +2029,15 @@ ngx_http_mp4_read_smhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_VMHD_ATOM].buf
|| trak->out[NGX_HTTP_MP4_SMHD_ATOM].buf)
{
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 vmhd/smhd atom in \"%s\"",
mp4->file.name.data);
return NGX_ERROR;
}
atom = &trak->smhd_atom_buf;
atom->temporary = 1;
atom->pos = atom_header;
@ -1995,6 +2069,12 @@ ngx_http_mp4_read_dinf_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_DINF_ATOM].buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 dinf atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
atom = &trak->dinf_atom_buf;
atom->temporary = 1;
atom->pos = atom_header;
@ -2023,6 +2103,12 @@ ngx_http_mp4_read_stbl_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_STBL_ATOM].buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 stbl atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
atom = &trak->stbl_atom_buf;
atom->temporary = 1;
atom->pos = atom_header;
@ -2144,6 +2230,12 @@ ngx_http_mp4_read_stsd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_STSD_ATOM].buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 stsd atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
atom = &trak->stsd_atom_buf;
atom->temporary = 1;
atom->pos = atom_header;
@ -2212,6 +2304,13 @@ ngx_http_mp4_read_stts_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
atom_end = atom_table + entries * sizeof(ngx_mp4_stts_entry_t);
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_STTS_ATOM].buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 stts atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
trak->time_to_sample_entries = entries;
atom = &trak->stts_atom_buf;
@ -2480,6 +2579,13 @@ ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
"sync sample entries:%uD", entries);
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_STSS_ATOM].buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 stss atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
trak->sync_samples_entries = entries;
atom_table = atom_header + sizeof(ngx_http_mp4_stss_atom_t);
@ -2678,6 +2784,13 @@ ngx_http_mp4_read_ctts_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
"composition offset entries:%uD", entries);
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_CTTS_ATOM].buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 ctts atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
trak->composition_offset_entries = entries;
atom_table = atom_header + sizeof(ngx_mp4_ctts_atom_t);
@ -2881,6 +2994,13 @@ ngx_http_mp4_read_stsc_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
atom_end = atom_table + entries * sizeof(ngx_mp4_stsc_entry_t);
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_STSC_ATOM].buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 stsc atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
trak->sample_to_chunk_entries = entries;
atom = &trak->stsc_atom_buf;
@ -3213,6 +3333,13 @@ ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
"sample uniform size:%uD, entries:%uD", size, entries);
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_STSZ_ATOM].buf) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 stsz atom in \"%s\"", mp4->file.name.data);
return NGX_ERROR;
}
trak->sample_sizes_entries = entries;
atom_table = atom_header + sizeof(ngx_mp4_stsz_atom_t);
@ -3396,6 +3523,16 @@ ngx_http_mp4_read_stco_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
atom_end = atom_table + entries * sizeof(uint32_t);
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_STCO_ATOM].buf
|| trak->out[NGX_HTTP_MP4_CO64_ATOM].buf)
{
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 stco/co64 atom in \"%s\"",
mp4->file.name.data);
return NGX_ERROR;
}
trak->chunks = entries;
atom = &trak->stco_atom_buf;
@ -3602,6 +3739,16 @@ ngx_http_mp4_read_co64_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
atom_end = atom_table + entries * sizeof(uint64_t);
trak = ngx_mp4_last_trak(mp4);
if (trak->out[NGX_HTTP_MP4_STCO_ATOM].buf
|| trak->out[NGX_HTTP_MP4_CO64_ATOM].buf)
{
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"duplicate mp4 stco/co64 atom in \"%s\"",
mp4->file.name.data);
return NGX_ERROR;
}
trak->chunks = entries;
atom = &trak->co64_atom_buf;

View File

@ -1116,7 +1116,7 @@ ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
len++;
}
if (len == 0) {
if (len == 0 || j == value[i].len) {
goto invalid;
}
@ -1206,7 +1206,7 @@ ngx_http_ssl_ocsp_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
len++;
}
if (len == 0) {
if (len == 0 || j == value[1].len) {
goto invalid;
}

View File

@ -61,6 +61,8 @@ static ngx_int_t ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_proxy_protocol_tlv(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r,
@ -214,6 +216,10 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
ngx_http_variable_proxy_protocol_port,
offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 },
{ ngx_string("proxy_protocol_tlv_"), NULL,
ngx_http_variable_proxy_protocol_tlv,
0, NGX_HTTP_VAR_PREFIX, 0 },
{ ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 },
{ ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 },
@ -1386,6 +1392,39 @@ ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r,
}
static ngx_int_t
ngx_http_variable_proxy_protocol_tlv(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
ngx_str_t *name = (ngx_str_t *) data;
ngx_int_t rc;
ngx_str_t tlv, value;
tlv.len = name->len - (sizeof("proxy_protocol_tlv_") - 1);
tlv.data = name->data + sizeof("proxy_protocol_tlv_") - 1;
rc = ngx_proxy_protocol_get_tlv(r->connection, &tlv, &value);
if (rc == NGX_ERROR) {
return NGX_ERROR;
}
if (rc == NGX_DECLINED) {
v->not_found = 1;
return NGX_OK;
}
v->len = value.len;
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
v->data = value.data;
return NGX_OK;
}
static ngx_int_t
ngx_http_variable_server_addr(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)

View File

@ -682,7 +682,7 @@ ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
len++;
}
if (len == 0) {
if (len == 0 || j == value[i].len) {
goto invalid;
}

View File

@ -80,8 +80,6 @@ typedef long time_t;
#pragma warning(default:4201)
/* disable some "-W4" level warnings */
/* 'type cast': from function pointer to data pointer */
#pragma warning(disable:4054)
@ -106,6 +104,9 @@ typedef long time_t;
/* array is too small to include a terminating null character */
#pragma warning(disable:4295)
/* conversion from 'type1' to 'type2' of greater size */
#pragma warning(disable:4306)
#endif

View File

@ -1073,7 +1073,7 @@ ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
len++;
}
if (len == 0) {
if (len == 0 || j == value[i].len) {
goto invalid;
}

View File

@ -23,6 +23,8 @@ static ngx_int_t ngx_stream_variable_proxy_protocol_addr(
ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_stream_variable_proxy_protocol_port(
ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_stream_variable_proxy_protocol_tlv(
ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_stream_variable_server_addr(ngx_stream_session_t *s,
ngx_stream_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_stream_variable_server_port(ngx_stream_session_t *s,
@ -79,6 +81,10 @@ static ngx_stream_variable_t ngx_stream_core_variables[] = {
ngx_stream_variable_proxy_protocol_port,
offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 },
{ ngx_string("proxy_protocol_tlv_"), NULL,
ngx_stream_variable_proxy_protocol_tlv,
0, NGX_STREAM_VAR_PREFIX, 0 },
{ ngx_string("server_addr"), NULL,
ngx_stream_variable_server_addr, 0, 0, 0 },
@ -621,6 +627,39 @@ ngx_stream_variable_proxy_protocol_port(ngx_stream_session_t *s,
}
static ngx_int_t
ngx_stream_variable_proxy_protocol_tlv(ngx_stream_session_t *s,
ngx_stream_variable_value_t *v, uintptr_t data)
{
ngx_str_t *name = (ngx_str_t *) data;
ngx_int_t rc;
ngx_str_t tlv, value;
tlv.len = name->len - (sizeof("proxy_protocol_tlv_") - 1);
tlv.data = name->data + sizeof("proxy_protocol_tlv_") - 1;
rc = ngx_proxy_protocol_get_tlv(s->connection, &tlv, &value);
if (rc == NGX_ERROR) {
return NGX_ERROR;
}
if (rc == NGX_DECLINED) {
v->not_found = 1;
return NGX_OK;
}
v->len = value.len;
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
v->data = value.data;
return NGX_OK;
}
static ngx_int_t
ngx_stream_variable_server_addr(ngx_stream_session_t *s,
ngx_stream_variable_value_t *v, uintptr_t data)