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"]
path = lib/nginx-dav-ext-module
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"]
path = lib/ngx_devel_kit
url = https://github.com/simplresty/ngx_devel_kit.git
@@ -29,7 +23,15 @@
path = lib/zlib
url = https://github.com/cloudflare/zlib.git
branch = gcc.amd64
[submodule "lib/ngx_http_geoip2_module"]
path = lib/ngx_http_geoip2_module
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
49d49835653857daa418e68d6cbfed4958c78fca release-1.15.4
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/)
## 아래의 필수 라이브러리를 설치해주세요.
- 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`
- Ubuntu / Debian - `apt install libjemalloc-dev uuid-dev libatomic1 libatomic-ops-dev expat unzip autoconf automake libtool libgd-dev libmaxminddb-dev g++ 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 libxslt1-dev libxml2-dev g++ curl`
## 설치 방법
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 자동 설정
- **아래 내용은 자동으로 설정됩니다. 따라서, 필요하지 않는 한 해당 설정은 nginx.conf 내에서 설정하지 마십시오.**
- ssl_protocols : TLSv1 TLSv1.1 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_protocols : 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
- 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** 는 사용하지 마십시오. 필요 없습니다.
- TLS v1.3 (draft 23, 26, 28, **final**)
- OpenSSL-1.1.2-dev 사용. (**draft 23, 26, 28, final**)
- 오래된 브라우저를 지원하려면 아래 설정을 이용하십시오. (TLS 버전)
- 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 Patch 파일은 [여기](https://github.com/hakasenyang/openssl-patch)에 있습니다.
- 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!)
- 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 }).
- 만약 두 개 이상의 server 설정이 없다면, SNI 은 활성화되지 않으며 Strict SNI 도 동작하지 않습니다.
- 인증서는 중복으로 설정해도 상관 없습니다.
- "strict_sni_header on" 을 사용하면 잘못 된 헤더에 대한 응답을 하지 않습니다. (strict_sni 와 같이 사용해야만 적용됩니다.)
- 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.)
- OCSP Stapling 사용 시 메모리 공유(shm)
- 기타.
## 더 이상 사용하지 않는 기능
+17 -8
View File
@@ -1,11 +1,13 @@
# Hakase-nginx
**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.
- 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`
- Ubuntu / Debian - `apt install libjemalloc-dev uuid-dev libatomic1 libatomic-ops-dev expat unzip autoconf automake libtool libgd-dev libmaxminddb-dev g++ 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 libxslt1-dev libxml2-dev g++ curl`
## How to Install?
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
- Auto SSL Cipher settings
- **The following information is preset. Do not set it yourself unless you need it.**
- ssl_protocols : TLSv1 TLSv1.1 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_protocols : 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
- 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.
- TLS v1.3 (draft 23, 26, 28, **final**)
- Use OpenSSL-1.1.2-dev (**draft 23, 26, 28, final**)
- Use the settings below to support older browsers. (TLS Protocol)
- 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))
- 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)
@@ -41,6 +48,7 @@ Example Web Server - [https://ssl.hakase.io/](https://ssl.hakase.io/)
- 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))
- 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.
- 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)
@@ -48,6 +56,7 @@ Example Web Server - [https://ssl.hakase.io/](https://ssl.hakase.io/)
## Upcoming Features
- Auto build (rpm, deb, etc.)
- Memory sharing(**shm**) for OCSP Stapling.
- ETC.
## Deprecated Features
+15 -4
View File
@@ -40,7 +40,7 @@ fi
if [ "$BITCHK" = 64 ]; then
if [ ! -f "lib/zlib/Makefile" ]; then
cd lib/zlib
./configure
./configure --64
cd ../..
fi
else
@@ -88,18 +88,23 @@ else
BUILD_OPENSSL_LTO=""
fi
### Temporary Ubuntu/Debian build error (libxslt/libxml2)
### URL : https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=721602
TEMP_OPT="-lm"
### Module check
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 [ "$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 [ "$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 \
--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-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} \
--conf-path=${NGX_CONF} \
--pid-path=${NGX_PID} \
@@ -165,6 +170,12 @@ mkdir -p ${NGX_LIB}
### Check for old files
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
rm ${NGX_SBIN_PATH}.old
systemctl restart nginx
+1 -1
View File
@@ -107,7 +107,7 @@ CORE_LIBS="$CORE_LIBS kernel32.lib user32.lib"
# msvc under Wine issues
# C1902: Program database manager mismatch; please check your installation
if [ -z "$NGX_WINE" ]; then
CFLAGS="$CFLAGS -Zi"
CFLAGS="$CFLAGS -Zi -Fd$NGX_OBJS/nginx.pdb"
CORE_LINK="$CORE_LINK -debug"
fi
+1 -1
View File
@@ -229,7 +229,7 @@ build: binary modules
binary: $NGX_OBJS${ngx_dirsep}nginx$ngx_binext
$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_long_end
+2 -17
View File
@@ -102,21 +102,6 @@ if [ $HTTP = YES ]; then
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
# ngx_http_static_module
# ngx_http_gzip_static_module
@@ -252,13 +237,13 @@ if [ $HTTP = YES ]; then
. auto/module
fi
if [ $HTTP_POSTPONE = YES ]; then
if :; then
ngx_module_name=ngx_http_postpone_filter_module
ngx_module_incs=
ngx_module_deps=
ngx_module_srcs=src/http/ngx_http_postpone_filter_module.c
ngx_module_libs=
ngx_module_link=$HTTP_POSTPONE
ngx_module_link=YES
. auto/module
fi
-1
View File
@@ -61,7 +61,6 @@ HTTP_SSL=NO
HTTP_V2=NO
HTTP_V2_HPACK_ENC=NO
HTTP_SSI=YES
HTTP_POSTPONE=NO
HTTP_REALIP=NO
HTTP_XSLT=NO
HTTP_IMAGE_FILTER=NO
+2 -6
View File
@@ -11,6 +11,7 @@ CORE_SRCS="$WIN32_SRCS $IOCP_SRCS"
OS_CONFIG="$WIN32_CONFIG"
NGX_ICONS="$NGX_WIN32_ICONS"
SELECT_SRCS=$WIN32_SELECT_SRCS
POLL_SRCS=$WIN32_POLL_SRCS
ngx_pic_opt=
ngx_binext=".exe"
@@ -31,12 +32,7 @@ case "$NGX_CC_NAME" in
esac
EVENT_MODULES="$EVENT_MODULES $IOCP_MODULE"
EVENT_FOUND=YES
if [ $EVENT_SELECT = NO ]; then
CORE_SRCS="$CORE_SRCS $SELECT_SRCS"
EVENT_MODULES="$EVENT_MODULES $SELECT_MODULE"
fi
#EVENT_FOUND=YES
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_crc32.c \
src/core/ngx_murmurhash.c \
src/core/ngx_md5.c \
src/core/ngx_sha1.c \
src/core/ngx_rbtree.c \
src/core/ngx_radix_tree.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_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_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
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_name="NGX_HAVE_GMTOFF"
ngx_feature_run=no
+6 -1
View File
@@ -31,7 +31,7 @@ http {
variables_hash_max_size 2048;
# 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 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
@@ -44,11 +44,16 @@ http {
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
# IPv6
#set_real_ip_from 2400:cb00::/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;
# SSL Config
+6 -3
View File
@@ -21,7 +21,7 @@ BUILD_MTS="-j$(expr $(nproc) \+ 1)"
### LTO build
### View : https://gcc.gnu.org/wiki/LinkTimeOptimization#Using_LTO
LTO=1
LTO=0
#########################
### Select add module ###
@@ -32,8 +32,8 @@ LTO=1
### PageSpeed
PAGESPEED=0
### nginx-rtmp-module
RTMP=0
### nginx-http-flv-module
FLV=0
### naxsi
NAXSI=1
@@ -47,6 +47,9 @@ FANCYINDEX=1
### GEOIP2
GEOIP2=1
### nginx-module-vts
VTS=0
##########################
### 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 post_action
syn keyword ngxDirectiveDeprecated contained limit_zone
syn keyword ngxDirectiveDeprecated contained proxy_downstream_buffer
syn keyword ngxDirectiveDeprecated contained proxy_upstream_buffer
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_timeout
syn keyword ngxDirectiveDeprecated contained spdy_streams_index_size
syn keyword ngxDirectiveDeprecated contained ssl
syn keyword ngxDirectiveDeprecated contained upstream_conf
syn keyword ngxDirective contained absolute_redirect
@@ -136,14 +138,20 @@ syn keyword ngxDirective contained alias
syn keyword ngxDirective contained allow
syn keyword ngxDirective contained ancient_browser
syn keyword ngxDirective contained ancient_browser_value
syn keyword ngxDirective contained api
syn keyword ngxDirective contained auth_basic
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_header
syn keyword ngxDirective contained auth_http_pass_client_cert
syn keyword ngxDirective contained auth_http_timeout
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_request
syn keyword ngxDirective contained auth_jwt_leeway
syn keyword ngxDirective contained auth_request
syn keyword ngxDirective contained auth_request_set
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_send_lowat
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_store
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_send_timeout
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_key
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_content
syn keyword ngxDirective contained js_filter
syn keyword ngxDirective contained js_import
syn keyword ngxDirective contained js_include
syn keyword ngxDirective contained js_path
syn keyword ngxDirective contained js_preread
syn keyword ngxDirective contained js_set
syn keyword ngxDirective contained keepalive
syn keyword ngxDirective contained keepalive_disable
syn keyword ngxDirective contained keepalive_requests
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_events
syn keyword ngxDirective contained large_client_header_buffers
syn keyword ngxDirective contained least_conn
syn keyword ngxDirective contained least_time
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_status
syn keyword ngxDirective contained limit_conn_zone
syn keyword ngxDirective contained limit_rate
syn keyword ngxDirective contained limit_rate_after
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_status
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_read_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 min_delete_depth
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 mp4
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_after
syn keyword ngxDirective contained mp4_max_buffer_size
syn keyword ngxDirective contained msie_padding
syn keyword ngxDirective contained msie_refresh
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_redirect
syn keyword ngxDirective contained proxy_request_buffering
syn keyword ngxDirective contained proxy_requests
syn keyword ngxDirective contained proxy_responses
syn keyword ngxDirective contained proxy_send_lowat
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_header
syn keyword ngxDirective contained proxy_socket_keepalive
syn keyword ngxDirective contained proxy_ssl
syn keyword ngxDirective contained proxy_ssl_certificate
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_upload_rate
syn keyword ngxDirective contained queue
syn keyword ngxDirective contained random
syn keyword ngxDirective contained random_index
syn keyword ngxDirective contained read_ahead
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_request_buffering
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_access
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_types
syn keyword ngxDirective contained ssi_value_length
syn keyword ngxDirective contained ssl
syn keyword ngxDirective contained ssl_buffer_size
syn keyword ngxDirective contained ssl_certificate
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_crl
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_engine
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_prefer_server_ciphers
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_request_buffering
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_key
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_types
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
" 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_format_full
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_service_name
@@ -751,8 +798,8 @@ syn keyword ngxDirectiveThirdParty contained auth_pam_set_pam_env
" AJP protocol proxy
" 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_buffer_size
syn keyword ngxDirectiveThirdParty contained ajp_busy_buffers_size
syn keyword ngxDirectiveThirdParty contained ajp_cache
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_headers
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_timeout
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 handler_code
syn keyword ngxDirectiveThirdParty contained handler_name
syn keyword ngxDirectiveThirdParty contained handler_type
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_name
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_var
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 rewrite_handler_code
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 write_page_size
" Certificate Transparency
" https://github.com/grahamedgecombe/nginx-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)
" 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
" 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_footer
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_ignore
syn keyword ngxDirectiveThirdParty contained fancyindex_localtime
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_time_format
@@ -937,10 +994,19 @@ syn keyword ngxDirectiveThirdParty contained notice_type
" 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_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_event_string
syn keyword ngxDirectiveThirdParty contained nchan_channel_group
syn keyword ngxDirectiveThirdParty contained nchan_channel_group_accounting
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_deflate_message_for_websocket
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_max_channels
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_channel_id
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_idle_channel_cache_timeout
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_inheritable
syn keyword ngxDirectiveThirdParty contained nchan_redis_ping_interval
syn keyword ngxDirectiveThirdParty contained nchan_redis_publish_msgpacked_max_size
syn keyword ngxDirectiveThirdParty contained nchan_redis_server
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_wait_after_connecting
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_sub_channel_id
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_channel_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_http_raw_stream_separator
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_fake_shm
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_max_pending_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_regex_cache_max_entries
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_socket_buffer_size
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/
syn keyword ngxDirectiveThirdParty contained passenger_abort_on_startup_error
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_file_descriptor_ulimit
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_root
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_default_group
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_document_root
syn keyword ngxDirectiveThirdParty contained passenger_dump_config_manifest
syn keyword ngxDirectiveThirdParty contained passenger_enabled
syn keyword ngxDirectiveThirdParty contained passenger_env_var
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_meteor_app_settings
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_pass_header
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_force_continuous_timestamps
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_behind
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_set_key
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_check_duplicate
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
" https://github.com/Lax/ngx_http_accounting_module
syn keyword ngxDirectiveThirdParty contained http_accounting
syn keyword ngxDirectiveThirdParty contained http_accounting_id
syn keyword ngxDirectiveThirdParty contained http_accounting_interval
syn keyword ngxDirectiveThirdParty contained http_accounting_log
syn keyword ngxDirectiveThirdParty contained http_accounting_perturb
syn keyword ngxDirectiveThirdParty contained accounting
syn keyword ngxDirectiveThirdParty contained accounting_id
syn keyword ngxDirectiveThirdParty contained accounting_interval
syn keyword ngxDirectiveThirdParty contained accounting_log
syn keyword ngxDirectiveThirdParty contained accounting_perturb
" concatenating files in a given context: CSS and JS files usually
" https://github.com/alibaba/nginx-http-concat
@@ -1917,11 +2005,7 @@ syn keyword ngxDirectiveThirdParty contained concat_unique
" update upstreams' config by restful interface
" https://github.com/yzprofile/ngx_http_dyups_module
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_trylock
syn keyword ngxDirectiveThirdParty contained dyups_upstream_conf
" add given content to the end of the response according to the condition specified
" 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
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.
.\" All rights reserved.
.\"
@@ -25,7 +25,7 @@
.\" SUCH DAMAGE.
.\"
.\"
.Dd June 16, 2015
.Dd December 5, 2019
.Dt NGINX 8
.Os
.Sh NAME
@@ -42,7 +42,8 @@
.Nm
(pronounced
.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
configuration, and low resource consumption.
.Pp
@@ -82,15 +83,15 @@ The following table shows the corresponding system signals:
.It Cm reload
.Dv SIGHUP
.El
.It Fl T
Same as
.Fl t ,
but additionally dump configuration files to standard output.
.It Fl t
Do not run, just test the configuration file.
.Nm
checks the configuration file syntax and then tries to open files
referenced in the configuration file.
.It Fl T
Same as
.Fl t ,
but additionally dump configuration files to standard output.
.It Fl V
Print the
.Nm
+2 -2
View File
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2002-2018 Igor Sysoev
* Copyright (C) 2011-2018 Nginx, Inc.
* Copyright (C) 2002-2019 Igor Sysoev
* Copyright (C) 2011-2019 Nginx, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
+1255
View File
@@ -5,6 +5,1261 @@
<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">
<change type="bugfix">
+3 -4
View File
@@ -6,9 +6,9 @@ TEMP = tmp
CC = cl
OBJS = objs.msvc8
OPENSSL = openssl-1.0.2p
OPENSSL = openssl-1.1.1g
ZLIB = zlib-1.2.11
PCRE = pcre-8.42
PCRE = pcre-8.44
release: export
@@ -65,7 +65,6 @@ win32:
--with-cc-opt=-DFD_SETSIZE=1024 \
--with-pcre=$(OBJS)/lib/$(PCRE) \
--with-zlib=$(OBJS)/lib/$(ZLIB) \
--with-select_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_addition_module \
@@ -83,7 +82,7 @@ win32:
--with-mail \
--with-stream \
--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-mail_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));
ls->fd = (ngx_socket_t) s;
ls->inherited = 1;
}
}
+2 -2
View File
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
#define nginx_version 1015006
#define NGINX_VERSION "1.15.6"
#define nginx_version 1019003
#define NGINX_VERSION "1.19.3"
#define NGINX_VER "nginx/" NGINX_VERSION " by Hakase"
#ifndef NGINX_SERVER
+10 -10
View File
@@ -125,20 +125,20 @@ typedef struct {
#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_only(b) (ngx_buf_in_memory(b) && !b->in_file)
#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_special(b) \
((b->flush || b->last_buf || b->sync) \
&& !ngx_buf_in_memory(b) && !b->in_file)
(((b)->flush || (b)->last_buf || (b)->sync) \
&& !ngx_buf_in_memory(b) && !(b)->in_file)
#define ngx_buf_sync_only(b) \
(b->sync \
&& !ngx_buf_in_memory(b) && !b->in_file && !b->flush && !b->last_buf)
((b)->sync && !ngx_buf_in_memory(b) \
&& !(b)->in_file && !(b)->flush && !(b)->last_buf)
#define ngx_buf_size(b) \
(ngx_buf_in_memory(b) ? (off_t) (b->last - b->pos): \
(b->file_last - b->file_pos))
(ngx_buf_in_memory(b) ? (off_t) ((b)->last - (b)->pos): \
((b)->file_last - (b)->file_pos))
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);
@@ -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);
#define ngx_free_chain(pool, cl) \
cl->next = pool->chain; \
pool->chain = cl
(cl)->next = (pool)->chain; \
(pool)->chain = (cl)
+1 -1
View File
@@ -310,7 +310,7 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
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;
}
+1 -1
View File
@@ -49,7 +49,7 @@
#define NGX_DIRECT_CONF 0x00010000
#define NGX_MAIN_CONF 0x01000000
#define NGX_ANY_CONF 0x1F000000
#define NGX_ANY_CONF 0xFF000000
+18 -5
View File
@@ -1070,7 +1070,8 @@ ngx_close_listening_sockets(ngx_cycle_t *cycle)
if (ls[i].sockaddr->sa_family == AF_UNIX
&& 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;
@@ -1106,12 +1107,9 @@ ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
return NULL;
}
c = ngx_cycle->free_connections;
if (c == NULL) {
ngx_drain_connections((ngx_cycle_t *) ngx_cycle);
c = ngx_cycle->free_connections;
}
if (c == NULL) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
@@ -1297,6 +1295,21 @@ ngx_drain_connections(ngx_cycle_t *cycle)
ngx_queue_t *q;
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);
for (i = 0; i < n; i++) {
+1 -2
View File
@@ -147,8 +147,7 @@ struct ngx_connection_s {
socklen_t socklen;
ngx_str_t addr_text;
ngx_str_t proxy_protocol_addr;
in_port_t proxy_protocol_port;
ngx_proxy_protocol_t *proxy_protocol;
#if (NGX_SSL || NGX_COMPAT)
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_thread_task_s ngx_thread_task_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_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)
{
nls[n].fd = ls[i].fd;
nls[n].inherited = ls[i].inherited;
nls[n].previous = &ls[i];
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) {
ngx_destroy_cycle_pools(&conf);
return NULL;
@@ -945,6 +1009,7 @@ ngx_int_t
ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
{
size_t len;
ngx_int_t rc;
ngx_uint_t create;
ngx_file_t file;
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;
}
rc = NGX_OK;
if (!ngx_test_config) {
len = ngx_snprintf(pid, NGX_INT64_LEN + 2, "%P%N", ngx_pid) - pid;
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);
}
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->shm.log = cf->cycle->log;
shm_zone->shm.addr = NULL;
shm_zone->shm.size = size;
shm_zone->shm.name = *name;
shm_zone->shm.exists = 0;
+1
View File
@@ -55,6 +55,7 @@ struct ngx_cycle_s {
ngx_queue_t reusable_connections_queue;
ngx_uint_t reusable_connections_n;
time_t connections_reuse_time;
ngx_array_t listening;
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;
if (file.len + NGX_DIR_MASK_LEN > buf.len) {
if (file.len > buf.len) {
if (buf.len) {
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);
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;
}
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++) {
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;
test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));
len = test[key] + NGX_HASH_ELT_SIZE(&names[n]);
#if 0
ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
"%ui: %ui %ui \"%V\"",
size, key, test[key], &names[n].key);
"%ui: %ui %uz \"%V\"",
size, key, len, &names[n].key);
#endif
if (test[key] > (u_short) bucket_size) {
if (len > bucket_size) {
goto next;
}
test[key] = (u_short) len;
}
goto found;
@@ -341,7 +351,18 @@ found:
}
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;
+230 -232
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_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_inet_add_addr(ngx_pool_t *pool, ngx_url_t *u,
struct sockaddr *sockaddr, socklen_t socklen, ngx_uint_t total);
in_addr_t
@@ -780,13 +782,10 @@ 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)
{
u_char *p, *host, *port, *last, *uri, *args;
u_char *host, *port, *last, *uri, *args, *dash;
size_t len;
ngx_int_t n;
struct sockaddr_in *sin;
#if (NGX_HAVE_INET6)
struct sockaddr_in6 *sin6;
#endif
u->socklen = sizeof(struct sockaddr_in);
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;
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);
if (n < 1 || n > 65535) {
@@ -838,10 +856,15 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
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;
sin->sin_port = htons((in_port_t) n);
u->port_text.len = len;
u->port_text.len = last - port;
u->port_text.data = port;
last = port - 1;
@@ -853,31 +876,69 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
/* 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 (u->err) {
return NGX_ERROR;
}
if (n < 1 || n > 65535) {
u->err = "invalid port";
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;
sin->sin_port = htons((in_port_t) n);
sin->sin_addr.s_addr = INADDR_ANY;
u->port_text.len = last - host;
u->port_text.data = host;
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->port = u->default_port;
sin->sin_port = htons(u->default_port);
u->last_port = 0;
}
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 == '*') {
sin->sin_addr.s_addr = INADDR_ANY;
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);
@@ -904,33 +965,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
u->wildcard = 1;
}
u->naddrs = 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;
return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1);
}
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->socklen = u->addrs[0].socklen;
ngx_memcpy(&u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen);
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;
}
u->wildcard = ngx_inet_wildcard(&u->sockaddr.sockaddr);
return NGX_OK;
}
@@ -976,7 +989,7 @@ static ngx_int_t
ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
{
#if (NGX_HAVE_INET6)
u_char *p, *host, *port, *last, *uri;
u_char *p, *host, *port, *last, *uri, *dash;
size_t len;
ngx_int_t n;
struct sockaddr_in6 *sin6;
@@ -1022,6 +1035,25 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
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);
if (n < 1 || n > 65535) {
@@ -1029,10 +1061,15 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
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;
sin6->sin6_port = htons((in_port_t) n);
u->port_text.len = len;
u->port_text.len = last - port;
u->port_text.data = port;
} else {
@@ -1061,33 +1098,8 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
}
u->family = AF_INET6;
u->naddrs = 1;
u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
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;
return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1);
#else
@@ -1104,15 +1116,9 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
ngx_int_t
ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
{
u_char *p, *host;
size_t len;
in_port_t port;
ngx_uint_t i;
u_char *host;
ngx_uint_t n;
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);
if (host == NULL) {
@@ -1136,7 +1142,7 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
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) {
@@ -1148,92 +1154,33 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
continue;
}
i++;
n++;
}
if (i == 0) {
if (n == 0) {
u->err = "host not found";
goto failed;
}
/* 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) {
if (rp->ai_family != AF_INET) {
switch (rp->ai_family) {
case AF_INET:
case AF_INET6:
break;
default:
continue;
}
sin = ngx_pcalloc(pool, rp->ai_addrlen);
if (sin == NULL) {
if (ngx_inet_add_addr(pool, u, rp->ai_addr, rp->ai_addrlen, n)
!= NGX_OK)
{
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);
@@ -1250,21 +1197,19 @@ failed:
ngx_int_t
ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
{
u_char *p, *host;
size_t len;
in_port_t port;
in_addr_t in_addr;
ngx_uint_t i;
u_char *host;
ngx_uint_t i, n;
struct hostent *h;
struct sockaddr_in *sin;
struct sockaddr_in sin;
/* 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);
if (host == NULL) {
return NGX_ERROR;
@@ -1281,76 +1226,31 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
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() */
u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
if (u->addrs == NULL) {
for (i = 0; i < n; i++) {
sin.sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
if (ngx_inet_add_addr(pool, u, (struct sockaddr *) &sin,
sizeof(struct sockaddr_in), n)
!= NGX_OK)
{
return NGX_ERROR;
}
u->naddrs = i;
for (i = 0; i < u->naddrs; i++) {
sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
if (sin == NULL) {
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 {
/* MP: ngx_shared_palloc() */
u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
if (u->addrs == NULL) {
if (ngx_inet_add_addr(pool, u, (struct sockaddr *) &sin,
sizeof(struct sockaddr_in), 1)
!= NGX_OK)
{
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;
@@ -1359,6 +1259,67 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
#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_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1,
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;
}
}
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 default_port;
in_port_t last_port;
int family;
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);
in_port_t ngx_inet_get_port(struct sockaddr *sa);
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_ */
+5 -9
View File
@@ -12,17 +12,13 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <openssl/md5.h>
typedef struct {
uint64_t bytes;
uint32_t a, b, c, d;
u_char buffer[64];
} ngx_md5_t;
typedef MD5_CTX ngx_md5_t;
void ngx_md5_init(ngx_md5_t *ctx);
void ngx_md5_update(ngx_md5_t *ctx, const void *data, size_t size);
void ngx_md5_final(u_char result[16], ngx_md5_t *ctx);
#define ngx_md5_init MD5_Init
#define ngx_md5_update MD5_Update
#define ngx_md5_final MD5_Final
#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;
}
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)) {
/* 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) {
#if 1
if (ngx_buf_size(in->buf) == 0 && !ngx_buf_special(in->buf)) {
ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
@@ -685,7 +704,26 @@ ngx_chain_writer(void *data, ngx_chain_t *in)
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);
@@ -709,7 +747,6 @@ ngx_chain_writer(void *data, ngx_chain_t *in)
for (cl = ctx->out; cl; cl = cl->next) {
#if 1
if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
@@ -729,7 +766,26 @@ ngx_chain_writer(void *data, ngx_chain_t *in)
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);
}
+151 -72
View File
@@ -40,6 +40,10 @@ typedef struct {
} 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,
u_char *last);
@@ -48,8 +52,8 @@ u_char *
ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
{
size_t len;
u_char ch, *p, *addr, *port;
ngx_int_t n;
u_char *p;
ngx_proxy_protocol_t *pp;
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;
addr = p;
for ( ;; ) {
if (p == last) {
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) {
pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t));
if (pp == NULL) {
return NULL;
}
ngx_memcpy(c->proxy_protocol_addr.data, addr, len);
c->proxy_protocol_addr.len = len;
p = ngx_proxy_protocol_read_addr(c, p, last, &pp->src_addr);
if (p == NULL) {
goto invalid;
}
p = ngx_proxy_protocol_read_addr(c, p, last, &pp->dst_addr);
if (p == NULL) {
goto invalid;
}
p = ngx_proxy_protocol_read_port(p, last, &pp->src_port, ' ');
if (p == NULL) {
goto invalid;
}
p = ngx_proxy_protocol_read_port(p, last, &pp->dst_port, CR);
if (p == NULL) {
goto invalid;
}
for ( ;; ) {
if (p == last) {
goto invalid;
}
if (*p++ == ' ') {
break;
}
}
port = p;
for ( ;; ) {
if (p == last) {
if (*p++ != LF) {
goto invalid;
}
if (*p++ == ' ') {
break;
}
}
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);
len = p - port - 1;
c->proxy_protocol = pp;
n = ngx_atoi(port, len);
if (n < 0 || n > 65535) {
goto invalid;
}
c->proxy_protocol_port = (in_port_t) n;
ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
"PROXY protocol address: %V %d", &c->proxy_protocol_addr,
c->proxy_protocol_port);
return p;
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 *
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;
socklen_t socklen;
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_inet_addrs_t *in;
#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;
}
pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t));
if (pp == NULL) {
return NULL;
}
family = header->family_transport >> 4;
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;
sockaddr.sockaddr_in.sin_family = AF_INET;
sockaddr.sockaddr_in.sin_port = 0;
memcpy(&sockaddr.sockaddr_in.sin_addr, in->src_addr, 4);
src_sockaddr.sockaddr_in.sin_family = AF_INET;
src_sockaddr.sockaddr_in.sin_port = 0;
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);
@@ -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;
sockaddr.sockaddr_in6.sin6_family = AF_INET6;
sockaddr.sockaddr_in6.sin6_port = 0;
memcpy(&sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16);
src_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
src_sockaddr.sockaddr_in6.sin6_port = 0;
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);
@@ -321,23 +391,32 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
return end;
}
c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
if (c->proxy_protocol_addr.data == NULL) {
pp->src_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
if (pp->src_addr.data == NULL) {
return NULL;
}
c->proxy_protocol_addr.len = ngx_sock_ntop(&sockaddr.sockaddr, socklen,
c->proxy_protocol_addr.data,
NGX_SOCKADDR_STRLEN, 0);
pp->src_addr.len = ngx_sock_ntop(&src_sockaddr.sockaddr, socklen,
pp->src_addr.data, NGX_SOCKADDR_STRLEN, 0);
ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
"PROXY protocol v2 address: %V %d", &c->proxy_protocol_addr,
c->proxy_protocol_port);
pp->dst_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
if (pp->dst_addr.data == NULL) {
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) {
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
"PROXY protocol v2 %z bytes of tlv ignored", end - buf);
}
c->proxy_protocol = pp;
return end;
}
+8
View File
@@ -16,6 +16,14 @@
#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 *last);
u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf,
-5
View File
@@ -174,13 +174,8 @@ ngx_rbtree_delete(ngx_rbtree_t *tree, ngx_rbtree_node_t *node)
} else {
subst = ngx_rbtree_min(node->right, sentinel);
if (subst->left != sentinel) {
temp = subst->left;
} else {
temp = subst->right;
}
}
if (subst == *root) {
*root = temp;
+10 -1
View File
@@ -972,7 +972,8 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
name = ngx_resolver_dup(r, rn->name, rn->nlen);
if (name == NULL) {
goto failed;
ngx_resolver_free(r, ctx);
return NGX_ERROR;
}
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) {
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->handler(ctx);
+5 -9
View File
@@ -12,17 +12,13 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <openssl/sha.h>
typedef struct {
uint64_t bytes;
uint32_t a, b, c, d, e, f;
u_char buffer[64];
} ngx_sha1_t;
typedef SHA_CTX ngx_sha1_t;
void ngx_sha1_init(ngx_sha1_t *ctx);
void ngx_sha1_update(ngx_sha1_t *ctx, const void *data, size_t size);
void ngx_sha1_final(u_char result[20], ngx_sha1_t *ctx);
#define ngx_sha1_init SHA1_Init
#define ngx_sha1_update SHA1_Update
#define ngx_sha1_final SHA1_Final
#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;
}
n = ((u_char *) p - pool->start) >> ngx_pagesize_shift;
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);
+9 -1
View File
@@ -1381,7 +1381,7 @@ ngx_utf8_length(u_char *p, size_t n)
continue;
}
if (ngx_utf8_decode(&p, n) > 0x10ffff) {
if (ngx_utf8_decode(&p, last - p) > 0x10ffff) {
/* invalid UTF-8 */
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)
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_memset(buf, c, n) (void) memset(buf, c, n)
void ngx_explicit_memzero(void *buf, size_t n);
#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) {
rev->ready = 1;
rev->available = -1;
if (flags & NGX_POST_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) {
rev->pending_eof = 1;
}
rev->available = 1;
#endif
rev->ready = 1;
rev->available = -1;
if (flags & NGX_POST_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));
sev.sigev_notify = SIGEV_PORT;
#if !(NGX_TEST_BUILD_EVENTPORT)
sev.sigev_value.sival_ptr = &pn;
#endif
if (timer_create(CLOCK_REALTIME, &sev, &event_timer) == -1) {
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) {
rev->ready = 1;
rev->available = -1;
if (flags & NGX_POST_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) {
ngx_memcpy(list, event_list, sizeof(ngx_event_t *) * nevents);
ngx_memcpy(list, event_list, sizeof(struct pollfd) * nevents);
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->ready = 1;
ev->available = -1;
queue = ev->accept ? &ngx_posted_accept_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) {
ev->ready = 1;
ev->available = -1;
queue = ev->accept ? &ngx_posted_accept_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 work_read_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_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_write_fd_set = master_write_fd_set;
work_except_fd_set = master_write_fd_set;
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 {
@@ -306,14 +309,20 @@ ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
if (ev->write) {
if (FD_ISSET(c->fd, &work_write_fd_set)) {
found = 1;
found++;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"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 {
if (FD_ISSET(c->fd, &work_read_fd_set)) {
found = 1;
found++;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"select read %d", c->fd);
}
@@ -321,13 +330,14 @@ ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
if (found) {
ev->ready = 1;
ev->available = -1;
queue = ev->accept ? &ngx_posted_accept_events
: &ngx_posted_events;
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;
(void) ngx_process_events(cycle, timer, flags);
@@ -639,6 +644,7 @@ ngx_event_process_init(ngx_cycle_t *cycle)
#endif
ngx_queue_init(&ngx_posted_accept_events);
ngx_queue_init(&ngx_posted_next_events);
ngx_queue_init(&ngx_posted_events);
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
* 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
*
* 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;
#else
unsigned available:1;
#endif
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) \
(*(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_udp_rbtree_insert_value(ngx_rbtree_node_t *temp,
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_enable_accept_events(ngx_cycle_t *cycle);
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 transparent:1;
unsigned so_keepalive:1;
unsigned down:1;
/* ngx_connection_log_error_e */
unsigned log_error:2;
+580 -175
View File
@@ -18,6 +18,10 @@ typedef struct {
} 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,
void *userdata);
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 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,
ngx_ssl_session_t *sess);
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,
unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
HMAC_CTX *hctx, int enc);
static void ngx_ssl_session_ticket_keys_cleanup(void *data);
#endif
#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_session_cache_index;
int ngx_ssl_session_ticket_keys_index;
int ngx_ssl_ocsp_index;
int ngx_ssl_certificate_index;
int ngx_ssl_next_certificate_index;
int ngx_ssl_certificate_name_index;
@@ -159,7 +165,6 @@ ngx_ssl_init(ngx_log_t *log)
#endif
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef SSL_OP_NO_COMPRESSION
{
/*
@@ -176,7 +181,6 @@ ngx_ssl_init(ngx_log_t *log)
(void) sk_SSL_COMP_pop(ssl_comp_methods);
}
}
#endif
#endif
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;
}
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,
NULL);
if (ngx_ssl_certificate_index == -1) {
@@ -345,6 +356,11 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
}
#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
SSL_CTX_set_min_proto_version(ssl->ctx, 0);
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);
#endif
#ifdef SSL_OP_NO_CLIENT_RENEGOTIATION
SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_CLIENT_RENEGOTIATION);
#endif
#ifdef SSL_MODE_RELEASE_BUFFERS
SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
@@ -409,34 +429,19 @@ 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)
{
BIO *bio;
char *err;
X509 *x509;
u_long n;
ngx_str_t *pwd;
ngx_uint_t tries;
EVP_PKEY *pkey;
STACK_OF(X509) *chain;
if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
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);
x509 = ngx_ssl_load_certificate(cf->pool, &err, cert, &chain);
if (x509 == NULL) {
if (err != NULL) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"PEM_read_bio_X509_AUX(\"%s\") failed", cert->data);
BIO_free(bio);
"cannot load certificate \"%s\": %s",
cert->data, err);
}
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,
"SSL_CTX_use_certificate(\"%s\") failed", cert->data);
X509_free(x509);
BIO_free(bio);
sk_X509_pop_free(chain, X509_free);
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");
X509_free(x509);
BIO_free(bio);
sk_X509_pop_free(chain, X509_free);
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");
X509_free(x509);
BIO_free(bio);
sk_X509_pop_free(chain, X509_free);
return NGX_ERROR;
}
if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509)
== 0)
{
if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509) == 0) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_set_ex_data() failed");
X509_free(x509);
BIO_free(bio);
sk_X509_pop_free(chain, X509_free);
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 ( ;; ) {
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
if (x509 == NULL) {
temp = PEM_read_bio_X509(bio, NULL, NULL, NULL);
if (temp == NULL) {
n = ERR_peek_last_error();
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 */
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"PEM_read_bio_X509(\"%s\") failed", cert->data);
*err = "PEM_read_bio_X509() failed";
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);
BIO_free(bio);
return NGX_ERROR;
sk_X509_pop_free(*chain, X509_free);
return NULL;
}
#else
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);
if (sk_X509_push(*chain, temp) == 0) {
*err = "sk_X509_push() failed";
BIO_free(bio);
X509_free(x509);
BIO_free(bio);
return NGX_ERROR;
sk_X509_pop_free(*chain, X509_free);
return NULL;
}
#endif
}
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) {
#ifndef OPENSSL_NO_ENGINE
u_char *p, *last;
ENGINE *engine;
EVP_PKEY *pkey;
p = key->data + sizeof("engine:") - 1;
last = (u_char *) ngx_strchr(p, ':');
if (last == NULL) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid syntax in \"%V\"", key);
return NGX_ERROR;
*err = "invalid syntax";
return NULL;
}
*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);
if (engine == NULL) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"ENGINE_by_id(\"%s\") failed", p);
return NGX_ERROR;
*err = "ENGINE_by_id() failed";
return NULL;
}
*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);
if (pkey == NULL) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"ENGINE_load_private_key(\"%s\") failed", last);
*err = "ENGINE_load_private_key() failed";
ENGINE_free(engine);
return NGX_ERROR;
return NULL;
}
ENGINE_free(engine);
if (SSL_CTX_use_PrivateKey(ssl->ctx, pkey) == 0) {
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;
return pkey;
#else
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"loading \"engine:...\" certificate keys "
"is not supported");
return NGX_ERROR;
*err = "loading \"engine:...\" certificate keys is not supported";
return NULL;
#endif
}
if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) {
return NGX_ERROR;
if (ngx_strncmp(key->data, "data:", sizeof("data:") - 1) == 0) {
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) {
tries = passwords->nelts;
pwd = passwords->elts;
SSL_CTX_set_default_passwd_cb(ssl->ctx, ngx_ssl_password_callback);
SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, pwd);
cb = ngx_ssl_password_callback;
} else {
tries = 1;
#if (NGX_SUPPRESS_WARN)
pwd = NULL;
#endif
cb = NULL;
}
for ( ;; ) {
if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data,
SSL_FILETYPE_PEM)
!= 0)
{
pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, pwd);
if (pkey != NULL) {
break;
}
if (--tries) {
if (tries-- > 1) {
ERR_clear_error();
SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, ++pwd);
(void) BIO_reset(bio);
pwd++;
continue;
}
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_use_PrivateKey_file(\"%s\") failed", key->data);
return NGX_ERROR;
*err = "PEM_read_bio_PrivateKey() failed";
BIO_free(bio);
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;
}
if (pwd == NULL) {
return 0;
}
if (pwd->len > (size_t) size) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"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;
}
/*
* 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);
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_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);
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.
*/
rbio = SSL_get_rbio((ngx_ssl_conn_t *) ssl_conn);
wbio = SSL_get_wbio((ngx_ssl_conn_t *) ssl_conn);
rbio = SSL_get_rbio(ssl_conn);
wbio = SSL_get_wbio(ssl_conn);
if (rbio != wbio) {
(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;
}
cln = ngx_pool_cleanup_add(cf->temp_pool, 0);
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;
}
@@ -1054,12 +1244,75 @@ cleanup:
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;
}
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
ngx_ssl_passwords_cleanup(void *data)
{
@@ -1071,7 +1324,7 @@ ngx_ssl_passwords_cleanup(void *data)
pwd = passwords->elts;
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_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
{
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#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);
#endif
#endif
#endif
return NGX_OK;
@@ -1363,6 +1614,7 @@ ngx_ssl_handshake(ngx_connection_t *c)
{
int n, sslerr;
ngx_err_t err;
ngx_int_t rc;
#ifdef SSL_READ_EARLY_DATA_SUCCESS
if (c->ssl->try_early_data) {
@@ -1370,6 +1622,10 @@ ngx_ssl_handshake(ngx_connection_t *c)
}
#endif
if (c->ssl->in_ocsp) {
return ngx_ssl_ocsp_validate(c);
}
ngx_ssl_clear_error(c->log);
n = SSL_do_handshake(c->ssl->connection);
@@ -1390,8 +1646,6 @@ ngx_ssl_handshake(ngx_connection_t *c)
ngx_ssl_handshake_log(c);
#endif
c->ssl->handshaked = 1;
c->recv = ngx_ssl_recv;
c->send = ngx_ssl_write;
c->recv_chain = ngx_ssl_recv_chain;
@@ -1410,6 +1664,20 @@ ngx_ssl_handshake(ngx_connection_t *c)
#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;
}
@@ -1479,6 +1747,7 @@ ngx_ssl_try_early_data(ngx_connection_t *c)
u_char buf;
size_t readbytes;
ngx_err_t err;
ngx_int_t rc;
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_preread = 1;
c->ssl->handshaked = 1;
c->ssl->in_early = 1;
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->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;
}
@@ -1691,6 +1973,10 @@ ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl, off_t limit)
last += n;
bytes += n;
if (!c->read->ready) {
return bytes;
}
if (last == b->end) {
cl = cl->next;
@@ -1768,6 +2054,47 @@ ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
if (size == 0) {
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;
}
@@ -1843,6 +2170,10 @@ ngx_ssl_recv_early(ngx_connection_t *c, u_char *buf, size_t size)
buf += 1;
}
if (c->ssl->write_blocked) {
return NGX_AGAIN;
}
/*
* SSL_read_early_data() may return data in parts, so try to read
* 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);
}
if (c->ssl->write_blocked) {
c->ssl->write_blocked = 0;
ngx_post_event(c->read, &ngx_posted_events);
}
c->sent += 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) {
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
"SSL_write_early_data: want write");
if (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);
}
/*
* 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;
return NGX_AGAIN;
}
@@ -2476,6 +2823,9 @@ ngx_ssl_shutdown(ngx_connection_t *c)
{
int n, sslerr, mode;
ngx_err_t err;
ngx_uint_t tries;
ngx_ssl_ocsp_cleanup(c);
if (SSL_in_init(c->ssl->connection)) {
/*
@@ -2514,28 +2864,38 @@ ngx_ssl_shutdown(ngx_connection_t *c)
ngx_ssl_clear_error(c->log);
tries = 2;
for ( ;; ) {
/*
* 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.
*/
n = SSL_shutdown(c->ssl->connection);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
sslerr = 0;
/* 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);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"SSL_get_error: %d", sslerr);
}
if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) {
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 */
sslerr = SSL_get_error(c->ssl->connection, n);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"SSL_get_error: %d", sslerr);
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;
@@ -2548,13 +2908,18 @@ ngx_ssl_shutdown(ngx_connection_t *c)
return NGX_ERROR;
}
if (sslerr == SSL_ERROR_WANT_READ) {
ngx_add_timer(c->read, 30000);
}
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");
@@ -2563,6 +2928,7 @@ ngx_ssl_shutdown(ngx_connection_t *c)
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 (err == NGX_ECONNRESET
#if (NGX_WIN32)
|| err == NGX_ECONNABORTED
#endif
|| err == NGX_EPIPE
|| err == NGX_ENOTCONN
|| 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_SHARED_CIPHER /* 193 */
|| n == SSL_R_RECORD_LENGTH_MISMATCH /* 213 */
#ifdef SSL_R_CLIENTHELLO_TLSEXT
|| n == SSL_R_CLIENTHELLO_TLSEXT /* 226 */
#endif
#ifdef SSL_R_PARSE_TLSEXT
|| n == SSL_R_PARSE_TLSEXT /* 227 */
#endif
#ifdef SSL_R_CALLBACK_FAILED
|| n == SSL_R_CALLBACK_FAILED /* 234 */
#endif
|| n == SSL_R_UNEXPECTED_MESSAGE /* 244 */
|| 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
|| n == SSL_R_INAPPROPRIATE_FALLBACK /* 373 */
#endif
#ifdef SSL_R_CERT_CB_ERROR
|| n == SSL_R_CERT_CB_ERROR /* 377 */
#endif
#ifdef SSL_R_VERSION_TOO_LOW
|| n == SSL_R_VERSION_TOO_LOW /* 396 */
#endif
@@ -2782,6 +3160,7 @@ 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);
va_end(args);
if (ERR_peek_error()) {
p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p);
for ( ;; ) {
@@ -2816,19 +3195,26 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
(void) ERR_get_error();
}
ngx_log_error(level, log, err, "%*s)", p - errstr, errstr);
if (p < last) {
*p++ = ')';
}
}
ngx_log_error(level, log, err, "%*s", p - errstr, errstr);
}
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)
{
long cache_mode;
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;
}
@@ -2894,11 +3280,14 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
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;
X509 *cert;
X509_NAME *name;
ngx_str_t *certs;
ngx_uint_t k;
EVP_MD_CTX *md;
unsigned int len;
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);
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) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"EVP_DigestUpdate() failed");
"EVP_DigestFinal_ex() 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);
#else
session_id = sess->session_id;
session_id_length = sess->session_id_length;
#endif
#if (NGX_PTR_SIZE == 8)
id = sess_id->sess_id;
@@ -3210,13 +3608,10 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
#endif
u_char *id, int len, int *copy)
{
#if OPENSSL_VERSION_NUMBER >= 0x0090707fL
const
#endif
u_char *p;
size_t slen;
uint32_t hash;
ngx_int_t rc;
const u_char *p;
ngx_shm_zone_t *shm_zone;
ngx_slab_pool_t *shpool;
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;
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
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);
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_array_t *keys;
ngx_file_info_t fi;
ngx_pool_cleanup_t *cln;
ngx_ssl_session_ticket_key_t *key;
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;
}
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;
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_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)
@@ -3611,6 +4008,8 @@ failed:
ngx_close_file_n " \"%V\" failed", &file.name);
}
ngx_explicit_memzero(&buf, 80);
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
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;
}
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
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->data = ngx_pnalloc(pool, 2 * len);
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);
if (name == NULL) {
X509_free(cert);
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);
if (name == NULL) {
X509_free(cert);
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);
if (rc == X509_V_OK) {
if (ngx_ssl_ocsp_get_status(c, &str) == NGX_OK) {
ngx_str_set(s, "SUCCESS");
return NGX_OK;
}
} else {
str = X509_verify_cert_error_string(rc);
}
s->data = ngx_pnalloc(pool, sizeof("FAILED:") - 1 + ngx_strlen(str));
if (s->data == NULL) {
+24 -1
View File
@@ -72,6 +72,9 @@ typedef struct {
} ngx_ssl_dyn_rec_t;
typedef struct ngx_ssl_ocsp_s ngx_ssl_ocsp_t;
struct ngx_ssl_s {
SSL_CTX *ctx;
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_write_handler;
ngx_ssl_ocsp_t *ocsp;
u_char early_buf;
unsigned handshaked:1;
@@ -106,7 +111,9 @@ struct ngx_ssl_connection_s {
unsigned handshake_buffer_set:1;
unsigned try_early_data:1;
unsigned in_early:1;
unsigned in_ocsp:1;
unsigned early_preread:1;
unsigned write_blocked:1;
ngx_ssl_dyn_rec_t dyn_rec;
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_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_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_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_uint_t prefer_server_ciphers);
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_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
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,
int key_length);
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_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,
@@ -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_uint_t enable);
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_array_t *paths);
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_session_cache_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_next_certificate_index;
extern int ngx_ssl_certificate_name_index;
+1066 -172
View File
@@ -22,6 +22,7 @@ typedef struct {
ngx_msec_t resolver_timeout;
ngx_addr_t *addrs;
ngx_uint_t naddrs;
ngx_str_t host;
ngx_str_t uri;
in_port_t port;
@@ -30,6 +31,7 @@ typedef struct {
X509 *cert;
X509 *issuer;
STACK_OF(X509) *chain;
u_char *name;
@@ -41,15 +43,66 @@ typedef struct {
} 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;
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 {
SSL_CTX *ssl_ctx;
X509 *cert;
X509 *issuer;
STACK_OF(X509) *chain;
int status;
time_t valid;
u_char *name;
ngx_uint_t naddrs;
ngx_uint_t naddr;
ngx_addr_t *addrs;
ngx_str_t host;
@@ -64,17 +117,20 @@ struct ngx_ssl_ocsp_ctx_s {
void (*handler)(ngx_ssl_ocsp_ctx_t *ctx);
void *data;
ngx_str_t key;
ngx_buf_t *request;
ngx_buf_t *response;
ngx_peer_connection_t peer;
ngx_shm_zone_t *shm_zone;
ngx_int_t (*process)(ngx_ssl_ocsp_ctx_t *ctx);
ngx_uint_t state;
ngx_uint_t code;
ngx_uint_t count;
ngx_uint_t flags;
ngx_uint_t done;
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 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_next(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_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_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_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);
@@ -173,6 +240,18 @@ ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, X509 *cert,
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->timeout = 60000;
staple->verify = verify;
@@ -227,7 +306,7 @@ ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
return NGX_ERROR;
}
bio = BIO_new_file((char *) file->data, "r");
bio = BIO_new_file((char *) file->data, "rb");
if (bio == NULL) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"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_STORE *store;
X509_STORE_CTX *store_ctx;
STACK_OF(X509) *chain;
cert = staple->cert;
#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, &chain);
#else
chain = ssl->ctx->extra_certs;
#endif
n = sk_X509_num(chain);
n = sk_X509_num(staple->chain);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
"SSL get issuer: %d extra certs", n);
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 OPENSSL_VERSION_NUMBER >= 0x10100001L
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->naddrs = u.naddrs;
staple->host = u.host;
staple->uri = u.uri;
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;
cert = SSL_get_certificate(ssl_conn);
if (cert == NULL) {
return rc;
}
staple = X509_get_ex_data(cert, ngx_ssl_stapling_index);
if (staple == NULL) {
@@ -554,16 +626,20 @@ ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
staple->loading = 1;
ctx = ngx_ssl_ocsp_start();
ctx = ngx_ssl_ocsp_start(ngx_cycle->log);
if (ctx == NULL) {
return;
}
ctx->ssl_ctx = staple->ssl_ctx;
ctx->cert = staple->cert;
ctx->issuer = staple->issuer;
ctx->chain = staple->chain;
ctx->name = staple->name;
ctx->flags = (staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY);
ctx->addrs = staple->addrs;
ctx->naddrs = staple->naddrs;
ctx->host = staple->host;
ctx->uri = staple->uri;
ctx->port = staple->port;
@@ -584,140 +660,27 @@ ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
static void
ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
{
#if OPENSSL_VERSION_NUMBER >= 0x0090707fL
const
#endif
u_char *p;
int n;
size_t len;
time_t now, valid;
time_t now;
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;
now = ngx_time();
ocsp = NULL;
basic = NULL;
id = NULL;
if (ctx->code != 200) {
if (ngx_ssl_ocsp_verify(ctx) != NGX_OK) {
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(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) {
if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
"certificate status \"%s\" in the OCSP response",
OCSP_cert_status_str(n));
OCSP_cert_status_str(ctx->status));
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 */
response.len = len;
response.len = ctx->response->last - ctx->response->pos;
response.data = ngx_alloc(response.len, ctx->log);
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_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) {
ngx_free(staple->staple.data);
}
staple->staple = response;
staple->valid = valid;
staple->valid = ctx->valid;
/*
* refresh before the response expires,
@@ -743,7 +702,7 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
*/
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);
return;
@@ -753,18 +712,6 @@ error:
staple->loading = 0;
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);
}
@@ -818,14 +765,507 @@ ngx_ssl_stapling_cleanup(void *data)
}
static ngx_ssl_ocsp_ctx_t *
ngx_ssl_ocsp_start(void)
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_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_ssl_ocsp_ctx_t *ctx;
pool = ngx_create_pool(2048, ngx_cycle->log);
pool = ngx_create_pool(2048, log);
if (pool == 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
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 (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,
"no resolver defined to resolve %V", &ctx->host);
goto connect;
@@ -1021,15 +1499,16 @@ static void
ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
{
ngx_int_t rc;
ngx_addr_t *addr;
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
"ssl ocsp connect");
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
"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.socklen = ctx->addrs[0].socklen;
ctx->peer.name = &ctx->addrs[0].name;
ctx->peer.sockaddr = addr->sockaddr;
ctx->peer.socklen = addr->socklen;
ctx->peer.name = &addr->name;
ctx->peer.get = ngx_event_get_peer;
ctx->peer.log = ctx->log;
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,
"ssl ocsp connect peer done");
if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
if (rc == NGX_ERROR) {
ngx_ssl_ocsp_error(ctx);
return;
}
if (rc == NGX_BUSY || rc == NGX_DECLINED) {
ngx_ssl_ocsp_next(ctx);
return;
}
ctx->peer.connection->data = ctx;
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;
if (ctx->timeout) {
ngx_add_timer(ctx->peer.connection->read, ctx->timeout);
ngx_add_timer(ctx->peer.connection->write, ctx->timeout);
}
if (rc == NGX_OK) {
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) {
ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT,
"OCSP responder timed out");
ngx_ssl_ocsp_error(ctx);
ngx_ssl_ocsp_next(ctx);
return;
}
@@ -1087,7 +1573,7 @@ ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
n = ngx_send(c, ctx->request->pos, size);
if (n == NGX_ERROR) {
ngx_ssl_ocsp_error(ctx);
ngx_ssl_ocsp_next(ctx);
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);
}
}
@@ -1132,7 +1618,7 @@ ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
if (rev->timedout) {
ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT,
"OCSP responder timed out");
ngx_ssl_ocsp_error(ctx);
ngx_ssl_ocsp_next(ctx);
return;
}
@@ -1156,7 +1642,7 @@ ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
rc = ctx->process(ctx);
if (rc == NGX_ERROR) {
ngx_ssl_ocsp_error(ctx);
ngx_ssl_ocsp_next(ctx);
return;
}
@@ -1187,7 +1673,7 @@ ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
"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 *
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
+33 -1
View File
@@ -172,7 +172,11 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
*/
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->eof = 1;
@@ -956,6 +960,22 @@ ngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
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);
if (cl == NULL) {
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;
}
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;
return NGX_OK;
+25
View File
@@ -11,6 +11,7 @@
ngx_queue_t ngx_posted_accept_events;
ngx_queue_t ngx_posted_next_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);
}
}
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_move_posted_next(ngx_cycle_t *cycle);
extern ngx_queue_t ngx_posted_accept_events;
extern ngx_queue_t ngx_posted_next_events;
extern ngx_queue_t ngx_posted_events;
+23 -2
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,
size_t size);
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,
struct sockaddr *sockaddr, socklen_t socklen,
struct sockaddr *local_sockaddr, socklen_t local_socklen);
@@ -259,12 +258,18 @@ ngx_event_recvmsg(ngx_event_t *ev)
rev = c->read;
c->udp->buffer = &buf;
rev->ready = 1;
rev->active = 0;
rev->handler(rev);
if (c->udp) {
c->udp->buffer = NULL;
}
rev->ready = 0;
rev->active = 1;
goto next;
}
@@ -343,6 +348,7 @@ ngx_event_recvmsg(ngx_event_t *ev)
rev = c->read;
wev = c->write;
rev->active = 1;
wev->ready = 1;
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);
c->udp->buffer = NULL;
c->read->ready = 0;
c->read->active = 1;
return n;
}
@@ -540,12 +548,18 @@ ngx_insert_udp_connection(ngx_connection_t *c)
}
static void
void
ngx_delete_udp_connection(void *data)
{
ngx_connection_t *c = data;
if (c->udp == NULL) {
return;
}
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
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);
static ngx_int_t ngx_http_auth_basic_set_realm(ngx_http_request_t *r,
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 char *ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
@@ -177,8 +176,8 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
offset);
if (n == NGX_ERROR) {
ngx_http_auth_basic_close(&file);
return NGX_HTTP_INTERNAL_SERVER_ERROR;
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
goto cleanup;
}
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] == ':') {
buf[i] = '\0';
ngx_http_auth_basic_close(&file);
pwd.len = i - 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;
@@ -251,8 +249,6 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
offset += n;
}
ngx_http_auth_basic_close(&file);
if (state == sw_passwd) {
pwd.len = i - passwd;
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);
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,
"user \"%V\" was not found in \"%s\"",
&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;
}
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 *
ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf)
+26 -10
View File
@@ -186,8 +186,6 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
return rc;
}
/* NGX_DIR_MASK_LEN is lesser than NGX_HTTP_AUTOINDEX_PREALLOCATE */
last = ngx_http_map_uri_to_path(r, &path, &root,
NGX_HTTP_AUTOINDEX_PREALLOCATE);
if (last == NULL) {
@@ -436,7 +434,7 @@ ngx_http_autoindex_html(ngx_http_request_t *r, ngx_array_t *entries)
{
u_char *last, scale;
off_t length;
size_t len, char_len, escape_html;
size_t len, entry_len, char_len, escape_html;
ngx_tm_t tm;
ngx_buf_t *b;
ngx_int_t size;
@@ -501,7 +499,7 @@ ngx_http_autoindex_html(ngx_http_request_t *r, ngx_array_t *entries)
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
+ 1 /* 1 is for "/" */
+ sizeof("\">") - 1
@@ -512,6 +510,12 @@ ngx_http_autoindex_html(ngx_http_request_t *r, ngx_array_t *entries)
+ sizeof(" 28-Sep-1970 12:00 ") - 1
+ 20 /* the file size */
+ 2;
if (len > NGX_MAX_SIZE_T_VALUE - entry_len) {
return NULL;
}
len += entry_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_str_t *callback)
{
size_t len;
size_t len, entry_len;
ngx_buf_t *b;
ngx_uint_t i;
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].name.len);
len += sizeof("{ }," CRLF) - 1
entry_len = sizeof("{ }," CRLF) - 1
+ sizeof("\"name\":\"\"") - 1
+ entry[i].name.len + entry[i].escape
+ sizeof(", \"type\":\"directory\"") - 1
+ sizeof(", \"mtime\":\"Wed, 31 Dec 1986 10:00:00 GMT\"") - 1;
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);
@@ -843,7 +853,7 @@ ngx_http_autoindex_jsonp_callback(ngx_http_request_t *r, ngx_str_t *callback)
static ngx_buf_t *
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_buf_t *b;
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].name.len);
len += sizeof("<directory></directory>" CRLF) - 1
entry_len = sizeof("<directory></directory>" CRLF) - 1
+ entry[i].name.len + entry[i].escape
+ sizeof(" mtime=\"1986-12-31T10:00:00Z\"") - 1;
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);
+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_error(ngx_log_t *log, ngx_err_t err,
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 char *ngx_http_dav_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
@@ -285,7 +285,7 @@ ngx_http_dav_put_handler(ngx_http_request_t *r)
}
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);
return;
}
@@ -312,7 +312,7 @@ ngx_http_dav_delete_handler(ngx_http_request_t *r)
ngx_file_info_t fi;
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,
"DELETE with body is unsupported");
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;
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,
"MKCOL with body is unsupported");
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';
r->uri.len--;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"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))
!= 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;
}
@@ -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_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;
}
@@ -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
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);
if (r->headers_out.location == NULL) {
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;
ngx_str_set(&r->headers_out.location->key, "Location");
r->headers_out.location->value.len = r->uri.len;
r->headers_out.location->value.data = location;
r->headers_out.location->value = r->uri;
return NGX_OK;
}
+118 -10
View File
@@ -81,12 +81,15 @@ typedef struct {
size_t length;
size_t padding;
off_t rest;
ngx_chain_t *free;
ngx_chain_t *busy;
unsigned fastcgi_stdout:1;
unsigned large_stderr:1;
unsigned header_sent:1;
unsigned closed:1;
ngx_array_t *split_parts;
@@ -2076,13 +2079,31 @@ static ngx_int_t
ngx_http_fastcgi_input_filter_init(void *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;
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);
r->upstream->pipe->length = flcf->keep_conn ?
u->pipe->length = flcf->keep_conn ?
(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;
}
@@ -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);
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;
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) {
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) {
p->upstream_done = 1;
}
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
"http fastcgi closed stdout");
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,
"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) {
p->upstream_done = 1;
break;
@@ -2252,6 +2306,18 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
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);
if (cl == NULL) {
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;
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");
b->last = b->pos + f->rest;
p->upstream_done = 1;
break;
}
f->rest -= b->last - b->pos;
}
}
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->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) {
u->length = 0;
break;
@@ -2486,6 +2572,14 @@ ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes)
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);
if (cl == NULL) {
return NGX_ERROR;
@@ -2510,15 +2604,29 @@ ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes)
f->pos += f->length;
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;
b->last = f->last;
if (f->rest > 0) {
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;
}
+13
View File
@@ -215,6 +215,13 @@ ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
break;
#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 */
sin = (struct sockaddr_in *) addr.sockaddr;
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;
#endif
#if (NGX_HAVE_UNIX_DOMAIN)
case AF_UNIX:
inaddr = INADDR_NONE;
break;
#endif
default: /* AF_INET */
sin = (struct sockaddr_in *) addr.sockaddr;
inaddr = ntohl(sin->sin_addr.s_addr);
+250 -30
View File
@@ -27,6 +27,9 @@ typedef struct {
ngx_str_t host;
ngx_uint_t host_set;
ngx_array_t *grpc_lengths;
ngx_array_t *grpc_values;
#if (NGX_HTTP_SSL)
ngx_uint_t ssl;
ngx_uint_t ssl_protocols;
@@ -78,6 +81,11 @@ typedef struct {
ngx_uint_t id;
ngx_uint_t pings;
ngx_uint_t settings;
off_t length;
ssize_t send_window;
size_t recv_window;
@@ -114,8 +122,11 @@ typedef struct {
unsigned end_stream:1;
unsigned done:1;
unsigned status:1;
unsigned rst:1;
ngx_http_request_t *request;
ngx_str_t host;
} ngx_http_grpc_ctx_t;
@@ -132,6 +143,8 @@ typedef struct {
} 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_reinit_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in);
@@ -521,10 +534,22 @@ ngx_http_grpc_handler(ngx_http_request_t *r)
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);
u = r->upstream;
if (glcf->grpc_lengths == NULL) {
ctx->host = glcf->host;
#if (NGX_HTTP_SSL)
u->ssl = (glcf->upstream.ssl != NULL);
@@ -538,6 +563,12 @@ ngx_http_grpc_handler(ngx_http_request_t *r)
ngx_str_set(&u->schema, "grpc://");
#endif
} else {
if (ngx_http_grpc_eval(r, ctx, glcf) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
}
u->output.tag = (ngx_buf_tag_t) &ngx_http_grpc_module;
u->conf = &glcf->upstream;
@@ -548,15 +579,6 @@ ngx_http_grpc_handler(ngx_http_request_t *r)
u->abort_request = ngx_http_grpc_abort_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 = ngx_http_grpc_filter;
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
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_list_part_t *part;
ngx_table_elt_t *header;
ngx_http_grpc_ctx_t *ctx;
ngx_http_upstream_t *u;
ngx_http_grpc_frame_t *f;
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);
ctx = ngx_http_get_module_ctx(r, ngx_http_grpc_module);
len = sizeof(ngx_http_grpc_connection_start) - 1
+ sizeof(ngx_http_grpc_frame_t); /* headers frame */
@@ -634,10 +756,10 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
/* :authority header */
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) {
tmp_len = glcf->host.len;
if (tmp_len < ctx->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 (glcf->ssl) {
if (u->ssl) {
*b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTPS_INDEX);
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) {
*b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_AUTHORITY_INDEX);
b->last = ngx_http_v2_write_value(b->last, glcf->host.data,
glcf->host.len, tmp);
b->last = ngx_http_v2_write_value(b->last, ctx->host.data,
ctx->host.len, tmp);
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));
@@ -1086,6 +1208,7 @@ ngx_http_grpc_reinit_request(ngx_http_request_t *r)
ctx->end_stream = 0;
ctx->done = 0;
ctx->status = 0;
ctx->rst = 0;
ctx->connection = NULL;
return NGX_OK;
@@ -1832,10 +1955,28 @@ ngx_http_grpc_filter_init(void *data)
r = ctx->request;
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->length > 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream prematurely closed stream");
return NGX_ERROR;
}
u->length = 0;
} else {
u->length = 1;
}
return NGX_OK;
@@ -1878,6 +2019,12 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
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
* remaining control frames. If there are unsent
@@ -1931,6 +2078,17 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
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) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream violated stream flow control, "
@@ -1969,7 +2127,10 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
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,
"upstream sent frame for closed stream %ui",
ctx->stream_id);
@@ -2012,13 +2173,23 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
return NGX_ERROR;
}
if (ctx->error || !ctx->done) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream rejected request with error %ui",
ctx->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) {
rc = ngx_http_grpc_parse_goaway(r, ctx, b);
@@ -3584,6 +3755,12 @@ ngx_http_grpc_parse_settings(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
ctx->rest);
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++) {
@@ -3736,6 +3913,12 @@ ngx_http_grpc_parse_ping(ngx_http_request_t *r,
"upstream sent ping frame with ack flag");
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++) {
@@ -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);
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->host = prev->host;
conf->grpc_lengths = prev->grpc_lengths;
conf->grpc_values = prev->grpc_values;
#if (NGX_HTTP_SSL)
conf->upstream.ssl = prev->upstream.ssl;
#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;
}
@@ -4525,15 +4716,51 @@ ngx_http_grpc_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
size_t add;
ngx_str_t *value, *url;
ngx_url_t u;
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";
}
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;
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) {
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");
}
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;
}
@@ -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);
if (cln == NULL) {
ngx_ssl_cleanup_ctx(glcf->upstream.ssl);
return NGX_ERROR;
}
+8 -111
View File
@@ -55,44 +55,23 @@ typedef struct {
unsigned redo:1;
unsigned done:1;
unsigned nomem:1;
unsigned gzheader:1;
unsigned buffering:1;
unsigned intel:1;
size_t zin;
size_t zout;
uint32_t crc32;
z_stream zstream;
ngx_http_request_t *request;
} 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,
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);
static ngx_int_t ngx_http_gzip_filter_deflate_start(ngx_http_request_t *r,
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,
ngx_http_gzip_ctx_t *ctx);
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;
}
if (!ctx->gzheader) {
if (ngx_http_gzip_filter_gzheader(r, ctx) != NGX_OK) {
goto failed;
}
}
rc = ngx_http_next_body_filter(r, ctx->out);
if (rc == NGX_ERROR) {
@@ -643,7 +616,7 @@ ngx_http_gzip_filter_deflate_start(ngx_http_request_t *r,
ctx->zstream.opaque = ctx;
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) {
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->crc32 = crc32(0L, Z_NULL, 0);
ctx->flush = Z_NO_FLUSH;
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
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) {
ctx->flush = Z_SYNC_FLUSH;
}
if (ctx->zstream.avail_in) {
ctx->crc32 = crc32(ctx->crc32, ctx->zstream.next_in,
ctx->zstream.avail_in);
} else if (ctx->flush == Z_NO_FLUSH) {
} else if (ctx->zstream.avail_in == 0) {
/* ctx->flush == Z_NO_FLUSH */
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;
if (ctx->zstream.avail_out == 0) {
if (ctx->zstream.avail_out == 0 && rc != Z_STREAM_END) {
/* zlib wants to output some more gzipped data */
@@ -935,10 +870,9 @@ ngx_http_gzip_filter_deflate_end(ngx_http_request_t *r,
int rc;
ngx_buf_t *b;
ngx_chain_t *cl;
struct gztrailer *trailer;
ctx->zin = ctx->zstream.total_in;
ctx->zout = 10 + ctx->zstream.total_out + 8;
ctx->zout = ctx->zstream.total_out;
rc = deflateEnd(&ctx->zstream);
@@ -955,55 +889,18 @@ ngx_http_gzip_filter_deflate_end(ngx_http_request_t *r,
return NGX_ERROR;
}
cl->buf = ctx->out_buf;
cl->next = NULL;
*ctx->last_out = cl;
ctx->last_out = &cl->next;
b = ctx->out_buf;
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;
if (ngx_buf_size(b) == 0) {
b->temporary = 0;
}
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_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);
if (name == NULL) {
return NGX_ERROR;
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
allocated = path.data + path.len - name;
+126 -38
View File
@@ -10,6 +10,11 @@
#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 {
u_char color;
u_char len;
@@ -25,7 +30,14 @@ typedef struct {
typedef struct {
ngx_rbtree_t *rbtree;
ngx_rbtree_t rbtree;
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;
@@ -40,6 +52,7 @@ typedef struct {
ngx_array_t limits;
ngx_uint_t log_level;
ngx_uint_t status_code;
ngx_flag_t dry_run;
} 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 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 char *ngx_http_limit_conn_merge_conf(ngx_conf_t *cf, void *parent,
void *child);
@@ -55,6 +70,7 @@ static char *ngx_http_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *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);
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),
&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
};
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 */
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
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;
ngx_str_t key;
ngx_uint_t i;
ngx_slab_pool_t *shpool;
ngx_rbtree_node_t *node;
ngx_pool_cleanup_t *cln;
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_cleanup_t *lccln;
if (r->main->limit_conn_set) {
if (r->main->limit_conn_status) {
return NGX_DECLINED;
}
@@ -179,15 +217,13 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
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);
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->rbtree, &key, hash);
node = ngx_http_limit_conn_lookup(&ctx->sh->rbtree, &key, hash);
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)
+ key.len;
node = ngx_slab_alloc_locked(shpool, n);
node = ngx_slab_alloc_locked(ctx->shpool, n);
if (node == NULL) {
ngx_shmtx_unlock(&shpool->mutex);
ngx_shmtx_unlock(&ctx->shpool->mutex);
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;
}
@@ -210,7 +255,7 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
lc->conn = 1;
ngx_memcpy(lc->data, key.data, key.len);
ngx_rbtree_insert(ctx->rbtree, node);
ngx_rbtree_insert(&ctx->sh->rbtree, node);
} else {
@@ -218,13 +263,23 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
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,
"limiting connections by zone \"%V\"",
"limiting connections%s by zone \"%V\"",
lccf->dry_run ? ", dry run," : "",
&limits[i].shm_zone->shm.name);
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;
}
@@ -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,
"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,
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_slab_pool_t *shpool;
ngx_rbtree_node_t *node;
ngx_http_limit_conn_ctx_t *ctx;
ngx_http_limit_conn_node_t *lc;
ctx = lccln->shm_zone->data;
shpool = (ngx_slab_pool_t *) lccln->shm_zone->shm.addr;
node = lccln->node;
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,
"limit conn cleanup: %08Xi %d", node->key, lc->conn);
@@ -356,11 +409,11 @@ ngx_http_limit_conn_cleanup(void *data)
lc->conn--;
if (lc->conn == 0) {
ngx_rbtree_delete(ctx->rbtree, node);
ngx_slab_free_locked(shpool, node);
ngx_rbtree_delete(&ctx->sh->rbtree, 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;
size_t len;
ngx_slab_pool_t *shpool;
ngx_rbtree_node_t *sentinel;
ngx_http_limit_conn_ctx_t *ctx;
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;
}
ctx->rbtree = octx->rbtree;
ctx->sh = octx->sh;
ctx->shpool = octx->shpool;
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) {
ctx->rbtree = shpool->data;
ctx->sh = ctx->shpool->data;
return NGX_OK;
}
ctx->rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t));
if (ctx->rbtree == NULL) {
ctx->sh = ngx_slab_alloc(ctx->shpool, sizeof(ngx_http_limit_conn_shctx_t));
if (ctx->sh == NULL) {
return NGX_ERROR;
}
shpool->data = ctx->rbtree;
ctx->shpool->data = ctx->sh;
sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t));
if (sentinel == NULL) {
return NGX_ERROR;
}
ngx_rbtree_init(ctx->rbtree, sentinel,
ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel,
ngx_http_limit_conn_rbtree_insert_value);
len = sizeof(" in limit_conn_zone \"\"") + shm_zone->shm.name.len;
shpool->log_ctx = ngx_slab_alloc(shpool, len);
if (shpool->log_ctx == NULL) {
ctx->shpool->log_ctx = ngx_slab_alloc(ctx->shpool, len);
if (ctx->shpool->log_ctx == NULL) {
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);
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 *
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->status_code = NGX_CONF_UNSET_UINT;
conf->dry_run = NGX_CONF_UNSET;
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_HTTP_SERVICE_UNAVAILABLE);
ngx_conf_merge_value(conf->dry_run, prev->dry_run, 0);
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
ngx_http_limit_conn_init(ngx_conf_t *cf)
{
+121 -17
View File
@@ -10,6 +10,13 @@
#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 {
u_char color;
u_char dummy;
@@ -44,7 +51,7 @@ typedef struct {
ngx_shm_zone_t *shm_zone;
/* integer value, 1 corresponds to 0.001 r/s */
ngx_uint_t burst;
ngx_uint_t nodelay; /* unsigned nodelay:1 */
ngx_uint_t delay;
} ngx_http_limit_req_limit_t;
@@ -53,6 +60,7 @@ typedef struct {
ngx_uint_t limit_log_level;
ngx_uint_t delay_log_level;
ngx_uint_t status_code;
ngx_flag_t dry_run;
} 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,
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 char *ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent,
void *child);
@@ -71,6 +81,7 @@ static char *ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd,
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);
@@ -118,12 +129,19 @@ static ngx_command_t ngx_http_limit_req_commands[] = {
offsetof(ngx_http_limit_req_conf_t, status_code),
&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
};
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 */
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
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_limit_t *limit, *limits;
if (r->main->limit_req_set) {
if (r->main->limit_req_status) {
return NGX_DECLINED;
}
@@ -224,13 +260,12 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
return NGX_DECLINED;
}
r->main->limit_req_set = 1;
if (rc == NGX_BUSY || rc == NGX_ERROR) {
if (rc == NGX_BUSY) {
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\"",
lrcf->dry_run ? ", dry run" : "",
excess / 1000, excess % 1000,
&limit->shm_zone->shm.name);
}
@@ -251,6 +286,13 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
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;
}
@@ -263,13 +305,22 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
delay = ngx_http_limit_req_account(limits, n, &excess, &limit);
if (!delay) {
r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_PASSED;
return NGX_DECLINED;
}
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);
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) {
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;
if (excess == 0 || (*limit)->nodelay) {
if ((ngx_uint_t) excess <= (*limit)->delay) {
max_delay = 0;
} else {
ctx = (*limit)->shm_zone->data;
max_delay = excess * 1000 / ctx->rate;
max_delay = (excess - (*limit)->delay) * 1000 / ctx->rate;
}
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;
if (limits[n].nodelay) {
if ((ngx_uint_t) excess <= limits[n].delay) {
continue;
}
delay = excess * 1000 / ctx->rate;
delay = (excess - limits[n].delay) * 1000 / ctx->rate;
if (delay > max_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 *
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->status_code = NGX_CONF_UNSET_UINT;
conf->dry_run = NGX_CONF_UNSET;
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_HTTP_SERVICE_UNAVAILABLE);
ngx_conf_merge_value(conf->dry_run, prev->dry_run, 0);
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_int_t burst;
ngx_int_t burst, delay;
ngx_str_t *value, s;
ngx_uint_t i, nodelay;
ngx_uint_t i;
ngx_shm_zone_t *shm_zone;
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;
burst = 0;
nodelay = 0;
delay = 0;
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);
if (burst <= 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;
}
@@ -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) {
nodelay = 1;
delay = NGX_MAX_INT_T_VALUE / 1000;
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->burst = burst * 1000;
limit->nodelay = nodelay;
limit->delay = delay * 1000;
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
ngx_http_limit_req_init(ngx_conf_t *cf)
{
+5 -2
View File
@@ -485,7 +485,8 @@ ngx_http_memcached_filter(void *data, ssize_t bytes)
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,
bytes)
!= 0)
@@ -540,7 +541,9 @@ ngx_http_memcached_filter(void *data, ssize_t bytes)
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,
"memcached sent invalid trailer");
+78 -11
View File
@@ -169,7 +169,14 @@ typedef struct {
#define ngx_mp4_atom_next(mp4, 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
@@ -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_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 {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"\"%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",
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 (trak->end_sample - trak->start_sample > entries) {
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,
"mp4 stsz end_chunk_samples_size:%uL",
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);
@@ -3212,6 +3240,7 @@ ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
{
size_t atom_size;
uint32_t entries;
uint64_t chunk_offset, samples_size;
ngx_buf_t *atom, *data;
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);
trak->start_offset = ngx_mp4_get_32value(data->pos);
trak->start_offset += trak->start_chunk_samples_size;
chunk_offset = ngx_mp4_get_32value(data->pos);
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_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);
if (entries) {
trak->end_offset =
ngx_mp4_get_32value(data->last - sizeof(uint32_t));
trak->end_offset += trak->end_chunk_samples_size;
chunk_offset = ngx_mp4_get_32value(data->last - sizeof(uint32_t));
samples_size = 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,
"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)
{
size_t atom_size;
uint64_t entries;
uint64_t entries, chunk_offset, samples_size;
ngx_buf_t *atom, *data;
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);
trak->start_offset = ngx_mp4_get_64value(data->pos);
trak->start_offset += trak->start_chunk_samples_size;
chunk_offset = ngx_mp4_get_64value(data->pos);
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_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);
if (entries) {
trak->end_offset =
ngx_mp4_get_64value(data->last - sizeof(uint64_t));
trak->end_offset += trak->end_chunk_samples_size;
chunk_offset = ngx_mp4_get_64value(data->last - sizeof(uint64_t));
samples_size = 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,
"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;
}
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);
if (cl == NULL) {
return NGX_ERROR;
@@ -2042,20 +2061,23 @@ ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
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;
if (p->length == 0) {
r = p->input_ctx;
p->upstream_done = 1;
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;
@@ -2082,6 +2104,23 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
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;
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 */
p->upstream_done = 1;
p->length = 0;
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;
}
@@ -2161,13 +2206,13 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
/* 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");
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",
ctx->chunked.state, p->length);
@@ -2227,6 +2272,18 @@ ngx_http_proxy_non_buffered_copy_filter(void *data, ssize_t bytes)
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;
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->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;
}
@@ -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);
if (cln == NULL) {
ngx_ssl_cleanup_ctx(plcf->upstream.ssl);
return NGX_ERROR;
}
@@ -98,7 +98,7 @@ ngx_http_random_index_handler(ngx_http_request_t *r)
}
#if (NGX_HAVE_D_TYPE)
len = NGX_DIR_MASK_LEN;
len = 0;
#else
len = NGX_HTTP_RANDOM_INDEX_PREALLOCATE;
#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)
{
off_t start, last;
ngx_int_t rc;
ngx_buf_t *buf;
ngx_chain_t *out, *cl, **ll;
ngx_chain_t *out, *cl, *tl, **ll;
ngx_http_range_t *range;
out = NULL;
@@ -721,8 +722,22 @@ ngx_http_range_singlepart_body(ngx_http_request_t *r,
"http range body buf: %O-%O", start, last);
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;
}
@@ -764,21 +779,42 @@ ngx_http_range_singlepart_body(ngx_http_request_t *r,
buf->last_buf = (r == r->main) ? 1 : 0;
buf->last_in_chain = 1;
*ll = cl;
cl->next = NULL;
break;
tl = ngx_alloc_chain_link(r->pool);
if (tl == NULL) {
return NGX_ERROR;
}
*ll = cl;
ll = &cl->next;
tl->buf = buf;
tl->next = NULL;
*ll = tl;
ll = &tl->next;
continue;
}
if (out == NULL) {
return NGX_OK;
tl = ngx_alloc_chain_link(r->pool);
if (tl == NULL) {
return NGX_ERROR;
}
return ngx_http_next_body_filter(r, out);
tl->buf = buf;
tl->next = NULL;
*ll = tl;
ll = &tl->next;
}
rc = ngx_http_next_body_filter(r, out);
while (out) {
cl = out;
out = out->next;
ngx_free_chain(r->pool, cl);
}
return rc;
}
+3 -4
View File
@@ -180,12 +180,11 @@ ngx_http_realip_handler(ngx_http_request_t *r)
case NGX_HTTP_REALIP_PROXY:
value = &r->connection->proxy_protocol_addr;
if (value->len == 0) {
if (r->connection->proxy_protocol == NULL) {
return NGX_DECLINED;
}
value = &r->connection->proxy_protocol->src_addr;
xfwd = NULL;
break;
@@ -238,7 +237,7 @@ found:
!= NGX_DECLINED)
{
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);
@@ -318,6 +318,11 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
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));
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_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_input_filter_init(void *data);
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);
@@ -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_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
&& scf->upstream.pass_request_body
&& !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
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 = 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->subrequest_ranges = 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 '-':
state = ssi_error_end0_state;
ctx->param->key.data[ctx->param->key.len++] = ch;
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);
break;
+283 -13
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);
#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_ECDH_CURVE "X25519:P-256:P-384:P-224:P-521"
#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"
#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,
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,
void *conf);
static char *ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
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);
@@ -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 = {
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),
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_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
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),
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_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
@@ -585,6 +626,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
* set by ngx_pcalloc():
*
* sscf->protocols = 0;
* sscf->certificate_values = NULL;
* sscf->dhparam = { 0, NULL };
* sscf->ecdh_curve = { 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->ciphers = { 0, NULL };
* sscf->shm_zone = NULL;
* sscf->ocsp_responder = { 0, NULL };
* sscf->stapling_file = { 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->builtin_session_cache = NGX_CONF_UNSET;
sscf->session_timeout = NGX_CONF_UNSET;
sscf->session_timeout_tls13 = NGX_CONF_UNSET;
sscf->session_tickets = NGX_CONF_UNSET;
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_verify = 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,
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,
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_bitmask_value(conf->protocols, prev->protocols,
(NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
|NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2|NGX_SSL_TLSv1_3));
(NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1_2|NGX_SSL_TLSv1_3));
ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
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_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_verify, prev->stapling_verify, 0);
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;
}
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
if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
@@ -773,13 +835,29 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_ssl_npn_advertised, NULL);
#endif
cln = ngx_pool_cleanup_add(cf->pool, 0);
if (cln == NULL) {
if (ngx_http_ssl_compile_certificates(cf, conf) != NGX_OK) {
return NGX_CONF_ERROR;
}
cln->handler = ngx_ssl_cleanup_ctx;
cln->data = &conf->ssl;
if (conf->certificate_values) {
#ifdef SSL_R_CERT_CB_ERROR
/* 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;
#endif
} else {
/* configure certificates */
if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
conf->certificate_keys, conf->passwords)
@@ -787,6 +865,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
{
return NGX_CONF_ERROR;
}
}
if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
conf->prefer_server_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) {
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;
}
@@ -826,6 +905,23 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
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) {
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,
conf->builtin_session_cache,
conf->shm_zone, conf->session_timeout)
conf->certificates, conf->builtin_session_cache,
conf->shm_zone, conf->session_timeout, conf->session_timeout_tls13)
!= NGX_OK)
{
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 *
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
ngx_http_ssl_init(ngx_conf_t *cf)
{
@@ -1080,12 +1339,13 @@ ngx_http_ssl_init(ngx_conf_t *cf)
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;
}
clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
if (sscf->stapling) {
if (ngx_ssl_stapling_resolver(cf, &sscf->ssl, clcf->resolver,
clcf->resolver_timeout)
!= NGX_OK)
@@ -1094,6 +1354,16 @@ ngx_http_ssl_init(ngx_conf_t *cf)
}
}
if (sscf->ocsp) {
if (ngx_ssl_ocsp_resolver(cf, &sscf->ssl, clcf->resolver,
clcf->resolver_timeout)
!= NGX_OK)
{
return NGX_ERROR;
}
}
}
if (cmcf->ports == NULL) {
return NGX_OK;
}
+8
View File
@@ -32,10 +32,14 @@ typedef struct {
ssize_t builtin_session_cache;
time_t session_timeout;
time_t session_timeout_tls13;
ngx_array_t *certificates;
ngx_array_t *certificate_keys;
ngx_array_t *certificate_values;
ngx_array_t *certificate_key_values;
ngx_str_t dhparam;
ngx_str_t ecdh_curve;
ngx_str_t client_certificate;
@@ -51,6 +55,10 @@ typedef struct {
ngx_flag_t session_tickets;
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_verify;
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;
if (!clcf->alias && clcf->root_lengths == NULL && r->args.len == 0) {
location = path.data + clcf->root.len;
if (!clcf->alias && r->args.len == 0) {
location = path.data + root;
*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);
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);
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);
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);
return hp->get_rr_peer(pc, &hp->rrp);
}
@@ -275,6 +275,7 @@ found:
c->idle = 0;
c->sent = 0;
c->data = NULL;
c->log = pc->log;
c->read->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;
#endif
#if (NGX_HAVE_UNIX_DOMAIN)
case AF_UNIX:
ctx->uid_set[0] = 0;
break;
#endif
default: /* AF_INET */
sin = (struct sockaddr_in *) c->local_sockaddr;
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_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_input_filter_init(void *data);
static void ngx_http_uwsgi_abort_request(ngx_http_request_t *r);
static void ngx_http_uwsgi_finalize_request(ngx_http_request_t *r,
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_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
&& uwcf->upstream.pass_request_body
&& !r->headers_in.chunked)
@@ -1141,6 +1146,7 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
r->upstream->request_bufs = cl;
}
b->flush = 1;
cl->next = NULL;
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
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);
if (cln == NULL) {
ngx_ssl_cleanup_ctx(uwcf->upstream.ssl);
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);
r->main_filter_need_in_memory = 1;
r->allow_ranges = 0;
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_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;
ngx_uint_t i;
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);
}
last = p + string.len;
while (p && *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';
} else {
len = last - value;
len = ngx_strlen(value);
}
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