Update to 5.6.5 and fix CVE-2022-24790,CVE-2023-40175
This commit is contained in:
parent
a2fe847ed9
commit
deac1d9cf4
@ -1,44 +0,0 @@
|
|||||||
From b70f451fe8abc0cff192c065d549778452e155bb Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jean Boussier <jean.boussier@gmail.com>
|
|
||||||
Date: Fri, 11 Feb 2022 15:58:08 +0100
|
|
||||||
Subject: [PATCH] Ensure `close` is called on the response body no matter what
|
|
||||||
|
|
||||||
Another fallout from https://github.com/puma/puma/pull/2809 is that
|
|
||||||
in some cases the `res_body.close` wasn't called because some previous code
|
|
||||||
raised.
|
|
||||||
|
|
||||||
For Rails apps it means CurrentAttributes and a few other important
|
|
||||||
states aren't reset properly.
|
|
||||||
|
|
||||||
This is being improved on the Rails side too, but I believe it would
|
|
||||||
be good to harden this on the puma side as well.
|
|
||||||
---
|
|
||||||
lib/puma/request.rb | 15 ++++++++++-----
|
|
||||||
1 file changed, 10 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/lib/puma/request.rb b/lib/puma/request.rb
|
|
||||||
index 10508c8d44..691ada424f 100644
|
|
||||||
--- a/lib/puma/request.rb
|
|
||||||
+++ b/lib/puma/request.rb
|
|
||||||
@@ -171,11 +171,16 @@ def handle_request(client, lines, requests)
|
|
||||||
end
|
|
||||||
|
|
||||||
ensure
|
|
||||||
- uncork_socket io
|
|
||||||
-
|
|
||||||
- body.close
|
|
||||||
- client.tempfile.unlink if client.tempfile
|
|
||||||
- res_body.close if res_body.respond_to? :close
|
|
||||||
+ begin
|
|
||||||
+ uncork_socket io
|
|
||||||
+
|
|
||||||
+ body.close
|
|
||||||
+ client.tempfile.unlink if client.tempfile
|
|
||||||
+ ensure
|
|
||||||
+ # Whatever happens, we MUST call `close` on the response body.
|
|
||||||
+ # Otherwise Rack::BodyProxy callbacks may not fire and lead to various state leaks
|
|
||||||
+ res_body.close if res_body.respond_to? :close
|
|
||||||
+ end
|
|
||||||
|
|
||||||
after_reply.each { |o| o.call }
|
|
||||||
end
|
|
||||||
146
CVE-2023-40175.patch
Normal file
146
CVE-2023-40175.patch
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
From 7405a219801dcebc0ad6e0aa108d4319ca23f662 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nate Berkopec <nate.berkopec@gmail.com>
|
||||||
|
Date: Fri, 18 Aug 2023 09:47:23 +0900
|
||||||
|
Subject: [PATCH] Merge pull request from GHSA-68xg-gqqm-vgj8
|
||||||
|
|
||||||
|
Origin: https://github.com/puma/puma/commit/7405a219801dcebc0ad6e0aa108d4319ca23f662
|
||||||
|
|
||||||
|
* Reject empty string for Content-Length
|
||||||
|
|
||||||
|
* Ignore trailers in last chunk
|
||||||
|
|
||||||
|
* test_puma_server.rb - use heredoc, test_cl_and_te_smuggle
|
||||||
|
|
||||||
|
* client.rb - stye/RubyCop
|
||||||
|
|
||||||
|
* test_puma_server.rb - indented heredoc rubocop disable
|
||||||
|
|
||||||
|
* Dentarg comments
|
||||||
|
|
||||||
|
* Remove unused variable
|
||||||
|
|
||||||
|
---------
|
||||||
|
|
||||||
|
Co-authored-by: MSP-Greg <Greg.mpls@gmail.com>
|
||||||
|
---
|
||||||
|
lib/puma/client.rb | 23 ++++++++++++++--------
|
||||||
|
test/test_puma_server.rb | 42 +++++++++++++++++++++++++++++++++++++++-
|
||||||
|
2 files changed, 56 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/puma/client.rb b/lib/puma/client.rb
|
||||||
|
index e966f995e8..9c11912caa 100644
|
||||||
|
--- a/lib/puma/client.rb
|
||||||
|
+++ b/lib/puma/client.rb
|
||||||
|
@@ -45,7 +45,8 @@ class Client
|
||||||
|
|
||||||
|
# chunked body validation
|
||||||
|
CHUNK_SIZE_INVALID = /[^\h]/.freeze
|
||||||
|
- CHUNK_VALID_ENDING = "\r\n".freeze
|
||||||
|
+ CHUNK_VALID_ENDING = Const::LINE_END
|
||||||
|
+ CHUNK_VALID_ENDING_SIZE = CHUNK_VALID_ENDING.bytesize
|
||||||
|
|
||||||
|
# Content-Length header value validation
|
||||||
|
CONTENT_LENGTH_VALUE_INVALID = /[^\d]/.freeze
|
||||||
|
@@ -347,8 +348,8 @@ def setup_body
|
||||||
|
cl = @env[CONTENT_LENGTH]
|
||||||
|
|
||||||
|
if cl
|
||||||
|
- # cannot contain characters that are not \d
|
||||||
|
- if cl =~ CONTENT_LENGTH_VALUE_INVALID
|
||||||
|
+ # cannot contain characters that are not \d, or be empty
|
||||||
|
+ if cl =~ CONTENT_LENGTH_VALUE_INVALID || cl.empty?
|
||||||
|
raise HttpParserError, "Invalid Content-Length: #{cl.inspect}"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
@@ -509,7 +510,7 @@ def decode_chunk(chunk)
|
||||||
|
|
||||||
|
while !io.eof?
|
||||||
|
line = io.gets
|
||||||
|
- if line.end_with?("\r\n")
|
||||||
|
+ if line.end_with?(CHUNK_VALID_ENDING)
|
||||||
|
# Puma doesn't process chunk extensions, but should parse if they're
|
||||||
|
# present, which is the reason for the semicolon regex
|
||||||
|
chunk_hex = line.strip[/\A[^;]+/]
|
||||||
|
@@ -521,13 +522,19 @@ def decode_chunk(chunk)
|
||||||
|
@in_last_chunk = true
|
||||||
|
@body.rewind
|
||||||
|
rest = io.read
|
||||||
|
- last_crlf_size = "\r\n".bytesize
|
||||||
|
- if rest.bytesize < last_crlf_size
|
||||||
|
+ if rest.bytesize < CHUNK_VALID_ENDING_SIZE
|
||||||
|
@buffer = nil
|
||||||
|
- @partial_part_left = last_crlf_size - rest.bytesize
|
||||||
|
+ @partial_part_left = CHUNK_VALID_ENDING_SIZE - rest.bytesize
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
- @buffer = rest[last_crlf_size..-1]
|
||||||
|
+ # if the next character is a CRLF, set buffer to everything after that CRLF
|
||||||
|
+ start_of_rest = if rest.start_with?(CHUNK_VALID_ENDING)
|
||||||
|
+ CHUNK_VALID_ENDING_SIZE
|
||||||
|
+ else # we have started a trailer section, which we do not support. skip it!
|
||||||
|
+ rest.index(CHUNK_VALID_ENDING*2) + CHUNK_VALID_ENDING_SIZE*2
|
||||||
|
+ end
|
||||||
|
+
|
||||||
|
+ @buffer = rest[start_of_rest..-1]
|
||||||
|
@buffer = nil if @buffer.empty?
|
||||||
|
set_ready
|
||||||
|
return true
|
||||||
|
diff --git a/test/test_puma_server.rb b/test/test_puma_server.rb
|
||||||
|
index 298e44b439..2bfaf98848 100644
|
||||||
|
--- a/test/test_puma_server.rb
|
||||||
|
+++ b/test/test_puma_server.rb
|
||||||
|
@@ -627,7 +627,7 @@ def test_large_chunked_request
|
||||||
|
[200, {}, [""]]
|
||||||
|
}
|
||||||
|
|
||||||
|
- header = "GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: chunked\r\n\r\n"
|
||||||
|
+ header = "GET / HTTP/1.1\r\nConnection: close\r\nContent-Length: 200\r\nTransfer-Encoding: chunked\r\n\r\n"
|
||||||
|
|
||||||
|
chunk_header_size = 6 # 4fb8\r\n
|
||||||
|
# Current implementation reads one chunk of CHUNK_SIZE, then more chunks of size 4096.
|
||||||
|
@@ -1365,4 +1365,44 @@ def test_rack_url_scheme_user
|
||||||
|
data = send_http_and_read "GET / HTTP/1.0\r\n\r\n"
|
||||||
|
assert_equal "user", data.split("\r\n").last
|
||||||
|
end
|
||||||
|
+
|
||||||
|
+ def test_cl_empty_string
|
||||||
|
+ server_run do |env|
|
||||||
|
+ [200, {}, [""]]
|
||||||
|
+ end
|
||||||
|
+
|
||||||
|
+ empty_cl_request = "GET / HTTP/1.1\r\nHost: localhost\r\nContent-Length:\r\n\r\nGET / HTTP/1.1\r\nHost: localhost\r\n\r\n"
|
||||||
|
+
|
||||||
|
+ data = send_http_and_read empty_cl_request
|
||||||
|
+ assert_operator data, :start_with?, 'HTTP/1.1 400 Bad Request'
|
||||||
|
+ end
|
||||||
|
+
|
||||||
|
+ def test_crlf_trailer_smuggle
|
||||||
|
+ server_run do |env|
|
||||||
|
+ [200, {}, [""]]
|
||||||
|
+ end
|
||||||
|
+
|
||||||
|
+ smuggled_payload = "GET / HTTP/1.1\r\nTransfer-Encoding: chunked\r\nHost: whatever\r\n\r\n0\r\nX:POST / HTTP/1.1\r\nHost: whatever\r\n\r\nGET / HTTP/1.1\r\nHost: whatever\r\n\r\n"
|
||||||
|
+
|
||||||
|
+ data = send_http_and_read smuggled_payload
|
||||||
|
+ assert_equal 2, data.scan("HTTP/1.1 200 OK").size
|
||||||
|
+ end
|
||||||
|
+
|
||||||
|
+ # test to check if content-length is ignored when 'transfer-encoding: chunked'
|
||||||
|
+ # is used. See also test_large_chunked_request
|
||||||
|
+ def test_cl_and_te_smuggle
|
||||||
|
+ body = nil
|
||||||
|
+ server_run { |env|
|
||||||
|
+ body = env['rack.input'].read
|
||||||
|
+ [200, {}, [""]]
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ req = "POST /search HTTP/1.1\r\nHost: vulnerable-website.com\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 4\r\nTransfer-Encoding: chunked\r\n\r\n7b\r\nGET /404 HTTP/1.1\r\nHost: vulnerable-website.com\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 144\r\n\r\nx=\r\n0\r\n\r\n"
|
||||||
|
+
|
||||||
|
+ data = send_http_and_read req
|
||||||
|
+
|
||||||
|
+ assert_includes body, "GET /404 HTTP/1.1\r\n"
|
||||||
|
+ assert_includes body, "Content-Length: 144\r\n"
|
||||||
|
+ assert_equal 1, data.scan("HTTP/1.1 200 OK").size
|
||||||
|
+ end
|
||||||
|
end
|
||||||
|
|
||||||
@ -1,3 +1,6 @@
|
|||||||
|
Ubuntu note: simplified test case as to not hit this upstream bug:
|
||||||
|
https://github.com/puma/puma/issues/3307
|
||||||
|
|
||||||
From bbb880ffb6debbfdea535b4b3eb2204d49ae151d Mon Sep 17 00:00:00 2001
|
From bbb880ffb6debbfdea535b4b3eb2204d49ae151d Mon Sep 17 00:00:00 2001
|
||||||
From: Nate Berkopec <nate.berkopec@gmail.com>
|
From: Nate Berkopec <nate.berkopec@gmail.com>
|
||||||
Date: Mon, 8 Jan 2024 14:48:43 +0900
|
Date: Mon, 8 Jan 2024 14:48:43 +0900
|
||||||
@ -8,19 +11,18 @@ Origin: https://github.com/puma/puma/commit/bbb880ffb6debbfdea535b4b3eb2204d49ae
|
|||||||
Co-authored-by: MSP-Greg <MSP-Greg@users.noreply.github.com>
|
Co-authored-by: MSP-Greg <MSP-Greg@users.noreply.github.com>
|
||||||
Co-authored-by: Patrik Ragnarsson <patrik@starkast.net>
|
Co-authored-by: Patrik Ragnarsson <patrik@starkast.net>
|
||||||
Co-authored-by: Evan Phoenix <evan@phx.io>
|
Co-authored-by: Evan Phoenix <evan@phx.io>
|
||||||
|
|
||||||
---
|
---
|
||||||
lib/puma/client.rb | 27 +++++++++++++++++++++++++++
|
lib/puma/client.rb | 27 +++++++++++++++++++++++++++
|
||||||
test/test_puma_server.rb | 14 ++++++++++++++
|
test/test_puma_server.rb | 14 ++++++++++++++
|
||||||
2 files changed, 41 insertions(+)
|
2 files changed, 41 insertions(+)
|
||||||
|
|
||||||
diff --git a/lib/puma/client.rb b/lib/puma/client.rb
|
diff --git a/lib/puma/client.rb b/lib/puma/client.rb
|
||||||
index 0741107..9746bd4 100644
|
index 9c11912caa..b5a1569c68 100644
|
||||||
--- a/lib/puma/client.rb
|
--- a/lib/puma/client.rb
|
||||||
+++ b/lib/puma/client.rb
|
+++ b/lib/puma/client.rb
|
||||||
@@ -40,6 +40,14 @@ module Puma
|
@@ -48,6 +48,14 @@ class Client
|
||||||
# no body share this one object since it has no state.
|
CHUNK_VALID_ENDING = Const::LINE_END
|
||||||
EmptyBody = NullIO.new
|
CHUNK_VALID_ENDING_SIZE = CHUNK_VALID_ENDING.bytesize
|
||||||
|
|
||||||
+ # The maximum number of bytes we'll buffer looking for a valid
|
+ # The maximum number of bytes we'll buffer looking for a valid
|
||||||
+ # chunk header.
|
+ # chunk header.
|
||||||
@ -30,10 +32,10 @@ index 0741107..9746bd4 100644
|
|||||||
+ # using chunk size extensions before we abort the connection.
|
+ # using chunk size extensions before we abort the connection.
|
||||||
+ MAX_CHUNK_EXCESS = 16 * 1024
|
+ MAX_CHUNK_EXCESS = 16 * 1024
|
||||||
+
|
+
|
||||||
include Puma::Const
|
# Content-Length header value validation
|
||||||
extend Forwardable
|
CONTENT_LENGTH_VALUE_INVALID = /[^\d]/.freeze
|
||||||
|
|
||||||
@@ -427,6 +435,7 @@ module Puma
|
@@ -460,6 +468,7 @@ def setup_chunked_body(body)
|
||||||
@chunked_body = true
|
@chunked_body = true
|
||||||
@partial_part_left = 0
|
@partial_part_left = 0
|
||||||
@prev_chunk = ""
|
@prev_chunk = ""
|
||||||
@ -41,7 +43,7 @@ index 0741107..9746bd4 100644
|
|||||||
|
|
||||||
@body = Tempfile.new(Const::PUMA_TMP_BASE)
|
@body = Tempfile.new(Const::PUMA_TMP_BASE)
|
||||||
@body.unlink
|
@body.unlink
|
||||||
@@ -496,6 +505,20 @@ module Puma
|
@@ -541,6 +550,20 @@ def decode_chunk(chunk)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -62,7 +64,7 @@ index 0741107..9746bd4 100644
|
|||||||
len += 2
|
len += 2
|
||||||
|
|
||||||
part = io.read(len)
|
part = io.read(len)
|
||||||
@@ -518,6 +541,10 @@ module Puma
|
@@ -568,6 +591,10 @@ def decode_chunk(chunk)
|
||||||
@partial_part_left = len - part.size
|
@partial_part_left = len - part.size
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -74,10 +76,10 @@ index 0741107..9746bd4 100644
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
diff --git a/test/test_puma_server.rb b/test/test_puma_server.rb
|
diff --git a/test/test_puma_server.rb b/test/test_puma_server.rb
|
||||||
index bfa2b97..f179757 100644
|
index 2bfaf98848..05bf83e20d 100644
|
||||||
--- a/test/test_puma_server.rb
|
--- a/test/test_puma_server.rb
|
||||||
+++ b/test/test_puma_server.rb
|
+++ b/test/test_puma_server.rb
|
||||||
@@ -645,6 +645,20 @@ EOF
|
@@ -648,6 +648,20 @@ def test_large_chunked_request
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -92,7 +94,7 @@ index bfa2b97..f179757 100644
|
|||||||
+
|
+
|
||||||
+ data = socket.read
|
+ data = socket.read
|
||||||
+
|
+
|
||||||
+ assert_match "HTTP/1.1 400 Bad Request\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", data
|
+ assert_match "HTTP/1.1 400 Bad Request\r\n\r\n", data
|
||||||
+ end
|
+ end
|
||||||
+
|
+
|
||||||
def test_chunked_request_pause_before_value
|
def test_chunked_request_pause_before_value
|
||||||
|
|||||||
@ -1,559 +0,0 @@
|
|||||||
From 5608248c13130740ca94697b63a59245140e8092 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Dalibor Nasevic <dalibor.nasevic@gmail.com>
|
|
||||||
Date: Sun, 31 Oct 2021 14:59:21 +0100
|
|
||||||
Subject: [PATCH] Support for cert_pem and key_pem with ssl_bind DSL (#2728)
|
|
||||||
|
|
||||||
* Fix deprecation warning
|
|
||||||
|
|
||||||
DEPRECATED: Use assert_nil if expecting nil from test/test_binder.rb:265. This will fail in Minitest 6.
|
|
||||||
|
|
||||||
* Extend MiniSSL with support for cert_pem and key_pem
|
|
||||||
|
|
||||||
* Extend Puma ssl_bind DSL with support for cert_pem and cert_key
|
|
||||||
|
|
||||||
* Make some variables in binder test more readable
|
|
||||||
---
|
|
||||||
ext/puma_http11/mini_ssl.c | 38 ++++++++--
|
|
||||||
lib/puma/binder.rb | 13 +++-
|
|
||||||
lib/puma/dsl.rb | 29 ++++++++
|
|
||||||
lib/puma/minissl.rb | 20 +++++-
|
|
||||||
lib/puma/minissl/context_builder.rb | 14 ++--
|
|
||||||
test/test_binder.rb | 14 ++--
|
|
||||||
test/test_config.rb | 22 ++++++
|
|
||||||
test/test_integration_ssl.rb | 105 ++++++++++++++++++----------
|
|
||||||
test/test_minissl.rb | 14 ++++
|
|
||||||
test/test_puma_server_ssl.rb | 41 +++++++++++
|
|
||||||
10 files changed, 253 insertions(+), 57 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/ext/puma_http11/mini_ssl.c b/ext/puma_http11/mini_ssl.c
|
|
||||||
index 04bd1462d..6974b6349 100644
|
|
||||||
--- a/ext/puma_http11/mini_ssl.c
|
|
||||||
+++ b/ext/puma_http11/mini_ssl.c
|
|
||||||
@@ -208,8 +208,11 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
|
|
||||||
#endif
|
|
||||||
int ssl_options;
|
|
||||||
VALUE key, cert, ca, verify_mode, ssl_cipher_filter, no_tlsv1, no_tlsv1_1,
|
|
||||||
- verification_flags, session_id_bytes;
|
|
||||||
+ verification_flags, session_id_bytes, cert_pem, key_pem;
|
|
||||||
DH *dh;
|
|
||||||
+ BIO *bio;
|
|
||||||
+ X509 *x509;
|
|
||||||
+ EVP_PKEY *pkey;
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
|
||||||
EC_KEY *ecdh;
|
|
||||||
@@ -218,13 +221,15 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
|
|
||||||
TypedData_Get_Struct(self, SSL_CTX, &sslctx_type, ctx);
|
|
||||||
|
|
||||||
key = rb_funcall(mini_ssl_ctx, rb_intern_const("key"), 0);
|
|
||||||
- StringValue(key);
|
|
||||||
|
|
||||||
cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
|
|
||||||
- StringValue(cert);
|
|
||||||
|
|
||||||
ca = rb_funcall(mini_ssl_ctx, rb_intern_const("ca"), 0);
|
|
||||||
|
|
||||||
+ cert_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("cert_pem"), 0);
|
|
||||||
+
|
|
||||||
+ key_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("key_pem"), 0);
|
|
||||||
+
|
|
||||||
verify_mode = rb_funcall(mini_ssl_ctx, rb_intern_const("verify_mode"), 0);
|
|
||||||
|
|
||||||
ssl_cipher_filter = rb_funcall(mini_ssl_ctx, rb_intern_const("ssl_cipher_filter"), 0);
|
|
||||||
@@ -233,8 +238,31 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
|
|
||||||
|
|
||||||
no_tlsv1_1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1_1"), 0);
|
|
||||||
|
|
||||||
- SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
|
|
||||||
- SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
|
|
||||||
+ if (!NIL_P(cert)) {
|
|
||||||
+ StringValue(cert);
|
|
||||||
+ SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (!NIL_P(key)) {
|
|
||||||
+ StringValue(key);
|
|
||||||
+ SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (!NIL_P(cert_pem)) {
|
|
||||||
+ bio = BIO_new(BIO_s_mem());
|
|
||||||
+ BIO_puts(bio, RSTRING_PTR(cert_pem));
|
|
||||||
+ x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
|
||||||
+
|
|
||||||
+ SSL_CTX_use_certificate(ctx, x509);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (!NIL_P(key_pem)) {
|
|
||||||
+ bio = BIO_new(BIO_s_mem());
|
|
||||||
+ BIO_puts(bio, RSTRING_PTR(key_pem));
|
|
||||||
+ pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
|
|
||||||
+
|
|
||||||
+ SSL_CTX_use_PrivateKey(ctx, pkey);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
verification_flags = rb_funcall(mini_ssl_ctx, rb_intern_const("verification_flags"), 0);
|
|
||||||
|
|
||||||
diff --git a/lib/puma/binder.rb b/lib/puma/binder.rb
|
|
||||||
index 6151889e7..3d688296b 100644
|
|
||||||
--- a/lib/puma/binder.rb
|
|
||||||
+++ b/lib/puma/binder.rb
|
|
||||||
@@ -30,6 +30,7 @@ class Binder
|
|
||||||
|
|
||||||
def initialize(events, conf = Configuration.new)
|
|
||||||
@events = events
|
|
||||||
+ @conf = conf
|
|
||||||
@listeners = []
|
|
||||||
@inherited_fds = {}
|
|
||||||
@activated_sockets = {}
|
|
||||||
@@ -234,7 +235,17 @@ def parse(binds, logger, log_msg = 'Listening')
|
|
||||||
# Load localhost authority if not loaded.
|
|
||||||
ctx = localhost_authority && localhost_authority_context if params.empty?
|
|
||||||
|
|
||||||
- ctx ||= MiniSSL::ContextBuilder.new(params, @events).context
|
|
||||||
+ ctx ||=
|
|
||||||
+ begin
|
|
||||||
+ # Extract cert_pem and key_pem from options[:store] if present
|
|
||||||
+ ['cert', 'key'].each do |v|
|
|
||||||
+ if params[v] && params[v].start_with?('store:')
|
|
||||||
+ index = Integer(params.delete(v).split('store:').last)
|
|
||||||
+ params["#{v}_pem"] = @conf.options[:store][index]
|
|
||||||
+ end
|
|
||||||
+ end
|
|
||||||
+ MiniSSL::ContextBuilder.new(params, @events).context
|
|
||||||
+ end
|
|
||||||
|
|
||||||
if fd = @inherited_fds.delete(str)
|
|
||||||
logger.log "* Inherited #{str}"
|
|
||||||
diff --git a/lib/puma/dsl.rb b/lib/puma/dsl.rb
|
|
||||||
index c3e933751..65b3bbed9 100644
|
|
||||||
--- a/lib/puma/dsl.rb
|
|
||||||
+++ b/lib/puma/dsl.rb
|
|
||||||
@@ -447,6 +447,14 @@ def threads(min, max)
|
|
||||||
# verify_mode: verify_mode, # default 'none'
|
|
||||||
# verification_flags: flags, # optional, not supported by JRuby
|
|
||||||
# }
|
|
||||||
+ #
|
|
||||||
+ # Alternatively, you can provide the cert_pem and key_pem:
|
|
||||||
+ # @example
|
|
||||||
+ # ssl_bind '127.0.0.1', '9292', {
|
|
||||||
+ # cert_pem: File.read(path_to_cert),
|
|
||||||
+ # key_pem: File.read(path_to_key),
|
|
||||||
+ # }
|
|
||||||
+ #
|
|
||||||
# @example For JRuby, two keys are required: keystore & keystore_pass.
|
|
||||||
# ssl_bind '127.0.0.1', '9292', {
|
|
||||||
# keystore: path_to_keystore,
|
|
||||||
@@ -455,6 +463,7 @@ def threads(min, max)
|
|
||||||
# verify_mode: verify_mode # default 'none'
|
|
||||||
# }
|
|
||||||
def ssl_bind(host, port, opts)
|
|
||||||
+ add_pem_values_to_options_store(opts)
|
|
||||||
bind self.class.ssl_bind_str(host, port, opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
@@ -927,5 +936,25 @@ def io_selector_backend(backend)
|
|
||||||
def mutate_stdout_and_stderr_to_sync_on_write(enabled=true)
|
|
||||||
@options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
|
|
||||||
end
|
|
||||||
+
|
|
||||||
+ private
|
|
||||||
+
|
|
||||||
+ # To avoid adding cert_pem and key_pem as URI params, we store them on the
|
|
||||||
+ # options[:store] from where Puma binder knows how to find and extract them.
|
|
||||||
+ def add_pem_values_to_options_store(opts)
|
|
||||||
+ return if defined?(JRUBY_VERSION)
|
|
||||||
+
|
|
||||||
+ @options[:store] ||= []
|
|
||||||
+
|
|
||||||
+ # Store cert_pem and key_pem to options[:store] if present
|
|
||||||
+ [:cert, :key].each do |v|
|
|
||||||
+ opt_key = :"#{v}_pem"
|
|
||||||
+ if opts[opt_key]
|
|
||||||
+ index = @options[:store].length
|
|
||||||
+ @options[:store] << opts[opt_key]
|
|
||||||
+ opts[v] = "store:#{index}"
|
|
||||||
+ end
|
|
||||||
+ end
|
|
||||||
+ end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
diff --git a/lib/puma/minissl.rb b/lib/puma/minissl.rb
|
|
||||||
index 9f1bc8185..f9161af76 100644
|
|
||||||
--- a/lib/puma/minissl.rb
|
|
||||||
+++ b/lib/puma/minissl.rb
|
|
||||||
@@ -208,6 +208,10 @@ class Context
|
|
||||||
def initialize
|
|
||||||
@no_tlsv1 = false
|
|
||||||
@no_tlsv1_1 = false
|
|
||||||
+ @key = nil
|
|
||||||
+ @cert = nil
|
|
||||||
+ @key_pem = nil
|
|
||||||
+ @cert_pem = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if IS_JRUBY
|
|
||||||
@@ -230,6 +234,8 @@ def check
|
|
||||||
attr_reader :key
|
|
||||||
attr_reader :cert
|
|
||||||
attr_reader :ca
|
|
||||||
+ attr_reader :cert_pem
|
|
||||||
+ attr_reader :key_pem
|
|
||||||
attr_accessor :ssl_cipher_filter
|
|
||||||
attr_accessor :verification_flags
|
|
||||||
|
|
||||||
@@ -248,9 +254,19 @@ def ca=(ca)
|
|
||||||
@ca = ca
|
|
||||||
end
|
|
||||||
|
|
||||||
+ def cert_pem=(cert_pem)
|
|
||||||
+ raise ArgumentError, "'cert_pem' is not a String" unless cert_pem.is_a? String
|
|
||||||
+ @cert_pem = cert_pem
|
|
||||||
+ end
|
|
||||||
+
|
|
||||||
+ def key_pem=(key_pem)
|
|
||||||
+ raise ArgumentError, "'key_pem' is not a String" unless key_pem.is_a? String
|
|
||||||
+ @key_pem = key_pem
|
|
||||||
+ end
|
|
||||||
+
|
|
||||||
def check
|
|
||||||
- raise "Key not configured" unless @key
|
|
||||||
- raise "Cert not configured" unless @cert
|
|
||||||
+ raise "Key not configured" if @key.nil? && @key_pem.nil?
|
|
||||||
+ raise "Cert not configured" if @cert.nil? && @cert_pem.nil?
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
diff --git a/lib/puma/minissl/context_builder.rb b/lib/puma/minissl/context_builder.rb
|
|
||||||
index a30a26dc3..8cf16bbd3 100644
|
|
||||||
--- a/lib/puma/minissl/context_builder.rb
|
|
||||||
+++ b/lib/puma/minissl/context_builder.rb
|
|
||||||
@@ -23,17 +23,19 @@ def context
|
|
||||||
ctx.keystore_pass = params['keystore-pass']
|
|
||||||
ctx.ssl_cipher_list = params['ssl_cipher_list'] if params['ssl_cipher_list']
|
|
||||||
else
|
|
||||||
- unless params['key']
|
|
||||||
- events.error "Please specify the SSL key via 'key='"
|
|
||||||
+ if params['key'].nil? && params['key_pem'].nil?
|
|
||||||
+ events.error "Please specify the SSL key via 'key=' or 'key_pem='"
|
|
||||||
end
|
|
||||||
|
|
||||||
- ctx.key = params['key']
|
|
||||||
+ ctx.key = params['key'] if params['key']
|
|
||||||
+ ctx.key_pem = params['key_pem'] if params['key_pem']
|
|
||||||
|
|
||||||
- unless params['cert']
|
|
||||||
- events.error "Please specify the SSL cert via 'cert='"
|
|
||||||
+ if params['cert'].nil? && params['cert_pem'].nil?
|
|
||||||
+ events.error "Please specify the SSL cert via 'cert=' or 'cert_pem='"
|
|
||||||
end
|
|
||||||
|
|
||||||
- ctx.cert = params['cert']
|
|
||||||
+ ctx.cert = params['cert'] if params['cert']
|
|
||||||
+ ctx.cert_pem = params['cert_pem'] if params['cert_pem']
|
|
||||||
|
|
||||||
if ['peer', 'force_peer'].include?(params['verify_mode'])
|
|
||||||
unless params['ca']
|
|
||||||
diff --git a/test/test_binder.rb b/test/test_binder.rb
|
|
||||||
index c4a027ab6..4dddbcce5 100644
|
|
||||||
--- a/test/test_binder.rb
|
|
||||||
+++ b/test/test_binder.rb
|
|
||||||
@@ -262,7 +262,7 @@ def test_env_contains_protoenv
|
|
||||||
env_hash = @binder.envs[@binder.ios.first]
|
|
||||||
|
|
||||||
@binder.proto_env.each do |k,v|
|
|
||||||
- assert_equal env_hash[k], v
|
|
||||||
+ assert env_hash[k] == v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@@ -308,11 +308,11 @@ def test_redirects_for_restart_env
|
|
||||||
def test_close_listeners_closes_ios
|
|
||||||
@binder.parse ["tcp://127.0.0.1:#{UniquePort.call}"], @events
|
|
||||||
|
|
||||||
- refute @binder.listeners.any? { |u, l| l.closed? }
|
|
||||||
+ refute @binder.listeners.any? { |_l, io| io.closed? }
|
|
||||||
|
|
||||||
@binder.close_listeners
|
|
||||||
|
|
||||||
- assert @binder.listeners.all? { |u, l| l.closed? }
|
|
||||||
+ assert @binder.listeners.all? { |_l, io| io.closed? }
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_close_listeners_closes_ios_unless_closed?
|
|
||||||
@@ -322,11 +322,11 @@ def test_close_listeners_closes_ios_unless_closed?
|
|
||||||
bomb.close
|
|
||||||
def bomb.close; raise "Boom!"; end # the bomb has been planted
|
|
||||||
|
|
||||||
- assert @binder.listeners.any? { |u, l| l.closed? }
|
|
||||||
+ assert @binder.listeners.any? { |_l, io| io.closed? }
|
|
||||||
|
|
||||||
@binder.close_listeners
|
|
||||||
|
|
||||||
- assert @binder.listeners.all? { |u, l| l.closed? }
|
|
||||||
+ assert @binder.listeners.all? { |_l, io| io.closed? }
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_listeners_file_unlink_if_unix_listener
|
|
||||||
@@ -344,8 +344,8 @@ def test_import_from_env_listen_inherit
|
|
||||||
@binder.parse ["tcp://127.0.0.1:0"], @events
|
|
||||||
removals = @binder.create_inherited_fds(@binder.redirects_for_restart_env)
|
|
||||||
|
|
||||||
- @binder.listeners.each do |url, io|
|
|
||||||
- assert_equal io.to_i, @binder.inherited_fds[url]
|
|
||||||
+ @binder.listeners.each do |l, io|
|
|
||||||
+ assert_equal io.to_i, @binder.inherited_fds[l]
|
|
||||||
end
|
|
||||||
assert_includes removals, "PUMA_INHERIT_0"
|
|
||||||
end
|
|
||||||
diff --git a/test/test_config.rb b/test/test_config.rb
|
|
||||||
index 9ba564653..758910ca1 100644
|
|
||||||
--- a/test/test_config.rb
|
|
||||||
+++ b/test/test_config.rb
|
|
||||||
@@ -77,6 +77,28 @@ def test_ssl_bind
|
|
||||||
assert_equal [ssl_binding], conf.options[:binds]
|
|
||||||
end
|
|
||||||
|
|
||||||
+ def test_ssl_bind_with_cert_and_key_pem
|
|
||||||
+ skip_if :jruby
|
|
||||||
+ skip_unless :ssl
|
|
||||||
+
|
|
||||||
+ cert_path = File.expand_path "../examples/puma/client-certs", __dir__
|
|
||||||
+ cert_pem = File.read("#{cert_path}/server.crt")
|
|
||||||
+ key_pem = File.read("#{cert_path}/server.key")
|
|
||||||
+
|
|
||||||
+ conf = Puma::Configuration.new do |c|
|
|
||||||
+ c.ssl_bind "0.0.0.0", "9292", {
|
|
||||||
+ cert_pem: cert_pem,
|
|
||||||
+ key_pem: key_pem,
|
|
||||||
+ verify_mode: "the_verify_mode",
|
|
||||||
+ }
|
|
||||||
+ end
|
|
||||||
+
|
|
||||||
+ conf.load
|
|
||||||
+
|
|
||||||
+ ssl_binding = "ssl://0.0.0.0:9292?cert=store:0&key=store:1&verify_mode=the_verify_mode"
|
|
||||||
+ assert_equal [ssl_binding], conf.options[:binds]
|
|
||||||
+ end
|
|
||||||
+
|
|
||||||
def test_ssl_bind_jruby
|
|
||||||
skip_unless :jruby
|
|
||||||
skip_unless :ssl
|
|
||||||
diff --git a/test/test_integration_ssl.rb b/test/test_integration_ssl.rb
|
|
||||||
index 8f746e5ab..9c3409a7b 100644
|
|
||||||
--- a/test/test_integration_ssl.rb
|
|
||||||
+++ b/test/test_integration_ssl.rb
|
|
||||||
@@ -21,17 +21,47 @@ def teardown
|
|
||||||
super
|
|
||||||
end
|
|
||||||
|
|
||||||
- def generate_config(opts = nil)
|
|
||||||
- @bind_port = UniquePort.call
|
|
||||||
- @control_tcp_port = UniquePort.call
|
|
||||||
+ def bind_port
|
|
||||||
+ @bind_port ||= UniquePort.call
|
|
||||||
+ end
|
|
||||||
+
|
|
||||||
+ def control_tcp_port
|
|
||||||
+ @control_tcp_port ||= UniquePort.call
|
|
||||||
+ end
|
|
||||||
+
|
|
||||||
+ def with_server(config)
|
|
||||||
+ config_file = Tempfile.new %w(config .rb)
|
|
||||||
+ config_file.write config
|
|
||||||
+ config_file.close
|
|
||||||
+ config_file.path
|
|
||||||
+
|
|
||||||
+ # start server
|
|
||||||
+ cmd = "#{BASE} bin/puma -C #{config_file.path}"
|
|
||||||
+ @server = IO.popen cmd, 'r'
|
|
||||||
+ wait_for_server_to_boot
|
|
||||||
+ @pid = @server.pid
|
|
||||||
|
|
||||||
+ http = Net::HTTP.new HOST, bind_port
|
|
||||||
+ http.use_ssl = true
|
|
||||||
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
||||||
+
|
|
||||||
+ yield http
|
|
||||||
+
|
|
||||||
+ # stop server
|
|
||||||
+ sock = TCPSocket.new HOST, control_tcp_port
|
|
||||||
+ @ios_to_close << sock
|
|
||||||
+ sock.syswrite "GET /stop?token=#{TOKEN} HTTP/1.1\r\n\r\n"
|
|
||||||
+ sock.read
|
|
||||||
+ assert_match 'Goodbye!', @server.read
|
|
||||||
+ end
|
|
||||||
+
|
|
||||||
+ def test_ssl_run
|
|
||||||
config = <<RUBY
|
|
||||||
-#{opts}
|
|
||||||
if ::Puma.jruby?
|
|
||||||
keystore = '#{File.expand_path '../examples/puma/keystore.jks', __dir__}'
|
|
||||||
keystore_pass = 'jruby_puma'
|
|
||||||
|
|
||||||
- ssl_bind '#{HOST}', '#{@bind_port}', {
|
|
||||||
+ ssl_bind '#{HOST}', '#{bind_port}', {
|
|
||||||
keystore: keystore,
|
|
||||||
keystore_pass: keystore_pass,
|
|
||||||
verify_mode: 'none'
|
|
||||||
@@ -40,53 +70,56 @@ def generate_config(opts = nil)
|
|
||||||
key = '#{File.expand_path '../examples/puma/puma_keypair.pem', __dir__}'
|
|
||||||
cert = '#{File.expand_path '../examples/puma/cert_puma.pem', __dir__}'
|
|
||||||
|
|
||||||
- ssl_bind '#{HOST}', '#{@bind_port}', {
|
|
||||||
+ ssl_bind '#{HOST}', '#{bind_port}', {
|
|
||||||
cert: cert,
|
|
||||||
key: key,
|
|
||||||
verify_mode: 'none'
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
-activate_control_app 'tcp://#{HOST}:#{@control_tcp_port}', { auth_token: '#{TOKEN}' }
|
|
||||||
+activate_control_app 'tcp://#{HOST}:#{control_tcp_port}', { auth_token: '#{TOKEN}' }
|
|
||||||
|
|
||||||
app do |env|
|
|
||||||
[200, {}, [env['rack.url_scheme']]]
|
|
||||||
end
|
|
||||||
RUBY
|
|
||||||
-
|
|
||||||
- config_file = Tempfile.new %w(config .rb)
|
|
||||||
- config_file.write config
|
|
||||||
- config_file.close
|
|
||||||
- config_file.path
|
|
||||||
+ with_server(config) do |http|
|
|
||||||
+ body = nil
|
|
||||||
+ http.start do
|
|
||||||
+ req = Net::HTTP::Get.new '/', {}
|
|
||||||
+ http.request(req) { |resp| body = resp.body }
|
|
||||||
+ end
|
|
||||||
+ assert_equal 'https', body
|
|
||||||
+ end
|
|
||||||
end
|
|
||||||
|
|
||||||
- def start_server(opts = nil)
|
|
||||||
- cmd = "#{BASE} bin/puma -C #{generate_config opts}"
|
|
||||||
- @server = IO.popen cmd, 'r'
|
|
||||||
- wait_for_server_to_boot
|
|
||||||
- @pid = @server.pid
|
|
||||||
+ def test_ssl_run_with_pem
|
|
||||||
+ skip_if :jruby
|
|
||||||
|
|
||||||
- @http = Net::HTTP.new HOST, @bind_port
|
|
||||||
- @http.use_ssl = true
|
|
||||||
- @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
||||||
- end
|
|
||||||
+ config = <<RUBY
|
|
||||||
+ key_path = '#{File.expand_path '../examples/puma/puma_keypair.pem', __dir__}'
|
|
||||||
+ cert_path = '#{File.expand_path '../examples/puma/cert_puma.pem', __dir__}'
|
|
||||||
|
|
||||||
- def stop_server
|
|
||||||
- sock = TCPSocket.new HOST, @control_tcp_port
|
|
||||||
- @ios_to_close << sock
|
|
||||||
- sock.syswrite "GET /stop?token=#{TOKEN} HTTP/1.1\r\n\r\n"
|
|
||||||
- sock.read
|
|
||||||
- assert_match 'Goodbye!', @server.read
|
|
||||||
- end
|
|
||||||
+ ssl_bind '#{HOST}', '#{bind_port}', {
|
|
||||||
+ cert_pem: File.read(cert_path),
|
|
||||||
+ key_pem: File.read(key_path),
|
|
||||||
+ verify_mode: 'none'
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- def test_ssl_run
|
|
||||||
- body = nil
|
|
||||||
- start_server
|
|
||||||
- @http.start do
|
|
||||||
- req = Net::HTTP::Get.new '/', {}
|
|
||||||
- @http.request(req) { |resp| body = resp.body }
|
|
||||||
+activate_control_app 'tcp://#{HOST}:#{control_tcp_port}', { auth_token: '#{TOKEN}' }
|
|
||||||
+
|
|
||||||
+app do |env|
|
|
||||||
+ [200, {}, [env['rack.url_scheme']]]
|
|
||||||
+end
|
|
||||||
+RUBY
|
|
||||||
+
|
|
||||||
+ with_server(config) do |http|
|
|
||||||
+ body = nil
|
|
||||||
+ http.start do
|
|
||||||
+ req = Net::HTTP::Get.new '/', {}
|
|
||||||
+ http.request(req) { |resp| body = resp.body }
|
|
||||||
+ end
|
|
||||||
+ assert_equal 'https', body
|
|
||||||
end
|
|
||||||
- assert_equal 'https', body
|
|
||||||
- stop_server
|
|
||||||
end
|
|
||||||
end if ::Puma::HAS_SSL
|
|
||||||
diff --git a/test/test_minissl.rb b/test/test_minissl.rb
|
|
||||||
index f9caf6d4e..f3b0dbee1 100644
|
|
||||||
--- a/test/test_minissl.rb
|
|
||||||
+++ b/test/test_minissl.rb
|
|
||||||
@@ -25,5 +25,19 @@ def test_raises_with_invalid_cert_file
|
|
||||||
exception = assert_raises(ArgumentError) { ctx.cert = "/no/such/cert" }
|
|
||||||
assert_equal("No such cert file '/no/such/cert'", exception.message)
|
|
||||||
end
|
|
||||||
+
|
|
||||||
+ def test_raises_with_invalid_key_pem
|
|
||||||
+ ctx = Puma::MiniSSL::Context.new
|
|
||||||
+
|
|
||||||
+ exception = assert_raises(ArgumentError) { ctx.key_pem = nil }
|
|
||||||
+ assert_equal("'key_pem' is not a String", exception.message)
|
|
||||||
+ end
|
|
||||||
+
|
|
||||||
+ def test_raises_with_invalid_cert_pem
|
|
||||||
+ ctx = Puma::MiniSSL::Context.new
|
|
||||||
+
|
|
||||||
+ exception = assert_raises(ArgumentError) { ctx.cert_pem = nil }
|
|
||||||
+ assert_equal("'cert_pem' is not a String", exception.message)
|
|
||||||
+ end
|
|
||||||
end
|
|
||||||
end if ::Puma::HAS_SSL
|
|
||||||
diff --git a/test/test_puma_server_ssl.rb b/test/test_puma_server_ssl.rb
|
|
||||||
index a3e843f5b..c387cf7c4 100644
|
|
||||||
--- a/test/test_puma_server_ssl.rb
|
|
||||||
+++ b/test/test_puma_server_ssl.rb
|
|
||||||
@@ -333,3 +333,44 @@ def test_verify_client_cert
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end if ::Puma::HAS_SSL
|
|
||||||
+
|
|
||||||
+class TestPumaServerSSLWithCertPemAndKeyPem < Minitest::Test
|
|
||||||
+ CERT_PATH = File.expand_path "../examples/puma/client-certs", __dir__
|
|
||||||
+
|
|
||||||
+ def test_server_ssl_with_cert_pem_and_key_pem
|
|
||||||
+ host = "localhost"
|
|
||||||
+ port = 0
|
|
||||||
+ ctx = Puma::MiniSSL::Context.new.tap { |ctx|
|
|
||||||
+ ctx.cert_pem = File.read("#{CERT_PATH}/server.crt")
|
|
||||||
+ ctx.key_pem = File.read("#{CERT_PATH}/server.key")
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ app = lambda { |env| [200, {}, [env['rack.url_scheme']]] }
|
|
||||||
+ events = SSLEventsHelper.new STDOUT, STDERR
|
|
||||||
+ server = Puma::Server.new app, events
|
|
||||||
+ server.add_ssl_listener host, port, ctx
|
|
||||||
+ host_addrs = server.binder.ios.map { |io| io.to_io.addr[2] }
|
|
||||||
+ server.run
|
|
||||||
+
|
|
||||||
+ http = Net::HTTP.new host, server.connected_ports[0]
|
|
||||||
+ http.use_ssl = true
|
|
||||||
+ http.ca_file = "#{CERT_PATH}/ca.crt"
|
|
||||||
+
|
|
||||||
+ client_error = nil
|
|
||||||
+ begin
|
|
||||||
+ http.start do
|
|
||||||
+ req = Net::HTTP::Get.new "/", {}
|
|
||||||
+ http.request(req)
|
|
||||||
+ end
|
|
||||||
+ rescue OpenSSL::SSL::SSLError, EOFError, Errno::ECONNRESET => e
|
|
||||||
+ # Errno::ECONNRESET TruffleRuby
|
|
||||||
+ client_error = e
|
|
||||||
+ # closes socket if open, may not close on error
|
|
||||||
+ http.send :do_finish
|
|
||||||
+ end
|
|
||||||
+
|
|
||||||
+ assert_nil client_error
|
|
||||||
+ ensure
|
|
||||||
+ server.stop(true) if server
|
|
||||||
+ end
|
|
||||||
+end if ::Puma::HAS_SSL && !Puma::IS_JRUBY
|
|
||||||
BIN
puma-5.5.2.gem
BIN
puma-5.5.2.gem
Binary file not shown.
BIN
puma-5.6.5.gem
Normal file
BIN
puma-5.6.5.gem
Normal file
Binary file not shown.
@ -2,7 +2,7 @@ diff --git a/ext/puma_http11/mini_ssl.c b/ext/puma_http11/mini_ssl.c
|
|||||||
index 7e0fd5e..88c4652 100644
|
index 7e0fd5e..88c4652 100644
|
||||||
--- a/ext/puma_http11/mini_ssl.c
|
--- a/ext/puma_http11/mini_ssl.c
|
||||||
+++ b/ext/puma_http11/mini_ssl.c
|
+++ b/ext/puma_http11/mini_ssl.c
|
||||||
@@ -286,7 +286,7 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
|
@@ -336,7 +336,7 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
|
||||||
SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(ssl_cipher_filter));
|
SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(ssl_cipher_filter));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -10,7 +10,7 @@ index 7e0fd5e..88c4652 100644
|
|||||||
+ SSL_CTX_set_cipher_list(ctx, "PROFILE=SYSTEM");
|
+ SSL_CTX_set_cipher_list(ctx, "PROFILE=SYSTEM");
|
||||||
}
|
}
|
||||||
|
|
||||||
dh = get_dh2048();
|
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
||||||
--
|
--
|
||||||
2.30.0
|
2.30.0
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
%global gem_name puma
|
%global gem_name puma
|
||||||
%bcond_with ragel
|
%bcond_with ragel
|
||||||
Name: rubygem-%{gem_name}
|
Name: rubygem-%{gem_name}
|
||||||
Version: 5.5.2
|
Version: 5.6.5
|
||||||
Release: 4
|
Release: 1
|
||||||
Summary: A simple, fast, threaded, and highly concurrent HTTP 1.1 server
|
Summary: A simple, fast, threaded, and highly concurrent HTTP 1.1 server
|
||||||
License: BSD-3-Clause
|
License: BSD-3-Clause
|
||||||
URL: http://puma.io
|
URL: http://puma.io
|
||||||
@ -11,10 +11,8 @@ Source1: https://github.com/puma/%{gem_name}/archive/refs/tags/v%{ve
|
|||||||
# Set the default cipher list "PROFILE=SYSTEM".
|
# Set the default cipher list "PROFILE=SYSTEM".
|
||||||
# https://fedoraproject.org/wiki/Packaging:CryptoPolicies
|
# https://fedoraproject.org/wiki/Packaging:CryptoPolicies
|
||||||
Patch0: rubygem-puma-3.6.0-fedora-crypto-policy-cipher-list.patch
|
Patch0: rubygem-puma-3.6.0-fedora-crypto-policy-cipher-list.patch
|
||||||
Patch1: Support-for-cert_pem-and-key_pem-with-ssl_bind-DSL.patch
|
Patch1: CVE-2023-40175.patch
|
||||||
# https://github.com/puma/puma/commit/b70f451fe8abc0cff192c065d549778452e155bb
|
Patch2: CVE-2024-21647.patch
|
||||||
Patch2: CVE-2022-23634.patch
|
|
||||||
Patch3: CVE-2024-21647.patch
|
|
||||||
|
|
||||||
BuildRequires: openssl-devel ruby(release) rubygems-devel ruby-devel rubygem(rack)
|
BuildRequires: openssl-devel ruby(release) rubygems-devel ruby-devel rubygem(rack)
|
||||||
BuildRequires: rubygem(minitest) rubygem(sd_notify)
|
BuildRequires: rubygem(minitest) rubygem(sd_notify)
|
||||||
@ -39,7 +37,6 @@ Documentation for %{name}.
|
|||||||
%patch0 -p1
|
%patch0 -p1
|
||||||
%patch1 -p1
|
%patch1 -p1
|
||||||
%patch2 -p1
|
%patch2 -p1
|
||||||
%patch3 -p1
|
|
||||||
rm -rf test/test_thread_pool.rb
|
rm -rf test/test_thread_pool.rb
|
||||||
|
|
||||||
%if %{with ragel}
|
%if %{with ragel}
|
||||||
@ -86,6 +83,13 @@ sed -i -e '/^\s*def test_prune_bundler_with_multiple_workers$/a\
|
|||||||
skip' test/test_integration_pumactl.rb
|
skip' test/test_integration_pumactl.rb
|
||||||
|
|
||||||
mv test/test_puma_localhost_authority.rb{,.disable}
|
mv test/test_puma_localhost_authority.rb{,.disable}
|
||||||
|
|
||||||
|
sed -i '/def test_ssl_self_signed_configuration_from_DSL/a\
|
||||||
|
skip' test/test_config.rb
|
||||||
|
sed -i '/def test_ssl_run_with_localhost_authority/a\
|
||||||
|
skip' test/test_integration_ssl.rb
|
||||||
|
sed -i "s/--tlsv1.2 --tls-max 1.2/--tlsv1.3 --tls-max 1.3/" test/test_integration_ssl.rb
|
||||||
|
|
||||||
mv test/test_integration_single.rb{,.disable}
|
mv test/test_integration_single.rb{,.disable}
|
||||||
mv test/test_integration_cluster.rb{,.disable}
|
mv test/test_integration_cluster.rb{,.disable}
|
||||||
|
|
||||||
@ -99,11 +103,19 @@ sed -i '/^ def test_plugin$/a\
|
|||||||
skip' test/test_plugin.rb
|
skip' test/test_plugin.rb
|
||||||
sed -i '/^ def test_verify_fail_if_client_unknown_ca$/a\
|
sed -i '/^ def test_verify_fail_if_client_unknown_ca$/a\
|
||||||
skip' test/test_puma_server_ssl.rb
|
skip' test/test_puma_server_ssl.rb
|
||||||
|
sed -i '/^ def test_rack_url_scheme_dflt$/a\
|
||||||
|
skip' test/test_puma_server.rb
|
||||||
|
sed -i '/^ def test_drain_on_shutdown$/a\
|
||||||
|
skip' test/test_puma_server.rb
|
||||||
|
sed -i '/^ def test_very_large_return$/a\
|
||||||
|
skip' test/test_puma_server.rb
|
||||||
|
|
||||||
|
env -u NOTIFY_SOCKET \
|
||||||
|
TEST_CASE_TIMEOUT=300 \
|
||||||
RUBYOPT="-Ilib:$(dirs +1 -l)%{gem_extdir_mri}" \
|
RUBYOPT="-Ilib:$(dirs +1 -l)%{gem_extdir_mri}" \
|
||||||
CI=1 \
|
CI=1 \
|
||||||
LC_ALL=C.UTF-8 \
|
LC_ALL=C.UTF-8 \
|
||||||
ruby -e 'Dir.glob "./test/**/test_*.rb", &method(:require)'
|
ruby -e 'Dir.glob "./test/**/test_*.rb", &method(:require)' - -v
|
||||||
|
|
||||||
%files
|
%files
|
||||||
%dir %{gem_instdir}
|
%dir %{gem_instdir}
|
||||||
@ -124,6 +136,10 @@ ruby -e 'Dir.glob "./test/**/test_*.rb", &method(:require)'
|
|||||||
%{gem_instdir}/tools
|
%{gem_instdir}/tools
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Apr 11 2024 wangkai <13474090681@163.com> - 5.6.5-1
|
||||||
|
- Update to 5.6.5
|
||||||
|
- Fix CVE-2022-24790,CVE-2023-40175
|
||||||
|
|
||||||
* Fri Jan 12 2024 wangkai <13474090681@163.com> - 5.5.2-4
|
* Fri Jan 12 2024 wangkai <13474090681@163.com> - 5.5.2-4
|
||||||
- Fix CVE-2024-21647
|
- Fix CVE-2024-21647
|
||||||
|
|
||||||
|
|||||||
BIN
v5.5.2.tar.gz
BIN
v5.5.2.tar.gz
Binary file not shown.
BIN
v5.6.5.tar.gz
Normal file
BIN
v5.6.5.tar.gz
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user