Compare commits

196 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
Hakase 1a084f42db Version bump - v1.17.8 2019-12-25 00:35:32 +09:00
Hakase 1d1103eacb Release - v1.17.7 2019-12-25 00:35:18 +09:00
Hakase b013300457 Latest update - 7600 2019-12-06 22:48:23 +09:00
Hakase f898acf52b Version bump - v1.17.7 2019-11-23 11:46:15 +09:00
Hakase 2fc052617a Release - v1.17.6 2019-11-23 11:45:56 +09:00
Hakase d9ff2e8286 Latest update - 7596 2019-11-23 11:45:34 +09:00
Hakase f65d4faa78 Latest update - 7592 2019-11-07 22:28:33 +09:00
Hakase d12bc8b656 Latest update - 7591 2019-10-24 21:00:01 +09:00
Hakase 7451bdd624 Version bump - v1.17.6 2019-10-24 20:59:42 +09:00
Hakase 38c401869f Release - v1.17.5 2019-10-24 20:59:16 +09:00
Hakase 8be97f4f6c Latest update - 7586 2019-10-24 20:58:54 +09:00
Hakase 50320dd197 Submodule update. 2019-10-17 23:56:38 +09:00
Hakase a6a35de341 Latest update - 7584 2019-10-17 23:53:16 +09:00
Hakase deb38ff87c Latest update - 7580 2019-10-16 08:53:14 +09:00
Hakase 8b760dce84 Latest update - 7579 2019-10-09 22:16:35 +09:00
Hakase 97092a7563 Latest update - 7576 2019-10-05 18:15:43 +09:00
Hakase f6e254ee01 Submodule update. 2019-09-25 02:30:37 +09:00
Hakase f5c2a2fc32 Version bump - v1.17.5 2019-09-25 02:29:56 +09:00
Hakase 9c64adbaf0 Release - v1.17.4 2019-09-25 02:29:30 +09:00
Hakase f730927e80 Latest update - 7572 2019-09-25 02:28:42 +09:00
Hakase 51eeb183ba Submodule update. 2019-09-21 00:46:28 +09:00
Hakase 10d3e51b9a Latest update - 7569 2019-09-20 03:48:06 +09:00
Hakase a3411665e2 Latest update - 7567 2019-09-18 01:03:41 +09:00
Hakase c0b58bbcf6 Latest update - 7566 2019-09-16 13:39:01 +09:00
Hakase d808b37656 Latest update - 7563 2019-09-06 08:41:03 +09:00
Hakase 03397594eb Latest update - 7561 2019-08-20 23:48:53 +09:00
Hakase 4306e53ad8 Latest update - 7560 2019-08-19 20:42:36 +09:00
Hakase b68cbb3eb3 Version bump - v1.17.4 2019-08-14 16:00:58 +09:00
Hakase ce26759c9c Release - v1.17.3 2019-08-14 16:00:33 +09:00
Hakase 21524b58bf Latest update - 7549 2019-08-14 15:59:44 +09:00
Hakase f56ad45457 Submodule update. 2019-08-04 17:41:12 +09:00
Hakase cbaaa317da Latest update - 7546 2019-08-02 17:47:18 +09:00
Hakase ae67e2622d Version bump - v1.17.3 2019-07-29 17:48:03 +09:00
Hakase 47cdb7029d Release - v1.17.2 2019-07-29 17:47:46 +09:00
Hakase f3f38a56ad Latest update - 7541 2019-07-20 18:06:33 +09:00
Hakase 28f62b6672 Latest update - 7540 2019-07-19 08:47:57 +09:00
Hakase a17d307d9b Submodule update. 2019-07-13 19:16:05 +09:00
Hakase 0cc7a3aba8 Latest update - 7534 2019-07-13 19:14:22 +09:00
Hakase bd600385ec Latest update - 7522 2019-07-11 00:56:38 +09:00
Hakase 04b26acf63 Version bump - 1.17.2 2019-06-26 00:45:13 +09:00
Hakase 822cd094bd Release 1.17.1 2019-06-26 00:44:54 +09:00
Hakase d15a32b24b Latest update - 7517 2019-06-26 00:44:34 +09:00
Hakase d853e3765b Latest update - 7516 2019-06-19 01:03:38 +09:00
Hakase b8b58c0e47 Latest update - 7515 2019-06-07 00:36:43 +09:00
Hakase 3e1e852389 Latest update - 7514 2019-06-04 19:54:29 +09:00
Hakase 3f31c9270d Latest update - 7513 2019-05-28 09:37:27 +09:00
Hakase 75dc02a1ae Version bump. - v1.17.1 2019-05-23 12:05:00 +09:00
Hakase c45b1861fb Submodule update. 2019-05-23 12:04:34 +09:00
Hakase a89def5d34 v1.17.0 2019-05-23 11:59:23 +09:00
Hakase b820457c51 Latest update - 7509 2019-05-17 02:54:19 +09:00
Hakase 83915a055e Latest update - 7508 2019-05-14 08:44:24 +09:00
Hakase b0003469d0 Submodule update. 2019-05-06 22:40:28 +09:00
Hakase 8941c16aa8 Change my domain. (hakase.io -> haka.se) 2019-05-02 20:57:25 +09:00
Hakase b5f41941cd Submodule update. 2019-04-26 08:42:28 +09:00
Hakase dd71767aff Latest update - 7505 2019-04-25 08:30:35 +09:00
Hakase 7564cabbbe Latest update - 7502 2019-04-24 22:21:21 +09:00
Hakase b714ce2c1c Version bump - v1.17.0 2019-04-24 22:20:48 +09:00
Hakase 206291a0bc Remove Curve (P-224, P-521) 2019-04-18 02:01:45 +09:00
Hakase 6cad2f3152 Version bump. 2019-04-17 08:39:21 +09:00
Hakase 4f95925cbc v1.15.12 2019-04-17 08:38:58 +09:00
Hakase b43386eff3 Latest update - 7495 2019-04-17 08:38:01 +09:00
Hakase 07e8892bce Latest update - 7494 2019-04-16 08:33:31 +09:00
Hakase 8a6aaf4b1d Fix typo - README.md 2019-04-14 05:37:30 +09:00
Hakase a14915add0 Fix typo. 2019-04-13 23:28:43 +09:00
Hakase a6bbd91dc4 Update submodules. 2019-04-13 23:27:01 +09:00
Hakase 26f4a88722 Update README 2019-04-13 23:25:06 +09:00
Hakase 0118903869 Changes in session time between TLS 1.3 and TLS 1.3 when using sessions, Disabling TLSv1.1 and TLSv1 2019-04-13 23:15:49 +09:00
Hakase 08dd8bbd68 Using MD5 and SHA1 built into OpenSSL. 2019-04-13 23:14:39 +09:00
Hakase 9c3ca70c28 Submodule update. 2019-04-09 23:15:47 +09:00
Hakase 15c0714e5a Version bump - v1.15.12 2019-04-09 23:15:06 +09:00
Hakase 57d64faf44 Release - v1.15.11 2019-04-09 23:14:22 +09:00
Hakase 8002bb166a Latest update - 7489 2019-04-05 08:46:50 +09:00
Hakase 12e748d160 Latest update - 7485 2019-04-04 23:03:17 +09:00
Hakase a592b83f05 Patch Strict-SNI 2019-04-03 20:46:05 +09:00
Hakase a791b0e99f Submodule update 2019-04-01 00:22:29 +09:00
Hakase bc1b82762d Update auto.sh 2019-04-01 00:17:08 +09:00
Hakase 7ecd537b1d Latest update - 7484 2019-03-27 09:38:57 +09:00
Hakase 171db61c23 Version bump. (v1.15.11) 2019-03-27 09:38:37 +09:00
Hakase 5fb9a0ac35 v1.15.10 2019-03-27 09:38:00 +09:00
Hakase da6806135a Latest update - 7480 2019-03-22 02:34:20 +09:00
Hakase 41f4b4b46d Submodule update 2019-03-16 01:23:35 +09:00
Hakase d4d98562a7 Latest update - 7477 2019-03-10 01:03:46 +09:00
Hakase b631260840 Update OpenSSL 2019-03-07 13:16:38 +09:00
Hakase dc52afc352 Submodule update 2019-03-06 08:45:31 +09:00
Hakase bf9c73acd9 Latest update - 7475 2019-03-06 08:44:16 +09:00
Hakase 1f56da06da Latest update - 7474 2019-03-04 03:38:48 +09:00
Hakase 2a9244ed12 Version bump. (v1.15.10) 2019-02-27 01:01:54 +09:00
Hakase 31afec620a Latest update - 7469 2019-02-27 01:01:12 +09:00
Hakase f381133186 Submodule update. 2019-02-26 16:41:54 +09:00
Hakase f6264bdb9e Latest update - 7466 2019-02-26 16:40:49 +09:00
Hakase efe1334ec8 Submodule update. 2019-02-22 12:55:14 +09:00
Hakase 7dd8869f15 Latest update - 7457 2019-02-22 12:44:38 +09:00
Hakase 90bc6bc527 Submodule update. 2019-02-12 03:54:09 +09:00
Hakase efa1e6768b Latest update - 7455 2019-02-09 23:07:21 +09:00
Hakase eb86129c61 Remove TLSv1.3 draft. 2019-02-09 20:37:24 +09:00
Hakase 29efc8627a Submodule update. 2019-02-09 20:37:09 +09:00
Hakase f924949dff Latest update - 7454 2019-02-01 08:41:13 +09:00
Hakase 4742b11713 Update submodule. 2019-01-30 02:31:25 +09:00
Hakase 1c72e66e95 Latest update - 7449 2019-01-29 16:22:31 +09:00
Hakase 8872fe80fa Latest update - 7446 2019-01-25 08:46:06 +09:00
Hakase f6cd26bb56 Submodule update 2019-01-18 00:57:24 +09:00
Hakase 81c695ae98 Latest update - 7441 2019-01-18 00:48:17 +09:00
Hakase 3beb8dc136 Update SSL Ciphers. 2019-01-17 10:21:31 +09:00
Hakase 0c8665df5a Changed submodule. (rtmp -> flv) 2019-01-15 09:29:52 +09:00
Hakase 1a812507f9 Fix typo. 2018-12-30 23:48:46 +09:00
Hakase 3ceaf578bd Temp Patch - Ubuntu/Debian build error 2018-12-30 23:43:51 +09:00
Hakase 23f25f774c Fix typo and README. 2018-12-30 23:42:11 +09:00
Hakase 9b3afe542c Submodule (vts) : Remove default enabled 2018-12-29 19:09:29 +09:00
Hakase 8ed0f75139 Update README.md 2018-12-26 23:07:07 +09:00
Hakase 89d374edcb Submodule update. 2018-12-26 08:59:59 +09:00
Hakase 891002d554 Latest update - 7437, Version bump 2018-12-26 08:47:53 +09:00
Hakase 394a004754 Latest update - 7431 2018-12-19 13:33:37 +09:00
Hakase b4248b3bc5 Latest update - 7430 2018-12-15 16:16:16 +09:00
Hakase e68a8ff05c Latest update - 7429 2018-12-14 17:50:47 +09:00
Hakase 94ae145265 Latest update - 7428 2018-12-13 08:36:46 +09:00
Hakase 66dd4ce3fb Submodule update. 2018-12-12 13:02:09 +09:00
Hakase 7ebc14b89c Latest update - 7427 2018-12-12 12:53:04 +09:00
Hakase a8295ca677 Update README and Submodules. 2018-12-06 23:54:24 +09:00
Hakase 6b63c62783 Minor modifications... 2018-12-06 23:53:07 +09:00
Hakase 14f097c6c2 Fixed windows build error 2018-11-28 21:25:00 +09:00
Hakase cf3204b7bb Submodule update 2018-11-28 00:35:23 +09:00
Hakase 93752a3fe0 Latest update - 7404, Version bump 2018-11-28 00:29:41 +09:00
Hakase 44f2125a4c Latest update - 7400 2018-11-22 10:14:23 +09:00
Hakase 6ee0f3383d Latest update - 7395 2018-11-16 12:53:33 +09:00
Hakase 70af837207 Update submodules. 2018-11-15 23:58:28 +09:00
Hakase 4a8dcfa071 Latest update - 7394 2018-11-15 23:57:50 +09:00
Hakase 8e7d26e094 Update submodule. 2018-11-14 11:45:25 +09:00
Hakase 9eb95c7f35 Latest update - 7393 2018-11-14 10:59:43 +09:00
Hakase 7781c82339 Update OpenSSL 2018-11-11 15:46:12 +09:00
Hakase 4d416e515c Fix build error. 2018-11-07 14:03:59 +09:00
Hakase c4b1183a2f Update submodules. 2018-11-07 08:50:24 +09:00
Hakase f87f0d9ecf Latest update - 7389 2018-11-07 08:49:31 +09:00
Hakase d7177b1453 Update submodules 2018-11-01 01:00:40 +09:00
Hakase 7e2db81bb5 Latest update - 7375 2018-11-01 00:52:52 +09:00
Hakase ef4b50eeec Latest update - 7373 2018-10-24 08:32:43 +09:00
Hakase fc69bd8b3d Update submodules. 2018-10-17 15:16:38 +09:00
165 changed files with 8621 additions and 2269 deletions
+9 -7
View File
@@ -7,12 +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/nginx-rtmp-module"]
path = lib/nginx-rtmp-module
url = https://github.com/arut/nginx-rtmp-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
@@ -29,7 +23,15 @@
path = lib/zlib path = lib/zlib
url = https://github.com/cloudflare/zlib.git url = https://github.com/cloudflare/zlib.git
branch = gcc.amd64 branch = gcc.amd64
[submodule "lib/ngx_http_geoip2_module"] [submodule "lib/ngx_http_geoip2_module"]
path = lib/ngx_http_geoip2_module path = lib/ngx_http_geoip2_module
url = https://github.com/leev/ngx_http_geoip2_module.git url = https://github.com/leev/ngx_http_geoip2_module.git
[submodule "lib/nginx-module-vts"]
path = lib/nginx-module-vts
url = https://github.com/vozlt/nginx-module-vts
[submodule "lib/nginx-http-flv-module"]
path = lib/nginx-http-flv-module
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
+21
View File
@@ -431,3 +431,24 @@ b234199c7ed8a156a6bb98f7ff58302c857c954f release-1.15.2
28b3e17ca7eba1e6a0891afde0e4bc5bcc99c861 release-1.15.3 28b3e17ca7eba1e6a0891afde0e4bc5bcc99c861 release-1.15.3
49d49835653857daa418e68d6cbfed4958c78fca release-1.15.4 49d49835653857daa418e68d6cbfed4958c78fca release-1.15.4
f062e43d74fc2578bb100a9e82a953efa1eb9e4e release-1.15.5 f062e43d74fc2578bb100a9e82a953efa1eb9e4e release-1.15.5
2351853ce6867b6166823bdf94333c0a76633c0a release-1.15.6
051a039ce1c7e09144de4a4846669ec7116cecea release-1.15.7
ee551e3f6dba336c0d875e266d7d55385f379b42 release-1.15.8
d2fd76709909767fc727a5b4affcf1dc9ca488a7 release-1.15.9
75f5c7f628411c79c7044102049f7ab4f7a246e7 release-1.15.10
5155d0296a5ef9841f035920527ffdb771076b44 release-1.15.11
0130ca3d58437b3c7c707cdddd813d530c68da9a release-1.15.12
054c1c46395caff79bb4caf16f40b331f71bb6dd release-1.17.0
7816bd7dabf6ee86c53c073b90a7143161546e06 release-1.17.1
2fc9f853a6b7cd29dc84e0af2ed3cf78e0da6ca8 release-1.17.2
ed4303aa1b31a9aad5440640c0840d9d0af45fed release-1.17.3
ce2ced3856909f36f8130c99eaa4dbdbae636ddc release-1.17.4
9af0dddbddb2c368bfedd2801bc100ffad01e19b release-1.17.5
de68d0d94320cbf033599c6f3ca37e5335c67fd7 release-1.17.6
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
+14 -7
View File
@@ -4,8 +4,8 @@
example Web Server - [https://ssl.hakase.io/](https://ssl.hakase.io/) example Web Server - [https://ssl.hakase.io/](https://ssl.hakase.io/)
## 아래의 필수 라이브러리를 설치해주세요. ## 아래의 필수 라이브러리를 설치해주세요.
- CentOS / Red Hat - `yum install jemalloc-devel libuuid-devel libatomic libatomic_ops-devel expat-devel unzip autoconf automake libtool gd-devel libmaxminddb-devel gcc-c++ curl` - CentOS / Red Hat - `yum install jemalloc-devel libuuid-devel libatomic libatomic_ops-devel expat-devel unzip autoconf automake libtool gd-devel libmaxminddb-devel libxslt-devel libxml2-devel gcc-c++ curl`
- Ubuntu / Debian - `apt install libjemalloc-dev uuid-dev libatomic1 libatomic-ops-dev expat unzip autoconf automake libtool libgd-dev libmaxminddb-dev g++ curl` - Ubuntu / Debian - `apt install libjemalloc-dev uuid-dev libatomic1 libatomic-ops-dev expat unzip autoconf automake libtool libgd-dev libmaxminddb-dev libxslt1-dev libxml2-dev g++ curl`
## 설치 방법 ## 설치 방법
1. 이 명령어를 이용하여 다운로드 합니다. - `git clone https://github.com/hakasenyang/nginx-build.git --recursive` 1. 이 명령어를 이용하여 다운로드 합니다. - `git clone https://github.com/hakasenyang/nginx-build.git --recursive`
@@ -22,13 +22,18 @@ example Web Server - [https://ssl.hakase.io/](https://ssl.hakase.io/)
## 기능 목록 ## 기능 목록
- SSL Cipher 자동 설정 - SSL Cipher 자동 설정
- **아래 내용은 자동으로 설정됩니다. 따라서, 필요하지 않는 한 해당 설정은 nginx.conf 내에서 설정하지 마십시오.** - **아래 내용은 자동으로 설정됩니다. 따라서, 필요하지 않는 한 해당 설정은 nginx.conf 내에서 설정하지 마십시오.**
- ssl_protocols : TLSv1 TLSv1.1 TLSv1.2 TLSv1.3 - ssl_protocols : TLSv1.2 TLSv1.3
- ssl_ciphers : [TLS13+AESGCM+AES128|TLS13+AESGCM+AES256|TLS13+CHACHA20]:[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
- ssl_prefer_server_ciphers : On - ssl_prefer_server_ciphers : On
- ssl_ecdh_curve : X25519:P-256:P-384:P-224:P-521 - ssl_ecdh_curve : X25519:P-256:P-384
- ssl_session_timeout : 64800 (< TLSv1.3)
- ssl_session_timeout_tls13 : 172800 (TLSv1.3 only)
- **ssl_dhparam** 는 사용하지 마십시오. 필요 없습니다. - **ssl_dhparam** 는 사용하지 마십시오. 필요 없습니다.
- TLS v1.3 (draft 23, 26, 28, **final**) - 오래된 브라우저를 지원하려면 아래 설정을 이용하십시오. (TLS 버전)
- OpenSSL-1.1.2-dev 사용. (**draft 23, 26, 28, final**) - 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
- TLS v1.3 (**final**)
- OpenSSL-3.0.0-dev 사용. (**final**)
- OpenSSL equal preference patch 사용 ([BoringSSL](https://github.com/google/boringssl) & [buik](https://gitlab.com/buik/openssl/blob/openssl-patch/openssl-1.1)) - OpenSSL equal preference patch 사용 ([BoringSSL](https://github.com/google/boringssl) & [buik](https://gitlab.com/buik/openssl/blob/openssl-patch/openssl-1.1))
- 제 OpenSSL Patch 파일은 [여기](https://github.com/hakasenyang/openssl-patch)에 있습니다. - 제 OpenSSL Patch 파일은 [여기](https://github.com/hakasenyang/openssl-patch)에 있습니다.
- AES-NI (AES 하드웨어 가속) 이 없는 환경에서는 CHACHA20 Cipher 가 우선으로 적용됩니다. (구 기기 안드로이드 등) - AES-NI (AES 하드웨어 가속) 이 없는 환경에서는 CHACHA20 Cipher 가 우선으로 적용됩니다. (구 기기 안드로이드 등)
@@ -40,6 +45,7 @@ example Web Server - [https://ssl.hakase.io/](https://ssl.hakase.io/)
- HPACK, SSL Dynamic TLS Records 지원. (Thanks to cloudflare!) - HPACK, SSL Dynamic TLS Records 지원. (Thanks to cloudflare!)
- SSL Strict-SNI (예: http { strict_sni on; } ) (Thanks to [@JemmyLoveJenny](https://github.com/hakasenyang/openssl-patch/issues/1#issuecomment-421551872)) - SSL Strict-SNI (예: http { strict_sni on; } ) (Thanks to [@JemmyLoveJenny](https://github.com/hakasenyang/openssl-patch/issues/1#issuecomment-421551872))
- Strict SNI 는 두 개 이상의 server 설정을 필요로 합니다. (server { listen 443 ssl }). - Strict SNI 는 두 개 이상의 server 설정을 필요로 합니다. (server { listen 443 ssl }).
- 만약 두 개 이상의 server 설정이 없다면, SNI 은 활성화되지 않으며 Strict SNI 도 동작하지 않습니다.
- 인증서는 중복으로 설정해도 상관 없습니다. - 인증서는 중복으로 설정해도 상관 없습니다.
- "strict_sni_header on" 을 사용하면 잘못 된 헤더에 대한 응답을 하지 않습니다. (strict_sni 와 같이 사용해야만 적용됩니다.) - "strict_sni_header on" 을 사용하면 잘못 된 헤더에 대한 응답을 하지 않습니다. (strict_sni 와 같이 사용해야만 적용됩니다.)
- GeoIP2 Module - [Issues #2](https://github.com/hakasenyang/nginx-build/issues/2) - GeoIP2 Module - [Issues #2](https://github.com/hakasenyang/nginx-build/issues/2)
@@ -47,6 +53,7 @@ example Web Server - [https://ssl.hakase.io/](https://ssl.hakase.io/)
## 차후 추가 될 기능 ## 차후 추가 될 기능
- apt, yum 설치. (rpm, deb, etc.) - apt, yum 설치. (rpm, deb, etc.)
- OCSP Stapling 사용 시 메모리 공유(shm)
- 기타. - 기타.
## 더 이상 사용하지 않는 기능 ## 더 이상 사용하지 않는 기능
+17 -8
View File
@@ -1,11 +1,13 @@
# Hakase-nginx # Hakase-nginx
**My nginx build files.** **My nginx build files.**
Example Web Server - [https://ssl.hakase.io/](https://ssl.hakase.io/) ## This repository is no longer operational. Use an alternative such as tengine.
Example Web Server - [https://ssl.haka.se/](https://ssl.haka.se/)
## Please install dependency library. ## Please install dependency library.
- CentOS / Red Hat - `yum install jemalloc-devel libuuid-devel libatomic libatomic_ops-devel expat-devel unzip autoconf automake libtool gd-devel libmaxminddb-devel gcc-c++ curl` - CentOS / Red Hat - `yum install jemalloc-devel libuuid-devel libatomic libatomic_ops-devel expat-devel unzip autoconf automake libtool gd-devel libmaxminddb-devel libxslt-devel libxml2-devel gcc-c++ curl`
- Ubuntu / Debian - `apt install libjemalloc-dev uuid-dev libatomic1 libatomic-ops-dev expat unzip autoconf automake libtool libgd-dev libmaxminddb-dev g++ curl` - Ubuntu / Debian - `apt install libjemalloc-dev uuid-dev libatomic1 libatomic-ops-dev expat unzip autoconf automake libtool libgd-dev libmaxminddb-dev libxslt1-dev libxml2-dev g++ curl`
## How to Install? ## How to Install?
1. Clone this repository - `git clone https://github.com/hakasenyang/nginx-build.git --recursive` 1. Clone this repository - `git clone https://github.com/hakasenyang/nginx-build.git --recursive`
@@ -23,13 +25,18 @@ Example Web Server - [https://ssl.hakase.io/](https://ssl.hakase.io/)
## Features ## Features
- Auto SSL Cipher settings - Auto SSL Cipher settings
- **The following information is preset. Do not set it yourself unless you need it.** - **The following information is preset. Do not set it yourself unless you need it.**
- ssl_protocols : TLSv1 TLSv1.1 TLSv1.2 TLSv1.3 - ssl_protocols : TLSv1.2 TLSv1.3
- ssl_ciphers : [TLS13+AESGCM+AES128|TLS13+AESGCM+AES256|TLS13+CHACHA20]:[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
- ssl_prefer_server_ciphers : On - ssl_prefer_server_ciphers : On
- ssl_ecdh_curve : X25519:P-256:P-384:P-224:P-521 - ssl_ecdh_curve : X25519:P-256:P-384
- ssl_session_timeout : 64800 (< TLSv1.3)
- ssl_session_timeout_tls13 : 172800 (TLSv1.3 only)
- DO NOT USE **ssl_dhparam**. Not required. - DO NOT USE **ssl_dhparam**. Not required.
- TLS v1.3 (draft 23, 26, 28, **final**) - Use the settings below to support older browsers. (TLS Protocol)
- Use OpenSSL-1.1.2-dev (**draft 23, 26, 28, final**) - 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
- TLS v1.3
- 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)
@@ -41,6 +48,7 @@ Example Web Server - [https://ssl.hakase.io/](https://ssl.hakase.io/)
- Support HPACK, SSL Dynamic TLS Records. (Thanks to cloudflare!) - Support HPACK, SSL Dynamic TLS Records. (Thanks to cloudflare!)
- SSL Strict-SNI (ex: http { strict_sni on; } ) (Thanks to [@JemmyLoveJenny](https://github.com/hakasenyang/openssl-patch/issues/1#issuecomment-421551872)) - SSL Strict-SNI (ex: http { strict_sni on; } ) (Thanks to [@JemmyLoveJenny](https://github.com/hakasenyang/openssl-patch/issues/1#issuecomment-421551872))
- Strict SNI requires at least two ssl server settings (server { listen 443 ssl }). - Strict SNI requires at least two ssl server settings (server { listen 443 ssl }).
- If you do not have two server settings, SNI will not be enabled and Strict SNI will not be enabled.
- It does not matter what kind of certificate or duplicate. - It does not matter what kind of certificate or duplicate.
- Use "strict_sni_header on" if you do not want to respond to invalid headers. (only with strict_sni) - Use "strict_sni_header on" if you do not want to respond to invalid headers. (only with strict_sni)
- GeoIP2 Module - [Issues #2](https://github.com/hakasenyang/nginx-build/issues/2) - GeoIP2 Module - [Issues #2](https://github.com/hakasenyang/nginx-build/issues/2)
@@ -48,6 +56,7 @@ Example Web Server - [https://ssl.hakase.io/](https://ssl.hakase.io/)
## Upcoming Features ## Upcoming Features
- Auto build (rpm, deb, etc.) - Auto build (rpm, deb, etc.)
- Memory sharing(**shm**) for OCSP Stapling.
- ETC. - ETC.
## Deprecated Features ## Deprecated Features
+15 -4
View File
@@ -40,7 +40,7 @@ fi
if [ "$BITCHK" = 64 ]; then if [ "$BITCHK" = 64 ]; then
if [ ! -f "lib/zlib/Makefile" ]; then if [ ! -f "lib/zlib/Makefile" ]; then
cd lib/zlib cd lib/zlib
./configure ./configure --64
cd ../.. cd ../..
fi fi
else else
@@ -88,18 +88,23 @@ else
BUILD_OPENSSL_LTO="" BUILD_OPENSSL_LTO=""
fi fi
### Temporary Ubuntu/Debian build error (libxslt/libxml2)
### URL : https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=721602
TEMP_OPT="-lm"
### Module check ### Module check
if [ "$PAGESPEED" = 1 ]; then BUILD_MODULES="--add-module=./lib/pagespeed ${PS_NGX_EXTRA_FLAGS}"; fi if [ "$PAGESPEED" = 1 ]; then BUILD_MODULES="--add-module=./lib/pagespeed ${PS_NGX_EXTRA_FLAGS}"; fi
if [ "$RTMP" = 1 ]; then BUILD_MODULES="${BUILD_MODULES} --add-module=./lib/nginx-rtmp-module"; fi if [ "$FLV" = 1 ]; then BUILD_MODULES="${BUILD_MODULES} --add-module=./lib/nginx-http-flv-module"; fi
if [ "$NAXSI" = 1 ]; then BUILD_MODULES="${BUILD_MODULES} --add-module=./lib/naxsi/naxsi_src"; fi if [ "$NAXSI" = 1 ]; then BUILD_MODULES="${BUILD_MODULES} --add-module=./lib/naxsi/naxsi_src"; fi
if [ "$DAV_EXT" = 1 ]; then BUILD_MODULES="${BUILD_MODULES} --add-module=./lib/nginx-dav-ext-module"; fi if [ "$DAV_EXT" = 1 ]; then BUILD_MODULES="${BUILD_MODULES} --add-module=./lib/nginx-dav-ext-module"; fi
if [ "$FANCYINDEX" = 1 ]; then BUILD_MODULES="${BUILD_MODULES} --add-module=./lib/ngx-fancyindex"; fi if [ "$FANCYINDEX" = 1 ]; then BUILD_MODULES="${BUILD_MODULES} --add-module=./lib/ngx-fancyindex"; fi
if [ "$GEOIP2" = 1 ]; then BUILD_MODULES="${BUILD_MODULES} --add-module=./lib/ngx_http_geoip2_module"; fi if [ "$GEOIP2" = 1 ]; then BUILD_MODULES="${BUILD_MODULES} --add-module=./lib/ngx_http_geoip2_module"; 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} -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} \
@@ -165,6 +170,12 @@ mkdir -p ${NGX_LIB}
### Check for old files ### Check for old files
if [ -f "${NGX_SBIN_PATH}.old" ]; then if [ -f "${NGX_SBIN_PATH}.old" ]; then
### Test nginx configuration.
"$NGX_SBIN_PATH" -t > /dev/null 2>&1
if test $? -ne 0; then
echo "Failed nginx configuration test."
exit 1
fi
sleep 1 sleep 1
rm ${NGX_SBIN_PATH}.old rm ${NGX_SBIN_PATH}.old
systemctl restart nginx systemctl restart nginx
+1 -1
View File
@@ -107,7 +107,7 @@ CORE_LIBS="$CORE_LIBS kernel32.lib user32.lib"
# msvc under Wine issues # msvc under Wine issues
# C1902: Program database manager mismatch; please check your installation # C1902: Program database manager mismatch; please check your installation
if [ -z "$NGX_WINE" ]; then if [ -z "$NGX_WINE" ]; then
CFLAGS="$CFLAGS -Zi" CFLAGS="$CFLAGS -Zi -Fd$NGX_OBJS/nginx.pdb"
CORE_LINK="$CORE_LINK -debug" CORE_LINK="$CORE_LINK -debug"
fi fi
+1 -1
View File
@@ -229,7 +229,7 @@ build: binary modules
binary: $NGX_OBJS${ngx_dirsep}nginx$ngx_binext binary: $NGX_OBJS${ngx_dirsep}nginx$ngx_binext
$NGX_OBJS${ngx_dirsep}nginx$ngx_binext: $ngx_deps$ngx_spacer $NGX_OBJS${ngx_dirsep}nginx$ngx_binext: $ngx_deps$ngx_spacer
\$(LINK) $ngx_long_start$ngx_binout$NGX_OBJS${ngx_dirsep}nginx$ngx_long_cont$ngx_objs$ngx_libs$ngx_link$ngx_main_link \$(LINK) $ngx_long_start$ngx_binout$NGX_OBJS${ngx_dirsep}nginx$ngx_binext$ngx_long_cont$ngx_objs$ngx_libs$ngx_link$ngx_main_link
$ngx_rcc $ngx_rcc
$ngx_long_end $ngx_long_end
+2 -17
View File
@@ -102,21 +102,6 @@ if [ $HTTP = YES ]; then
fi fi
if [ $HTTP_SSI = YES ]; then
HTTP_POSTPONE=YES
fi
if [ $HTTP_SLICE = YES ]; then
HTTP_POSTPONE=YES
fi
if [ $HTTP_ADDITION = YES ]; then
HTTP_POSTPONE=YES
fi
# the module order is important # the module order is important
# ngx_http_static_module # ngx_http_static_module
# ngx_http_gzip_static_module # ngx_http_gzip_static_module
@@ -252,13 +237,13 @@ if [ $HTTP = YES ]; then
. auto/module . auto/module
fi fi
if [ $HTTP_POSTPONE = YES ]; then if :; then
ngx_module_name=ngx_http_postpone_filter_module ngx_module_name=ngx_http_postpone_filter_module
ngx_module_incs= ngx_module_incs=
ngx_module_deps= ngx_module_deps=
ngx_module_srcs=src/http/ngx_http_postpone_filter_module.c ngx_module_srcs=src/http/ngx_http_postpone_filter_module.c
ngx_module_libs= ngx_module_libs=
ngx_module_link=$HTTP_POSTPONE ngx_module_link=YES
. auto/module . auto/module
fi fi
-1
View File
@@ -61,7 +61,6 @@ HTTP_SSL=NO
HTTP_V2=NO HTTP_V2=NO
HTTP_V2_HPACK_ENC=NO HTTP_V2_HPACK_ENC=NO
HTTP_SSI=YES HTTP_SSI=YES
HTTP_POSTPONE=NO
HTTP_REALIP=NO HTTP_REALIP=NO
HTTP_XSLT=NO HTTP_XSLT=NO
HTTP_IMAGE_FILTER=NO HTTP_IMAGE_FILTER=NO
+2 -6
View File
@@ -11,6 +11,7 @@ CORE_SRCS="$WIN32_SRCS $IOCP_SRCS"
OS_CONFIG="$WIN32_CONFIG" OS_CONFIG="$WIN32_CONFIG"
NGX_ICONS="$NGX_WIN32_ICONS" NGX_ICONS="$NGX_WIN32_ICONS"
SELECT_SRCS=$WIN32_SELECT_SRCS SELECT_SRCS=$WIN32_SELECT_SRCS
POLL_SRCS=$WIN32_POLL_SRCS
ngx_pic_opt= ngx_pic_opt=
ngx_binext=".exe" ngx_binext=".exe"
@@ -31,12 +32,7 @@ case "$NGX_CC_NAME" in
esac esac
EVENT_MODULES="$EVENT_MODULES $IOCP_MODULE" EVENT_MODULES="$EVENT_MODULES $IOCP_MODULE"
EVENT_FOUND=YES #EVENT_FOUND=YES
if [ $EVENT_SELECT = NO ]; then
CORE_SRCS="$CORE_SRCS $SELECT_SRCS"
EVENT_MODULES="$EVENT_MODULES $SELECT_MODULE"
fi
have=NGX_HAVE_INET6 . auto/have have=NGX_HAVE_INET6 . auto/have
+1 -2
View File
@@ -60,8 +60,6 @@ CORE_SRCS="src/core/nginx.c \
src/core/ngx_file.c \ src/core/ngx_file.c \
src/core/ngx_crc32.c \ src/core/ngx_crc32.c \
src/core/ngx_murmurhash.c \ src/core/ngx_murmurhash.c \
src/core/ngx_md5.c \
src/core/ngx_sha1.c \
src/core/ngx_rbtree.c \ src/core/ngx_rbtree.c \
src/core/ngx_radix_tree.c \ src/core/ngx_radix_tree.c \
src/core/ngx_slab.c \ src/core/ngx_slab.c \
@@ -106,6 +104,7 @@ WIN32_SELECT_SRCS=src/event/modules/ngx_win32_select_module.c
POLL_MODULE=ngx_poll_module POLL_MODULE=ngx_poll_module
POLL_SRCS=src/event/modules/ngx_poll_module.c POLL_SRCS=src/event/modules/ngx_poll_module.c
WIN32_POLL_SRCS=src/event/modules/ngx_win32_poll_module.c
KQUEUE_MODULE=ngx_kqueue_module KQUEUE_MODULE=ngx_kqueue_module
KQUEUE_SRCS=src/event/modules/ngx_kqueue_module.c KQUEUE_SRCS=src/event/modules/ngx_kqueue_module.c
+12
View File
@@ -943,6 +943,18 @@ ngx_feature_test="int i = FIONBIO; printf(\"%d\", i)"
. auto/feature . auto/feature
ngx_feature="ioctl(FIONREAD)"
ngx_feature_name="NGX_HAVE_FIONREAD"
ngx_feature_run=no
ngx_feature_incs="#include <sys/ioctl.h>
#include <stdio.h>
$NGX_INCLUDE_SYS_FILIO_H"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="int i = FIONREAD; printf(\"%d\", i)"
. auto/feature
ngx_feature="struct tm.tm_gmtoff" ngx_feature="struct tm.tm_gmtoff"
ngx_feature_name="NGX_HAVE_GMTOFF" ngx_feature_name="NGX_HAVE_GMTOFF"
ngx_feature_run=no ngx_feature_run=no
+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
+6 -3
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 ###
@@ -32,8 +32,8 @@ LTO=1
### PageSpeed ### PageSpeed
PAGESPEED=0 PAGESPEED=0
### nginx-rtmp-module ### nginx-http-flv-module
RTMP=0 FLV=0
### naxsi ### naxsi
NAXSI=1 NAXSI=1
@@ -47,6 +47,9 @@ FANCYINDEX=1
### GEOIP2 ### GEOIP2
GEOIP2=1 GEOIP2=1
### nginx-module-vts
VTS=0
########################## ##########################
### nginx install path ### ### nginx install path ###
########################## ##########################
+155 -15
View File
@@ -108,6 +108,7 @@ syn keyword ngxDirectiveControl contained set
syn keyword ngxDirectiveError contained error_page syn keyword ngxDirectiveError contained error_page
syn keyword ngxDirectiveError contained post_action syn keyword ngxDirectiveError contained post_action
syn keyword ngxDirectiveDeprecated contained limit_zone
syn keyword ngxDirectiveDeprecated contained proxy_downstream_buffer syn keyword ngxDirectiveDeprecated contained proxy_downstream_buffer
syn keyword ngxDirectiveDeprecated contained proxy_upstream_buffer syn keyword ngxDirectiveDeprecated contained proxy_upstream_buffer
syn keyword ngxDirectiveDeprecated contained spdy_chunk_size syn keyword ngxDirectiveDeprecated contained spdy_chunk_size
@@ -118,6 +119,7 @@ syn keyword ngxDirectiveDeprecated contained spdy_pool_size
syn keyword ngxDirectiveDeprecated contained spdy_recv_buffer_size syn keyword ngxDirectiveDeprecated contained spdy_recv_buffer_size
syn keyword ngxDirectiveDeprecated contained spdy_recv_timeout syn keyword ngxDirectiveDeprecated contained spdy_recv_timeout
syn keyword ngxDirectiveDeprecated contained spdy_streams_index_size syn keyword ngxDirectiveDeprecated contained spdy_streams_index_size
syn keyword ngxDirectiveDeprecated contained ssl
syn keyword ngxDirectiveDeprecated contained upstream_conf syn keyword ngxDirectiveDeprecated contained upstream_conf
syn keyword ngxDirective contained absolute_redirect syn keyword ngxDirective contained absolute_redirect
@@ -136,14 +138,20 @@ syn keyword ngxDirective contained alias
syn keyword ngxDirective contained allow syn keyword ngxDirective contained allow
syn keyword ngxDirective contained ancient_browser syn keyword ngxDirective contained ancient_browser
syn keyword ngxDirective contained ancient_browser_value syn keyword ngxDirective contained ancient_browser_value
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
syn keyword ngxDirective contained auth_http_timeout syn keyword ngxDirective contained auth_http_timeout
syn keyword ngxDirective contained auth_jwt syn keyword ngxDirective contained auth_jwt
syn keyword ngxDirective contained auth_jwt_claim_set
syn keyword ngxDirective contained auth_jwt_header_set
syn keyword ngxDirective contained auth_jwt_key_file syn keyword ngxDirective contained auth_jwt_key_file
syn keyword ngxDirective contained auth_jwt_key_request
syn keyword ngxDirective contained auth_jwt_leeway
syn keyword ngxDirective contained auth_request syn keyword ngxDirective contained auth_request
syn keyword ngxDirective contained auth_request_set syn keyword ngxDirective contained auth_request_set
syn keyword ngxDirective contained autoindex syn keyword ngxDirective contained autoindex
@@ -229,6 +237,7 @@ syn keyword ngxDirective contained fastcgi_read_timeout
syn keyword ngxDirective contained fastcgi_request_buffering syn keyword ngxDirective contained fastcgi_request_buffering
syn keyword ngxDirective contained fastcgi_send_lowat syn keyword ngxDirective contained fastcgi_send_lowat
syn keyword ngxDirective contained fastcgi_send_timeout syn keyword ngxDirective contained fastcgi_send_timeout
syn keyword ngxDirective contained fastcgi_socket_keepalive
syn keyword ngxDirective contained fastcgi_split_path_info syn keyword ngxDirective contained fastcgi_split_path_info
syn keyword ngxDirective contained fastcgi_store syn keyword ngxDirective contained fastcgi_store
syn keyword ngxDirective contained fastcgi_store_access syn keyword ngxDirective contained fastcgi_store_access
@@ -255,6 +264,7 @@ syn keyword ngxDirective contained grpc_pass_header
syn keyword ngxDirective contained grpc_read_timeout syn keyword ngxDirective contained grpc_read_timeout
syn keyword ngxDirective contained grpc_send_timeout syn keyword ngxDirective contained grpc_send_timeout
syn keyword ngxDirective contained grpc_set_header syn keyword ngxDirective contained grpc_set_header
syn keyword ngxDirective contained grpc_socket_keepalive
syn keyword ngxDirective contained grpc_ssl_certificate syn keyword ngxDirective contained grpc_ssl_certificate
syn keyword ngxDirective contained grpc_ssl_certificate_key syn keyword ngxDirective contained grpc_ssl_certificate_key
syn keyword ngxDirective contained grpc_ssl_ciphers syn keyword ngxDirective contained grpc_ssl_ciphers
@@ -323,25 +333,31 @@ 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_preread syn keyword ngxDirective contained js_preread
syn keyword ngxDirective contained js_set syn keyword ngxDirective contained js_set
syn keyword ngxDirective contained keepalive syn keyword ngxDirective contained keepalive
syn keyword ngxDirective contained keepalive_disable syn keyword ngxDirective contained keepalive_disable
syn keyword ngxDirective contained keepalive_requests syn keyword ngxDirective contained keepalive_requests
syn keyword ngxDirective contained keepalive_timeout syn keyword ngxDirective contained keepalive_timeout
syn keyword ngxDirective contained keyval
syn keyword ngxDirective contained keyval_zone
syn keyword ngxDirective contained kqueue_changes syn keyword ngxDirective contained kqueue_changes
syn keyword ngxDirective contained kqueue_events syn keyword ngxDirective contained kqueue_events
syn keyword ngxDirective contained large_client_header_buffers 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
syn keyword ngxDirective contained limit_rate syn keyword ngxDirective contained limit_rate
syn keyword ngxDirective contained limit_rate_after syn keyword ngxDirective contained limit_rate_after
syn keyword ngxDirective contained limit_req syn keyword ngxDirective contained limit_req
syn keyword ngxDirective contained limit_req_dry_run
syn keyword ngxDirective contained limit_req_log_level syn keyword ngxDirective contained limit_req_log_level
syn keyword ngxDirective contained limit_req_status syn keyword ngxDirective contained limit_req_status
syn keyword ngxDirective contained limit_req_zone syn keyword ngxDirective contained limit_req_zone
@@ -367,6 +383,7 @@ syn keyword ngxDirective contained memcached_next_upstream_timeout
syn keyword ngxDirective contained memcached_next_upstream_tries syn keyword ngxDirective contained memcached_next_upstream_tries
syn keyword ngxDirective contained memcached_read_timeout syn keyword ngxDirective contained memcached_read_timeout
syn keyword ngxDirective contained memcached_send_timeout syn keyword ngxDirective contained memcached_send_timeout
syn keyword ngxDirective contained memcached_socket_keepalive
syn keyword ngxDirective contained merge_slashes syn keyword ngxDirective contained merge_slashes
syn keyword ngxDirective contained min_delete_depth syn keyword ngxDirective contained min_delete_depth
syn keyword ngxDirective contained mirror syn keyword ngxDirective contained mirror
@@ -375,9 +392,9 @@ syn keyword ngxDirective contained modern_browser
syn keyword ngxDirective contained modern_browser_value syn keyword ngxDirective contained modern_browser_value
syn keyword ngxDirective contained mp4 syn keyword ngxDirective contained mp4
syn keyword ngxDirective contained mp4_buffer_size syn keyword ngxDirective contained mp4_buffer_size
syn keyword ngxDirective contained mp4_max_buffer_size
syn keyword ngxDirective contained mp4_limit_rate syn keyword ngxDirective contained mp4_limit_rate
syn keyword ngxDirective contained mp4_limit_rate_after syn keyword ngxDirective contained mp4_limit_rate_after
syn keyword ngxDirective contained mp4_max_buffer_size
syn keyword ngxDirective contained msie_padding syn keyword ngxDirective contained msie_padding
syn keyword ngxDirective contained msie_refresh syn keyword ngxDirective contained msie_refresh
syn keyword ngxDirective contained multi_accept syn keyword ngxDirective contained multi_accept
@@ -456,11 +473,14 @@ syn keyword ngxDirective contained proxy_protocol_timeout
syn keyword ngxDirective contained proxy_read_timeout syn keyword ngxDirective contained proxy_read_timeout
syn keyword ngxDirective contained proxy_redirect syn keyword ngxDirective contained proxy_redirect
syn keyword ngxDirective contained proxy_request_buffering syn keyword ngxDirective contained proxy_request_buffering
syn keyword ngxDirective contained proxy_requests
syn keyword ngxDirective contained proxy_responses syn keyword ngxDirective contained proxy_responses
syn keyword ngxDirective contained proxy_send_lowat syn keyword ngxDirective contained proxy_send_lowat
syn keyword ngxDirective contained proxy_send_timeout syn keyword ngxDirective contained proxy_send_timeout
syn keyword ngxDirective contained proxy_session_drop
syn keyword ngxDirective contained proxy_set_body syn keyword ngxDirective contained proxy_set_body
syn keyword ngxDirective contained proxy_set_header syn keyword ngxDirective contained proxy_set_header
syn keyword ngxDirective contained proxy_socket_keepalive
syn keyword ngxDirective contained proxy_ssl syn keyword ngxDirective contained proxy_ssl
syn keyword ngxDirective contained proxy_ssl_certificate syn keyword ngxDirective contained proxy_ssl_certificate
syn keyword ngxDirective contained proxy_ssl_certificate_key syn keyword ngxDirective contained proxy_ssl_certificate_key
@@ -481,6 +501,7 @@ syn keyword ngxDirective contained proxy_temp_path
syn keyword ngxDirective contained proxy_timeout syn keyword ngxDirective contained proxy_timeout
syn keyword ngxDirective contained proxy_upload_rate syn keyword ngxDirective contained proxy_upload_rate
syn keyword ngxDirective contained queue syn keyword ngxDirective contained queue
syn keyword ngxDirective contained random
syn keyword ngxDirective contained random_index syn keyword ngxDirective contained random_index
syn keyword ngxDirective contained read_ahead syn keyword ngxDirective contained read_ahead
syn keyword ngxDirective contained real_ip_header syn keyword ngxDirective contained real_ip_header
@@ -533,6 +554,7 @@ syn keyword ngxDirective contained scgi_pass_request_headers
syn keyword ngxDirective contained scgi_read_timeout syn keyword ngxDirective contained scgi_read_timeout
syn keyword ngxDirective contained scgi_request_buffering syn keyword ngxDirective contained scgi_request_buffering
syn keyword ngxDirective contained scgi_send_timeout syn keyword ngxDirective contained scgi_send_timeout
syn keyword ngxDirective contained scgi_socket_keepalive
syn keyword ngxDirective contained scgi_store syn keyword ngxDirective contained scgi_store
syn keyword ngxDirective contained scgi_store_access syn keyword ngxDirective contained scgi_store_access
syn keyword ngxDirective contained scgi_temp_file_write_size syn keyword ngxDirective contained scgi_temp_file_write_size
@@ -565,7 +587,6 @@ syn keyword ngxDirective contained ssi_min_file_chunk
syn keyword ngxDirective contained ssi_silent_errors syn keyword ngxDirective contained ssi_silent_errors
syn keyword ngxDirective contained ssi_types syn keyword ngxDirective contained ssi_types
syn keyword ngxDirective contained ssi_value_length syn keyword ngxDirective contained ssi_value_length
syn keyword ngxDirective contained ssl
syn keyword ngxDirective contained ssl_buffer_size syn keyword ngxDirective contained ssl_buffer_size
syn keyword ngxDirective contained ssl_certificate syn keyword ngxDirective contained ssl_certificate
syn keyword ngxDirective contained ssl_certificate_key syn keyword ngxDirective contained ssl_certificate_key
@@ -573,9 +594,13 @@ syn keyword ngxDirective contained ssl_ciphers
syn keyword ngxDirective contained ssl_client_certificate syn keyword ngxDirective contained ssl_client_certificate
syn keyword ngxDirective contained ssl_crl syn keyword ngxDirective contained ssl_crl
syn keyword ngxDirective contained ssl_dhparam syn keyword ngxDirective contained ssl_dhparam
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
@@ -664,6 +689,7 @@ syn keyword ngxDirective contained uwsgi_pass_request_headers
syn keyword ngxDirective contained uwsgi_read_timeout syn keyword ngxDirective contained uwsgi_read_timeout
syn keyword ngxDirective contained uwsgi_request_buffering syn keyword ngxDirective contained uwsgi_request_buffering
syn keyword ngxDirective contained uwsgi_send_timeout syn keyword ngxDirective contained uwsgi_send_timeout
syn keyword ngxDirective contained uwsgi_socket_keepalive
syn keyword ngxDirective contained uwsgi_ssl_certificate syn keyword ngxDirective contained uwsgi_ssl_certificate
syn keyword ngxDirective contained uwsgi_ssl_certificate_key syn keyword ngxDirective contained uwsgi_ssl_certificate_key
syn keyword ngxDirective contained uwsgi_ssl_ciphers syn keyword ngxDirective contained uwsgi_ssl_ciphers
@@ -701,6 +727,26 @@ syn keyword ngxDirective contained xslt_string_param
syn keyword ngxDirective contained xslt_stylesheet syn keyword ngxDirective contained xslt_stylesheet
syn keyword ngxDirective contained xslt_types syn keyword ngxDirective contained xslt_types
syn keyword ngxDirective contained zone syn keyword ngxDirective contained zone
syn keyword ngxDirective contained zone_sync
syn keyword ngxDirective contained zone_sync_buffers
syn keyword ngxDirective contained zone_sync_connect_retry_interval
syn keyword ngxDirective contained zone_sync_connect_timeout
syn keyword ngxDirective contained zone_sync_interval
syn keyword ngxDirective contained zone_sync_recv_buffer_size
syn keyword ngxDirective contained zone_sync_server
syn keyword ngxDirective contained zone_sync_ssl
syn keyword ngxDirective contained zone_sync_ssl_certificate
syn keyword ngxDirective contained zone_sync_ssl_certificate_key
syn keyword ngxDirective contained zone_sync_ssl_ciphers
syn keyword ngxDirective contained zone_sync_ssl_crl
syn keyword ngxDirective contained zone_sync_ssl_name
syn keyword ngxDirective contained zone_sync_ssl_password_file
syn keyword ngxDirective contained zone_sync_ssl_protocols
syn keyword ngxDirective contained zone_sync_ssl_server_name
syn keyword ngxDirective contained zone_sync_ssl_trusted_certificate
syn keyword ngxDirective contained zone_sync_ssl_verify
syn keyword ngxDirective contained zone_sync_ssl_verify_depth
syn keyword ngxDirective contained zone_sync_timeout
" 3rd party modules list taken from " 3rd party modules list taken from
" https://github.com/freebsd/freebsd-ports/blob/master/www/nginx-devel/Makefile " https://github.com/freebsd/freebsd-ports/blob/master/www/nginx-devel/Makefile
@@ -730,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
@@ -751,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
@@ -778,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
@@ -814,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
@@ -831,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
@@ -839,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
@@ -876,6 +929,8 @@ syn keyword ngxDirectiveThirdParty contained more_set_input_headers
" NGINX WebDAV missing commands support (PROPFIND & OPTIONS) " NGINX WebDAV missing commands support (PROPFIND & OPTIONS)
" https://github.com/arut/nginx-dav-ext-module " https://github.com/arut/nginx-dav-ext-module
syn keyword ngxDirectiveThirdParty contained dav_ext_lock
syn keyword ngxDirectiveThirdParty contained dav_ext_lock_zone
syn keyword ngxDirectiveThirdParty contained dav_ext_methods syn keyword ngxDirectiveThirdParty contained dav_ext_methods
" ngx_eval " ngx_eval
@@ -895,10 +950,12 @@ syn keyword ngxDirectiveThirdParty contained fancyindex_directories_first
syn keyword ngxDirectiveThirdParty contained fancyindex_exact_size syn keyword ngxDirectiveThirdParty contained fancyindex_exact_size
syn keyword ngxDirectiveThirdParty contained fancyindex_footer syn keyword ngxDirectiveThirdParty contained fancyindex_footer
syn keyword ngxDirectiveThirdParty contained fancyindex_header syn keyword ngxDirectiveThirdParty contained fancyindex_header
syn keyword ngxDirectiveThirdParty contained fancyindex_hide_parent_dir
syn keyword ngxDirectiveThirdParty contained fancyindex_hide_symlinks 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
@@ -937,10 +994,19 @@ syn keyword ngxDirectiveThirdParty contained notice_type
" nchan " nchan
" https://github.com/slact/nchan " https://github.com/slact/nchan
syn keyword ngxDirectiveThirdParty contained nchan_access_control_allow_credentials
syn keyword ngxDirectiveThirdParty contained nchan_access_control_allow_origin syn keyword ngxDirectiveThirdParty contained nchan_access_control_allow_origin
syn keyword ngxDirectiveThirdParty contained nchan_authorize_request syn keyword ngxDirectiveThirdParty contained nchan_authorize_request
syn keyword ngxDirectiveThirdParty contained nchan_channel_event_string syn keyword ngxDirectiveThirdParty contained nchan_benchmark
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_channels
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_message_padding_bytes
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_messages_per_channel_per_minute
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_publisher_distribution
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_subscriber_distribution
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_subscribers_per_channel
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_time
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
@@ -948,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
@@ -974,15 +1044,19 @@ syn keyword ngxDirectiveThirdParty contained nchan_publisher_upstream_request
syn keyword ngxDirectiveThirdParty contained nchan_pubsub syn keyword ngxDirectiveThirdParty contained nchan_pubsub
syn keyword ngxDirectiveThirdParty contained nchan_pubsub_channel_id syn keyword ngxDirectiveThirdParty contained nchan_pubsub_channel_id
syn keyword ngxDirectiveThirdParty contained nchan_pubsub_location syn keyword ngxDirectiveThirdParty contained nchan_pubsub_location
syn keyword ngxDirectiveThirdParty contained nchan_redis_connect_timeout
syn keyword ngxDirectiveThirdParty contained nchan_redis_fakesub_timer_interval syn keyword ngxDirectiveThirdParty contained nchan_redis_fakesub_timer_interval
syn keyword ngxDirectiveThirdParty contained nchan_redis_idle_channel_cache_timeout syn keyword ngxDirectiveThirdParty contained nchan_redis_idle_channel_cache_timeout
syn keyword ngxDirectiveThirdParty contained nchan_redis_namespace syn keyword ngxDirectiveThirdParty contained nchan_redis_namespace
syn keyword ngxDirectiveThirdParty contained nchan_redis_nostore_fastpublish
syn keyword ngxDirectiveThirdParty contained nchan_redis_optimize_target
syn keyword ngxDirectiveThirdParty contained nchan_redis_pass syn keyword ngxDirectiveThirdParty contained nchan_redis_pass
syn keyword ngxDirectiveThirdParty contained nchan_redis_pass_inheritable syn keyword ngxDirectiveThirdParty contained nchan_redis_pass_inheritable
syn keyword ngxDirectiveThirdParty contained nchan_redis_ping_interval syn keyword ngxDirectiveThirdParty contained nchan_redis_ping_interval
syn keyword ngxDirectiveThirdParty contained nchan_redis_publish_msgpacked_max_size syn keyword ngxDirectiveThirdParty contained nchan_redis_publish_msgpacked_max_size
syn keyword ngxDirectiveThirdParty contained nchan_redis_server syn keyword ngxDirectiveThirdParty contained nchan_redis_server
syn keyword ngxDirectiveThirdParty contained nchan_redis_storage_mode syn keyword ngxDirectiveThirdParty contained nchan_redis_storage_mode
syn keyword ngxDirectiveThirdParty contained nchan_redis_subscribe_weights
syn keyword ngxDirectiveThirdParty contained nchan_redis_url syn keyword ngxDirectiveThirdParty contained nchan_redis_url
syn keyword ngxDirectiveThirdParty contained nchan_redis_wait_after_connecting syn keyword ngxDirectiveThirdParty contained nchan_redis_wait_after_connecting
syn keyword ngxDirectiveThirdParty contained nchan_shared_memory_size syn keyword ngxDirectiveThirdParty contained nchan_shared_memory_size
@@ -991,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
@@ -1272,6 +1346,7 @@ syn keyword ngxDirectiveThirdParty contained lua_check_client_abort
syn keyword ngxDirectiveThirdParty contained lua_code_cache syn keyword ngxDirectiveThirdParty contained lua_code_cache
syn keyword ngxDirectiveThirdParty contained lua_fake_shm syn keyword ngxDirectiveThirdParty contained lua_fake_shm
syn keyword ngxDirectiveThirdParty contained lua_http10_buffering syn keyword ngxDirectiveThirdParty contained lua_http10_buffering
syn keyword ngxDirectiveThirdParty contained lua_load_resty_core
syn keyword ngxDirectiveThirdParty contained lua_malloc_trim syn keyword ngxDirectiveThirdParty contained lua_malloc_trim
syn keyword ngxDirectiveThirdParty contained lua_max_pending_timers syn keyword ngxDirectiveThirdParty contained lua_max_pending_timers
syn keyword ngxDirectiveThirdParty contained lua_max_running_timers syn keyword ngxDirectiveThirdParty contained lua_max_running_timers
@@ -1280,6 +1355,7 @@ syn keyword ngxDirectiveThirdParty contained lua_package_cpath
syn keyword ngxDirectiveThirdParty contained lua_package_path syn keyword ngxDirectiveThirdParty contained lua_package_path
syn keyword ngxDirectiveThirdParty contained lua_regex_cache_max_entries syn keyword ngxDirectiveThirdParty contained lua_regex_cache_max_entries
syn keyword ngxDirectiveThirdParty contained lua_regex_match_limit syn keyword ngxDirectiveThirdParty contained lua_regex_match_limit
syn keyword ngxDirectiveThirdParty contained lua_sa_restart
syn keyword ngxDirectiveThirdParty contained lua_shared_dict syn keyword ngxDirectiveThirdParty contained lua_shared_dict
syn keyword ngxDirectiveThirdParty contained lua_socket_buffer_size syn keyword ngxDirectiveThirdParty contained lua_socket_buffer_size
syn keyword ngxDirectiveThirdParty contained lua_socket_connect_timeout syn keyword ngxDirectiveThirdParty contained lua_socket_connect_timeout
@@ -1355,9 +1431,15 @@ syn keyword ngxDirectiveThirdParty contained rules_enabled
" https://www.phusionpassenger.com/library/config/nginx/reference/ " https://www.phusionpassenger.com/library/config/nginx/reference/
syn keyword ngxDirectiveThirdParty contained passenger_abort_on_startup_error syn keyword ngxDirectiveThirdParty contained passenger_abort_on_startup_error
syn keyword ngxDirectiveThirdParty contained passenger_abort_websockets_on_process_shutdown syn keyword ngxDirectiveThirdParty contained passenger_abort_websockets_on_process_shutdown
syn keyword ngxDirectiveThirdParty contained passenger_admin_panel_auth_type
syn keyword ngxDirectiveThirdParty contained passenger_admin_panel_password
syn keyword ngxDirectiveThirdParty contained passenger_admin_panel_url
syn keyword ngxDirectiveThirdParty contained passenger_admin_panel_username
syn keyword ngxDirectiveThirdParty contained passenger_anonymous_telemetry_proxy
syn keyword ngxDirectiveThirdParty contained passenger_app_env syn keyword ngxDirectiveThirdParty contained passenger_app_env
syn keyword ngxDirectiveThirdParty contained passenger_app_file_descriptor_ulimit syn keyword ngxDirectiveThirdParty contained passenger_app_file_descriptor_ulimit
syn keyword ngxDirectiveThirdParty contained passenger_app_group_name syn keyword ngxDirectiveThirdParty contained passenger_app_group_name
syn keyword ngxDirectiveThirdParty contained passenger_app_log_file
syn keyword ngxDirectiveThirdParty contained passenger_app_rights syn keyword ngxDirectiveThirdParty contained passenger_app_rights
syn keyword ngxDirectiveThirdParty contained passenger_app_root syn keyword ngxDirectiveThirdParty contained passenger_app_root
syn keyword ngxDirectiveThirdParty contained passenger_app_type syn keyword ngxDirectiveThirdParty contained passenger_app_type
@@ -1373,8 +1455,10 @@ syn keyword ngxDirectiveThirdParty contained passenger_data_buffer_dir
syn keyword ngxDirectiveThirdParty contained passenger_debugger syn keyword ngxDirectiveThirdParty contained passenger_debugger
syn keyword ngxDirectiveThirdParty contained passenger_default_group syn keyword ngxDirectiveThirdParty contained passenger_default_group
syn keyword ngxDirectiveThirdParty contained passenger_default_user syn keyword ngxDirectiveThirdParty contained passenger_default_user
syn keyword ngxDirectiveThirdParty contained passenger_disable_anonymous_telemetry
syn keyword ngxDirectiveThirdParty contained passenger_disable_security_update_check syn keyword ngxDirectiveThirdParty contained passenger_disable_security_update_check
syn keyword ngxDirectiveThirdParty contained passenger_document_root syn keyword ngxDirectiveThirdParty contained passenger_document_root
syn keyword ngxDirectiveThirdParty contained passenger_dump_config_manifest
syn keyword ngxDirectiveThirdParty contained passenger_enabled syn keyword ngxDirectiveThirdParty contained passenger_enabled
syn keyword ngxDirectiveThirdParty contained passenger_env_var syn keyword ngxDirectiveThirdParty contained passenger_env_var
syn keyword ngxDirectiveThirdParty contained passenger_file_descriptor_log_file syn keyword ngxDirectiveThirdParty contained passenger_file_descriptor_log_file
@@ -1402,6 +1486,7 @@ syn keyword ngxDirectiveThirdParty contained passenger_max_requests
syn keyword ngxDirectiveThirdParty contained passenger_memory_limit syn keyword ngxDirectiveThirdParty contained passenger_memory_limit
syn keyword ngxDirectiveThirdParty contained passenger_meteor_app_settings syn keyword ngxDirectiveThirdParty contained passenger_meteor_app_settings
syn keyword ngxDirectiveThirdParty contained passenger_min_instances syn keyword ngxDirectiveThirdParty contained passenger_min_instances
syn keyword ngxDirectiveThirdParty contained passenger_monitor_log_file
syn keyword ngxDirectiveThirdParty contained passenger_nodejs syn keyword ngxDirectiveThirdParty contained passenger_nodejs
syn keyword ngxDirectiveThirdParty contained passenger_pass_header syn keyword ngxDirectiveThirdParty contained passenger_pass_header
syn keyword ngxDirectiveThirdParty contained passenger_pool_idle_time syn keyword ngxDirectiveThirdParty contained passenger_pool_idle_time
@@ -1716,6 +1801,7 @@ syn keyword ngxDirectiveThirdParty contained vod_expires_live_time_dependent
syn keyword ngxDirectiveThirdParty contained vod_fallback_upstream_location syn keyword ngxDirectiveThirdParty contained vod_fallback_upstream_location
syn keyword ngxDirectiveThirdParty contained vod_force_continuous_timestamps syn keyword ngxDirectiveThirdParty contained vod_force_continuous_timestamps
syn keyword ngxDirectiveThirdParty contained vod_force_playlist_type_vod syn keyword ngxDirectiveThirdParty contained vod_force_playlist_type_vod
syn keyword ngxDirectiveThirdParty contained vod_force_sequence_index
syn keyword ngxDirectiveThirdParty contained vod_gop_look_ahead syn keyword ngxDirectiveThirdParty contained vod_gop_look_ahead
syn keyword ngxDirectiveThirdParty contained vod_gop_look_behind syn keyword ngxDirectiveThirdParty contained vod_gop_look_behind
syn keyword ngxDirectiveThirdParty contained vod_ignore_edit_list syn keyword ngxDirectiveThirdParty contained vod_ignore_edit_list
@@ -1778,6 +1864,8 @@ syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_filter
syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_filter_by_host syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_filter_by_host
syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_filter_by_set_key syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_filter_by_set_key
syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_filter_check_duplicate syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_filter_check_duplicate
syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_filter_max_node
syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_histogram_buckets
syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_limit syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_limit
syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_limit_check_duplicate syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_limit_check_duplicate
syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_limit_traffic syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_limit_traffic
@@ -1899,11 +1987,11 @@ syn keyword ngxDirectiveThirdParty contained form_auth_remote_user
" ngx_http_accounting_module " ngx_http_accounting_module
" https://github.com/Lax/ngx_http_accounting_module " https://github.com/Lax/ngx_http_accounting_module
syn keyword ngxDirectiveThirdParty contained http_accounting syn keyword ngxDirectiveThirdParty contained accounting
syn keyword ngxDirectiveThirdParty contained http_accounting_id syn keyword ngxDirectiveThirdParty contained accounting_id
syn keyword ngxDirectiveThirdParty contained http_accounting_interval syn keyword ngxDirectiveThirdParty contained accounting_interval
syn keyword ngxDirectiveThirdParty contained http_accounting_log syn keyword ngxDirectiveThirdParty contained accounting_log
syn keyword ngxDirectiveThirdParty contained http_accounting_perturb syn keyword ngxDirectiveThirdParty contained accounting_perturb
" concatenating files in a given context: CSS and JS files usually " concatenating files in a given context: CSS and JS files usually
" https://github.com/alibaba/nginx-http-concat " https://github.com/alibaba/nginx-http-concat
@@ -1917,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
@@ -2238,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
+8 -7
View File
@@ -1,5 +1,5 @@
.\" .\"
.\" Copyright (C) 2010 Sergey A. Osokin .\" Copyright (C) 2010, 2019 Sergey A. Osokin
.\" Copyright (C) Nginx, Inc. .\" Copyright (C) Nginx, Inc.
.\" All rights reserved. .\" All rights reserved.
.\" .\"
@@ -25,7 +25,7 @@
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.\" .\"
.Dd June 16, 2015 .Dd December 5, 2019
.Dt NGINX 8 .Dt NGINX 8
.Os .Os
.Sh NAME .Sh NAME
@@ -42,7 +42,8 @@
.Nm .Nm
(pronounced (pronounced
.Dq engine x ) .Dq engine x )
is an HTTP and reverse proxy server, as well as a mail proxy server. is an HTTP and reverse proxy server, a mail proxy server, and a generic
TCP/UDP proxy server.
It is known for its high performance, stability, rich feature set, simple It is known for its high performance, stability, rich feature set, simple
configuration, and low resource consumption. configuration, and low resource consumption.
.Pp .Pp
@@ -82,15 +83,15 @@ The following table shows the corresponding system signals:
.It Cm reload .It Cm reload
.Dv SIGHUP .Dv SIGHUP
.El .El
.It Fl T
Same as
.Fl t ,
but additionally dump configuration files to standard output.
.It Fl t .It Fl t
Do not run, just test the configuration file. Do not run, just test the configuration file.
.Nm .Nm
checks the configuration file syntax and then tries to open files checks the configuration file syntax and then tries to open files
referenced in the configuration file. referenced in the configuration file.
.It Fl T
Same as
.Fl t ,
but additionally dump configuration files to standard output.
.It Fl V .It Fl V
Print the Print the
.Nm .Nm
+2 -2
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2002-2018 Igor Sysoev * Copyright (C) 2002-2019 Igor Sysoev
* Copyright (C) 2011-2018 Nginx, Inc. * Copyright (C) 2011-2019 Nginx, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
+1255
View File
@@ -5,6 +5,1261 @@
<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">
<change type="bugfix">
<para lang="ru">
на старте или во время переконфигурации мог произойти segmentation fault,
если в конфигурации использовалась
директива rewrite с пустой строкой замены.
</para>
<para lang="en">
a segmentation fault might occur on start or during reconfiguration
if the "rewrite" directive with an empty replacement string
was used in the configuration.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если директива break использовалась совместно с директивой alias
или директивой proxy_pass с URI.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if the "break" directive was used with the "alias" directive
or with the "proxy_pass" directive with a URI.
</para>
</change>
<change type="bugfix">
<para lang="ru">
строка Location заголовка ответа могла содержать мусор,
если URI запроса был изменён на URI, содержащий нулевой символ.
</para>
<para lang="en">
the "Location" response header line might contain garbage
if the request URI was rewritten to the one containing a null character.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при возврате перенаправлений с помощью директивы error_page
запросы с телом обрабатывались некорректно;
ошибка появилась в 0.7.12.
</para>
<para lang="en">
requests with bodies were handled incorrectly
when returning redirections with the "error_page" directive;
the bug had appeared in 0.7.12.
</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">
при обработке 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">
в модуле ngx_http_dav_module.
</para>
<para lang="en">
in the ngx_http_dav_module.
</para>
</change>
</changes>
<changes ver="1.17.6" date="2019-11-19">
<change type="feature">
<para lang="ru">
переменные $proxy_protocol_server_addr и $proxy_protocol_server_port.
</para>
<para lang="en">
the $proxy_protocol_server_addr and $proxy_protocol_server_port variables.
</para>
</change>
<change type="feature">
<para lang="ru">
директива limit_conn_dry_run.
</para>
<para lang="en">
the "limit_conn_dry_run" directive.
</para>
</change>
<change type="feature">
<para lang="ru">
переменные $limit_req_status и $limit_conn_status.
</para>
<para lang="en">
the $limit_req_status and $limit_conn_status variables.
</para>
</change>
</changes>
<changes ver="1.17.5" date="2019-10-22">
<change type="feature">
<para lang="ru">
теперь nginx использует вызов ioctl(FIONREAD), если он доступен,
чтобы избежать чтения из быстрого соединения в течение долгого времени.
</para>
<para lang="en">
now nginx uses ioctl(FIONREAD), if available,
to avoid reading from a fast connection for a long time.
</para>
</change>
<change type="bugfix">
<para lang="ru">
неполные закодированные символы в конце URI запроса игнорировались.
</para>
<para lang="en">
incomplete escaped characters at the end of the request URI were ignored.
</para>
</change>
<change type="bugfix">
<para lang="ru">
"/." и "/.." в конце URI запроса не нормализовывались.
</para>
<para lang="en">
"/." and "/.." at the end of the request URI were not normalized.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в директиве merge_slashes.
</para>
<para lang="en">
in the "merge_slashes" directive.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в директиве ignore_invalid_headers.<br/>
Спасибо Alan Kemp.
</para>
<para lang="en">
in the "ignore_invalid_headers" directive.<br/>
Thanks to Alan Kemp.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx не собирался с MinGW-w64 gcc 8.1 и новее.
</para>
<para lang="en">
nginx could not be built with MinGW-w64 gcc 8.1 or newer.
</para>
</change>
</changes>
<changes ver="1.17.4" date="2019-09-24">
<change type="change">
<para lang="ru">
улучшено детектирование некорректного поведения клиентов в HTTP/2.
</para>
<para lang="en">
better detection of incorrect client behavior in HTTP/2.
</para>
</change>
<change type="change">
<para lang="ru">
в обработке непрочитанного тела запроса
при возврате ошибок в HTTP/2.
</para>
<para lang="en">
in handling of not fully read client request body
when returning errors in HTTP/2.
</para>
</change>
<change type="bugfix">
<para lang="ru">
директива worker_shutdown_timeout могла не работать
при использовании HTTP/2.
</para>
<para lang="en">
the "worker_shutdown_timeout" directive might not work
when using HTTP/2.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при использовании HTTP/2 и директивы proxy_request_buffering
в рабочем процессе мог произойти segmentation fault.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
when using HTTP/2 and the "proxy_request_buffering" directive.
</para>
</change>
<change type="bugfix">
<para lang="ru">
на Windows при использовании SSL
уровень записи в лог ошибки ECONNABORTED был "crit" вместо "error".
</para>
<para lang="en">
the ECONNABORTED error log level was "crit" instead of "error"
on Windows when using SSL.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx игнорировал лишние данные при использовании chunked transfer encoding.
</para>
<para lang="en">
nginx ignored extra data when using chunked transfer encoding.
</para>
</change>
<change type="bugfix">
<para lang="ru">
если использовалась директива return и
при чтении тела запроса возникала ошибка,
nginx всегда возвращал ошибку 500.
</para>
<para lang="en">
nginx always returned the 500 error
if the "return" directive was used
and an error occurred during reading client request body.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в обработке ошибок выделения памяти.
</para>
<para lang="en">
in memory allocation error handling.
</para>
</change>
</changes>
<changes ver="1.17.3" date="2019-08-13">
<change type="security">
<para lang="ru">
при использовании HTTP/2 клиент мог вызвать
чрезмерное потребление памяти и ресурсов процессора
(CVE-2019-9511, CVE-2019-9513, CVE-2019-9516).
</para>
<para lang="en">
when using HTTP/2 a client might cause
excessive memory consumption and CPU usage
(CVE-2019-9511, CVE-2019-9513, CVE-2019-9516).
</para>
</change>
<change type="bugfix">
<para lang="ru">
при использовании сжатия в логах могли появляться сообщения "zero size buf";
ошибка появилась в 1.17.2.
</para>
<para lang="en">
"zero size buf" alerts might appear in logs when using gzipping;
the bug had appeared in 1.17.2.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при использовании директивы resolver в SMTP прокси-сервере
в рабочем процессе мог произойти segmentation fault.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if the "resolver" directive was used in SMTP proxy.
</para>
</change>
</changes>
<changes ver="1.17.2" date="2019-07-23">
<change type="change">
<para lang="ru">
минимальная поддерживаемая версия zlib&mdash;1.2.0.4.<br/>
Спасибо Илье Леошкевичу.
</para>
<para lang="en">
minimum supported zlib version is 1.2.0.4.<br/>
Thanks to Ilya Leoshkevich.
</para>
</change>
<change type="change">
<para lang="ru">
метод $r->internal_redirect() встроенного перла
теперь ожидает закодированный URI.
</para>
<para lang="en">
the $r->internal_redirect() embedded perl method
now expects escaped URIs.
</para>
</change>
<change type="feature">
<para lang="ru">
теперь с помощью метода $r->internal_redirect() встроенного перла
можно перейти в именованный location.
</para>
<para lang="en">
it is now possible to switch to a named location
using the $r->internal_redirect() embedded perl method.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в обработке ошибок во встроенном перле.
</para>
<para lang="en">
in error handling in embedded perl.
</para>
</change>
<change type="bugfix">
<para lang="ru">
на старте или во время переконфигурации мог произойти segmentation fault,
если в конфигурации использовалось значение hash bucket size больше 64 килобайт.
</para>
<para lang="en">
a segmentation fault might occur on start or during reconfiguration
if hash bucket size larger than 64 kilobytes was used in the configuration.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при использовании методов обработки соединений select, poll и /dev/poll
nginx мог нагружать процессор во время небуферизованного проксирования
и при проксировании WebSocket-соединений.
</para>
<para lang="en">
nginx might hog CPU during unbuffered proxying
and when proxying WebSocket connections
if the select, poll, or /dev/poll methods were used.
</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>
<change type="bugfix">
<para lang="ru">
в модуле ngx_http_ssi_filter_module.
</para>
<para lang="en">
in the ngx_http_ssi_filter_module.
</para>
</change>
</changes>
<changes ver="1.17.1" date="2019-06-25">
<change type="feature">
<para lang="ru">
директива limit_req_dry_run.
</para>
<para lang="en">
the "limit_req_dry_run" directive.
</para>
</change>
<change type="feature">
<para lang="ru">
при использовании директивы hash в блоке upstream
пустой ключ хэширования теперь приводит к переключению
на round-robin балансировку.<br/>
Спасибо Niklas Keller.
</para>
<para lang="en">
when using the "hash" directive inside the "upstream" block
an empty hash key now triggers round-robin balancing.<br/>
Thanks to Niklas Keller.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если использовалось кэширование и директива image_filter,
а ошибки с кодом 415 перенаправлялись с помощью директивы error_page;
ошибка появилась в 1.11.10.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if caching was used along with the "image_filter" directive,
and errors with code 415 were redirected with the "error_page" directive;
the bug had appeared in 1.11.10.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если использовался встроенный перл;
ошибка появилась в 1.7.3.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if embedded perl was used;
the bug had appeared in 1.7.3.
</para>
</change>
</changes>
<changes ver="1.17.0" date="2019-05-21">
<change type="feature">
<para lang="ru">
директивы limit_rate и limit_rate_after поддерживают переменные.
</para>
<para lang="en">
variables support in the "limit_rate" and "limit_rate_after" directives.
</para>
</change>
<change type="feature">
<para lang="ru">
директивы proxy_upload_rate и proxy_download_rate в модуле stream
поддерживают переменные.
</para>
<para lang="en">
variables support
in the "proxy_upload_rate" and "proxy_download_rate" directives
in the stream module.
</para>
</change>
<change type="change">
<para lang="ru">
минимальная поддерживаемая версия OpenSSL&mdash;0.9.8.
</para>
<para lang="en">
minimum supported OpenSSL version is 0.9.8.
</para>
</change>
<change type="change">
<para lang="ru">
теперь postpone-фильтр собирается всегда.
</para>
<para lang="en">
now the postpone filter is always built.
</para>
</change>
<change type="bugfix">
<para lang="ru">
директива include не работала в блоках if и limit_except.
</para>
<para lang="en">
the "include" directive did not work inside the "if" and "limit_except" blocks.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в обработке byte ranges.
</para>
<para lang="en">
in byte ranges processing.
</para>
</change>
</changes>
<changes ver="1.15.12" date="2019-04-16">
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если в директивах ssl_certificate или ssl_certificate_key
использовались переменные
и был включён OCSP stapling.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if variables were used
in the "ssl_certificate" or "ssl_certificate_key" directives
and OCSP stapling was enabled.
</para>
</change>
</changes>
<changes ver="1.15.11" date="2019-04-09">
<change type="bugfix">
<para lang="ru">
в директиве ssl_stapling_file на Windows.
</para>
<para lang="en">
in the "ssl_stapling_file" directive on Windows.
</para>
</change>
</changes>
<changes ver="1.15.10" date="2019-03-26">
<change type="change">
<para lang="ru">
теперь при использовании имени хоста в директиве listen
nginx создаёт listen-сокеты для всех адресов,
соответствующих этому имени
(ранее использовался только первый адрес).
</para>
<para lang="en">
when using a hostname in the "listen" directive
nginx now creates listening sockets
for all addresses the hostname resolves to
(previously, only the first address was used).
</para>
</change>
<change type="feature">
<para lang="ru">
диапазоны портов в директиве listen.
</para>
<para lang="en">
port ranges in the "listen" directive.
</para>
</change>
<change type="feature">
<para lang="ru">
возможность загрузки SSL-сертификатов и секретных ключей из переменных.
</para>
<para lang="en">
loading of SSL certificates and secret keys from variables.
</para>
</change>
<change type="workaround">
<para lang="ru">
переменная $ssl_server_name могла быть пустой
при использовании OpenSSL 1.1.1.
</para>
<para lang="en">
the $ssl_server_name variable might be empty
when using OpenSSL 1.1.1.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx/Windows не собирался с Visual Studio 2015 и новее;
ошибка появилась в 1.15.9.
</para>
<para lang="en">
nginx/Windows could not be built with Visual Studio 2015 or newer;
the bug had appeared in 1.15.9.
</para>
</change>
</changes>
<changes ver="1.15.9" date="2019-02-26">
<change type="feature">
<para lang="ru">
директивы ssl_certificate и ssl_certificate_key
поддерживают переменные.
</para>
<para lang="en">
variables support
in the "ssl_certificate" and "ssl_certificate_key" directives.
</para>
</change>
<change type="feature">
<para lang="ru">
метод poll теперь доступен на Windows
при использовании Windows Vista и новее.
</para>
<para lang="en">
the "poll" method is now available on Windows
when using Windows Vista or newer.
</para>
</change>
<change type="bugfix">
<para lang="ru">
если при использовании метода select на Windows
происходила ошибка при установлении соединения с бэкендом,
nginx ожидал истечения таймаута на установление соединения.
</para>
<para lang="en">
if the "select" method was used on Windows
and an error occurred while establishing a backend connection,
nginx waited for the connection establishment timeout to expire.
</para>
</change>
<change type="bugfix">
<para lang="ru">
директивы proxy_upload_rate и proxy_download_rate
в модуле stream
работали некорректно при проксировании UDP-пакетов.
</para>
<para lang="en">
the "proxy_upload_rate" and "proxy_download_rate" directives
in the stream module
worked incorrectly when proxying UDP datagrams.
</para>
</change>
</changes>
<changes ver="1.15.8" date="2018-12-25">
<change type="feature">
<para lang="ru">
переменная $upstream_bytes_sent.<br/>
Спасибо Piotr Sikora.
</para>
<para lang="en">
the $upstream_bytes_sent variable.<br/>
Thanks to Piotr Sikora.
</para>
</change>
<change type="feature">
<para lang="ru">
новые директивы в скриптах подсветки синтаксиса для vim.<br/>
Спасибо Геннадию Махомеду.
</para>
<para lang="en">
new directives in vim syntax highlighting scripts.<br/>
Thanks to Gena Makhomed.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в директиве proxy_cache_background_update.
</para>
<para lang="en">
in the "proxy_cache_background_update" directive.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в директиве geo при использовании unix domain listen-сокетов.
</para>
<para lang="en">
in the "geo" directive when using unix domain listen sockets.
</para>
</change>
<change type="workaround">
<para lang="ru">
при использовании директивы ssl_early_data с OpenSSL
в логах могли появляться сообщения
"ignoring stale global SSL error ... bad length".
</para>
<para lang="en">
the "ignoring stale global SSL error ... bad length"
alerts might appear in logs
when using the "ssl_early_data" directive with OpenSSL.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в nginx/Windows.
</para>
<para lang="en">
in nginx/Windows.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в модуле ngx_http_autoindex_module на 32-битных платформах.
</para>
<para lang="en">
in the ngx_http_autoindex_module on 32-bit platforms.
</para>
</change>
</changes>
<changes ver="1.15.7" date="2018-11-27">
<change type="feature">
<para lang="ru">
директива proxy_requests в модуле stream.
</para>
<para lang="en">
the "proxy_requests" directive in the stream module.
</para>
</change>
<change type="feature">
<para lang="ru">
параметр "delay" директивы "limit_req".<br/>
Спасибо Владиславу Шабанову и Петру Щучкину.
</para>
<para lang="en">
the "delay" parameter of the "limit_req" directive.<br/>
Thanks to Vladislav Shabanov and Peter Shchuchkin.
</para>
</change>
<change type="bugfix">
<para lang="ru">
утечки памяти в случае ошибок при переконфигурации.
</para>
<para lang="en">
memory leak on errors during reconfiguration.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в переменных $upstream_response_time, $upstream_connect_time и
$upstream_header_time.
</para>
<para lang="en">
in the $upstream_response_time, $upstream_connect_time, and
$upstream_header_time variables.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если использовался модуль ngx_http_mp4_module на 32-битных платформах.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if the ngx_http_mp4_module was used on 32-bit platforms.
</para>
</change>
</changes>
<changes ver="1.15.6" date="2018-11-06">
<change type="security">
<para lang="ru">
при использовании HTTP/2 клиент мог вызвать
чрезмерное потреблению памяти (CVE-2018-16843)
и ресурсов процессора (CVE-2018-16844).
</para>
<para lang="en">
when using HTTP/2 a client might cause
excessive memory consumption (CVE-2018-16843)
and CPU usage (CVE-2018-16844).
</para>
</change>
<change type="security">
<para lang="ru">
при обработке специально созданного mp4-файла модулем ngx_http_mp4_module
содержимое памяти рабочего процесса могло быть отправлено клиенту
(CVE-2018-16845).
</para>
<para lang="en">
processing of a specially crafted mp4 file with the ngx_http_mp4_module
might result in worker process memory disclosure
(CVE-2018-16845).
</para>
</change>
<change type="feature">
<para lang="ru">
директивы proxy_socket_keepalive, fastcgi_socket_keepalive,
grpc_socket_keepalive, memcached_socket_keepalive,
scgi_socket_keepalive и uwsgi_socket_keepalive.
</para>
<para lang="en">
the "proxy_socket_keepalive", "fastcgi_socket_keepalive",
"grpc_socket_keepalive", "memcached_socket_keepalive",
"scgi_socket_keepalive", and "uwsgi_socket_keepalive" directives.
</para>
</change>
<change type="bugfix">
<para lang="ru">
если nginx был собран с OpenSSL 1.1.0, а использовался с OpenSSL 1.1.1,
протокол TLS 1.3 всегда был разрешён.
</para>
<para lang="en">
if nginx was built with OpenSSL 1.1.0 and used with OpenSSL 1.1.1,
the TLS 1.3 protocol was always enabled.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при работе с gRPC-бэкендами могло расходоваться большое количество памяти.
</para>
<para lang="en">
working with gRPC backends might result in excessive memory consumption.
</para>
</change>
</changes>
<changes ver="1.15.5" date="2018-10-02"> <changes ver="1.15.5" date="2018-10-02">
<change type="bugfix"> <change type="bugfix">
+3 -4
View File
@@ -6,9 +6,9 @@ TEMP = tmp
CC = cl CC = cl
OBJS = objs.msvc8 OBJS = objs.msvc8
OPENSSL = openssl-1.0.2p OPENSSL = openssl-1.1.1g
ZLIB = zlib-1.2.11 ZLIB = zlib-1.2.11
PCRE = pcre-8.42 PCRE = pcre-8.44
release: export release: export
@@ -65,7 +65,6 @@ win32:
--with-cc-opt=-DFD_SETSIZE=1024 \ --with-cc-opt=-DFD_SETSIZE=1024 \
--with-pcre=$(OBJS)/lib/$(PCRE) \ --with-pcre=$(OBJS)/lib/$(PCRE) \
--with-zlib=$(OBJS)/lib/$(ZLIB) \ --with-zlib=$(OBJS)/lib/$(ZLIB) \
--with-select_module \
--with-http_v2_module \ --with-http_v2_module \
--with-http_realip_module \ --with-http_realip_module \
--with-http_addition_module \ --with-http_addition_module \
@@ -83,7 +82,7 @@ win32:
--with-mail \ --with-mail \
--with-stream \ --with-stream \
--with-openssl=$(OBJS)/lib/$(OPENSSL) \ --with-openssl=$(OBJS)/lib/$(OPENSSL) \
--with-openssl-opt=no-asm \ --with-openssl-opt="no-asm no-tests -D_WIN32_WINNT=0x0501" \
--with-http_ssl_module \ --with-http_ssl_module \
--with-mail_ssl_module \ --with-mail_ssl_module \
--with-stream_ssl_module --with-stream_ssl_module
+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 1015006 #define nginx_version 1019003
#define NGINX_VERSION "1.15.6" #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)
+1 -1
View File
@@ -310,7 +310,7 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
goto failed; goto failed;
} }
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv); ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", rv);
goto failed; goto failed;
} }
+1 -1
View File
@@ -49,7 +49,7 @@
#define NGX_DIRECT_CONF 0x00010000 #define NGX_DIRECT_CONF 0x00010000
#define NGX_MAIN_CONF 0x01000000 #define NGX_MAIN_CONF 0x01000000
#define NGX_ANY_CONF 0x1F000000 #define NGX_ANY_CONF 0xFF000000
+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++) {
+1 -2
View File
@@ -147,8 +147,7 @@ struct ngx_connection_s {
socklen_t socklen; socklen_t socklen;
ngx_str_t addr_text; ngx_str_t addr_text;
ngx_str_t proxy_protocol_addr; ngx_proxy_protocol_t *proxy_protocol;
in_port_t proxy_protocol_port;
#if (NGX_SSL || NGX_COMPAT) #if (NGX_SSL || NGX_COMPAT)
ngx_ssl_connection_t *ssl; ngx_ssl_connection_t *ssl;
+1
View File
@@ -26,6 +26,7 @@ typedef struct ngx_event_aio_s ngx_event_aio_t;
typedef struct ngx_connection_s ngx_connection_t; typedef struct ngx_connection_s ngx_connection_t;
typedef struct ngx_thread_task_s ngx_thread_task_t; typedef struct ngx_thread_task_s ngx_thread_task_t;
typedef struct ngx_ssl_s ngx_ssl_t; typedef struct ngx_ssl_s ngx_ssl_t;
typedef struct ngx_proxy_protocol_s ngx_proxy_protocol_t;
typedef struct ngx_ssl_connection_s ngx_ssl_connection_t; typedef struct ngx_ssl_connection_s ngx_ssl_connection_t;
typedef struct ngx_udp_connection_s ngx_udp_connection_t; typedef struct ngx_udp_connection_s ngx_udp_connection_t;
+70 -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;
@@ -843,6 +844,69 @@ failed:
} }
} }
/* free the newly created shared memory */
part = &cycle->shared_memory.part;
shm_zone = part->elts;
for (i = 0; /* void */ ; i++) {
if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
shm_zone = part->elts;
i = 0;
}
if (shm_zone[i].shm.addr == NULL) {
continue;
}
opart = &old_cycle->shared_memory.part;
oshm_zone = opart->elts;
for (n = 0; /* void */ ; n++) {
if (n >= opart->nelts) {
if (opart->next == NULL) {
break;
}
opart = opart->next;
oshm_zone = opart->elts;
n = 0;
}
if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) {
continue;
}
if (ngx_strncmp(shm_zone[i].shm.name.data,
oshm_zone[n].shm.name.data,
shm_zone[i].shm.name.len)
!= 0)
{
continue;
}
if (shm_zone[i].tag == oshm_zone[n].tag
&& shm_zone[i].shm.size == oshm_zone[n].shm.size
&& !shm_zone[i].noreuse)
{
goto old_shm_zone_found;
}
break;
}
ngx_shm_free(&shm_zone[i].shm);
old_shm_zone_found:
continue;
}
if (ngx_test_config) { if (ngx_test_config) {
ngx_destroy_cycle_pools(&conf); ngx_destroy_cycle_pools(&conf);
return NULL; return NULL;
@@ -945,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];
@@ -969,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;
} }
} }
@@ -982,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;
} }
@@ -1274,6 +1341,7 @@ ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag)
shm_zone->data = NULL; shm_zone->data = NULL;
shm_zone->shm.log = cf->cycle->log; shm_zone->shm.log = cf->cycle->log;
shm_zone->shm.addr = NULL;
shm_zone->shm.size = size; shm_zone->shm.size = size;
shm_zone->shm.name = *name; shm_zone->shm.name = *name;
shm_zone->shm.exists = 0; shm_zone->shm.exists = 0;
+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;
+2 -2
View File
@@ -1017,13 +1017,13 @@ ngx_walk_tree(ngx_tree_ctx_t *ctx, ngx_str_t *tree)
file.len = tree->len + 1 + len; file.len = tree->len + 1 + len;
if (file.len + NGX_DIR_MASK_LEN > buf.len) { if (file.len > buf.len) {
if (buf.len) { if (buf.len) {
ngx_free(buf.data); ngx_free(buf.data);
} }
buf.len = tree->len + 1 + len + NGX_DIR_MASK_LEN; buf.len = tree->len + 1 + len;
buf.data = ngx_alloc(buf.len + 1, ctx->log); buf.data = ngx_alloc(buf.len + 1, ctx->log);
if (buf.data == NULL) { if (buf.data == NULL) {
+26 -5
View File
@@ -265,6 +265,14 @@ ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
return NGX_ERROR; return NGX_ERROR;
} }
if (hinit->bucket_size > 65536 - ngx_cacheline_size) {
ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
"could not build %s, too large "
"%s_bucket_size: %i",
hinit->name, hinit->name, hinit->bucket_size);
return NGX_ERROR;
}
for (n = 0; n < nelts; n++) { for (n = 0; n < nelts; n++) {
if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *)) if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *))
{ {
@@ -300,17 +308,19 @@ ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
} }
key = names[n].key_hash % size; key = names[n].key_hash % size;
test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n])); len = test[key] + NGX_HASH_ELT_SIZE(&names[n]);
#if 0 #if 0
ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
"%ui: %ui %ui \"%V\"", "%ui: %ui %uz \"%V\"",
size, key, test[key], &names[n].key); size, key, len, &names[n].key);
#endif #endif
if (test[key] > (u_short) bucket_size) { if (len > bucket_size) {
goto next; goto next;
} }
test[key] = (u_short) len;
} }
goto found; goto found;
@@ -341,7 +351,18 @@ found:
} }
key = names[n].key_hash % size; key = names[n].key_hash % size;
test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n])); len = test[key] + NGX_HASH_ELT_SIZE(&names[n]);
if (len > 65536 - ngx_cacheline_size) {
ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
"could not build %s, you should "
"increase %s_max_size: %i",
hinit->name, hinit->name, hinit->max_size);
ngx_free(test);
return NGX_ERROR;
}
test[key] = (u_short) len;
} }
len = 0; len = 0;
+233 -235
View File
@@ -12,6 +12,8 @@
static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u); static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);
static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u); static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);
static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u); static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);
static ngx_int_t ngx_inet_add_addr(ngx_pool_t *pool, ngx_url_t *u,
struct sockaddr *sockaddr, socklen_t socklen, ngx_uint_t total);
in_addr_t in_addr_t
@@ -780,13 +782,10 @@ ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
static ngx_int_t static ngx_int_t
ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u) ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
{ {
u_char *p, *host, *port, *last, *uri, *args; u_char *host, *port, *last, *uri, *args, *dash;
size_t len; size_t len;
ngx_int_t n; ngx_int_t n;
struct sockaddr_in *sin; struct sockaddr_in *sin;
#if (NGX_HAVE_INET6)
struct sockaddr_in6 *sin6;
#endif
u->socklen = sizeof(struct sockaddr_in); u->socklen = sizeof(struct sockaddr_in);
sin = (struct sockaddr_in *) &u->sockaddr; sin = (struct sockaddr_in *) &u->sockaddr;
@@ -831,6 +830,25 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
len = last - port; len = last - port;
if (u->listen) {
dash = ngx_strlchr(port, last, '-');
if (dash) {
dash++;
n = ngx_atoi(dash, last - dash);
if (n < 1 || n > 65535) {
u->err = "invalid port";
return NGX_ERROR;
}
u->last_port = (in_port_t) n;
len = dash - port - 1;
}
}
n = ngx_atoi(port, len); n = ngx_atoi(port, len);
if (n < 1 || n > 65535) { if (n < 1 || n > 65535) {
@@ -838,10 +856,15 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
return NGX_ERROR; return NGX_ERROR;
} }
if (u->last_port && n > u->last_port) {
u->err = "invalid port range";
return NGX_ERROR;
}
u->port = (in_port_t) n; u->port = (in_port_t) n;
sin->sin_port = htons((in_port_t) n); sin->sin_port = htons((in_port_t) n);
u->port_text.len = len; u->port_text.len = last - port;
u->port_text.data = port; u->port_text.data = port;
last = port - 1; last = port - 1;
@@ -853,31 +876,69 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
/* test value as port only */ /* test value as port only */
n = ngx_atoi(host, last - host); len = last - host;
dash = ngx_strlchr(host, last, '-');
if (dash) {
dash++;
n = ngx_atoi(dash, last - dash);
if (n == NGX_ERROR) {
goto no_port;
}
if (n < 1 || n > 65535) {
u->err = "invalid port";
} else {
u->last_port = (in_port_t) n;
}
len = dash - host - 1;
}
n = ngx_atoi(host, len);
if (n != NGX_ERROR) { if (n != NGX_ERROR) {
if (u->err) {
return NGX_ERROR;
}
if (n < 1 || n > 65535) { if (n < 1 || n > 65535) {
u->err = "invalid port"; u->err = "invalid port";
return NGX_ERROR; return NGX_ERROR;
} }
if (u->last_port && n > u->last_port) {
u->err = "invalid port range";
return NGX_ERROR;
}
u->port = (in_port_t) n; u->port = (in_port_t) n;
sin->sin_port = htons((in_port_t) n); sin->sin_port = htons((in_port_t) n);
sin->sin_addr.s_addr = INADDR_ANY;
u->port_text.len = last - host; u->port_text.len = last - host;
u->port_text.data = host; u->port_text.data = host;
u->wildcard = 1; u->wildcard = 1;
return NGX_OK; return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr,
u->socklen, 1);
} }
} }
} }
no_port:
u->err = NULL;
u->no_port = 1; u->no_port = 1;
u->port = u->default_port; u->port = u->default_port;
sin->sin_port = htons(u->default_port); sin->sin_port = htons(u->default_port);
u->last_port = 0;
} }
len = last - host; len = last - host;
@@ -893,7 +954,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
if (u->listen && len == 1 && *host == '*') { if (u->listen && len == 1 && *host == '*') {
sin->sin_addr.s_addr = INADDR_ANY; sin->sin_addr.s_addr = INADDR_ANY;
u->wildcard = 1; u->wildcard = 1;
return NGX_OK; return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1);
} }
sin->sin_addr.s_addr = ngx_inet_addr(host, len); sin->sin_addr.s_addr = ngx_inet_addr(host, len);
@@ -904,33 +965,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
u->wildcard = 1; u->wildcard = 1;
} }
u->naddrs = 1; return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1);
u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
if (u->addrs == NULL) {
return NGX_ERROR;
}
sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
if (sin == NULL) {
return NGX_ERROR;
}
ngx_memcpy(sin, &u->sockaddr, sizeof(struct sockaddr_in));
u->addrs[0].sockaddr = (struct sockaddr *) sin;
u->addrs[0].socklen = sizeof(struct sockaddr_in);
p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
if (p == NULL) {
return NGX_ERROR;
}
u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
&u->host, u->port) - p;
u->addrs[0].name.data = p;
return NGX_OK;
} }
if (u->no_resolve) { if (u->no_resolve) {
@@ -944,29 +979,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
u->family = u->addrs[0].sockaddr->sa_family; u->family = u->addrs[0].sockaddr->sa_family;
u->socklen = u->addrs[0].socklen; u->socklen = u->addrs[0].socklen;
ngx_memcpy(&u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen); ngx_memcpy(&u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen);
u->wildcard = ngx_inet_wildcard(&u->sockaddr.sockaddr);
switch (u->family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
sin6 = (struct sockaddr_in6 *) &u->sockaddr;
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
u->wildcard = 1;
}
break;
#endif
default: /* AF_INET */
sin = (struct sockaddr_in *) &u->sockaddr;
if (sin->sin_addr.s_addr == INADDR_ANY) {
u->wildcard = 1;
}
break;
}
return NGX_OK; return NGX_OK;
} }
@@ -976,7 +989,7 @@ static ngx_int_t
ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u) ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
{ {
#if (NGX_HAVE_INET6) #if (NGX_HAVE_INET6)
u_char *p, *host, *port, *last, *uri; u_char *p, *host, *port, *last, *uri, *dash;
size_t len; size_t len;
ngx_int_t n; ngx_int_t n;
struct sockaddr_in6 *sin6; struct sockaddr_in6 *sin6;
@@ -1022,6 +1035,25 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
len = last - port; len = last - port;
if (u->listen) {
dash = ngx_strlchr(port, last, '-');
if (dash) {
dash++;
n = ngx_atoi(dash, last - dash);
if (n < 1 || n > 65535) {
u->err = "invalid port";
return NGX_ERROR;
}
u->last_port = (in_port_t) n;
len = dash - port - 1;
}
}
n = ngx_atoi(port, len); n = ngx_atoi(port, len);
if (n < 1 || n > 65535) { if (n < 1 || n > 65535) {
@@ -1029,10 +1061,15 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
return NGX_ERROR; return NGX_ERROR;
} }
if (u->last_port && n > u->last_port) {
u->err = "invalid port range";
return NGX_ERROR;
}
u->port = (in_port_t) n; u->port = (in_port_t) n;
sin6->sin6_port = htons((in_port_t) n); sin6->sin6_port = htons((in_port_t) n);
u->port_text.len = len; u->port_text.len = last - port;
u->port_text.data = port; u->port_text.data = port;
} else { } else {
@@ -1061,33 +1098,8 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
} }
u->family = AF_INET6; u->family = AF_INET6;
u->naddrs = 1;
u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t)); return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1);
if (u->addrs == NULL) {
return NGX_ERROR;
}
sin6 = ngx_pcalloc(pool, sizeof(struct sockaddr_in6));
if (sin6 == NULL) {
return NGX_ERROR;
}
ngx_memcpy(sin6, &u->sockaddr, sizeof(struct sockaddr_in6));
u->addrs[0].sockaddr = (struct sockaddr *) sin6;
u->addrs[0].socklen = sizeof(struct sockaddr_in6);
p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
if (p == NULL) {
return NGX_ERROR;
}
u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
&u->host, u->port) - p;
u->addrs[0].name.data = p;
return NGX_OK;
#else #else
@@ -1104,15 +1116,9 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
ngx_int_t ngx_int_t
ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u) ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
{ {
u_char *p, *host; u_char *host;
size_t len; ngx_uint_t n;
in_port_t port; struct addrinfo hints, *res, *rp;
ngx_uint_t i;
struct addrinfo hints, *res, *rp;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
port = htons(u->port);
host = ngx_alloc(u->host.len + 1, pool->log); host = ngx_alloc(u->host.len + 1, pool->log);
if (host == NULL) { if (host == NULL) {
@@ -1136,7 +1142,7 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
ngx_free(host); ngx_free(host);
for (i = 0, rp = res; rp != NULL; rp = rp->ai_next) { for (n = 0, rp = res; rp != NULL; rp = rp->ai_next) {
switch (rp->ai_family) { switch (rp->ai_family) {
@@ -1148,92 +1154,33 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
continue; continue;
} }
i++; n++;
} }
if (i == 0) { if (n == 0) {
u->err = "host not found"; u->err = "host not found";
goto failed; goto failed;
} }
/* MP: ngx_shared_palloc() */ /* MP: ngx_shared_palloc() */
u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
if (u->addrs == NULL) {
goto failed;
}
u->naddrs = i;
i = 0;
/* AF_INET addresses first */
for (rp = res; rp != NULL; rp = rp->ai_next) { for (rp = res; rp != NULL; rp = rp->ai_next) {
if (rp->ai_family != AF_INET) { switch (rp->ai_family) {
case AF_INET:
case AF_INET6:
break;
default:
continue; continue;
} }
sin = ngx_pcalloc(pool, rp->ai_addrlen); if (ngx_inet_add_addr(pool, u, rp->ai_addr, rp->ai_addrlen, n)
if (sin == NULL) { != NGX_OK)
{
goto failed; goto failed;
} }
ngx_memcpy(sin, rp->ai_addr, rp->ai_addrlen);
sin->sin_port = port;
u->addrs[i].sockaddr = (struct sockaddr *) sin;
u->addrs[i].socklen = rp->ai_addrlen;
len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
p = ngx_pnalloc(pool, len);
if (p == NULL) {
goto failed;
}
len = ngx_sock_ntop((struct sockaddr *) sin, rp->ai_addrlen, p, len, 1);
u->addrs[i].name.len = len;
u->addrs[i].name.data = p;
i++;
}
for (rp = res; rp != NULL; rp = rp->ai_next) {
if (rp->ai_family != AF_INET6) {
continue;
}
sin6 = ngx_pcalloc(pool, rp->ai_addrlen);
if (sin6 == NULL) {
goto failed;
}
ngx_memcpy(sin6, rp->ai_addr, rp->ai_addrlen);
sin6->sin6_port = port;
u->addrs[i].sockaddr = (struct sockaddr *) sin6;
u->addrs[i].socklen = rp->ai_addrlen;
len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;
p = ngx_pnalloc(pool, len);
if (p == NULL) {
goto failed;
}
len = ngx_sock_ntop((struct sockaddr *) sin6, rp->ai_addrlen, p,
len, 1);
u->addrs[i].name.len = len;
u->addrs[i].name.data = p;
i++;
} }
freeaddrinfo(res); freeaddrinfo(res);
@@ -1250,21 +1197,19 @@ failed:
ngx_int_t ngx_int_t
ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u) ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
{ {
u_char *p, *host; u_char *host;
size_t len; ngx_uint_t i, n;
in_port_t port;
in_addr_t in_addr;
ngx_uint_t i;
struct hostent *h; struct hostent *h;
struct sockaddr_in *sin; struct sockaddr_in sin;
/* AF_INET only */ /* AF_INET only */
port = htons(u->port); ngx_memzero(&sin, sizeof(struct sockaddr_in));
in_addr = ngx_inet_addr(u->host.data, u->host.len); sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ngx_inet_addr(u->host.data, u->host.len);
if (in_addr == INADDR_NONE) { if (sin.sin_addr.s_addr == INADDR_NONE) {
host = ngx_alloc(u->host.len + 1, pool->log); host = ngx_alloc(u->host.len + 1, pool->log);
if (host == NULL) { if (host == NULL) {
return NGX_ERROR; return NGX_ERROR;
@@ -1281,76 +1226,31 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
return NGX_ERROR; return NGX_ERROR;
} }
for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ } for (n = 0; h->h_addr_list[n] != NULL; n++) { /* void */ }
/* MP: ngx_shared_palloc() */ /* MP: ngx_shared_palloc() */
u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t)); for (i = 0; i < n; i++) {
if (u->addrs == NULL) { sin.sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
return NGX_ERROR;
}
u->naddrs = i; if (ngx_inet_add_addr(pool, u, (struct sockaddr *) &sin,
sizeof(struct sockaddr_in), n)
for (i = 0; i < u->naddrs; i++) { != NGX_OK)
{
sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
if (sin == NULL) {
return NGX_ERROR; return NGX_ERROR;
} }
sin->sin_family = AF_INET;
sin->sin_port = port;
sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
u->addrs[i].sockaddr = (struct sockaddr *) sin;
u->addrs[i].socklen = sizeof(struct sockaddr_in);
len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
p = ngx_pnalloc(pool, len);
if (p == NULL) {
return NGX_ERROR;
}
len = ngx_sock_ntop((struct sockaddr *) sin,
sizeof(struct sockaddr_in), p, len, 1);
u->addrs[i].name.len = len;
u->addrs[i].name.data = p;
} }
} else { } else {
/* MP: ngx_shared_palloc() */ /* MP: ngx_shared_palloc() */
u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t)); if (ngx_inet_add_addr(pool, u, (struct sockaddr *) &sin,
if (u->addrs == NULL) { sizeof(struct sockaddr_in), 1)
!= NGX_OK)
{
return NGX_ERROR; return NGX_ERROR;
} }
sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
if (sin == NULL) {
return NGX_ERROR;
}
u->naddrs = 1;
sin->sin_family = AF_INET;
sin->sin_port = port;
sin->sin_addr.s_addr = in_addr;
u->addrs[0].sockaddr = (struct sockaddr *) sin;
u->addrs[0].socklen = sizeof(struct sockaddr_in);
p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
if (p == NULL) {
return NGX_ERROR;
}
u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
&u->host, ntohs(port)) - p;
u->addrs[0].name.data = p;
} }
return NGX_OK; return NGX_OK;
@@ -1359,6 +1259,67 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
#endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */ #endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */
static ngx_int_t
ngx_inet_add_addr(ngx_pool_t *pool, ngx_url_t *u, struct sockaddr *sockaddr,
socklen_t socklen, ngx_uint_t total)
{
u_char *p;
size_t len;
ngx_uint_t i, nports;
ngx_addr_t *addr;
struct sockaddr *sa;
nports = u->last_port ? u->last_port - u->port + 1 : 1;
if (u->addrs == NULL) {
u->addrs = ngx_palloc(pool, total * nports * sizeof(ngx_addr_t));
if (u->addrs == NULL) {
return NGX_ERROR;
}
}
for (i = 0; i < nports; i++) {
sa = ngx_pcalloc(pool, socklen);
if (sa == NULL) {
return NGX_ERROR;
}
ngx_memcpy(sa, sockaddr, socklen);
ngx_inet_set_port(sa, u->port + i);
switch (sa->sa_family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65536") - 1;
break;
#endif
default: /* AF_INET */
len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
}
p = ngx_pnalloc(pool, len);
if (p == NULL) {
return NGX_ERROR;
}
len = ngx_sock_ntop(sa, socklen, p, len, 1);
addr = &u->addrs[u->naddrs++];
addr->sockaddr = sa;
addr->socklen = socklen;
addr->name.len = len;
addr->name.data = p;
}
return NGX_OK;
}
ngx_int_t ngx_int_t
ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1, ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1,
struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port) struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port)
@@ -1495,3 +1456,40 @@ ngx_inet_set_port(struct sockaddr *sa, in_port_t port)
break; break;
} }
} }
ngx_uint_t
ngx_inet_wildcard(struct sockaddr *sa)
{
struct sockaddr_in *sin;
#if (NGX_HAVE_INET6)
struct sockaddr_in6 *sin6;
#endif
switch (sa->sa_family) {
case AF_INET:
sin = (struct sockaddr_in *) sa;
if (sin->sin_addr.s_addr == INADDR_ANY) {
return 1;
}
break;
#if (NGX_HAVE_INET6)
case AF_INET6:
sin6 = (struct sockaddr_in6 *) sa;
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
return 1;
}
break;
#endif
}
return 0;
}
+2
View File
@@ -86,6 +86,7 @@ typedef struct {
in_port_t port; in_port_t port;
in_port_t default_port; in_port_t default_port;
in_port_t last_port;
int family; int family;
unsigned listen:1; unsigned listen:1;
@@ -125,6 +126,7 @@ ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1,
struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port); struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port);
in_port_t ngx_inet_get_port(struct sockaddr *sa); in_port_t ngx_inet_get_port(struct sockaddr *sa);
void ngx_inet_set_port(struct sockaddr *sa, in_port_t port); void ngx_inet_set_port(struct sockaddr *sa, in_port_t port);
ngx_uint_t ngx_inet_wildcard(struct sockaddr *sa);
#endif /* _NGX_INET_H_INCLUDED_ */ #endif /* _NGX_INET_H_INCLUDED_ */
+5 -9
View File
@@ -12,17 +12,13 @@
#include <ngx_config.h> #include <ngx_config.h>
#include <ngx_core.h> #include <ngx_core.h>
#include <openssl/md5.h>
typedef struct { typedef MD5_CTX ngx_md5_t;
uint64_t bytes;
uint32_t a, b, c, d;
u_char buffer[64];
} ngx_md5_t;
#define ngx_md5_init MD5_Init
void ngx_md5_init(ngx_md5_t *ctx); #define ngx_md5_update MD5_Update
void ngx_md5_update(ngx_md5_t *ctx, const void *data, size_t size); #define ngx_md5_final MD5_Final
void ngx_md5_final(u_char result[16], ngx_md5_t *ctx);
#endif /* _NGX_MD5_H_INCLUDED_ */ #endif /* _NGX_MD5_H_INCLUDED_ */
+60 -4
View File
@@ -126,6 +126,26 @@ ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in)
continue; continue;
} }
if (bsize < 0) {
ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
"negative size buf in output "
"t:%d r:%d f:%d %p %p-%p %p %O-%O",
ctx->in->buf->temporary,
ctx->in->buf->recycled,
ctx->in->buf->in_file,
ctx->in->buf->start,
ctx->in->buf->pos,
ctx->in->buf->last,
ctx->in->buf->file,
ctx->in->buf->file_pos,
ctx->in->buf->file_last);
ngx_debug_point();
return NGX_ERROR;
}
if (ngx_output_chain_as_is(ctx, ctx->in->buf)) { if (ngx_output_chain_as_is(ctx, ctx->in->buf)) {
/* move the chain link to the output chain */ /* move the chain link to the output chain */
@@ -665,7 +685,6 @@ ngx_chain_writer(void *data, ngx_chain_t *in)
for (size = 0; in; in = in->next) { for (size = 0; in; in = in->next) {
#if 1
if (ngx_buf_size(in->buf) == 0 && !ngx_buf_special(in->buf)) { if (ngx_buf_size(in->buf) == 0 && !ngx_buf_special(in->buf)) {
ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0, ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
@@ -685,7 +704,26 @@ ngx_chain_writer(void *data, ngx_chain_t *in)
continue; continue;
} }
#endif
if (ngx_buf_size(in->buf) < 0) {
ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
"negative size buf in chain writer "
"t:%d r:%d f:%d %p %p-%p %p %O-%O",
in->buf->temporary,
in->buf->recycled,
in->buf->in_file,
in->buf->start,
in->buf->pos,
in->buf->last,
in->buf->file,
in->buf->file_pos,
in->buf->file_last);
ngx_debug_point();
return NGX_ERROR;
}
size += ngx_buf_size(in->buf); size += ngx_buf_size(in->buf);
@@ -709,7 +747,6 @@ ngx_chain_writer(void *data, ngx_chain_t *in)
for (cl = ctx->out; cl; cl = cl->next) { for (cl = ctx->out; cl; cl = cl->next) {
#if 1
if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0, ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
@@ -729,7 +766,26 @@ ngx_chain_writer(void *data, ngx_chain_t *in)
continue; continue;
} }
#endif
if (ngx_buf_size(cl->buf) < 0) {
ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
"negative size buf in chain writer "
"t:%d r:%d f:%d %p %p-%p %p %O-%O",
cl->buf->temporary,
cl->buf->recycled,
cl->buf->in_file,
cl->buf->start,
cl->buf->pos,
cl->buf->last,
cl->buf->file,
cl->buf->file_pos,
cl->buf->file_last);
ngx_debug_point();
return NGX_ERROR;
}
size += ngx_buf_size(cl->buf); size += ngx_buf_size(cl->buf);
} }
+158 -79
View File
@@ -40,6 +40,10 @@ typedef struct {
} ngx_proxy_protocol_inet6_addrs_t; } ngx_proxy_protocol_inet6_addrs_t;
static u_char *ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p,
u_char *last, ngx_str_t *addr);
static u_char *ngx_proxy_protocol_read_port(u_char *p, u_char *last,
in_port_t *port, u_char sep);
static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf,
u_char *last); u_char *last);
@@ -47,9 +51,9 @@ static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf,
u_char * u_char *
ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last) ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
{ {
size_t len; size_t len;
u_char ch, *p, *addr, *port; u_char *p;
ngx_int_t n; ngx_proxy_protocol_t *pp;
static const u_char signature[] = "\r\n\r\n\0\r\nQUIT\n"; static const u_char signature[] = "\r\n\r\n\0\r\nQUIT\n";
@@ -83,73 +87,47 @@ ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
} }
p += 5; p += 5;
addr = p;
for ( ;; ) { pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t));
if (p == last) { if (pp == NULL) {
goto invalid;
}
ch = *p++;
if (ch == ' ') {
break;
}
if (ch != ':' && ch != '.'
&& (ch < 'a' || ch > 'f')
&& (ch < 'A' || ch > 'F')
&& (ch < '0' || ch > '9'))
{
goto invalid;
}
}
len = p - addr - 1;
c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, len);
if (c->proxy_protocol_addr.data == NULL) {
return NULL; return NULL;
} }
ngx_memcpy(c->proxy_protocol_addr.data, addr, len); p = ngx_proxy_protocol_read_addr(c, p, last, &pp->src_addr);
c->proxy_protocol_addr.len = len; if (p == NULL) {
for ( ;; ) {
if (p == last) {
goto invalid;
}
if (*p++ == ' ') {
break;
}
}
port = p;
for ( ;; ) {
if (p == last) {
goto invalid;
}
if (*p++ == ' ') {
break;
}
}
len = p - port - 1;
n = ngx_atoi(port, len);
if (n < 0 || n > 65535) {
goto invalid; goto invalid;
} }
c->proxy_protocol_port = (in_port_t) n; p = ngx_proxy_protocol_read_addr(c, p, last, &pp->dst_addr);
if (p == NULL) {
goto invalid;
}
ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0, p = ngx_proxy_protocol_read_port(p, last, &pp->src_port, ' ');
"PROXY protocol address: %V %d", &c->proxy_protocol_addr, if (p == NULL) {
c->proxy_protocol_port); goto invalid;
}
p = ngx_proxy_protocol_read_port(p, last, &pp->dst_port, CR);
if (p == NULL) {
goto invalid;
}
if (p == last) {
goto invalid;
}
if (*p++ != LF) {
goto invalid;
}
ngx_log_debug4(NGX_LOG_DEBUG_CORE, c->log, 0,
"PROXY protocol src: %V %d, dst: %V %d",
&pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port);
c->proxy_protocol = pp;
return p;
skip: skip:
@@ -168,6 +146,82 @@ invalid:
} }
static u_char *
ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p, u_char *last,
ngx_str_t *addr)
{
size_t len;
u_char ch, *pos;
pos = p;
for ( ;; ) {
if (p == last) {
return NULL;
}
ch = *p++;
if (ch == ' ') {
break;
}
if (ch != ':' && ch != '.'
&& (ch < 'a' || ch > 'f')
&& (ch < 'A' || ch > 'F')
&& (ch < '0' || ch > '9'))
{
return NULL;
}
}
len = p - pos - 1;
addr->data = ngx_pnalloc(c->pool, len);
if (addr->data == NULL) {
return NULL;
}
ngx_memcpy(addr->data, pos, len);
addr->len = len;
return p;
}
static u_char *
ngx_proxy_protocol_read_port(u_char *p, u_char *last, in_port_t *port,
u_char sep)
{
size_t len;
u_char *pos;
ngx_int_t n;
pos = p;
for ( ;; ) {
if (p == last) {
return NULL;
}
if (*p++ == sep) {
break;
}
}
len = p - pos - 1;
n = ngx_atoi(pos, len);
if (n < 0 || n > 65535) {
return NULL;
}
*port = (in_port_t) n;
return p;
}
u_char * u_char *
ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last) ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last)
{ {
@@ -219,7 +273,8 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
size_t len; size_t len;
socklen_t socklen; socklen_t socklen;
ngx_uint_t version, command, family, transport; ngx_uint_t version, command, family, transport;
ngx_sockaddr_t sockaddr; ngx_sockaddr_t src_sockaddr, dst_sockaddr;
ngx_proxy_protocol_t *pp;
ngx_proxy_protocol_header_t *header; ngx_proxy_protocol_header_t *header;
ngx_proxy_protocol_inet_addrs_t *in; ngx_proxy_protocol_inet_addrs_t *in;
#if (NGX_HAVE_INET6) #if (NGX_HAVE_INET6)
@@ -266,6 +321,11 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
return end; return end;
} }
pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t));
if (pp == NULL) {
return NULL;
}
family = header->family_transport >> 4; family = header->family_transport >> 4;
switch (family) { switch (family) {
@@ -278,11 +338,16 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
in = (ngx_proxy_protocol_inet_addrs_t *) buf; in = (ngx_proxy_protocol_inet_addrs_t *) buf;
sockaddr.sockaddr_in.sin_family = AF_INET; src_sockaddr.sockaddr_in.sin_family = AF_INET;
sockaddr.sockaddr_in.sin_port = 0; src_sockaddr.sockaddr_in.sin_port = 0;
memcpy(&sockaddr.sockaddr_in.sin_addr, in->src_addr, 4); memcpy(&src_sockaddr.sockaddr_in.sin_addr, in->src_addr, 4);
c->proxy_protocol_port = ngx_proxy_protocol_parse_uint16(in->src_port); dst_sockaddr.sockaddr_in.sin_family = AF_INET;
dst_sockaddr.sockaddr_in.sin_port = 0;
memcpy(&dst_sockaddr.sockaddr_in.sin_addr, in->dst_addr, 4);
pp->src_port = ngx_proxy_protocol_parse_uint16(in->src_port);
pp->dst_port = ngx_proxy_protocol_parse_uint16(in->dst_port);
socklen = sizeof(struct sockaddr_in); socklen = sizeof(struct sockaddr_in);
@@ -300,11 +365,16 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
in6 = (ngx_proxy_protocol_inet6_addrs_t *) buf; in6 = (ngx_proxy_protocol_inet6_addrs_t *) buf;
sockaddr.sockaddr_in6.sin6_family = AF_INET6; src_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
sockaddr.sockaddr_in6.sin6_port = 0; src_sockaddr.sockaddr_in6.sin6_port = 0;
memcpy(&sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16); memcpy(&src_sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16);
c->proxy_protocol_port = ngx_proxy_protocol_parse_uint16(in6->src_port); dst_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
dst_sockaddr.sockaddr_in6.sin6_port = 0;
memcpy(&dst_sockaddr.sockaddr_in6.sin6_addr, in6->dst_addr, 16);
pp->src_port = ngx_proxy_protocol_parse_uint16(in6->src_port);
pp->dst_port = ngx_proxy_protocol_parse_uint16(in6->dst_port);
socklen = sizeof(struct sockaddr_in6); socklen = sizeof(struct sockaddr_in6);
@@ -321,23 +391,32 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
return end; return end;
} }
c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN); pp->src_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
if (c->proxy_protocol_addr.data == NULL) { if (pp->src_addr.data == NULL) {
return NULL; return NULL;
} }
c->proxy_protocol_addr.len = ngx_sock_ntop(&sockaddr.sockaddr, socklen, pp->src_addr.len = ngx_sock_ntop(&src_sockaddr.sockaddr, socklen,
c->proxy_protocol_addr.data, pp->src_addr.data, NGX_SOCKADDR_STRLEN, 0);
NGX_SOCKADDR_STRLEN, 0);
ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0, pp->dst_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
"PROXY protocol v2 address: %V %d", &c->proxy_protocol_addr, if (pp->dst_addr.data == NULL) {
c->proxy_protocol_port); return NULL;
}
pp->dst_addr.len = ngx_sock_ntop(&dst_sockaddr.sockaddr, socklen,
pp->dst_addr.data, NGX_SOCKADDR_STRLEN, 0);
ngx_log_debug4(NGX_LOG_DEBUG_CORE, c->log, 0,
"PROXY protocol v2 src: %V %d, dst: %V %d",
&pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port);
if (buf < end) { if (buf < end) {
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
"PROXY protocol v2 %z bytes of tlv ignored", end - buf); "PROXY protocol v2 %z bytes of tlv ignored", end - buf);
} }
c->proxy_protocol = pp;
return end; return end;
} }
+8
View File
@@ -16,6 +16,14 @@
#define NGX_PROXY_PROTOCOL_MAX_HEADER 107 #define NGX_PROXY_PROTOCOL_MAX_HEADER 107
struct ngx_proxy_protocol_s {
ngx_str_t src_addr;
ngx_str_t dst_addr;
in_port_t src_port;
in_port_t dst_port;
};
u_char *ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf,
u_char *last); u_char *last);
u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf,
+1 -6
View File
@@ -174,12 +174,7 @@ ngx_rbtree_delete(ngx_rbtree_t *tree, ngx_rbtree_node_t *node)
} else { } else {
subst = ngx_rbtree_min(node->right, sentinel); subst = ngx_rbtree_min(node->right, sentinel);
temp = subst->right;
if (subst->left != sentinel) {
temp = subst->left;
} else {
temp = subst->right;
}
} }
if (subst == *root) { if (subst == *root) {
+11 -2
View File
@@ -972,7 +972,8 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
name = ngx_resolver_dup(r, rn->name, rn->nlen); name = ngx_resolver_dup(r, rn->name, rn->nlen);
if (name == NULL) { if (name == NULL) {
goto failed; ngx_resolver_free(r, ctx);
return NGX_ERROR;
} }
ctx->name.len = rn->nlen; ctx->name.len = rn->nlen;
@@ -4266,7 +4267,15 @@ ngx_resolver_report_srv(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
} }
if (naddrs == 0) { if (naddrs == 0) {
ctx->state = NGX_RESOLVE_NXDOMAIN; ctx->state = srvs[0].state;
for (i = 0; i < nsrvs; i++) {
if (srvs[i].state == NGX_RESOLVE_NXDOMAIN) {
ctx->state = NGX_RESOLVE_NXDOMAIN;
break;
}
}
ctx->valid = ngx_time() + (r->valid ? r->valid : 10); ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
ctx->handler(ctx); ctx->handler(ctx);
+5 -9
View File
@@ -12,17 +12,13 @@
#include <ngx_config.h> #include <ngx_config.h>
#include <ngx_core.h> #include <ngx_core.h>
#include <openssl/sha.h>
typedef struct { typedef SHA_CTX ngx_sha1_t;
uint64_t bytes;
uint32_t a, b, c, d, e, f;
u_char buffer[64];
} ngx_sha1_t;
#define ngx_sha1_init SHA1_Init
void ngx_sha1_init(ngx_sha1_t *ctx); #define ngx_sha1_update SHA1_Update
void ngx_sha1_update(ngx_sha1_t *ctx, const void *data, size_t size); #define ngx_sha1_final SHA1_Final
void ngx_sha1_final(u_char result[20], ngx_sha1_t *ctx);
#endif /* _NGX_SHA1_H_INCLUDED_ */ #endif /* _NGX_SHA1_H_INCLUDED_ */
+1 -2
View File
@@ -635,10 +635,9 @@ ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p)
goto fail; goto fail;
} }
n = ((u_char *) p - pool->start) >> ngx_pagesize_shift;
size = slab & ~NGX_SLAB_PAGE_START; size = slab & ~NGX_SLAB_PAGE_START;
ngx_slab_free_pages(pool, &pool->pages[n], size); ngx_slab_free_pages(pool, page, size);
ngx_slab_junk(p, size << ngx_pagesize_shift); ngx_slab_junk(p, size << ngx_pagesize_shift);
+9 -1
View File
@@ -1381,7 +1381,7 @@ ngx_utf8_length(u_char *p, size_t n)
continue; continue;
} }
if (ngx_utf8_decode(&p, n) > 0x10ffff) { if (ngx_utf8_decode(&p, last - p) > 0x10ffff) {
/* invalid UTF-8 */ /* invalid UTF-8 */
return n; return n;
} }
@@ -2013,6 +2013,14 @@ ngx_sort(void *base, size_t n, size_t size,
} }
void
ngx_explicit_memzero(void *buf, size_t n)
{
ngx_memzero(buf, n);
ngx_memory_barrier();
}
#if (NGX_MEMCPY_LIMIT) #if (NGX_MEMCPY_LIMIT)
void * void *
+2
View File
@@ -88,6 +88,8 @@ ngx_strlchr(u_char *p, u_char *last, u_char c)
#define ngx_memzero(buf, n) (void) memset(buf, 0, n) #define ngx_memzero(buf, n) (void) memset(buf, 0, n)
#define ngx_memset(buf, c, n) (void) memset(buf, c, n) #define ngx_memset(buf, c, n) (void) memset(buf, c, n)
void ngx_explicit_memzero(void *buf, size_t n);
#if (NGX_MEMCPY_LIMIT) #if (NGX_MEMCPY_LIMIT)
+1
View File
@@ -495,6 +495,7 @@ ngx_devpoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
if ((revents & POLLIN) && rev->active) { if ((revents & POLLIN) && rev->active) {
rev->ready = 1; rev->ready = 1;
rev->available = -1;
if (flags & NGX_POST_EVENTS) { if (flags & NGX_POST_EVENTS) {
queue = rev->accept ? &ngx_posted_accept_events queue = rev->accept ? &ngx_posted_accept_events
+1 -2
View File
@@ -886,11 +886,10 @@ ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
if (revents & EPOLLRDHUP) { if (revents & EPOLLRDHUP) {
rev->pending_eof = 1; rev->pending_eof = 1;
} }
rev->available = 1;
#endif #endif
rev->ready = 1; rev->ready = 1;
rev->available = -1;
if (flags & NGX_POST_EVENTS) { if (flags & NGX_POST_EVENTS) {
queue = rev->accept ? &ngx_posted_accept_events queue = rev->accept ? &ngx_posted_accept_events
+1 -2
View File
@@ -250,9 +250,7 @@ ngx_eventport_init(ngx_cycle_t *cycle, ngx_msec_t timer)
ngx_memzero(&sev, sizeof(struct sigevent)); ngx_memzero(&sev, sizeof(struct sigevent));
sev.sigev_notify = SIGEV_PORT; sev.sigev_notify = SIGEV_PORT;
#if !(NGX_TEST_BUILD_EVENTPORT)
sev.sigev_value.sival_ptr = &pn; sev.sigev_value.sival_ptr = &pn;
#endif
if (timer_create(CLOCK_REALTIME, &sev, &event_timer) == -1) { if (timer_create(CLOCK_REALTIME, &sev, &event_timer) == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
@@ -561,6 +559,7 @@ ngx_eventport_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
if (revents & POLLIN) { if (revents & POLLIN) {
rev->ready = 1; rev->ready = 1;
rev->available = -1;
if (flags & NGX_POST_EVENTS) { if (flags & NGX_POST_EVENTS) {
queue = rev->accept ? &ngx_posted_accept_events queue = rev->accept ? &ngx_posted_accept_events
+2 -1
View File
@@ -84,7 +84,7 @@ ngx_poll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
} }
if (event_list) { if (event_list) {
ngx_memcpy(list, event_list, sizeof(ngx_event_t *) * nevents); ngx_memcpy(list, event_list, sizeof(struct pollfd) * nevents);
ngx_free(event_list); ngx_free(event_list);
} }
@@ -370,6 +370,7 @@ ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
ev = c->read; ev = c->read;
ev->ready = 1; ev->ready = 1;
ev->available = -1;
queue = ev->accept ? &ngx_posted_accept_events queue = ev->accept ? &ngx_posted_accept_events
: &ngx_posted_events; : &ngx_posted_events;
+1
View File
@@ -330,6 +330,7 @@ ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
if (found) { if (found) {
ev->ready = 1; ev->ready = 1;
ev->available = -1;
queue = ev->accept ? &ngx_posted_accept_events queue = ev->accept ? &ngx_posted_accept_events
: &ngx_posted_events; : &ngx_posted_events;
+436
View File
@@ -0,0 +1,436 @@
/*
* Copyright (C) Igor Sysoev
* Copyright (C) Maxim Dounin
* Copyright (C) Nginx, Inc.
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
static ngx_int_t ngx_poll_init(ngx_cycle_t *cycle, ngx_msec_t timer);
static void ngx_poll_done(ngx_cycle_t *cycle);
static ngx_int_t ngx_poll_add_event(ngx_event_t *ev, ngx_int_t event,
ngx_uint_t flags);
static ngx_int_t ngx_poll_del_event(ngx_event_t *ev, ngx_int_t event,
ngx_uint_t flags);
static ngx_int_t ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
ngx_uint_t flags);
static char *ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf);
static struct pollfd *event_list;
static ngx_connection_t **event_index;
static ngx_uint_t nevents;
static ngx_str_t poll_name = ngx_string("poll");
static ngx_event_module_t ngx_poll_module_ctx = {
&poll_name,
NULL, /* create configuration */
ngx_poll_init_conf, /* init configuration */
{
ngx_poll_add_event, /* add an event */
ngx_poll_del_event, /* delete an event */
ngx_poll_add_event, /* enable an event */
ngx_poll_del_event, /* disable an event */
NULL, /* add an connection */
NULL, /* delete an connection */
NULL, /* trigger a notify */
ngx_poll_process_events, /* process the events */
ngx_poll_init, /* init the events */
ngx_poll_done /* done the events */
}
};
ngx_module_t ngx_poll_module = {
NGX_MODULE_V1,
&ngx_poll_module_ctx, /* module context */
NULL, /* module directives */
NGX_EVENT_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static ngx_int_t
ngx_poll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
{
struct pollfd *list;
ngx_connection_t **index;
if (event_list == NULL) {
nevents = 0;
}
if (ngx_process >= NGX_PROCESS_WORKER
|| cycle->old_cycle == NULL
|| cycle->old_cycle->connection_n < cycle->connection_n)
{
list = ngx_alloc(sizeof(struct pollfd) * cycle->connection_n,
cycle->log);
if (list == NULL) {
return NGX_ERROR;
}
if (event_list) {
ngx_memcpy(list, event_list, sizeof(struct pollfd) * nevents);
ngx_free(event_list);
}
event_list = list;
index = ngx_alloc(sizeof(ngx_connection_t *) * cycle->connection_n,
cycle->log);
if (index == NULL) {
return NGX_ERROR;
}
if (event_index) {
ngx_memcpy(index, event_index,
sizeof(ngx_connection_t *) * nevents);
ngx_free(event_index);
}
event_index = index;
}
ngx_io = ngx_os_io;
ngx_event_actions = ngx_poll_module_ctx.actions;
ngx_event_flags = NGX_USE_LEVEL_EVENT;
return NGX_OK;
}
static void
ngx_poll_done(ngx_cycle_t *cycle)
{
ngx_free(event_list);
ngx_free(event_index);
event_list = NULL;
event_index = NULL;
}
static ngx_int_t
ngx_poll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
{
ngx_event_t *e;
ngx_connection_t *c;
c = ev->data;
ev->active = 1;
if (ev->index != NGX_INVALID_INDEX) {
ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
"poll event fd:%d ev:%i is already set", c->fd, event);
return NGX_OK;
}
if (event == NGX_READ_EVENT) {
e = c->write;
#if (NGX_READ_EVENT != POLLIN)
event = POLLIN;
#endif
} else {
e = c->read;
#if (NGX_WRITE_EVENT != POLLOUT)
event = POLLOUT;
#endif
}
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
"poll add event: fd:%d ev:%i", c->fd, event);
if (e == NULL || e->index == NGX_INVALID_INDEX) {
event_list[nevents].fd = c->fd;
event_list[nevents].events = (short) event;
event_list[nevents].revents = 0;
event_index[nevents] = c;
ev->index = nevents;
nevents++;
} else {
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
"poll add index: %i", e->index);
event_list[e->index].events |= (short) event;
ev->index = e->index;
}
return NGX_OK;
}
static ngx_int_t
ngx_poll_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
{
ngx_event_t *e;
ngx_connection_t *c;
c = ev->data;
ev->active = 0;
if (ev->index == NGX_INVALID_INDEX) {
ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
"poll event fd:%d ev:%i is already deleted",
c->fd, event);
return NGX_OK;
}
if (event == NGX_READ_EVENT) {
e = c->write;
#if (NGX_READ_EVENT != POLLIN)
event = POLLIN;
#endif
} else {
e = c->read;
#if (NGX_WRITE_EVENT != POLLOUT)
event = POLLOUT;
#endif
}
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
"poll del event: fd:%d ev:%i", c->fd, event);
if (e == NULL || e->index == NGX_INVALID_INDEX) {
nevents--;
if (ev->index < nevents) {
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
"index: copy event %ui to %i", nevents, ev->index);
event_list[ev->index] = event_list[nevents];
event_index[ev->index] = event_index[nevents];
c = event_index[ev->index];
if (c->fd == (ngx_socket_t) -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
"unexpected last event");
} else {
if (c->read->index == nevents) {
c->read->index = ev->index;
}
if (c->write->index == nevents) {
c->write->index = ev->index;
}
}
}
} else {
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
"poll del index: %i", e->index);
event_list[e->index].events &= (short) ~event;
}
ev->index = NGX_INVALID_INDEX;
return NGX_OK;
}
static ngx_int_t
ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
{
int ready, revents;
ngx_err_t err;
ngx_uint_t i, found;
ngx_event_t *ev;
ngx_queue_t *queue;
ngx_connection_t *c;
/* NGX_TIMER_INFINITE == INFTIM */
#if (NGX_DEBUG0)
if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
for (i = 0; i < nevents; i++) {
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"poll: %ui: fd:%d ev:%04Xd",
i, event_list[i].fd, event_list[i].events);
}
}
#endif
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "poll timer: %M", timer);
ready = WSAPoll(event_list, (u_int) nevents, (int) timer);
err = (ready == -1) ? ngx_errno : 0;
if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
ngx_time_update();
}
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"poll ready %d of %ui", ready, nevents);
if (err) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "WSAPoll() failed");
return NGX_ERROR;
}
if (ready == 0) {
if (timer != NGX_TIMER_INFINITE) {
return NGX_OK;
}
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
"WSAPoll() returned no events without timeout");
return NGX_ERROR;
}
for (i = 0; i < nevents && ready; i++) {
revents = event_list[i].revents;
#if 1
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"poll: %ui: fd:%d ev:%04Xd rev:%04Xd",
i, event_list[i].fd, event_list[i].events, revents);
#else
if (revents) {
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"poll: %ui: fd:%d ev:%04Xd rev:%04Xd",
i, event_list[i].fd, event_list[i].events, revents);
}
#endif
if (revents & POLLNVAL) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
"poll() error fd:%d ev:%04Xd rev:%04Xd",
event_list[i].fd, event_list[i].events, revents);
}
if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
"strange poll() events fd:%d ev:%04Xd rev:%04Xd",
event_list[i].fd, event_list[i].events, revents);
}
if (event_list[i].fd == (ngx_socket_t) -1) {
/*
* the disabled event, a workaround for our possible bug,
* see the comment below
*/
continue;
}
c = event_index[i];
if (c->fd == (ngx_socket_t) -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unexpected event");
/*
* it is certainly our fault and it should be investigated,
* in the meantime we disable this event to avoid a CPU spinning
*/
if (i == nevents - 1) {
nevents--;
} else {
event_list[i].fd = (ngx_socket_t) -1;
}
continue;
}
if (revents & (POLLERR|POLLHUP|POLLNVAL)) {
/*
* if the error events were returned, add POLLIN and POLLOUT
* to handle the events at least in one active handler
*/
revents |= POLLIN|POLLOUT;
}
found = 0;
if ((revents & POLLIN) && c->read->active) {
found = 1;
ev = c->read;
ev->ready = 1;
ev->available = -1;
queue = ev->accept ? &ngx_posted_accept_events
: &ngx_posted_events;
ngx_post_event(ev, queue);
}
if ((revents & POLLOUT) && c->write->active) {
found = 1;
ev = c->write;
ev->ready = 1;
ngx_post_event(ev, &ngx_posted_events);
}
if (found) {
ready--;
continue;
}
}
if (ready != 0) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "poll ready != events");
}
return NGX_OK;
}
static char *
ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf)
{
ngx_event_conf_t *ecf;
ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
if (ecf->use != ngx_poll_module.ctx_index) {
return NGX_CONF_OK;
}
#if (NGX_LOAD_WSAPOLL)
if (!ngx_have_wsapoll) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
"poll is not available on this platform");
return NGX_CONF_ERROR;
}
#endif
return NGX_CONF_OK;
}
+14 -4
View File
@@ -26,6 +26,7 @@ static fd_set master_read_fd_set;
static fd_set master_write_fd_set; static fd_set master_write_fd_set;
static fd_set work_read_fd_set; static fd_set work_read_fd_set;
static fd_set work_write_fd_set; static fd_set work_write_fd_set;
static fd_set work_except_fd_set;
static ngx_uint_t max_read; static ngx_uint_t max_read;
static ngx_uint_t max_write; static ngx_uint_t max_write;
@@ -251,9 +252,11 @@ ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
work_read_fd_set = master_read_fd_set; work_read_fd_set = master_read_fd_set;
work_write_fd_set = master_write_fd_set; work_write_fd_set = master_write_fd_set;
work_except_fd_set = master_write_fd_set;
if (max_read || max_write) { if (max_read || max_write) {
ready = select(0, &work_read_fd_set, &work_write_fd_set, NULL, tp); ready = select(0, &work_read_fd_set, &work_write_fd_set,
&work_except_fd_set, tp);
} else { } else {
@@ -306,14 +309,20 @@ ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
if (ev->write) { if (ev->write) {
if (FD_ISSET(c->fd, &work_write_fd_set)) { if (FD_ISSET(c->fd, &work_write_fd_set)) {
found = 1; found++;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"select write %d", c->fd); "select write %d", c->fd);
} }
if (FD_ISSET(c->fd, &work_except_fd_set)) {
found++;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"select except %d", c->fd);
}
} else { } else {
if (FD_ISSET(c->fd, &work_read_fd_set)) { if (FD_ISSET(c->fd, &work_read_fd_set)) {
found = 1; found++;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"select read %d", c->fd); "select read %d", c->fd);
} }
@@ -321,13 +330,14 @@ ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
if (found) { if (found) {
ev->ready = 1; ev->ready = 1;
ev->available = -1;
queue = ev->accept ? &ngx_posted_accept_events queue = ev->accept ? &ngx_posted_accept_events
: &ngx_posted_events; : &ngx_posted_events;
ngx_post_event(ev, queue); ngx_post_event(ev, queue);
nready++; nready += found;
} }
} }
+6
View File
@@ -237,6 +237,11 @@ ngx_process_events_and_timers(ngx_cycle_t *cycle)
} }
} }
if (!ngx_queue_empty(&ngx_posted_next_events)) {
ngx_event_move_posted_next(cycle);
timer = 0;
}
delta = ngx_current_msec; delta = ngx_current_msec;
(void) ngx_process_events(cycle, timer, flags); (void) ngx_process_events(cycle, timer, flags);
@@ -639,6 +644,7 @@ ngx_event_process_init(ngx_cycle_t *cycle)
#endif #endif
ngx_queue_init(&ngx_posted_accept_events); ngx_queue_init(&ngx_posted_accept_events);
ngx_queue_init(&ngx_posted_next_events);
ngx_queue_init(&ngx_posted_events); ngx_queue_init(&ngx_posted_events);
if (ngx_event_timer_init(cycle->log) == NGX_ERROR) { if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
+3 -9
View File
@@ -91,21 +91,14 @@ struct ngx_event_s {
* write: available space in buffer when event is ready * write: available space in buffer when event is ready
* or lowat when event is set with NGX_LOWAT_EVENT flag * or lowat when event is set with NGX_LOWAT_EVENT flag
* *
* epoll with EPOLLRDHUP:
* accept: 1 if accept many, 0 otherwise
* read: 1 if there can be data to read, 0 otherwise
*
* iocp: TODO * iocp: TODO
* *
* otherwise: * otherwise:
* accept: 1 if accept many, 0 otherwise * accept: 1 if accept many, 0 otherwise
* read: bytes to read when event is ready, -1 if not known
*/ */
#if (NGX_HAVE_KQUEUE) || (NGX_HAVE_IOCP)
int available; int available;
#else
unsigned available:1;
#endif
ngx_event_handler_pt handler; ngx_event_handler_pt handler;
@@ -499,7 +492,7 @@ extern ngx_module_t ngx_event_core_module;
#define ngx_event_get_conf(conf_ctx, module) \ #define ngx_event_get_conf(conf_ctx, module) \
(*(ngx_get_conf(conf_ctx, ngx_events_module))) [module.ctx_index]; (*(ngx_get_conf(conf_ctx, ngx_events_module))) [module.ctx_index]
@@ -507,6 +500,7 @@ void ngx_event_accept(ngx_event_t *ev);
void ngx_event_recvmsg(ngx_event_t *ev); void ngx_event_recvmsg(ngx_event_t *ev);
void ngx_udp_rbtree_insert_value(ngx_rbtree_node_t *temp, void ngx_udp_rbtree_insert_value(ngx_rbtree_node_t *temp,
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
void ngx_delete_udp_connection(void *data);
ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t *cycle); ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t *cycle);
ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle); ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle);
u_char *ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len); u_char *ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len);
+1
View File
@@ -63,6 +63,7 @@ struct ngx_peer_connection_s {
unsigned cached:1; unsigned cached:1;
unsigned transparent:1; unsigned transparent:1;
unsigned so_keepalive:1; unsigned so_keepalive:1;
unsigned down:1;
/* ngx_connection_log_error_e */ /* ngx_connection_log_error_e */
unsigned log_error:2; unsigned log_error:2;
+637 -232
View File
@@ -18,6 +18,10 @@ typedef struct {
} ngx_openssl_conf_t; } ngx_openssl_conf_t;
static X509 *ngx_ssl_load_certificate(ngx_pool_t *pool, char **err,
ngx_str_t *cert, STACK_OF(X509) **chain);
static EVP_PKEY *ngx_ssl_load_certificate_key(ngx_pool_t *pool, char **err,
ngx_str_t *key, ngx_array_t *passwords);
static int ngx_ssl_password_callback(char *buf, int size, int rwflag, static int ngx_ssl_password_callback(char *buf, int size, int rwflag,
void *userdata); void *userdata);
static int ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store); static int ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
@@ -50,7 +54,7 @@ static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
static void ngx_ssl_clear_error(ngx_log_t *log); static void ngx_ssl_clear_error(ngx_log_t *log);
static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl, static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl,
ngx_str_t *sess_ctx); ngx_str_t *sess_ctx, ngx_array_t *certificates);
static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn,
ngx_ssl_session_t *sess); ngx_ssl_session_t *sess);
static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
@@ -68,6 +72,7 @@ static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx, unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
HMAC_CTX *hctx, int enc); HMAC_CTX *hctx, int enc);
static void ngx_ssl_session_ticket_keys_cleanup(void *data);
#endif #endif
#ifndef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT #ifndef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
@@ -125,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;
@@ -159,7 +165,6 @@ ngx_ssl_init(ngx_log_t *log)
#endif #endif
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef SSL_OP_NO_COMPRESSION #ifndef SSL_OP_NO_COMPRESSION
{ {
/* /*
@@ -176,7 +181,6 @@ ngx_ssl_init(ngx_log_t *log)
(void) sk_SSL_COMP_pop(ssl_comp_methods); (void) sk_SSL_COMP_pop(ssl_comp_methods);
} }
} }
#endif
#endif #endif
ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
@@ -210,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) {
@@ -345,6 +356,11 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
} }
#endif #endif
#ifdef SSL_CTX_set_min_proto_version
SSL_CTX_set_min_proto_version(ssl->ctx, 0);
SSL_CTX_set_max_proto_version(ssl->ctx, TLS1_2_VERSION);
#endif
#ifdef TLS1_3_VERSION #ifdef TLS1_3_VERSION
SSL_CTX_set_min_proto_version(ssl->ctx, 0); SSL_CTX_set_min_proto_version(ssl->ctx, 0);
SSL_CTX_set_max_proto_version(ssl->ctx, TLS1_3_VERSION); SSL_CTX_set_max_proto_version(ssl->ctx, TLS1_3_VERSION);
@@ -362,6 +378,10 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_ANTI_REPLAY); SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_ANTI_REPLAY);
#endif #endif
#ifdef SSL_OP_NO_CLIENT_RENEGOTIATION
SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_CLIENT_RENEGOTIATION);
#endif
#ifdef SSL_MODE_RELEASE_BUFFERS #ifdef SSL_MODE_RELEASE_BUFFERS
SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS); SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS);
#endif #endif
@@ -409,34 +429,19 @@ ngx_int_t
ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
ngx_str_t *key, ngx_array_t *passwords) ngx_str_t *key, ngx_array_t *passwords)
{ {
BIO *bio; char *err;
X509 *x509; X509 *x509;
u_long n; EVP_PKEY *pkey;
ngx_str_t *pwd; STACK_OF(X509) *chain;
ngx_uint_t tries;
if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) { x509 = ngx_ssl_load_certificate(cf->pool, &err, cert, &chain);
return NGX_ERROR;
}
/*
* we can't use SSL_CTX_use_certificate_chain_file() as it doesn't
* allow to access certificate later from SSL_CTX, so we reimplement
* it here
*/
bio = BIO_new_file((char *) cert->data, "r");
if (bio == NULL) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"BIO_new_file(\"%s\") failed", cert->data);
return NGX_ERROR;
}
x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
if (x509 == NULL) { if (x509 == NULL) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, if (err != NULL) {
"PEM_read_bio_X509_AUX(\"%s\") failed", cert->data); ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
BIO_free(bio); "cannot load certificate \"%s\": %s",
cert->data, err);
}
return NGX_ERROR; return NGX_ERROR;
} }
@@ -444,7 +449,7 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_use_certificate(\"%s\") failed", cert->data); "SSL_CTX_use_certificate(\"%s\") failed", cert->data);
X509_free(x509); X509_free(x509);
BIO_free(bio); sk_X509_pop_free(chain, X509_free);
return NGX_ERROR; return NGX_ERROR;
} }
@@ -453,7 +458,7 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
{ {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed");
X509_free(x509); X509_free(x509);
BIO_free(bio); sk_X509_pop_free(chain, X509_free);
return NGX_ERROR; return NGX_ERROR;
} }
@@ -463,26 +468,211 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
{ {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed");
X509_free(x509); X509_free(x509);
BIO_free(bio); sk_X509_pop_free(chain, X509_free);
return NGX_ERROR; return NGX_ERROR;
} }
if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509) if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509) == 0) {
== 0)
{
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_set_ex_data() failed"); "SSL_CTX_set_ex_data() failed");
X509_free(x509); X509_free(x509);
BIO_free(bio); sk_X509_pop_free(chain, X509_free);
return NGX_ERROR; return NGX_ERROR;
} }
/* read rest of the chain */ /*
* Note that x509 is not freed here, but will be instead freed in
* ngx_ssl_cleanup_ctx(). This is because we need to preserve all
* certificates to be able to iterate all of them through exdata
* (ngx_ssl_certificate_index, ngx_ssl_next_certificate_index),
* while OpenSSL can free a certificate if it is replaced with another
* certificate of the same type.
*/
#ifdef SSL_CTX_set0_chain
if (SSL_CTX_set0_chain(ssl->ctx, chain) == 0) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_set0_chain(\"%s\") failed", cert->data);
sk_X509_pop_free(chain, X509_free);
return NGX_ERROR;
}
#else
{
int n;
/* SSL_CTX_set0_chain() is only available in OpenSSL 1.0.2+ */
n = sk_X509_num(chain);
while (n--) {
x509 = sk_X509_shift(chain);
if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_add_extra_chain_cert(\"%s\") failed",
cert->data);
sk_X509_pop_free(chain, X509_free);
return NGX_ERROR;
}
}
sk_X509_free(chain);
}
#endif
pkey = ngx_ssl_load_certificate_key(cf->pool, &err, key, passwords);
if (pkey == NULL) {
if (err != NULL) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"cannot load certificate key \"%s\": %s",
key->data, err);
}
return NGX_ERROR;
}
if (SSL_CTX_use_PrivateKey(ssl->ctx, pkey) == 0) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_use_PrivateKey(\"%s\") failed", key->data);
EVP_PKEY_free(pkey);
return NGX_ERROR;
}
EVP_PKEY_free(pkey);
return NGX_OK;
}
ngx_int_t
ngx_ssl_connection_certificate(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords)
{
char *err;
X509 *x509;
EVP_PKEY *pkey;
STACK_OF(X509) *chain;
x509 = ngx_ssl_load_certificate(pool, &err, cert, &chain);
if (x509 == NULL) {
if (err != NULL) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"cannot load certificate \"%s\": %s",
cert->data, err);
}
return NGX_ERROR;
}
if (SSL_use_certificate(c->ssl->connection, x509) == 0) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"SSL_use_certificate(\"%s\") failed", cert->data);
X509_free(x509);
sk_X509_pop_free(chain, X509_free);
return NGX_ERROR;
}
X509_free(x509);
#ifdef SSL_set0_chain
/*
* SSL_set0_chain() is only available in OpenSSL 1.0.2+,
* but this function is only called via certificate callback,
* which is only available in OpenSSL 1.0.2+ as well
*/
if (SSL_set0_chain(c->ssl->connection, chain) == 0) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"SSL_set0_chain(\"%s\") failed", cert->data);
sk_X509_pop_free(chain, X509_free);
return NGX_ERROR;
}
#endif
pkey = ngx_ssl_load_certificate_key(pool, &err, key, passwords);
if (pkey == NULL) {
if (err != NULL) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"cannot load certificate key \"%s\": %s",
key->data, err);
}
return NGX_ERROR;
}
if (SSL_use_PrivateKey(c->ssl->connection, pkey) == 0) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"SSL_use_PrivateKey(\"%s\") failed", key->data);
EVP_PKEY_free(pkey);
return NGX_ERROR;
}
EVP_PKEY_free(pkey);
return NGX_OK;
}
static X509 *
ngx_ssl_load_certificate(ngx_pool_t *pool, char **err, ngx_str_t *cert,
STACK_OF(X509) **chain)
{
BIO *bio;
X509 *x509, *temp;
u_long n;
if (ngx_strncmp(cert->data, "data:", sizeof("data:") - 1) == 0) {
bio = BIO_new_mem_buf(cert->data + sizeof("data:") - 1,
cert->len - (sizeof("data:") - 1));
if (bio == NULL) {
*err = "BIO_new_mem_buf() failed";
return NULL;
}
} else {
if (ngx_get_full_name(pool, (ngx_str_t *) &ngx_cycle->conf_prefix, cert)
!= NGX_OK)
{
*err = NULL;
return NULL;
}
bio = BIO_new_file((char *) cert->data, "r");
if (bio == NULL) {
*err = "BIO_new_file() failed";
return NULL;
}
}
/* certificate itself */
x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
if (x509 == NULL) {
*err = "PEM_read_bio_X509_AUX() failed";
BIO_free(bio);
return NULL;
}
/* rest of the chain */
*chain = sk_X509_new_null();
if (*chain == NULL) {
*err = "sk_X509_new_null() failed";
BIO_free(bio);
X509_free(x509);
return NULL;
}
for ( ;; ) { for ( ;; ) {
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); temp = PEM_read_bio_X509(bio, NULL, NULL, NULL);
if (x509 == NULL) { if (temp == NULL) {
n = ERR_peek_last_error(); n = ERR_peek_last_error();
if (ERR_GET_LIB(n) == ERR_LIB_PEM if (ERR_GET_LIB(n) == ERR_LIB_PEM
@@ -495,58 +685,51 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
/* some real error */ /* some real error */
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, *err = "PEM_read_bio_X509() failed";
"PEM_read_bio_X509(\"%s\") failed", cert->data);
BIO_free(bio); BIO_free(bio);
return NGX_ERROR;
}
#ifdef SSL_CTRL_CHAIN_CERT
/*
* SSL_CTX_add0_chain_cert() is needed to add chain to
* a particular certificate when multiple certificates are used;
* only available in OpenSSL 1.0.2+
*/
if (SSL_CTX_add0_chain_cert(ssl->ctx, x509) == 0) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_add0_chain_cert(\"%s\") failed",
cert->data);
X509_free(x509); X509_free(x509);
BIO_free(bio); sk_X509_pop_free(*chain, X509_free);
return NGX_ERROR; return NULL;
} }
#else if (sk_X509_push(*chain, temp) == 0) {
if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) { *err = "sk_X509_push() failed";
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_add_extra_chain_cert(\"%s\") failed",
cert->data);
X509_free(x509);
BIO_free(bio); BIO_free(bio);
return NGX_ERROR; X509_free(x509);
sk_X509_pop_free(*chain, X509_free);
return NULL;
} }
#endif
} }
BIO_free(bio); BIO_free(bio);
return x509;
}
static EVP_PKEY *
ngx_ssl_load_certificate_key(ngx_pool_t *pool, char **err,
ngx_str_t *key, ngx_array_t *passwords)
{
BIO *bio;
EVP_PKEY *pkey;
ngx_str_t *pwd;
ngx_uint_t tries;
pem_password_cb *cb;
if (ngx_strncmp(key->data, "engine:", sizeof("engine:") - 1) == 0) { if (ngx_strncmp(key->data, "engine:", sizeof("engine:") - 1) == 0) {
#ifndef OPENSSL_NO_ENGINE #ifndef OPENSSL_NO_ENGINE
u_char *p, *last; u_char *p, *last;
ENGINE *engine; ENGINE *engine;
EVP_PKEY *pkey;
p = key->data + sizeof("engine:") - 1; p = key->data + sizeof("engine:") - 1;
last = (u_char *) ngx_strchr(p, ':'); last = (u_char *) ngx_strchr(p, ':');
if (last == NULL) { if (last == NULL) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, *err = "invalid syntax";
"invalid syntax in \"%V\"", key); return NULL;
return NGX_ERROR;
} }
*last = '\0'; *last = '\0';
@@ -554,9 +737,8 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
engine = ENGINE_by_id((char *) p); engine = ENGINE_by_id((char *) p);
if (engine == NULL) { if (engine == NULL) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, *err = "ENGINE_by_id() failed";
"ENGINE_by_id(\"%s\") failed", p); return NULL;
return NGX_ERROR;
} }
*last++ = ':'; *last++ = ':';
@@ -564,76 +746,81 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
pkey = ENGINE_load_private_key(engine, (char *) last, 0, 0); pkey = ENGINE_load_private_key(engine, (char *) last, 0, 0);
if (pkey == NULL) { if (pkey == NULL) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, *err = "ENGINE_load_private_key() failed";
"ENGINE_load_private_key(\"%s\") failed", last);
ENGINE_free(engine); ENGINE_free(engine);
return NGX_ERROR; return NULL;
} }
ENGINE_free(engine); ENGINE_free(engine);
if (SSL_CTX_use_PrivateKey(ssl->ctx, pkey) == 0) { return pkey;
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_use_PrivateKey(\"%s\") failed", last);
EVP_PKEY_free(pkey);
return NGX_ERROR;
}
EVP_PKEY_free(pkey);
return NGX_OK;
#else #else
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, *err = "loading \"engine:...\" certificate keys is not supported";
"loading \"engine:...\" certificate keys " return NULL;
"is not supported");
return NGX_ERROR;
#endif #endif
} }
if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) { if (ngx_strncmp(key->data, "data:", sizeof("data:") - 1) == 0) {
return NGX_ERROR;
bio = BIO_new_mem_buf(key->data + sizeof("data:") - 1,
key->len - (sizeof("data:") - 1));
if (bio == NULL) {
*err = "BIO_new_mem_buf() failed";
return NULL;
}
} else {
if (ngx_get_full_name(pool, (ngx_str_t *) &ngx_cycle->conf_prefix, key)
!= NGX_OK)
{
*err = NULL;
return NULL;
}
bio = BIO_new_file((char *) key->data, "r");
if (bio == NULL) {
*err = "BIO_new_file() failed";
return NULL;
}
} }
if (passwords) { if (passwords) {
tries = passwords->nelts; tries = passwords->nelts;
pwd = passwords->elts; pwd = passwords->elts;
cb = ngx_ssl_password_callback;
SSL_CTX_set_default_passwd_cb(ssl->ctx, ngx_ssl_password_callback);
SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, pwd);
} else { } else {
tries = 1; tries = 1;
#if (NGX_SUPPRESS_WARN)
pwd = NULL; pwd = NULL;
#endif cb = NULL;
} }
for ( ;; ) { for ( ;; ) {
if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data, pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, pwd);
SSL_FILETYPE_PEM) if (pkey != NULL) {
!= 0)
{
break; break;
} }
if (--tries) { if (tries-- > 1) {
ERR_clear_error(); ERR_clear_error();
SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, ++pwd); (void) BIO_reset(bio);
pwd++;
continue; continue;
} }
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, *err = "PEM_read_bio_PrivateKey() failed";
"SSL_CTX_use_PrivateKey_file(\"%s\") failed", key->data); BIO_free(bio);
return NGX_ERROR; return NULL;
} }
SSL_CTX_set_default_passwd_cb(ssl->ctx, NULL); BIO_free(bio);
return NGX_OK; return pkey;
} }
@@ -648,6 +835,10 @@ ngx_ssl_password_callback(char *buf, int size, int rwflag, void *userdata)
return 0; return 0;
} }
if (pwd == NULL) {
return 0;
}
if (pwd->len > (size_t) size) { if (pwd->len > (size_t) size) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"password is truncated to %d bytes", size); "password is truncated to %d bytes", size);
@@ -727,13 +918,6 @@ ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
return NGX_ERROR; return NGX_ERROR;
} }
/*
* before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
* always leaved an error in the error queue
*/
ERR_clear_error();
SSL_CTX_set_client_CA_list(ssl->ctx, list); SSL_CTX_set_client_CA_list(ssl->ctx, list);
return NGX_OK; return NGX_OK;
@@ -744,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) {
@@ -899,8 +1086,8 @@ ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret)
* added to wbio, and set buffer size. * added to wbio, and set buffer size.
*/ */
rbio = SSL_get_rbio((ngx_ssl_conn_t *) ssl_conn); rbio = SSL_get_rbio(ssl_conn);
wbio = SSL_get_wbio((ngx_ssl_conn_t *) ssl_conn); wbio = SSL_get_wbio(ssl_conn);
if (rbio != wbio) { if (rbio != wbio) {
(void) BIO_set_write_buffer_size(wbio, NGX_SSL_BUFSIZE); (void) BIO_set_write_buffer_size(wbio, NGX_SSL_BUFSIZE);
@@ -949,10 +1136,13 @@ ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file)
return NULL; return NULL;
} }
cln = ngx_pool_cleanup_add(cf->temp_pool, 0);
passwords = ngx_array_create(cf->temp_pool, 4, sizeof(ngx_str_t)); passwords = ngx_array_create(cf->temp_pool, 4, sizeof(ngx_str_t));
if (passwords == NULL) {
return NULL;
}
if (cln == NULL || passwords == NULL) { cln = ngx_pool_cleanup_add(cf->temp_pool, 0);
if (cln == NULL) {
return NULL; return NULL;
} }
@@ -1054,12 +1244,75 @@ cleanup:
ngx_close_file_n " \"%s\" failed", file->data); ngx_close_file_n " \"%s\" failed", file->data);
} }
ngx_memzero(buf, NGX_SSL_PASSWORD_BUFFER_SIZE); ngx_explicit_memzero(buf, NGX_SSL_PASSWORD_BUFFER_SIZE);
return passwords; return passwords;
} }
ngx_array_t *
ngx_ssl_preserve_passwords(ngx_conf_t *cf, ngx_array_t *passwords)
{
ngx_str_t *opwd, *pwd;
ngx_uint_t i;
ngx_array_t *pwds;
ngx_pool_cleanup_t *cln;
static ngx_array_t empty_passwords;
if (passwords == NULL) {
/*
* If there are no passwords, an empty array is used
* to make sure OpenSSL's default password callback
* won't block on reading from stdin.
*/
return &empty_passwords;
}
/*
* Passwords are normally allocated from the temporary pool
* and cleared after parsing configuration. To be used at
* runtime they have to be copied to the configuration pool.
*/
pwds = ngx_array_create(cf->pool, passwords->nelts, sizeof(ngx_str_t));
if (pwds == NULL) {
return NULL;
}
cln = ngx_pool_cleanup_add(cf->pool, 0);
if (cln == NULL) {
return NULL;
}
cln->handler = ngx_ssl_passwords_cleanup;
cln->data = pwds;
opwd = passwords->elts;
for (i = 0; i < passwords->nelts; i++) {
pwd = ngx_array_push(pwds);
if (pwd == NULL) {
return NULL;
}
pwd->len = opwd[i].len;
pwd->data = ngx_pnalloc(cf->pool, pwd->len);
if (pwd->data == NULL) {
pwds->nelts--;
return NULL;
}
ngx_memcpy(pwd->data, opwd[i].data, opwd[i].len);
}
return pwds;
}
static void static void
ngx_ssl_passwords_cleanup(void *data) ngx_ssl_passwords_cleanup(void *data)
{ {
@@ -1071,7 +1324,7 @@ ngx_ssl_passwords_cleanup(void *data)
pwd = passwords->elts; pwd = passwords->elts;
for (i = 0; i < passwords->nelts; i++) { for (i = 0; i < passwords->nelts; i++) {
ngx_memzero(pwd[i].data, pwd[i].len); ngx_explicit_memzero(pwd[i].data, pwd[i].len);
} }
} }
@@ -1117,7 +1370,6 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
ngx_int_t ngx_int_t
ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name) ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
{ {
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef OPENSSL_NO_ECDH #ifndef OPENSSL_NO_ECDH
/* /*
@@ -1191,7 +1443,6 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
EC_KEY_free(ecdh); EC_KEY_free(ecdh);
#endif #endif
#endif
#endif #endif
return NGX_OK; return NGX_OK;
@@ -1363,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) {
@@ -1370,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);
@@ -1390,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;
@@ -1410,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;
} }
@@ -1479,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);
@@ -1513,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;
@@ -1521,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;
} }
@@ -1691,6 +1973,10 @@ ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl, off_t limit)
last += n; last += n;
bytes += n; bytes += n;
if (!c->read->ready) {
return bytes;
}
if (last == b->end) { if (last == b->end) {
cl = cl->next; cl = cl->next;
@@ -1768,6 +2054,47 @@ ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
if (size == 0) { if (size == 0) {
c->read->ready = 1; c->read->ready = 1;
if (c->read->available >= 0) {
c->read->available -= bytes;
/*
* there can be data buffered at SSL layer,
* so we post an event to continue reading on the next
* iteration of the event loop
*/
if (c->read->available < 0) {
c->read->available = 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_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"SSL_read: avail:%d", c->read->available);
} else {
#if (NGX_HAVE_FIONREAD)
if (ngx_socket_nread(c->fd, &c->read->available) == -1) {
c->read->error = 1;
ngx_connection_error(c, ngx_socket_errno,
ngx_socket_nread_n " failed");
return NGX_ERROR;
}
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"SSL_read: avail:%d", c->read->available);
#endif
}
return bytes; return bytes;
} }
@@ -1843,6 +2170,10 @@ ngx_ssl_recv_early(ngx_connection_t *c, u_char *buf, size_t size)
buf += 1; buf += 1;
} }
if (c->ssl->write_blocked) {
return NGX_AGAIN;
}
/* /*
* SSL_read_early_data() may return data in parts, so try to read * SSL_read_early_data() may return data in parts, so try to read
* until SSL_read_early_data() would return no data * until SSL_read_early_data() would return no data
@@ -2381,6 +2712,11 @@ ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size)
ngx_post_event(c->read, &ngx_posted_events); ngx_post_event(c->read, &ngx_posted_events);
} }
if (c->ssl->write_blocked) {
c->ssl->write_blocked = 0;
ngx_post_event(c->read, &ngx_posted_events);
}
c->sent += written; c->sent += written;
return written; return written;
@@ -2394,6 +2730,9 @@ ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size)
if (sslerr == SSL_ERROR_WANT_WRITE) { if (sslerr == SSL_ERROR_WANT_WRITE) {
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
"SSL_write_early_data: want write");
if (c->ssl->saved_read_handler) { if (c->ssl->saved_read_handler) {
c->read->handler = c->ssl->saved_read_handler; c->read->handler = c->ssl->saved_read_handler;
@@ -2407,6 +2746,14 @@ ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size)
ngx_post_event(c->read, &ngx_posted_events); ngx_post_event(c->read, &ngx_posted_events);
} }
/*
* OpenSSL 1.1.1a fails to handle SSL_read_early_data()
* if an SSL_write_early_data() call blocked on writing,
* see https://github.com/openssl/openssl/issues/7757
*/
c->ssl->write_blocked = 1;
c->write->ready = 0; c->write->ready = 0;
return NGX_AGAIN; return NGX_AGAIN;
} }
@@ -2474,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)) {
/* /*
@@ -2514,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;
} }
@@ -2604,6 +2970,9 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
if (sslerr == SSL_ERROR_SYSCALL) { if (sslerr == SSL_ERROR_SYSCALL) {
if (err == NGX_ECONNRESET if (err == NGX_ECONNRESET
#if (NGX_WIN32)
|| err == NGX_ECONNABORTED
#endif
|| err == NGX_EPIPE || err == NGX_EPIPE
|| err == NGX_ENOTCONN || err == NGX_ENOTCONN
|| err == NGX_ETIMEDOUT || err == NGX_ETIMEDOUT
@@ -2673,8 +3042,14 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
|| n == SSL_R_NO_COMPRESSION_SPECIFIED /* 187 */ || n == SSL_R_NO_COMPRESSION_SPECIFIED /* 187 */
|| n == SSL_R_NO_SHARED_CIPHER /* 193 */ || n == SSL_R_NO_SHARED_CIPHER /* 193 */
|| n == SSL_R_RECORD_LENGTH_MISMATCH /* 213 */ || n == SSL_R_RECORD_LENGTH_MISMATCH /* 213 */
#ifdef SSL_R_CLIENTHELLO_TLSEXT
|| n == SSL_R_CLIENTHELLO_TLSEXT /* 226 */
#endif
#ifdef SSL_R_PARSE_TLSEXT #ifdef SSL_R_PARSE_TLSEXT
|| n == SSL_R_PARSE_TLSEXT /* 227 */ || n == SSL_R_PARSE_TLSEXT /* 227 */
#endif
#ifdef SSL_R_CALLBACK_FAILED
|| n == SSL_R_CALLBACK_FAILED /* 234 */
#endif #endif
|| n == SSL_R_UNEXPECTED_MESSAGE /* 244 */ || n == SSL_R_UNEXPECTED_MESSAGE /* 244 */
|| n == SSL_R_UNEXPECTED_RECORD /* 245 */ || n == SSL_R_UNEXPECTED_RECORD /* 245 */
@@ -2703,6 +3078,9 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
#ifdef SSL_R_INAPPROPRIATE_FALLBACK #ifdef SSL_R_INAPPROPRIATE_FALLBACK
|| n == SSL_R_INAPPROPRIATE_FALLBACK /* 373 */ || n == SSL_R_INAPPROPRIATE_FALLBACK /* 373 */
#endif #endif
#ifdef SSL_R_CERT_CB_ERROR
|| n == SSL_R_CERT_CB_ERROR /* 377 */
#endif
#ifdef SSL_R_VERSION_TOO_LOW #ifdef SSL_R_VERSION_TOO_LOW
|| n == SSL_R_VERSION_TOO_LOW /* 396 */ || n == SSL_R_VERSION_TOO_LOW /* 396 */
#endif #endif
@@ -2782,53 +3160,61 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
p = ngx_vslprintf(errstr, last - 1, fmt, args); p = ngx_vslprintf(errstr, last - 1, fmt, args);
va_end(args); va_end(args);
p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p); if (ERR_peek_error()) {
p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p);
for ( ;; ) { for ( ;; ) {
n = ERR_peek_error_line_data(NULL, NULL, &data, &flags); n = ERR_peek_error_line_data(NULL, NULL, &data, &flags);
if (n == 0) { if (n == 0) {
break; break;
}
/* ERR_error_string_n() requires at least one byte */
if (p >= last - 1) {
goto next;
}
*p++ = ' ';
ERR_error_string_n(n, (char *) p, last - p);
while (p < last && *p) {
p++;
}
if (p < last && *data && (flags & ERR_TXT_STRING)) {
*p++ = ':';
p = ngx_cpystrn(p, (u_char *) data, last - p);
}
next:
(void) ERR_get_error();
} }
/* ERR_error_string_n() requires at least one byte */ if (p < last) {
*p++ = ')';
if (p >= last - 1) {
goto next;
} }
*p++ = ' ';
ERR_error_string_n(n, (char *) p, last - p);
while (p < last && *p) {
p++;
}
if (p < last && *data && (flags & ERR_TXT_STRING)) {
*p++ = ':';
p = ngx_cpystrn(p, (u_char *) data, last - p);
}
next:
(void) ERR_get_error();
} }
ngx_log_error(level, log, err, "%*s)", p - errstr, errstr); ngx_log_error(level, log, err, "%*s", p - errstr, errstr);
} }
ngx_int_t ngx_int_t
ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout) ngx_array_t *certificates, ssize_t builtin_session_cache,
ngx_shm_zone_t *shm_zone, time_t timeout, time_t timeout_tls13)
{ {
long cache_mode; long cache_mode;
SSL_CTX_set_timeout(ssl->ctx, (long) timeout); SSL_CTX_set_timeout(ssl->ctx, (long) timeout);
SSL_CTX_set_timeout_tls13(ssl->ctx, (long) timeout_tls13);
if (ngx_ssl_session_id_context(ssl, sess_ctx) != NGX_OK) { if (ngx_ssl_session_id_context(ssl, sess_ctx, certificates) != NGX_OK) {
return NGX_ERROR; return NGX_ERROR;
} }
@@ -2894,11 +3280,14 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
static ngx_int_t static ngx_int_t
ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx) ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
ngx_array_t *certificates)
{ {
int n, i; int n, i;
X509 *cert; X509 *cert;
X509_NAME *name; X509_NAME *name;
ngx_str_t *certs;
ngx_uint_t k;
EVP_MD_CTX *md; EVP_MD_CTX *md;
unsigned int len; unsigned int len;
STACK_OF(X509_NAME) *list; STACK_OF(X509_NAME) *list;
@@ -2943,6 +3332,24 @@ ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx)
} }
} }
if (SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index) == NULL) {
/*
* If certificates are loaded dynamically, we use certificate
* names as specified in the configuration (with variables).
*/
certs = certificates->elts;
for (k = 0; k < certificates->nelts; k++) {
if (EVP_DigestUpdate(md, certs[k].data, certs[k].len) == 0) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"EVP_DigestUpdate() failed");
goto failed;
}
}
}
list = SSL_CTX_get_client_CA_list(ssl->ctx); list = SSL_CTX_get_client_CA_list(ssl->ctx);
if (list != NULL) { if (list != NULL) {
@@ -2967,7 +3374,7 @@ ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx)
if (EVP_DigestFinal_ex(md, buf, &len) == 0) { if (EVP_DigestFinal_ex(md, buf, &len) == 0) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"EVP_DigestUpdate() failed"); "EVP_DigestFinal_ex() failed");
goto failed; goto failed;
} }
@@ -3124,17 +3531,8 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
} }
} }
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
session_id = (u_char *) SSL_SESSION_get_id(sess, &session_id_length); session_id = (u_char *) SSL_SESSION_get_id(sess, &session_id_length);
#else
session_id = sess->session_id;
session_id_length = sess->session_id_length;
#endif
#if (NGX_PTR_SIZE == 8) #if (NGX_PTR_SIZE == 8)
id = sess_id->sess_id; id = sess_id->sess_id;
@@ -3210,13 +3608,10 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
#endif #endif
u_char *id, int len, int *copy) u_char *id, int len, int *copy)
{ {
#if OPENSSL_VERSION_NUMBER >= 0x0090707fL
const
#endif
u_char *p;
size_t slen; size_t slen;
uint32_t hash; uint32_t hash;
ngx_int_t rc; ngx_int_t rc;
const u_char *p;
ngx_shm_zone_t *shm_zone; ngx_shm_zone_t *shm_zone;
ngx_slab_pool_t *shpool; ngx_slab_pool_t *shpool;
ngx_rbtree_node_t *node, *sentinel; ngx_rbtree_node_t *node, *sentinel;
@@ -3338,17 +3733,8 @@ ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
cache = shm_zone->data; cache = shm_zone->data;
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
id = (u_char *) SSL_SESSION_get_id(sess, &len); id = (u_char *) SSL_SESSION_get_id(sess, &len);
#else
id = sess->session_id;
len = sess->session_id_length;
#endif
hash = ngx_crc32_short(id, len); hash = ngx_crc32_short(id, len);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
@@ -3498,6 +3884,7 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
ngx_uint_t i; ngx_uint_t i;
ngx_array_t *keys; ngx_array_t *keys;
ngx_file_info_t fi; ngx_file_info_t fi;
ngx_pool_cleanup_t *cln;
ngx_ssl_session_ticket_key_t *key; ngx_ssl_session_ticket_key_t *key;
if (paths == NULL) { if (paths == NULL) {
@@ -3510,6 +3897,14 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
return NGX_ERROR; return NGX_ERROR;
} }
cln = ngx_pool_cleanup_add(cf->pool, 0);
if (cln == NULL) {
return NGX_ERROR;
}
cln->handler = ngx_ssl_session_ticket_keys_cleanup;
cln->data = keys;
path = paths->elts; path = paths->elts;
for (i = 0; i < paths->nelts; i++) { for (i = 0; i < paths->nelts; i++) {
@@ -3581,6 +3976,8 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
ngx_close_file_n " \"%V\" failed", &file.name); ngx_close_file_n " \"%V\" failed", &file.name);
} }
ngx_explicit_memzero(&buf, 80);
} }
if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_ticket_keys_index, keys) if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_ticket_keys_index, keys)
@@ -3611,6 +4008,8 @@ failed:
ngx_close_file_n " \"%V\" failed", &file.name); ngx_close_file_n " \"%V\" failed", &file.name);
} }
ngx_explicit_memzero(&buf, 80);
return NGX_ERROR; return NGX_ERROR;
} }
@@ -3739,6 +4138,16 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
} }
} }
static void
ngx_ssl_session_ticket_keys_cleanup(void *data)
{
ngx_array_t *keys = data;
ngx_explicit_memzero(keys->elts,
keys->nelts * sizeof(ngx_ssl_session_ticket_key_t));
}
#else #else
ngx_int_t ngx_int_t
@@ -4124,17 +4533,8 @@ ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
return NGX_OK; return NGX_OK;
} }
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
buf = (u_char *) SSL_SESSION_get_id(sess, &len); buf = (u_char *) SSL_SESSION_get_id(sess, &len);
#else
buf = sess->session_id;
len = sess->session_id_length;
#endif
s->len = 2 * len; s->len = 2 * len;
s->data = ngx_pnalloc(pool, 2 * len); s->data = ngx_pnalloc(pool, 2 * len);
if (s->data == NULL) { if (s->data == NULL) {
@@ -4359,6 +4759,7 @@ ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
name = X509_get_subject_name(cert); name = X509_get_subject_name(cert);
if (name == NULL) { if (name == NULL) {
X509_free(cert);
return NGX_ERROR; return NGX_ERROR;
} }
@@ -4410,6 +4811,7 @@ ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
name = X509_get_issuer_name(cert); name = X509_get_issuer_name(cert);
if (name == NULL) { if (name == NULL) {
X509_free(cert);
return NGX_ERROR; return NGX_ERROR;
} }
@@ -4622,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) {
+24 -1
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,7 +111,9 @@ 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;
ngx_ssl_dyn_rec_t dyn_rec; ngx_ssl_dyn_rec_t dyn_rec;
ngx_msec_t dyn_rec_last_write; ngx_msec_t dyn_rec_last_write;
@@ -173,10 +180,14 @@ typedef struct {
ngx_int_t ngx_ssl_init(ngx_log_t *log); ngx_int_t ngx_ssl_init(ngx_log_t *log);
ngx_int_t ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data); ngx_int_t ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data);
ngx_int_t ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_int_t ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_array_t *certs, ngx_array_t *keys, ngx_array_t *passwords); ngx_array_t *certs, ngx_array_t *keys, ngx_array_t *passwords);
ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords); ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords);
ngx_int_t ngx_ssl_connection_certificate(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords);
ngx_int_t ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers, ngx_int_t ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers,
ngx_uint_t prefer_server_ciphers); ngx_uint_t prefer_server_ciphers);
ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
@@ -188,9 +199,19 @@ 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);
ngx_array_t *ngx_ssl_preserve_passwords(ngx_conf_t *cf,
ngx_array_t *passwords);
ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file); ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file);
ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name); ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name);
ngx_int_t ngx_ssl_early_data(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_int_t ngx_ssl_early_data(ngx_conf_t *cf, ngx_ssl_t *ssl,
@@ -198,7 +219,8 @@ ngx_int_t ngx_ssl_early_data(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_int_t ngx_ssl_client_session_cache(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_int_t ngx_ssl_client_session_cache(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_uint_t enable); ngx_uint_t enable);
ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout); ngx_array_t *certificates, ssize_t builtin_session_cache,
ngx_shm_zone_t *shm_zone, time_t timeout, time_t timeout_tls13);
ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_array_t *paths); ngx_array_t *paths);
ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data);
@@ -286,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;
+1071 -177
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;
@@ -227,7 +306,7 @@ ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
return NGX_ERROR; return NGX_ERROR;
} }
bio = BIO_new_file((char *) file->data, "r"); bio = BIO_new_file((char *) file->data, "rb");
if (bio == NULL) { if (bio == NULL) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"BIO_new_file(\"%s\") failed", file->data); "BIO_new_file(\"%s\") failed", file->data);
@@ -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;
@@ -511,6 +578,11 @@ ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data)
rc = SSL_TLSEXT_ERR_NOACK; rc = SSL_TLSEXT_ERR_NOACK;
cert = SSL_get_certificate(ssl_conn); cert = SSL_get_certificate(ssl_conn);
if (cert == NULL) {
return rc;
}
staple = X509_get_ex_data(cert, ngx_ssl_stapling_index); staple = X509_get_ex_data(cert, ngx_ssl_stapling_index);
if (staple == NULL) { if (staple == NULL) {
@@ -554,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;
@@ -584,140 +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)
{ {
#if OPENSSL_VERSION_NUMBER >= 0x0090707fL time_t now;
const ngx_str_t response;
#endif ngx_ssl_stapling_t *staple;
u_char *p;
int n;
size_t len;
time_t now, valid;
ngx_str_t response;
X509_STORE *store;
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) {
@@ -726,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,
@@ -743,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;
@@ -753,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);
} }
@@ -818,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;
} }
@@ -882,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)
{ {
@@ -907,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;
@@ -1020,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;
@@ -1039,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;
@@ -1052,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);
@@ -1078,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;
} }
@@ -1087,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;
} }
@@ -1109,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);
} }
} }
@@ -1132,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;
} }
@@ -1156,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;
} }
@@ -1187,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);
} }
@@ -1829,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)
{ {
@@ -1889,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
+33 -1
View File
@@ -172,7 +172,11 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
*/ */
if (p->upstream->read->available == 0 if (p->upstream->read->available == 0
&& p->upstream->read->pending_eof) && p->upstream->read->pending_eof
#if (NGX_SSL)
&& !p->upstream->ssl
#endif
)
{ {
p->upstream->read->ready = 0; p->upstream->read->ready = 0;
p->upstream->read->eof = 1; p->upstream->read->eof = 1;
@@ -956,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;
@@ -983,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;
+25
View File
@@ -11,6 +11,7 @@
ngx_queue_t ngx_posted_accept_events; ngx_queue_t ngx_posted_accept_events;
ngx_queue_t ngx_posted_next_events;
ngx_queue_t ngx_posted_events; ngx_queue_t ngx_posted_events;
@@ -33,3 +34,27 @@ ngx_event_process_posted(ngx_cycle_t *cycle, ngx_queue_t *posted)
ev->handler(ev); ev->handler(ev);
} }
} }
void
ngx_event_move_posted_next(ngx_cycle_t *cycle)
{
ngx_queue_t *q;
ngx_event_t *ev;
for (q = ngx_queue_head(&ngx_posted_next_events);
q != ngx_queue_sentinel(&ngx_posted_next_events);
q = ngx_queue_next(q))
{
ev = ngx_queue_data(q, ngx_event_t, queue);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"posted next event %p", ev);
ev->ready = 1;
ev->available = -1;
}
ngx_queue_add(&ngx_posted_events, &ngx_posted_next_events);
ngx_queue_init(&ngx_posted_next_events);
}
+2
View File
@@ -39,9 +39,11 @@
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_move_posted_next(ngx_cycle_t *cycle);
extern ngx_queue_t ngx_posted_accept_events; extern ngx_queue_t ngx_posted_accept_events;
extern ngx_queue_t ngx_posted_next_events;
extern ngx_queue_t ngx_posted_events; extern ngx_queue_t ngx_posted_events;
+24 -3
View File
@@ -25,7 +25,6 @@ struct ngx_udp_connection_s {
static ssize_t ngx_udp_shared_recv(ngx_connection_t *c, u_char *buf, static ssize_t ngx_udp_shared_recv(ngx_connection_t *c, u_char *buf,
size_t size); size_t size);
static ngx_int_t ngx_insert_udp_connection(ngx_connection_t *c); static ngx_int_t ngx_insert_udp_connection(ngx_connection_t *c);
static void ngx_delete_udp_connection(void *data);
static ngx_connection_t *ngx_lookup_udp_connection(ngx_listening_t *ls, static ngx_connection_t *ngx_lookup_udp_connection(ngx_listening_t *ls,
struct sockaddr *sockaddr, socklen_t socklen, struct sockaddr *sockaddr, socklen_t socklen,
struct sockaddr *local_sockaddr, socklen_t local_socklen); struct sockaddr *local_sockaddr, socklen_t local_socklen);
@@ -259,12 +258,18 @@ ngx_event_recvmsg(ngx_event_t *ev)
rev = c->read; rev = c->read;
c->udp->buffer = &buf; c->udp->buffer = &buf;
rev->ready = 1; rev->ready = 1;
rev->active = 0;
rev->handler(rev); rev->handler(rev);
c->udp->buffer = NULL; if (c->udp) {
c->udp->buffer = NULL;
}
rev->ready = 0; rev->ready = 0;
rev->active = 1;
goto next; goto next;
} }
@@ -343,6 +348,7 @@ ngx_event_recvmsg(ngx_event_t *ev)
rev = c->read; rev = c->read;
wev = c->write; wev = c->write;
rev->active = 1;
wev->ready = 1; wev->ready = 1;
rev->log = log; rev->log = log;
@@ -436,7 +442,9 @@ ngx_udp_shared_recv(ngx_connection_t *c, u_char *buf, size_t size)
ngx_memcpy(buf, b->pos, n); ngx_memcpy(buf, b->pos, n);
c->udp->buffer = NULL; c->udp->buffer = NULL;
c->read->ready = 0; c->read->ready = 0;
c->read->active = 1;
return n; return n;
} }
@@ -540,12 +548,18 @@ ngx_insert_udp_connection(ngx_connection_t *c)
} }
static void void
ngx_delete_udp_connection(void *data) ngx_delete_udp_connection(void *data)
{ {
ngx_connection_t *c = data; ngx_connection_t *c = data;
if (c->udp == NULL) {
return;
}
ngx_rbtree_delete(&c->listening->rbtree, &c->udp->node); ngx_rbtree_delete(&c->listening->rbtree, &c->udp->node);
c->udp = NULL;
} }
@@ -813,6 +827,13 @@ void ngx_event_recvmsg(ngx_event_t *ev)
} }
void
ngx_delete_udp_connection(void *data)
{
return;
}
#endif #endif
static void static void
+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)
+42 -26
View File
@@ -186,8 +186,6 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
return rc; return rc;
} }
/* NGX_DIR_MASK_LEN is lesser than NGX_HTTP_AUTOINDEX_PREALLOCATE */
last = ngx_http_map_uri_to_path(r, &path, &root, last = ngx_http_map_uri_to_path(r, &path, &root,
NGX_HTTP_AUTOINDEX_PREALLOCATE); NGX_HTTP_AUTOINDEX_PREALLOCATE);
if (last == NULL) { if (last == NULL) {
@@ -436,7 +434,7 @@ ngx_http_autoindex_html(ngx_http_request_t *r, ngx_array_t *entries)
{ {
u_char *last, scale; u_char *last, scale;
off_t length; off_t length;
size_t len, char_len, escape_html; size_t len, entry_len, char_len, escape_html;
ngx_tm_t tm; ngx_tm_t tm;
ngx_buf_t *b; ngx_buf_t *b;
ngx_int_t size; ngx_int_t size;
@@ -501,17 +499,23 @@ ngx_http_autoindex_html(ngx_http_request_t *r, ngx_array_t *entries)
entry[i].utf_len = entry[i].name.len; entry[i].utf_len = entry[i].name.len;
} }
len += sizeof("<a href=\"") - 1 entry_len = sizeof("<a href=\"") - 1
+ entry[i].name.len + entry[i].escape + entry[i].name.len + entry[i].escape
+ 1 /* 1 is for "/" */ + 1 /* 1 is for "/" */
+ sizeof("\">") - 1 + sizeof("\">") - 1
+ entry[i].name.len - entry[i].utf_len + entry[i].name.len - entry[i].utf_len
+ entry[i].escape_html + entry[i].escape_html
+ NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof("&gt;") - 2 + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof("&gt;") - 2
+ sizeof("</a>") - 1 + sizeof("</a>") - 1
+ sizeof(" 28-Sep-1970 12:00 ") - 1 + sizeof(" 28-Sep-1970 12:00 ") - 1
+ 20 /* the file size */ + 20 /* the file size */
+ 2; + 2;
if (len > NGX_MAX_SIZE_T_VALUE - entry_len) {
return NULL;
}
len += entry_len;
} }
b = ngx_create_temp_buf(r->pool, len); b = ngx_create_temp_buf(r->pool, len);
@@ -699,7 +703,7 @@ static ngx_buf_t *
ngx_http_autoindex_json(ngx_http_request_t *r, ngx_array_t *entries, ngx_http_autoindex_json(ngx_http_request_t *r, ngx_array_t *entries,
ngx_str_t *callback) ngx_str_t *callback)
{ {
size_t len; size_t len, entry_len;
ngx_buf_t *b; ngx_buf_t *b;
ngx_uint_t i; ngx_uint_t i;
ngx_http_autoindex_entry_t *entry; ngx_http_autoindex_entry_t *entry;
@@ -716,15 +720,21 @@ ngx_http_autoindex_json(ngx_http_request_t *r, ngx_array_t *entries,
entry[i].escape = ngx_escape_json(NULL, entry[i].name.data, entry[i].escape = ngx_escape_json(NULL, entry[i].name.data,
entry[i].name.len); entry[i].name.len);
len += sizeof("{ }," CRLF) - 1 entry_len = sizeof("{ }," CRLF) - 1
+ sizeof("\"name\":\"\"") - 1 + sizeof("\"name\":\"\"") - 1
+ entry[i].name.len + entry[i].escape + entry[i].name.len + entry[i].escape
+ sizeof(", \"type\":\"directory\"") - 1 + sizeof(", \"type\":\"directory\"") - 1
+ sizeof(", \"mtime\":\"Wed, 31 Dec 1986 10:00:00 GMT\"") - 1; + sizeof(", \"mtime\":\"Wed, 31 Dec 1986 10:00:00 GMT\"") - 1;
if (entry[i].file) { if (entry[i].file) {
len += sizeof(", \"size\":") - 1 + NGX_OFF_T_LEN; entry_len += sizeof(", \"size\":") - 1 + NGX_OFF_T_LEN;
} }
if (len > NGX_MAX_SIZE_T_VALUE - entry_len) {
return NULL;
}
len += entry_len;
} }
b = ngx_create_temp_buf(r->pool, len); b = ngx_create_temp_buf(r->pool, len);
@@ -843,7 +853,7 @@ ngx_http_autoindex_jsonp_callback(ngx_http_request_t *r, ngx_str_t *callback)
static ngx_buf_t * static ngx_buf_t *
ngx_http_autoindex_xml(ngx_http_request_t *r, ngx_array_t *entries) ngx_http_autoindex_xml(ngx_http_request_t *r, ngx_array_t *entries)
{ {
size_t len; size_t len, entry_len;
ngx_tm_t tm; ngx_tm_t tm;
ngx_buf_t *b; ngx_buf_t *b;
ngx_str_t type; ngx_str_t type;
@@ -861,13 +871,19 @@ ngx_http_autoindex_xml(ngx_http_request_t *r, ngx_array_t *entries)
entry[i].escape = ngx_escape_html(NULL, entry[i].name.data, entry[i].escape = ngx_escape_html(NULL, entry[i].name.data,
entry[i].name.len); entry[i].name.len);
len += sizeof("<directory></directory>" CRLF) - 1 entry_len = sizeof("<directory></directory>" CRLF) - 1
+ entry[i].name.len + entry[i].escape + entry[i].name.len + entry[i].escape
+ sizeof(" mtime=\"1986-12-31T10:00:00Z\"") - 1; + sizeof(" mtime=\"1986-12-31T10:00:00Z\"") - 1;
if (entry[i].file) { if (entry[i].file) {
len += sizeof(" size=\"\"") - 1 + NGX_OFF_T_LEN; entry_len += sizeof(" size=\"\"") - 1 + NGX_OFF_T_LEN;
} }
if (len > NGX_MAX_SIZE_T_VALUE - entry_len) {
return NULL;
}
len += entry_len;
} }
b = ngx_create_temp_buf(r->pool, len); b = ngx_create_temp_buf(r->pool, len);
+10 -28
View File
@@ -56,7 +56,7 @@ static ngx_int_t ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx,
static ngx_int_t ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt); static ngx_int_t ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt);
static ngx_int_t ngx_http_dav_error(ngx_log_t *log, ngx_err_t err, static ngx_int_t ngx_http_dav_error(ngx_log_t *log, ngx_err_t err,
ngx_int_t not_found, char *failed, u_char *path); ngx_int_t not_found, char *failed, u_char *path);
static ngx_int_t ngx_http_dav_location(ngx_http_request_t *r, u_char *path); static ngx_int_t ngx_http_dav_location(ngx_http_request_t *r);
static void *ngx_http_dav_create_loc_conf(ngx_conf_t *cf); static void *ngx_http_dav_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_dav_merge_loc_conf(ngx_conf_t *cf, static char *ngx_http_dav_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child); void *parent, void *child);
@@ -285,7 +285,7 @@ ngx_http_dav_put_handler(ngx_http_request_t *r)
} }
if (status == NGX_HTTP_CREATED) { if (status == NGX_HTTP_CREATED) {
if (ngx_http_dav_location(r, path.data) != NGX_OK) { if (ngx_http_dav_location(r) != NGX_OK) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return; return;
} }
@@ -312,7 +312,7 @@ ngx_http_dav_delete_handler(ngx_http_request_t *r)
ngx_file_info_t fi; ngx_file_info_t fi;
ngx_http_dav_loc_conf_t *dlcf; ngx_http_dav_loc_conf_t *dlcf;
if (r->headers_in.content_length_n > 0) { if (r->headers_in.content_length_n > 0 || r->headers_in.chunked) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"DELETE with body is unsupported"); "DELETE with body is unsupported");
return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
@@ -495,7 +495,7 @@ ngx_http_dav_mkcol_handler(ngx_http_request_t *r, ngx_http_dav_loc_conf_t *dlcf)
size_t root; size_t root;
ngx_str_t path; ngx_str_t path;
if (r->headers_in.content_length_n > 0) { if (r->headers_in.content_length_n > 0 || r->headers_in.chunked) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"MKCOL with body is unsupported"); "MKCOL with body is unsupported");
return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
@@ -513,7 +513,6 @@ ngx_http_dav_mkcol_handler(ngx_http_request_t *r, ngx_http_dav_loc_conf_t *dlcf)
} }
*(p - 1) = '\0'; *(p - 1) = '\0';
r->uri.len--;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http mkcol path: \"%s\"", path.data); "http mkcol path: \"%s\"", path.data);
@@ -521,7 +520,7 @@ ngx_http_dav_mkcol_handler(ngx_http_request_t *r, ngx_http_dav_loc_conf_t *dlcf)
if (ngx_create_dir(path.data, ngx_dir_access(dlcf->access)) if (ngx_create_dir(path.data, ngx_dir_access(dlcf->access))
!= NGX_FILE_ERROR) != NGX_FILE_ERROR)
{ {
if (ngx_http_dav_location(r, path.data) != NGX_OK) { if (ngx_http_dav_location(r) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
} }
@@ -550,7 +549,9 @@ ngx_http_dav_copy_move_handler(ngx_http_request_t *r)
ngx_http_dav_copy_ctx_t copy; ngx_http_dav_copy_ctx_t copy;
ngx_http_dav_loc_conf_t *dlcf; ngx_http_dav_loc_conf_t *dlcf;
if (r->headers_in.content_length_n > 0) { if (r->headers_in.content_length_n > 0 || r->headers_in.chunked) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"COPY and MOVE with body are unsupported");
return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
} }
@@ -1069,35 +1070,16 @@ ngx_http_dav_error(ngx_log_t *log, ngx_err_t err, ngx_int_t not_found,
static ngx_int_t static ngx_int_t
ngx_http_dav_location(ngx_http_request_t *r, u_char *path) ngx_http_dav_location(ngx_http_request_t *r)
{ {
u_char *location;
ngx_http_core_loc_conf_t *clcf;
r->headers_out.location = ngx_list_push(&r->headers_out.headers); r->headers_out.location = ngx_list_push(&r->headers_out.headers);
if (r->headers_out.location == NULL) { if (r->headers_out.location == NULL) {
return NGX_ERROR; return NGX_ERROR;
} }
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (!clcf->alias && clcf->root_lengths == NULL) {
location = path + clcf->root.len;
} else {
location = ngx_pnalloc(r->pool, r->uri.len);
if (location == NULL) {
ngx_http_clear_location(r);
return NGX_ERROR;
}
ngx_memcpy(location, r->uri.data, r->uri.len);
}
r->headers_out.location->hash = 1; r->headers_out.location->hash = 1;
ngx_str_set(&r->headers_out.location->key, "Location"); ngx_str_set(&r->headers_out.location->key, "Location");
r->headers_out.location->value.len = r->uri.len; r->headers_out.location->value = r->uri;
r->headers_out.location->value.data = location;
return NGX_OK; return NGX_OK;
} }
+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;
+13
View File
@@ -215,6 +215,13 @@ ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
break; break;
#endif #endif
#if (NGX_HAVE_UNIX_DOMAIN)
case AF_UNIX:
vv = (ngx_http_variable_value_t *)
ngx_radix32tree_find(ctx->u.trees.tree, INADDR_NONE);
break;
#endif
default: /* AF_INET */ default: /* AF_INET */
sin = (struct sockaddr_in *) addr.sockaddr; sin = (struct sockaddr_in *) addr.sockaddr;
inaddr = ntohl(sin->sin_addr.s_addr); inaddr = ntohl(sin->sin_addr.s_addr);
@@ -277,6 +284,12 @@ ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
break; break;
#endif #endif
#if (NGX_HAVE_UNIX_DOMAIN)
case AF_UNIX:
inaddr = INADDR_NONE;
break;
#endif
default: /* AF_INET */ default: /* AF_INET */
sin = (struct sockaddr_in *) addr.sockaddr; sin = (struct sockaddr_in *) addr.sockaddr;
inaddr = ntohl(sin->sin_addr.s_addr); inaddr = ntohl(sin->sin_addr.s_addr);
+265 -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;
@@ -78,6 +81,11 @@ typedef struct {
ngx_uint_t id; ngx_uint_t id;
ngx_uint_t pings;
ngx_uint_t settings;
off_t length;
ssize_t send_window; ssize_t send_window;
size_t recv_window; size_t recv_window;
@@ -114,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;
@@ -132,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);
@@ -521,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;
@@ -548,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;
@@ -573,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)
{ {
@@ -584,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;
@@ -595,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 */
@@ -634,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;
} }
} }
@@ -782,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,
@@ -843,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));
@@ -1086,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;
@@ -1832,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;
@@ -1878,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
@@ -1931,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, "
@@ -1969,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);
@@ -2012,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) {
@@ -3584,6 +3755,12 @@ ngx_http_grpc_parse_settings(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
ctx->rest); ctx->rest);
return NGX_ERROR; return NGX_ERROR;
} }
if (ctx->free == NULL && ctx->settings++ > 1000) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream sent too many settings frames");
return NGX_ERROR;
}
} }
for (p = b->pos; p < last; p++) { for (p = b->pos; p < last; p++) {
@@ -3736,6 +3913,12 @@ ngx_http_grpc_parse_ping(ngx_http_request_t *r,
"upstream sent ping frame with ack flag"); "upstream sent ping frame with ack flag");
return NGX_ERROR; return NGX_ERROR;
} }
if (ctx->free == NULL && ctx->pings++ > 1000) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream sent too many ping frames");
return NGX_ERROR;
}
} }
for (p = b->pos; p < last; p++) { for (p = b->pos; p < last; p++) {
@@ -4304,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;
} }
@@ -4522,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;
@@ -4578,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;
} }
@@ -4635,6 +4854,7 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf)
cln = ngx_pool_cleanup_add(cf->pool, 0); cln = ngx_pool_cleanup_add(cf->pool, 0);
if (cln == NULL) { if (cln == NULL) {
ngx_ssl_cleanup_ctx(glcf->upstream.ssl);
return NGX_ERROR; return NGX_ERROR;
} }
+17 -120
View File
@@ -55,44 +55,23 @@ typedef struct {
unsigned redo:1; unsigned redo:1;
unsigned done:1; unsigned done:1;
unsigned nomem:1; unsigned nomem:1;
unsigned gzheader:1;
unsigned buffering:1; unsigned buffering:1;
unsigned intel:1; unsigned intel:1;
size_t zin; size_t zin;
size_t zout; size_t zout;
uint32_t crc32;
z_stream zstream; z_stream zstream;
ngx_http_request_t *request; ngx_http_request_t *request;
} ngx_http_gzip_ctx_t; } ngx_http_gzip_ctx_t;
#if (NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED)
struct gztrailer {
uint32_t crc32;
uint32_t zlen;
};
#else /* NGX_HAVE_BIG_ENDIAN || !NGX_HAVE_NONALIGNED */
struct gztrailer {
u_char crc32[4];
u_char zlen[4];
};
#endif
static void ngx_http_gzip_filter_memory(ngx_http_request_t *r, static void ngx_http_gzip_filter_memory(ngx_http_request_t *r,
ngx_http_gzip_ctx_t *ctx); ngx_http_gzip_ctx_t *ctx);
static ngx_int_t ngx_http_gzip_filter_buffer(ngx_http_gzip_ctx_t *ctx, static ngx_int_t ngx_http_gzip_filter_buffer(ngx_http_gzip_ctx_t *ctx,
ngx_chain_t *in); ngx_chain_t *in);
static ngx_int_t ngx_http_gzip_filter_deflate_start(ngx_http_request_t *r, static ngx_int_t ngx_http_gzip_filter_deflate_start(ngx_http_request_t *r,
ngx_http_gzip_ctx_t *ctx); ngx_http_gzip_ctx_t *ctx);
static ngx_int_t ngx_http_gzip_filter_gzheader(ngx_http_request_t *r,
ngx_http_gzip_ctx_t *ctx);
static ngx_int_t ngx_http_gzip_filter_add_data(ngx_http_request_t *r, static ngx_int_t ngx_http_gzip_filter_add_data(ngx_http_request_t *r,
ngx_http_gzip_ctx_t *ctx); ngx_http_gzip_ctx_t *ctx);
static ngx_int_t ngx_http_gzip_filter_get_buf(ngx_http_request_t *r, static ngx_int_t ngx_http_gzip_filter_get_buf(ngx_http_request_t *r,
@@ -446,12 +425,6 @@ ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
return ctx->busy ? NGX_AGAIN : NGX_OK; return ctx->busy ? NGX_AGAIN : NGX_OK;
} }
if (!ctx->gzheader) {
if (ngx_http_gzip_filter_gzheader(r, ctx) != NGX_OK) {
goto failed;
}
}
rc = ngx_http_next_body_filter(r, ctx->out); rc = ngx_http_next_body_filter(r, ctx->out);
if (rc == NGX_ERROR) { if (rc == NGX_ERROR) {
@@ -643,7 +616,7 @@ ngx_http_gzip_filter_deflate_start(ngx_http_request_t *r,
ctx->zstream.opaque = ctx; ctx->zstream.opaque = ctx;
rc = deflateInit2(&ctx->zstream, (int) conf->level, Z_DEFLATED, rc = deflateInit2(&ctx->zstream, (int) conf->level, Z_DEFLATED,
- ctx->wbits, ctx->memlevel, Z_DEFAULT_STRATEGY); ctx->wbits + 16, ctx->memlevel, Z_DEFAULT_STRATEGY);
if (rc != Z_OK) { if (rc != Z_OK) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
@@ -652,45 +625,12 @@ ngx_http_gzip_filter_deflate_start(ngx_http_request_t *r,
} }
ctx->last_out = &ctx->out; ctx->last_out = &ctx->out;
ctx->crc32 = crc32(0L, Z_NULL, 0);
ctx->flush = Z_NO_FLUSH; ctx->flush = Z_NO_FLUSH;
return NGX_OK; return NGX_OK;
} }
static ngx_int_t
ngx_http_gzip_filter_gzheader(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
{
ngx_buf_t *b;
ngx_chain_t *cl;
static u_char gzheader[10] =
{ 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 };
b = ngx_calloc_buf(r->pool);
if (b == NULL) {
return NGX_ERROR;
}
b->memory = 1;
b->pos = gzheader;
b->last = b->pos + 10;
cl = ngx_alloc_chain_link(r->pool);
if (cl == NULL) {
return NGX_ERROR;
}
cl->buf = b;
cl->next = ctx->out;
ctx->out = cl;
ctx->gzheader = 1;
return NGX_OK;
}
static ngx_int_t static ngx_int_t
ngx_http_gzip_filter_add_data(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx) ngx_http_gzip_filter_add_data(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
{ {
@@ -743,14 +683,9 @@ ngx_http_gzip_filter_add_data(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
} else if (ctx->in_buf->flush) { } else if (ctx->in_buf->flush) {
ctx->flush = Z_SYNC_FLUSH; ctx->flush = Z_SYNC_FLUSH;
}
if (ctx->zstream.avail_in) { } else if (ctx->zstream.avail_in == 0) {
/* ctx->flush == Z_NO_FLUSH */
ctx->crc32 = crc32(ctx->crc32, ctx->zstream.next_in,
ctx->zstream.avail_in);
} else if (ctx->flush == Z_NO_FLUSH) {
return NGX_AGAIN; return NGX_AGAIN;
} }
@@ -843,7 +778,7 @@ ngx_http_gzip_filter_deflate(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
ctx->out_buf->last = ctx->zstream.next_out; ctx->out_buf->last = ctx->zstream.next_out;
if (ctx->zstream.avail_out == 0) { if (ctx->zstream.avail_out == 0 && rc != Z_STREAM_END) {
/* zlib wants to output some more gzipped data */ /* zlib wants to output some more gzipped data */
@@ -932,13 +867,12 @@ static ngx_int_t
ngx_http_gzip_filter_deflate_end(ngx_http_request_t *r, ngx_http_gzip_filter_deflate_end(ngx_http_request_t *r,
ngx_http_gzip_ctx_t *ctx) ngx_http_gzip_ctx_t *ctx)
{ {
int rc; int rc;
ngx_buf_t *b; ngx_buf_t *b;
ngx_chain_t *cl; ngx_chain_t *cl;
struct gztrailer *trailer;
ctx->zin = ctx->zstream.total_in; ctx->zin = ctx->zstream.total_in;
ctx->zout = 10 + ctx->zstream.total_out + 8; ctx->zout = ctx->zstream.total_out;
rc = deflateEnd(&ctx->zstream); rc = deflateEnd(&ctx->zstream);
@@ -955,56 +889,19 @@ ngx_http_gzip_filter_deflate_end(ngx_http_request_t *r,
return NGX_ERROR; return NGX_ERROR;
} }
cl->buf = ctx->out_buf; b = ctx->out_buf;
if (ngx_buf_size(b) == 0) {
b->temporary = 0;
}
b->last_buf = 1;
cl->buf = b;
cl->next = NULL; cl->next = NULL;
*ctx->last_out = cl; *ctx->last_out = cl;
ctx->last_out = &cl->next; ctx->last_out = &cl->next;
if (ctx->zstream.avail_out >= 8) {
trailer = (struct gztrailer *) ctx->out_buf->last;
ctx->out_buf->last += 8;
ctx->out_buf->last_buf = 1;
} else {
b = ngx_create_temp_buf(r->pool, 8);
if (b == NULL) {
return NGX_ERROR;
}
b->last_buf = 1;
cl = ngx_alloc_chain_link(r->pool);
if (cl == NULL) {
return NGX_ERROR;
}
cl->buf = b;
cl->next = NULL;
*ctx->last_out = cl;
ctx->last_out = &cl->next;
trailer = (struct gztrailer *) b->pos;
b->last += 8;
}
#if (NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED)
trailer->crc32 = ctx->crc32;
trailer->zlen = ctx->zin;
#else
trailer->crc32[0] = (u_char) (ctx->crc32 & 0xff);
trailer->crc32[1] = (u_char) ((ctx->crc32 >> 8) & 0xff);
trailer->crc32[2] = (u_char) ((ctx->crc32 >> 16) & 0xff);
trailer->crc32[3] = (u_char) ((ctx->crc32 >> 24) & 0xff);
trailer->zlen[0] = (u_char) (ctx->zin & 0xff);
trailer->zlen[1] = (u_char) ((ctx->zin >> 8) & 0xff);
trailer->zlen[2] = (u_char) ((ctx->zin >> 16) & 0xff);
trailer->zlen[3] = (u_char) ((ctx->zin >> 24) & 0xff);
#endif
ctx->zstream.avail_in = 0; ctx->zstream.avail_in = 0;
ctx->zstream.avail_out = 0; ctx->zstream.avail_out = 0;
+1 -1
View File
@@ -163,7 +163,7 @@ ngx_http_index_handler(ngx_http_request_t *r)
name = ngx_http_map_uri_to_path(r, &path, &root, reserve); name = ngx_http_map_uri_to_path(r, &path, &root, reserve);
if (name == NULL) { if (name == NULL) {
return NGX_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
} }
allocated = path.data + path.len - name; allocated = path.data + path.len - name;
+138 -50
View File
@@ -10,36 +10,49 @@
#include <ngx_http.h> #include <ngx_http.h>
#define NGX_HTTP_LIMIT_CONN_PASSED 1
#define NGX_HTTP_LIMIT_CONN_REJECTED 2
#define NGX_HTTP_LIMIT_CONN_REJECTED_DRY_RUN 3
typedef struct { typedef struct {
u_char color; u_char color;
u_char len; u_char len;
u_short conn; u_short conn;
u_char data[1]; u_char data[1];
} ngx_http_limit_conn_node_t; } ngx_http_limit_conn_node_t;
typedef struct { typedef struct {
ngx_shm_zone_t *shm_zone; ngx_shm_zone_t *shm_zone;
ngx_rbtree_node_t *node; ngx_rbtree_node_t *node;
} ngx_http_limit_conn_cleanup_t; } ngx_http_limit_conn_cleanup_t;
typedef struct { typedef struct {
ngx_rbtree_t *rbtree; ngx_rbtree_t rbtree;
ngx_http_complex_value_t key; ngx_rbtree_node_t sentinel;
} ngx_http_limit_conn_shctx_t;
typedef struct {
ngx_http_limit_conn_shctx_t *sh;
ngx_slab_pool_t *shpool;
ngx_http_complex_value_t key;
} ngx_http_limit_conn_ctx_t; } ngx_http_limit_conn_ctx_t;
typedef struct { typedef struct {
ngx_shm_zone_t *shm_zone; ngx_shm_zone_t *shm_zone;
ngx_uint_t conn; ngx_uint_t conn;
} ngx_http_limit_conn_limit_t; } ngx_http_limit_conn_limit_t;
typedef struct { typedef struct {
ngx_array_t limits; ngx_array_t limits;
ngx_uint_t log_level; ngx_uint_t log_level;
ngx_uint_t status_code; ngx_uint_t status_code;
ngx_flag_t dry_run;
} ngx_http_limit_conn_conf_t; } ngx_http_limit_conn_conf_t;
@@ -48,6 +61,8 @@ static ngx_rbtree_node_t *ngx_http_limit_conn_lookup(ngx_rbtree_t *rbtree,
static void ngx_http_limit_conn_cleanup(void *data); static void ngx_http_limit_conn_cleanup(void *data);
static ngx_inline void ngx_http_limit_conn_cleanup_all(ngx_pool_t *pool); static ngx_inline void ngx_http_limit_conn_cleanup_all(ngx_pool_t *pool);
static ngx_int_t ngx_http_limit_conn_status_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static void *ngx_http_limit_conn_create_conf(ngx_conf_t *cf); static void *ngx_http_limit_conn_create_conf(ngx_conf_t *cf);
static char *ngx_http_limit_conn_merge_conf(ngx_conf_t *cf, void *parent, static char *ngx_http_limit_conn_merge_conf(ngx_conf_t *cf, void *parent,
void *child); void *child);
@@ -55,6 +70,7 @@ static char *ngx_http_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf); void *conf);
static char *ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd, static char *ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf); void *conf);
static ngx_int_t ngx_http_limit_conn_add_variables(ngx_conf_t *cf);
static ngx_int_t ngx_http_limit_conn_init(ngx_conf_t *cf); static ngx_int_t ngx_http_limit_conn_init(ngx_conf_t *cf);
@@ -102,12 +118,19 @@ static ngx_command_t ngx_http_limit_conn_commands[] = {
offsetof(ngx_http_limit_conn_conf_t, status_code), offsetof(ngx_http_limit_conn_conf_t, status_code),
&ngx_http_limit_conn_status_bounds }, &ngx_http_limit_conn_status_bounds },
{ ngx_string("limit_conn_dry_run"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_limit_conn_conf_t, dry_run),
NULL },
ngx_null_command ngx_null_command
}; };
static ngx_http_module_t ngx_http_limit_conn_module_ctx = { static ngx_http_module_t ngx_http_limit_conn_module_ctx = {
NULL, /* preconfiguration */ ngx_http_limit_conn_add_variables, /* preconfiguration */
ngx_http_limit_conn_init, /* postconfiguration */ ngx_http_limit_conn_init, /* postconfiguration */
NULL, /* create main configuration */ NULL, /* create main configuration */
@@ -137,6 +160,22 @@ ngx_module_t ngx_http_limit_conn_module = {
}; };
static ngx_http_variable_t ngx_http_limit_conn_vars[] = {
{ ngx_string("limit_conn_status"), NULL,
ngx_http_limit_conn_status_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
ngx_http_null_variable
};
static ngx_str_t ngx_http_limit_conn_status[] = {
ngx_string("PASSED"),
ngx_string("REJECTED"),
ngx_string("REJECTED_DRY_RUN")
};
static ngx_int_t static ngx_int_t
ngx_http_limit_conn_handler(ngx_http_request_t *r) ngx_http_limit_conn_handler(ngx_http_request_t *r)
{ {
@@ -144,7 +183,6 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
uint32_t hash; uint32_t hash;
ngx_str_t key; ngx_str_t key;
ngx_uint_t i; ngx_uint_t i;
ngx_slab_pool_t *shpool;
ngx_rbtree_node_t *node; ngx_rbtree_node_t *node;
ngx_pool_cleanup_t *cln; ngx_pool_cleanup_t *cln;
ngx_http_limit_conn_ctx_t *ctx; ngx_http_limit_conn_ctx_t *ctx;
@@ -153,7 +191,7 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
ngx_http_limit_conn_limit_t *limits; ngx_http_limit_conn_limit_t *limits;
ngx_http_limit_conn_cleanup_t *lccln; ngx_http_limit_conn_cleanup_t *lccln;
if (r->main->limit_conn_set) { if (r->main->limit_conn_status) {
return NGX_DECLINED; return NGX_DECLINED;
} }
@@ -179,15 +217,13 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
continue; continue;
} }
r->main->limit_conn_set = 1; r->main->limit_conn_status = NGX_HTTP_LIMIT_CONN_PASSED;
hash = ngx_crc32_short(key.data, key.len); hash = ngx_crc32_short(key.data, key.len);
shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr; ngx_shmtx_lock(&ctx->shpool->mutex);
ngx_shmtx_lock(&shpool->mutex); node = ngx_http_limit_conn_lookup(&ctx->sh->rbtree, &key, hash);
node = ngx_http_limit_conn_lookup(ctx->rbtree, &key, hash);
if (node == NULL) { if (node == NULL) {
@@ -195,11 +231,20 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
+ offsetof(ngx_http_limit_conn_node_t, data) + offsetof(ngx_http_limit_conn_node_t, data)
+ key.len; + key.len;
node = ngx_slab_alloc_locked(shpool, n); node = ngx_slab_alloc_locked(ctx->shpool, n);
if (node == NULL) { if (node == NULL) {
ngx_shmtx_unlock(&shpool->mutex); ngx_shmtx_unlock(&ctx->shpool->mutex);
ngx_http_limit_conn_cleanup_all(r->pool); ngx_http_limit_conn_cleanup_all(r->pool);
if (lccf->dry_run) {
r->main->limit_conn_status =
NGX_HTTP_LIMIT_CONN_REJECTED_DRY_RUN;
return NGX_DECLINED;
}
r->main->limit_conn_status = NGX_HTTP_LIMIT_CONN_REJECTED;
return lccf->status_code; return lccf->status_code;
} }
@@ -210,7 +255,7 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
lc->conn = 1; lc->conn = 1;
ngx_memcpy(lc->data, key.data, key.len); ngx_memcpy(lc->data, key.data, key.len);
ngx_rbtree_insert(ctx->rbtree, node); ngx_rbtree_insert(&ctx->sh->rbtree, node);
} else { } else {
@@ -218,13 +263,23 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
if ((ngx_uint_t) lc->conn >= limits[i].conn) { if ((ngx_uint_t) lc->conn >= limits[i].conn) {
ngx_shmtx_unlock(&shpool->mutex); ngx_shmtx_unlock(&ctx->shpool->mutex);
ngx_log_error(lccf->log_level, r->connection->log, 0, ngx_log_error(lccf->log_level, r->connection->log, 0,
"limiting connections by zone \"%V\"", "limiting connections%s by zone \"%V\"",
lccf->dry_run ? ", dry run," : "",
&limits[i].shm_zone->shm.name); &limits[i].shm_zone->shm.name);
ngx_http_limit_conn_cleanup_all(r->pool); ngx_http_limit_conn_cleanup_all(r->pool);
if (lccf->dry_run) {
r->main->limit_conn_status =
NGX_HTTP_LIMIT_CONN_REJECTED_DRY_RUN;
return NGX_DECLINED;
}
r->main->limit_conn_status = NGX_HTTP_LIMIT_CONN_REJECTED;
return lccf->status_code; return lccf->status_code;
} }
@@ -234,7 +289,7 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"limit conn: %08Xi %d", node->key, lc->conn); "limit conn: %08Xi %d", node->key, lc->conn);
ngx_shmtx_unlock(&shpool->mutex); ngx_shmtx_unlock(&ctx->shpool->mutex);
cln = ngx_pool_cleanup_add(r->pool, cln = ngx_pool_cleanup_add(r->pool,
sizeof(ngx_http_limit_conn_cleanup_t)); sizeof(ngx_http_limit_conn_cleanup_t));
@@ -338,17 +393,15 @@ ngx_http_limit_conn_cleanup(void *data)
{ {
ngx_http_limit_conn_cleanup_t *lccln = data; ngx_http_limit_conn_cleanup_t *lccln = data;
ngx_slab_pool_t *shpool;
ngx_rbtree_node_t *node; ngx_rbtree_node_t *node;
ngx_http_limit_conn_ctx_t *ctx; ngx_http_limit_conn_ctx_t *ctx;
ngx_http_limit_conn_node_t *lc; ngx_http_limit_conn_node_t *lc;
ctx = lccln->shm_zone->data; ctx = lccln->shm_zone->data;
shpool = (ngx_slab_pool_t *) lccln->shm_zone->shm.addr;
node = lccln->node; node = lccln->node;
lc = (ngx_http_limit_conn_node_t *) &node->color; lc = (ngx_http_limit_conn_node_t *) &node->color;
ngx_shmtx_lock(&shpool->mutex); ngx_shmtx_lock(&ctx->shpool->mutex);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, lccln->shm_zone->shm.log, 0, ngx_log_debug2(NGX_LOG_DEBUG_HTTP, lccln->shm_zone->shm.log, 0,
"limit conn cleanup: %08Xi %d", node->key, lc->conn); "limit conn cleanup: %08Xi %d", node->key, lc->conn);
@@ -356,11 +409,11 @@ ngx_http_limit_conn_cleanup(void *data)
lc->conn--; lc->conn--;
if (lc->conn == 0) { if (lc->conn == 0) {
ngx_rbtree_delete(ctx->rbtree, node); ngx_rbtree_delete(&ctx->sh->rbtree, node);
ngx_slab_free_locked(shpool, node); ngx_slab_free_locked(ctx->shpool, node);
} }
ngx_shmtx_unlock(&shpool->mutex); ngx_shmtx_unlock(&ctx->shpool->mutex);
} }
@@ -386,8 +439,6 @@ ngx_http_limit_conn_init_zone(ngx_shm_zone_t *shm_zone, void *data)
ngx_http_limit_conn_ctx_t *octx = data; ngx_http_limit_conn_ctx_t *octx = data;
size_t len; size_t len;
ngx_slab_pool_t *shpool;
ngx_rbtree_node_t *sentinel;
ngx_http_limit_conn_ctx_t *ctx; ngx_http_limit_conn_ctx_t *ctx;
ctx = shm_zone->data; ctx = shm_zone->data;
@@ -406,48 +457,63 @@ ngx_http_limit_conn_init_zone(ngx_shm_zone_t *shm_zone, void *data)
return NGX_ERROR; return NGX_ERROR;
} }
ctx->rbtree = octx->rbtree; ctx->sh = octx->sh;
ctx->shpool = octx->shpool;
return NGX_OK; return NGX_OK;
} }
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; ctx->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
if (shm_zone->shm.exists) { if (shm_zone->shm.exists) {
ctx->rbtree = shpool->data; ctx->sh = ctx->shpool->data;
return NGX_OK; return NGX_OK;
} }
ctx->rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t)); ctx->sh = ngx_slab_alloc(ctx->shpool, sizeof(ngx_http_limit_conn_shctx_t));
if (ctx->rbtree == NULL) { if (ctx->sh == NULL) {
return NGX_ERROR; return NGX_ERROR;
} }
shpool->data = ctx->rbtree; ctx->shpool->data = ctx->sh;
sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t)); ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel,
if (sentinel == NULL) {
return NGX_ERROR;
}
ngx_rbtree_init(ctx->rbtree, sentinel,
ngx_http_limit_conn_rbtree_insert_value); ngx_http_limit_conn_rbtree_insert_value);
len = sizeof(" in limit_conn_zone \"\"") + shm_zone->shm.name.len; len = sizeof(" in limit_conn_zone \"\"") + shm_zone->shm.name.len;
shpool->log_ctx = ngx_slab_alloc(shpool, len); ctx->shpool->log_ctx = ngx_slab_alloc(ctx->shpool, len);
if (shpool->log_ctx == NULL) { if (ctx->shpool->log_ctx == NULL) {
return NGX_ERROR; return NGX_ERROR;
} }
ngx_sprintf(shpool->log_ctx, " in limit_conn_zone \"%V\"%Z", ngx_sprintf(ctx->shpool->log_ctx, " in limit_conn_zone \"%V\"%Z",
&shm_zone->shm.name); &shm_zone->shm.name);
return NGX_OK; return NGX_OK;
} }
static ngx_int_t
ngx_http_limit_conn_status_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
if (r->main->limit_conn_status == 0) {
v->not_found = 1;
return NGX_OK;
}
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
v->len = ngx_http_limit_conn_status[r->main->limit_conn_status - 1].len;
v->data = ngx_http_limit_conn_status[r->main->limit_conn_status - 1].data;
return NGX_OK;
}
static void * static void *
ngx_http_limit_conn_create_conf(ngx_conf_t *cf) ngx_http_limit_conn_create_conf(ngx_conf_t *cf)
{ {
@@ -466,6 +532,7 @@ ngx_http_limit_conn_create_conf(ngx_conf_t *cf)
conf->log_level = NGX_CONF_UNSET_UINT; conf->log_level = NGX_CONF_UNSET_UINT;
conf->status_code = NGX_CONF_UNSET_UINT; conf->status_code = NGX_CONF_UNSET_UINT;
conf->dry_run = NGX_CONF_UNSET;
return conf; return conf;
} }
@@ -485,6 +552,8 @@ ngx_http_limit_conn_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_uint_value(conf->status_code, prev->status_code, ngx_conf_merge_uint_value(conf->status_code, prev->status_code,
NGX_HTTP_SERVICE_UNAVAILABLE); NGX_HTTP_SERVICE_UNAVAILABLE);
ngx_conf_merge_value(conf->dry_run, prev->dry_run, 0);
return NGX_CONF_OK; return NGX_CONF_OK;
} }
@@ -651,6 +720,25 @@ ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
} }
static ngx_int_t
ngx_http_limit_conn_add_variables(ngx_conf_t *cf)
{
ngx_http_variable_t *var, *v;
for (v = ngx_http_limit_conn_vars; v->name.len; v++) {
var = ngx_http_add_variable(cf, &v->name, v->flags);
if (var == NULL) {
return NGX_ERROR;
}
var->get_handler = v->get_handler;
var->data = v->data;
}
return NGX_OK;
}
static ngx_int_t static ngx_int_t
ngx_http_limit_conn_init(ngx_conf_t *cf) ngx_http_limit_conn_init(ngx_conf_t *cf)
{ {
+123 -19
View File
@@ -10,6 +10,13 @@
#include <ngx_http.h> #include <ngx_http.h>
#define NGX_HTTP_LIMIT_REQ_PASSED 1
#define NGX_HTTP_LIMIT_REQ_DELAYED 2
#define NGX_HTTP_LIMIT_REQ_REJECTED 3
#define NGX_HTTP_LIMIT_REQ_DELAYED_DRY_RUN 4
#define NGX_HTTP_LIMIT_REQ_REJECTED_DRY_RUN 5
typedef struct { typedef struct {
u_char color; u_char color;
u_char dummy; u_char dummy;
@@ -44,7 +51,7 @@ typedef struct {
ngx_shm_zone_t *shm_zone; ngx_shm_zone_t *shm_zone;
/* integer value, 1 corresponds to 0.001 r/s */ /* integer value, 1 corresponds to 0.001 r/s */
ngx_uint_t burst; ngx_uint_t burst;
ngx_uint_t nodelay; /* unsigned nodelay:1 */ ngx_uint_t delay;
} ngx_http_limit_req_limit_t; } ngx_http_limit_req_limit_t;
@@ -53,6 +60,7 @@ typedef struct {
ngx_uint_t limit_log_level; ngx_uint_t limit_log_level;
ngx_uint_t delay_log_level; ngx_uint_t delay_log_level;
ngx_uint_t status_code; ngx_uint_t status_code;
ngx_flag_t dry_run;
} ngx_http_limit_req_conf_t; } ngx_http_limit_req_conf_t;
@@ -64,6 +72,8 @@ static ngx_msec_t ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits,
static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx,
ngx_uint_t n); ngx_uint_t n);
static ngx_int_t ngx_http_limit_req_status_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static void *ngx_http_limit_req_create_conf(ngx_conf_t *cf); static void *ngx_http_limit_req_create_conf(ngx_conf_t *cf);
static char *ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent, static char *ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent,
void *child); void *child);
@@ -71,6 +81,7 @@ static char *ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf); void *conf);
static char *ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, static char *ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf); void *conf);
static ngx_int_t ngx_http_limit_req_add_variables(ngx_conf_t *cf);
static ngx_int_t ngx_http_limit_req_init(ngx_conf_t *cf); static ngx_int_t ngx_http_limit_req_init(ngx_conf_t *cf);
@@ -118,12 +129,19 @@ static ngx_command_t ngx_http_limit_req_commands[] = {
offsetof(ngx_http_limit_req_conf_t, status_code), offsetof(ngx_http_limit_req_conf_t, status_code),
&ngx_http_limit_req_status_bounds }, &ngx_http_limit_req_status_bounds },
{ ngx_string("limit_req_dry_run"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_limit_req_conf_t, dry_run),
NULL },
ngx_null_command ngx_null_command
}; };
static ngx_http_module_t ngx_http_limit_req_module_ctx = { static ngx_http_module_t ngx_http_limit_req_module_ctx = {
NULL, /* preconfiguration */ ngx_http_limit_req_add_variables, /* preconfiguration */
ngx_http_limit_req_init, /* postconfiguration */ ngx_http_limit_req_init, /* postconfiguration */
NULL, /* create main configuration */ NULL, /* create main configuration */
@@ -153,6 +171,24 @@ ngx_module_t ngx_http_limit_req_module = {
}; };
static ngx_http_variable_t ngx_http_limit_req_vars[] = {
{ ngx_string("limit_req_status"), NULL,
ngx_http_limit_req_status_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
ngx_http_null_variable
};
static ngx_str_t ngx_http_limit_req_status[] = {
ngx_string("PASSED"),
ngx_string("DELAYED"),
ngx_string("REJECTED"),
ngx_string("DELAYED_DRY_RUN"),
ngx_string("REJECTED_DRY_RUN")
};
static ngx_int_t static ngx_int_t
ngx_http_limit_req_handler(ngx_http_request_t *r) ngx_http_limit_req_handler(ngx_http_request_t *r)
{ {
@@ -165,7 +201,7 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
ngx_http_limit_req_conf_t *lrcf; ngx_http_limit_req_conf_t *lrcf;
ngx_http_limit_req_limit_t *limit, *limits; ngx_http_limit_req_limit_t *limit, *limits;
if (r->main->limit_req_set) { if (r->main->limit_req_status) {
return NGX_DECLINED; return NGX_DECLINED;
} }
@@ -224,15 +260,14 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
return NGX_DECLINED; return NGX_DECLINED;
} }
r->main->limit_req_set = 1;
if (rc == NGX_BUSY || rc == NGX_ERROR) { if (rc == NGX_BUSY || rc == NGX_ERROR) {
if (rc == NGX_BUSY) { if (rc == NGX_BUSY) {
ngx_log_error(lrcf->limit_log_level, r->connection->log, 0, ngx_log_error(lrcf->limit_log_level, r->connection->log, 0,
"limiting requests, excess: %ui.%03ui by zone \"%V\"", "limiting requests%s, excess: %ui.%03ui by zone \"%V\"",
excess / 1000, excess % 1000, lrcf->dry_run ? ", dry run" : "",
&limit->shm_zone->shm.name); excess / 1000, excess % 1000,
&limit->shm_zone->shm.name);
} }
while (n--) { while (n--) {
@@ -251,6 +286,13 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
ctx->node = NULL; ctx->node = NULL;
} }
if (lrcf->dry_run) {
r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_REJECTED_DRY_RUN;
return NGX_DECLINED;
}
r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_REJECTED;
return lrcf->status_code; return lrcf->status_code;
} }
@@ -263,13 +305,22 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
delay = ngx_http_limit_req_account(limits, n, &excess, &limit); delay = ngx_http_limit_req_account(limits, n, &excess, &limit);
if (!delay) { if (!delay) {
r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_PASSED;
return NGX_DECLINED; return NGX_DECLINED;
} }
ngx_log_error(lrcf->delay_log_level, r->connection->log, 0, ngx_log_error(lrcf->delay_log_level, r->connection->log, 0,
"delaying request, excess: %ui.%03ui, by zone \"%V\"", "delaying request%s, excess: %ui.%03ui, by zone \"%V\"",
lrcf->dry_run ? ", dry run" : "",
excess / 1000, excess % 1000, &limit->shm_zone->shm.name); excess / 1000, excess % 1000, &limit->shm_zone->shm.name);
if (lrcf->dry_run) {
r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_DELAYED_DRY_RUN;
return NGX_DECLINED;
}
r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_DELAYED;
if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
} }
@@ -499,12 +550,12 @@ ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits, ngx_uint_t n,
excess = *ep; excess = *ep;
if (excess == 0 || (*limit)->nodelay) { if ((ngx_uint_t) excess <= (*limit)->delay) {
max_delay = 0; max_delay = 0;
} else { } else {
ctx = (*limit)->shm_zone->data; ctx = (*limit)->shm_zone->data;
max_delay = excess * 1000 / ctx->rate; max_delay = (excess - (*limit)->delay) * 1000 / ctx->rate;
} }
while (n--) { while (n--) {
@@ -544,11 +595,11 @@ ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits, ngx_uint_t n,
ctx->node = NULL; ctx->node = NULL;
if (limits[n].nodelay) { if ((ngx_uint_t) excess <= limits[n].delay) {
continue; continue;
} }
delay = excess * 1000 / ctx->rate; delay = (excess - limits[n].delay) * 1000 / ctx->rate;
if (delay > max_delay) { if (delay > max_delay) {
max_delay = delay; max_delay = delay;
@@ -693,6 +744,25 @@ ngx_http_limit_req_init_zone(ngx_shm_zone_t *shm_zone, void *data)
} }
static ngx_int_t
ngx_http_limit_req_status_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
if (r->main->limit_req_status == 0) {
v->not_found = 1;
return NGX_OK;
}
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
v->len = ngx_http_limit_req_status[r->main->limit_req_status - 1].len;
v->data = ngx_http_limit_req_status[r->main->limit_req_status - 1].data;
return NGX_OK;
}
static void * static void *
ngx_http_limit_req_create_conf(ngx_conf_t *cf) ngx_http_limit_req_create_conf(ngx_conf_t *cf)
{ {
@@ -711,6 +781,7 @@ ngx_http_limit_req_create_conf(ngx_conf_t *cf)
conf->limit_log_level = NGX_CONF_UNSET_UINT; conf->limit_log_level = NGX_CONF_UNSET_UINT;
conf->status_code = NGX_CONF_UNSET_UINT; conf->status_code = NGX_CONF_UNSET_UINT;
conf->dry_run = NGX_CONF_UNSET;
return conf; return conf;
} }
@@ -735,6 +806,8 @@ ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_uint_value(conf->status_code, prev->status_code, ngx_conf_merge_uint_value(conf->status_code, prev->status_code,
NGX_HTTP_SERVICE_UNAVAILABLE); NGX_HTTP_SERVICE_UNAVAILABLE);
ngx_conf_merge_value(conf->dry_run, prev->dry_run, 0);
return NGX_CONF_OK; return NGX_CONF_OK;
} }
@@ -875,9 +948,9 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{ {
ngx_http_limit_req_conf_t *lrcf = conf; ngx_http_limit_req_conf_t *lrcf = conf;
ngx_int_t burst; ngx_int_t burst, delay;
ngx_str_t *value, s; ngx_str_t *value, s;
ngx_uint_t i, nodelay; ngx_uint_t i;
ngx_shm_zone_t *shm_zone; ngx_shm_zone_t *shm_zone;
ngx_http_limit_req_limit_t *limit, *limits; ngx_http_limit_req_limit_t *limit, *limits;
@@ -885,7 +958,7 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
shm_zone = NULL; shm_zone = NULL;
burst = 0; burst = 0;
nodelay = 0; delay = 0;
for (i = 1; i < cf->args->nelts; i++) { for (i = 1; i < cf->args->nelts; i++) {
@@ -908,7 +981,19 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
burst = ngx_atoi(value[i].data + 6, value[i].len - 6); burst = ngx_atoi(value[i].data + 6, value[i].len - 6);
if (burst <= 0) { if (burst <= 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid burst rate \"%V\"", &value[i]); "invalid burst value \"%V\"", &value[i]);
return NGX_CONF_ERROR;
}
continue;
}
if (ngx_strncmp(value[i].data, "delay=", 6) == 0) {
delay = ngx_atoi(value[i].data + 6, value[i].len - 6);
if (delay <= 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid delay value \"%V\"", &value[i]);
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
@@ -916,7 +1001,7 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
} }
if (ngx_strcmp(value[i].data, "nodelay") == 0) { if (ngx_strcmp(value[i].data, "nodelay") == 0) {
nodelay = 1; delay = NGX_MAX_INT_T_VALUE / 1000;
continue; continue;
} }
@@ -956,12 +1041,31 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
limit->shm_zone = shm_zone; limit->shm_zone = shm_zone;
limit->burst = burst * 1000; limit->burst = burst * 1000;
limit->nodelay = nodelay; limit->delay = delay * 1000;
return NGX_CONF_OK; return NGX_CONF_OK;
} }
static ngx_int_t
ngx_http_limit_req_add_variables(ngx_conf_t *cf)
{
ngx_http_variable_t *var, *v;
for (v = ngx_http_limit_req_vars; v->name.len; v++) {
var = ngx_http_add_variable(cf, &v->name, v->flags);
if (var == NULL) {
return NGX_ERROR;
}
var->get_handler = v->get_handler;
var->data = v->data;
}
return NGX_OK;
}
static ngx_int_t static ngx_int_t
ngx_http_limit_req_init(ngx_conf_t *cf) ngx_http_limit_req_init(ngx_conf_t *cf)
{ {
+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");
+79 -12
View File
@@ -169,7 +169,14 @@ typedef struct {
#define ngx_mp4_atom_next(mp4, n) \ #define ngx_mp4_atom_next(mp4, n) \
mp4->buffer_pos += (size_t) n; \ \
if (n > (size_t) (mp4->buffer_end - mp4->buffer_pos)) { \
mp4->buffer_pos = mp4->buffer_end; \
\
} else { \
mp4->buffer_pos += (size_t) n; \
} \
\
mp4->offset += n mp4->offset += n
@@ -942,6 +949,13 @@ ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4,
atom_size = ngx_mp4_get_64value(atom_header + 8); atom_size = ngx_mp4_get_64value(atom_header + 8);
atom_header_size = sizeof(ngx_mp4_atom_header64_t); atom_header_size = sizeof(ngx_mp4_atom_header64_t);
if (atom_size < sizeof(ngx_mp4_atom_header64_t)) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"\"%s\" mp4 atom is too small:%uL",
mp4->file.name.data, atom_size);
return NGX_ERROR;
}
} else { } else {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"\"%s\" mp4 atom is too small:%uL", "\"%s\" mp4 atom is too small:%uL",
@@ -3102,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,
@@ -3121,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);
@@ -3212,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;
@@ -3242,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,
@@ -3262,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);
@@ -3395,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;
@@ -3426,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,
@@ -3446,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);
+76 -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;
} }
@@ -4270,6 +4333,7 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf)
cln = ngx_pool_cleanup_add(cf->pool, 0); cln = ngx_pool_cleanup_add(cf->pool, 0);
if (cln == NULL) { if (cln == NULL) {
ngx_ssl_cleanup_ctx(plcf->upstream.ssl);
return NGX_ERROR; return NGX_ERROR;
} }
@@ -98,7 +98,7 @@ ngx_http_random_index_handler(ngx_http_request_t *r)
} }
#if (NGX_HAVE_D_TYPE) #if (NGX_HAVE_D_TYPE)
len = NGX_DIR_MASK_LEN; len = 0;
#else #else
len = NGX_HTTP_RANDOM_INDEX_PREALLOCATE; len = NGX_HTTP_RANDOM_INDEX_PREALLOCATE;
#endif #endif
+47 -11
View File
@@ -700,8 +700,9 @@ ngx_http_range_singlepart_body(ngx_http_request_t *r,
ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in) ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in)
{ {
off_t start, last; off_t start, last;
ngx_int_t rc;
ngx_buf_t *buf; ngx_buf_t *buf;
ngx_chain_t *out, *cl, **ll; ngx_chain_t *out, *cl, *tl, **ll;
ngx_http_range_t *range; ngx_http_range_t *range;
out = NULL; out = NULL;
@@ -721,8 +722,22 @@ ngx_http_range_singlepart_body(ngx_http_request_t *r,
"http range body buf: %O-%O", start, last); "http range body buf: %O-%O", start, last);
if (ngx_buf_special(buf)) { if (ngx_buf_special(buf)) {
*ll = cl;
ll = &cl->next; if (range->end <= start) {
continue;
}
tl = ngx_alloc_chain_link(r->pool);
if (tl == NULL) {
return NGX_ERROR;
}
tl->buf = buf;
tl->next = NULL;
*ll = tl;
ll = &tl->next;
continue; continue;
} }
@@ -764,21 +779,42 @@ ngx_http_range_singlepart_body(ngx_http_request_t *r,
buf->last_buf = (r == r->main) ? 1 : 0; buf->last_buf = (r == r->main) ? 1 : 0;
buf->last_in_chain = 1; buf->last_in_chain = 1;
*ll = cl;
cl->next = NULL;
break; tl = ngx_alloc_chain_link(r->pool);
if (tl == NULL) {
return NGX_ERROR;
}
tl->buf = buf;
tl->next = NULL;
*ll = tl;
ll = &tl->next;
continue;
} }
*ll = cl; tl = ngx_alloc_chain_link(r->pool);
ll = &cl->next; if (tl == NULL) {
return NGX_ERROR;
}
tl->buf = buf;
tl->next = NULL;
*ll = tl;
ll = &tl->next;
} }
if (out == NULL) { rc = ngx_http_next_body_filter(r, out);
return NGX_OK;
while (out) {
cl = out;
out = out->next;
ngx_free_chain(r->pool, cl);
} }
return ngx_http_next_body_filter(r, out); return rc;
} }
+3 -4
View File
@@ -180,12 +180,11 @@ ngx_http_realip_handler(ngx_http_request_t *r)
case NGX_HTTP_REALIP_PROXY: case NGX_HTTP_REALIP_PROXY:
value = &r->connection->proxy_protocol_addr; if (r->connection->proxy_protocol == NULL) {
if (value->len == 0) {
return NGX_DECLINED; return NGX_DECLINED;
} }
value = &r->connection->proxy_protocol->src_addr;
xfwd = NULL; xfwd = NULL;
break; break;
@@ -238,7 +237,7 @@ found:
!= NGX_DECLINED) != NGX_DECLINED)
{ {
if (rlcf->type == NGX_HTTP_REALIP_PROXY) { if (rlcf->type == NGX_HTTP_REALIP_PROXY) {
ngx_inet_set_port(addr.sockaddr, c->proxy_protocol_port); ngx_inet_set_port(addr.sockaddr, c->proxy_protocol->src_port);
} }
return ngx_http_realip_set_addr(r, &addr); return ngx_http_realip_set_addr(r, &addr);
@@ -318,6 +318,11 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts; value = cf->args->elts;
if (value[2].len == 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty replacement");
return NGX_CONF_ERROR;
}
ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
rc.pattern = value[1]; rc.pattern = value[1];
+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;
@@ -1254,9 +1254,9 @@ ngx_http_ssi_parse(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx)
case '-': case '-':
state = ssi_error_end0_state; state = ssi_error_end0_state;
ctx->param->key.data[ctx->param->key.len++] = ch;
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"invalid \"%V\" parameter in \"%V\" SSI command", "unexpected \"-\" symbol after \"%V\" "
"parameter in \"%V\" SSI command",
&ctx->param->key, &ctx->command); &ctx->param->key, &ctx->command);
break; break;
+291 -21
View File
@@ -14,8 +14,8 @@ typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
ngx_pool_t *pool, ngx_str_t *s); ngx_pool_t *pool, ngx_str_t *s);
#define NGX_DEFAULT_CIPHERS "[TLS13+AESGCM+AES128|TLS13+AESGCM+AES256|TLS13+CHACHA20]:[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" #define NGX_DEFAULT_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"
#define NGX_DEFAULT_ECDH_CURVE "X25519:P-256:P-384:P-224:P-521" #define NGX_DEFAULT_ECDH_CURVE "X25519:P-256:P-384"
#define NGX_HTTP_NPN_ADVERTISE "\x08http/1.1" #define NGX_HTTP_NPN_ADVERTISE "\x08http/1.1"
@@ -41,12 +41,17 @@ static void *ngx_http_ssl_create_srv_conf(ngx_conf_t *cf);
static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf,
void *parent, void *child); void *parent, void *child);
static ngx_int_t ngx_http_ssl_compile_certificates(ngx_conf_t *cf,
ngx_http_ssl_srv_conf_t *conf);
static char *ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, static char *ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf); void *conf);
static char *ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, 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);
@@ -71,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"
}; };
@@ -204,6 +217,13 @@ static ngx_command_t ngx_http_ssl_commands[] = {
offsetof(ngx_http_ssl_srv_conf_t, session_timeout), offsetof(ngx_http_ssl_srv_conf_t, session_timeout),
NULL }, NULL },
{ ngx_string("ssl_session_timeout_tls13"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_sec_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_ssl_srv_conf_t, session_timeout_tls13),
NULL },
{ ngx_string("ssl_crl"), { ngx_string("ssl_crl"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot, ngx_conf_set_str_slot,
@@ -211,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,
@@ -585,6 +626,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
* set by ngx_pcalloc(): * set by ngx_pcalloc():
* *
* sscf->protocols = 0; * sscf->protocols = 0;
* sscf->certificate_values = NULL;
* sscf->dhparam = { 0, NULL }; * sscf->dhparam = { 0, NULL };
* sscf->ecdh_curve = { 0, NULL }; * sscf->ecdh_curve = { 0, NULL };
* sscf->client_certificate = { 0, NULL }; * sscf->client_certificate = { 0, NULL };
@@ -592,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 };
*/ */
@@ -607,8 +650,11 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
sscf->passwords = NGX_CONF_UNSET_PTR; sscf->passwords = NGX_CONF_UNSET_PTR;
sscf->builtin_session_cache = NGX_CONF_UNSET; sscf->builtin_session_cache = NGX_CONF_UNSET;
sscf->session_timeout = NGX_CONF_UNSET; sscf->session_timeout = 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;
@@ -641,7 +687,10 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
} }
ngx_conf_merge_value(conf->session_timeout, ngx_conf_merge_value(conf->session_timeout,
prev->session_timeout, 86400); prev->session_timeout, 64800);
ngx_conf_merge_value(conf->session_timeout_tls13,
prev->session_timeout_tls13, 172800);
ngx_conf_merge_value(conf->prefer_server_ciphers, ngx_conf_merge_value(conf->prefer_server_ciphers,
prev->prefer_server_ciphers, 1); prev->prefer_server_ciphers, 1);
@@ -649,8 +698,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->early_data, prev->early_data, 1); ngx_conf_merge_value(conf->early_data, prev->early_data, 1);
ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
(NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1_2|NGX_SSL_TLSv1_3));
|NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2|NGX_SSL_TLSv1_3));
ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
NGX_SSL_BUFSIZE); NGX_SSL_BUFSIZE);
@@ -677,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, "");
@@ -750,6 +803,15 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
cln = ngx_pool_cleanup_add(cf->pool, 0);
if (cln == NULL) {
ngx_ssl_cleanup_ctx(&conf->ssl);
return NGX_CONF_ERROR;
}
cln->handler = ngx_ssl_cleanup_ctx;
cln->data = &conf->ssl;
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx, if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
@@ -773,19 +835,36 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_ssl_npn_advertised, NULL); ngx_http_ssl_npn_advertised, NULL);
#endif #endif
cln = ngx_pool_cleanup_add(cf->pool, 0); if (ngx_http_ssl_compile_certificates(cf, conf) != NGX_OK) {
if (cln == NULL) {
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
cln->handler = ngx_ssl_cleanup_ctx; if (conf->certificate_values) {
cln->data = &conf->ssl;
if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, #ifdef SSL_R_CERT_CB_ERROR
conf->certificate_keys, conf->passwords)
!= NGX_OK) /* install callback to lookup certificates */
{
SSL_CTX_set_cert_cb(conf->ssl.ctx, ngx_http_ssl_certificate, conf);
#else
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"variables in "
"\"ssl_certificate\" and \"ssl_certificate_key\" "
"directives are not supported on this platform");
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
#endif
} else {
/* configure certificates */
if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
conf->certificate_keys, conf->passwords)
!= NGX_OK)
{
return NGX_CONF_ERROR;
}
} }
if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
@@ -801,7 +880,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
if (conf->client_certificate.len == 0 && conf->verify != 3) { if (conf->client_certificate.len == 0 && conf->verify != 3) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0, ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"no ssl_client_certificate for ssl_client_verify"); "no ssl_client_certificate for ssl_verify_client");
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
@@ -826,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;
} }
@@ -842,8 +938,8 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
} }
if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx, if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx,
conf->builtin_session_cache, conf->certificates, conf->builtin_session_cache,
conf->shm_zone, conf->session_timeout) conf->shm_zone, conf->session_timeout, conf->session_timeout_tls13)
!= NGX_OK) != NGX_OK)
{ {
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
@@ -907,6 +1003,90 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
} }
static ngx_int_t
ngx_http_ssl_compile_certificates(ngx_conf_t *cf,
ngx_http_ssl_srv_conf_t *conf)
{
ngx_str_t *cert, *key;
ngx_uint_t i, nelts;
ngx_http_complex_value_t *cv;
ngx_http_compile_complex_value_t ccv;
cert = conf->certificates->elts;
key = conf->certificate_keys->elts;
nelts = conf->certificates->nelts;
for (i = 0; i < nelts; i++) {
if (ngx_http_script_variables_count(&cert[i])) {
goto found;
}
if (ngx_http_script_variables_count(&key[i])) {
goto found;
}
}
return NGX_OK;
found:
conf->certificate_values = ngx_array_create(cf->pool, nelts,
sizeof(ngx_http_complex_value_t));
if (conf->certificate_values == NULL) {
return NGX_ERROR;
}
conf->certificate_key_values = ngx_array_create(cf->pool, nelts,
sizeof(ngx_http_complex_value_t));
if (conf->certificate_key_values == NULL) {
return NGX_ERROR;
}
for (i = 0; i < nelts; i++) {
cv = ngx_array_push(conf->certificate_values);
if (cv == NULL) {
return NGX_ERROR;
}
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
ccv.cf = cf;
ccv.value = &cert[i];
ccv.complex_value = cv;
ccv.zero = 1;
if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
return NGX_ERROR;
}
cv = ngx_array_push(conf->certificate_key_values);
if (cv == NULL) {
return NGX_ERROR;
}
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
ccv.cf = cf;
ccv.value = &key[i];
ccv.complex_value = cv;
ccv.zero = 1;
if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
return NGX_ERROR;
}
}
conf->passwords = ngx_ssl_preserve_passwords(cf, conf->passwords);
if (conf->passwords == NULL) {
return NGX_ERROR;
}
return NGX_OK;
}
static char * static char *
ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{ {
@@ -1062,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)
{ {
@@ -1080,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;
}
} }
} }
+8
View File
@@ -32,10 +32,14 @@ typedef struct {
ssize_t builtin_session_cache; ssize_t builtin_session_cache;
time_t session_timeout; time_t session_timeout;
time_t session_timeout_tls13;
ngx_array_t *certificates; ngx_array_t *certificates;
ngx_array_t *certificate_keys; ngx_array_t *certificate_keys;
ngx_array_t *certificate_values;
ngx_array_t *certificate_key_values;
ngx_str_t dhparam; ngx_str_t dhparam;
ngx_str_t ecdh_curve; ngx_str_t ecdh_curve;
ngx_str_t client_certificate; ngx_str_t client_certificate;
@@ -51,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;
+2 -2
View File
@@ -157,8 +157,8 @@ ngx_http_static_handler(ngx_http_request_t *r)
len = r->uri.len + 1; len = r->uri.len + 1;
if (!clcf->alias && clcf->root_lengths == NULL && r->args.len == 0) { if (!clcf->alias && r->args.len == 0) {
location = path.data + clcf->root.len; location = path.data + root;
*last = '/'; *last = '/';
@@ -178,7 +178,7 @@ ngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data)
ngx_http_upstream_rr_peers_rlock(hp->rrp.peers); ngx_http_upstream_rr_peers_rlock(hp->rrp.peers);
if (hp->tries > 20 || hp->rrp.peers->single) { if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) {
ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); ngx_http_upstream_rr_peers_unlock(hp->rrp.peers);
return hp->get_rr_peer(pc, &hp->rrp); return hp->get_rr_peer(pc, &hp->rrp);
} }
@@ -509,7 +509,7 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data)
ngx_http_upstream_rr_peers_wlock(hp->rrp.peers); ngx_http_upstream_rr_peers_wlock(hp->rrp.peers);
if (hp->tries > 20 || hp->rrp.peers->single) { if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) {
ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); ngx_http_upstream_rr_peers_unlock(hp->rrp.peers);
return hp->get_rr_peer(pc, &hp->rrp); return hp->get_rr_peer(pc, &hp->rrp);
} }
@@ -275,6 +275,7 @@ found:
c->idle = 0; c->idle = 0;
c->sent = 0; c->sent = 0;
c->data = NULL;
c->log = pc->log; c->log = pc->log;
c->read->log = pc->log; c->read->log = pc->log;
c->write->log = pc->log; c->write->log = pc->log;
@@ -545,6 +545,13 @@ ngx_http_userid_create_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
break; break;
#endif #endif
#if (NGX_HAVE_UNIX_DOMAIN)
case AF_UNIX:
ctx->uid_set[0] = 0;
break;
#endif
default: /* AF_INET */ default: /* AF_INET */
sin = (struct sockaddr_in *) c->local_sockaddr; sin = (struct sockaddr_in *) c->local_sockaddr;
ctx->uid_set[0] = sin->sin_addr.s_addr; ctx->uid_set[0] = sin->sin_addr.s_addr;
+38
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)
{ {
@@ -2359,6 +2396,7 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
cln = ngx_pool_cleanup_add(cf->pool, 0); cln = ngx_pool_cleanup_add(cf->pool, 0);
if (cln == NULL) { if (cln == NULL) {
ngx_ssl_cleanup_ctx(uwcf->upstream.ssl);
return NGX_ERROR; return NGX_ERROR;
} }
@@ -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;
} }
@@ -628,7 +629,7 @@ static ngx_int_t
ngx_http_xslt_params(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx, ngx_http_xslt_params(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
ngx_array_t *params, ngx_uint_t final) ngx_array_t *params, ngx_uint_t final)
{ {
u_char *p, *last, *value, *dst, *src, **s; u_char *p, *value, *dst, *src, **s;
size_t len; size_t len;
ngx_uint_t i; ngx_uint_t i;
ngx_str_t string; ngx_str_t string;
@@ -698,8 +699,6 @@ ngx_http_xslt_params(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
ngx_memcpy(p, string.data, string.len + 1); ngx_memcpy(p, string.data, string.len + 1);
} }
last = p + string.len;
while (p && *p) { while (p && *p) {
value = p; value = p;
@@ -729,7 +728,7 @@ ngx_http_xslt_params(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
*p++ = '\0'; *p++ = '\0';
} else { } else {
len = last - value; len = ngx_strlen(value);
} }
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,

Some files were not shown because too many files have changed in this diff Show More