Compare commits

..
60 Commits
Author SHA1 Message Date
Hakase 008819315c Update README.md 2020-10-05 21:35:23 +09:00
Hakase 677450910d Submodule update, fix build error. 2020-10-05 21:34:12 +09:00
Hakase d23cd2f0e0 Latest update - 7702 2020-08-29 19:53:01 +09:00
Hakase 72680e2bd2 Version bump - v1.19.3 2020-08-29 19:52:51 +09:00
Hakase 10689fcf23 Release - v1.19.2 2020-08-29 19:52:37 +09:00
Hakase c8ca86a8d2 Latest update - 7698 2020-08-29 19:52:20 +09:00
Hakase 9b69c0a792 Submodule update. 2020-07-12 20:03:05 +09:00
Hakase 38112b0b03 Latest update - 7684 2020-07-12 20:01:50 +09:00
Hakase 8407b245de Version bump - v1.19.2 2020-07-12 20:01:36 +09:00
Hakase cdf4d451e4 Release - v1.19.1 2020-07-12 20:01:21 +09:00
Hakase 141b7448a4 Latest update - 7680 2020-07-12 20:00:53 +09:00
Hakase b54c866079 Latest update - 7672 2020-07-01 15:21:18 +09:00
Hakase f1c30863fd Latest update - 7671 2020-06-28 19:20:30 +09:00
Hakase d3a0c6f60b Latest update - 7665 2020-06-15 01:33:51 +09:00
Hakase da1c2b041b Latest update - 7661 2020-05-27 20:32:16 +09:00
Hakase 605baf04af Version bump - v1.19.1 2020-05-27 20:32:04 +09:00
Hakase e5ed7cb934 Release - v1.19.0 2020-05-27 20:31:46 +09:00
Hakase b839120943 Latest update - 7655 2020-05-25 20:36:22 +09:00
Hakase da5d29fcc3 Fix README.md (OpenSSL version) 2020-05-17 20:33:33 +09:00
Hakase a204ef38f1 Submodule update. 2020-05-17 20:31:41 +09:00
Hakase 840eeb7822 Latest update - 7649 2020-05-17 20:30:28 +09:00
Hakase b44a2acbe4 Latest update - 7648 2020-05-09 15:33:53 +09:00
Hakase 5343d2bbc5 Edit submodule - ngx_brotli 2020-05-02 00:02:16 +09:00
Hakase 0ad16b54fb Submodule update. (OpenSSL) 2020-04-30 00:06:27 +09:00
Hakase 5dd8c93d82 Submodule update. (fix header) 2020-04-30 00:03:01 +09:00
Hakase ce239236e3 Submodule update. 2020-04-29 23:53:09 +09:00
Hakase 2c96cb11ab Submodule update. 2020-04-25 21:11:30 +09:00
Hakase f0749362b8 Submodule update. 2020-04-25 20:23:22 +09:00
Hakase 17760a9544 Latest update - 7647 2020-04-25 19:55:22 +09:00
Hakase 73d234d143 Version bump - v1.19.0 2020-04-25 19:55:02 +09:00
Hakase 0d55d860d8 Release - v1.18.0 2020-04-25 19:54:38 +09:00
Hakase 214d1434e0 Version bump - v1.17.11 2020-04-15 18:40:12 +09:00
Hakase b09da0b6bc Release - v1.17.10 2020-04-15 18:39:55 +09:00
Hakase cacff59229 Latest update - 7639 2020-04-15 18:39:36 +09:00
Hakase 31970d8a16 Latest update - 7638 2020-04-14 12:44:32 +09:00
Hakase d62ff9ef6d Latest update - 7637 2020-03-17 16:19:44 +09:00
Hakase 0e342ce410 Update special response. 2020-03-08 21:45:18 +09:00
Hakase 17c9415840 Submodule update. 2020-03-08 13:12:24 +09:00
Hakase b882d7f6f8 Version bump - v1.17.10 2020-03-04 08:50:28 +09:00
Hakase c80cd29962 Release - v1.17.9 2020-03-04 08:49:59 +09:00
Hakase 7ed9723455 Latest update - 7633 2020-03-04 08:48:31 +09:00
Hakase c58ddf89e9 Submodule update. 2020-03-03 19:23:04 +09:00
Hakase 49dbf201ac Latest update - 7632 2020-03-03 18:15:29 +09:00
Hakase a5a19139a3 Latest update - 7630 2020-02-28 23:44:39 +09:00
Hakase 801540a2d5 Latest update - 7628 2020-02-28 12:37:52 +09:00
Hakase 980e7d0358 Latest update - 7627 2020-02-21 08:51:06 +09:00
Hakase d477388bae Fix build error - naxsi 2020-02-17 21:36:49 +09:00
Hakase 795a5f5d70 Latest update - 7624 2020-02-13 08:43:38 +09:00
Hakase c975811c7b Submodule update. 2020-02-11 23:23:09 +09:00
Hakase 5a5ea54d48 Latest update - 7623 2020-02-07 01:31:27 +09:00
Hakase fd07a01249 Fix nginx.conf (Cloudflare IPs) 2020-01-27 18:34:36 +09:00
Hakase f6849c3590 Version bump - v1.17.9 2020-01-22 16:59:20 +09:00
Hakase ab20392497 Release - v1.17.8 2020-01-22 16:58:56 +09:00
Hakase 347c3f34fe Edit config.inc.example 2020-01-22 16:58:15 +09:00
Hakase 3850d60a81 Submodule update. 2020-01-22 16:37:22 +09:00
Hakase de1993b3e5 Submodule update. 2020-01-21 11:01:18 +09:00
Hakase 796de73034 Submodule update. 2020-01-17 19:47:15 +09:00
Hakase 978d81dd1b Latest update - 7618 2020-01-17 19:40:11 +09:00
Hakase df26e63ebf Submodule update. 2020-01-09 22:20:57 +09:00
Hakase bcbd6417f6 Latest update - 7617 2019-12-28 20:18:39 +09:00
63 changed files with 3154 additions and 567 deletions
+3 -3
View File
@@ -7,9 +7,6 @@
[submodule "lib/nginx-dav-ext-module"] [submodule "lib/nginx-dav-ext-module"]
path = lib/nginx-dav-ext-module path = lib/nginx-dav-ext-module
url = https://github.com/arut/nginx-dav-ext-module.git url = https://github.com/arut/nginx-dav-ext-module.git
[submodule "lib/ngx_brotli"]
path = lib/ngx_brotli
url = https://github.com/eustas/ngx_brotli.git
[submodule "lib/ngx_devel_kit"] [submodule "lib/ngx_devel_kit"]
path = lib/ngx_devel_kit path = lib/ngx_devel_kit
url = https://github.com/simplresty/ngx_devel_kit.git url = https://github.com/simplresty/ngx_devel_kit.git
@@ -35,3 +32,6 @@
[submodule "lib/nginx-http-flv-module"] [submodule "lib/nginx-http-flv-module"]
path = lib/nginx-http-flv-module path = lib/nginx-http-flv-module
url = https://github.com/winshining/nginx-http-flv-module.git url = https://github.com/winshining/nginx-http-flv-module.git
[submodule "lib/ngx_brotli"]
path = lib/ngx_brotli
url = https://github.com/google/ngx_brotli.git
+6
View File
@@ -446,3 +446,9 @@ ce2ced3856909f36f8130c99eaa4dbdbae636ddc release-1.17.4
9af0dddbddb2c368bfedd2801bc100ffad01e19b release-1.17.5 9af0dddbddb2c368bfedd2801bc100ffad01e19b release-1.17.5
de68d0d94320cbf033599c6f3ca37e5335c67fd7 release-1.17.6 de68d0d94320cbf033599c6f3ca37e5335c67fd7 release-1.17.6
e56295fe0ea76bf53b06bffa77a2d3a9a335cb8c release-1.17.7 e56295fe0ea76bf53b06bffa77a2d3a9a335cb8c release-1.17.7
fdacd273711ddf20f778c1fb91529ab53979a454 release-1.17.8
5e8d52bca714d4b85284ddb649d1ba4a3ca978a8 release-1.17.9
c44970de01474f6f3e01b0adea85ec1d03e3a5f2 release-1.17.10
cbe6ba650211541310618849168631ce0b788f35 release-1.19.0
062920e2f3bf871ef7a3d8496edec1b3065faf80 release-1.19.1
a7b46539f507e6c64efa0efda69ad60b6f4ffbce release-1.19.2
+4 -2
View File
@@ -1,6 +1,8 @@
# Hakase-nginx # Hakase-nginx
**My nginx build files.** **My nginx build files.**
## This repository is no longer operational. Use an alternative such as tengine.
Example Web Server - [https://ssl.haka.se/](https://ssl.haka.se/) Example Web Server - [https://ssl.haka.se/](https://ssl.haka.se/)
## Please install dependency library. ## Please install dependency library.
@@ -33,8 +35,8 @@ Example Web Server - [https://ssl.haka.se/](https://ssl.haka.se/)
- Use the settings below to support older browsers. (TLS Protocol) - Use the settings below to support older browsers. (TLS Protocol)
- ssl_protocols : TLSv1 TLSv1.1 TLSv1.2 TLSv1.3 - ssl_protocols : TLSv1 TLSv1.1 TLSv1.2 TLSv1.3
- ssl_ciphers : [TLS13+AESGCM+AES128|TLS13+CHACHA20]:TLS13+AESGCM+AES256:[EECDH+ECDSA+AESGCM+AES128|EECDH+ECDSA+CHACHA20]:EECDH+ECDSA+AESGCM+AES256:EECDH+ECDSA+AES128+SHA:EECDH+ECDSA+AES256+SHA:[EECDH+aRSA+AESGCM+AES128|EECDH+aRSA+CHACHA20]:EECDH+aRSA+AESGCM+AES256:EECDH+aRSA+AES128+SHA:EECDH+aRSA+AES256+SHA:RSA+AES128+SHA:RSA+AES256+SHA:RSA+3DES - ssl_ciphers : [TLS13+AESGCM+AES128|TLS13+CHACHA20]:TLS13+AESGCM+AES256:[EECDH+ECDSA+AESGCM+AES128|EECDH+ECDSA+CHACHA20]:EECDH+ECDSA+AESGCM+AES256:EECDH+ECDSA+AES128+SHA:EECDH+ECDSA+AES256+SHA:[EECDH+aRSA+AESGCM+AES128|EECDH+aRSA+CHACHA20]:EECDH+aRSA+AESGCM+AES256:EECDH+aRSA+AES128+SHA:EECDH+aRSA+AES256+SHA:RSA+AES128+SHA:RSA+AES256+SHA:RSA+3DES
- TLS v1.3 (**final**) - TLS v1.3
- Use OpenSSL-3.0.0-dev (**final**) - Use OpenSSL-3.0.0-alpha3-dev
- Use OpenSSL equal preference patch ([BoringSSL](https://github.com/google/boringssl) & [buik](https://gitlab.com/buik/openssl/blob/openssl-patch/openssl-1.1)) - Use OpenSSL equal preference patch ([BoringSSL](https://github.com/google/boringssl) & [buik](https://gitlab.com/buik/openssl/blob/openssl-patch/openssl-1.1))
- My OpenSSL patch is [here](https://github.com/hakasenyang/openssl-patch). - My OpenSSL patch is [here](https://github.com/hakasenyang/openssl-patch).
- Prefers ChaCha20 suites with clients that don't have AES-NI(AES hardware acceleration) (e.g., Android devices) - Prefers ChaCha20 suites with clients that don't have AES-NI(AES hardware acceleration) (e.g., Android devices)
+2 -2
View File
@@ -102,9 +102,9 @@ if [ "$GEOIP2" = 1 ]; then BUILD_MODULES="${BUILD_MODULES} --add-module=./lib/ng
if [ "$VTS" = 1 ]; then BUILD_MODULES="${BUILD_MODULES} --add-module=./lib/nginx-module-vts"; fi if [ "$VTS" = 1 ]; then BUILD_MODULES="${BUILD_MODULES} --add-module=./lib/nginx-module-vts"; fi
auto/configure \ auto/configure \
--with-cc-opt="-DTCP_FASTOPEN=23 ${BUILD_BIT}${BUILD_LTO} ${TEMP_OPT} -g -O3 -march=native -fstack-protector-strong -fuse-ld=gold -fuse-linker-plugin --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wno-strict-aliasing -Wp,-D_FORTIFY_SOURCE=2 -gsplit-dwarf -DNGX_HTTP_HEADERS" \ --with-cc-opt="-Wno-stringop-truncation -DTCP_FASTOPEN=23 ${BUILD_BIT}${BUILD_LTO} ${TEMP_OPT} -g -O3 -march=native -fstack-protector-strong -fuse-ld=gold -fuse-linker-plugin --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wno-strict-aliasing -Wp,-D_FORTIFY_SOURCE=2 -gsplit-dwarf -DNGX_HTTP_HEADERS" \
--with-ld-opt="${BUILD_LD} ${BUILD_LTO}" \ --with-ld-opt="${BUILD_LD} ${BUILD_LTO}" \
--with-openssl-opt="enable-weak-ssl-ciphers no-ssl3-method -march=native -ljemalloc ${BUILD_OPENSSL_LTO}" \ --with-openssl-opt="no-cmp enable-weak-ssl-ciphers no-ssl3-method -march=native -ljemalloc ${BUILD_OPENSSL_LTO}" \
--builddir=objs --prefix=${NGX_PREFIX} \ --builddir=objs --prefix=${NGX_PREFIX} \
--conf-path=${NGX_CONF} \ --conf-path=${NGX_CONF} \
--pid-path=${NGX_PID} \ --pid-path=${NGX_PID} \
+23 -18
View File
@@ -31,24 +31,29 @@ http {
variables_hash_max_size 2048; variables_hash_max_size 2048;
# Cloudflare CDN # Cloudflare CDN
set_real_ip_from 199.27.128.0/21; # IPv4
set_real_ip_from 173.245.48.0/20; set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22; set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22; set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22; set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18; set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18; set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20; set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20; set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22; set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17; set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15; set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/12; set_real_ip_from 104.16.0.0/12;
#set_real_ip_from 2400:cb00::/32; set_real_ip_from 172.64.0.0/13;
#set_real_ip_from 2606:4700::/32; set_real_ip_from 131.0.72.0/22;
#set_real_ip_from 2803:f800::/32; # IPv6
#set_real_ip_from 2405:b500::/32; #set_real_ip_from 2400:cb00::/32;
#set_real_ip_from 2405:8100::/32; #set_real_ip_from 2606:4700::/32;
#set_real_ip_from 2803:f800::/32;
#set_real_ip_from 2405:b500::/32;
#set_real_ip_from 2405:8100::/32;
#set_real_ip_from 2a06:98c0::/29;
#set_real_ip_from 2c0f:f248::/32;
real_ip_header CF-Connecting-IP; real_ip_header CF-Connecting-IP;
# SSL Config # SSL Config
+1 -1
View File
@@ -21,7 +21,7 @@ BUILD_MTS="-j$(expr $(nproc) \+ 1)"
### LTO build ### LTO build
### View : https://gcc.gnu.org/wiki/LinkTimeOptimization#Using_LTO ### View : https://gcc.gnu.org/wiki/LinkTimeOptimization#Using_LTO
LTO=1 LTO=0
######################### #########################
### Select add module ### ### Select add module ###
+78 -8
View File
@@ -141,6 +141,7 @@ syn keyword ngxDirective contained ancient_browser_value
syn keyword ngxDirective contained api syn keyword ngxDirective contained api
syn keyword ngxDirective contained auth_basic syn keyword ngxDirective contained auth_basic
syn keyword ngxDirective contained auth_basic_user_file syn keyword ngxDirective contained auth_basic_user_file
syn keyword ngxDirective contained auth_delay
syn keyword ngxDirective contained auth_http syn keyword ngxDirective contained auth_http
syn keyword ngxDirective contained auth_http_header syn keyword ngxDirective contained auth_http_header
syn keyword ngxDirective contained auth_http_pass_client_cert syn keyword ngxDirective contained auth_http_pass_client_cert
@@ -332,6 +333,7 @@ syn keyword ngxDirective contained ip_hash
syn keyword ngxDirective contained js_access syn keyword ngxDirective contained js_access
syn keyword ngxDirective contained js_content syn keyword ngxDirective contained js_content
syn keyword ngxDirective contained js_filter syn keyword ngxDirective contained js_filter
syn keyword ngxDirective contained js_import
syn keyword ngxDirective contained js_include syn keyword ngxDirective contained js_include
syn keyword ngxDirective contained js_path syn keyword ngxDirective contained js_path
syn keyword ngxDirective contained js_preread syn keyword ngxDirective contained js_preread
@@ -348,6 +350,7 @@ syn keyword ngxDirective contained large_client_header_buffers
syn keyword ngxDirective contained least_conn syn keyword ngxDirective contained least_conn
syn keyword ngxDirective contained least_time syn keyword ngxDirective contained least_time
syn keyword ngxDirective contained limit_conn syn keyword ngxDirective contained limit_conn
syn keyword ngxDirective contained limit_conn_dry_run
syn keyword ngxDirective contained limit_conn_log_level syn keyword ngxDirective contained limit_conn_log_level
syn keyword ngxDirective contained limit_conn_status syn keyword ngxDirective contained limit_conn_status
syn keyword ngxDirective contained limit_conn_zone syn keyword ngxDirective contained limit_conn_zone
@@ -595,6 +598,9 @@ syn keyword ngxDirective contained ssl_early_data
syn keyword ngxDirective contained ssl_ecdh_curve syn keyword ngxDirective contained ssl_ecdh_curve
syn keyword ngxDirective contained ssl_engine syn keyword ngxDirective contained ssl_engine
syn keyword ngxDirective contained ssl_handshake_timeout syn keyword ngxDirective contained ssl_handshake_timeout
syn keyword ngxDirective contained ssl_ocsp
syn keyword ngxDirective contained ssl_ocsp_cache
syn keyword ngxDirective contained ssl_ocsp_responder
syn keyword ngxDirective contained ssl_password_file syn keyword ngxDirective contained ssl_password_file
syn keyword ngxDirective contained ssl_prefer_server_ciphers syn keyword ngxDirective contained ssl_prefer_server_ciphers
syn keyword ngxDirective contained ssl_preread syn keyword ngxDirective contained ssl_preread
@@ -770,6 +776,7 @@ syn keyword ngxDirectiveThirdParty contained auth_gss_authorized_principal
syn keyword ngxDirectiveThirdParty contained auth_gss_force_realm syn keyword ngxDirectiveThirdParty contained auth_gss_force_realm
syn keyword ngxDirectiveThirdParty contained auth_gss_format_full syn keyword ngxDirectiveThirdParty contained auth_gss_format_full
syn keyword ngxDirectiveThirdParty contained auth_gss_keytab syn keyword ngxDirectiveThirdParty contained auth_gss_keytab
syn keyword ngxDirectiveThirdParty contained auth_gss_map_to_local
syn keyword ngxDirectiveThirdParty contained auth_gss_realm syn keyword ngxDirectiveThirdParty contained auth_gss_realm
syn keyword ngxDirectiveThirdParty contained auth_gss_service_name syn keyword ngxDirectiveThirdParty contained auth_gss_service_name
@@ -791,8 +798,8 @@ syn keyword ngxDirectiveThirdParty contained auth_pam_set_pam_env
" AJP protocol proxy " AJP protocol proxy
" https://github.com/yaoweibin/nginx_ajp_module " https://github.com/yaoweibin/nginx_ajp_module
syn keyword ngxDirectiveThirdParty contained ajp_buffer_size
syn keyword ngxDirectiveThirdParty contained ajp_buffers syn keyword ngxDirectiveThirdParty contained ajp_buffers
syn keyword ngxDirectiveThirdParty contained ajp_buffer_size
syn keyword ngxDirectiveThirdParty contained ajp_busy_buffers_size syn keyword ngxDirectiveThirdParty contained ajp_busy_buffers_size
syn keyword ngxDirectiveThirdParty contained ajp_cache syn keyword ngxDirectiveThirdParty contained ajp_cache
syn keyword ngxDirectiveThirdParty contained ajp_cache_key syn keyword ngxDirectiveThirdParty contained ajp_cache_key
@@ -818,6 +825,7 @@ syn keyword ngxDirectiveThirdParty contained ajp_pass_header
syn keyword ngxDirectiveThirdParty contained ajp_pass_request_body syn keyword ngxDirectiveThirdParty contained ajp_pass_request_body
syn keyword ngxDirectiveThirdParty contained ajp_pass_request_headers syn keyword ngxDirectiveThirdParty contained ajp_pass_request_headers
syn keyword ngxDirectiveThirdParty contained ajp_read_timeout syn keyword ngxDirectiveThirdParty contained ajp_read_timeout
syn keyword ngxDirectiveThirdParty contained ajp_secret
syn keyword ngxDirectiveThirdParty contained ajp_send_lowat syn keyword ngxDirectiveThirdParty contained ajp_send_lowat
syn keyword ngxDirectiveThirdParty contained ajp_send_timeout syn keyword ngxDirectiveThirdParty contained ajp_send_timeout
syn keyword ngxDirectiveThirdParty contained ajp_store syn keyword ngxDirectiveThirdParty contained ajp_store
@@ -854,8 +862,8 @@ syn keyword ngxDirectiveThirdParty contained content_handler_property
syn keyword ngxDirectiveThirdParty contained content_handler_type syn keyword ngxDirectiveThirdParty contained content_handler_type
syn keyword ngxDirectiveThirdParty contained handler_code syn keyword ngxDirectiveThirdParty contained handler_code
syn keyword ngxDirectiveThirdParty contained handler_name syn keyword ngxDirectiveThirdParty contained handler_name
syn keyword ngxDirectiveThirdParty contained handler_type
syn keyword ngxDirectiveThirdParty contained handlers_lazy_init syn keyword ngxDirectiveThirdParty contained handlers_lazy_init
syn keyword ngxDirectiveThirdParty contained handler_type
syn keyword ngxDirectiveThirdParty contained header_filter_code syn keyword ngxDirectiveThirdParty contained header_filter_code
syn keyword ngxDirectiveThirdParty contained header_filter_name syn keyword ngxDirectiveThirdParty contained header_filter_name
syn keyword ngxDirectiveThirdParty contained header_filter_property syn keyword ngxDirectiveThirdParty contained header_filter_property
@@ -871,6 +879,10 @@ syn keyword ngxDirectiveThirdParty contained jvm_options
syn keyword ngxDirectiveThirdParty contained jvm_path syn keyword ngxDirectiveThirdParty contained jvm_path
syn keyword ngxDirectiveThirdParty contained jvm_var syn keyword ngxDirectiveThirdParty contained jvm_var
syn keyword ngxDirectiveThirdParty contained jvm_workers syn keyword ngxDirectiveThirdParty contained jvm_workers
syn keyword ngxDirectiveThirdParty contained log_handler_code
syn keyword ngxDirectiveThirdParty contained log_handler_name
syn keyword ngxDirectiveThirdParty contained log_handler_property
syn keyword ngxDirectiveThirdParty contained log_handler_type
syn keyword ngxDirectiveThirdParty contained max_balanced_tcp_connections syn keyword ngxDirectiveThirdParty contained max_balanced_tcp_connections
syn keyword ngxDirectiveThirdParty contained rewrite_handler_code syn keyword ngxDirectiveThirdParty contained rewrite_handler_code
syn keyword ngxDirectiveThirdParty contained rewrite_handler_name syn keyword ngxDirectiveThirdParty contained rewrite_handler_name
@@ -879,6 +891,7 @@ syn keyword ngxDirectiveThirdParty contained rewrite_handler_type
syn keyword ngxDirectiveThirdParty contained shared_map syn keyword ngxDirectiveThirdParty contained shared_map
syn keyword ngxDirectiveThirdParty contained write_page_size syn keyword ngxDirectiveThirdParty contained write_page_size
" Certificate Transparency " Certificate Transparency
" https://github.com/grahamedgecombe/nginx-ct " https://github.com/grahamedgecombe/nginx-ct
syn keyword ngxDirectiveThirdParty contained ssl_ct syn keyword ngxDirectiveThirdParty contained ssl_ct
@@ -942,6 +955,7 @@ syn keyword ngxDirectiveThirdParty contained fancyindex_hide_symlinks
syn keyword ngxDirectiveThirdParty contained fancyindex_ignore syn keyword ngxDirectiveThirdParty contained fancyindex_ignore
syn keyword ngxDirectiveThirdParty contained fancyindex_localtime syn keyword ngxDirectiveThirdParty contained fancyindex_localtime
syn keyword ngxDirectiveThirdParty contained fancyindex_name_length syn keyword ngxDirectiveThirdParty contained fancyindex_name_length
syn keyword ngxDirectiveThirdParty contained fancyindex_show_dotfiles
syn keyword ngxDirectiveThirdParty contained fancyindex_show_path syn keyword ngxDirectiveThirdParty contained fancyindex_show_path
syn keyword ngxDirectiveThirdParty contained fancyindex_time_format syn keyword ngxDirectiveThirdParty contained fancyindex_time_format
@@ -991,8 +1005,8 @@ syn keyword ngxDirectiveThirdParty contained nchan_benchmark_publisher_distribut
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_subscriber_distribution syn keyword ngxDirectiveThirdParty contained nchan_benchmark_subscriber_distribution
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_subscribers_per_channel syn keyword ngxDirectiveThirdParty contained nchan_benchmark_subscribers_per_channel
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_time syn keyword ngxDirectiveThirdParty contained nchan_benchmark_time
syn keyword ngxDirectiveThirdParty contained nchan_channel_event_string
syn keyword ngxDirectiveThirdParty contained nchan_channel_events_channel_id syn keyword ngxDirectiveThirdParty contained nchan_channel_events_channel_id
syn keyword ngxDirectiveThirdParty contained nchan_channel_event_string
syn keyword ngxDirectiveThirdParty contained nchan_channel_group syn keyword ngxDirectiveThirdParty contained nchan_channel_group
syn keyword ngxDirectiveThirdParty contained nchan_channel_group_accounting syn keyword ngxDirectiveThirdParty contained nchan_channel_group_accounting
syn keyword ngxDirectiveThirdParty contained nchan_channel_id syn keyword ngxDirectiveThirdParty contained nchan_channel_id
@@ -1000,6 +1014,10 @@ syn keyword ngxDirectiveThirdParty contained nchan_channel_id_split_delimiter
syn keyword ngxDirectiveThirdParty contained nchan_channel_timeout syn keyword ngxDirectiveThirdParty contained nchan_channel_timeout
syn keyword ngxDirectiveThirdParty contained nchan_deflate_message_for_websocket syn keyword ngxDirectiveThirdParty contained nchan_deflate_message_for_websocket
syn keyword ngxDirectiveThirdParty contained nchan_eventsource_event syn keyword ngxDirectiveThirdParty contained nchan_eventsource_event
syn keyword ngxDirectiveThirdParty contained nchan_eventsource_ping_comment
syn keyword ngxDirectiveThirdParty contained nchan_eventsource_ping_data
syn keyword ngxDirectiveThirdParty contained nchan_eventsource_ping_event
syn keyword ngxDirectiveThirdParty contained nchan_eventsource_ping_interval
syn keyword ngxDirectiveThirdParty contained nchan_group_location syn keyword ngxDirectiveThirdParty contained nchan_group_location
syn keyword ngxDirectiveThirdParty contained nchan_group_max_channels syn keyword ngxDirectiveThirdParty contained nchan_group_max_channels
syn keyword ngxDirectiveThirdParty contained nchan_group_max_messages syn keyword ngxDirectiveThirdParty contained nchan_group_max_messages
@@ -1047,10 +1065,10 @@ syn keyword ngxDirectiveThirdParty contained nchan_store_messages
syn keyword ngxDirectiveThirdParty contained nchan_stub_status syn keyword ngxDirectiveThirdParty contained nchan_stub_status
syn keyword ngxDirectiveThirdParty contained nchan_sub_channel_id syn keyword ngxDirectiveThirdParty contained nchan_sub_channel_id
syn keyword ngxDirectiveThirdParty contained nchan_subscribe_existing_channels_only syn keyword ngxDirectiveThirdParty contained nchan_subscribe_existing_channels_only
syn keyword ngxDirectiveThirdParty contained nchan_subscribe_request
syn keyword ngxDirectiveThirdParty contained nchan_subscriber syn keyword ngxDirectiveThirdParty contained nchan_subscriber
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_channel_id syn keyword ngxDirectiveThirdParty contained nchan_subscriber_channel_id
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_compound_etag_message_id syn keyword ngxDirectiveThirdParty contained nchan_subscriber_compound_etag_message_id
syn keyword ngxDirectiveThirdParty contained nchan_subscribe_request
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_first_message syn keyword ngxDirectiveThirdParty contained nchan_subscriber_first_message
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_http_raw_stream_separator syn keyword ngxDirectiveThirdParty contained nchan_subscriber_http_raw_stream_separator
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_last_message_id syn keyword ngxDirectiveThirdParty contained nchan_subscriber_last_message_id
@@ -1987,11 +2005,7 @@ syn keyword ngxDirectiveThirdParty contained concat_unique
" update upstreams' config by restful interface " update upstreams' config by restful interface
" https://github.com/yzprofile/ngx_http_dyups_module " https://github.com/yzprofile/ngx_http_dyups_module
syn keyword ngxDirectiveThirdParty contained dyups_interface syn keyword ngxDirectiveThirdParty contained dyups_interface
syn keyword ngxDirectiveThirdParty contained dyups_read_msg_log
syn keyword ngxDirectiveThirdParty contained dyups_read_msg_timeout
syn keyword ngxDirectiveThirdParty contained dyups_shm_zone_size syn keyword ngxDirectiveThirdParty contained dyups_shm_zone_size
syn keyword ngxDirectiveThirdParty contained dyups_trylock
syn keyword ngxDirectiveThirdParty contained dyups_upstream_conf
" add given content to the end of the response according to the condition specified " add given content to the end of the response according to the condition specified
" https://github.com/flygoast/ngx_http_footer_if_filter " https://github.com/flygoast/ngx_http_footer_if_filter
@@ -2308,6 +2322,62 @@ syn keyword ngxDirectiveThirdParty contained user_agent
" https://github.com/flygoast/ngx_http_upstream_ketama_chash " https://github.com/flygoast/ngx_http_upstream_ketama_chash
syn keyword ngxDirectiveThirdParty contained ketama_chash syn keyword ngxDirectiveThirdParty contained ketama_chash
" nginx-sticky-module-ng
" https://github.com/ayty-adrianomartins/nginx-sticky-module-ng
syn keyword ngxDirectiveThirdParty contained sticky_no_fallback
" dynamic linking and call the function of your application
" https://github.com/Taymindis/nginx-link-function
syn keyword ngxDirectiveThirdParty contained ngx_link_func_add_prop
syn keyword ngxDirectiveThirdParty contained ngx_link_func_add_req_header
syn keyword ngxDirectiveThirdParty contained ngx_link_func_ca_cert
syn keyword ngxDirectiveThirdParty contained ngx_link_func_call
syn keyword ngxDirectiveThirdParty contained ngx_link_func_download_link_lib
syn keyword ngxDirectiveThirdParty contained ngx_link_func_lib
syn keyword ngxDirectiveThirdParty contained ngx_link_func_shm_size
syn keyword ngxDirectiveThirdParty contained ngx_link_func_subrequest
" purge content from FastCGI, proxy, SCGI and uWSGI caches
" https://github.com/torden/ngx_cache_purge
syn keyword ngxDirectiveThirdParty contained cache_purge_response_type
" set the flags "HttpOnly", "secure" and "SameSite" for cookies
" https://github.com/AirisX/nginx_cookie_flag_module
syn keyword ngxDirectiveThirdParty contained set_cookie_flag
" Embed websockify into Nginx (convert any tcp connection into websocket)
" https://github.com/tg123/websockify-nginx-module
syn keyword ngxDirectiveThirdParty contained websockify_buffer_size
syn keyword ngxDirectiveThirdParty contained websockify_connect_timeout
syn keyword ngxDirectiveThirdParty contained websockify_pass
syn keyword ngxDirectiveThirdParty contained websockify_read_timeout
syn keyword ngxDirectiveThirdParty contained websockify_send_timeout
" IP2Location Nginx
" https://github.com/ip2location/ip2location-nginx
syn keyword ngxDirectiveThirdParty contained ip2location
syn keyword ngxDirectiveThirdParty contained ip2location_access_type
syn keyword ngxDirectiveThirdParty contained ip2location_proxy
syn keyword ngxDirectiveThirdParty contained ip2location_proxy_recursive
" IP2Proxy module for Nginx
" https://github.com/ip2location/ip2proxy-nginx
syn keyword ngxDirectiveThirdParty contained ip2proxy
syn keyword ngxDirectiveThirdParty contained ip2proxy_access_type
syn keyword ngxDirectiveThirdParty contained ip2proxy_as
syn keyword ngxDirectiveThirdParty contained ip2proxy_asn
syn keyword ngxDirectiveThirdParty contained ip2proxy_city
syn keyword ngxDirectiveThirdParty contained ip2proxy_country_long
syn keyword ngxDirectiveThirdParty contained ip2proxy_country_short
syn keyword ngxDirectiveThirdParty contained ip2proxy_database
syn keyword ngxDirectiveThirdParty contained ip2proxy_domain
syn keyword ngxDirectiveThirdParty contained ip2proxy_is_proxy
syn keyword ngxDirectiveThirdParty contained ip2proxy_isp
syn keyword ngxDirectiveThirdParty contained ip2proxy_last_seen
syn keyword ngxDirectiveThirdParty contained ip2proxy_proxy_type
syn keyword ngxDirectiveThirdParty contained ip2proxy_region
syn keyword ngxDirectiveThirdParty contained ip2proxy_reverse_proxy
syn keyword ngxDirectiveThirdParty contained ip2proxy_usage_type
+397
View File
@@ -5,6 +5,403 @@
<change_log title="nginx"> <change_log title="nginx">
<changes ver="1.19.2" date="2020-08-11">
<change type="change">
<para lang="ru">
теперь nginx начинает закрывать keepalive-соединения,
не дожидаясь исчерпания всех свободных соединений,
а также пишет об этом предупреждение в лог ошибок.
</para>
<para lang="en">
now nginx starts closing keepalive connections
before all free worker connections are exhausted,
and logs a warning about this to the error log.
</para>
</change>
<change type="change">
<para lang="ru">
оптимизация чтения тела запроса
при использовании chunked transfer encoding.
</para>
<para lang="en">
optimization of client request body reading
when using chunked transfer encoding.
</para>
</change>
<change type="bugfix">
<para lang="ru">
утечки памяти при использовании директивы ssl_ocsp.
</para>
<para lang="en">
memory leak if the "ssl_ocsp" directive was used.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в логах могли появляться сообщения "zero size buf in output",
если FastCGI-сервер возвращал некорректный ответ;
ошибка появилась в 1.19.1.
</para>
<para lang="en">
"zero size buf in output" alerts might appear in logs
if a FastCGI server returned an incorrect response;
the bug had appeared in 1.19.1.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если размеры large_client_header_buffers отличались
в разных виртуальных серверах.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if different large_client_header_buffers sizes were used
in different virtual servers.
</para>
</change>
<change type="bugfix">
<para lang="ru">
SSL shutdown мог не работать.
</para>
<para lang="en">
SSL shutdown might not work.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в логах могли появляться сообщения
"SSL_shutdown() failed (SSL: ... bad write retry)".
</para>
<para lang="en">
"SSL_shutdown() failed (SSL: ... bad write retry)"
messages might appear in logs.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в модуле ngx_http_slice_module.
</para>
<para lang="en">
in the ngx_http_slice_module.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в модуле ngx_http_xslt_filter_module.
</para>
<para lang="en">
in the ngx_http_xslt_filter_module.
</para>
</change>
</changes>
<changes ver="1.19.1" date="2020-07-07">
<change type="change">
<para lang="ru">
директивы lingering_close, lingering_time и lingering_timeout
теперь работают при использовании HTTP/2.
</para>
<para lang="en">
the "lingering_close", "lingering_time", and "lingering_timeout" directives
now work when using HTTP/2.
</para>
</change>
<change type="change">
<para lang="ru">
теперь лишние данные, присланные бэкендом, всегда отбрасываются.
</para>
<para lang="en">
now extra data sent by a backend are always discarded.
</para>
</change>
<change type="change">
<para lang="ru">
теперь при получении слишком короткого ответа от FastCGI-сервера
nginx пытается отправить клиенту доступную часть ответа,
после чего закрывает соединение с клиентом.
</para>
<para lang="en">
now after receiving a too short response from a FastCGI server
nginx tries to send the available part of the response to the client,
and then closes the client connection.
</para>
</change>
<change type="change">
<para lang="ru">
теперь при получении ответа некорректной длины от gRPC-бэкенда
nginx прекращает обработку ответа с ошибкой.
</para>
<para lang="en">
now after receiving a response with incorrect length from a gRPC backend
nginx stops response processing with an error.
</para>
</change>
<change type="feature">
<para lang="ru">
параметр min_free в директивах proxy_cache_path, fastcgi_cache_path,
scgi_cache_path и uwsgi_cache_path.<br/>
Спасибо Adam Bambuch.
</para>
<para lang="en">
the "min_free" parameter of the "proxy_cache_path", "fastcgi_cache_path",
"scgi_cache_path", and "uwsgi_cache_path" directives.<br/>
Thanks to Adam Bambuch.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx не удалял unix domain listen-сокеты
при плавном завершении по сигналу SIGQUIT.
</para>
<para lang="en">
nginx did not delete unix domain listen sockets
during graceful shutdown on the SIGQUIT signal.
</para>
</change>
<change type="bugfix">
<para lang="ru">
UDP-пакеты нулевого размера не проксировались.
</para>
<para lang="en">
zero length UDP datagrams were not proxied.
</para>
</change>
<change type="bugfix">
<para lang="ru">
проксирование на uwsgi-бэкенды с использованием SSL могло не работать.<br/>
Спасибо Guanzhong Chen.
</para>
<para lang="en">
proxying to uwsgi backends using SSL might not work.<br/>
Thanks to Guanzhong Chen.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в обработке ошибок при использовании директивы ssl_ocsp.
</para>
<para lang="en">
in error handling when using the "ssl_ocsp" directive.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при использовании файловых систем XFS и NFS
размер кэша на диске мог считаться некорректно.
</para>
<para lang="en">
on XFS and NFS file systems
disk cache size might be calculated incorrectly.
</para>
</change>
<change type="bugfix">
<para lang="ru">
если сервер memcached возвращал некорректный ответ,
в логах могли появляться сообщения "negative size buf in writer".
</para>
<para lang="en">
"negative size buf in writer" alerts might appear in logs
if a memcached server returned a malformed response.
</para>
</change>
</changes>
<changes ver="1.19.0" date="2020-05-26">
<change type="feature">
<para lang="ru">
проверка клиентских сертификатов с помощью OCSP.
</para>
<para lang="en">
client certificate validation with OCSP.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при работе с gRPC-бэкендами
могли возникать ошибки "upstream sent frame for closed stream".
</para>
<para lang="en">
"upstream sent frame for closed stream" errors might occur
when working with gRPC backends.
</para>
</change>
<change type="bugfix">
<para lang="ru">
OCSP stapling мог не работать,
если не была указана директива resolver.
</para>
<para lang="en">
OCSP stapling might not work
if the "resolver" directive was not specified.
</para>
</change>
<change type="bugfix">
<para lang="ru">
соединения с некорректным HTTP/2 preface не логгировались.
</para>
<para lang="en">
connections with incorrect HTTP/2 preface were not logged.
</para>
</change>
</changes>
<changes ver="1.17.10" date="2020-04-14">
<change type="feature">
<para lang="ru">
директива auth_delay.
</para>
<para lang="en">
the "auth_delay" directive.
</para>
</change>
</changes>
<changes ver="1.17.9" date="2020-03-03">
<change type="change">
<para lang="ru">
теперь nginx не разрешает
несколько строк "Host" в заголовке запроса.
</para>
<para lang="en">
now nginx does not allow
several "Host" request header lines.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx игнорировал дополнительные
строки "Transfer-Encoding" в заголовке запроса.
</para>
<para lang="en">
nginx ignored additional
"Transfer-Encoding" request header lines.
</para>
</change>
<change type="bugfix">
<para lang="ru">
утечки сокетов при использовании HTTP/2.
</para>
<para lang="en">
socket leak when using HTTP/2.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если использовался OCSP stapling.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if OCSP stapling was used.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в модуле ngx_http_mp4_module.
</para>
<para lang="en">
in the ngx_http_mp4_module.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при перенаправлении ошибок с кодом 494 с помощью директивы error_page
nginx возвращал ответ с кодом 494 вместо 400.
</para>
<para lang="en">
nginx used status code 494 instead of 400
if errors with code 494 were redirected with the "error_page" directive.
</para>
</change>
<change type="bugfix">
<para lang="ru">
утечки сокетов при использовании подзапросов в модуле njs и директивы aio.
</para>
<para lang="en">
socket leak when using subrequests in the njs module and the "aio" directive.
</para>
</change>
</changes>
<changes ver="1.17.8" date="2020-01-21">
<change type="feature">
<para lang="ru">
директива grpc_pass поддерживает переменные.
</para>
<para lang="en">
variables support in the "grpc_pass" directive.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при обработке pipelined-запросов по SSL-соединению мог произойти таймаут;
ошибка появилась в 1.17.5.
</para>
<para lang="en">
a timeout might occur while handling pipelined requests in an SSL connection;
the bug had appeared in 1.17.5.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в директиве debug_points при использовании HTTP/2.<br/>
Спасибо Даниилу Бондареву.
</para>
<para lang="en">
in the "debug_points" directive when using HTTP/2.<br/>
Thanks to Daniil Bondarev.
</para>
</change>
</changes>
<changes ver="1.17.7" date="2019-12-24"> <changes ver="1.17.7" date="2019-12-24">
<change type="bugfix"> <change type="bugfix">
+2 -2
View File
@@ -6,9 +6,9 @@ TEMP = tmp
CC = cl CC = cl
OBJS = objs.msvc8 OBJS = objs.msvc8
OPENSSL = openssl-1.1.1d OPENSSL = openssl-1.1.1g
ZLIB = zlib-1.2.11 ZLIB = zlib-1.2.11
PCRE = pcre-8.43 PCRE = pcre-8.44
release: export release: export
+1
View File
@@ -492,6 +492,7 @@ ngx_add_inherited_sockets(ngx_cycle_t *cycle)
ngx_memzero(ls, sizeof(ngx_listening_t)); ngx_memzero(ls, sizeof(ngx_listening_t));
ls->fd = (ngx_socket_t) s; ls->fd = (ngx_socket_t) s;
ls->inherited = 1;
} }
} }
+2 -2
View File
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_ #define _NGINX_H_INCLUDED_
#define nginx_version 1017008 #define nginx_version 1019003
#define NGINX_VERSION "1.17.8" #define NGINX_VERSION "1.19.3"
#define NGINX_VER "nginx/" NGINX_VERSION " by Hakase" #define NGINX_VER "nginx/" NGINX_VERSION " by Hakase"
#ifndef NGINX_SERVER #ifndef NGINX_SERVER
+10 -10
View File
@@ -125,20 +125,20 @@ typedef struct {
#define NGX_CHAIN_ERROR (ngx_chain_t *) NGX_ERROR #define NGX_CHAIN_ERROR (ngx_chain_t *) NGX_ERROR
#define ngx_buf_in_memory(b) (b->temporary || b->memory || b->mmap) #define ngx_buf_in_memory(b) ((b)->temporary || (b)->memory || (b)->mmap)
#define ngx_buf_in_memory_only(b) (ngx_buf_in_memory(b) && !b->in_file) #define ngx_buf_in_memory_only(b) (ngx_buf_in_memory(b) && !(b)->in_file)
#define ngx_buf_special(b) \ #define ngx_buf_special(b) \
((b->flush || b->last_buf || b->sync) \ (((b)->flush || (b)->last_buf || (b)->sync) \
&& !ngx_buf_in_memory(b) && !b->in_file) && !ngx_buf_in_memory(b) && !(b)->in_file)
#define ngx_buf_sync_only(b) \ #define ngx_buf_sync_only(b) \
(b->sync \ ((b)->sync && !ngx_buf_in_memory(b) \
&& !ngx_buf_in_memory(b) && !b->in_file && !b->flush && !b->last_buf) && !(b)->in_file && !(b)->flush && !(b)->last_buf)
#define ngx_buf_size(b) \ #define ngx_buf_size(b) \
(ngx_buf_in_memory(b) ? (off_t) (b->last - b->pos): \ (ngx_buf_in_memory(b) ? (off_t) ((b)->last - (b)->pos): \
(b->file_last - b->file_pos)) ((b)->file_last - (b)->file_pos))
ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size); ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size);
ngx_chain_t *ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs); ngx_chain_t *ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs);
@@ -149,8 +149,8 @@ ngx_chain_t *ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs);
ngx_chain_t *ngx_alloc_chain_link(ngx_pool_t *pool); ngx_chain_t *ngx_alloc_chain_link(ngx_pool_t *pool);
#define ngx_free_chain(pool, cl) \ #define ngx_free_chain(pool, cl) \
cl->next = pool->chain; \ (cl)->next = (pool)->chain; \
pool->chain = cl (pool)->chain = (cl)
+19 -6
View File
@@ -1070,7 +1070,8 @@ ngx_close_listening_sockets(ngx_cycle_t *cycle)
if (ls[i].sockaddr->sa_family == AF_UNIX if (ls[i].sockaddr->sa_family == AF_UNIX
&& ngx_process <= NGX_PROCESS_MASTER && ngx_process <= NGX_PROCESS_MASTER
&& ngx_new_binary == 0) && ngx_new_binary == 0
&& (!ls[i].inherited || ngx_getppid() != ngx_parent))
{ {
u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1; u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1;
@@ -1106,12 +1107,9 @@ ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
return NULL; return NULL;
} }
c = ngx_cycle->free_connections; ngx_drain_connections((ngx_cycle_t *) ngx_cycle);
if (c == NULL) { c = ngx_cycle->free_connections;
ngx_drain_connections((ngx_cycle_t *) ngx_cycle);
c = ngx_cycle->free_connections;
}
if (c == NULL) { if (c == NULL) {
ngx_log_error(NGX_LOG_ALERT, log, 0, ngx_log_error(NGX_LOG_ALERT, log, 0,
@@ -1297,6 +1295,21 @@ ngx_drain_connections(ngx_cycle_t *cycle)
ngx_queue_t *q; ngx_queue_t *q;
ngx_connection_t *c; ngx_connection_t *c;
if (cycle->free_connection_n > cycle->connection_n / 16
|| cycle->reusable_connections_n == 0)
{
return;
}
if (cycle->connections_reuse_time != ngx_time()) {
cycle->connections_reuse_time = ngx_time();
ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
"%ui worker_connections are not enough, "
"reusing connections",
cycle->connection_n);
}
n = ngx_max(ngx_min(32, cycle->reusable_connections_n / 8), 1); n = ngx_max(ngx_min(32, cycle->reusable_connections_n / 8), 1);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
+6 -2
View File
@@ -520,6 +520,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
== NGX_OK) == NGX_OK)
{ {
nls[n].fd = ls[i].fd; nls[n].fd = ls[i].fd;
nls[n].inherited = ls[i].inherited;
nls[n].previous = &ls[i]; nls[n].previous = &ls[i];
ls[i].remain = 1; ls[i].remain = 1;
@@ -1008,6 +1009,7 @@ ngx_int_t
ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log) ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
{ {
size_t len; size_t len;
ngx_int_t rc;
ngx_uint_t create; ngx_uint_t create;
ngx_file_t file; ngx_file_t file;
u_char pid[NGX_INT64_LEN + 2]; u_char pid[NGX_INT64_LEN + 2];
@@ -1032,11 +1034,13 @@ ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
return NGX_ERROR; return NGX_ERROR;
} }
rc = NGX_OK;
if (!ngx_test_config) { if (!ngx_test_config) {
len = ngx_snprintf(pid, NGX_INT64_LEN + 2, "%P%N", ngx_pid) - pid; len = ngx_snprintf(pid, NGX_INT64_LEN + 2, "%P%N", ngx_pid) - pid;
if (ngx_write_file(&file, pid, len, 0) == NGX_ERROR) { if (ngx_write_file(&file, pid, len, 0) == NGX_ERROR) {
return NGX_ERROR; rc = NGX_ERROR;
} }
} }
@@ -1045,7 +1049,7 @@ ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
ngx_close_file_n " \"%s\" failed", file.name.data); ngx_close_file_n " \"%s\" failed", file.name.data);
} }
return NGX_OK; return rc;
} }
+1
View File
@@ -55,6 +55,7 @@ struct ngx_cycle_s {
ngx_queue_t reusable_connections_queue; ngx_queue_t reusable_connections_queue;
ngx_uint_t reusable_connections_n; ngx_uint_t reusable_connections_n;
time_t connections_reuse_time;
ngx_array_t listening; ngx_array_t listening;
ngx_array_t paths; ngx_array_t paths;
+1 -1
View File
@@ -238,6 +238,7 @@ ngx_process_events_and_timers(ngx_cycle_t *cycle)
} }
if (!ngx_queue_empty(&ngx_posted_next_events)) { if (!ngx_queue_empty(&ngx_posted_next_events)) {
ngx_event_move_posted_next(cycle);
timer = 0; timer = 0;
} }
@@ -261,7 +262,6 @@ ngx_process_events_and_timers(ngx_cycle_t *cycle)
} }
ngx_event_process_posted(cycle, &ngx_posted_events); ngx_event_process_posted(cycle, &ngx_posted_events);
ngx_event_process_posted_next(cycle, &ngx_posted_next_events);
} }
+113 -45
View File
@@ -130,6 +130,7 @@ int ngx_ssl_connection_index;
int ngx_ssl_server_conf_index; int ngx_ssl_server_conf_index;
int ngx_ssl_session_cache_index; int ngx_ssl_session_cache_index;
int ngx_ssl_session_ticket_keys_index; int ngx_ssl_session_ticket_keys_index;
int ngx_ssl_ocsp_index;
int ngx_ssl_certificate_index; int ngx_ssl_certificate_index;
int ngx_ssl_next_certificate_index; int ngx_ssl_next_certificate_index;
int ngx_ssl_certificate_name_index; int ngx_ssl_certificate_name_index;
@@ -213,6 +214,13 @@ ngx_ssl_init(ngx_log_t *log)
return NGX_ERROR; return NGX_ERROR;
} }
ngx_ssl_ocsp_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
if (ngx_ssl_ocsp_index == -1) {
ngx_ssl_error(NGX_LOG_ALERT, log, 0,
"SSL_CTX_get_ex_new_index() failed");
return NGX_ERROR;
}
ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
NULL); NULL);
if (ngx_ssl_certificate_index == -1) { if (ngx_ssl_certificate_index == -1) {
@@ -920,6 +928,9 @@ ngx_int_t
ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
ngx_int_t depth) ngx_int_t depth)
{ {
SSL_CTX_set_verify(ssl->ctx, SSL_CTX_get_verify_mode(ssl->ctx),
ngx_ssl_verify_callback);
SSL_CTX_set_verify_depth(ssl->ctx, depth); SSL_CTX_set_verify_depth(ssl->ctx, depth);
if (cert->len == 0) { if (cert->len == 0) {
@@ -1603,6 +1614,7 @@ ngx_ssl_handshake(ngx_connection_t *c)
{ {
int n, sslerr; int n, sslerr;
ngx_err_t err; ngx_err_t err;
ngx_int_t rc;
#ifdef SSL_READ_EARLY_DATA_SUCCESS #ifdef SSL_READ_EARLY_DATA_SUCCESS
if (c->ssl->try_early_data) { if (c->ssl->try_early_data) {
@@ -1610,6 +1622,10 @@ ngx_ssl_handshake(ngx_connection_t *c)
} }
#endif #endif
if (c->ssl->in_ocsp) {
return ngx_ssl_ocsp_validate(c);
}
ngx_ssl_clear_error(c->log); ngx_ssl_clear_error(c->log);
n = SSL_do_handshake(c->ssl->connection); n = SSL_do_handshake(c->ssl->connection);
@@ -1630,8 +1646,6 @@ ngx_ssl_handshake(ngx_connection_t *c)
ngx_ssl_handshake_log(c); ngx_ssl_handshake_log(c);
#endif #endif
c->ssl->handshaked = 1;
c->recv = ngx_ssl_recv; c->recv = ngx_ssl_recv;
c->send = ngx_ssl_write; c->send = ngx_ssl_write;
c->recv_chain = ngx_ssl_recv_chain; c->recv_chain = ngx_ssl_recv_chain;
@@ -1650,6 +1664,20 @@ ngx_ssl_handshake(ngx_connection_t *c)
#endif #endif
#endif #endif
rc = ngx_ssl_ocsp_validate(c);
if (rc == NGX_ERROR) {
return NGX_ERROR;
}
if (rc == NGX_AGAIN) {
c->read->handler = ngx_ssl_handshake_handler;
c->write->handler = ngx_ssl_handshake_handler;
return NGX_AGAIN;
}
c->ssl->handshaked = 1;
return NGX_OK; return NGX_OK;
} }
@@ -1719,6 +1747,7 @@ ngx_ssl_try_early_data(ngx_connection_t *c)
u_char buf; u_char buf;
size_t readbytes; size_t readbytes;
ngx_err_t err; ngx_err_t err;
ngx_int_t rc;
ngx_ssl_clear_error(c->log); ngx_ssl_clear_error(c->log);
@@ -1753,7 +1782,6 @@ ngx_ssl_try_early_data(ngx_connection_t *c)
c->ssl->early_buf = buf; c->ssl->early_buf = buf;
c->ssl->early_preread = 1; c->ssl->early_preread = 1;
c->ssl->handshaked = 1;
c->ssl->in_early = 1; c->ssl->in_early = 1;
c->recv = ngx_ssl_recv; c->recv = ngx_ssl_recv;
@@ -1761,6 +1789,20 @@ ngx_ssl_try_early_data(ngx_connection_t *c)
c->recv_chain = ngx_ssl_recv_chain; c->recv_chain = ngx_ssl_recv_chain;
c->send_chain = ngx_ssl_send_chain; c->send_chain = ngx_ssl_send_chain;
rc = ngx_ssl_ocsp_validate(c);
if (rc == NGX_ERROR) {
return NGX_ERROR;
}
if (rc == NGX_AGAIN) {
c->read->handler = ngx_ssl_handshake_handler;
c->write->handler = ngx_ssl_handshake_handler;
return NGX_AGAIN;
}
c->ssl->handshaked = 1;
return NGX_OK; return NGX_OK;
} }
@@ -2026,6 +2068,10 @@ ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
c->read->available = 0; c->read->available = 0;
c->read->ready = 0; c->read->ready = 0;
if (c->read->posted) {
ngx_delete_posted_event(c->read);
}
ngx_post_event(c->read, &ngx_posted_next_events); ngx_post_event(c->read, &ngx_posted_next_events);
} }
@@ -2775,8 +2821,11 @@ ngx_ssl_free_buffer(ngx_connection_t *c)
ngx_int_t ngx_int_t
ngx_ssl_shutdown(ngx_connection_t *c) ngx_ssl_shutdown(ngx_connection_t *c)
{ {
int n, sslerr, mode; int n, sslerr, mode;
ngx_err_t err; ngx_err_t err;
ngx_uint_t tries;
ngx_ssl_ocsp_cleanup(c);
if (SSL_in_init(c->ssl->connection)) { if (SSL_in_init(c->ssl->connection)) {
/* /*
@@ -2815,55 +2864,71 @@ ngx_ssl_shutdown(ngx_connection_t *c)
ngx_ssl_clear_error(c->log); ngx_ssl_clear_error(c->log);
n = SSL_shutdown(c->ssl->connection); tries = 2;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n); for ( ;; ) {
sslerr = 0; /*
* For bidirectional shutdown, SSL_shutdown() needs to be called
* twice: first call sends the "close notify" alert and returns 0,
* second call waits for the peer's "close notify" alert.
*/
/* before 0.9.8m SSL_shutdown() returned 0 instead of -1 on errors */ n = SSL_shutdown(c->ssl->connection);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
if (n == 1) {
SSL_free(c->ssl->connection);
c->ssl = NULL;
return NGX_OK;
}
if (n == 0 && tries-- > 1) {
continue;
}
/* before 0.9.8m SSL_shutdown() returned 0 instead of -1 on errors */
if (n != 1 && ERR_peek_error()) {
sslerr = SSL_get_error(c->ssl->connection, n); sslerr = SSL_get_error(c->ssl->connection, n);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"SSL_get_error: %d", sslerr); "SSL_get_error: %d", sslerr);
}
if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) { if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
c->read->handler = ngx_ssl_shutdown_handler;
c->write->handler = ngx_ssl_shutdown_handler;
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
return NGX_ERROR;
}
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
return NGX_ERROR;
}
ngx_add_timer(c->read, 3000);
return NGX_AGAIN;
}
if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
SSL_free(c->ssl->connection);
c->ssl = NULL;
return NGX_OK;
}
err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
SSL_free(c->ssl->connection); SSL_free(c->ssl->connection);
c->ssl = NULL; c->ssl = NULL;
return NGX_OK; return NGX_ERROR;
} }
if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
c->read->handler = ngx_ssl_shutdown_handler;
c->write->handler = ngx_ssl_shutdown_handler;
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
return NGX_ERROR;
}
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
return NGX_ERROR;
}
if (sslerr == SSL_ERROR_WANT_READ) {
ngx_add_timer(c->read, 30000);
}
return NGX_AGAIN;
}
err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
SSL_free(c->ssl->connection);
c->ssl = NULL;
return NGX_ERROR;
} }
@@ -4959,11 +5024,14 @@ ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
rc = SSL_get_verify_result(c->ssl->connection); rc = SSL_get_verify_result(c->ssl->connection);
if (rc == X509_V_OK) { if (rc == X509_V_OK) {
ngx_str_set(s, "SUCCESS"); if (ngx_ssl_ocsp_get_status(c, &str) == NGX_OK) {
return NGX_OK; ngx_str_set(s, "SUCCESS");
} return NGX_OK;
}
str = X509_verify_cert_error_string(rc); } else {
str = X509_verify_cert_error_string(rc);
}
s->data = ngx_pnalloc(pool, sizeof("FAILED:") - 1 + ngx_strlen(str)); s->data = ngx_pnalloc(pool, sizeof("FAILED:") - 1 + ngx_strlen(str));
if (s->data == NULL) { if (s->data == NULL) {
+15
View File
@@ -72,6 +72,9 @@ typedef struct {
} ngx_ssl_dyn_rec_t; } ngx_ssl_dyn_rec_t;
typedef struct ngx_ssl_ocsp_s ngx_ssl_ocsp_t;
struct ngx_ssl_s { struct ngx_ssl_s {
SSL_CTX *ctx; SSL_CTX *ctx;
ngx_log_t *log; ngx_log_t *log;
@@ -96,6 +99,8 @@ struct ngx_ssl_connection_s {
ngx_event_handler_pt saved_read_handler; ngx_event_handler_pt saved_read_handler;
ngx_event_handler_pt saved_write_handler; ngx_event_handler_pt saved_write_handler;
ngx_ssl_ocsp_t *ocsp;
u_char early_buf; u_char early_buf;
unsigned handshaked:1; unsigned handshaked:1;
@@ -106,6 +111,7 @@ struct ngx_ssl_connection_s {
unsigned handshake_buffer_set:1; unsigned handshake_buffer_set:1;
unsigned try_early_data:1; unsigned try_early_data:1;
unsigned in_early:1; unsigned in_early:1;
unsigned in_ocsp:1;
unsigned early_preread:1; unsigned early_preread:1;
unsigned write_blocked:1; unsigned write_blocked:1;
@@ -193,6 +199,14 @@ ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify); ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify);
ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_resolver_t *resolver, ngx_msec_t resolver_timeout); ngx_resolver_t *resolver, ngx_msec_t resolver_timeout);
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);
RSA *ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export, RSA *ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
int key_length); int key_length);
ngx_array_t *ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file); ngx_array_t *ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file);
@@ -294,6 +308,7 @@ extern int ngx_ssl_connection_index;
extern int ngx_ssl_server_conf_index; extern int ngx_ssl_server_conf_index;
extern int ngx_ssl_session_cache_index; extern int ngx_ssl_session_cache_index;
extern int ngx_ssl_session_ticket_keys_index; extern int ngx_ssl_session_ticket_keys_index;
extern int ngx_ssl_ocsp_index;
extern int ngx_ssl_certificate_index; extern int ngx_ssl_certificate_index;
extern int ngx_ssl_next_certificate_index; extern int ngx_ssl_next_certificate_index;
extern int ngx_ssl_certificate_name_index; extern int ngx_ssl_certificate_name_index;
+1065 -173
View File
@@ -22,6 +22,7 @@ typedef struct {
ngx_msec_t resolver_timeout; ngx_msec_t resolver_timeout;
ngx_addr_t *addrs; ngx_addr_t *addrs;
ngx_uint_t naddrs;
ngx_str_t host; ngx_str_t host;
ngx_str_t uri; ngx_str_t uri;
in_port_t port; in_port_t port;
@@ -30,6 +31,7 @@ typedef struct {
X509 *cert; X509 *cert;
X509 *issuer; X509 *issuer;
STACK_OF(X509) *chain;
u_char *name; u_char *name;
@@ -41,15 +43,66 @@ typedef struct {
} ngx_ssl_stapling_t; } ngx_ssl_stapling_t;
typedef struct {
ngx_addr_t *addrs;
ngx_uint_t naddrs;
ngx_str_t host;
ngx_str_t uri;
in_port_t port;
ngx_uint_t depth;
ngx_shm_zone_t *shm_zone;
ngx_resolver_t *resolver;
ngx_msec_t resolver_timeout;
} ngx_ssl_ocsp_conf_t;
typedef struct {
ngx_rbtree_t rbtree;
ngx_rbtree_node_t sentinel;
ngx_queue_t expire_queue;
} ngx_ssl_ocsp_cache_t;
typedef struct {
ngx_str_node_t node;
ngx_queue_t queue;
int status;
time_t valid;
} ngx_ssl_ocsp_cache_node_t;
typedef struct ngx_ssl_ocsp_ctx_s ngx_ssl_ocsp_ctx_t; typedef struct ngx_ssl_ocsp_ctx_s ngx_ssl_ocsp_ctx_t;
struct ngx_ssl_ocsp_s {
STACK_OF(X509) *certs;
ngx_uint_t ncert;
int cert_status;
ngx_int_t status;
ngx_ssl_ocsp_conf_t *conf;
ngx_ssl_ocsp_ctx_t *ctx;
};
struct ngx_ssl_ocsp_ctx_s { struct ngx_ssl_ocsp_ctx_s {
SSL_CTX *ssl_ctx;
X509 *cert; X509 *cert;
X509 *issuer; X509 *issuer;
STACK_OF(X509) *chain;
int status;
time_t valid;
u_char *name; u_char *name;
ngx_uint_t naddrs; ngx_uint_t naddrs;
ngx_uint_t naddr;
ngx_addr_t *addrs; ngx_addr_t *addrs;
ngx_str_t host; ngx_str_t host;
@@ -64,17 +117,20 @@ struct ngx_ssl_ocsp_ctx_s {
void (*handler)(ngx_ssl_ocsp_ctx_t *ctx); void (*handler)(ngx_ssl_ocsp_ctx_t *ctx);
void *data; void *data;
ngx_str_t key;
ngx_buf_t *request; ngx_buf_t *request;
ngx_buf_t *response; ngx_buf_t *response;
ngx_peer_connection_t peer; ngx_peer_connection_t peer;
ngx_shm_zone_t *shm_zone;
ngx_int_t (*process)(ngx_ssl_ocsp_ctx_t *ctx); ngx_int_t (*process)(ngx_ssl_ocsp_ctx_t *ctx);
ngx_uint_t state; ngx_uint_t state;
ngx_uint_t code; ngx_uint_t code;
ngx_uint_t count; ngx_uint_t count;
ngx_uint_t flags;
ngx_uint_t done; ngx_uint_t done;
u_char *header_name_start; u_char *header_name_start;
@@ -105,8 +161,14 @@ static time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time);
static void ngx_ssl_stapling_cleanup(void *data); static void ngx_ssl_stapling_cleanup(void *data);
static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(void); static void ngx_ssl_ocsp_validate_next(ngx_connection_t *c);
static void ngx_ssl_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);
static ngx_int_t ngx_ssl_ocsp_responder(ngx_connection_t *c,
ngx_ssl_ocsp_ctx_t *ctx);
static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(ngx_log_t *log);
static void ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx); static void ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx);
static void ngx_ssl_ocsp_next(ngx_ssl_ocsp_ctx_t *ctx);
static void ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx); static void ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx);
static void ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve); static void ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve);
static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx); static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx);
@@ -120,6 +182,11 @@ static ngx_int_t ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx);
static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx); static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx);
static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx); static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx);
static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx); static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx);
static ngx_int_t ngx_ssl_ocsp_verify(ngx_ssl_ocsp_ctx_t *ctx);
static ngx_int_t ngx_ssl_ocsp_cache_lookup(ngx_ssl_ocsp_ctx_t *ctx);
static ngx_int_t ngx_ssl_ocsp_cache_store(ngx_ssl_ocsp_ctx_t *ctx);
static ngx_int_t ngx_ssl_ocsp_create_key(ngx_ssl_ocsp_ctx_t *ctx);
static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len); static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len);
@@ -173,6 +240,18 @@ ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, X509 *cert,
return NGX_ERROR; return NGX_ERROR;
} }
#ifdef SSL_CTRL_SELECT_CURRENT_CERT
/* OpenSSL 1.0.2+ */
SSL_CTX_select_current_cert(ssl->ctx, cert);
#endif
#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
/* OpenSSL 1.0.1+ */
SSL_CTX_get_extra_chain_certs(ssl->ctx, &staple->chain);
#else
staple->chain = ssl->ctx->extra_certs;
#endif
staple->ssl_ctx = ssl->ctx; staple->ssl_ctx = ssl->ctx;
staple->timeout = 60000; staple->timeout = 60000;
staple->verify = verify; staple->verify = verify;
@@ -289,29 +368,16 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl,
X509 *cert, *issuer; X509 *cert, *issuer;
X509_STORE *store; X509_STORE *store;
X509_STORE_CTX *store_ctx; X509_STORE_CTX *store_ctx;
STACK_OF(X509) *chain;
cert = staple->cert; cert = staple->cert;
#ifdef SSL_CTRL_SELECT_CURRENT_CERT n = sk_X509_num(staple->chain);
/* OpenSSL 1.0.2+ */
SSL_CTX_select_current_cert(ssl->ctx, cert);
#endif
#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
/* OpenSSL 1.0.1+ */
SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain);
#else
chain = ssl->ctx->extra_certs;
#endif
n = sk_X509_num(chain);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
"SSL get issuer: %d extra certs", n); "SSL get issuer: %d extra certs", n);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
issuer = sk_X509_value(chain, i); issuer = sk_X509_value(staple->chain, i);
if (X509_check_issued(issuer, cert) == X509_V_OK) { if (X509_check_issued(issuer, cert) == X509_V_OK) {
#if OPENSSL_VERSION_NUMBER >= 0x10100001L #if OPENSSL_VERSION_NUMBER >= 0x10100001L
X509_up_ref(issuer); X509_up_ref(issuer);
@@ -462,6 +528,7 @@ ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
} }
staple->addrs = u.addrs; staple->addrs = u.addrs;
staple->naddrs = u.naddrs;
staple->host = u.host; staple->host = u.host;
staple->uri = u.uri; staple->uri = u.uri;
staple->port = u.port; staple->port = u.port;
@@ -559,16 +626,20 @@ ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
staple->loading = 1; staple->loading = 1;
ctx = ngx_ssl_ocsp_start(); ctx = ngx_ssl_ocsp_start(ngx_cycle->log);
if (ctx == NULL) { if (ctx == NULL) {
return; return;
} }
ctx->ssl_ctx = staple->ssl_ctx;
ctx->cert = staple->cert; ctx->cert = staple->cert;
ctx->issuer = staple->issuer; ctx->issuer = staple->issuer;
ctx->chain = staple->chain;
ctx->name = staple->name; ctx->name = staple->name;
ctx->flags = (staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY);
ctx->addrs = staple->addrs; ctx->addrs = staple->addrs;
ctx->naddrs = staple->naddrs;
ctx->host = staple->host; ctx->host = staple->host;
ctx->uri = staple->uri; ctx->uri = staple->uri;
ctx->port = staple->port; ctx->port = staple->port;
@@ -589,137 +660,27 @@ ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
static void static void
ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx) ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
{ {
int n; time_t now;
size_t len; ngx_str_t response;
time_t now, valid; ngx_ssl_stapling_t *staple;
ngx_str_t response;
X509_STORE *store;
const u_char *p;
STACK_OF(X509) *chain;
OCSP_CERTID *id;
OCSP_RESPONSE *ocsp;
OCSP_BASICRESP *basic;
ngx_ssl_stapling_t *staple;
ASN1_GENERALIZEDTIME *thisupdate, *nextupdate;
staple = ctx->data; staple = ctx->data;
now = ngx_time(); now = ngx_time();
ocsp = NULL;
basic = NULL;
id = NULL;
if (ctx->code != 200) { if (ngx_ssl_ocsp_verify(ctx) != NGX_OK) {
goto error; goto error;
} }
/* check the response */ if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
len = ctx->response->last - ctx->response->pos;
p = ctx->response->pos;
ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
if (ocsp == NULL) {
ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
"d2i_OCSP_RESPONSE() failed");
goto error;
}
n = OCSP_response_status(ocsp);
if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
"OCSP response not successful (%d: %s)",
n, OCSP_response_status_str(n));
goto error;
}
basic = OCSP_response_get1_basic(ocsp);
if (basic == NULL) {
ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
"OCSP_response_get1_basic() failed");
goto error;
}
store = SSL_CTX_get_cert_store(staple->ssl_ctx);
if (store == NULL) {
ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
"SSL_CTX_get_cert_store() failed");
goto error;
}
#ifdef SSL_CTRL_SELECT_CURRENT_CERT
/* OpenSSL 1.0.2+ */
SSL_CTX_select_current_cert(staple->ssl_ctx, ctx->cert);
#endif
#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
/* OpenSSL 1.0.1+ */
SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain);
#else
chain = staple->ssl_ctx->extra_certs;
#endif
if (OCSP_basic_verify(basic, chain, store,
staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY)
!= 1)
{
ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
"OCSP_basic_verify() failed");
goto error;
}
id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
if (id == NULL) {
ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
"OCSP_cert_to_id() failed");
goto error;
}
if (OCSP_resp_find_status(basic, id, &n, NULL, NULL,
&thisupdate, &nextupdate)
!= 1)
{
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
"certificate status not found in the OCSP response");
goto error;
}
if (n != V_OCSP_CERTSTATUS_GOOD) {
ngx_log_error(NGX_LOG_ERR, ctx->log, 0, ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
"certificate status \"%s\" in the OCSP response", "certificate status \"%s\" in the OCSP response",
OCSP_cert_status_str(n)); OCSP_cert_status_str(ctx->status));
goto error; goto error;
} }
if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
"OCSP_check_validity() failed");
goto error;
}
if (nextupdate) {
valid = ngx_ssl_stapling_time(nextupdate);
if (valid == (time_t) NGX_ERROR) {
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
"invalid nextUpdate time in certificate status");
goto error;
}
} else {
valid = NGX_MAX_TIME_T_VALUE;
}
OCSP_CERTID_free(id);
OCSP_BASICRESP_free(basic);
OCSP_RESPONSE_free(ocsp);
id = NULL;
basic = NULL;
ocsp = NULL;
/* copy the response to memory not in ctx->pool */ /* copy the response to memory not in ctx->pool */
response.len = len; response.len = ctx->response->last - ctx->response->pos;
response.data = ngx_alloc(response.len, ctx->log); response.data = ngx_alloc(response.len, ctx->log);
if (response.data == NULL) { if (response.data == NULL) {
@@ -728,16 +689,12 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
ngx_memcpy(response.data, ctx->response->pos, response.len); ngx_memcpy(response.data, ctx->response->pos, response.len);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
"ssl ocsp response, %s, %uz",
OCSP_cert_status_str(n), response.len);
if (staple->staple.data) { if (staple->staple.data) {
ngx_free(staple->staple.data); ngx_free(staple->staple.data);
} }
staple->staple = response; staple->staple = response;
staple->valid = valid; staple->valid = ctx->valid;
/* /*
* refresh before the response expires, * refresh before the response expires,
@@ -745,7 +702,7 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
*/ */
staple->loading = 0; staple->loading = 0;
staple->refresh = ngx_max(ngx_min(valid - 300, now + 3600), now + 300); staple->refresh = ngx_max(ngx_min(ctx->valid - 300, now + 3600), now + 300);
ngx_ssl_ocsp_done(ctx); ngx_ssl_ocsp_done(ctx);
return; return;
@@ -755,18 +712,6 @@ error:
staple->loading = 0; staple->loading = 0;
staple->refresh = now + 300; staple->refresh = now + 300;
if (id) {
OCSP_CERTID_free(id);
}
if (basic) {
OCSP_BASICRESP_free(basic);
}
if (ocsp) {
OCSP_RESPONSE_free(ocsp);
}
ngx_ssl_ocsp_done(ctx); ngx_ssl_ocsp_done(ctx);
} }
@@ -820,14 +765,507 @@ ngx_ssl_stapling_cleanup(void *data)
} }
static ngx_ssl_ocsp_ctx_t * ngx_int_t
ngx_ssl_ocsp_start(void) 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_url_t u;
ngx_ssl_ocsp_conf_t *ocf;
ocf = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_ocsp_conf_t));
if (ocf == NULL) {
return NGX_ERROR;
}
ocf->depth = depth;
ocf->shm_zone = shm_zone;
if (responder->len) {
ngx_memzero(&u, sizeof(ngx_url_t));
u.url = *responder;
u.default_port = 80;
u.uri_part = 1;
if (u.url.len > 7
&& ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
{
u.url.len -= 7;
u.url.data += 7;
} else {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"invalid URL prefix in OCSP responder \"%V\" "
"in \"ssl_ocsp_responder\"", &u.url);
return NGX_ERROR;
}
if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
if (u.err) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"%s in OCSP responder \"%V\" "
"in \"ssl_ocsp_responder\"", u.err, &u.url);
}
return NGX_ERROR;
}
ocf->addrs = u.addrs;
ocf->naddrs = u.naddrs;
ocf->host = u.host;
ocf->uri = u.uri;
ocf->port = u.port;
}
if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_ocsp_index, ocf) == 0) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_set_ex_data() failed");
return NGX_ERROR;
}
return NGX_OK;
}
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_ssl_ocsp_conf_t *ocf;
ocf = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_ocsp_index);
ocf->resolver = resolver;
ocf->resolver_timeout = resolver_timeout;
return NGX_OK;
}
ngx_int_t
ngx_ssl_ocsp_validate(ngx_connection_t *c)
{
X509 *cert;
SSL_CTX *ssl_ctx;
ngx_int_t rc;
X509_STORE *store;
X509_STORE_CTX *store_ctx;
STACK_OF(X509) *chain;
ngx_ssl_ocsp_t *ocsp;
ngx_ssl_ocsp_conf_t *ocf;
if (c->ssl->in_ocsp) {
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
return NGX_ERROR;
}
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
return NGX_ERROR;
}
return NGX_AGAIN;
}
ssl_ctx = SSL_get_SSL_CTX(c->ssl->connection);
ocf = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_ocsp_index);
if (ocf == NULL) {
return NGX_OK;
}
if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) {
return NGX_OK;
}
cert = SSL_get_peer_certificate(c->ssl->connection);
if (cert == NULL) {
return NGX_OK;
}
ocsp = ngx_pcalloc(c->pool, sizeof(ngx_ssl_ocsp_t));
if (ocsp == NULL) {
X509_free(cert);
return NGX_ERROR;
}
c->ssl->ocsp = ocsp;
ocsp->status = NGX_AGAIN;
ocsp->cert_status = V_OCSP_CERTSTATUS_GOOD;
ocsp->conf = ocf;
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined LIBRESSL_VERSION_NUMBER)
ocsp->certs = SSL_get0_verified_chain(c->ssl->connection);
if (ocsp->certs) {
ocsp->certs = X509_chain_up_ref(ocsp->certs);
if (ocsp->certs == NULL) {
X509_free(cert);
return NGX_ERROR;
}
}
#endif
if (ocsp->certs == NULL) {
store = SSL_CTX_get_cert_store(ssl_ctx);
if (store == NULL) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"SSL_CTX_get_cert_store() failed");
X509_free(cert);
return NGX_ERROR;
}
store_ctx = X509_STORE_CTX_new();
if (store_ctx == NULL) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"X509_STORE_CTX_new() failed");
X509_free(cert);
return NGX_ERROR;
}
chain = SSL_get_peer_cert_chain(c->ssl->connection);
if (X509_STORE_CTX_init(store_ctx, store, cert, chain) == 0) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"X509_STORE_CTX_init() failed");
X509_STORE_CTX_free(store_ctx);
X509_free(cert);
return NGX_ERROR;
}
rc = X509_verify_cert(store_ctx);
if (rc <= 0) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "X509_verify_cert() failed");
X509_STORE_CTX_free(store_ctx);
X509_free(cert);
return NGX_ERROR;
}
ocsp->certs = X509_STORE_CTX_get1_chain(store_ctx);
if (ocsp->certs == NULL) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"X509_STORE_CTX_get1_chain() failed");
X509_STORE_CTX_free(store_ctx);
X509_free(cert);
return NGX_ERROR;
}
X509_STORE_CTX_free(store_ctx);
}
X509_free(cert);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"ssl ocsp validate, certs:%d", sk_X509_num(ocsp->certs));
ngx_ssl_ocsp_validate_next(c);
if (ocsp->status == NGX_AGAIN) {
c->ssl->in_ocsp = 1;
return NGX_AGAIN;
}
return NGX_OK;
}
static void
ngx_ssl_ocsp_validate_next(ngx_connection_t *c)
{
ngx_int_t rc;
ngx_uint_t n;
ngx_ssl_ocsp_t *ocsp;
ngx_ssl_ocsp_ctx_t *ctx;
ngx_ssl_ocsp_conf_t *ocf;
ocsp = c->ssl->ocsp;
ocf = ocsp->conf;
n = sk_X509_num(ocsp->certs);
for ( ;; ) {
if (ocsp->ncert == n - 1 || (ocf->depth == 2 && ocsp->ncert == 1)) {
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"ssl ocsp validated, certs:%ui", ocsp->ncert);
rc = NGX_OK;
goto done;
}
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"ssl ocsp validate cert:%ui", ocsp->ncert);
ctx = ngx_ssl_ocsp_start(c->log);
if (ctx == NULL) {
rc = NGX_ERROR;
goto done;
}
ocsp->ctx = ctx;
ctx->ssl_ctx = SSL_get_SSL_CTX(c->ssl->connection);
ctx->cert = sk_X509_value(ocsp->certs, ocsp->ncert);
ctx->issuer = sk_X509_value(ocsp->certs, ocsp->ncert + 1);
ctx->chain = ocsp->certs;
ctx->resolver = ocf->resolver;
ctx->resolver_timeout = ocf->resolver_timeout;
ctx->handler = ngx_ssl_ocsp_handler;
ctx->data = c;
ctx->shm_zone = ocf->shm_zone;
ctx->addrs = ocf->addrs;
ctx->naddrs = ocf->naddrs;
ctx->host = ocf->host;
ctx->uri = ocf->uri;
ctx->port = ocf->port;
rc = ngx_ssl_ocsp_responder(c, ctx);
if (rc != NGX_OK) {
goto done;
}
if (ctx->uri.len == 0) {
ngx_str_set(&ctx->uri, "/");
}
ocsp->ncert++;
rc = ngx_ssl_ocsp_cache_lookup(ctx);
if (rc == NGX_ERROR) {
goto done;
}
if (rc == NGX_DECLINED) {
break;
}
/* rc == NGX_OK */
if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
"ssl ocsp cached status \"%s\"",
OCSP_cert_status_str(ctx->status));
ocsp->cert_status = ctx->status;
goto done;
}
ocsp->ctx = NULL;
ngx_ssl_ocsp_done(ctx);
}
ngx_ssl_ocsp_request(ctx);
return;
done:
ocsp->status = rc;
if (c->ssl->in_ocsp) {
c->ssl->handshaked = 1;
c->ssl->handler(c);
}
}
static void
ngx_ssl_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
{
ngx_int_t rc;
ngx_ssl_ocsp_t *ocsp;
ngx_connection_t *c;
c = ctx->data;
ocsp = c->ssl->ocsp;
ocsp->ctx = NULL;
rc = ngx_ssl_ocsp_verify(ctx);
if (rc != NGX_OK) {
goto done;
}
rc = ngx_ssl_ocsp_cache_store(ctx);
if (rc != NGX_OK) {
goto done;
}
if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
ocsp->cert_status = ctx->status;
goto done;
}
ngx_ssl_ocsp_done(ctx);
ngx_ssl_ocsp_validate_next(c);
return;
done:
ocsp->status = rc;
ngx_ssl_ocsp_done(ctx);
if (c->ssl->in_ocsp) {
c->ssl->handshaked = 1;
c->ssl->handler(c);
}
}
static ngx_int_t
ngx_ssl_ocsp_responder(ngx_connection_t *c, ngx_ssl_ocsp_ctx_t *ctx)
{
char *s;
ngx_str_t responder;
ngx_url_t u;
STACK_OF(OPENSSL_STRING) *aia;
if (ctx->host.len) {
return NGX_OK;
}
/* extract OCSP responder URL from certificate */
aia = X509_get1_ocsp(ctx->cert);
if (aia == NULL) {
ngx_log_error(NGX_LOG_ERR, c->log, 0,
"no OCSP responder URL in certificate");
return NGX_ERROR;
}
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
s = sk_OPENSSL_STRING_value(aia, 0);
#else
s = sk_value(aia, 0);
#endif
if (s == NULL) {
ngx_log_error(NGX_LOG_ERR, c->log, 0,
"no OCSP responder URL in certificate");
X509_email_free(aia);
return NGX_ERROR;
}
responder.len = ngx_strlen(s);
responder.data = ngx_palloc(ctx->pool, responder.len);
if (responder.data == NULL) {
X509_email_free(aia);
return NGX_ERROR;
}
ngx_memcpy(responder.data, s, responder.len);
X509_email_free(aia);
ngx_memzero(&u, sizeof(ngx_url_t));
u.url = responder;
u.default_port = 80;
u.uri_part = 1;
u.no_resolve = 1;
if (u.url.len > 7
&& ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
{
u.url.len -= 7;
u.url.data += 7;
} else {
ngx_log_error(NGX_LOG_ERR, c->log, 0,
"invalid URL prefix in OCSP responder \"%V\" "
"in certificate", &u.url);
return NGX_ERROR;
}
if (ngx_parse_url(ctx->pool, &u) != NGX_OK) {
if (u.err) {
ngx_log_error(NGX_LOG_ERR, c->log, 0,
"%s in OCSP responder \"%V\" in certificate",
u.err, &u.url);
}
return NGX_ERROR;
}
if (u.host.len == 0) {
ngx_log_error(NGX_LOG_ERR, c->log, 0,
"empty host in OCSP responder in certificate");
return NGX_ERROR;
}
ctx->addrs = u.addrs;
ctx->naddrs = u.naddrs;
ctx->host = u.host;
ctx->uri = u.uri;
ctx->port = u.port;
return NGX_OK;
}
ngx_int_t
ngx_ssl_ocsp_get_status(ngx_connection_t *c, const char **s)
{
ngx_ssl_ocsp_t *ocsp;
ocsp = c->ssl->ocsp;
if (ocsp == NULL) {
return NGX_OK;
}
if (ocsp->status == NGX_ERROR) {
*s = "certificate status request failed";
return NGX_DECLINED;
}
switch (ocsp->cert_status) {
case V_OCSP_CERTSTATUS_GOOD:
return NGX_OK;
case V_OCSP_CERTSTATUS_REVOKED:
*s = "certificate revoked";
break;
default: /* V_OCSP_CERTSTATUS_UNKNOWN */
*s = "certificate status unknown";
}
return NGX_DECLINED;
}
void
ngx_ssl_ocsp_cleanup(ngx_connection_t *c)
{
ngx_ssl_ocsp_t *ocsp;
ocsp = c->ssl->ocsp;
if (ocsp == NULL) {
return;
}
if (ocsp->ctx) {
ngx_ssl_ocsp_done(ocsp->ctx);
ocsp->ctx = NULL;
}
if (ocsp->certs) {
sk_X509_pop_free(ocsp->certs, X509_free);
ocsp->certs = NULL;
}
}
static ngx_ssl_ocsp_ctx_t *
ngx_ssl_ocsp_start(ngx_log_t *log)
{ {
ngx_log_t *log;
ngx_pool_t *pool; ngx_pool_t *pool;
ngx_ssl_ocsp_ctx_t *ctx; ngx_ssl_ocsp_ctx_t *ctx;
pool = ngx_create_pool(2048, ngx_cycle->log); pool = ngx_create_pool(2048, log);
if (pool == NULL) { if (pool == NULL) {
return NULL; return NULL;
} }
@@ -884,6 +1322,36 @@ ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t *ctx)
} }
static void
ngx_ssl_ocsp_next(ngx_ssl_ocsp_ctx_t *ctx)
{
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
"ssl ocsp next");
if (++ctx->naddr >= ctx->naddrs) {
ngx_ssl_ocsp_error(ctx);
return;
}
ctx->request->pos = ctx->request->start;
if (ctx->response) {
ctx->response->last = ctx->response->pos;
}
if (ctx->peer.connection) {
ngx_close_connection(ctx->peer.connection);
ctx->peer.connection = NULL;
}
ctx->state = 0;
ctx->count = 0;
ctx->done = 0;
ngx_ssl_ocsp_connect(ctx);
}
static void static void
ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx) ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
{ {
@@ -909,6 +1377,14 @@ ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
} }
if (resolve == NGX_NO_RESOLVER) { if (resolve == NGX_NO_RESOLVER) {
if (ctx->naddrs == 0) {
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
"no resolver defined to resolve %V", &ctx->host);
ngx_ssl_ocsp_error(ctx);
return;
}
ngx_log_error(NGX_LOG_WARN, ctx->log, 0, ngx_log_error(NGX_LOG_WARN, ctx->log, 0,
"no resolver defined to resolve %V", &ctx->host); "no resolver defined to resolve %V", &ctx->host);
goto connect; goto connect;
@@ -1022,16 +1498,17 @@ failed:
static void static void
ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx) ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
{ {
ngx_int_t rc; ngx_int_t rc;
ngx_addr_t *addr;
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
"ssl ocsp connect"); "ssl ocsp connect %ui/%ui", ctx->naddr, ctx->naddrs);
/* TODO: use all ip addresses */ addr = &ctx->addrs[ctx->naddr];
ctx->peer.sockaddr = ctx->addrs[0].sockaddr; ctx->peer.sockaddr = addr->sockaddr;
ctx->peer.socklen = ctx->addrs[0].socklen; ctx->peer.socklen = addr->socklen;
ctx->peer.name = &ctx->addrs[0].name; ctx->peer.name = &addr->name;
ctx->peer.get = ngx_event_get_peer; ctx->peer.get = ngx_event_get_peer;
ctx->peer.log = ctx->log; ctx->peer.log = ctx->log;
ctx->peer.log_error = NGX_ERROR_ERR; ctx->peer.log_error = NGX_ERROR_ERR;
@@ -1041,11 +1518,16 @@ ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
"ssl ocsp connect peer done"); "ssl ocsp connect peer done");
if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) { if (rc == NGX_ERROR) {
ngx_ssl_ocsp_error(ctx); ngx_ssl_ocsp_error(ctx);
return; return;
} }
if (rc == NGX_BUSY || rc == NGX_DECLINED) {
ngx_ssl_ocsp_next(ctx);
return;
}
ctx->peer.connection->data = ctx; ctx->peer.connection->data = ctx;
ctx->peer.connection->pool = ctx->pool; ctx->peer.connection->pool = ctx->pool;
@@ -1054,8 +1536,10 @@ ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
ctx->process = ngx_ssl_ocsp_process_status_line; ctx->process = ngx_ssl_ocsp_process_status_line;
ngx_add_timer(ctx->peer.connection->read, ctx->timeout); if (ctx->timeout) {
ngx_add_timer(ctx->peer.connection->write, ctx->timeout); ngx_add_timer(ctx->peer.connection->read, ctx->timeout);
ngx_add_timer(ctx->peer.connection->write, ctx->timeout);
}
if (rc == NGX_OK) { if (rc == NGX_OK) {
ngx_ssl_ocsp_write_handler(ctx->peer.connection->write); ngx_ssl_ocsp_write_handler(ctx->peer.connection->write);
@@ -1080,7 +1564,7 @@ ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
if (wev->timedout) { if (wev->timedout) {
ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT, ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT,
"OCSP responder timed out"); "OCSP responder timed out");
ngx_ssl_ocsp_error(ctx); ngx_ssl_ocsp_next(ctx);
return; return;
} }
@@ -1089,7 +1573,7 @@ ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
n = ngx_send(c, ctx->request->pos, size); n = ngx_send(c, ctx->request->pos, size);
if (n == NGX_ERROR) { if (n == NGX_ERROR) {
ngx_ssl_ocsp_error(ctx); ngx_ssl_ocsp_next(ctx);
return; return;
} }
@@ -1111,7 +1595,7 @@ ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
} }
} }
if (!wev->timer_set) { if (!wev->timer_set && ctx->timeout) {
ngx_add_timer(wev, ctx->timeout); ngx_add_timer(wev, ctx->timeout);
} }
} }
@@ -1134,7 +1618,7 @@ ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
if (rev->timedout) { if (rev->timedout) {
ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT, ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT,
"OCSP responder timed out"); "OCSP responder timed out");
ngx_ssl_ocsp_error(ctx); ngx_ssl_ocsp_next(ctx);
return; return;
} }
@@ -1158,7 +1642,7 @@ ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
rc = ctx->process(ctx); rc = ctx->process(ctx);
if (rc == NGX_ERROR) { if (rc == NGX_ERROR) {
ngx_ssl_ocsp_error(ctx); ngx_ssl_ocsp_next(ctx);
return; return;
} }
@@ -1189,7 +1673,7 @@ ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
ngx_log_error(NGX_LOG_ERR, ctx->log, 0, ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
"OCSP responder prematurely closed connection"); "OCSP responder prematurely closed connection");
ngx_ssl_ocsp_error(ctx); ngx_ssl_ocsp_next(ctx);
} }
@@ -1831,6 +2315,368 @@ ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx)
} }
static ngx_int_t
ngx_ssl_ocsp_verify(ngx_ssl_ocsp_ctx_t *ctx)
{
int n;
size_t len;
X509_STORE *store;
const u_char *p;
OCSP_CERTID *id;
OCSP_RESPONSE *ocsp;
OCSP_BASICRESP *basic;
ASN1_GENERALIZEDTIME *thisupdate, *nextupdate;
ocsp = NULL;
basic = NULL;
id = NULL;
if (ctx->code != 200) {
goto error;
}
/* check the response */
len = ctx->response->last - ctx->response->pos;
p = ctx->response->pos;
ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
if (ocsp == NULL) {
ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
"d2i_OCSP_RESPONSE() failed");
goto error;
}
n = OCSP_response_status(ocsp);
if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
"OCSP response not successful (%d: %s)",
n, OCSP_response_status_str(n));
goto error;
}
basic = OCSP_response_get1_basic(ocsp);
if (basic == NULL) {
ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
"OCSP_response_get1_basic() failed");
goto error;
}
store = SSL_CTX_get_cert_store(ctx->ssl_ctx);
if (store == NULL) {
ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
"SSL_CTX_get_cert_store() failed");
goto error;
}
if (OCSP_basic_verify(basic, ctx->chain, store, ctx->flags) != 1) {
ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
"OCSP_basic_verify() failed");
goto error;
}
id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
if (id == NULL) {
ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
"OCSP_cert_to_id() failed");
goto error;
}
if (OCSP_resp_find_status(basic, id, &ctx->status, NULL, NULL,
&thisupdate, &nextupdate)
!= 1)
{
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
"certificate status not found in the OCSP response");
goto error;
}
if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
"OCSP_check_validity() failed");
goto error;
}
if (nextupdate) {
ctx->valid = ngx_ssl_stapling_time(nextupdate);
if (ctx->valid == (time_t) NGX_ERROR) {
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
"invalid nextUpdate time in certificate status");
goto error;
}
} else {
ctx->valid = NGX_MAX_TIME_T_VALUE;
}
OCSP_CERTID_free(id);
OCSP_BASICRESP_free(basic);
OCSP_RESPONSE_free(ocsp);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
"ssl ocsp response, %s, %uz",
OCSP_cert_status_str(ctx->status), len);
return NGX_OK;
error:
if (id) {
OCSP_CERTID_free(id);
}
if (basic) {
OCSP_BASICRESP_free(basic);
}
if (ocsp) {
OCSP_RESPONSE_free(ocsp);
}
return NGX_ERROR;
}
ngx_int_t
ngx_ssl_ocsp_cache_init(ngx_shm_zone_t *shm_zone, void *data)
{
size_t len;
ngx_slab_pool_t *shpool;
ngx_ssl_ocsp_cache_t *cache;
if (data) {
shm_zone->data = data;
return NGX_OK;
}
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
if (shm_zone->shm.exists) {
shm_zone->data = shpool->data;
return NGX_OK;
}
cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_ocsp_cache_t));
if (cache == NULL) {
return NGX_ERROR;
}
shpool->data = cache;
shm_zone->data = cache;
ngx_rbtree_init(&cache->rbtree, &cache->sentinel,
ngx_str_rbtree_insert_value);
ngx_queue_init(&cache->expire_queue);
len = sizeof(" in OCSP cache \"\"") + shm_zone->shm.name.len;
shpool->log_ctx = ngx_slab_alloc(shpool, len);
if (shpool->log_ctx == NULL) {
return NGX_ERROR;
}
ngx_sprintf(shpool->log_ctx, " in OCSP cache \"%V\"%Z",
&shm_zone->shm.name);
shpool->log_nomem = 0;
return NGX_OK;
}
static ngx_int_t
ngx_ssl_ocsp_cache_lookup(ngx_ssl_ocsp_ctx_t *ctx)
{
uint32_t hash;
ngx_shm_zone_t *shm_zone;
ngx_slab_pool_t *shpool;
ngx_ssl_ocsp_cache_t *cache;
ngx_ssl_ocsp_cache_node_t *node;
shm_zone = ctx->shm_zone;
if (shm_zone == NULL) {
return NGX_DECLINED;
}
if (ngx_ssl_ocsp_create_key(ctx) != NGX_OK) {
return NGX_ERROR;
}
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp cache lookup");
cache = shm_zone->data;
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
hash = ngx_hash_key(ctx->key.data, ctx->key.len);
ngx_shmtx_lock(&shpool->mutex);
node = (ngx_ssl_ocsp_cache_node_t *)
ngx_str_rbtree_lookup(&cache->rbtree, &ctx->key, hash);
if (node) {
if (node->valid > ngx_time()) {
ctx->status = node->status;
ngx_shmtx_unlock(&shpool->mutex);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
"ssl ocsp cache hit, %s",
OCSP_cert_status_str(ctx->status));
return NGX_OK;
}
ngx_queue_remove(&node->queue);
ngx_rbtree_delete(&cache->rbtree, &node->node.node);
ngx_slab_free_locked(shpool, node);
ngx_shmtx_unlock(&shpool->mutex);
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
"ssl ocsp cache expired");
return NGX_DECLINED;
}
ngx_shmtx_unlock(&shpool->mutex);
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp cache miss");
return NGX_DECLINED;
}
static ngx_int_t
ngx_ssl_ocsp_cache_store(ngx_ssl_ocsp_ctx_t *ctx)
{
time_t now, valid;
uint32_t hash;
ngx_queue_t *q;
ngx_shm_zone_t *shm_zone;
ngx_slab_pool_t *shpool;
ngx_ssl_ocsp_cache_t *cache;
ngx_ssl_ocsp_cache_node_t *node;
shm_zone = ctx->shm_zone;
if (shm_zone == NULL) {
return NGX_OK;
}
valid = ctx->valid;
now = ngx_time();
if (valid < now) {
return NGX_OK;
}
if (valid == NGX_MAX_TIME_T_VALUE) {
valid = now + 3600;
}
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
"ssl ocsp cache store, valid:%T", valid - now);
cache = shm_zone->data;
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
hash = ngx_hash_key(ctx->key.data, ctx->key.len);
ngx_shmtx_lock(&shpool->mutex);
node = ngx_slab_calloc_locked(shpool,
sizeof(ngx_ssl_ocsp_cache_node_t) + ctx->key.len);
if (node == NULL) {
if (!ngx_queue_empty(&cache->expire_queue)) {
q = ngx_queue_last(&cache->expire_queue);
node = ngx_queue_data(q, ngx_ssl_ocsp_cache_node_t, queue);
ngx_rbtree_delete(&cache->rbtree, &node->node.node);
ngx_queue_remove(q);
ngx_slab_free_locked(shpool, node);
node = ngx_slab_alloc_locked(shpool,
sizeof(ngx_ssl_ocsp_cache_node_t) + ctx->key.len);
}
if (node == NULL) {
ngx_shmtx_unlock(&shpool->mutex);
ngx_log_error(NGX_LOG_ALERT, ctx->log, 0,
"could not allocate new entry%s", shpool->log_ctx);
return NGX_ERROR;
}
}
node->node.str.len = ctx->key.len;
node->node.str.data = (u_char *) node + sizeof(ngx_ssl_ocsp_cache_node_t);
ngx_memcpy(node->node.str.data, ctx->key.data, ctx->key.len);
node->node.node.key = hash;
node->status = ctx->status;
node->valid = valid;
ngx_rbtree_insert(&cache->rbtree, &node->node.node);
ngx_queue_insert_head(&cache->expire_queue, &node->queue);
ngx_shmtx_unlock(&shpool->mutex);
return NGX_OK;
}
static ngx_int_t
ngx_ssl_ocsp_create_key(ngx_ssl_ocsp_ctx_t *ctx)
{
u_char *p;
X509_NAME *name;
ASN1_INTEGER *serial;
p = ngx_pnalloc(ctx->pool, 60);
if (p == NULL) {
return NGX_ERROR;
}
ctx->key.data = p;
ctx->key.len = 60;
name = X509_get_subject_name(ctx->issuer);
if (X509_NAME_digest(name, EVP_sha1(), p, NULL) == 0) {
return NGX_ERROR;
}
p += 20;
if (X509_pubkey_digest(ctx->issuer, EVP_sha1(), p, NULL) == 0) {
return NGX_ERROR;
}
p += 20;
serial = X509_get_serialNumber(ctx->cert);
if (serial->length > 20) {
return NGX_ERROR;
}
p = ngx_cpymem(p, serial->data, serial->length);
ngx_memzero(p, 20 - serial->length);
#if (NGX_DEBUG)
{
u_char buf[120];
ngx_hex_dump(buf, ctx->key.data, ctx->key.len);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
"ssl ocsp key %*s", sizeof(buf), buf);
}
#endif
return NGX_OK;
}
static u_char * static u_char *
ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len) ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len)
{ {
@@ -1891,4 +2737,50 @@ ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
} }
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_log_error(NGX_LOG_EMERG, ssl->log, 0,
"\"ssl_ocsp\" is not supported on this platform");
return NGX_ERROR;
}
ngx_int_t
ngx_ssl_ocsp_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
{
return NGX_OK;
}
ngx_int_t
ngx_ssl_ocsp_validate(ngx_connection_t *c)
{
return NGX_OK;
}
ngx_int_t
ngx_ssl_ocsp_get_status(ngx_connection_t *c, const char **s)
{
return NGX_OK;
}
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)
{
return NGX_OK;
}
#endif #endif
+28
View File
@@ -960,6 +960,22 @@ ngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
return NGX_OK; return NGX_OK;
} }
if (p->upstream_done) {
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
"input data after close");
return NGX_OK;
}
if (p->length == 0) {
p->upstream_done = 1;
ngx_log_error(NGX_LOG_WARN, p->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
return NGX_OK;
}
cl = ngx_chain_get_free_buf(p->pool, &p->free); cl = ngx_chain_get_free_buf(p->pool, &p->free);
if (cl == NULL) { if (cl == NULL) {
return NGX_ERROR; return NGX_ERROR;
@@ -987,6 +1003,18 @@ ngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
return NGX_OK; return NGX_OK;
} }
if (b->last - b->pos > p->length) {
ngx_log_error(NGX_LOG_WARN, p->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
b->last = b->pos + p->length;
p->upstream_done = 1;
return NGX_OK;
}
p->length -= b->last - b->pos; p->length -= b->last - b->pos;
return NGX_OK; return NGX_OK;
+10 -12
View File
@@ -37,26 +37,24 @@ ngx_event_process_posted(ngx_cycle_t *cycle, ngx_queue_t *posted)
void void
ngx_event_process_posted_next(ngx_cycle_t *cycle, ngx_queue_t *posted) ngx_event_move_posted_next(ngx_cycle_t *cycle)
{ {
ngx_queue_t *q; ngx_queue_t *q;
ngx_event_t *ev; ngx_event_t *ev;
while (!ngx_queue_empty(posted)) { for (q = ngx_queue_head(&ngx_posted_next_events);
q != ngx_queue_sentinel(&ngx_posted_next_events);
q = ngx_queue_head(posted); q = ngx_queue_next(q))
{
ev = ngx_queue_data(q, ngx_event_t, queue); ev = ngx_queue_data(q, ngx_event_t, queue);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"posted next event %p", ev); "posted next event %p", ev);
ngx_delete_posted_event(ev); ev->ready = 1;
ev->available = -1;
if (!ev->ready) {
ev->ready = 1;
ev->available = -1;
}
ev->handler(ev);
} }
ngx_queue_add(&ngx_posted_events, &ngx_posted_next_events);
ngx_queue_init(&ngx_posted_next_events);
} }
+1 -1
View File
@@ -39,7 +39,7 @@
void ngx_event_process_posted(ngx_cycle_t *cycle, ngx_queue_t *posted); void ngx_event_process_posted(ngx_cycle_t *cycle, ngx_queue_t *posted);
void ngx_event_process_posted_next(ngx_cycle_t *cycle, ngx_queue_t *posted); void ngx_event_move_posted_next(ngx_cycle_t *cycle);
extern ngx_queue_t ngx_posted_accept_events; extern ngx_queue_t ngx_posted_accept_events;
+18 -19
View File
@@ -25,7 +25,6 @@ static ngx_int_t ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r,
ngx_str_t *passwd, ngx_str_t *realm); ngx_str_t *passwd, ngx_str_t *realm);
static ngx_int_t ngx_http_auth_basic_set_realm(ngx_http_request_t *r, static ngx_int_t ngx_http_auth_basic_set_realm(ngx_http_request_t *r,
ngx_str_t *realm); ngx_str_t *realm);
static void ngx_http_auth_basic_close(ngx_file_t *file);
static void *ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf); static void *ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf, static char *ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child); void *parent, void *child);
@@ -177,8 +176,8 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
offset); offset);
if (n == NGX_ERROR) { if (n == NGX_ERROR) {
ngx_http_auth_basic_close(&file); rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
return NGX_HTTP_INTERNAL_SERVER_ERROR; goto cleanup;
} }
if (n == 0) { if (n == 0) {
@@ -219,12 +218,11 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
if (buf[i] == LF || buf[i] == CR || buf[i] == ':') { if (buf[i] == LF || buf[i] == CR || buf[i] == ':') {
buf[i] = '\0'; buf[i] = '\0';
ngx_http_auth_basic_close(&file);
pwd.len = i - passwd; pwd.len = i - passwd;
pwd.data = &buf[passwd]; pwd.data = &buf[passwd];
return ngx_http_auth_basic_crypt_handler(r, &pwd, &realm); rc = ngx_http_auth_basic_crypt_handler(r, &pwd, &realm);
goto cleanup;
} }
break; break;
@@ -251,8 +249,6 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
offset += n; offset += n;
} }
ngx_http_auth_basic_close(&file);
if (state == sw_passwd) { if (state == sw_passwd) {
pwd.len = i - passwd; pwd.len = i - passwd;
pwd.data = ngx_pnalloc(r->pool, pwd.len + 1); pwd.data = ngx_pnalloc(r->pool, pwd.len + 1);
@@ -262,14 +258,26 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
ngx_cpystrn(pwd.data, &buf[passwd], pwd.len + 1); ngx_cpystrn(pwd.data, &buf[passwd], pwd.len + 1);
return ngx_http_auth_basic_crypt_handler(r, &pwd, &realm); rc = ngx_http_auth_basic_crypt_handler(r, &pwd, &realm);
goto cleanup;
} }
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"user \"%V\" was not found in \"%s\"", "user \"%V\" was not found in \"%s\"",
&r->headers_in.user, user_file.data); &r->headers_in.user, user_file.data);
return ngx_http_auth_basic_set_realm(r, &realm); rc = ngx_http_auth_basic_set_realm(r, &realm);
cleanup:
if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
ngx_close_file_n " \"%s\" failed", user_file.data);
}
ngx_explicit_memzero(buf, NGX_HTTP_AUTH_BUF_SIZE);
return rc;
} }
@@ -338,15 +346,6 @@ ngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm)
return NGX_HTTP_UNAUTHORIZED; return NGX_HTTP_UNAUTHORIZED;
} }
static void
ngx_http_auth_basic_close(ngx_file_t *file)
{
if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, file->log, ngx_errno,
ngx_close_file_n " \"%s\" failed", file->name.data);
}
}
static void * static void *
ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf) ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf)
+122 -14
View File
@@ -81,12 +81,15 @@ typedef struct {
size_t length; size_t length;
size_t padding; size_t padding;
off_t rest;
ngx_chain_t *free; ngx_chain_t *free;
ngx_chain_t *busy; ngx_chain_t *busy;
unsigned fastcgi_stdout:1; unsigned fastcgi_stdout:1;
unsigned large_stderr:1; unsigned large_stderr:1;
unsigned header_sent:1; unsigned header_sent:1;
unsigned closed:1;
ngx_array_t *split_parts; ngx_array_t *split_parts;
@@ -2075,13 +2078,31 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
static ngx_int_t static ngx_int_t
ngx_http_fastcgi_input_filter_init(void *data) ngx_http_fastcgi_input_filter_init(void *data)
{ {
ngx_http_request_t *r = data; ngx_http_request_t *r = data;
ngx_http_upstream_t *u;
ngx_http_fastcgi_ctx_t *f;
ngx_http_fastcgi_loc_conf_t *flcf; ngx_http_fastcgi_loc_conf_t *flcf;
u = r->upstream;
f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
r->upstream->pipe->length = flcf->keep_conn ? u->pipe->length = flcf->keep_conn ?
(off_t) sizeof(ngx_http_fastcgi_header_t) : -1; (off_t) sizeof(ngx_http_fastcgi_header_t) : -1;
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED)
{
f->rest = 0;
} else if (r->method == NGX_HTTP_HEAD) {
f->rest = -2;
} else {
f->rest = u->headers_in.content_length_n;
}
return NGX_OK; return NGX_OK;
} }
@@ -2106,6 +2127,15 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module); f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
if (p->upstream_done || f->closed) {
r->upstream->keepalive = 0;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
"http fastcgi data after close");
return NGX_OK;
}
b = NULL; b = NULL;
prev = &buf->shadow; prev = &buf->shadow;
@@ -2128,13 +2158,25 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) { if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
f->state = ngx_http_fastcgi_st_padding; f->state = ngx_http_fastcgi_st_padding;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
"http fastcgi closed stdout");
if (f->rest > 0) {
ngx_log_error(NGX_LOG_ERR, p->log, 0,
"upstream prematurely closed "
"FastCGI stdout");
p->upstream_error = 1;
p->upstream_eof = 0;
f->closed = 1;
break;
}
if (!flcf->keep_conn) { if (!flcf->keep_conn) {
p->upstream_done = 1; p->upstream_done = 1;
} }
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
"http fastcgi closed stdout");
continue; continue;
} }
@@ -2143,6 +2185,18 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0, ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
"http fastcgi sent end request"); "http fastcgi sent end request");
if (f->rest > 0) {
ngx_log_error(NGX_LOG_ERR, p->log, 0,
"upstream prematurely closed "
"FastCGI request");
p->upstream_error = 1;
p->upstream_eof = 0;
f->closed = 1;
break;
}
if (!flcf->keep_conn) { if (!flcf->keep_conn) {
p->upstream_done = 1; p->upstream_done = 1;
break; break;
@@ -2252,6 +2306,18 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
break; break;
} }
if (f->rest == -2) {
f->rest = r->upstream->headers_in.content_length_n;
}
if (f->rest == 0) {
ngx_log_error(NGX_LOG_WARN, p->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
p->upstream_done = 1;
break;
}
cl = ngx_chain_get_free_buf(p->pool, &p->free); cl = ngx_chain_get_free_buf(p->pool, &p->free);
if (cl == NULL) { if (cl == NULL) {
return NGX_ERROR; return NGX_ERROR;
@@ -2289,15 +2355,27 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
f->pos += f->length; f->pos += f->length;
b->last = f->pos; b->last = f->pos;
continue; } else {
f->length -= f->last - f->pos;
f->pos = f->last;
b->last = f->last;
} }
f->length -= f->last - f->pos; if (f->rest > 0) {
b->last = f->last; if (b->last - b->pos > f->rest) {
ngx_log_error(NGX_LOG_WARN, p->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
break; b->last = b->pos + f->rest;
p->upstream_done = 1;
break;
}
f->rest -= b->last - b->pos;
}
} }
if (flcf->keep_conn) { if (flcf->keep_conn) {
@@ -2391,6 +2469,14 @@ ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes)
if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) { if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
if (f->rest > 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream prematurely closed "
"FastCGI request");
u->error = 1;
break;
}
if (f->pos + f->padding < f->last) { if (f->pos + f->padding < f->last) {
u->length = 0; u->length = 0;
break; break;
@@ -2486,6 +2572,14 @@ ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes)
break; break;
} }
if (f->rest == 0) {
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
u->length = 0;
break;
}
cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs); cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
if (cl == NULL) { if (cl == NULL) {
return NGX_ERROR; return NGX_ERROR;
@@ -2510,13 +2604,27 @@ ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes)
f->pos += f->length; f->pos += f->length;
b->last = f->pos; b->last = f->pos;
continue; } else {
f->length -= f->last - f->pos;
f->pos = f->last;
b->last = f->last;
} }
f->length -= f->last - f->pos; if (f->rest > 0) {
b->last = f->last;
break; if (b->last - b->pos > f->rest) {
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
b->last = b->pos + f->rest;
u->length = 0;
break;
}
f->rest -= b->last - b->pos;
}
} }
return NGX_OK; return NGX_OK;
+249 -45
View File
@@ -27,6 +27,9 @@ typedef struct {
ngx_str_t host; ngx_str_t host;
ngx_uint_t host_set; ngx_uint_t host_set;
ngx_array_t *grpc_lengths;
ngx_array_t *grpc_values;
#if (NGX_HTTP_SSL) #if (NGX_HTTP_SSL)
ngx_uint_t ssl; ngx_uint_t ssl;
ngx_uint_t ssl_protocols; ngx_uint_t ssl_protocols;
@@ -81,6 +84,8 @@ typedef struct {
ngx_uint_t pings; ngx_uint_t pings;
ngx_uint_t settings; ngx_uint_t settings;
off_t length;
ssize_t send_window; ssize_t send_window;
size_t recv_window; size_t recv_window;
@@ -117,8 +122,11 @@ typedef struct {
unsigned end_stream:1; unsigned end_stream:1;
unsigned done:1; unsigned done:1;
unsigned status:1; unsigned status:1;
unsigned rst:1;
ngx_http_request_t *request; ngx_http_request_t *request;
ngx_str_t host;
} ngx_http_grpc_ctx_t; } ngx_http_grpc_ctx_t;
@@ -135,6 +143,8 @@ typedef struct {
} ngx_http_grpc_frame_t; } ngx_http_grpc_frame_t;
static ngx_int_t ngx_http_grpc_eval(ngx_http_request_t *r,
ngx_http_grpc_ctx_t *ctx, ngx_http_grpc_loc_conf_t *glcf);
static ngx_int_t ngx_http_grpc_create_request(ngx_http_request_t *r); static ngx_int_t ngx_http_grpc_create_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_grpc_reinit_request(ngx_http_request_t *r); static ngx_int_t ngx_http_grpc_reinit_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in); static ngx_int_t ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in);
@@ -524,22 +534,40 @@ ngx_http_grpc_handler(ngx_http_request_t *r)
return NGX_HTTP_INTERNAL_SERVER_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
} }
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_grpc_ctx_t));
if (ctx == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
ctx->request = r;
ngx_http_set_ctx(r, ctx, ngx_http_grpc_module);
glcf = ngx_http_get_module_loc_conf(r, ngx_http_grpc_module); glcf = ngx_http_get_module_loc_conf(r, ngx_http_grpc_module);
u = r->upstream; u = r->upstream;
#if (NGX_HTTP_SSL) if (glcf->grpc_lengths == NULL) {
u->ssl = (glcf->upstream.ssl != NULL); ctx->host = glcf->host;
if (u->ssl) { #if (NGX_HTTP_SSL)
ngx_str_set(&u->schema, "grpcs://"); u->ssl = (glcf->upstream.ssl != NULL);
if (u->ssl) {
ngx_str_set(&u->schema, "grpcs://");
} else {
ngx_str_set(&u->schema, "grpc://");
}
#else
ngx_str_set(&u->schema, "grpc://");
#endif
} else { } else {
ngx_str_set(&u->schema, "grpc://"); if (ngx_http_grpc_eval(r, ctx, glcf) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
} }
#else
ngx_str_set(&u->schema, "grpc://");
#endif
u->output.tag = (ngx_buf_tag_t) &ngx_http_grpc_module; u->output.tag = (ngx_buf_tag_t) &ngx_http_grpc_module;
@@ -551,15 +579,6 @@ ngx_http_grpc_handler(ngx_http_request_t *r)
u->abort_request = ngx_http_grpc_abort_request; u->abort_request = ngx_http_grpc_abort_request;
u->finalize_request = ngx_http_grpc_finalize_request; u->finalize_request = ngx_http_grpc_finalize_request;
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_grpc_ctx_t));
if (ctx == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
ctx->request = r;
ngx_http_set_ctx(r, ctx, ngx_http_grpc_module);
u->input_filter_init = ngx_http_grpc_filter_init; u->input_filter_init = ngx_http_grpc_filter_init;
u->input_filter = ngx_http_grpc_filter; u->input_filter = ngx_http_grpc_filter;
u->input_filter_ctx = ctx; u->input_filter_ctx = ctx;
@@ -576,6 +595,103 @@ ngx_http_grpc_handler(ngx_http_request_t *r)
} }
static ngx_int_t
ngx_http_grpc_eval(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
ngx_http_grpc_loc_conf_t *glcf)
{
size_t add;
ngx_url_t url;
ngx_http_upstream_t *u;
ngx_memzero(&url, sizeof(ngx_url_t));
if (ngx_http_script_run(r, &url.url, glcf->grpc_lengths->elts, 0,
glcf->grpc_values->elts)
== NULL)
{
return NGX_ERROR;
}
if (url.url.len > 7
&& ngx_strncasecmp(url.url.data, (u_char *) "grpc://", 7) == 0)
{
add = 7;
} else if (url.url.len > 8
&& ngx_strncasecmp(url.url.data, (u_char *) "grpcs://", 8) == 0)
{
#if (NGX_HTTP_SSL)
add = 8;
r->upstream->ssl = 1;
#else
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"grpcs protocol requires SSL support");
return NGX_ERROR;
#endif
} else {
add = 0;
}
u = r->upstream;
if (add) {
u->schema.len = add;
u->schema.data = url.url.data;
url.url.data += add;
url.url.len -= add;
} else {
ngx_str_set(&u->schema, "grpc://");
}
url.no_resolve = 1;
if (ngx_parse_url(r->pool, &url) != NGX_OK) {
if (url.err) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"%s in upstream \"%V\"", url.err, &url.url);
}
return NGX_ERROR;
}
u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
if (u->resolved == NULL) {
return NGX_ERROR;
}
if (url.addrs) {
u->resolved->sockaddr = url.addrs[0].sockaddr;
u->resolved->socklen = url.addrs[0].socklen;
u->resolved->name = url.addrs[0].name;
u->resolved->naddrs = 1;
}
u->resolved->host = url.host;
u->resolved->port = url.port;
u->resolved->no_port = url.no_port;
if (url.family != AF_UNIX) {
if (url.no_port) {
ctx->host = url.host;
} else {
ctx->host.len = url.host.len + 1 + url.port_text.len;
ctx->host.data = url.host.data;
}
} else {
ngx_str_set(&ctx->host, "localhost");
}
return NGX_OK;
}
static ngx_int_t static ngx_int_t
ngx_http_grpc_create_request(ngx_http_request_t *r) ngx_http_grpc_create_request(ngx_http_request_t *r)
{ {
@@ -587,6 +703,7 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
ngx_chain_t *cl, *body; ngx_chain_t *cl, *body;
ngx_list_part_t *part; ngx_list_part_t *part;
ngx_table_elt_t *header; ngx_table_elt_t *header;
ngx_http_grpc_ctx_t *ctx;
ngx_http_upstream_t *u; ngx_http_upstream_t *u;
ngx_http_grpc_frame_t *f; ngx_http_grpc_frame_t *f;
ngx_http_script_code_pt code; ngx_http_script_code_pt code;
@@ -598,6 +715,8 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
glcf = ngx_http_get_module_loc_conf(r, ngx_http_grpc_module); glcf = ngx_http_get_module_loc_conf(r, ngx_http_grpc_module);
ctx = ngx_http_get_module_ctx(r, ngx_http_grpc_module);
len = sizeof(ngx_http_grpc_connection_start) - 1 len = sizeof(ngx_http_grpc_connection_start) - 1
+ sizeof(ngx_http_grpc_frame_t); /* headers frame */ + sizeof(ngx_http_grpc_frame_t); /* headers frame */
@@ -637,10 +756,10 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
/* :authority header */ /* :authority header */
if (!glcf->host_set) { if (!glcf->host_set) {
len += 1 + NGX_HTTP_V2_INT_OCTETS + glcf->host.len; len += 1 + NGX_HTTP_V2_INT_OCTETS + ctx->host.len;
if (tmp_len < glcf->host.len) { if (tmp_len < ctx->host.len) {
tmp_len = glcf->host.len; tmp_len = ctx->host.len;
} }
} }
@@ -785,7 +904,7 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
} }
#if (NGX_HTTP_SSL) #if (NGX_HTTP_SSL)
if (glcf->ssl) { if (u->ssl) {
*b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTPS_INDEX); *b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTPS_INDEX);
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -846,11 +965,11 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
if (!glcf->host_set) { if (!glcf->host_set) {
*b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_AUTHORITY_INDEX); *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_AUTHORITY_INDEX);
b->last = ngx_http_v2_write_value(b->last, glcf->host.data, b->last = ngx_http_v2_write_value(b->last, ctx->host.data,
glcf->host.len, tmp); ctx->host.len, tmp);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"grpc header: \":authority: %V\"", &glcf->host); "grpc header: \":authority: %V\"", &ctx->host);
} }
ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
@@ -1089,6 +1208,7 @@ ngx_http_grpc_reinit_request(ngx_http_request_t *r)
ctx->end_stream = 0; ctx->end_stream = 0;
ctx->done = 0; ctx->done = 0;
ctx->status = 0; ctx->status = 0;
ctx->rst = 0;
ctx->connection = NULL; ctx->connection = NULL;
return NGX_OK; return NGX_OK;
@@ -1835,10 +1955,28 @@ ngx_http_grpc_filter_init(void *data)
r = ctx->request; r = ctx->request;
u = r->upstream; u = r->upstream;
u->length = 1; if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
|| r->method == NGX_HTTP_HEAD)
{
ctx->length = 0;
} else {
ctx->length = u->headers_in.content_length_n;
}
if (ctx->end_stream) { if (ctx->end_stream) {
if (ctx->length > 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream prematurely closed stream");
return NGX_ERROR;
}
u->length = 0; u->length = 0;
} else {
u->length = 1;
} }
return NGX_OK; return NGX_OK;
@@ -1881,6 +2019,12 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
if (ctx->done) { if (ctx->done) {
if (ctx->length > 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream prematurely closed stream");
return NGX_ERROR;
}
/* /*
* We have finished parsing the response and the * We have finished parsing the response and the
* remaining control frames. If there are unsent * remaining control frames. If there are unsent
@@ -1934,6 +2078,17 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
return NGX_ERROR; return NGX_ERROR;
} }
if (ctx->length != -1) {
if ((off_t) ctx->rest > ctx->length) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream sent response body larger "
"than indicated content length");
return NGX_ERROR;
}
ctx->length -= ctx->rest;
}
if (ctx->rest > ctx->recv_window) { if (ctx->rest > ctx->recv_window) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream violated stream flow control, " "upstream violated stream flow control, "
@@ -1972,7 +2127,10 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
return NGX_ERROR; return NGX_ERROR;
} }
if (ctx->stream_id && ctx->done) { if (ctx->stream_id && ctx->done
&& ctx->type != NGX_HTTP_V2_RST_STREAM_FRAME
&& ctx->type != NGX_HTTP_V2_WINDOW_UPDATE_FRAME)
{
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream sent frame for closed stream %ui", "upstream sent frame for closed stream %ui",
ctx->stream_id); ctx->stream_id);
@@ -2015,11 +2173,21 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
return NGX_ERROR; return NGX_ERROR;
} }
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, if (ctx->error || !ctx->done) {
"upstream rejected request with error %ui", ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
ctx->error); "upstream rejected request with error %ui",
ctx->error);
return NGX_ERROR;
}
return NGX_ERROR; if (ctx->rst) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream sent frame for closed stream %ui",
ctx->stream_id);
return NGX_ERROR;
}
ctx->rst = 1;
} }
if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) { if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) {
@@ -4319,15 +4487,23 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
if (clcf->noname && conf->upstream.upstream == NULL) { if (clcf->noname
&& conf->upstream.upstream == NULL && conf->grpc_lengths == NULL)
{
conf->upstream.upstream = prev->upstream.upstream; conf->upstream.upstream = prev->upstream.upstream;
conf->host = prev->host; conf->host = prev->host;
conf->grpc_lengths = prev->grpc_lengths;
conf->grpc_values = prev->grpc_values;
#if (NGX_HTTP_SSL) #if (NGX_HTTP_SSL)
conf->upstream.ssl = prev->upstream.ssl; conf->upstream.ssl = prev->upstream.ssl;
#endif #endif
} }
if (clcf->lmt_excpt && clcf->handler == NULL && conf->upstream.upstream) { if (clcf->lmt_excpt && clcf->handler == NULL
&& (conf->upstream.upstream || conf->grpc_lengths))
{
clcf->handler = ngx_http_grpc_handler; clcf->handler = ngx_http_grpc_handler;
} }
@@ -4537,18 +4713,54 @@ ngx_http_grpc_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{ {
ngx_http_grpc_loc_conf_t *glcf = conf; ngx_http_grpc_loc_conf_t *glcf = conf;
size_t add; size_t add;
ngx_str_t *value, *url; ngx_str_t *value, *url;
ngx_url_t u; ngx_url_t u;
ngx_http_core_loc_conf_t *clcf; ngx_uint_t n;
ngx_http_core_loc_conf_t *clcf;
ngx_http_script_compile_t sc;
if (glcf->upstream.upstream) { if (glcf->upstream.upstream || glcf->grpc_lengths) {
return "is duplicate"; return "is duplicate";
} }
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_http_grpc_handler;
if (clcf->name.len && clcf->name.data[clcf->name.len - 1] == '/') {
clcf->auto_redirect = 1;
}
value = cf->args->elts; value = cf->args->elts;
url = &value[1]; url = &value[1];
n = ngx_http_script_variables_count(url);
if (n) {
ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
sc.cf = cf;
sc.source = url;
sc.lengths = &glcf->grpc_lengths;
sc.values = &glcf->grpc_values;
sc.variables = n;
sc.complete_lengths = 1;
sc.complete_values = 1;
if (ngx_http_script_compile(&sc) != NGX_OK) {
return NGX_CONF_ERROR;
}
#if (NGX_HTTP_SSL)
glcf->ssl = 1;
#endif
return NGX_CONF_OK;
}
if (ngx_strncasecmp(url->data, (u_char *) "grpc://", 7) == 0) { if (ngx_strncasecmp(url->data, (u_char *) "grpc://", 7) == 0) {
add = 7; add = 7;
@@ -4593,14 +4805,6 @@ ngx_http_grpc_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_str_set(&glcf->host, "localhost"); ngx_str_set(&glcf->host, "localhost");
} }
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_http_grpc_handler;
if (clcf->name.len && clcf->name.data[clcf->name.len - 1] == '/') {
clcf->auto_redirect = 1;
}
return NGX_CONF_OK; return NGX_CONF_OK;
} }
+6 -3
View File
@@ -485,10 +485,11 @@ ngx_http_memcached_filter(void *data, ssize_t bytes)
if (u->length == (ssize_t) ctx->rest) { if (u->length == (ssize_t) ctx->rest) {
if (ngx_strncmp(b->last, if (bytes > u->length
|| ngx_strncmp(b->last,
ngx_http_memcached_end + NGX_HTTP_MEMCACHED_END - ctx->rest, ngx_http_memcached_end + NGX_HTTP_MEMCACHED_END - ctx->rest,
bytes) bytes)
!= 0) != 0)
{ {
ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0, ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
"memcached sent invalid trailer"); "memcached sent invalid trailer");
@@ -540,7 +541,9 @@ ngx_http_memcached_filter(void *data, ssize_t bytes)
last += (size_t) (u->length - NGX_HTTP_MEMCACHED_END); last += (size_t) (u->length - NGX_HTTP_MEMCACHED_END);
if (ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0) { if (bytes > u->length
|| ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0)
{
ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0, ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
"memcached sent invalid trailer"); "memcached sent invalid trailer");
+64 -11
View File
@@ -3116,6 +3116,13 @@ ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
"chunk samples sizes:%uL", "chunk samples sizes:%uL",
trak->start_chunk_samples_size); trak->start_chunk_samples_size);
if (trak->start_chunk_samples_size > (uint64_t) mp4->end) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"too large mp4 start samples size in \"%s\"",
mp4->file.name.data);
return NGX_ERROR;
}
if (mp4->length) { if (mp4->length) {
if (trak->end_sample - trak->start_sample > entries) { if (trak->end_sample - trak->start_sample > entries) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
@@ -3135,6 +3142,13 @@ ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
"mp4 stsz end_chunk_samples_size:%uL", "mp4 stsz end_chunk_samples_size:%uL",
trak->end_chunk_samples_size); trak->end_chunk_samples_size);
if (trak->end_chunk_samples_size > (uint64_t) mp4->end) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"too large mp4 end samples size in \"%s\"",
mp4->file.name.data);
return NGX_ERROR;
}
} }
atom_size = sizeof(ngx_mp4_stsz_atom_t) + (data->last - data->pos); atom_size = sizeof(ngx_mp4_stsz_atom_t) + (data->last - data->pos);
@@ -3226,6 +3240,7 @@ ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
{ {
size_t atom_size; size_t atom_size;
uint32_t entries; uint32_t entries;
uint64_t chunk_offset, samples_size;
ngx_buf_t *atom, *data; ngx_buf_t *atom, *data;
ngx_mp4_stco_atom_t *stco_atom; ngx_mp4_stco_atom_t *stco_atom;
@@ -3256,8 +3271,19 @@ ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
data->pos += trak->start_chunk * sizeof(uint32_t); data->pos += trak->start_chunk * sizeof(uint32_t);
trak->start_offset = ngx_mp4_get_32value(data->pos); chunk_offset = ngx_mp4_get_32value(data->pos);
trak->start_offset += trak->start_chunk_samples_size; samples_size = trak->start_chunk_samples_size;
if (chunk_offset > (uint64_t) mp4->end - samples_size
|| chunk_offset + samples_size > NGX_MAX_UINT32_VALUE)
{
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"too large chunk offset in \"%s\"",
mp4->file.name.data);
return NGX_ERROR;
}
trak->start_offset = chunk_offset + samples_size;
ngx_mp4_set_32value(data->pos, trak->start_offset); ngx_mp4_set_32value(data->pos, trak->start_offset);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
@@ -3276,9 +3302,19 @@ ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
data->last = data->pos + entries * sizeof(uint32_t); data->last = data->pos + entries * sizeof(uint32_t);
if (entries) { if (entries) {
trak->end_offset = chunk_offset = ngx_mp4_get_32value(data->last - sizeof(uint32_t));
ngx_mp4_get_32value(data->last - sizeof(uint32_t)); samples_size = trak->end_chunk_samples_size;
trak->end_offset += trak->end_chunk_samples_size;
if (chunk_offset > (uint64_t) mp4->end - samples_size
|| chunk_offset + samples_size > NGX_MAX_UINT32_VALUE)
{
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"too large chunk offset in \"%s\"",
mp4->file.name.data);
return NGX_ERROR;
}
trak->end_offset = chunk_offset + samples_size;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
"end chunk offset:%O", trak->end_offset); "end chunk offset:%O", trak->end_offset);
@@ -3409,7 +3445,7 @@ ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4,
ngx_http_mp4_trak_t *trak) ngx_http_mp4_trak_t *trak)
{ {
size_t atom_size; size_t atom_size;
uint64_t entries; uint64_t entries, chunk_offset, samples_size;
ngx_buf_t *atom, *data; ngx_buf_t *atom, *data;
ngx_mp4_co64_atom_t *co64_atom; ngx_mp4_co64_atom_t *co64_atom;
@@ -3440,8 +3476,17 @@ ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4,
data->pos += trak->start_chunk * sizeof(uint64_t); data->pos += trak->start_chunk * sizeof(uint64_t);
trak->start_offset = ngx_mp4_get_64value(data->pos); chunk_offset = ngx_mp4_get_64value(data->pos);
trak->start_offset += trak->start_chunk_samples_size; samples_size = trak->start_chunk_samples_size;
if (chunk_offset > (uint64_t) mp4->end - samples_size) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"too large chunk offset in \"%s\"",
mp4->file.name.data);
return NGX_ERROR;
}
trak->start_offset = chunk_offset + samples_size;
ngx_mp4_set_64value(data->pos, trak->start_offset); ngx_mp4_set_64value(data->pos, trak->start_offset);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
@@ -3460,9 +3505,17 @@ ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4,
data->last = data->pos + entries * sizeof(uint64_t); data->last = data->pos + entries * sizeof(uint64_t);
if (entries) { if (entries) {
trak->end_offset = chunk_offset = ngx_mp4_get_64value(data->last - sizeof(uint64_t));
ngx_mp4_get_64value(data->last - sizeof(uint64_t)); samples_size = trak->end_chunk_samples_size;
trak->end_offset += trak->end_chunk_samples_size;
if (chunk_offset > (uint64_t) mp4->end - samples_size) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"too large chunk offset in \"%s\"",
mp4->file.name.data);
return NGX_ERROR;
}
trak->end_offset = chunk_offset + samples_size;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
"end chunk offset:%O", trak->end_offset); "end chunk offset:%O", trak->end_offset);
+75 -12
View File
@@ -2015,6 +2015,25 @@ ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
return NGX_OK; return NGX_OK;
} }
if (p->upstream_done) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
"http proxy data after close");
return NGX_OK;
}
if (p->length == 0) {
ngx_log_error(NGX_LOG_WARN, p->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
r = p->input_ctx;
r->upstream->keepalive = 0;
p->upstream_done = 1;
return NGX_OK;
}
cl = ngx_chain_get_free_buf(p->pool, &p->free); cl = ngx_chain_get_free_buf(p->pool, &p->free);
if (cl == NULL) { if (cl == NULL) {
return NGX_ERROR; return NGX_ERROR;
@@ -2042,20 +2061,23 @@ ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
return NGX_OK; return NGX_OK;
} }
if (b->last - b->pos > p->length) {
ngx_log_error(NGX_LOG_WARN, p->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
b->last = b->pos + p->length;
p->upstream_done = 1;
return NGX_OK;
}
p->length -= b->last - b->pos; p->length -= b->last - b->pos;
if (p->length == 0) { if (p->length == 0) {
r = p->input_ctx; r = p->input_ctx;
p->upstream_done = 1;
r->upstream->keepalive = !r->upstream->headers_in.connection_close; r->upstream->keepalive = !r->upstream->headers_in.connection_close;
} else if (p->length < 0) {
r = p->input_ctx;
p->upstream_done = 1;
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
} }
return NGX_OK; return NGX_OK;
@@ -2082,6 +2104,23 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
return NGX_ERROR; return NGX_ERROR;
} }
if (p->upstream_done) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
"http proxy data after close");
return NGX_OK;
}
if (p->length == 0) {
ngx_log_error(NGX_LOG_WARN, p->log, 0,
"upstream sent data after final chunk");
r->upstream->keepalive = 0;
p->upstream_done = 1;
return NGX_OK;
}
b = NULL; b = NULL;
prev = &buf->shadow; prev = &buf->shadow;
@@ -2144,9 +2183,15 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
/* a whole response has been parsed successfully */ /* a whole response has been parsed successfully */
p->upstream_done = 1; p->length = 0;
r->upstream->keepalive = !r->upstream->headers_in.connection_close; r->upstream->keepalive = !r->upstream->headers_in.connection_close;
if (buf->pos != buf->last) {
ngx_log_error(NGX_LOG_WARN, p->log, 0,
"upstream sent data after final chunk");
r->upstream->keepalive = 0;
}
break; break;
} }
@@ -2161,13 +2206,13 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
/* invalid response */ /* invalid response */
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, ngx_log_error(NGX_LOG_ERR, p->log, 0,
"upstream sent invalid chunked response"); "upstream sent invalid chunked response");
return NGX_ERROR; return NGX_ERROR;
} }
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ngx_log_debug2(NGX_LOG_DEBUG_HTTP, p->log, 0,
"http proxy chunked state %ui, length %O", "http proxy chunked state %ui, length %O",
ctx->chunked.state, p->length); ctx->chunked.state, p->length);
@@ -2227,6 +2272,18 @@ ngx_http_proxy_non_buffered_copy_filter(void *data, ssize_t bytes)
return NGX_OK; return NGX_OK;
} }
if (bytes > u->length) {
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
cl->buf->last = cl->buf->pos + u->length;
u->length = 0;
return NGX_OK;
}
u->length -= bytes; u->length -= bytes;
if (u->length == 0) { if (u->length == 0) {
@@ -2313,6 +2370,12 @@ ngx_http_proxy_non_buffered_chunked_filter(void *data, ssize_t bytes)
u->keepalive = !u->headers_in.connection_close; u->keepalive = !u->headers_in.connection_close;
u->length = 0; u->length = 0;
if (buf->pos != buf->last) {
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
"upstream sent data after final chunk");
u->keepalive = 0;
}
break; break;
} }
+36
View File
@@ -49,6 +49,7 @@ static ngx_int_t ngx_http_scgi_create_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_scgi_reinit_request(ngx_http_request_t *r); static ngx_int_t ngx_http_scgi_reinit_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_scgi_process_status_line(ngx_http_request_t *r); static ngx_int_t ngx_http_scgi_process_status_line(ngx_http_request_t *r);
static ngx_int_t ngx_http_scgi_process_header(ngx_http_request_t *r); static ngx_int_t ngx_http_scgi_process_header(ngx_http_request_t *r);
static ngx_int_t ngx_http_scgi_input_filter_init(void *data);
static void ngx_http_scgi_abort_request(ngx_http_request_t *r); static void ngx_http_scgi_abort_request(ngx_http_request_t *r);
static void ngx_http_scgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc); static void ngx_http_scgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc);
@@ -534,6 +535,10 @@ ngx_http_scgi_handler(ngx_http_request_t *r)
u->pipe->input_filter = ngx_event_pipe_copy_input_filter; u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
u->pipe->input_ctx = r; u->pipe->input_ctx = r;
u->input_filter_init = ngx_http_scgi_input_filter_init;
u->input_filter = ngx_http_upstream_non_buffered_filter;
u->input_filter_ctx = r;
if (!scf->upstream.request_buffering if (!scf->upstream.request_buffering
&& scf->upstream.pass_request_body && scf->upstream.pass_request_body
&& !r->headers_in.chunked) && !r->headers_in.chunked)
@@ -1145,6 +1150,37 @@ ngx_http_scgi_process_header(ngx_http_request_t *r)
} }
static ngx_int_t
ngx_http_scgi_input_filter_init(void *data)
{
ngx_http_request_t *r = data;
ngx_http_upstream_t *u;
u = r->upstream;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http scgi filter init s:%ui l:%O",
u->headers_in.status_n, u->headers_in.content_length_n);
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED)
{
u->pipe->length = 0;
u->length = 0;
} else if (r->method == NGX_HTTP_HEAD) {
u->pipe->length = -1;
u->length = -1;
} else {
u->pipe->length = u->headers_in.content_length_n;
u->length = u->headers_in.content_length_n;
}
return NGX_OK;
}
static void static void
ngx_http_scgi_abort_request(ngx_http_request_t *r) ngx_http_scgi_abort_request(ngx_http_request_t *r)
{ {
@@ -180,6 +180,11 @@ ngx_http_slice_header_filter(ngx_http_request_t *r)
r->headers_out.content_range->hash = 0; r->headers_out.content_range->hash = 0;
r->headers_out.content_range = NULL; r->headers_out.content_range = NULL;
if (r->headers_out.accept_ranges) {
r->headers_out.accept_ranges->hash = 0;
r->headers_out.accept_ranges = NULL;
}
r->allow_ranges = 1; r->allow_ranges = 1;
r->subrequest_ranges = 1; r->subrequest_ranges = 1;
r->single_range = 1; r->single_range = 1;
+151 -5
View File
@@ -50,6 +50,8 @@ static char *ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf); void *conf);
static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf); void *conf);
static char *ngx_http_ssl_ocsp_cache(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf); static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf);
@@ -74,6 +76,14 @@ static ngx_conf_enum_t ngx_http_ssl_verify[] = {
}; };
static ngx_conf_enum_t ngx_http_ssl_ocsp[] = {
{ ngx_string("off"), 0 },
{ ngx_string("on"), 1 },
{ ngx_string("leaf"), 2 },
{ ngx_null_string, 0 }
};
static ngx_conf_deprecated_t ngx_http_ssl_deprecated = { static ngx_conf_deprecated_t ngx_http_ssl_deprecated = {
ngx_conf_deprecated, "ssl", "listen ... ssl" ngx_conf_deprecated, "ssl", "listen ... ssl"
}; };
@@ -221,6 +231,27 @@ static ngx_command_t ngx_http_ssl_commands[] = {
offsetof(ngx_http_ssl_srv_conf_t, crl), offsetof(ngx_http_ssl_srv_conf_t, crl),
NULL }, NULL },
{ ngx_string("ssl_ocsp"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
ngx_conf_set_enum_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_ssl_srv_conf_t, ocsp),
&ngx_http_ssl_ocsp },
{ ngx_string("ssl_ocsp_responder"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_ssl_srv_conf_t, ocsp_responder),
NULL },
{ ngx_string("ssl_ocsp_cache"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_http_ssl_ocsp_cache,
NGX_HTTP_SRV_CONF_OFFSET,
0,
NULL },
{ ngx_string("ssl_stapling"), { ngx_string("ssl_stapling"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot, ngx_conf_set_flag_slot,
@@ -603,6 +634,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
* sscf->crl = { 0, NULL }; * sscf->crl = { 0, NULL };
* sscf->ciphers = { 0, NULL }; * sscf->ciphers = { 0, NULL };
* sscf->shm_zone = NULL; * sscf->shm_zone = NULL;
* sscf->ocsp_responder = { 0, NULL };
* sscf->stapling_file = { 0, NULL }; * sscf->stapling_file = { 0, NULL };
* sscf->stapling_responder = { 0, NULL }; * sscf->stapling_responder = { 0, NULL };
*/ */
@@ -621,6 +653,8 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
sscf->session_timeout_tls13 = NGX_CONF_UNSET; sscf->session_timeout_tls13 = NGX_CONF_UNSET;
sscf->session_tickets = NGX_CONF_UNSET; sscf->session_tickets = NGX_CONF_UNSET;
sscf->session_ticket_keys = NGX_CONF_UNSET_PTR; sscf->session_ticket_keys = NGX_CONF_UNSET_PTR;
sscf->ocsp = NGX_CONF_UNSET_UINT;
sscf->ocsp_cache_zone = NGX_CONF_UNSET_PTR;
sscf->stapling = NGX_CONF_UNSET; sscf->stapling = NGX_CONF_UNSET;
sscf->stapling_verify = NGX_CONF_UNSET; sscf->stapling_verify = NGX_CONF_UNSET;
sscf->dyn_rec_enable = NGX_CONF_UNSET; sscf->dyn_rec_enable = NGX_CONF_UNSET;
@@ -691,6 +725,11 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
ngx_conf_merge_uint_value(conf->ocsp, prev->ocsp, 0);
ngx_conf_merge_str_value(conf->ocsp_responder, prev->ocsp_responder, "");
ngx_conf_merge_ptr_value(conf->ocsp_cache_zone,
prev->ocsp_cache_zone, NULL);
ngx_conf_merge_value(conf->stapling, prev->stapling, 0); ngx_conf_merge_value(conf->stapling, prev->stapling, 0);
ngx_conf_merge_value(conf->stapling_verify, prev->stapling_verify, 0); ngx_conf_merge_value(conf->stapling_verify, prev->stapling_verify, 0);
ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, ""); ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, "");
@@ -866,6 +905,23 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
if (conf->ocsp) {
if (conf->verify == 3) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"\"ssl_ocsp\" is incompatible with "
"\"ssl_verify_client optional_no_ca\"");
return NGX_CONF_ERROR;
}
if (ngx_ssl_ocsp(cf, &conf->ssl, &conf->ocsp_responder, conf->ocsp,
conf->ocsp_cache_zone)
!= NGX_OK)
{
return NGX_CONF_ERROR;
}
}
if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
@@ -1186,6 +1242,85 @@ invalid:
} }
static char *
ngx_http_ssl_ocsp_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_ssl_srv_conf_t *sscf = conf;
size_t len;
ngx_int_t n;
ngx_str_t *value, name, size;
ngx_uint_t j;
if (sscf->ocsp_cache_zone != NGX_CONF_UNSET_PTR) {
return "is duplicate";
}
value = cf->args->elts;
if (ngx_strcmp(value[1].data, "off") == 0) {
sscf->ocsp_cache_zone = NULL;
return NGX_CONF_OK;
}
if (value[1].len <= sizeof("shared:") - 1
|| ngx_strncmp(value[1].data, "shared:", sizeof("shared:") - 1) != 0)
{
goto invalid;
}
len = 0;
for (j = sizeof("shared:") - 1; j < value[1].len; j++) {
if (value[1].data[j] == ':') {
break;
}
len++;
}
if (len == 0) {
goto invalid;
}
name.len = len;
name.data = value[1].data + sizeof("shared:") - 1;
size.len = value[1].len - j - 1;
size.data = name.data + len + 1;
n = ngx_parse_size(&size);
if (n == NGX_ERROR) {
goto invalid;
}
if (n < (ngx_int_t) (8 * ngx_pagesize)) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"OCSP cache \"%V\" is too small", &value[1]);
return NGX_CONF_ERROR;
}
sscf->ocsp_cache_zone = ngx_shared_memory_add(cf, &name, n,
&ngx_http_ssl_module_ctx);
if (sscf->ocsp_cache_zone == NULL) {
return NGX_CONF_ERROR;
}
sscf->ocsp_cache_zone->init = ngx_ssl_ocsp_cache_init;
return NGX_CONF_OK;
invalid:
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid OCSP cache \"%V\"", &value[1]);
return NGX_CONF_ERROR;
}
static ngx_int_t static ngx_int_t
ngx_http_ssl_init(ngx_conf_t *cf) ngx_http_ssl_init(ngx_conf_t *cf)
{ {
@@ -1204,17 +1339,28 @@ ngx_http_ssl_init(ngx_conf_t *cf)
sscf = cscfp[s]->ctx->srv_conf[ngx_http_ssl_module.ctx_index]; sscf = cscfp[s]->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
if (sscf->ssl.ctx == NULL || !sscf->stapling) { if (sscf->ssl.ctx == NULL) {
continue; continue;
} }
clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index]; clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
if (ngx_ssl_stapling_resolver(cf, &sscf->ssl, clcf->resolver, if (sscf->stapling) {
if (ngx_ssl_stapling_resolver(cf, &sscf->ssl, clcf->resolver,
clcf->resolver_timeout)
!= NGX_OK)
{
return NGX_ERROR;
}
}
if (sscf->ocsp) {
if (ngx_ssl_ocsp_resolver(cf, &sscf->ssl, clcf->resolver,
clcf->resolver_timeout) clcf->resolver_timeout)
!= NGX_OK) != NGX_OK)
{ {
return NGX_ERROR; return NGX_ERROR;
}
} }
} }
+4
View File
@@ -55,6 +55,10 @@ typedef struct {
ngx_flag_t session_tickets; ngx_flag_t session_tickets;
ngx_array_t *session_ticket_keys; ngx_array_t *session_ticket_keys;
ngx_uint_t ocsp;
ngx_str_t ocsp_responder;
ngx_shm_zone_t *ocsp_cache_zone;
ngx_flag_t stapling; ngx_flag_t stapling;
ngx_flag_t stapling_verify; ngx_flag_t stapling_verify;
ngx_str_t stapling_file; ngx_str_t stapling_file;
+37
View File
@@ -67,6 +67,7 @@ static ngx_int_t ngx_http_uwsgi_create_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_uwsgi_reinit_request(ngx_http_request_t *r); static ngx_int_t ngx_http_uwsgi_reinit_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_uwsgi_process_status_line(ngx_http_request_t *r); static ngx_int_t ngx_http_uwsgi_process_status_line(ngx_http_request_t *r);
static ngx_int_t ngx_http_uwsgi_process_header(ngx_http_request_t *r); static ngx_int_t ngx_http_uwsgi_process_header(ngx_http_request_t *r);
static ngx_int_t ngx_http_uwsgi_input_filter_init(void *data);
static void ngx_http_uwsgi_abort_request(ngx_http_request_t *r); static void ngx_http_uwsgi_abort_request(ngx_http_request_t *r);
static void ngx_http_uwsgi_finalize_request(ngx_http_request_t *r, static void ngx_http_uwsgi_finalize_request(ngx_http_request_t *r,
ngx_int_t rc); ngx_int_t rc);
@@ -703,6 +704,10 @@ ngx_http_uwsgi_handler(ngx_http_request_t *r)
u->pipe->input_filter = ngx_event_pipe_copy_input_filter; u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
u->pipe->input_ctx = r; u->pipe->input_ctx = r;
u->input_filter_init = ngx_http_uwsgi_input_filter_init;
u->input_filter = ngx_http_upstream_non_buffered_filter;
u->input_filter_ctx = r;
if (!uwcf->upstream.request_buffering if (!uwcf->upstream.request_buffering
&& uwcf->upstream.pass_request_body && uwcf->upstream.pass_request_body
&& !r->headers_in.chunked) && !r->headers_in.chunked)
@@ -1141,6 +1146,7 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
r->upstream->request_bufs = cl; r->upstream->request_bufs = cl;
} }
b->flush = 1;
cl->next = NULL; cl->next = NULL;
return NGX_OK; return NGX_OK;
@@ -1355,6 +1361,37 @@ ngx_http_uwsgi_process_header(ngx_http_request_t *r)
} }
static ngx_int_t
ngx_http_uwsgi_input_filter_init(void *data)
{
ngx_http_request_t *r = data;
ngx_http_upstream_t *u;
u = r->upstream;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http uwsgi filter init s:%ui l:%O",
u->headers_in.status_n, u->headers_in.content_length_n);
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED)
{
u->pipe->length = 0;
u->length = 0;
} else if (r->method == NGX_HTTP_HEAD) {
u->pipe->length = -1;
u->length = -1;
} else {
u->pipe->length = u->headers_in.content_length_n;
u->length = u->headers_in.content_length_n;
}
return NGX_OK;
}
static void static void
ngx_http_uwsgi_abort_request(ngx_http_request_t *r) ngx_http_uwsgi_abort_request(ngx_http_request_t *r)
{ {
@@ -233,6 +233,7 @@ ngx_http_xslt_header_filter(ngx_http_request_t *r)
ngx_http_set_ctx(r, ctx, ngx_http_xslt_filter_module); ngx_http_set_ctx(r, ctx, ngx_http_xslt_filter_module);
r->main_filter_need_in_memory = 1; r->main_filter_need_in_memory = 1;
r->allow_ranges = 0;
return NGX_OK; return NGX_OK;
} }
+2 -2
View File
@@ -1469,14 +1469,14 @@ ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
NGX_HASH_WILDCARD_KEY); NGX_HASH_WILDCARD_KEY);
if (rc == NGX_ERROR) { if (rc == NGX_ERROR) {
return NGX_ERROR; goto failed;
} }
if (rc == NGX_DECLINED) { if (rc == NGX_DECLINED) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0, ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"invalid server name or wildcard \"%V\" on %V", "invalid server name or wildcard \"%V\" on %V",
&name[n].name, &addr->opt.addr_text); &name[n].name, &addr->opt.addr_text);
return NGX_ERROR; goto failed;
} }
if (rc == NGX_BUSY) { if (rc == NGX_BUSY) {
+1
View File
@@ -160,6 +160,7 @@ struct ngx_http_file_cache_s {
ngx_path_t *path; ngx_path_t *path;
off_t min_free;
off_t max_size; off_t max_size;
size_t bsize; size_t bsize;
+111 -32
View File
@@ -21,6 +21,9 @@ typedef struct {
#define NGX_HTTP_REQUEST_BODY_FILE_CLEAN 2 #define NGX_HTTP_REQUEST_BODY_FILE_CLEAN 2
static ngx_int_t ngx_http_core_auth_delay(ngx_http_request_t *r);
static void ngx_http_core_auth_delay_handler(ngx_http_request_t *r);
static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r); static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r);
static ngx_int_t ngx_http_core_find_static_location(ngx_http_request_t *r, static ngx_int_t ngx_http_core_find_static_location(ngx_http_request_t *r,
ngx_http_location_tree_node_t *node); ngx_http_location_tree_node_t *node);
@@ -534,6 +537,13 @@ static ngx_command_t ngx_http_core_commands[] = {
offsetof(ngx_http_core_loc_conf_t, satisfy), offsetof(ngx_http_core_loc_conf_t, satisfy),
&ngx_http_core_satisfy }, &ngx_http_core_satisfy },
{ ngx_string("auth_delay"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_core_loc_conf_t, auth_delay),
NULL },
{ ngx_string("internal"), { ngx_string("internal"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_http_core_internal, ngx_http_core_internal,
@@ -1138,6 +1148,10 @@ ngx_http_core_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
/* rc == NGX_ERROR || rc == NGX_HTTP_... */ /* rc == NGX_ERROR || rc == NGX_HTTP_... */
if (rc == NGX_HTTP_UNAUTHORIZED) {
return ngx_http_core_auth_delay(r);
}
ngx_http_finalize_request(r, rc); ngx_http_finalize_request(r, rc);
return NGX_OK; return NGX_OK;
} }
@@ -1155,12 +1169,17 @@ ngx_http_core_post_access_phase(ngx_http_request_t *r,
access_code = r->access_code; access_code = r->access_code;
if (access_code) { if (access_code) {
r->access_code = 0;
if (access_code == NGX_HTTP_FORBIDDEN) { if (access_code == NGX_HTTP_FORBIDDEN) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"access forbidden by rule"); "access forbidden by rule");
} }
r->access_code = 0; if (access_code == NGX_HTTP_UNAUTHORIZED) {
return ngx_http_core_auth_delay(r);
}
ngx_http_finalize_request(r, access_code); ngx_http_finalize_request(r, access_code);
return NGX_OK; return NGX_OK;
} }
@@ -1170,6 +1189,65 @@ ngx_http_core_post_access_phase(ngx_http_request_t *r,
} }
static ngx_int_t
ngx_http_core_auth_delay(ngx_http_request_t *r)
{
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (clcf->auth_delay == 0) {
ngx_http_finalize_request(r, NGX_HTTP_UNAUTHORIZED);
return NGX_OK;
}
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"delaying unauthorized request");
if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
r->read_event_handler = ngx_http_test_reading;
r->write_event_handler = ngx_http_core_auth_delay_handler;
r->connection->write->delayed = 1;
ngx_add_timer(r->connection->write, clcf->auth_delay);
/*
* trigger an additional event loop iteration
* to ensure constant-time processing
*/
ngx_post_event(r->connection->write, &ngx_posted_next_events);
return NGX_OK;
}
static void
ngx_http_core_auth_delay_handler(ngx_http_request_t *r)
{
ngx_event_t *wev;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"auth delay handler");
wev = r->connection->write;
if (wev->delayed) {
if (ngx_handle_write_event(wev, 0) != NGX_OK) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
}
return;
}
ngx_http_finalize_request(r, NGX_HTTP_UNAUTHORIZED);
}
ngx_int_t ngx_int_t
ngx_http_core_content_phase(ngx_http_request_t *r, ngx_http_core_content_phase(ngx_http_request_t *r,
ngx_http_phase_handler_t *ph) ngx_http_phase_handler_t *ph)
@@ -2681,43 +2759,41 @@ ngx_http_get_forwarded_addr_internal(ngx_http_request_t *r, ngx_addr_t *addr,
u_char *xff, size_t xfflen, ngx_array_t *proxies, int recursive) u_char *xff, size_t xfflen, ngx_array_t *proxies, int recursive)
{ {
u_char *p; u_char *p;
ngx_int_t rc;
ngx_addr_t paddr; ngx_addr_t paddr;
ngx_uint_t found;
if (ngx_cidr_match(addr->sockaddr, proxies) != NGX_OK) { found = 0;
return NGX_DECLINED;
}
for (p = xff + xfflen - 1; p > xff; p--, xfflen--) { do {
if (*p != ' ' && *p != ',') {
break;
}
}
for ( /* void */ ; p > xff; p--) { if (ngx_cidr_match(addr->sockaddr, proxies) != NGX_OK) {
if (*p == ' ' || *p == ',') { return found ? NGX_DONE : NGX_DECLINED;
p++;
break;
}
}
if (ngx_parse_addr_port(r->pool, &paddr, p, xfflen - (p - xff)) != NGX_OK) {
return NGX_DECLINED;
}
*addr = paddr;
if (recursive && p > xff) {
rc = ngx_http_get_forwarded_addr_internal(r, addr, xff, p - 1 - xff,
proxies, 1);
if (rc == NGX_DECLINED) {
return NGX_DONE;
} }
/* rc == NGX_OK || rc == NGX_DONE */ for (p = xff + xfflen - 1; p > xff; p--, xfflen--) {
return rc; if (*p != ' ' && *p != ',') {
} break;
}
}
for ( /* void */ ; p > xff; p--) {
if (*p == ' ' || *p == ',') {
p++;
break;
}
}
if (ngx_parse_addr_port(r->pool, &paddr, p, xfflen - (p - xff))
!= NGX_OK)
{
return found ? NGX_DONE : NGX_DECLINED;
}
*addr = paddr;
found = 1;
xfflen = p - 1 - xff;
} while (recursive && p > xff);
return NGX_OK; return NGX_OK;
} }
@@ -3410,6 +3486,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf)
clcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE; clcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE;
clcf->client_body_timeout = NGX_CONF_UNSET_MSEC; clcf->client_body_timeout = NGX_CONF_UNSET_MSEC;
clcf->satisfy = NGX_CONF_UNSET_UINT; clcf->satisfy = NGX_CONF_UNSET_UINT;
clcf->auth_delay = NGX_CONF_UNSET_MSEC;
clcf->if_modified_since = NGX_CONF_UNSET_UINT; clcf->if_modified_since = NGX_CONF_UNSET_UINT;
clcf->max_ranges = NGX_CONF_UNSET_UINT; clcf->max_ranges = NGX_CONF_UNSET_UINT;
clcf->client_body_in_file_only = NGX_CONF_UNSET_UINT; clcf->client_body_in_file_only = NGX_CONF_UNSET_UINT;
@@ -3627,6 +3704,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|NGX_HTTP_KEEPALIVE_DISABLE_MSIE6)); |NGX_HTTP_KEEPALIVE_DISABLE_MSIE6));
ngx_conf_merge_uint_value(conf->satisfy, prev->satisfy, ngx_conf_merge_uint_value(conf->satisfy, prev->satisfy,
NGX_HTTP_SATISFY_ALL); NGX_HTTP_SATISFY_ALL);
ngx_conf_merge_msec_value(conf->auth_delay, prev->auth_delay, 0);
ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since, ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since,
NGX_HTTP_IMS_EXACT); NGX_HTTP_IMS_EXACT);
ngx_conf_merge_uint_value(conf->max_ranges, prev->max_ranges, ngx_conf_merge_uint_value(conf->max_ranges, prev->max_ranges,
@@ -4707,6 +4785,7 @@ ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
case NGX_HTTP_TO_HTTPS: case NGX_HTTP_TO_HTTPS:
case NGX_HTTPS_CERT_ERROR: case NGX_HTTPS_CERT_ERROR:
case NGX_HTTPS_NO_CERT: case NGX_HTTPS_NO_CERT:
case NGX_HTTP_REQUEST_HEADER_TOO_LARGE:
err->overwrite = NGX_HTTP_BAD_REQUEST; err->overwrite = NGX_HTTP_BAD_REQUEST;
} }
} }
+1
View File
@@ -363,6 +363,7 @@ struct ngx_http_core_loc_conf_s {
ngx_msec_t lingering_time; /* lingering_time */ ngx_msec_t lingering_time; /* lingering_time */
ngx_msec_t lingering_timeout; /* lingering_timeout */ ngx_msec_t lingering_timeout; /* lingering_timeout */
ngx_msec_t resolver_timeout; /* resolver_timeout */ ngx_msec_t resolver_timeout; /* resolver_timeout */
ngx_msec_t auth_delay; /* auth_delay */
ngx_resolver_t *resolver; /* resolver */ ngx_resolver_t *resolver; /* resolver */
+40 -3
View File
@@ -1959,7 +1959,7 @@ ngx_http_file_cache_manager(void *data)
{ {
ngx_http_file_cache_t *cache = data; ngx_http_file_cache_t *cache = data;
off_t size; off_t size, free;
time_t wait; time_t wait;
ngx_msec_t elapsed, next; ngx_msec_t elapsed, next;
ngx_uint_t count, watermark; ngx_uint_t count, watermark;
@@ -1988,7 +1988,19 @@ ngx_http_file_cache_manager(void *data)
size, count, (ngx_int_t) watermark); size, count, (ngx_int_t) watermark);
if (size < cache->max_size && count < watermark) { if (size < cache->max_size && count < watermark) {
break;
if (!cache->min_free) {
break;
}
free = ngx_fs_available(cache->path->name.data);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
"http file cache free: %O", free);
if (free > cache->min_free) {
break;
}
} }
wait = ngx_http_file_cache_forced_expire(cache); wait = ngx_http_file_cache_forced_expire(cache);
@@ -2304,7 +2316,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{ {
char *confp = conf; char *confp = conf;
off_t max_size; off_t max_size, min_free;
u_char *last, *p; u_char *last, *p;
time_t inactive; time_t inactive;
ssize_t size; ssize_t size;
@@ -2341,6 +2353,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
name.len = 0; name.len = 0;
size = 0; size = 0;
max_size = NGX_MAX_OFF_T_VALUE; max_size = NGX_MAX_OFF_T_VALUE;
min_free = 0;
value = cf->args->elts; value = cf->args->elts;
@@ -2476,6 +2489,29 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
continue; continue;
} }
if (ngx_strncmp(value[i].data, "min_free=", 9) == 0) {
#if (NGX_WIN32 || NGX_HAVE_STATFS || NGX_HAVE_STATVFS)
s.len = value[i].len - 9;
s.data = value[i].data + 9;
min_free = ngx_parse_offset(&s);
if (min_free < 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid min_free value \"%V\"", &value[i]);
return NGX_CONF_ERROR;
}
#else
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"min_free is not supported "
"on this platform, ignored");
#endif
continue;
}
if (ngx_strncmp(value[i].data, "loader_files=", 13) == 0) { if (ngx_strncmp(value[i].data, "loader_files=", 13) == 0) {
loader_files = ngx_atoi(value[i].data + 13, value[i].len - 13); loader_files = ngx_atoi(value[i].data + 13, value[i].len - 13);
@@ -2607,6 +2643,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
cache->inactive = inactive; cache->inactive = inactive;
cache->max_size = max_size; cache->max_size = max_size;
cache->min_free = min_free;
caches = (ngx_array_t *) (confp + cmd->offset); caches = (ngx_array_t *) (confp + cmd->offset);
+49 -32
View File
@@ -131,7 +131,7 @@ ngx_http_header_t ngx_http_headers_in[] = {
{ ngx_string("Transfer-Encoding"), { ngx_string("Transfer-Encoding"),
offsetof(ngx_http_headers_in_t, transfer_encoding), offsetof(ngx_http_headers_in_t, transfer_encoding),
ngx_http_process_header_line }, ngx_http_process_unique_header_line },
{ ngx_string("TE"), { ngx_string("TE"),
offsetof(ngx_http_headers_in_t, te), offsetof(ngx_http_headers_in_t, te),
@@ -748,6 +748,8 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
return; return;
} }
ngx_reusable_connection(c, 0);
rc = ngx_ssl_handshake(c); rc = ngx_ssl_handshake(c);
if (rc == NGX_AGAIN) { if (rc == NGX_AGAIN) {
@@ -756,8 +758,6 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
ngx_add_timer(rev, c->listening->post_accept_timeout); ngx_add_timer(rev, c->listening->post_accept_timeout);
} }
ngx_reusable_connection(c, 0);
c->ssl->handler = ngx_http_ssl_handshake_handler; c->ssl->handler = ngx_http_ssl_handshake_handler;
return; return;
} }
@@ -1654,6 +1654,12 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http large header copy: %uz", r->header_in->pos - old); "http large header copy: %uz", r->header_in->pos - old);
if (r->header_in->pos - old > b->end - b->start) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
"too large header to copy");
return NGX_ERROR;
}
new = b->start; new = b->start;
ngx_memcpy(new, old, r->header_in->pos - old); ngx_memcpy(new, old, r->header_in->pos - old);
@@ -1762,10 +1768,18 @@ ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
ngx_int_t rc; ngx_int_t rc;
ngx_str_t host; ngx_str_t host;
if (r->headers_in.host == NULL) { if (r->headers_in.host) {
r->headers_in.host = h; ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"client sent duplicate host header: \"%V: %V\", "
"previous value: \"%V: %V\"",
&h->key, &h->value, &r->headers_in.host->key,
&r->headers_in.host->value);
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return NGX_ERROR;
} }
r->headers_in.host = h;
host = h->value; host = h->value;
rc = ngx_http_validate_host(&host, r->pool, 0); rc = ngx_http_validate_host(&host, r->pool, 0);
@@ -1962,10 +1976,7 @@ ngx_http_process_request_header(ngx_http_request_t *r)
r->headers_in.content_length_n = -1; r->headers_in.content_length_n = -1;
r->headers_in.chunked = 1; r->headers_in.chunked = 1;
} else if (r->headers_in.transfer_encoding->value.len != 8 } else {
|| ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
(u_char *) "identity", 8) != 0)
{
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"client sent unknown \"Transfer-Encoding\": \"%V\"", "client sent unknown \"Transfer-Encoding\": \"%V\"",
&r->headers_in.transfer_encoding->value); &r->headers_in.transfer_encoding->value);
@@ -1998,6 +2009,7 @@ ngx_http_process_request(ngx_http_request_t *r)
if (r->http_connection->ssl) { if (r->http_connection->ssl) {
long rc; long rc;
X509 *cert; X509 *cert;
const char *s;
ngx_http_ssl_srv_conf_t *sscf; ngx_http_ssl_srv_conf_t *sscf;
if (c->ssl == NULL) { if (c->ssl == NULL) {
@@ -2046,6 +2058,17 @@ ngx_http_process_request(ngx_http_request_t *r)
X509_free(cert); X509_free(cert);
} }
if (ngx_ssl_ocsp_get_status(c, &s) != NGX_OK) {
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client SSL certificate verify error: %s", s);
ngx_ssl_remove_cached_session(c->ssl->session_ctx,
(SSL_get0_session(c->ssl->connection)));
ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
return;
}
} }
} }
@@ -2497,26 +2520,6 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
} }
if (r != r->main) { if (r != r->main) {
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (r->background) {
if (!r->logged) {
if (clcf->log_subrequest) {
ngx_http_log_request(r);
}
r->logged = 1;
} else {
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
"subrequest: \"%V?%V\" logged again",
&r->uri, &r->args);
}
r->done = 1;
ngx_http_finalize_connection(r);
return;
}
if (r->buffered || r->postponed) { if (r->buffered || r->postponed) {
@@ -2529,11 +2532,12 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
pr = r->parent; pr = r->parent;
if (r == c->data) { if (r == c->data || r->background) {
r->main->count--;
if (!r->logged) { if (!r->logged) {
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (clcf->log_subrequest) { if (clcf->log_subrequest) {
ngx_http_log_request(r); ngx_http_log_request(r);
} }
@@ -2548,6 +2552,13 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
r->done = 1; r->done = 1;
if (r->background) {
ngx_http_finalize_connection(r);
return;
}
r->main->count--;
if (pr->postponed && pr->postponed->request == r) { if (pr->postponed && pr->postponed->request == r) {
pr->postponed = pr->postponed->next; pr->postponed = pr->postponed->next;
} }
@@ -2995,6 +3006,12 @@ closed:
rev->error = 1; rev->error = 1;
} }
#if (NGX_HTTP_SSL)
if (c->ssl) {
c->ssl->no_send_shutdown = 1;
}
#endif
ngx_log_error(NGX_LOG_INFO, c->log, err, ngx_log_error(NGX_LOG_INFO, c->log, err,
"client prematurely closed connection"); "client prematurely closed connection");
+148 -51
View File
@@ -12,6 +12,8 @@
static void ngx_http_read_client_request_body_handler(ngx_http_request_t *r); static void ngx_http_read_client_request_body_handler(ngx_http_request_t *r);
static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r); static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r);
static ngx_int_t ngx_http_copy_pipelined_header(ngx_http_request_t *r,
ngx_buf_t *buf);
static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r); static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r);
static ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r); static ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r);
static ngx_int_t ngx_http_discard_request_body_filter(ngx_http_request_t *r, static ngx_int_t ngx_http_discard_request_body_filter(ngx_http_request_t *r,
@@ -282,28 +284,12 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
for ( ;; ) { for ( ;; ) {
if (rb->buf->last == rb->buf->end) { if (rb->buf->last == rb->buf->end) {
if (rb->buf->pos != rb->buf->last) { /* update chains */
/* pass buffer to request body filter chain */ rc = ngx_http_request_body_filter(r, NULL);
out.buf = rb->buf; if (rc != NGX_OK) {
out.next = NULL; return rc;
rc = ngx_http_request_body_filter(r, &out);
if (rc != NGX_OK) {
return rc;
}
} else {
/* update chains */
rc = ngx_http_request_body_filter(r, NULL);
if (rc != NGX_OK) {
return rc;
}
} }
if (rb->busy != NULL) { if (rb->busy != NULL) {
@@ -355,17 +341,15 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
rb->buf->last += n; rb->buf->last += n;
r->request_length += n; r->request_length += n;
if (n == rest) { /* pass buffer to request body filter chain */
/* pass buffer to request body filter chain */
out.buf = rb->buf; out.buf = rb->buf;
out.next = NULL; out.next = NULL;
rc = ngx_http_request_body_filter(r, &out); rc = ngx_http_request_body_filter(r, &out);
if (rc != NGX_OK) { if (rc != NGX_OK) {
return rc; return rc;
}
} }
if (rb->rest == 0) { if (rb->rest == 0) {
@@ -386,21 +370,6 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
if (!c->read->ready) { if (!c->read->ready) {
if (r->request_body_no_buffering
&& rb->buf->pos != rb->buf->last)
{
/* pass buffer to request body filter chain */
out.buf = rb->buf;
out.next = NULL;
rc = ngx_http_request_body_filter(r, &out);
if (rc != NGX_OK) {
return rc;
}
}
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
ngx_add_timer(c->read, clcf->client_body_timeout); ngx_add_timer(c->read, clcf->client_body_timeout);
@@ -412,6 +381,10 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
} }
} }
if (ngx_http_copy_pipelined_header(r, rb->buf) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
if (c->read->timer_set) { if (c->read->timer_set) {
ngx_del_timer(c->read); ngx_del_timer(c->read);
} }
@@ -425,6 +398,88 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
} }
static ngx_int_t
ngx_http_copy_pipelined_header(ngx_http_request_t *r, ngx_buf_t *buf)
{
size_t n;
ngx_buf_t *b;
ngx_chain_t *cl;
ngx_http_connection_t *hc;
ngx_http_core_srv_conf_t *cscf;
b = r->header_in;
n = buf->last - buf->pos;
if (buf == b || n == 0) {
return NGX_OK;
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http body pipelined header: %uz", n);
/*
* if there is a pipelined request in the client body buffer,
* copy it to the r->header_in buffer if there is enough room,
* or allocate a large client header buffer
*/
if (n > (size_t) (b->end - b->last)) {
hc = r->http_connection;
if (hc->free) {
cl = hc->free;
hc->free = cl->next;
b = cl->buf;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http large header free: %p %uz",
b->pos, b->end - b->last);
} else {
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
b = ngx_create_temp_buf(r->connection->pool,
cscf->large_client_header_buffers.size);
if (b == NULL) {
return NGX_ERROR;
}
cl = ngx_alloc_chain_link(r->connection->pool);
if (cl == NULL) {
return NGX_ERROR;
}
cl->buf = b;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http large header alloc: %p %uz",
b->pos, b->end - b->last);
}
cl->next = hc->busy;
hc->busy = cl;
hc->nbusy++;
r->header_in = b;
if (n > (size_t) (b->end - b->last)) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
"too large pipelined header after reading body");
return NGX_ERROR;
}
}
ngx_memcpy(b->last, buf->pos, n);
b->last += n;
r->request_length -= n;
return NGX_OK;
}
static ngx_int_t static ngx_int_t
ngx_http_write_request_body(ngx_http_request_t *r) ngx_http_write_request_body(ngx_http_request_t *r)
{ {
@@ -670,8 +725,7 @@ ngx_http_read_discarded_request_body(ngx_http_request_t *r)
for ( ;; ) { for ( ;; ) {
if (r->headers_in.content_length_n == 0) { if (r->headers_in.content_length_n == 0) {
r->read_event_handler = ngx_http_block_reading; break;
return NGX_OK;
} }
if (!r->connection->read->ready) { if (!r->connection->read->ready) {
@@ -705,15 +759,24 @@ ngx_http_read_discarded_request_body(ngx_http_request_t *r)
return rc; return rc;
} }
} }
if (ngx_http_copy_pipelined_header(r, &b) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
r->read_event_handler = ngx_http_block_reading;
return NGX_OK;
} }
static ngx_int_t static ngx_int_t
ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b) ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b)
{ {
size_t size; size_t size;
ngx_int_t rc; ngx_int_t rc;
ngx_http_request_body_t *rb; ngx_http_request_body_t *rb;
ngx_http_core_srv_conf_t *cscf;
if (r->headers_in.chunked) { if (r->headers_in.chunked) {
@@ -768,7 +831,10 @@ ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b)
/* set amount of data we want to see next time */ /* set amount of data we want to see next time */
r->headers_in.content_length_n = rb->chunked->length; cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
r->headers_in.content_length_n = ngx_max(rb->chunked->length,
(off_t) cscf->large_client_header_buffers.size);
break; break;
} }
@@ -936,6 +1002,7 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
ngx_chain_t *cl, *out, *tl, **ll; ngx_chain_t *cl, *out, *tl, **ll;
ngx_http_request_body_t *rb; ngx_http_request_body_t *rb;
ngx_http_core_loc_conf_t *clcf; ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
rb = r->request_body; rb = r->request_body;
@@ -949,8 +1016,10 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
return NGX_HTTP_INTERNAL_SERVER_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
} }
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
r->headers_in.content_length_n = 0; r->headers_in.content_length_n = 0;
rb->rest = 3; rb->rest = cscf->large_client_header_buffers.size;
} }
out = NULL; out = NULL;
@@ -958,6 +1027,8 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
for (cl = in; cl; cl = cl->next) { for (cl = in; cl; cl = cl->next) {
b = NULL;
for ( ;; ) { for ( ;; ) {
ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0, ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
@@ -992,6 +1063,29 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
} }
if (b
&& rb->chunked->size <= 128
&& cl->buf->last - cl->buf->pos >= rb->chunked->size)
{
r->headers_in.content_length_n += rb->chunked->size;
if (rb->chunked->size < 8) {
while (rb->chunked->size) {
*b->last++ = *cl->buf->pos++;
rb->chunked->size--;
}
} else {
ngx_memmove(b->last, cl->buf->pos, rb->chunked->size);
b->last += rb->chunked->size;
cl->buf->pos += rb->chunked->size;
rb->chunked->size = 0;
}
continue;
}
tl = ngx_chain_get_free_buf(r->pool, &rb->free); tl = ngx_chain_get_free_buf(r->pool, &rb->free);
if (tl == NULL) { if (tl == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -1057,7 +1151,10 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
/* set rb->rest, amount of data we want to see next time */ /* set rb->rest, amount of data we want to see next time */
rb->rest = rb->chunked->length; cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
rb->rest = ngx_max(rb->chunked->length,
(off_t) cscf->large_client_header_buffers.size);
break; break;
} }
+1
View File
@@ -33,6 +33,7 @@ static u_char ngx_http_error_build_tail[] =
static u_char ngx_http_error_tail[] = static u_char ngx_http_error_tail[] =
"<hr><center>" NGINX_SERVER "</center>" CRLF
"</body>" CRLF "</body>" CRLF
"</html>" CRLF "</html>" CRLF
; ;
+19 -7
View File
@@ -77,9 +77,6 @@ static void
static void static void
ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r, ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
ngx_uint_t do_write); ngx_uint_t do_write);
static ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data);
static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data,
ssize_t bytes);
#if (NGX_THREADS) #if (NGX_THREADS)
static ngx_int_t ngx_http_upstream_thread_handler(ngx_thread_task_t *task, static ngx_int_t ngx_http_upstream_thread_handler(ngx_thread_task_t *task,
ngx_file_t *file); ngx_file_t *file);
@@ -1919,6 +1916,7 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
u->keepalive = 0; u->keepalive = 0;
u->upgrade = 0; u->upgrade = 0;
u->error = 0;
ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t)); ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
u->headers_in.content_length_n = -1; u->headers_in.content_length_n = -1;
@@ -2475,7 +2473,7 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
#if (NGX_HTTP_CACHE) #if (NGX_HTTP_CACHE)
if (u->cache_status == NGX_HTTP_CACHE_EXPIRED if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
&& ((u->conf->cache_use_stale & un->mask) || r->cache->stale_error)) && (u->conf->cache_use_stale & un->mask))
{ {
ngx_int_t rc; ngx_int_t rc;
@@ -2502,6 +2500,8 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
} }
#endif #endif
break;
} }
#if (NGX_HTTP_CACHE) #if (NGX_HTTP_CACHE)
@@ -3625,7 +3625,7 @@ ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
return; return;
} }
if (upstream->read->error) { if (upstream->read->error || u->error) {
ngx_http_upstream_finalize_request(r, u, ngx_http_upstream_finalize_request(r, u,
NGX_HTTP_BAD_GATEWAY); NGX_HTTP_BAD_GATEWAY);
return; return;
@@ -3703,14 +3703,14 @@ ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
} }
static ngx_int_t ngx_int_t
ngx_http_upstream_non_buffered_filter_init(void *data) ngx_http_upstream_non_buffered_filter_init(void *data)
{ {
return NGX_OK; return NGX_OK;
} }
static ngx_int_t ngx_int_t
ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes) ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
{ {
ngx_http_request_t *r = data; ngx_http_request_t *r = data;
@@ -3746,6 +3746,18 @@ ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
return NGX_OK; return NGX_OK;
} }
if (bytes > u->length) {
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
"upstream sent more data than specified in "
"\"Content-Length\" header");
cl->buf->last = cl->buf->pos + u->length;
u->length = 0;
return NGX_OK;
}
u->length -= bytes; u->length -= bytes;
return NGX_OK; return NGX_OK;
+3
View File
@@ -391,6 +391,7 @@ struct ngx_http_upstream_s {
unsigned buffering:1; unsigned buffering:1;
unsigned keepalive:1; unsigned keepalive:1;
unsigned upgrade:1; unsigned upgrade:1;
unsigned error:1;
unsigned request_sent:1; unsigned request_sent:1;
unsigned request_body_sent:1; unsigned request_body_sent:1;
@@ -414,6 +415,8 @@ typedef struct {
ngx_int_t ngx_http_upstream_create(ngx_http_request_t *r); ngx_int_t ngx_http_upstream_create(ngx_http_request_t *r);
void ngx_http_upstream_init(ngx_http_request_t *r); void ngx_http_upstream_init(ngx_http_request_t *r);
ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data);
ngx_int_t ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes);
ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf,
ngx_url_t *u, ngx_uint_t flags); ngx_url_t *u, ngx_uint_t flags);
char *ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, char *ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+1 -1
View File
@@ -1075,7 +1075,7 @@ ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v,
len = name->len - (sizeof("arg_") - 1); len = name->len - (sizeof("arg_") - 1);
arg = name->data + sizeof("arg_") - 1; arg = name->data + sizeof("arg_") - 1;
if (ngx_http_arg(r, arg, len, &value) != NGX_OK) { if (len == 0 || ngx_http_arg(r, arg, len, &value) != NGX_OK) {
v->not_found = 1; v->not_found = 1;
return NGX_OK; return NGX_OK;
} }
+134 -18
View File
@@ -60,6 +60,8 @@ typedef struct {
static void ngx_http_v2_read_handler(ngx_event_t *rev); static void ngx_http_v2_read_handler(ngx_event_t *rev);
static void ngx_http_v2_write_handler(ngx_event_t *wev); static void ngx_http_v2_write_handler(ngx_event_t *wev);
static void ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c); static void ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c);
static void ngx_http_v2_lingering_close(ngx_http_v2_connection_t *h2c);
static void ngx_http_v2_lingering_close_handler(ngx_event_t *rev);
static u_char *ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, static u_char *ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c,
u_char *pos, u_char *end); u_char *pos, u_char *end);
@@ -475,6 +477,7 @@ ngx_http_v2_write_handler(ngx_event_t *wev)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http2 write event timed out"); "http2 write event timed out");
c->error = 1; c->error = 1;
c->timedout = 1;
ngx_http_v2_finalize_connection(h2c, 0); ngx_http_v2_finalize_connection(h2c, 0);
return; return;
} }
@@ -663,7 +666,7 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c)
} }
if (h2c->goaway) { if (h2c->goaway) {
ngx_http_close_connection(c); ngx_http_v2_lingering_close(h2c);
return; return;
} }
@@ -701,6 +704,113 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c)
} }
static void
ngx_http_v2_lingering_close(ngx_http_v2_connection_t *h2c)
{
ngx_event_t *rev, *wev;
ngx_connection_t *c;
ngx_http_core_loc_conf_t *clcf;
c = h2c->connection;
clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx,
ngx_http_core_module);
if (clcf->lingering_close == NGX_HTTP_LINGERING_OFF) {
ngx_http_close_connection(c);
return;
}
rev = c->read;
rev->handler = ngx_http_v2_lingering_close_handler;
h2c->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
ngx_add_timer(rev, clcf->lingering_timeout);
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_connection(c);
return;
}
wev = c->write;
wev->handler = ngx_http_empty_handler;
if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
ngx_http_close_connection(c);
return;
}
}
if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
ngx_connection_error(c, ngx_socket_errno,
ngx_shutdown_socket_n " failed");
ngx_http_close_connection(c);
return;
}
if (rev->ready) {
ngx_http_v2_lingering_close_handler(rev);
}
}
static void
ngx_http_v2_lingering_close_handler(ngx_event_t *rev)
{
ssize_t n;
ngx_msec_t timer;
ngx_connection_t *c;
ngx_http_core_loc_conf_t *clcf;
ngx_http_v2_connection_t *h2c;
u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
c = rev->data;
h2c = c->data;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http2 lingering close handler");
if (rev->timedout) {
ngx_http_close_connection(c);
return;
}
timer = (ngx_msec_t) h2c->lingering_time - (ngx_msec_t) ngx_time();
if ((ngx_msec_int_t) timer <= 0) {
ngx_http_close_connection(c);
return;
}
do {
n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %z", n);
if (n == NGX_ERROR || n == 0) {
ngx_http_close_connection(c);
return;
}
} while (rev->ready);
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_connection(c);
return;
}
clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx,
ngx_http_core_module);
timer *= 1000;
if (timer > clcf->lingering_timeout) {
timer = clcf->lingering_timeout;
}
ngx_add_timer(rev, timer);
}
static u_char * static u_char *
ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, u_char *pos, ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, u_char *pos,
u_char *end) u_char *end)
@@ -733,9 +843,8 @@ ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, u_char *pos,
} }
if (ngx_memcmp(pos, preface, sizeof(preface) - 1) != 0) { if (ngx_memcmp(pos, preface, sizeof(preface) - 1) != 0) {
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
"invalid http2 connection preface \"%*s\"", "invalid connection preface");
sizeof(preface) - 1, pos);
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
} }
@@ -756,9 +865,8 @@ ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, u_char *pos,
} }
if (ngx_memcmp(pos, preface, sizeof(preface) - 1) != 0) { if (ngx_memcmp(pos, preface, sizeof(preface) - 1) != 0) {
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
"invalid http2 connection preface \"%*s\"", "invalid connection preface");
sizeof(preface) - 1, pos);
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
} }
@@ -1721,8 +1829,13 @@ ngx_http_v2_state_header_complete(ngx_http_v2_connection_t *h2c, u_char *pos,
ngx_http_v2_stream_t *stream; ngx_http_v2_stream_t *stream;
if (h2c->state.length) { if (h2c->state.length) {
h2c->state.handler = ngx_http_v2_state_header_block; if (end - pos > 0) {
return pos; h2c->state.handler = ngx_http_v2_state_header_block;
return pos;
}
return ngx_http_v2_state_headers_save(h2c, pos, end,
ngx_http_v2_state_header_block);
} }
if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG)) { if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG)) {
@@ -2476,10 +2589,6 @@ ngx_http_v2_connection_error(ngx_http_v2_connection_t *h2c,
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
"http2 state connection error"); "http2 state connection error");
if (err == NGX_HTTP_V2_INTERNAL_ERROR) {
ngx_debug_point();
}
ngx_http_v2_finalize_connection(h2c, err); ngx_http_v2_finalize_connection(h2c, err);
return NULL; return NULL;
@@ -4552,16 +4661,15 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c,
h2c->blocked = 1; h2c->blocked = 1;
if (!c->error && !h2c->goaway) { if (!c->error && !h2c->goaway) {
h2c->goaway = 1;
if (ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) { if (ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) {
(void) ngx_http_v2_send_output_queue(h2c); (void) ngx_http_v2_send_output_queue(h2c);
} }
} }
c->error = 1;
if (!h2c->processing && !h2c->pushing) { if (!h2c->processing && !h2c->pushing) {
ngx_http_close_connection(c); goto done;
return;
} }
c->read->handler = ngx_http_empty_handler; c->read->handler = ngx_http_empty_handler;
@@ -4609,10 +4717,18 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c,
h2c->blocked = 0; h2c->blocked = 0;
if (h2c->processing || h2c->pushing) { if (h2c->processing || h2c->pushing) {
c->error = 1;
return; return;
} }
ngx_http_close_connection(c); done:
if (c->error) {
ngx_http_close_connection(c);
return;
}
ngx_http_v2_lingering_close(h2c);
} }
+2
View File
@@ -207,6 +207,8 @@ struct ngx_http_v2_connection_s {
ngx_uint_t last_sid; ngx_uint_t last_sid;
ngx_uint_t last_push; ngx_uint_t last_push;
time_t lingering_time;
unsigned closed_nodes:8; unsigned closed_nodes:8;
unsigned settings_ack:1; unsigned settings_ack:1;
unsigned table_update:1; unsigned table_update:1;
+45
View File
@@ -875,9 +875,28 @@ ngx_fs_bsize(u_char *name)
return 512; return 512;
} }
#if (NGX_LINUX)
if ((size_t) fs.f_bsize > ngx_pagesize) {
return 512;
}
#endif
return (size_t) fs.f_bsize; return (size_t) fs.f_bsize;
} }
off_t
ngx_fs_available(u_char *name)
{
struct statfs fs;
if (statfs((char *) name, &fs) == -1) {
return NGX_MAX_OFF_T_VALUE;
}
return (off_t) fs.f_bavail * fs.f_bsize;
}
#elif (NGX_HAVE_STATVFS) #elif (NGX_HAVE_STATVFS)
size_t size_t
@@ -893,9 +912,28 @@ ngx_fs_bsize(u_char *name)
return 512; return 512;
} }
#if (NGX_LINUX)
if ((size_t) fs.f_frsize > ngx_pagesize) {
return 512;
}
#endif
return (size_t) fs.f_frsize; return (size_t) fs.f_frsize;
} }
off_t
ngx_fs_available(u_char *name)
{
struct statvfs fs;
if (statvfs((char *) name, &fs) == -1) {
return NGX_MAX_OFF_T_VALUE;
}
return (off_t) fs.f_bavail * fs.f_frsize;
}
#else #else
size_t size_t
@@ -904,4 +942,11 @@ ngx_fs_bsize(u_char *name)
return 512; return 512;
} }
off_t
ngx_fs_available(u_char *name)
{
return NGX_MAX_OFF_T_VALUE;
}
#endif #endif
+5 -1
View File
@@ -185,7 +185,10 @@ ngx_int_t ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s);
#define ngx_is_exec(sb) (((sb)->st_mode & S_IXUSR) == S_IXUSR) #define ngx_is_exec(sb) (((sb)->st_mode & S_IXUSR) == S_IXUSR)
#define ngx_file_access(sb) ((sb)->st_mode & 0777) #define ngx_file_access(sb) ((sb)->st_mode & 0777)
#define ngx_file_size(sb) (sb)->st_size #define ngx_file_size(sb) (sb)->st_size
#define ngx_file_fs_size(sb) ngx_max((sb)->st_size, (sb)->st_blocks * 512) #define ngx_file_fs_size(sb) \
(((sb)->st_blocks * 512 > (sb)->st_size \
&& (sb)->st_blocks * 512 < (sb)->st_size + 8 * (sb)->st_blksize) \
? (sb)->st_blocks * 512 : (sb)->st_size)
#define ngx_file_mtime(sb) (sb)->st_mtime #define ngx_file_mtime(sb) (sb)->st_mtime
#define ngx_file_uniq(sb) (sb)->st_ino #define ngx_file_uniq(sb) (sb)->st_ino
@@ -346,6 +349,7 @@ ngx_int_t ngx_directio_off(ngx_fd_t fd);
#endif #endif
size_t ngx_fs_bsize(u_char *name); size_t ngx_fs_bsize(u_char *name);
off_t ngx_fs_available(u_char *name);
#if (NGX_HAVE_OPENAT) #if (NGX_HAVE_OPENAT)
+2 -12
View File
@@ -77,12 +77,11 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
u_char *p; u_char *p;
size_t size; size_t size;
ngx_int_t i; ngx_int_t i;
ngx_uint_t n, sigio; ngx_uint_t sigio;
sigset_t set; sigset_t set;
struct itimerval itv; struct itimerval itv;
ngx_uint_t live; ngx_uint_t live;
ngx_msec_t delay; ngx_msec_t delay;
ngx_listening_t *ls;
ngx_core_conf_t *ccf; ngx_core_conf_t *ccf;
sigemptyset(&set); sigemptyset(&set);
@@ -204,16 +203,7 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
if (ngx_quit) { if (ngx_quit) {
ngx_signal_worker_processes(cycle, ngx_signal_worker_processes(cycle,
ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
ngx_close_listening_sockets(cycle);
ls = cycle->listening.elts;
for (n = 0; n < cycle->listening.nelts; n++) {
if (ngx_close_socket(ls[n].fd) == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
ngx_close_socket_n " %V failed",
&ls[n].addr_text);
}
}
cycle->listening.nelts = 0;
continue; continue;
} }
+7
View File
@@ -189,6 +189,13 @@ ngx_udp_output_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *in, ngx_log_t *log)
return cl; return cl;
} }
/* zero-sized datagram; pretend to have at least 1 iov */
if (n == 0) {
iov = &vec->iovs[n++];
iov->iov_base = NULL;
iov->iov_len = 0;
}
vec->count = n; vec->count = n;
vec->size = total; vec->size = total;
+13
View File
@@ -658,6 +658,19 @@ ngx_fs_bsize(u_char *name)
} }
off_t
ngx_fs_available(u_char *name)
{
ULARGE_INTEGER navail;
if (GetDiskFreeSpaceEx((const char *) name, &navail, NULL, NULL) == 0) {
return NGX_MAX_OFF_T_VALUE;
}
return (off_t) navail.QuadPart;
}
static ngx_int_t static ngx_int_t
ngx_win32_check_filename(u_char *name, u_short *u, size_t len) ngx_win32_check_filename(u_char *name, u_short *u, size_t len)
{ {
+1
View File
@@ -259,6 +259,7 @@ ngx_int_t ngx_directio_off(ngx_fd_t fd);
#define ngx_directio_off_n "ngx_directio_off_n" #define ngx_directio_off_n "ngx_directio_off_n"
size_t ngx_fs_bsize(u_char *name); size_t ngx_fs_bsize(u_char *name);
off_t ngx_fs_available(u_char *name);
#define ngx_stdout GetStdHandle(STD_OUTPUT_HANDLE) #define ngx_stdout GetStdHandle(STD_OUTPUT_HANDLE)
+2 -1
View File
@@ -839,7 +839,7 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
u->upstream_buf.last = p; u->upstream_buf.last = p;
} }
if (c->buffer && c->buffer->pos < c->buffer->last) { if (c->buffer && c->buffer->pos <= c->buffer->last) {
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
"stream proxy add preread buffer: %uz", "stream proxy add preread buffer: %uz",
c->buffer->last - c->buffer->pos); c->buffer->last - c->buffer->pos);
@@ -853,6 +853,7 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
*cl->buf = *c->buffer; *cl->buf = *c->buffer;
cl->buf->tag = (ngx_buf_tag_t) &ngx_stream_proxy_module; cl->buf->tag = (ngx_buf_tag_t) &ngx_stream_proxy_module;
cl->buf->temporary = (cl->buf->pos == cl->buf->last) ? 0 : 1;
cl->buf->flush = 1; cl->buf->flush = 1;
cl->next = u->upstream_out; cl->next = u->upstream_out;
+2 -1
View File
@@ -234,7 +234,8 @@ ngx_stream_write_filter(ngx_stream_session_t *s, ngx_chain_t *in,
if (size == 0 if (size == 0
&& !(c->buffered & NGX_LOWLEVEL_BUFFERED) && !(c->buffered & NGX_LOWLEVEL_BUFFERED)
&& !(last && c->need_last_buf)) && !(last && c->need_last_buf)
&& !(c->type == SOCK_DGRAM && flush))
{ {
if (last || flush || sync) { if (last || flush || sync) {
for (cl = *out; cl; /* void */) { for (cl = *out; cl; /* void */) {