Compare commits

...

30 Commits

Author SHA1 Message Date
Tatsuhiro Tsujikawa
c13e63a501 Update manual pages 2017-05-30 23:57:53 +09:00
Tatsuhiro Tsujikawa
c6d89dd0ba Bump up version number to 1.23.1 2017-05-30 23:55:55 +09:00
Tatsuhiro Tsujikawa
d134ccd35d nghttpx: Fix crash in OCSP response verification 2017-05-30 23:55:11 +09:00
Tatsuhiro Tsujikawa
3a6f83394c Update bash_completion 2017-05-26 22:17:10 +09:00
Tatsuhiro Tsujikawa
acf36f3d1a Update manual pages 2017-05-26 22:16:51 +09:00
Tatsuhiro Tsujikawa
63e6a8bab2 Bump up version number to 1.23.0, LT revision to 27:3:13 2017-05-26 21:37:28 +09:00
Tatsuhiro Tsujikawa
5361cc6bd1 Update authors 2017-05-26 21:34:43 +09:00
Tatsuhiro Tsujikawa
cabac55394 Merge pull request #925 from sohamm17/patch-1
spelling mistake in arguments to build nghttp apps
2017-05-25 23:38:54 +09:00
Tatsuhiro Tsujikawa
db7483ef10 Merge branch 'nghttpx-verify-ocsp' 2017-05-25 23:37:34 +09:00
Tatsuhiro Tsujikawa
4b51ccbefe examples: Attempt to fix OpenSSL link error 2017-05-25 23:24:44 +09:00
Tatsuhiro Tsujikawa
74c2f1257a nghttpx: Add --no-verify-ocsp to disable OCSP response verification 2017-05-25 23:14:58 +09:00
Tatsuhiro Tsujikawa
1428a5e3ae nghttpx: Verify OCSP response
At least we should make sure that the OCSP response is targeted to the
expected certificate.  This is important because we pass the file path
to the external script, and if the file is replaced because of
renewal, and nghttpx has not reloaded its configuration, the
certificate nghttpx has loaded and the one included in the file
differ.  Verifying the OCSP response detects this, and avoids to send
wrong OCSP response.
2017-05-25 23:14:57 +09:00
Tatsuhiro Tsujikawa
fe021c1524 Merge branch 'memchunk-no-unique-ptr' 2017-05-25 00:53:13 +09:00
Tatsuhiro Tsujikawa
c57bf21306 src: memchunks: Don't use std::unique_ptr to avoid potential SO 2017-05-25 00:23:51 +09:00
Soham Sinha
1743b7d92d spelling mistake in arguments to build nghttp apps 2017-05-22 17:20:30 -04:00
Tatsuhiro Tsujikawa
7f31278c4c Update doc 2017-05-22 22:53:49 +09:00
Tatsuhiro Tsujikawa
8401e16a15 nghttpx: Fix compile error with gcc 2017-05-22 22:10:55 +09:00
Tatsuhiro Tsujikawa
07fb5854f3 nghttpx: Compile with openssl 1.0.2 2017-05-22 22:09:34 +09:00
Tatsuhiro Tsujikawa
b56a99bfba Update bash_completion 2017-05-21 11:43:00 +09:00
Tatsuhiro Tsujikawa
b91e4e4df1 Update manual pages 2017-05-21 11:42:46 +09:00
Tatsuhiro Tsujikawa
52a4d6ac31 Merge branch 'nghttpx-fix-cert-selection' 2017-05-21 11:26:12 +09:00
Tatsuhiro Tsujikawa
796ab87b14 nghttpx: Fix certificate selection based on pub key algorithm 2017-05-21 11:12:47 +09:00
Tatsuhiro Tsujikawa
ed1fad3bd4 nghttpx: Call ERR_clear_error()
Call ERR_clear_error() before the OpenSSL function if we use
SSL_get_error() to examine error stack.
2017-05-21 10:32:12 +09:00
Tatsuhiro Tsujikawa
9c1876f542 nghttpx: Fix certificate indexing bug 2017-05-21 00:19:33 +09:00
Tatsuhiro Tsujikawa
7d111d9963 Merge pull request #923 from nghttp2/compile-with-disable-assert
Compile with --disable-assert
2017-05-18 23:49:41 +09:00
Tatsuhiro Tsujikawa
8c2ce0cf3f Merge pull request #922 from nghttp2/nghttpx-ocsp-startup
nghttpx: Run OCSP at startup
2017-05-18 23:49:23 +09:00
Tatsuhiro Tsujikawa
1b442cb16f Compile with --disable-assert 2017-05-18 23:10:44 +09:00
Tatsuhiro Tsujikawa
2bf3680d87 Merge pull request #919 from projectgus/fix_ndebug_compile
nghttp2_session: Allow for compiling library with -DNDEBUG set
2017-05-18 22:37:51 +09:00
Tatsuhiro Tsujikawa
0d4f0f0db5 nghttpx: Run OCSP at startup
With --ocsp-startup option, nghttpx starts accepting connections after
initial attempts to get OCSP responses finish.  It does not matter
some of the attempts fail.  This feature is useful if OCSP responses
must be available before accepting connections.
2017-05-18 22:33:49 +09:00
Angus Gratton
e17ff8fd32 nghttp2_session: Allow for compiling library with -DNDEBUG set 2017-05-17 14:43:06 +10:00
39 changed files with 431 additions and 94 deletions

View File

@@ -21,6 +21,7 @@ Amir Pakdel
Anders Bakken Anders Bakken
Andreas Pohl Andreas Pohl
Andy Davies Andy Davies
Angus Gratton
Ant Bryan Ant Bryan
Benedikt Christoph Wolters Benedikt Christoph Wolters
Benedikt Christoph Wolters Benedikt Christoph Wolters
@@ -66,11 +67,13 @@ Remo E
Reza Tavakoli Reza Tavakoli
Ross Smith II Ross Smith II
Scott Mitchell Scott Mitchell
Soham Sinha
Stefan Eissing Stefan Eissing
Stephen Ludin Stephen Ludin
Sunpoet Po-Chuan Hsieh Sunpoet Po-Chuan Hsieh
Svante Signell Svante Signell
Syohei YOSHIDA Syohei YOSHIDA
Tapanito
Tatsuhiko Kubo Tatsuhiko Kubo
Tatsuhiro Tsujikawa Tatsuhiro Tsujikawa
Tom Harwood Tom Harwood

View File

@@ -24,12 +24,12 @@
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.0)
# XXX using 1.8.90 instead of 1.9.0-DEV # XXX using 1.8.90 instead of 1.9.0-DEV
project(nghttp2 VERSION 1.22.90) project(nghttp2 VERSION 1.23.1)
# See versioning rule: # See versioning rule:
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
set(LT_CURRENT 27) set(LT_CURRENT 27)
set(LT_REVISION 2) set(LT_REVISION 3)
set(LT_AGE 13) set(LT_AGE 13)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

View File

@@ -25,7 +25,7 @@ dnl Do not change user variables!
dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
AC_PREREQ(2.61) AC_PREREQ(2.61)
AC_INIT([nghttp2], [1.23.0-DEV], [t-tujikawa@users.sourceforge.net]) AC_INIT([nghttp2], [1.23.1], [t-tujikawa@users.sourceforge.net])
AC_CONFIG_AUX_DIR([.]) AC_CONFIG_AUX_DIR([.])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
@@ -45,7 +45,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl See versioning rule: dnl See versioning rule:
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
AC_SUBST(LT_CURRENT, 27) AC_SUBST(LT_CURRENT, 27)
AC_SUBST(LT_REVISION, 2) AC_SUBST(LT_REVISION, 3)
AC_SUBST(LT_AGE, 13) AC_SUBST(LT_AGE, 13)
major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"` major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"`

View File

@@ -8,7 +8,7 @@ _nghttp()
_get_comp_words_by_ref cur prev _get_comp_words_by_ref cur prev
case $cur in case $cur in
-*) -*)
COMPREPLY=( $( compgen -W '--no-push --verbose --no-dep --get-assets --har --header-table-size --multiply --encoder-header-table-size --padding --hexdump --max-concurrent-streams --continuation --connection-window-bits --peer-max-concurrent-streams --timeout --data --no-content-length --version --color --cert --upgrade --remote-name --trailer --weight --help --key --null-out --window-bits --expect-continue --stat --header ' -- "$cur" ) ) COMPREPLY=( $( compgen -W '--no-push --verbose --no-dep --get-assets --har --header-table-size --multiply --encoder-header-table-size --padding --hexdump --max-concurrent-streams --continuation --connection-window-bits --peer-max-concurrent-streams --timeout --data --no-content-length --version --color --cert --upgrade --remote-name --trailer --weight --help --key --null-out --window-bits --expect-continue --stat --no-verify-peer --header ' -- "$cur" ) )
;; ;;
*) *)
_filedir _filedir

View File

@@ -8,7 +8,7 @@ _nghttpx()
_get_comp_words_by_ref cur prev _get_comp_words_by_ref cur prev
case $cur in case $cur in
-*) -*)
COMPREPLY=( $( compgen -W '--worker-read-rate --include --frontend-http2-dump-response-header --tls-ticket-key-file --verify-client-cacert --max-response-header-fields --backend-http2-window-size --frontend-keep-alive-timeout --backend-request-buffer --max-request-header-fields --fastopen --backend-connect-timeout --tls-max-proto-version --conf --dns-lookup-timeout --backend-http2-max-concurrent-streams --worker-write-burst --npn-list --dns-max-try --fetch-ocsp-response-file --no-via --tls-session-cache-memcached-cert-file --no-http2-cipher-black-list --mruby-file --client-no-http2-cipher-black-list --stream-read-timeout --client-ciphers --forwarded-for --accesslog-syslog --dns-cache-timeout --frontend-http2-read-timeout --listener-disable-timeout --ciphers --client-psk-secrets --strip-incoming-x-forwarded-for --no-server-rewrite --private-key-passwd-file --backend-keep-alive-timeout --backend-http-proxy-uri --frontend-max-requests --rlimit-nofile --no-strip-incoming-x-forwarded-proto --tls-ticket-key-memcached-cert-file --ocsp-update-interval --forwarded-by --tls-session-cache-memcached-private-key-file --error-page --backend-write-timeout --tls-dyn-rec-warmup-threshold --tls-ticket-key-memcached-max-retry --frontend-http2-window-size --http2-no-cookie-crumbling --worker-read-burst --dh-param-file --accesslog-format --errorlog-syslog --redirect-https-port --request-header-field-buffer --api-max-request-body --frontend-http2-decoder-dynamic-table-size --errorlog-file --frontend-http2-max-concurrent-streams --psk-secrets --frontend-write-timeout --tls-ticket-key-cipher --read-burst --no-add-x-forwarded-proto --backend --server-name --insecure --backend-max-backoff --log-level --host-rewrite --tls-ticket-key-memcached-interval --frontend-http2-setting-timeout --frontend-http2-connection-window-size --worker-frontend-connections --syslog-facility --no-server-push --no-location-rewrite --single-thread --tls-session-cache-memcached --no-ocsp --backend-response-buffer --tls-min-proto-version --workers --add-forwarded --worker-write-rate --add-request-header --backend-http2-settings-timeout --subcert --ecdh-curves --no-kqueue --help --frontend-frame-debug --tls-sct-dir --pid-file --frontend-http2-dump-request-header --daemon --write-rate --altsvc --backend-http2-decoder-dynamic-table-size --user --add-x-forwarded-for --frontend-read-timeout --tls-ticket-key-memcached-max-fail --backlog --write-burst --backend-connections-per-host --response-header-field-buffer --tls-ticket-key-memcached-address-family --padding --tls-session-cache-memcached-address-family --stream-write-timeout --cacert --tls-ticket-key-memcached-private-key-file --accesslog-write-early --backend-address-family --backend-http2-connection-window-size --version --add-response-header --backend-read-timeout --frontend-http2-optimize-window-size --frontend --accesslog-file --http2-proxy --backend-http2-encoder-dynamic-table-size --client-private-key-file --single-process --client-cert-file --tls-ticket-key-memcached --tls-dyn-rec-idle-timeout --frontend-http2-optimize-write-buffer-size --verify-client --frontend-http2-encoder-dynamic-table-size --read-rate --backend-connections-per-frontend --strip-incoming-forwarded ' -- "$cur" ) ) COMPREPLY=( $( compgen -W '--worker-read-rate --include --frontend-http2-dump-response-header --tls-ticket-key-file --verify-client-cacert --max-response-header-fields --backend-http2-window-size --frontend-keep-alive-timeout --backend-request-buffer --max-request-header-fields --fastopen --backend-connect-timeout --tls-max-proto-version --conf --dns-lookup-timeout --backend-http2-max-concurrent-streams --worker-write-burst --npn-list --dns-max-try --fetch-ocsp-response-file --no-via --tls-session-cache-memcached-cert-file --no-http2-cipher-black-list --mruby-file --client-no-http2-cipher-black-list --stream-read-timeout --client-ciphers --ocsp-update-interval --forwarded-for --accesslog-syslog --dns-cache-timeout --frontend-http2-read-timeout --listener-disable-timeout --ciphers --client-psk-secrets --strip-incoming-x-forwarded-for --no-server-rewrite --private-key-passwd-file --backend-keep-alive-timeout --backend-http-proxy-uri --frontend-max-requests --rlimit-nofile --no-strip-incoming-x-forwarded-proto --tls-ticket-key-memcached-cert-file --no-verify-ocsp --forwarded-by --tls-session-cache-memcached-private-key-file --error-page --ocsp-startup --backend-write-timeout --tls-dyn-rec-warmup-threshold --tls-ticket-key-memcached-max-retry --frontend-http2-window-size --http2-no-cookie-crumbling --worker-read-burst --dh-param-file --accesslog-format --errorlog-syslog --redirect-https-port --request-header-field-buffer --api-max-request-body --frontend-http2-decoder-dynamic-table-size --errorlog-file --frontend-http2-max-concurrent-streams --psk-secrets --frontend-write-timeout --tls-ticket-key-cipher --read-burst --no-add-x-forwarded-proto --backend --server-name --insecure --backend-max-backoff --log-level --host-rewrite --tls-ticket-key-memcached-interval --frontend-http2-setting-timeout --frontend-http2-connection-window-size --worker-frontend-connections --syslog-facility --no-server-push --no-location-rewrite --single-thread --tls-session-cache-memcached --no-ocsp --backend-response-buffer --tls-min-proto-version --workers --add-forwarded --worker-write-rate --add-request-header --backend-http2-settings-timeout --subcert --ecdh-curves --no-kqueue --help --frontend-frame-debug --tls-sct-dir --pid-file --frontend-http2-dump-request-header --daemon --write-rate --altsvc --backend-http2-decoder-dynamic-table-size --user --add-x-forwarded-for --frontend-read-timeout --tls-ticket-key-memcached-max-fail --backlog --write-burst --backend-connections-per-host --response-header-field-buffer --tls-ticket-key-memcached-address-family --padding --tls-session-cache-memcached-address-family --stream-write-timeout --cacert --tls-ticket-key-memcached-private-key-file --accesslog-write-early --backend-address-family --backend-http2-connection-window-size --version --add-response-header --backend-read-timeout --frontend-http2-optimize-window-size --frontend --accesslog-file --http2-proxy --backend-http2-encoder-dynamic-table-size --client-private-key-file --single-process --client-cert-file --tls-ticket-key-memcached --tls-dyn-rec-idle-timeout --frontend-http2-optimize-write-buffer-size --verify-client --frontend-http2-encoder-dynamic-table-size --read-rate --backend-connections-per-frontend --strip-incoming-forwarded ' -- "$cur" ) )
;; ;;
*) *)
_filedir _filedir

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "H2LOAD" "1" "Apr 24, 2017" "1.22.0" "nghttp2" .TH "H2LOAD" "1" "May 30, 2017" "1.23.1" "nghttp2"
.SH NAME .SH NAME
h2load \- HTTP/2 benchmarking tool h2load \- HTTP/2 benchmarking tool
. .

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "NGHTTP" "1" "Apr 24, 2017" "1.22.0" "nghttp2" .TH "NGHTTP" "1" "May 30, 2017" "1.23.1" "nghttp2"
.SH NAME .SH NAME
nghttp \- HTTP/2 client nghttp \- HTTP/2 client
. .
@@ -236,6 +236,12 @@ combined with the \fI\%\-d\fP option.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-y, \-\-no\-verify\-peer
Suppress warning on server certificate verification
failure.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-version .B \-\-version
Display version information and exit. Display version information and exit.
.UNINDENT .UNINDENT

View File

@@ -186,6 +186,11 @@ OPTIONS
Continue interim response. This option is ignored unless Continue interim response. This option is ignored unless
combined with the :option:`-d` option. combined with the :option:`-d` option.
.. option:: -y, --no-verify-peer
Suppress warning on server certificate verification
failure.
.. option:: --version .. option:: --version
Display version information and exit. Display version information and exit.

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "NGHTTPD" "1" "Apr 24, 2017" "1.22.0" "nghttp2" .TH "NGHTTPD" "1" "May 30, 2017" "1.23.1" "nghttp2"
.SH NAME .SH NAME
nghttpd \- HTTP/2 server nghttpd \- HTTP/2 server
. .

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "NGHTTPX" "1" "Apr 24, 2017" "1.22.0" "nghttp2" .TH "NGHTTPX" "1" "May 30, 2017" "1.23.1" "nghttp2"
.SH NAME .SH NAME
nghttpx \- HTTP/2 proxy nghttpx \- HTTP/2 proxy
. .
@@ -96,6 +96,18 @@ host pattern "*.nghttp2.org" matches against
match against "nghttp2.org". The exact hosts match match against "nghttp2.org". The exact hosts match
takes precedence over the wildcard hosts match. takes precedence over the wildcard hosts match.
.sp .sp
If path part ends with "*", it is treated as wildcard
path. The wildcard path behaves differently from the
normal path. For normal path, match is made around the
boundary of path component separator,"\fI/\fP". On the other
hand, the wildcard path does not take into account the
path component separator. All paths which include the
wildcard path without last "*" as prefix, and are
strictly longer than wildcard path without last "*" are
matched. "*" must match at least one character. For
example, the pattern "\fI/foo*\fP" matches "\fI/foo/\fP" and
"\fI/foobar\fP". But it does not match "\fI/foo\fP", or "\fI/fo\fP".
.sp
If <PATTERN> is omitted or empty string, "\fI/\fP" is used as If <PATTERN> is omitted or empty string, "\fI/\fP" is used as
pattern, which matches all request paths (catch\-all pattern, which matches all request paths (catch\-all
pattern). The catch\-all backend must be given. pattern). The catch\-all backend must be given.
@@ -611,12 +623,12 @@ password protected it\(aqll be requested interactively.
Specify additional certificate and private key file. Specify additional certificate and private key file.
nghttpx will choose certificates based on the hostname nghttpx will choose certificates based on the hostname
indicated by client using TLS SNI extension. If nghttpx indicated by client using TLS SNI extension. If nghttpx
is built with OpenSSL >= 1.0.2, signature algorithms is built with OpenSSL >= 1.0.2, the shared elliptic
(e.g., ECDSA+SHA256, RSA+SHA256) presented by client are curves (e.g., P\-256) between client and server are also
also taken into consideration. This allows nghttpx to taken into consideration. This allows nghttpx to send
send ECDSA certificate to modern clients, while sending ECDSA certificate to modern clients, while sending RSA
RSA based certificate to older clients. This option can based certificate to older clients. This option can be
be used multiple times. To make OCSP stapling work, used multiple times. To make OCSP stapling work,
<CERTPATH> must be absolute path. <CERTPATH> must be absolute path.
.sp .sp
Additional parameter can be specified in <PARAM>. The Additional parameter can be specified in <PARAM>. The
@@ -812,6 +824,20 @@ Default: \fB4h\fP
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-ocsp\-startup
Start accepting connections after initial attempts to
get OCSP responses finish. It does not matter some of
the attempts fail. This feature is useful if OCSP
responses must be available before accepting
connections.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-no\-verify\-ocsp
nghttpx does not verify OCSP response.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-no\-ocsp .B \-\-no\-ocsp
Disable OCSP stapling. Disable OCSP stapling.
.UNINDENT .UNINDENT
@@ -1730,6 +1756,22 @@ be customized using \fI\%\-\-fetch\-ocsp\-response\-file\fP option.
.sp .sp
If OCSP query is failed, previous OCSP response, if any, is continued If OCSP query is failed, previous OCSP response, if any, is continued
to be used. to be used.
.sp
\fI\%\-\-fetch\-ocsp\-response\-file\fP option provides wide range of
possibility to manage OCSP response. It can take an arbitrary script
or executable. The requirement is that it supports the command\-line
interface of \fBfetch\-ocsp\-response\fP script, and it must return a
valid DER encoded OCSP response on success. It must return exit code
0 on success, and 75 for temporary error, and the other error code for
generic failure. For large cluster of servers, it is not efficient
for each server to perform OCSP query using \fBfetch\-ocsp\-response\fP\&.
Instead, you can retrieve OCSP response in some way, and store it in a
disk or a shared database. Then specify a program in
\fI\%\-\-fetch\-ocsp\-response\-file\fP to fetch it from those stores.
This could provide a way to share the OCSP response between fleet of
servers, and also any OCSP query strategy can be applied which may be
beyond the ability of nghttpx itself or \fBfetch\-ocsp\-response\fP
script.
.SH TLS SESSION RESUMPTION .SH TLS SESSION RESUMPTION
.sp .sp
nghttpx supports TLS session resumption through both session ID and nghttpx supports TLS session resumption through both session ID and

View File

@@ -80,6 +80,18 @@ Connections
match against "nghttp2.org". The exact hosts match match against "nghttp2.org". The exact hosts match
takes precedence over the wildcard hosts match. takes precedence over the wildcard hosts match.
If path part ends with "\*", it is treated as wildcard
path. The wildcard path behaves differently from the
normal path. For normal path, match is made around the
boundary of path component separator,"*/*". On the other
hand, the wildcard path does not take into account the
path component separator. All paths which include the
wildcard path without last "\*" as prefix, and are
strictly longer than wildcard path without last "\*" are
matched. "\*" must match at least one character. For
example, the pattern "*/foo\**" matches "*/foo/*" and
"*/foobar*". But it does not match "*/foo*", or "*/fo*".
If <PATTERN> is omitted or empty string, "*/*" is used as If <PATTERN> is omitted or empty string, "*/*" is used as
pattern, which matches all request paths (catch-all pattern, which matches all request paths (catch-all
pattern). The catch-all backend must be given. pattern). The catch-all backend must be given.
@@ -563,12 +575,12 @@ SSL/TLS
Specify additional certificate and private key file. Specify additional certificate and private key file.
nghttpx will choose certificates based on the hostname nghttpx will choose certificates based on the hostname
indicated by client using TLS SNI extension. If nghttpx indicated by client using TLS SNI extension. If nghttpx
is built with OpenSSL >= 1.0.2, signature algorithms is built with OpenSSL >= 1.0.2, the shared elliptic
(e.g., ECDSA+SHA256, RSA+SHA256) presented by client are curves (e.g., P-256) between client and server are also
also taken into consideration. This allows nghttpx to taken into consideration. This allows nghttpx to send
send ECDSA certificate to modern clients, while sending ECDSA certificate to modern clients, while sending RSA
RSA based certificate to older clients. This option can based certificate to older clients. This option can be
be used multiple times. To make OCSP stapling work, used multiple times. To make OCSP stapling work,
<CERTPATH> must be absolute path. <CERTPATH> must be absolute path.
Additional parameter can be specified in <PARAM>. The Additional parameter can be specified in <PARAM>. The
@@ -743,6 +755,18 @@ SSL/TLS
Default: ``4h`` Default: ``4h``
.. option:: --ocsp-startup
Start accepting connections after initial attempts to
get OCSP responses finish. It does not matter some of
the attempts fail. This feature is useful if OCSP
responses must be available before accepting
connections.
.. option:: --no-verify-ocsp
nghttpx does not verify OCSP response.
.. option:: --no-ocsp .. option:: --no-ocsp
Disable OCSP stapling. Disable OCSP stapling.
@@ -1581,6 +1605,22 @@ be customized using :option:`--fetch-ocsp-response-file` option.
If OCSP query is failed, previous OCSP response, if any, is continued If OCSP query is failed, previous OCSP response, if any, is continued
to be used. to be used.
:option:`--fetch-ocsp-response-file` option provides wide range of
possibility to manage OCSP response. It can take an arbitrary script
or executable. The requirement is that it supports the command-line
interface of ``fetch-ocsp-response`` script, and it must return a
valid DER encoded OCSP response on success. It must return exit code
0 on success, and 75 for temporary error, and the other error code for
generic failure. For large cluster of servers, it is not efficient
for each server to perform OCSP query using ``fetch-ocsp-response``.
Instead, you can retrieve OCSP response in some way, and store it in a
disk or a shared database. Then specify a program in
:option:`--fetch-ocsp-response-file` to fetch it from those stores.
This could provide a way to share the OCSP response between fleet of
servers, and also any OCSP query strategy can be applied which may be
beyond the ability of nghttpx itself or ``fetch-ocsp-response``
script.
TLS SESSION RESUMPTION TLS SESSION RESUMPTION
---------------------- ----------------------

View File

@@ -171,6 +171,22 @@ be customized using :option:`--fetch-ocsp-response-file` option.
If OCSP query is failed, previous OCSP response, if any, is continued If OCSP query is failed, previous OCSP response, if any, is continued
to be used. to be used.
:option:`--fetch-ocsp-response-file` option provides wide range of
possibility to manage OCSP response. It can take an arbitrary script
or executable. The requirement is that it supports the command-line
interface of ``fetch-ocsp-response`` script, and it must return a
valid DER encoded OCSP response on success. It must return exit code
0 on success, and 75 for temporary error, and the other error code for
generic failure. For large cluster of servers, it is not efficient
for each server to perform OCSP query using ``fetch-ocsp-response``.
Instead, you can retrieve OCSP response in some way, and store it in a
disk or a shared database. Then specify a program in
:option:`--fetch-ocsp-response-file` to fetch it from those stores.
This could provide a way to share the OCSP response between fleet of
servers, and also any OCSP query strategy can be applied which may be
beyond the ability of nghttpx itself or ``fetch-ocsp-response``
script.
TLS SESSION RESUMPTION TLS SESSION RESUMPTION
---------------------- ----------------------

View File

@@ -12,7 +12,7 @@ Compiling from source
--------------------- ---------------------
h2load is compiled alongside nghttp2 and requires that the h2load is compiled alongside nghttp2 and requires that the
``--enable-apps`` flag is passed to ``./configure`` and `required ``--enable-app`` flag is passed to ``./configure`` and `required
dependencies <https://github.com/nghttp2/nghttp2#requirements>`_ are dependencies <https://github.com/nghttp2/nghttp2#requirements>`_ are
available during compilation. For details on compiling, see `nghttp2: available during compilation. For details on compiling, see `nghttp2:
Building from Git Building from Git

View File

@@ -62,11 +62,11 @@ ASIOCPPFLAGS = ${AM_CPPFLAGS} ${BOOST_CPPFLAGS}
ASIOLDADD = $(top_builddir)/lib/libnghttp2.la \ ASIOLDADD = $(top_builddir)/lib/libnghttp2.la \
$(top_builddir)/src/libnghttp2_asio.la @JEMALLOC_LIBS@ \ $(top_builddir)/src/libnghttp2_asio.la @JEMALLOC_LIBS@ \
$(top_builddir)/third-party/libhttp-parser.la \ $(top_builddir)/third-party/libhttp-parser.la \
@OPENSSL_LIBS@ \
${BOOST_LDFLAGS} \ ${BOOST_LDFLAGS} \
${BOOST_ASIO_LIB} \ ${BOOST_ASIO_LIB} \
${BOOST_THREAD_LIB} \ ${BOOST_THREAD_LIB} \
${BOOST_SYSTEM_LIB} \ ${BOOST_SYSTEM_LIB} \
@OPENSSL_LIBS@ \
@APPLDFLAGS@ @APPLDFLAGS@
asio_sv_SOURCES = asio-sv.cc asio_sv_SOURCES = asio-sv.cc

View File

@@ -166,6 +166,8 @@ OPTIONS = [
"single-process", "single-process",
"no-add-x-forwarded-proto", "no-add-x-forwarded-proto",
"no-strip-incoming-x-forwarded-proto", "no-strip-incoming-x-forwarded-proto",
"ocsp-startup",
"no-verify-ocsp",
] ]
LOGVARS = [ LOGVARS = [

View File

@@ -672,6 +672,9 @@ int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame) {
nghttp2_buf *buf; nghttp2_buf *buf;
nghttp2_ext_altsvc *altsvc; nghttp2_ext_altsvc *altsvc;
/* This is required with --disable-assert. */
(void)rv;
altsvc = frame->payload; altsvc = frame->payload;
buf = &bufs->head->buf; buf = &bufs->head->buf;

View File

@@ -7150,6 +7150,7 @@ uint32_t nghttp2_session_get_remote_settings(nghttp2_session *session,
} }
assert(0); assert(0);
abort(); /* if NDEBUG is set */
} }
uint32_t nghttp2_session_get_local_settings(nghttp2_session *session, uint32_t nghttp2_session_get_local_settings(nghttp2_session *session,
@@ -7170,6 +7171,7 @@ uint32_t nghttp2_session_get_local_settings(nghttp2_session *session,
} }
assert(0); assert(0);
abort(); /* if NDEBUG is set */
} }
static int nghttp2_session_upgrade_internal(nghttp2_session *session, static int nghttp2_session_upgrade_internal(nghttp2_session *session,

View File

@@ -180,6 +180,9 @@ ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
void Http2Session::on_connect() { void Http2Session::on_connect() {
int rv; int rv;
// This is required with --disable-assert.
(void)rv;
nghttp2_session_callbacks *callbacks; nghttp2_session_callbacks *callbacks;
nghttp2_session_callbacks_new(&callbacks); nghttp2_session_callbacks_new(&callbacks);

View File

@@ -50,23 +50,21 @@ namespace nghttp2 {
#endif // !defined(IOV_MAX) || IOV_MAX >= DEFAULT_WR_IOVCNT #endif // !defined(IOV_MAX) || IOV_MAX >= DEFAULT_WR_IOVCNT
template <size_t N> struct Memchunk { template <size_t N> struct Memchunk {
Memchunk(std::unique_ptr<Memchunk> next_chunk) Memchunk(Memchunk *next_chunk)
: pos(std::begin(buf)), : pos(std::begin(buf)), last(pos), knext(next_chunk), next(nullptr) {}
last(pos),
knext(std::move(next_chunk)),
next(nullptr) {}
size_t len() const { return last - pos; } size_t len() const { return last - pos; }
size_t left() const { return std::end(buf) - last; } size_t left() const { return std::end(buf) - last; }
void reset() { pos = last = std::begin(buf); } void reset() { pos = last = std::begin(buf); }
std::array<uint8_t, N> buf; std::array<uint8_t, N> buf;
uint8_t *pos, *last; uint8_t *pos, *last;
std::unique_ptr<Memchunk> knext; Memchunk *knext;
Memchunk *next; Memchunk *next;
static const size_t size = N; static const size_t size = N;
}; };
template <typename T> struct Pool { template <typename T> struct Pool {
Pool() : pool(nullptr), freelist(nullptr), poolsize(0) {} Pool() : pool(nullptr), freelist(nullptr), poolsize(0) {}
~Pool() { clear(); }
T *get() { T *get() {
if (freelist) { if (freelist) {
auto m = freelist; auto m = freelist;
@@ -76,9 +74,9 @@ template <typename T> struct Pool {
return m; return m;
} }
pool = make_unique<T>(std::move(pool)); pool = new T{pool};
poolsize += T::size; poolsize += T::size;
return pool.get(); return pool;
} }
void recycle(T *m) { void recycle(T *m) {
m->next = freelist; m->next = freelist;
@@ -86,11 +84,16 @@ template <typename T> struct Pool {
} }
void clear() { void clear() {
freelist = nullptr; freelist = nullptr;
for (auto p = pool; p;) {
auto knext = p->knext;
delete p;
p = knext;
}
pool = nullptr; pool = nullptr;
poolsize = 0; poolsize = 0;
} }
using value_type = T; using value_type = T;
std::unique_ptr<T> pool; T *pool;
T *freelist; T *freelist;
size_t poolsize; size_t poolsize;
}; };

View File

@@ -42,34 +42,34 @@ void test_pool_recycle(void) {
auto m1 = pool.get(); auto m1 = pool.get();
CU_ASSERT(m1 == pool.pool.get()); CU_ASSERT(m1 == pool.pool);
CU_ASSERT(MemchunkPool::value_type::size == pool.poolsize); CU_ASSERT(MemchunkPool::value_type::size == pool.poolsize);
CU_ASSERT(nullptr == pool.freelist); CU_ASSERT(nullptr == pool.freelist);
auto m2 = pool.get(); auto m2 = pool.get();
CU_ASSERT(m2 == pool.pool.get()); CU_ASSERT(m2 == pool.pool);
CU_ASSERT(2 * MemchunkPool::value_type::size == pool.poolsize); CU_ASSERT(2 * MemchunkPool::value_type::size == pool.poolsize);
CU_ASSERT(nullptr == pool.freelist); CU_ASSERT(nullptr == pool.freelist);
CU_ASSERT(m1 == m2->knext.get()); CU_ASSERT(m1 == m2->knext);
CU_ASSERT(nullptr == m1->knext.get()); CU_ASSERT(nullptr == m1->knext);
auto m3 = pool.get(); auto m3 = pool.get();
CU_ASSERT(m3 == pool.pool.get()); CU_ASSERT(m3 == pool.pool);
CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize); CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize);
CU_ASSERT(nullptr == pool.freelist); CU_ASSERT(nullptr == pool.freelist);
pool.recycle(m3); pool.recycle(m3);
CU_ASSERT(m3 == pool.pool.get()); CU_ASSERT(m3 == pool.pool);
CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize); CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize);
CU_ASSERT(m3 == pool.freelist); CU_ASSERT(m3 == pool.freelist);
auto m4 = pool.get(); auto m4 = pool.get();
CU_ASSERT(m3 == m4); CU_ASSERT(m3 == m4);
CU_ASSERT(m4 == pool.pool.get()); CU_ASSERT(m4 == pool.pool);
CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize); CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize);
CU_ASSERT(nullptr == pool.freelist); CU_ASSERT(nullptr == pool.freelist);

View File

@@ -172,6 +172,8 @@ Request::~Request() { nghttp2_gzip_inflate_del(inflater); }
void Request::init_inflater() { void Request::init_inflater() {
int rv; int rv;
// This is required with --disable-assert.
(void)rv;
rv = nghttp2_gzip_inflate_new(&inflater); rv = nghttp2_gzip_inflate_new(&inflater);
assert(rv == 0); assert(rv == 0);
} }

View File

@@ -43,14 +43,14 @@ static size_t deflate_data(uint8_t *out, size_t outlen, const uint8_t *in,
zst.opaque = Z_NULL; zst.opaque = Z_NULL;
rv = deflateInit(&zst, Z_DEFAULT_COMPRESSION); rv = deflateInit(&zst, Z_DEFAULT_COMPRESSION);
assert(rv == Z_OK); CU_ASSERT(rv == Z_OK);
zst.avail_in = (unsigned int)inlen; zst.avail_in = (unsigned int)inlen;
zst.next_in = (uint8_t *)in; zst.next_in = (uint8_t *)in;
zst.avail_out = (unsigned int)outlen; zst.avail_out = (unsigned int)outlen;
zst.next_out = out; zst.next_out = out;
rv = deflate(&zst, Z_SYNC_FLUSH); rv = deflate(&zst, Z_SYNC_FLUSH);
assert(rv == Z_OK); CU_ASSERT(rv == Z_OK);
deflateEnd(&zst); deflateEnd(&zst);

View File

@@ -2084,12 +2084,12 @@ SSL/TLS:
Specify additional certificate and private key file. Specify additional certificate and private key file.
nghttpx will choose certificates based on the hostname nghttpx will choose certificates based on the hostname
indicated by client using TLS SNI extension. If nghttpx indicated by client using TLS SNI extension. If nghttpx
is built with OpenSSL >= 1.0.2, signature algorithms is built with OpenSSL >= 1.0.2, the shared elliptic
(e.g., ECDSA+SHA256, RSA+SHA256) presented by client are curves (e.g., P-256) between client and server are also
also taken into consideration. This allows nghttpx to taken into consideration. This allows nghttpx to send
send ECDSA certificate to modern clients, while sending ECDSA certificate to modern clients, while sending RSA
RSA based certificate to older clients. This option can based certificate to older clients. This option can be
be used multiple times. To make OCSP stapling work, used multiple times. To make OCSP stapling work,
<CERTPATH> must be absolute path. <CERTPATH> must be absolute path.
Additional parameter can be specified in <PARAM>. The Additional parameter can be specified in <PARAM>. The
@@ -2234,6 +2234,14 @@ SSL/TLS:
Set interval to update OCSP response cache. Set interval to update OCSP response cache.
Default: )" Default: )"
<< util::duration_str(config->tls.ocsp.update_interval) << R"( << util::duration_str(config->tls.ocsp.update_interval) << R"(
--ocsp-startup
Start accepting connections after initial attempts to
get OCSP responses finish. It does not matter some of
the attempts fail. This feature is useful if OCSP
responses must be available before accepting
connections.
--no-verify-ocsp
nghttpx does not verify OCSP response.
--no-ocsp Disable OCSP stapling. --no-ocsp Disable OCSP stapling.
--tls-session-cache-memcached=<HOST>,<PORT>[;tls] --tls-session-cache-memcached=<HOST>,<PORT>[;tls]
Specify address of memcached server to store session Specify address of memcached server to store session
@@ -3183,7 +3191,9 @@ int main(int argc, char **argv) {
{SHRPX_OPT_BACKEND_HTTP_PROXY_URI.c_str(), required_argument, &flag, {SHRPX_OPT_BACKEND_HTTP_PROXY_URI.c_str(), required_argument, &flag,
26}, 26},
{SHRPX_OPT_BACKEND_NO_TLS.c_str(), no_argument, &flag, 27}, {SHRPX_OPT_BACKEND_NO_TLS.c_str(), no_argument, &flag, 27},
{SHRPX_OPT_OCSP_STARTUP.c_str(), no_argument, &flag, 28},
{SHRPX_OPT_FRONTEND_NO_TLS.c_str(), no_argument, &flag, 29}, {SHRPX_OPT_FRONTEND_NO_TLS.c_str(), no_argument, &flag, 29},
{SHRPX_OPT_NO_VERIFY_OCSP.c_str(), no_argument, &flag, 30},
{SHRPX_OPT_BACKEND_TLS_SNI_FIELD.c_str(), required_argument, &flag, 31}, {SHRPX_OPT_BACKEND_TLS_SNI_FIELD.c_str(), required_argument, &flag, 31},
{SHRPX_OPT_DH_PARAM_FILE.c_str(), required_argument, &flag, 33}, {SHRPX_OPT_DH_PARAM_FILE.c_str(), required_argument, &flag, 33},
{SHRPX_OPT_READ_RATE.c_str(), required_argument, &flag, 34}, {SHRPX_OPT_READ_RATE.c_str(), required_argument, &flag, 34},
@@ -3533,11 +3543,21 @@ int main(int argc, char **argv) {
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_NO_TLS, cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_NO_TLS,
StringRef::from_lit("yes")); StringRef::from_lit("yes"));
break; break;
case 28:
// --ocsp-startup
cmdcfgs.emplace_back(SHRPX_OPT_OCSP_STARTUP,
StringRef::from_lit("yes"));
break;
case 29: case 29:
// --frontend-no-tls // --frontend-no-tls
cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_NO_TLS, cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_NO_TLS,
StringRef::from_lit("yes")); StringRef::from_lit("yes"));
break; break;
case 30:
// --no-verify-ocsp
cmdcfgs.emplace_back(SHRPX_OPT_NO_VERIFY_OCSP,
StringRef::from_lit("yes"));
break;
case 31: case 31:
// --backend-tls-sni-field // --backend-tls-sni-field
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_TLS_SNI_FIELD, cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_TLS_SNI_FIELD,

View File

@@ -1591,6 +1591,11 @@ int option_lookup_token(const char *name, size_t namelen) {
return SHRPX_OPTID_HTTP2_BRIDGE; return SHRPX_OPTID_HTTP2_BRIDGE;
} }
break; break;
case 'p':
if (util::strieq_l("ocsp-startu", name, 11)) {
return SHRPX_OPTID_OCSP_STARTUP;
}
break;
case 'y': case 'y':
if (util::strieq_l("client-prox", name, 11)) { if (util::strieq_l("client-prox", name, 11)) {
return SHRPX_OPTID_CLIENT_PROXY; return SHRPX_OPTID_CLIENT_PROXY;
@@ -1646,6 +1651,11 @@ int option_lookup_token(const char *name, size_t namelen) {
return SHRPX_OPTID_NO_SERVER_PUSH; return SHRPX_OPTID_NO_SERVER_PUSH;
} }
break; break;
case 'p':
if (util::strieq_l("no-verify-ocs", name, 13)) {
return SHRPX_OPTID_NO_VERIFY_OCSP;
}
break;
case 's': case 's':
if (util::strieq_l("backend-no-tl", name, 13)) { if (util::strieq_l("backend-no-tl", name, 13)) {
return SHRPX_OPTID_BACKEND_NO_TLS; return SHRPX_OPTID_BACKEND_NO_TLS;
@@ -3420,6 +3430,14 @@ int parse_config(Config *config, int optid, const StringRef &opt,
case SHRPX_OPTID_NO_STRIP_INCOMING_X_FORWARDED_PROTO: case SHRPX_OPTID_NO_STRIP_INCOMING_X_FORWARDED_PROTO:
config->http.xfp.strip_incoming = !util::strieq_l("yes", optarg); config->http.xfp.strip_incoming = !util::strieq_l("yes", optarg);
return 0;
case SHRPX_OPTID_OCSP_STARTUP:
config->tls.ocsp.startup = util::strieq_l("yes", optarg);
return 0;
case SHRPX_OPTID_NO_VERIFY_OCSP:
config->tls.ocsp.no_verify = util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_CONF: case SHRPX_OPTID_CONF:
LOG(WARN) << "conf: ignored"; LOG(WARN) << "conf: ignored";
@@ -3613,6 +3631,7 @@ StringRef strproto(shrpx_proto proto) {
// gcc needs this. // gcc needs this.
assert(0); assert(0);
abort();
} }
namespace { namespace {

View File

@@ -341,6 +341,8 @@ constexpr auto SHRPX_OPT_NO_ADD_X_FORWARDED_PROTO =
StringRef::from_lit("no-add-x-forwarded-proto"); StringRef::from_lit("no-add-x-forwarded-proto");
constexpr auto SHRPX_OPT_NO_STRIP_INCOMING_X_FORWARDED_PROTO = constexpr auto SHRPX_OPT_NO_STRIP_INCOMING_X_FORWARDED_PROTO =
StringRef::from_lit("no-strip-incoming-x-forwarded-proto"); StringRef::from_lit("no-strip-incoming-x-forwarded-proto");
constexpr auto SHRPX_OPT_OCSP_STARTUP = StringRef::from_lit("ocsp-startup");
constexpr auto SHRPX_OPT_NO_VERIFY_OCSP = StringRef::from_lit("no-verify-ocsp");
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
@@ -561,6 +563,8 @@ struct TLSConfig {
ev_tstamp update_interval; ev_tstamp update_interval;
StringRef fetch_ocsp_response_file; StringRef fetch_ocsp_response_file;
bool disabled; bool disabled;
bool startup;
bool no_verify;
} ocsp; } ocsp;
// Client verification configurations // Client verification configurations
@@ -1043,8 +1047,10 @@ enum {
SHRPX_OPTID_NO_SERVER_PUSH, SHRPX_OPTID_NO_SERVER_PUSH,
SHRPX_OPTID_NO_SERVER_REWRITE, SHRPX_OPTID_NO_SERVER_REWRITE,
SHRPX_OPTID_NO_STRIP_INCOMING_X_FORWARDED_PROTO, SHRPX_OPTID_NO_STRIP_INCOMING_X_FORWARDED_PROTO,
SHRPX_OPTID_NO_VERIFY_OCSP,
SHRPX_OPTID_NO_VIA, SHRPX_OPTID_NO_VIA,
SHRPX_OPTID_NPN_LIST, SHRPX_OPTID_NPN_LIST,
SHRPX_OPTID_OCSP_STARTUP,
SHRPX_OPTID_OCSP_UPDATE_INTERVAL, SHRPX_OPTID_OCSP_UPDATE_INTERVAL,
SHRPX_OPTID_PADDING, SHRPX_OPTID_PADDING,
SHRPX_OPTID_PID_FILE, SHRPX_OPTID_PID_FILE,

View File

@@ -163,14 +163,14 @@ void test_shrpx_config_parse_log_format(void) {
void test_shrpx_config_read_tls_ticket_key_file(void) { void test_shrpx_config_read_tls_ticket_key_file(void) {
char file1[] = "/tmp/nghttpx-unittest.XXXXXX"; char file1[] = "/tmp/nghttpx-unittest.XXXXXX";
auto fd1 = mkstemp(file1); auto fd1 = mkstemp(file1);
assert(fd1 != -1); CU_ASSERT(fd1 != -1);
assert(48 == CU_ASSERT(48 ==
write(fd1, "0..............12..............34..............5", 48)); write(fd1, "0..............12..............34..............5", 48));
char file2[] = "/tmp/nghttpx-unittest.XXXXXX"; char file2[] = "/tmp/nghttpx-unittest.XXXXXX";
auto fd2 = mkstemp(file2); auto fd2 = mkstemp(file2);
assert(fd2 != -1); CU_ASSERT(fd2 != -1);
assert(48 == CU_ASSERT(48 ==
write(fd2, "6..............78..............9a..............b", 48)); write(fd2, "6..............78..............9a..............b", 48));
close(fd1); close(fd1);
close(fd2); close(fd2);
@@ -204,16 +204,18 @@ void test_shrpx_config_read_tls_ticket_key_file(void) {
void test_shrpx_config_read_tls_ticket_key_file_aes_256(void) { void test_shrpx_config_read_tls_ticket_key_file_aes_256(void) {
char file1[] = "/tmp/nghttpx-unittest.XXXXXX"; char file1[] = "/tmp/nghttpx-unittest.XXXXXX";
auto fd1 = mkstemp(file1); auto fd1 = mkstemp(file1);
assert(fd1 != -1); CU_ASSERT(fd1 != -1);
assert(80 == write(fd1, "0..............12..............................34..." CU_ASSERT(80 == write(fd1,
"...........................5", "0..............12..............................34..."
80)); "...........................5",
80));
char file2[] = "/tmp/nghttpx-unittest.XXXXXX"; char file2[] = "/tmp/nghttpx-unittest.XXXXXX";
auto fd2 = mkstemp(file2); auto fd2 = mkstemp(file2);
assert(fd2 != -1); CU_ASSERT(fd2 != -1);
assert(80 == write(fd2, "6..............78..............................9a..." CU_ASSERT(80 == write(fd2,
"...........................b", "6..............78..............................9a..."
80)); "...........................b",
80));
close(fd1); close(fd1);
close(fd2); close(fd2);

View File

@@ -381,6 +381,8 @@ int Connection::tls_handshake() {
break; break;
} }
ERR_clear_error();
auto rv = SSL_do_handshake(tls.ssl); auto rv = SSL_do_handshake(tls.ssl);
if (rv <= 0) { if (rv <= 0) {
@@ -615,6 +617,8 @@ ssize_t Connection::write_tls(const void *data, size_t len) {
tls.last_write_idle = -1.; tls.last_write_idle = -1.;
ERR_clear_error();
auto rv = SSL_write(tls.ssl, data, len); auto rv = SSL_write(tls.ssl, data, len);
if (rv <= 0) { if (rv <= 0) {
@@ -667,6 +671,8 @@ ssize_t Connection::read_tls(void *data, size_t len) {
tls.last_readlen = 0; tls.last_readlen = 0;
} }
ERR_clear_error();
auto rv = SSL_read(tls.ssl, data, len); auto rv = SSL_read(tls.ssl, data, len);
if (rv <= 0) { if (rv <= 0) {

View File

@@ -118,7 +118,8 @@ ConnectionHandler::ConnectionHandler(struct ev_loop *loop, std::mt19937 &gen)
tls_ticket_key_memcached_get_retry_count_(0), tls_ticket_key_memcached_get_retry_count_(0),
tls_ticket_key_memcached_fail_count_(0), tls_ticket_key_memcached_fail_count_(0),
worker_round_robin_cnt_(get_config()->api.enabled ? 1 : 0), worker_round_robin_cnt_(get_config()->api.enabled ? 1 : 0),
graceful_shutdown_(false) { graceful_shutdown_(false),
enable_acceptor_on_ocsp_completion_(false) {
ev_timer_init(&disable_acceptor_timer_, acceptor_disable_cb, 0., 0.); ev_timer_init(&disable_acceptor_timer_, acceptor_disable_cb, 0., 0.);
disable_acceptor_timer_.data = this; disable_acceptor_timer_.data = this;
@@ -504,6 +505,9 @@ bool ConnectionHandler::get_graceful_shutdown() const {
} }
void ConnectionHandler::cancel_ocsp_update() { void ConnectionHandler::cancel_ocsp_update() {
enable_acceptor_on_ocsp_completion_ = false;
ev_timer_stop(loop_, &ocsp_timer_);
if (ocsp_.proc.pid == 0) { if (ocsp_.proc.pid == 0) {
return; return;
} }
@@ -616,8 +620,13 @@ void ConnectionHandler::handle_ocsp_complete() {
<< " finished successfully"; << " finished successfully";
} }
auto config = get_config();
auto &tlsconf = config->tls;
if (tlsconf.ocsp.no_verify ||
tls::verify_ocsp_response(ssl_ctx, ocsp_.resp.data(),
ocsp_.resp.size()) == 0) {
#ifndef OPENSSL_IS_BORINGSSL #ifndef OPENSSL_IS_BORINGSSL
{
#ifdef HAVE_ATOMIC_STD_SHARED_PTR #ifdef HAVE_ATOMIC_STD_SHARED_PTR
std::atomic_store_explicit( std::atomic_store_explicit(
&tls_ctx_data->ocsp_data, &tls_ctx_data->ocsp_data,
@@ -628,10 +637,10 @@ void ConnectionHandler::handle_ocsp_complete() {
tls_ctx_data->ocsp_data = tls_ctx_data->ocsp_data =
std::make_shared<std::vector<uint8_t>>(std::move(ocsp_.resp)); std::make_shared<std::vector<uint8_t>>(std::move(ocsp_.resp));
#endif // !HAVE_ATOMIC_STD_SHARED_PTR #endif // !HAVE_ATOMIC_STD_SHARED_PTR
}
#else // OPENSSL_IS_BORINGSSL #else // OPENSSL_IS_BORINGSSL
SSL_CTX_set_ocsp_response(ssl_ctx, ocsp_.resp.data(), ocsp_.resp.size()); SSL_CTX_set_ocsp_response(ssl_ctx, ocsp_.resp.data(), ocsp_.resp.size());
#endif // OPENSSL_IS_BORINGSSL #endif // OPENSSL_IS_BORINGSSL
}
++ocsp_.next; ++ocsp_.next;
proceed_next_cert_ocsp(); proceed_next_cert_ocsp();
@@ -656,6 +665,12 @@ void ConnectionHandler::proceed_next_cert_ocsp() {
// We have updated all ocsp response, and schedule next update. // We have updated all ocsp response, and schedule next update.
ev_timer_set(&ocsp_timer_, get_config()->tls.ocsp.update_interval, 0.); ev_timer_set(&ocsp_timer_, get_config()->tls.ocsp.update_interval, 0.);
ev_timer_start(loop_, &ocsp_timer_); ev_timer_start(loop_, &ocsp_timer_);
if (enable_acceptor_on_ocsp_completion_) {
enable_acceptor_on_ocsp_completion_ = false;
enable_acceptor();
}
return; return;
} }
@@ -855,4 +870,8 @@ ConnectionHandler::get_indexed_ssl_ctx(size_t idx) const {
return indexed_ssl_ctx_[idx]; return indexed_ssl_ctx_[idx];
} }
void ConnectionHandler::set_enable_acceptor_on_ocsp_completion(bool f) {
enable_acceptor_on_ocsp_completion_ = f;
}
} // namespace shrpx } // namespace shrpx

View File

@@ -174,6 +174,8 @@ public:
void void
worker_replace_downstream(std::shared_ptr<DownstreamConfig> downstreamconf); worker_replace_downstream(std::shared_ptr<DownstreamConfig> downstreamconf);
void set_enable_acceptor_on_ocsp_completion(bool f);
private: private:
// Stores all SSL_CTX objects. // Stores all SSL_CTX objects.
std::vector<SSL_CTX *> all_ssl_ctx_; std::vector<SSL_CTX *> all_ssl_ctx_;
@@ -220,6 +222,9 @@ private:
size_t tls_ticket_key_memcached_fail_count_; size_t tls_ticket_key_memcached_fail_count_;
unsigned int worker_round_robin_cnt_; unsigned int worker_round_robin_cnt_;
bool graceful_shutdown_; bool graceful_shutdown_;
// true if acceptors should be enabled after the initial ocsp update
// has finished.
bool enable_acceptor_on_ocsp_completion_;
}; };
} // namespace shrpx } // namespace shrpx

View File

@@ -204,6 +204,7 @@ int DNSResolver::handle_event(int rfd, int wfd) {
default: default:
// Unreachable // Unreachable
assert(0); assert(0);
abort();
} }
} }

View File

@@ -250,6 +250,7 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) {
return DNS_STATUS_OK; return DNS_STATUS_OK;
default: default:
assert(0); assert(0);
abort();
} }
} }

View File

@@ -158,6 +158,8 @@ Downstream *DownstreamQueue::remove_and_get_blocked(Downstream *downstream,
auto next_downstream = link->downstream; auto next_downstream = link->downstream;
auto link2 = next_downstream->detach_blocked_link(); auto link2 = next_downstream->detach_blocked_link();
// This is required with --disable-assert.
(void)link2;
assert(link2 == link); assert(link2 == link);
ent.blocked.remove(link); ent.blocked.remove(link);
delete link; delete link;

View File

@@ -334,6 +334,7 @@ int Http2Session::resolve_name() {
return 0; return 0;
default: default:
assert(0); assert(0);
abort();
} }
} }
@@ -2115,7 +2116,10 @@ int Http2Session::write_tls() {
for (;;) { for (;;) {
if (wb_.rleft() > 0) { if (wb_.rleft() > 0) {
auto iovcnt = wb_.riovec(&iov, 1); auto iovcnt = wb_.riovec(&iov, 1);
assert(iovcnt == 1); if (iovcnt != 1) {
assert(0);
return -1;
}
auto nwrite = conn_.write_tls(iov.iov_base, iov.iov_len); auto nwrite = conn_.write_tls(iov.iov_base, iov.iov_len);
if (nwrite == 0) { if (nwrite == 0) {

View File

@@ -1307,7 +1307,10 @@ int HttpDownstreamConnection::write_tls() {
while (input->rleft() > 0) { while (input->rleft() > 0) {
auto iovcnt = input->riovec(&iov, 1); auto iovcnt = input->riovec(&iov, 1);
assert(iovcnt == 1); if (iovcnt != 1) {
assert(0);
return -1;
}
auto nwrite = conn_.write_tls(iov.iov_base, iov.iov_len); auto nwrite = conn_.write_tls(iov.iov_base, iov.iov_len);
if (nwrite == 0) { if (nwrite == 0) {

View File

@@ -478,7 +478,10 @@ int LiveCheck::write_tls() {
for (;;) { for (;;) {
if (wb_.rleft() > 0) { if (wb_.rleft() > 0) {
auto iovcnt = wb_.riovec(&iov, 1); auto iovcnt = wb_.riovec(&iov, 1);
assert(iovcnt == 1); if (iovcnt != 1) {
assert(0);
return -1;
}
auto nwrite = conn_.write_tls(iov.iov_base, iov.iov_len); auto nwrite = conn_.write_tls(iov.iov_base, iov.iov_len);
if (nwrite == 0) { if (nwrite == 0) {
@@ -544,7 +547,10 @@ int LiveCheck::write_clear() {
for (;;) { for (;;) {
if (wb_.rleft() > 0) { if (wb_.rleft() > 0) {
auto iovcnt = wb_.riovec(&iov, 1); auto iovcnt = wb_.riovec(&iov, 1);
assert(iovcnt == 1); if (iovcnt != 1) {
assert(0);
return -1;
}
auto nwrite = conn_.write_clear(iov.iov_base, iov.iov_len); auto nwrite = conn_.write_clear(iov.iov_base, iov.iov_len);
if (nwrite == 0) { if (nwrite == 0) {

View File

@@ -45,6 +45,7 @@
#include <openssl/x509v3.h> #include <openssl/x509v3.h>
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/dh.h> #include <openssl/dh.h>
#include <openssl/ocsp.h>
#include <nghttp2/nghttp2.h> #include <nghttp2/nghttp2.h>
@@ -186,19 +187,43 @@ int servername_callback(SSL *ssl, int *al, void *arg) {
#if !defined(OPENSSL_IS_BORINGSSL) && !defined(LIBRESSL_VERSION_NUMBER) && \ #if !defined(OPENSSL_IS_BORINGSSL) && !defined(LIBRESSL_VERSION_NUMBER) && \
OPENSSL_VERSION_NUMBER >= 0x10002000L OPENSSL_VERSION_NUMBER >= 0x10002000L
// boringssl removed SSL_get_sigalgs. auto num_shared_curves = SSL_get_shared_curve(ssl, -1);
auto num_sigalg =
SSL_get_sigalgs(ssl, 0, nullptr, nullptr, nullptr, nullptr, nullptr); for (auto i = 0; i < num_shared_curves; ++i) {
auto shared_curve = SSL_get_shared_curve(ssl, i);
for (auto i = 0; i < num_sigalg; ++i) {
int sigalg;
SSL_get_sigalgs(ssl, i, nullptr, nullptr, &sigalg, nullptr, nullptr);
for (auto ssl_ctx : ssl_ctx_list) { for (auto ssl_ctx : ssl_ctx_list) {
auto cert = SSL_CTX_get0_certificate(ssl_ctx); auto cert = SSL_CTX_get0_certificate(ssl_ctx);
// X509_get_signature_nid is available since OpenSSL 1.0.2.
auto cert_sigalg = X509_get_signature_nid(cert);
if (sigalg == cert_sigalg) { #if OPENSSL_1_1_API
auto pubkey = X509_get0_pubkey(cert);
#else // !OPENSSL_1_1_API
auto pubkey = X509_get_pubkey(cert);
#endif // !OPENSSL_1_1_API
if (EVP_PKEY_base_id(pubkey) != EVP_PKEY_EC) {
continue;
}
#if OPENSSL_1_1_API
auto eckey = EVP_PKEY_get0_EC_KEY(pubkey);
#else // !OPENSSL_1_1_API
auto eckey = EVP_PKEY_get1_EC_KEY(pubkey);
#endif // !OPENSSL_1_1_API
if (eckey == nullptr) {
continue;
}
auto ecgroup = EC_KEY_get0_group(eckey);
auto cert_curve = EC_GROUP_get_curve_name(ecgroup);
#if !OPENSSL_1_1_API
EC_KEY_free(eckey);
EVP_PKEY_free(pubkey);
#endif // !OPENSSL_1_1_API
if (shared_curve == cert_curve) {
SSL_set_SSL_CTX(ssl, ssl_ctx); SSL_set_SSL_CTX(ssl, ssl_ctx);
return SSL_TLSEXT_ERR_OK; return SSL_TLSEXT_ERR_OK;
} }
@@ -1511,8 +1536,6 @@ int cert_lookup_tree_add_ssl_ctx(
#endif // defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < #endif // defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER <
// 0x10002000L // 0x10002000L
auto idx = indexed_ssl_ctx.size();
auto altnames = static_cast<GENERAL_NAMES *>( auto altnames = static_cast<GENERAL_NAMES *>(
X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr)); X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr));
if (altnames) { if (altnames) {
@@ -1555,15 +1578,16 @@ int cert_lookup_tree_add_ssl_ctx(
auto end_buf = std::copy_n(name, len, std::begin(buf)); auto end_buf = std::copy_n(name, len, std::begin(buf));
util::inp_strlower(std::begin(buf), end_buf); util::inp_strlower(std::begin(buf), end_buf);
auto nidx = lt->add_cert(StringRef{std::begin(buf), end_buf}, idx); auto idx = lt->add_cert(StringRef{std::begin(buf), end_buf},
if (nidx == -1) { indexed_ssl_ctx.size());
if (idx == -1) {
continue; continue;
} }
idx = nidx;
if (idx < indexed_ssl_ctx.size()) { if (static_cast<size_t>(idx) < indexed_ssl_ctx.size()) {
indexed_ssl_ctx[idx].push_back(ssl_ctx); indexed_ssl_ctx[idx].push_back(ssl_ctx);
} else { } else {
assert(idx == indexed_ssl_ctx.size()); assert(static_cast<size_t>(idx) == indexed_ssl_ctx.size());
indexed_ssl_ctx.emplace_back(std::vector<SSL_CTX *>{ssl_ctx}); indexed_ssl_ctx.emplace_back(std::vector<SSL_CTX *>{ssl_ctx});
} }
} }
@@ -1595,15 +1619,16 @@ int cert_lookup_tree_add_ssl_ctx(
util::inp_strlower(std::begin(buf), end_buf); util::inp_strlower(std::begin(buf), end_buf);
auto nidx = lt->add_cert(StringRef{std::begin(buf), end_buf}, idx); auto idx =
if (nidx == -1) { lt->add_cert(StringRef{std::begin(buf), end_buf}, indexed_ssl_ctx.size());
if (idx == -1) {
return 0; return 0;
} }
idx = nidx;
if (idx < indexed_ssl_ctx.size()) { if (static_cast<size_t>(idx) < indexed_ssl_ctx.size()) {
indexed_ssl_ctx[idx].push_back(ssl_ctx); indexed_ssl_ctx[idx].push_back(ssl_ctx);
} else { } else {
assert(idx == indexed_ssl_ctx.size()); assert(static_cast<size_t>(idx) == indexed_ssl_ctx.size());
indexed_ssl_ctx.emplace_back(std::vector<SSL_CTX *>{ssl_ctx}); indexed_ssl_ctx.emplace_back(std::vector<SSL_CTX *>{ssl_ctx});
} }
@@ -1794,6 +1819,87 @@ int proto_version_from_string(const StringRef &v) {
return -1; return -1;
} }
int verify_ocsp_response(SSL_CTX *ssl_ctx, const uint8_t *ocsp_resp,
size_t ocsp_resplen) {
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10002000L
int rv;
STACK_OF(X509) * chain_certs;
SSL_CTX_get0_chain_certs(ssl_ctx, &chain_certs);
auto resp = d2i_OCSP_RESPONSE(nullptr, &ocsp_resp, ocsp_resplen);
if (resp == nullptr) {
LOG(ERROR) << "d2i_OCSP_RESPONSE failed";
return -1;
}
auto resp_deleter = defer(OCSP_RESPONSE_free, resp);
ERR_clear_error();
auto bs = OCSP_response_get1_basic(resp);
if (bs == nullptr) {
LOG(ERROR) << "OCSP_response_get1_basic failed: "
<< ERR_error_string(ERR_get_error(), nullptr);
return -1;
}
auto bs_deleter = defer(OCSP_BASICRESP_free, bs);
auto store = X509_STORE_new();
auto store_deleter = defer(X509_STORE_free, store);
ERR_clear_error();
rv = OCSP_basic_verify(bs, chain_certs, store, OCSP_TRUSTOTHER);
if (rv != 1) {
LOG(ERROR) << "OCSP_basic_verify failed: "
<< ERR_error_string(ERR_get_error(), nullptr);
return -1;
}
auto sresp = OCSP_resp_get0(bs, 0);
if (sresp == nullptr) {
LOG(ERROR) << "OCSP response verification failed: no single response";
return -1;
}
#if OPENSSL_1_1_API
auto certid = OCSP_SINGLERESP_get0_id(sresp);
#else // !OPENSSL_1_1_API
auto certid = sresp->certId;
#endif // !OPENSSL_1_1_API
assert(certid != nullptr);
ASN1_INTEGER *serial;
rv = OCSP_id_get0_info(nullptr, nullptr, nullptr, &serial,
const_cast<OCSP_CERTID *>(certid));
if (rv != 1) {
LOG(ERROR) << "OCSP_id_get0_info failed";
return -1;
}
if (serial == nullptr) {
LOG(ERROR) << "OCSP response does not contain serial number";
return -1;
}
auto cert = SSL_CTX_get0_certificate(ssl_ctx);
auto cert_serial = X509_get_serialNumber(cert);
if (ASN1_INTEGER_cmp(cert_serial, serial)) {
LOG(ERROR) << "OCSP verification serial numbers do not match";
return -1;
}
if (LOG_ENABLED(INFO)) {
LOG(INFO) << "OCSP verification succeeded";
}
#endif // !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >=
// 0x10002000L
return 0;
}
} // namespace tls } // namespace tls
} // namespace shrpx } // namespace shrpx

View File

@@ -264,6 +264,11 @@ X509 *load_certificate(const char *filename);
// TLS version string. // TLS version string.
int proto_version_from_string(const StringRef &v); int proto_version_from_string(const StringRef &v);
// Verifies OCSP response |ocsp_resp| of length |ocsp_resplen|. This
// function returns 0 if it succeeds, or -1.
int verify_ocsp_response(SSL_CTX *ssl_ctx, const uint8_t *ocsp_resp,
size_t ocsp_resplen);
} // namespace tls } // namespace tls
} // namespace shrpx } // namespace shrpx

View File

@@ -154,9 +154,9 @@ void test_shrpx_tls_cert_lookup_tree_add_ssl_ctx(void) {
CU_ASSERT(-1 == tree.lookup(StringRef::from_lit("not-used.nghttp2.org"))); CU_ASSERT(-1 == tree.lookup(StringRef::from_lit("not-used.nghttp2.org")));
CU_ASSERT(0 == tree.lookup(StringRef::from_lit("test.nghttp2.org"))); CU_ASSERT(0 == tree.lookup(StringRef::from_lit("test.nghttp2.org")));
CU_ASSERT(0 == tree.lookup(StringRef::from_lit("w.test.nghttp2.org"))); CU_ASSERT(1 == tree.lookup(StringRef::from_lit("w.test.nghttp2.org")));
CU_ASSERT(0 == tree.lookup(StringRef::from_lit("www.test.nghttp2.org"))); CU_ASSERT(2 == tree.lookup(StringRef::from_lit("www.test.nghttp2.org")));
CU_ASSERT(1 == tree.lookup(StringRef::from_lit("test.example.com"))); CU_ASSERT(3 == tree.lookup(StringRef::from_lit("test.example.com")));
} }
template <size_t N, size_t M> template <size_t N, size_t M>

View File

@@ -547,6 +547,11 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
ev_io_start(loop, &ipcev); ev_io_start(loop, &ipcev);
if (tls::upstream_tls_enabled(config->conn) && !config->tls.ocsp.disabled) { if (tls::upstream_tls_enabled(config->conn) && !config->tls.ocsp.disabled) {
if (config->tls.ocsp.startup) {
conn_handler.set_enable_acceptor_on_ocsp_completion(true);
conn_handler.disable_acceptor();
}
conn_handler.proceed_next_cert_ocsp(); conn_handler.proceed_next_cert_ocsp();
} }