diff options
-rw-r--r-- | community/h2o/APKBUILD | 28 | ||||
-rw-r--r-- | community/h2o/backslashinterpreationintests.patch | 14 | ||||
-rw-r--r-- | community/h2o/cannotlocatetutilpm.patch | 39 | ||||
-rw-r--r-- | community/h2o/disabletls13intls12tests.patch | 25 | ||||
-rw-r--r-- | community/h2o/increasewaitforserverstartintests.patch | 14 | ||||
-rw-r--r-- | community/h2o/largeheadertest.patch | 19 | ||||
-rw-r--r-- | community/h2o/missingsubmodules.patch | 503 | ||||
-rw-r--r-- | community/h2o/proxysessionresumption.patch | 134 | ||||
-rw-r--r-- | community/h2o/sessiontickettest.patch | 140 | ||||
-rw-r--r-- | community/perl-http-entity-parser/APKBUILD (renamed from testing/perl-http-entity-parser/APKBUILD) | 0 | ||||
-rw-r--r-- | community/perl-http-multipartparser/APKBUILD (renamed from testing/perl-http-multipartparser/APKBUILD) | 0 | ||||
-rw-r--r-- | community/perl-protocol-http2/APKBUILD (renamed from testing/perl-protocol-http2/APKBUILD) | 0 | ||||
-rw-r--r-- | community/perl-www-form-urlencoded/APKBUILD (renamed from testing/perl-www-form-urlencoded/APKBUILD) | 0 |
13 files changed, 912 insertions, 4 deletions
diff --git a/community/h2o/APKBUILD b/community/h2o/APKBUILD index 9be25491d4c..c46efaf3c06 100644 --- a/community/h2o/APKBUILD +++ b/community/h2o/APKBUILD @@ -1,21 +1,30 @@ # Contributor: Bennett Goble <nivardus@gmail.com> +# Contributor: Axel Ulrich <ulrich.axel@gmail.com> # Maintainer: Bennett Goble <nivardus@gmail.com> pkgname=h2o pkgver=2.2.6 -pkgrel=4 +pkgrel=5 pkgdesc="An optimized HTTP/1, HTTP/2 server written in C" url="https://h2o.examp1e.net" arch="all !s390x" depends="perl openssl" license="MIT" makedepends="cmake ruby-dev bison zlib-dev wslay-dev openssl-dev libuv-dev yaml-dev" -options="!check" +checkdepends="perl-test-harness-utils perl-test-tcp perl-test-simple perl-json perl-path-tiny perl-scope-guard perl-test-exception perl-protocol-http2 perl-test-requires perl-hash-multivalue perl-plack perl-lwp-protocol-https perl-http-headers-fast perl-cookie-baker perl-http-entity-parser perl-starlet perl-fcgi-procmanager perl-cgi perl-fcgi nodejs wget" install="$pkgname.pre-install" subpackages="$pkgname-dev $pkgname-doc $pkgname-openrc" source="$pkgname-$pkgver.tar.gz::https://github.com/h2o/h2o/archive/v$pkgver.tar.gz h2o.conf h2o.initd h2o.logrotate + missingsubmodules.patch + backslashinterpreationintests.patch + disabletls13intls12tests.patch + largeheadertest.patch + proxysessionresumption.patch + sessiontickettest.patch + cannotlocatetutilpm.patch + increasewaitforserverstartintests.patch " # secfixes: @@ -32,7 +41,10 @@ build() { -DCMAKE_INSTALL_PREFIX=/usr \ -DWITH_MRUBY=ON make -C build - make -C build libh2o +} + +check() { + make -C build check } package() { @@ -56,4 +68,12 @@ package() { sha512sums="f2f28905c01782a0432c9dfdb2f21054e0a4741ac4c5f26802d4b439d0172840aa215aba5dc7c9af62275dcc24de105674a3819384dc38246e43ce3e8263eb20 h2o-2.2.6.tar.gz 444f55c3eaae1f349223036086e45c983ea8be89e793068537ec25488c4065174bc509d0987ddc65a0357cb8acfec272e90d13ea7cdadf9cf112953d857aa574 h2o.conf e93e66a6b00b1bff94e37489c5fdf99d9d657adc63975ec54be30f8da23dafe7d7389f02a6452ed819efc9d8398aa716782a7fd6d8509621a975ed954b73bef9 h2o.initd -3d2c9e36c48cbb974d0691e4af8e9eb8f13e3bebb98a30417cdc87e76a4b5cddc4e4f665ebea26b95174287b95d002fdc3363f30ffcf15247fcd0530fe1abfcc h2o.logrotate" +3d2c9e36c48cbb974d0691e4af8e9eb8f13e3bebb98a30417cdc87e76a4b5cddc4e4f665ebea26b95174287b95d002fdc3363f30ffcf15247fcd0530fe1abfcc h2o.logrotate +c03ceeea23a545b948815aeb48872dbac388665f0c79c643e7fa17695580c71260b2227058fe60702d052536e8bdb4d8104d430557ec0c3c4515ed132db7a4a8 missingsubmodules.patch +cd62b93041f2f9407d3aa82c924aa13a3f38330a3557c230c47f30eb3d8bbb90db95cdd2ff1e8248eadcae711c90d0e33caa221ede46015df92c3fe4148a6f21 backslashinterpreationintests.patch +28c5a3a8f64391f317c90f826a488e513b25ad3e7c5febffc0f3a0323b361e4b2900d9dd5e542754b0083c30f68f270eb3b17a8b23ad3f43e4b28feb260ad9eb disabletls13intls12tests.patch +a8b2edff9da782319682ecbf62b93090eedc5503236a7106d0313429b157ec091ddbeb9b8f9f91567ae712a4f2c082b9ba8f84d890b72b54c161c0c4e1cab0ef largeheadertest.patch +a5df628f200475f5db6eb9d1714e955cd33c2de3081ee5f770929833a4cb9e5030fe338c23bcfb516235c2036c6e6452bb52447da0c3d69e3ea8de8bfa00f420 proxysessionresumption.patch +9304ea3ebb74eb66f3d8c8facfc8a08366cb35ac8f5ee8090f59202abd13842d4a4565b5cbfcfff3110473a03bb9ff00b0f74311b450113675f0cb6d6b759d90 sessiontickettest.patch +848b9d20221c2d55b034bd3b9943100fd82f3e32a6032e126868471f9e18f60a9d94bc9024890e4af7ee8ffd6308cc1beb001e3052cb938b14280d331493307b cannotlocatetutilpm.patch +26c4f34bdcb82cdca00b81e8c3223a1c517f912f433e99ae4a9aa16481db2cd23fc77f65773932f8c6e30cb5e34d5d37e0e7a022518a6a13db75d8e16fee2ab4 increasewaitforserverstartintests.patch" diff --git a/community/h2o/backslashinterpreationintests.patch b/community/h2o/backslashinterpreationintests.patch new file mode 100644 index 00000000000..c8cb4663c85 --- /dev/null +++ b/community/h2o/backslashinterpreationintests.patch @@ -0,0 +1,14 @@ +Upstream: Yes +Reason: Without this patch tests fail on shells backslash escapes disabled +Url: https://github.com/h2o/h2o/pull/2331 +--- a/t/50mruby.t ++++ b/t/50mruby.t +@@ -498,7 +498,7 @@ + EOT + my $nc = sub { + my $path = shift; +- my $cmd = "echo 'GET $path HTTP/1.1\\r\\nHost: 127.0.0.1\\r\\n\\r' | nc 127.0.0.1 $server->{port}"; ++ my $cmd = "echo 'GET $path HTTP/1.1\r\nHost: 127.0.0.1\r\n\r' | nc 127.0.0.1 $server->{port}"; + (undef, my $r) = run_prog($cmd); + split(/\r\n\r\n/, $r, 2); + }; diff --git a/community/h2o/cannotlocatetutilpm.patch b/community/h2o/cannotlocatetutilpm.patch new file mode 100644 index 00000000000..2897fcdc081 --- /dev/null +++ b/community/h2o/cannotlocatetutilpm.patch @@ -0,0 +1,39 @@ +Upstream: Yes +Reason: Without this patch make check fails +Url: https://github.com/h2o/h2o/issues/2167 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -386,13 +386,13 @@ + OUTPUT_NAME h2o + VERSION ${LIBRARY_VERSION} + SOVERSION ${LIBRARY_SOVERSION}) +-TARGET_LINK_LIBRARIES(libh2o ${LIBUV_LIBRARIES} ${EXTRA_LIBS}) ++TARGET_LINK_LIBRARIES(libh2o ${WSLAY_LIBRARIES} ${LIBUV_LIBRARIES} ${EXTRA_LIBS}) + SET_TARGET_PROPERTIES(libh2o-evloop PROPERTIES + OUTPUT_NAME h2o-evloop + COMPILE_FLAGS "-DH2O_USE_LIBUV=0" + VERSION ${LIBRARY_VERSION} + SOVERSION ${LIBRARY_SOVERSION}) +-TARGET_LINK_LIBRARIES(libh2o-evloop ${EXTRA_LIBS}) ++TARGET_LINK_LIBRARIES(libh2o-evloop ${WSLAY_LIBRARIES} ${EXTRA_LIBS}) + + IF (OPENSSL_FOUND) + TARGET_INCLUDE_DIRECTORIES(libh2o PUBLIC ${OPENSSL_INCLUDE_DIR}) +@@ -553,7 +553,7 @@ + ENDIF (OPENSSL_FOUND) + ENDIF (WITH_BUNDLED_SSL) + +-ADD_CUSTOM_TARGET(check env H2O_ROOT=. BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR} prove -v t/*.t ++ADD_CUSTOM_TARGET(check env H2O_ROOT=. BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR} prove -I. -v t/*.t + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS h2o t-00unit-evloop.t) + IF (LIBUV_FOUND) +@@ -563,7 +563,7 @@ + ENDIF () + ENDIF () + +-ADD_CUSTOM_TARGET(check-as-root env H2O_ROOT=. BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR} prove -v t/90root-*.t ++ADD_CUSTOM_TARGET(check-as-root env H2O_ROOT=. BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR} prove -I. -v t/90root-*.t + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + + IF (BUILD_FUZZER) diff --git a/community/h2o/disabletls13intls12tests.patch b/community/h2o/disabletls13intls12tests.patch new file mode 100644 index 00000000000..714e9fa4bd9 --- /dev/null +++ b/community/h2o/disabletls13intls12tests.patch @@ -0,0 +1,25 @@ +Upstream: Yes +Reason: Without this patch certain TLS1.2 bahavior tests fail as TLS1.3 is chosen by default +Url: https://github.com/h2o/h2o/commit/442908871b935311c903d2d234708b3de9b40fd5 +--- a/t/40ssl-cipher-suite.t ++++ b/t/40ssl-cipher-suite.t +@@ -32,7 +32,7 @@ + ); + + # connect to the server with AES256-SHA as the first choice, and check that AES128-SHA was selected +-my $log = `openssl s_client -cipher AES256-SHA:AES128-SHA -host 127.0.0.1 -port $port < /dev/null 2>&1`; ++my $log = `openssl s_client -cipher AES256-SHA:AES128-SHA -host 127.0.0.1 -port $port -tls1_2 < /dev/null 2>&1`; + like $log, qr/^\s*Cipher\s*:\s*AES128-SHA\s*$/m; + + done_testing; +--- a/t/50access-log.t ++++ b/t/50access-log.t +@@ -168,7 +168,7 @@ + sub { + my $server = shift; + system("curl --silent http://127.0.0.1:$server->{port}/ > /dev/null"); +- system("curl --silent --insecure @{[curl_supports_http2() ? ' --http1.1' : '']} https://127.0.0.1:$server->{tls_port}/ > /dev/null"); ++ system("curl --silent --insecure @{[curl_supports_http2() ? ' --http1.1' : '']} https://127.0.0.1:$server->{tls_port}/ --tls-max 1.2 > /dev/null"); + if (prog_exists("nghttp")) { + system("nghttp -n https://127.0.0.1:$server->{tls_port}/"); + system("nghttp -n --weight=22 https://127.0.0.1:$server->{tls_port}/"); diff --git a/community/h2o/increasewaitforserverstartintests.patch b/community/h2o/increasewaitforserverstartintests.patch new file mode 100644 index 00000000000..057341c026f --- /dev/null +++ b/community/h2o/increasewaitforserverstartintests.patch @@ -0,0 +1,14 @@ +Upstream: No +Reason: Without this patch some tests fail as the server is not fully started, +issue only present on Alpine running in docker +--- a/t/Util.pm ++++ b/t/Util.pm +@@ -125,7 +125,7 @@ + if (waitpid($pid, WNOHANG) == $pid) { + die "server failed to start (got $?)\n"; + } +- sleep 0.1; ++ sleep 3; + } + } + my $guard = scope_guard(sub { diff --git a/community/h2o/largeheadertest.patch b/community/h2o/largeheadertest.patch new file mode 100644 index 00000000000..3c3770b522a --- /dev/null +++ b/community/h2o/largeheadertest.patch @@ -0,0 +1,19 @@ +Upstream: No +Reason: Without this patch tests using curl for large http headers fail, issue not present with curl on other distro's +Url: https://lists.alpinelinux.org/~alpine/users/%3CCAG5E%3DNdf%3Dc1+Hwt2rY%3DK-kJTtWuMHLnitDoCLrCKkp7n5ksD6w%40mail.gmail.com%3E +--- a/t/50fastcgi.t ++++ b/t/50fastcgi.t +@@ -66,7 +66,12 @@ + my ($proto, $port, $curl) = @_; + plan skip_all => "skip due to curl bug #659" + if $curl =~ /--http2/; +- my $content = `$curl --silent --show-error -H foo:@{["0123456789"x7000]} $proto://127.0.0.1:$port/echo-headers`; ++ my $content; ++ if ($curl =~ /--http1.1/) { ++ $content = `wget --no-check-certificate -O - --header="foo:@{["0123456789"x7000]}" https://127.0.0.1:$port/echo-headers`; ++ } else { ++ $content = `$curl --silent --show-error -H foo:@{["0123456789"x7000]} $proto://127.0.0.1:$port/echo-headers`; ++ } + like $content, qr/^foo: (0123456789){7000,7000}$/mi; + if ($proto eq 'https') { + like $content, qr/^https: on$/m; diff --git a/community/h2o/missingsubmodules.patch b/community/h2o/missingsubmodules.patch new file mode 100644 index 00000000000..85063bbcc97 --- /dev/null +++ b/community/h2o/missingsubmodules.patch @@ -0,0 +1,503 @@ +Upstream: Yes +Reason: Without this patch certain tests are failing as these files are dependencies for tests +Url: https://github.com/h2o/h2o/issues/2329 +--- /dev/null ++++ b/misc/cache-digest/cache-digest.js +@@ -0,0 +1,247 @@ ++/* ++ * Copyright (c) 2015,2016 Jxck, DeNA Co., Ltd., Kazuho Oku ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ * IN THE SOFTWARE. ++ * ++ * ++ * Includes a minified SHA256 implementation taken from https://gist.github.com/kazuho/bb8aab1a2946bbf42127d8a6197ad18c, ++ * licensed under the following copyright: ++ * ++ * Copyright (c) 2015,2016 Chen Yi-Cyuan, Kazuho Oku ++ * ++ * MIT License ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ * IN THE SOFTWARE. ++ */ ++"use strict"; ++ ++if (typeof self !== "undefined" && "ServiceWorkerGlobalScope" in self && ++ self instanceof ServiceWorkerGlobalScope) { ++ ++ /* ServiceWorker */ ++ self.addEventListener('fetch', function(evt) { ++ var req = evt.request.clone(); ++ if (req.method != "GET" || req.url.match(/\/cache-digests?\.js(?:\?|$)/)) { ++ logInfo(req, "skip"); ++ return; ++ } ++ evt.respondWith(caches.open("v1").then(function (cache) { ++ return cache.match(req).then(function (res) { ++ if (res && isFresh(res.headers.entries(), Date.now())) { ++ logInfo(req, "hit"); ++ return res; ++ } ++ var requestWithDigests = function (digests) { ++ if (digests != null) { ++ var err = null; ++ try { ++ req = new Request(req); ++ req.headers.append("cache-digest", digests); ++ if (req.headers.get("cache-digest") == null) ++ err = "append failed"; ++ } catch (e) { ++ err = e; ++ } ++ if (err) ++ logError(req, e); ++ } ++ return fetch(req).then(function (res) { ++ var cached = false; ++ if (res.status == 200 && isFresh(res.headers.entries(), Date.now())) { ++ cache.put(req, res.clone()); ++ cached = true; ++ } ++ logInfo(req, "fetched" + (cached ? " & cached" : "") + " with cache-digest:\"" + digests + "\""); ++ return res; ++ }); ++ }; ++ if (req.mode == "navigate") { ++ return generateCacheDigests(cache).then(requestWithDigests); ++ } else { ++ return requestWithDigests(null); ++ } ++ }); ++ })); ++ }); ++ ++} else if (typeof navigator !== "undefined") { ++ ++ /* bootstrap, loaded via <script src=...> */ ++ navigator.serviceWorker.register("/cache-digest.js", {scope: "./"}).then(function(reg) { ++ console.log("registered cache-digest.js service worker"); ++ }).catch(function(e) { ++ console.log("failed to register cache-digest.js service worker:" + e); ++ }); ++ ++} ++ ++// returns a promise that returns the cache digest value ++function generateCacheDigests(cache) { ++ var urls = []; ++ return cache.keys().then(function (reqs) { ++ // collect 31-bit hashes of fresh responses ++ return Promise.all(reqs.map(function (req) { ++ var now = Date.now(); ++ return cache.match(req).then(function (resp) { ++ if (resp && isFresh(resp.headers.entries(), now)) ++ urls.push(req.url); ++ }); ++ })).then(function () { ++ var dv = calcDigestValue(urls, 7); ++ return dv != null ? base64Encode(dv) + "; complete" : null; ++ }); ++ }); ++} ++ ++function calcDigestValue(urls, pbits) { ++ var nbits = Math.round(Math.log(Math.max(urls.length, 1)) * 1.4426950408889634); // round log2(urls.length) ++ if (nbits + pbits > 31) ++ return null; ++ var hashes = []; ++ for (var i = 0; i != urls.length; ++i) ++ hashes.push(sha256Truncated(urls[i], nbits + pbits)); ++ return (new BitCoder).addBits(nbits, 5).addBits(pbits, 5).gcsEncode(hashes, pbits).value; ++} ++ ++function isFresh(headers, now) { ++ var date = 0, maxAge = null; ++ var o; ++ while (!(o = headers.next()).done) { ++ var name = o.value[0], value = o.value[1]; ++ if (name.match(/^expires$/i) != null) { ++ var parsed = Date.parse(value); ++ if (parsed && parsed > now) ++ return true; ++ } else if (name.match(/^cache-control$/i) != null) { ++ var directives = value.split(/\s*,\s*/); ++ for (var i = 0; i != directives.length; ++i) { ++ var d = directives[i]; ++ if (d.match(/^\s*no-(?:cache|store)\s*$/) != null) { ++ return false; ++ } else if (d.match(/^\s*max-age\s*=\s*([0-9]+)/) != null) { ++ maxAge = Math.min(RegExp.$1, maxAge || Infinity); ++ } ++ } ++ } else if (name.match(/^date$/i) != null) { ++ date = Date.parse(value); ++ } ++ } ++ ++ if (maxAge != null) { ++ if (date + maxAge * 1000 > now) ++ return true; ++ } ++ ++ return false; ++} ++ ++function BitCoder() { ++ this.value = []; ++ this.leftBits = 0; ++} ++ ++BitCoder.prototype.addBit = function (b) { ++ if (this.leftBits == 0) { ++ this.value.push(0); ++ this.leftBits = 8; ++ } ++ --this.leftBits; ++ if (b) ++ this.value[this.value.length - 1] |= 1 << this.leftBits; ++ return this; ++}; ++ ++BitCoder.prototype.addBits = function (v, nbits) { ++ if (nbits != 0) { ++ do { ++ --nbits; ++ this.addBit(v & (1 << nbits)); ++ } while (nbits != 0); ++ } ++ return this; ++}; ++ ++BitCoder.prototype.gcsEncode = function (values, bits_fixed) { ++ values = values.sort(function (a, b) { return a - b; }); ++ var prev = -1; ++ for (var i = 0; i != values.length; ++i) { ++ if (prev == values[i]) ++ continue; ++ var v = values[i] - prev - 1; ++ for (var q = v >> bits_fixed; q != 0; --q) ++ this.addBit(0); ++ this.addBit(1); ++ this.addBits(v, bits_fixed); ++ prev = values[i]; ++ } ++ return this; ++}; ++ ++var base64Encode = function (buf) { ++ var TOKENS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; ++ return function base64Encode(buf) { ++ var str = ''; ++ for (var pos = 0; pos < buf.length; pos += 3) { ++ var quad = buf[pos] << 16 | buf[pos + 1] << 8 | buf[pos + 2]; ++ str += TOKENS[(quad >> 18)] + TOKENS[(quad >> 12) & 63] + TOKENS[(quad >> 6) & 63] + TOKENS[quad & 63]; ++ } ++ str = str.substring(0, str.length - pos + buf.length); ++ return str; ++ }; ++}(); ++ ++function sha256Truncated(src, bits) { ++ // only supports bits <= 31 ++ return ((sha256(src)[0] >> 1) & 0x7fffffff) >> (31 - bits); ++} ++ ++var sha256=function(){var r=[-2147483648,8388608,32768,128],o=[24,16,8,0],a=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298];return function(n){var t,e,f,h,c,u,v,d,i,l,A,C,g,s=[],w=!0,b=!1,j=0,k=0,m=0,p=n.length,q=1779033703,x=3144134277,y=1013904242,z=2773480762,B=1359893119,D=2600822924,E=528734635,F=1541459225,G=0;do{for(s[0]=G,s[16]=s[1]=s[2]=s[3]=s[4]=s[5]=s[6]=s[7]=s[8]=s[9]=s[10]=s[11]=s[12]=s[13]=s[14]=s[15]=0,e=k;p>j&&64>e;++j)t=n.charCodeAt(j),128>t?s[e>>2]|=t<<o[3&e++]:2048>t?(s[e>>2]|=(192|t>>6)<<o[3&e++],s[e>>2]|=(128|63&t)<<o[3&e++]):55296>t||t>=57344?(s[e>>2]|=(224|t>>12)<<o[3&e++],s[e>>2]|=(128|t>>6&63)<<o[3&e++],s[e>>2]|=(128|63&t)<<o[3&e++]):(t=65536+((1023&t)<<10|1023&n.charCodeAt(++j)),s[e>>2]|=(240|t>>18)<<o[3&e++],s[e>>2]|=(128|t>>12&63)<<o[3&e++],s[e>>2]|=(128|t>>6&63)<<o[3&e++],s[e>>2]|=(128|63&t)<<o[3&e++]);m+=e-k,k=e-64,j==p&&(s[e>>2]|=r[3&e],++j),G=s[16],j>p&&56>e&&(s[15]=m<<3,b=!0);var H=q,I=x,J=y,K=z,L=B,M=D,N=E,O=F;for(f=16;64>f;++f)v=s[f-15],h=(v>>>7|v<<25)^(v>>>18|v<<14)^v>>>3,v=s[f-2],c=(v>>>17|v<<15)^(v>>>19|v<<13)^v>>>10,s[f]=s[f-16]+h+s[f-7]+c<<0;for(g=I&J,f=0;64>f;f+=4)w?(l=704751109,v=s[0]-210244248,O=v-1521486534<<0,K=v+143694565<<0,w=!1):(h=(H>>>2|H<<30)^(H>>>13|H<<19)^(H>>>22|H<<10),c=(L>>>6|L<<26)^(L>>>11|L<<21)^(L>>>25|L<<7),l=H&I,u=l^H&J^g,i=L&M^~L&N,v=O+c+i+a[f]+s[f],d=h+u,O=K+v<<0,K=v+d<<0),h=(K>>>2|K<<30)^(K>>>13|K<<19)^(K>>>22|K<<10),c=(O>>>6|O<<26)^(O>>>11|O<<21)^(O>>>25|O<<7),A=K&H,u=A^K&I^l,i=O&L^~O&M,v=N+c+i+a[f+1]+s[f+1],d=h+u,N=J+v<<0,J=v+d<<0,h=(J>>>2|J<<30)^(J>>>13|J<<19)^(J>>>22|J<<10),c=(N>>>6|N<<26)^(N>>>11|N<<21)^(N>>>25|N<<7),C=J&K,u=C^J&H^A,i=N&O^~N&L,v=M+c+i+a[f+2]+s[f+2],d=h+u,M=I+v<<0,I=v+d<<0,h=(I>>>2|I<<30)^(I>>>13|I<<19)^(I>>>22|I<<10),c=(M>>>6|M<<26)^(M>>>11|M<<21)^(M>>>25|M<<7),g=I&J,u=g^I&K^C,i=M&N^~M&O,v=L+c+i+a[f+3]+s[f+3],d=h+u,L=H+v<<0,H=v+d<<0;q=q+H<<0,x=x+I<<0,y=y+J<<0,z=z+K<<0,B=B+L<<0,D=D+M<<0,E=E+N<<0,F=F+O<<0}while(!b);return[q,x,y,z,B,D,E,F]}}(); ++ ++function logRequest(req) { ++ var s = req.method + " " + req.url + "\n"; ++ var o; ++ for (var iter = req.headers.entries(); !(o = iter.next()).done;) ++ s += o.value[0] + ": " + o.value[1] + "\n"; ++ console.log(s); ++} ++function logError(req, msg) { ++ console.log(req.url + ":error:" + msg); ++} ++function logInfo(req, msg) { ++ console.log(req.url + ":info:" + msg); ++} ++function logDebug(req, msg) { ++ console.log(req.url + ":debug:" + msg); ++} +--- /dev/null ++++ b/misc/cache-digest/cli.js +@@ -0,0 +1,247 @@ ++/* ++ * Copyright (c) 2015,2016 Jxck, DeNA Co., Ltd., Kazuho Oku ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ * IN THE SOFTWARE. ++ * ++ * ++ * Includes a minified SHA256 implementation taken from https://gist.github.com/kazuho/bb8aab1a2946bbf42127d8a6197ad18c, ++ * licensed under the following copyright: ++ * ++ * Copyright (c) 2015,2016 Chen Yi-Cyuan, Kazuho Oku ++ * ++ * MIT License ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ * IN THE SOFTWARE. ++ */ ++"use strict"; ++ ++if (typeof self !== "undefined" && "ServiceWorkerGlobalScope" in self && ++ self instanceof ServiceWorkerGlobalScope) { ++ ++ /* ServiceWorker */ ++ self.addEventListener('fetch', function(evt) { ++ var req = evt.request.clone(); ++ if (req.method != "GET" || req.url.match(/\/cache-digests?\.js(?:\?|$)/)) { ++ logInfo(req, "skip"); ++ return; ++ } ++ evt.respondWith(caches.open("v1").then(function (cache) { ++ return cache.match(req).then(function (res) { ++ if (res && isFresh(res.headers.entries(), Date.now())) { ++ logInfo(req, "hit"); ++ return res; ++ } ++ var requestWithDigests = function (digests) { ++ if (digests != null) { ++ var err = null; ++ try { ++ req = new Request(req); ++ req.headers.append("cache-digest", digests); ++ if (req.headers.get("cache-digest") == null) ++ err = "append failed"; ++ } catch (e) { ++ err = e; ++ } ++ if (err) ++ logError(req, e); ++ } ++ return fetch(req).then(function (res) { ++ var cached = false; ++ if (res.status == 200 && isFresh(res.headers.entries(), Date.now())) { ++ cache.put(req, res.clone()); ++ cached = true; ++ } ++ logInfo(req, "fetched" + (cached ? " & cached" : "") + " with cache-digest:\"" + digests + "\""); ++ return res; ++ }); ++ }; ++ if (req.mode == "navigate") { ++ return generateCacheDigests(cache).then(requestWithDigests); ++ } else { ++ return requestWithDigests(null); ++ } ++ }); ++ })); ++ }); ++ ++} else if (typeof navigator !== "undefined") { ++ ++ /* bootstrap, loaded via <script src=...> */ ++ navigator.serviceWorker.register("/cache-digest.js", {scope: "./"}).then(function(reg) { ++ console.log("registered cache-digest.js service worker"); ++ }).catch(function(e) { ++ console.log("failed to register cache-digest.js service worker:" + e); ++ }); ++ ++} ++ ++// returns a promise that returns the cache digest value ++function generateCacheDigests(cache) { ++ var urls = []; ++ return cache.keys().then(function (reqs) { ++ // collect 31-bit hashes of fresh responses ++ return Promise.all(reqs.map(function (req) { ++ var now = Date.now(); ++ return cache.match(req).then(function (resp) { ++ if (resp && isFresh(resp.headers.entries(), now)) ++ urls.push(req.url); ++ }); ++ })).then(function () { ++ var dv = calcDigestValue(urls, 7); ++ return dv != null ? base64Encode(dv) + "; complete" : null; ++ }); ++ }); ++} ++ ++function calcDigestValue(urls, pbits) { ++ var nbits = Math.round(Math.log(Math.max(urls.length, 1)) * 1.4426950408889634); // round log2(urls.length) ++ if (nbits + pbits > 31) ++ return null; ++ var hashes = []; ++ for (var i = 0; i != urls.length; ++i) ++ hashes.push(sha256Truncated(urls[i], nbits + pbits)); ++ return (new BitCoder).addBits(nbits, 5).addBits(pbits, 5).gcsEncode(hashes, pbits).value; ++} ++ ++function isFresh(headers, now) { ++ var date = 0, maxAge = null; ++ var o; ++ while (!(o = headers.next()).done) { ++ var name = o.value[0], value = o.value[1]; ++ if (name.match(/^expires$/i) != null) { ++ var parsed = Date.parse(value); ++ if (parsed && parsed > now) ++ return true; ++ } else if (name.match(/^cache-control$/i) != null) { ++ var directives = value.split(/\s*,\s*/); ++ for (var i = 0; i != directives.length; ++i) { ++ var d = directives[i]; ++ if (d.match(/^\s*no-(?:cache|store)\s*$/) != null) { ++ return false; ++ } else if (d.match(/^\s*max-age\s*=\s*([0-9]+)/) != null) { ++ maxAge = Math.min(RegExp.$1, maxAge || Infinity); ++ } ++ } ++ } else if (name.match(/^date$/i) != null) { ++ date = Date.parse(value); ++ } ++ } ++ ++ if (maxAge != null) { ++ if (date + maxAge * 1000 > now) ++ return true; ++ } ++ ++ return false; ++} ++ ++function BitCoder() { ++ this.value = []; ++ this.leftBits = 0; ++} ++ ++BitCoder.prototype.addBit = function (b) { ++ if (this.leftBits == 0) { ++ this.value.push(0); ++ this.leftBits = 8; ++ } ++ --this.leftBits; ++ if (b) ++ this.value[this.value.length - 1] |= 1 << this.leftBits; ++ return this; ++}; ++ ++BitCoder.prototype.addBits = function (v, nbits) { ++ if (nbits != 0) { ++ do { ++ --nbits; ++ this.addBit(v & (1 << nbits)); ++ } while (nbits != 0); ++ } ++ return this; ++}; ++ ++BitCoder.prototype.gcsEncode = function (values, bits_fixed) { ++ values = values.sort(function (a, b) { return a - b; }); ++ var prev = -1; ++ for (var i = 0; i != values.length; ++i) { ++ if (prev == values[i]) ++ continue; ++ var v = values[i] - prev - 1; ++ for (var q = v >> bits_fixed; q != 0; --q) ++ this.addBit(0); ++ this.addBit(1); ++ this.addBits(v, bits_fixed); ++ prev = values[i]; ++ } ++ return this; ++}; ++ ++var base64Encode = function (buf) { ++ var TOKENS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; ++ return function base64Encode(buf) { ++ var str = ''; ++ for (var pos = 0; pos < buf.length; pos += 3) { ++ var quad = buf[pos] << 16 | buf[pos + 1] << 8 | buf[pos + 2]; ++ str += TOKENS[(quad >> 18)] + TOKENS[(quad >> 12) & 63] + TOKENS[(quad >> 6) & 63] + TOKENS[quad & 63]; ++ } ++ str = str.substring(0, str.length - pos + buf.length); ++ return str; ++ }; ++}(); ++ ++function sha256Truncated(src, bits) { ++ // only supports bits <= 31 ++ return ((sha256(src)[0] >> 1) & 0x7fffffff) >> (31 - bits); ++} ++ ++var sha256=function(){var r=[-2147483648,8388608,32768,128],o=[24,16,8,0],a=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298];return function(n){var t,e,f,h,c,u,v,d,i,l,A,C,g,s=[],w=!0,b=!1,j=0,k=0,m=0,p=n.length,q=1779033703,x=3144134277,y=1013904242,z=2773480762,B=1359893119,D=2600822924,E=528734635,F=1541459225,G=0;do{for(s[0]=G,s[16]=s[1]=s[2]=s[3]=s[4]=s[5]=s[6]=s[7]=s[8]=s[9]=s[10]=s[11]=s[12]=s[13]=s[14]=s[15]=0,e=k;p>j&&64>e;++j)t=n.charCodeAt(j),128>t?s[e>>2]|=t<<o[3&e++]:2048>t?(s[e>>2]|=(192|t>>6)<<o[3&e++],s[e>>2]|=(128|63&t)<<o[3&e++]):55296>t||t>=57344?(s[e>>2]|=(224|t>>12)<<o[3&e++],s[e>>2]|=(128|t>>6&63)<<o[3&e++],s[e>>2]|=(128|63&t)<<o[3&e++]):(t=65536+((1023&t)<<10|1023&n.charCodeAt(++j)),s[e>>2]|=(240|t>>18)<<o[3&e++],s[e>>2]|=(128|t>>12&63)<<o[3&e++],s[e>>2]|=(128|t>>6&63)<<o[3&e++],s[e>>2]|=(128|63&t)<<o[3&e++]);m+=e-k,k=e-64,j==p&&(s[e>>2]|=r[3&e],++j),G=s[16],j>p&&56>e&&(s[15]=m<<3,b=!0);var H=q,I=x,J=y,K=z,L=B,M=D,N=E,O=F;for(f=16;64>f;++f)v=s[f-15],h=(v>>>7|v<<25)^(v>>>18|v<<14)^v>>>3,v=s[f-2],c=(v>>>17|v<<15)^(v>>>19|v<<13)^v>>>10,s[f]=s[f-16]+h+s[f-7]+c<<0;for(g=I&J,f=0;64>f;f+=4)w?(l=704751109,v=s[0]-210244248,O=v-1521486534<<0,K=v+143694565<<0,w=!1):(h=(H>>>2|H<<30)^(H>>>13|H<<19)^(H>>>22|H<<10),c=(L>>>6|L<<26)^(L>>>11|L<<21)^(L>>>25|L<<7),l=H&I,u=l^H&J^g,i=L&M^~L&N,v=O+c+i+a[f]+s[f],d=h+u,O=K+v<<0,K=v+d<<0),h=(K>>>2|K<<30)^(K>>>13|K<<19)^(K>>>22|K<<10),c=(O>>>6|O<<26)^(O>>>11|O<<21)^(O>>>25|O<<7),A=K&H,u=A^K&I^l,i=O&L^~O&M,v=N+c+i+a[f+1]+s[f+1],d=h+u,N=J+v<<0,J=v+d<<0,h=(J>>>2|J<<30)^(J>>>13|J<<19)^(J>>>22|J<<10),c=(N>>>6|N<<26)^(N>>>11|N<<21)^(N>>>25|N<<7),C=J&K,u=C^J&H^A,i=N&O^~N&L,v=M+c+i+a[f+2]+s[f+2],d=h+u,M=I+v<<0,I=v+d<<0,h=(I>>>2|I<<30)^(I>>>13|I<<19)^(I>>>22|I<<10),c=(M>>>6|M<<26)^(M>>>11|M<<21)^(M>>>25|M<<7),g=I&J,u=g^I&K^C,i=M&N^~M&O,v=L+c+i+a[f+3]+s[f+3],d=h+u,L=H+v<<0,H=v+d<<0;q=q+H<<0,x=x+I<<0,y=y+J<<0,z=z+K<<0,B=B+L<<0,D=D+M<<0,E=E+N<<0,F=F+O<<0}while(!b);return[q,x,y,z,B,D,E,F]}}(); ++ ++function logRequest(req) { ++ var s = req.method + " " + req.url + "\n"; ++ var o; ++ for (var iter = req.headers.entries(); !(o = iter.next()).done;) ++ s += o.value[0] + ": " + o.value[1] + "\n"; ++ console.log(s); ++} ++function logError(req, msg) { ++ console.log(req.url + ":error:" + msg); ++} ++function logInfo(req, msg) { ++ console.log(req.url + ":info:" + msg); ++} ++function logDebug(req, msg) { ++ console.log(req.url + ":debug:" + msg); ++} diff --git a/community/h2o/proxysessionresumption.patch b/community/h2o/proxysessionresumption.patch new file mode 100644 index 00000000000..c7d45336a73 --- /dev/null +++ b/community/h2o/proxysessionresumption.patch @@ -0,0 +1,134 @@ +Upstream: Yes +Reason: Without this patch proxy ssl session resumptions fails +Url: https://github.com/h2o/h2o/pull/2088 +--- a/include/h2o/socket.h ++++ b/include/h2o/socket.h +@@ -71,6 +71,9 @@ + + #define H2O_SOCKET_INITIAL_INPUT_BUFFER_SIZE 4096 + ++#define H2O_SESSID_CTX ((const uint8_t*)"h2o") ++#define H2O_SESSID_CTX_LEN (sizeof("h2o") - 1) ++ + typedef struct st_h2o_socket_t h2o_socket_t; + + typedef void (*h2o_socket_cb)(h2o_socket_t *sock, const char *err); +@@ -266,6 +269,7 @@ + static h2o_iovec_t h2o_socket_log_ssl_cipher(h2o_socket_t *sock, h2o_mem_pool_t *pool); + h2o_iovec_t h2o_socket_log_ssl_cipher_bits(h2o_socket_t *sock, h2o_mem_pool_t *pool); + h2o_iovec_t h2o_socket_log_ssl_session_id(h2o_socket_t *sock, h2o_mem_pool_t *pool); ++int h2o_socket_ssl_new_session_cb(SSL *s, SSL_SESSION *sess); + + /** + * compares socket addresses +--- a/lib/common/socket.c ++++ b/lib/common/socket.c +@@ -916,6 +916,8 @@ + static void create_ossl(h2o_socket_t *sock) + { + sock->ssl->ossl = SSL_new(sock->ssl->ssl_ctx); ++ /* set app data to be used in h2o_socket_ssl_new_session_cb */ ++ SSL_set_app_data(sock->ssl->ossl, sock); + setup_bio(sock); + } + +@@ -942,6 +944,26 @@ + } + } + ++int h2o_socket_ssl_new_session_cb(SSL *s, SSL_SESSION *sess) ++{ ++ h2o_socket_t *sock = (h2o_socket_t *)SSL_get_app_data(s); ++ assert(sock != NULL); ++ assert(sock->ssl != NULL); ++ ++ if (!SSL_is_server(s) && sock->ssl->handshake.client.session_cache != NULL ++#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x1010100fL ++ && SSL_SESSION_is_resumable(sess) ++#endif ++ ) { ++ h2o_cache_set(sock->ssl->handshake.client.session_cache, h2o_now(h2o_socket_get_loop(sock)), ++ sock->ssl->handshake.client.session_cache_key, sock->ssl->handshake.client.session_cache_key_hash, ++ h2o_iovec_init(sess, 1)); ++ return 1; /* retain ref count */ ++ } ++ ++ return 0; /* drop ref count */ ++} ++ + static int on_async_resumption_new(SSL *ssl, SSL_SESSION *session) + { + h2o_iovec_t data; +@@ -992,16 +1014,6 @@ + sock->ssl->record_overhead = 32; /* sufficiently large number that can hold most payloads */ + break; + } +- } +- } +- +- /* set ssl session into the cache */ +- if (sock->ssl->ossl != NULL && !SSL_is_server(sock->ssl->ossl) && sock->ssl->handshake.client.session_cache != NULL) { +- if (err == NULL || err == h2o_socket_error_ssl_cert_name_mismatch) { +- SSL_SESSION *session = SSL_get1_session(sock->ssl->ossl); +- h2o_cache_set(sock->ssl->handshake.client.session_cache, h2o_now(h2o_socket_get_loop(sock)), +- sock->ssl->handshake.client.session_cache_key, sock->ssl->handshake.client.session_cache_key_hash, +- h2o_iovec_init(session, 1)); + } + } + +--- a/lib/handler/configurator/proxy.c ++++ b/lib/handler/configurator/proxy.c +@@ -27,6 +27,7 @@ + #include <openssl/ssl.h> + #include "h2o.h" + #include "h2o/configurator.h" ++#include "h2o/socket.h" + + struct proxy_configurator_t { + h2o_configurator_t super; +@@ -86,6 +87,9 @@ + { + SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method()); + SSL_CTX_set_options(ctx, SSL_CTX_get_options(ctx) | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); ++ SSL_CTX_set_session_id_context(ctx, H2O_SESSID_CTX, H2O_SESSID_CTX_LEN); ++ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL_STORE); ++ SSL_CTX_sess_set_new_cb(ctx, h2o_socket_ssl_new_session_cb); + return ctx; + } + +@@ -119,6 +123,7 @@ + + /* create new ctx */ + *ctx = create_ssl_ctx(); ++ SSL_CTX_set_session_id_context(*ctx, H2O_SESSID_CTX, H2O_SESSID_CTX_LEN); + SSL_CTX_set_cert_store(*ctx, cert_store); + SSL_CTX_set_verify(*ctx, verify_mode, NULL); + if (new_session_cache != NULL) +--- a/src/main.c ++++ b/src/main.c +@@ -674,9 +674,15 @@ + ssl_options |= SSL_OP_NO_COMPRESSION; + #endif + ++#ifdef SSL_OP_NO_RENEGOTIATION ++ ssl_options |= SSL_OP_NO_RENEGOTIATION; ++#endif ++ + /* setup */ + ssl_ctx = SSL_CTX_new(SSLv23_server_method()); + SSL_CTX_set_options(ssl_ctx, ssl_options); ++ ++ SSL_CTX_set_session_id_context(ssl_ctx, H2O_SESSID_CTX, H2O_SESSID_CTX_LEN); + + setup_ecc_key(ssl_ctx); + if (SSL_CTX_use_certificate_chain_file(ssl_ctx, certificate_file->data.scalar) != 1) { +--- a/src/ssl.c ++++ b/src/ssl.c +@@ -116,6 +116,7 @@ + size_t i; + for (i = 0; i != num_contexts; ++i) { + SSL_CTX_set_session_cache_mode(contexts[i], SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_AUTO_CLEAR); ++ SSL_CTX_set_session_id_context(contexts[i], H2O_SESSID_CTX, H2O_SESSID_CTX_LEN); + SSL_CTX_set_timeout(contexts[i], conf.lifetime); + } + spawn_cache_cleanup_thread(contexts, num_contexts); diff --git a/community/h2o/sessiontickettest.patch b/community/h2o/sessiontickettest.patch new file mode 100644 index 00000000000..86ea5ba4cae --- /dev/null +++ b/community/h2o/sessiontickettest.patch @@ -0,0 +1,140 @@ +Upstream: Yes +Reason: Without this patch the session ticket test fails +Url: https://github.com/h2o/h2o/pull/2334 +--- a/t/40session-ticket.t ++++ b/t/40session-ticket.t +@@ -3,6 +3,7 @@ + use File::Temp qw(tempdir); + use Net::EmptyPort qw(check_port empty_port); + use Test::More; ++use Time::HiRes qw(sleep); + use t::Util; + + plan skip_all => "could not find openssl" +@@ -17,16 +18,16 @@ + mode: ticket + EOT + sub { +- is test(), "New"; +- test(); # openssl 0.9.8 seems to return "New" (maybe because in the first run we did not specify -sess_in) +- is test(), "Reused"; +- is test(), "Reused"; ++ sleep 5; ++ is test("new"), "New"; ++ is test("reuse"), "Reused"; ++ is test("reuse"), "Reused"; + }); + spawn_with(<< "EOT", + mode: ticket + EOT + sub { +- is test(), "New"; ++ is test("reuse"), "New"; + }); + }; + +@@ -36,11 +37,13 @@ + mode: ticket + ticket-store: file + ticket-file: $tickets_file ++num-threads: 1 + EOT + sub { +- is test(), "New"; +- is test(), "Reused"; +- is test(), "Reused"; ++ sleep 5; # wait for tickets file to be loaded ++ is test("new"), "New"; ++ is test("reuse"), "Reused"; ++ is test("reuse"), "Reused"; + }); + spawn_with(<< "EOT", + mode: ticket +@@ -48,8 +51,8 @@ + ticket-file: $tickets_file + EOT + sub { +- sleep 1; +- is test(), "Reused"; ++ sleep 5; # wait for tickets file to be loaded ++ is test("reuse"), "Reused"; + }); + }; + +@@ -59,11 +62,13 @@ + mode: ticket + ticket-store: file + ticket-file: $tickets_file ++num-threads: 1 + EOT + sub { +- is test(), "New"; +- is test(), "New"; +- is test(), "New"; ++ sleep 5; # wait for tickets file to be loaded ++ is test("new"), "New"; ++ is test("reuse"), "New"; ++ is test("reuse"), "New"; + }); + }; + +@@ -86,15 +91,17 @@ + host: 127.0.0.1 + port: $memc_port + protocol: $memc_proto ++num-threads: 1 + EOT + spawn_with($conf, sub { +- is test(), "New"; +- is test(), "Reused"; +- is test(), "Reused"; ++ sleep 5; ++ is test("new"), "New"; ++ is test("reuse"), "Reused"; ++ is test("reuse"), "Reused"; + }); + spawn_with($conf, sub { +- sleep 1; +- is test(), "Reused"; ++ sleep 5; ++ is test("reuse"), "Reused"; + }); + }; + $doit->("binary"); +@@ -120,14 +127,33 @@ + } + + sub test { ++ my $sess_mode = shift @_; # reuse or new ++ ++ # 'openssl -sess_out' writes a session file ONLY if ++ # a session was handed out by the server! ++ ++ my $cmd_opts; ++ if ( $sess_mode eq 'new' ) { ++ unlink "$tempdir/session"; ++ $cmd_opts = "-sess_out $tempdir/session"; ++ } else { ++ return "no session to reuse $tempdir/session does no exist" unless ( -e "$tempdir/session" ); ++ $cmd_opts = "-sess_in $tempdir/session"; ++ } ++ + my $lines = do { +- my $cmd_opts = (-e "$tempdir/session" ? "-sess_in $tempdir/session" : "") . " -sess_out $tempdir/session"; +- open my $fh, "-|", "openssl s_client $cmd_opts -connect 127.0.0.1:$server->{tls_port} 2>&1 < /dev/null" ++ open my $fh, "-|", "openssl s_client $cmd_opts -prexit -servername 127.0.0.1 -connect 127.0.0.1:$server->{tls_port} -tls1_2 2>&1" + or die "failed to open pipe:$!"; + local $/; + <$fh>; + }; ++ print $lines; + $lines =~ m{---\n(New|Reused),}s + or die "failed to parse the output of s_client:{{{$lines}}}"; +- $1; ++ ++ if ( $sess_mode eq 'new' ) { ++ -e "$tempdir/session" ? $1 : "no session created $tempdir/session does no exist"; ++ } else { ++ $1; ++ } + } diff --git a/testing/perl-http-entity-parser/APKBUILD b/community/perl-http-entity-parser/APKBUILD index f5541a00ab5..f5541a00ab5 100644 --- a/testing/perl-http-entity-parser/APKBUILD +++ b/community/perl-http-entity-parser/APKBUILD diff --git a/testing/perl-http-multipartparser/APKBUILD b/community/perl-http-multipartparser/APKBUILD index 262cd14b43d..262cd14b43d 100644 --- a/testing/perl-http-multipartparser/APKBUILD +++ b/community/perl-http-multipartparser/APKBUILD diff --git a/testing/perl-protocol-http2/APKBUILD b/community/perl-protocol-http2/APKBUILD index 11bd53dd6c9..11bd53dd6c9 100644 --- a/testing/perl-protocol-http2/APKBUILD +++ b/community/perl-protocol-http2/APKBUILD diff --git a/testing/perl-www-form-urlencoded/APKBUILD b/community/perl-www-form-urlencoded/APKBUILD index 57ab9bb2d3d..57ab9bb2d3d 100644 --- a/testing/perl-www-form-urlencoded/APKBUILD +++ b/community/perl-www-form-urlencoded/APKBUILD |