From 4abe2e6cca013422a20b06104e5ab1230446a6cb Mon Sep 17 00:00:00 2001 From: Alex Vong Date: Fri, 23 Nov 2018 06:34:10 +0800 Subject: [PATCH] gnu: ruby-1.8: Fix CVE-2013-4164, CVE-2014-{8080,8090}, CVE-2015-1855, CVE-2017-{0898,10784,17405,17742,17790} and CVE-2018-{6914,8777,8778,8779,8780}. * gnu/packages/patches/ruby-1.8-CVE-2013-4164.patch, gnu/packages/patches/ruby-1.8-CVE-2014-8080.patch, gnu/packages/patches/ruby-1.8-CVE-2014-8090.patch, gnu/packages/patches/ruby-1.8-CVE-2015-1855.patch, gnu/packages/patches/ruby-1.8-CVE-2017-0898.patch, gnu/packages/patches/ruby-1.8-CVE-2017-10784.patch, gnu/packages/patches/ruby-1.8-CVE-2017-17405.patch, gnu/packages/patches/ruby-1.8-CVE-2017-17742-pre.patch, gnu/packages/patches/ruby-1.8-CVE-2017-17742.patch, gnu/packages/patches/ruby-1.8-CVE-2017-17790.patch, gnu/packages/patches/ruby-1.8-CVE-2018-6914.patch, gnu/packages/patches/ruby-1.8-CVE-2018-8777+CVE-2017-17742-pre.patch, gnu/packages/patches/ruby-1.8-CVE-2018-8777.patch, gnu/packages/patches/ruby-1.8-CVE-2018-8778.patch, gnu/packages/patches/ruby-1.8-CVE-2018-8779.patch, gnu/packages/patches/ruby-1.8-CVE-2018-8780+CVE-2018-8779-pre.patch, gnu/packages/patches/ruby-1.8-CVE-2018-8780.patch: New files. * gnu/local.mk (dist_patch_DATA): Add them. * gnu/packages/ruby.scm (ruby-1.8)[source]: Use them. --- gnu/local.mk | 17 + .../patches/ruby-1.8-CVE-2013-4164.patch | 84 ++++ .../patches/ruby-1.8-CVE-2014-8080.patch | 76 ++++ .../patches/ruby-1.8-CVE-2014-8090.patch | 120 ++++++ .../patches/ruby-1.8-CVE-2015-1855.patch | 270 ++++++++++++ .../patches/ruby-1.8-CVE-2017-0898.patch | 110 +++++ .../patches/ruby-1.8-CVE-2017-10784.patch | 99 +++++ .../patches/ruby-1.8-CVE-2017-17405.patch | 62 +++ .../patches/ruby-1.8-CVE-2017-17742-pre.patch | 161 +++++++ .../patches/ruby-1.8-CVE-2017-17742.patch | 132 ++++++ .../patches/ruby-1.8-CVE-2017-17790.patch | 32 ++ .../patches/ruby-1.8-CVE-2018-6914.patch | 99 +++++ ...1.8-CVE-2018-8777+CVE-2017-17742-pre.patch | 366 ++++++++++++++++ .../patches/ruby-1.8-CVE-2018-8777.patch | 394 ++++++++++++++++++ .../patches/ruby-1.8-CVE-2018-8778.patch | 67 +++ .../patches/ruby-1.8-CVE-2018-8779.patch | 99 +++++ ...-1.8-CVE-2018-8780+CVE-2018-8779-pre.patch | 52 +++ .../patches/ruby-1.8-CVE-2018-8780.patch | 114 +++++ gnu/packages/ruby.scm | 20 +- 19 files changed, 2373 insertions(+), 1 deletion(-) create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2013-4164.patch create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2014-8080.patch create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2014-8090.patch create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2015-1855.patch create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2017-0898.patch create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2017-10784.patch create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2017-17405.patch create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2017-17742-pre.patch create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2017-17742.patch create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2017-17790.patch create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2018-6914.patch create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2018-8777+CVE-2017-17742-pre.patch create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2018-8777.patch create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2018-8778.patch create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2018-8779.patch create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2018-8780+CVE-2018-8779-pre.patch create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2018-8780.patch diff --git a/gnu/local.mk b/gnu/local.mk index c56278e93..83cc4cfe3 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -1127,6 +1127,23 @@ dist_patch_DATA = \ %D%/packages/patches/rpcbind-CVE-2017-8779.patch \ %D%/packages/patches/rtags-separate-rct.patch \ %D%/packages/patches/racket-store-checksum-override.patch \ + %D%/packages/patches/ruby-1.8-CVE-2013-4164.patch \ + %D%/packages/patches/ruby-1.8-CVE-2014-8080.patch \ + %D%/packages/patches/ruby-1.8-CVE-2014-8090.patch \ + %D%/packages/patches/ruby-1.8-CVE-2015-1855.patch \ + %D%/packages/patches/ruby-1.8-CVE-2017-0898.patch \ + %D%/packages/patches/ruby-1.8-CVE-2017-10784.patch \ + %D%/packages/patches/ruby-1.8-CVE-2017-17405.patch \ + %D%/packages/patches/ruby-1.8-CVE-2017-17742-pre.patch \ + %D%/packages/patches/ruby-1.8-CVE-2017-17742.patch \ + %D%/packages/patches/ruby-1.8-CVE-2017-17790.patch \ + %D%/packages/patches/ruby-1.8-CVE-2018-6914.patch \ + %D%/packages/patches/ruby-1.8-CVE-2018-8777+CVE-2017-17742-pre.patch \ + %D%/packages/patches/ruby-1.8-CVE-2018-8777.patch \ + %D%/packages/patches/ruby-1.8-CVE-2018-8778.patch \ + %D%/packages/patches/ruby-1.8-CVE-2018-8779.patch \ + %D%/packages/patches/ruby-1.8-CVE-2018-8780+CVE-2018-8779-pre.patch \ + %D%/packages/patches/ruby-1.8-CVE-2018-8780.patch \ %D%/packages/patches/ruby-rubygems-276-for-ruby24.patch \ %D%/packages/patches/ruby-concurrent-ignore-broken-test.patch \ %D%/packages/patches/ruby-concurrent-test-arm.patch \ diff --git a/gnu/packages/patches/ruby-1.8-CVE-2013-4164.patch b/gnu/packages/patches/ruby-1.8-CVE-2013-4164.patch new file mode 100644 index 000000000..5838d2b14 --- /dev/null +++ b/gnu/packages/patches/ruby-1.8-CVE-2013-4164.patch @@ -0,0 +1,84 @@ +Fix CVE-2013-4164: + +https://www.ruby-lang.org/en/news/2013/11/22/heap-overflow-in-floating-point-parsing-cve-2013-4164/ +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-4164 +https://security-tracker.debian.org/tracker/CVE-2013-4164 + +Patch copied from snapshot.debian.org: + +https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz + +Description: Fix Heap Overflow in Floating Point Parsing + This vulnerability is tracked with CVE-2013-4164. + . + https://www.ruby-lang.org/en/news/2013/11/22/ruby-1-9-3-p484-is-released/ +Origin: backport, https://bugs.ruby-lang.org/projects/ruby-193/repository/revisions/43776/diff + https://bugs.ruby-lang.org/projects/ruby-193/repository/revisions/43782/diff +Bug-Debian: http://bugs.debian.org/730189 +Forwarded: not-needed +Applied-Upstream: 1.9.3-p484, 2.0.0-p353 +Last-Update: 2013-11-29 + +--- a/util.c ++++ b/util.c +@@ -892,6 +892,11 @@ extern void *MALLOC(size_t); + #else + #define MALLOC malloc + #endif ++#ifdef FREE ++extern void FREE(void*); ++#else ++#define FREE free ++#endif + + #ifndef Omit_Private_Memory + #ifndef PRIVATE_MEM +@@ -1176,7 +1181,7 @@ Balloc(int k) + #endif + + ACQUIRE_DTOA_LOCK(0); +- if ((rv = freelist[k]) != 0) { ++ if (k <= Kmax && (rv = freelist[k]) != 0) { + freelist[k] = rv->next; + } + else { +@@ -1186,7 +1191,7 @@ Balloc(int k) + #else + len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) + /sizeof(double); +- if (pmem_next - private_mem + len <= PRIVATE_mem) { ++ if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) { + rv = (Bigint*)pmem_next; + pmem_next += len; + } +@@ -1205,6 +1210,10 @@ static void + Bfree(Bigint *v) + { + if (v) { ++ if (v->k > Kmax) { ++ FREE(v); ++ return; ++ } + ACQUIRE_DTOA_LOCK(0); + v->next = freelist[v->k]; + freelist[v->k] = v; +@@ -2200,6 +2209,7 @@ break2: + for (; c >= '0' && c <= '9'; c = *++s) { + have_dig: + nz++; ++ if (nf > DBL_DIG * 4) continue; + if (c -= '0') { + nf += nz; + for (i = 1; i < nz; i++) +--- a/test/ruby/test_float.rb ++++ b/test/ruby/test_float.rb +@@ -171,4 +171,9 @@ class TestFloat < Test::Unit::TestCase + assert_raise(ArgumentError) { 1.0 < nil } + assert_raise(ArgumentError) { 1.0 <= nil } + end ++ ++ def test_long_string ++ assert(10.0 - ("1."+"1"*300000).to_f*9 < 0.000001) ++ end ++ + end diff --git a/gnu/packages/patches/ruby-1.8-CVE-2014-8080.patch b/gnu/packages/patches/ruby-1.8-CVE-2014-8080.patch new file mode 100644 index 000000000..169b41379 --- /dev/null +++ b/gnu/packages/patches/ruby-1.8-CVE-2014-8080.patch @@ -0,0 +1,76 @@ +Fix CVE-2014-8080: + +https://www.ruby-lang.org/en/news/2014/10/27/rexml-dos-cve-2014-8080/ +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-8080 +https://security-tracker.debian.org/tracker/CVE-2014-8080 + +Patch copied from snapshot.debian.org: + +https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz + +Description: Fix CVE-2014-8080 +Origin: upstream, http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=48161 +Forwarded: not-needed +Author: Alessandro Ghedini +Last-Update: 2015-02-07 + +--- a/lib/rexml/entity.rb ++++ b/lib/rexml/entity.rb +@@ -138,8 +138,14 @@ + matches = @value.scan(PEREFERENCE_RE) + rv = @value.clone + if @parent ++ sum = 0 + matches.each do |entity_reference| + entity_value = @parent.entity( entity_reference[0] ) ++ if sum + entity_value.bytesize > Document.entity_expansion_text_limit ++ raise "entity expansion has grown too large" ++ else ++ sum += entity_value.bytesize ++ end + rv.gsub!( /%#{entity_reference};/um, entity_value ) + end + end +--- a/test/rexml/test_document.rb ++++ b/test/rexml/test_document.rb +@@ -26,6 +26,20 @@ + + EOF + ++ XML_WITH_NESTED_PARAMETER_ENTITY = < ++ ++ ++ ++ ++ ++ ++ ++]> ++ ++EOF ++ + XML_WITH_4_ENTITY_EXPANSION = < + +Last-Update: 2015-02-07 + +--- a/lib/rexml/document.rb ++++ b/lib/rexml/document.rb +@@ -235,6 +235,10 @@ + end + end + ++ def document ++ self ++ end ++ + private + def build( source ) + Parsers::TreeParser.new( source, self ).parse +--- a/lib/rexml/entity.rb ++++ b/lib/rexml/entity.rb +@@ -157,6 +157,7 @@ + + # This is a set of entity constants -- the ones defined in the XML + # specification. These are +gt+, +lt+, +amp+, +quot+ and +apos+. ++ # CAUTION: these entities does not have parent and document + module EntityConst + # +>+ + GT = Entity.new( 'gt', '>' ) +--- a/test/rexml/test_document.rb ++++ b/test/rexml/test_document.rb +@@ -26,6 +26,22 @@ + + EOF + ++ XML_WITH_NESTED_EMPTY_ENTITY = < ++ ++ ++ ++ ++ ++ ++ ++]> ++ +++&a; ++ ++EOF ++ + XML_WITH_NESTED_PARAMETER_ENTITY = < +@@ -40,6 +56,20 @@ + + EOF + ++ XML_WITH_NESTED_EMPTY_PARAMETER_ENTITY = < ++ ++ ++ ++ ++ ++ ++ ++]> ++ ++EOF ++ + XML_WITH_4_ENTITY_EXPANSION = < + + +--- a/ext/openssl/lib/openssl/ssl-internal.rb ++++ b/ext/openssl/lib/openssl/ssl-internal.rb +@@ -96,8 +96,7 @@ module OpenSSL + case san.tag + when 2 # dNSName in GeneralName (RFC5280) + should_verify_common_name = false +- reg = Regexp.escape(san.value).gsub(/\\\*/, "[^.]+") +- return true if /\A#{reg}\z/i =~ hostname ++ return true if verify_hostname(hostname, san.value) + when 7 # iPAddress in GeneralName (RFC5280) + should_verify_common_name = false + # follows GENERAL_NAME_print() in x509v3/v3_alt.c +@@ -112,8 +111,7 @@ module OpenSSL + if should_verify_common_name + cert.subject.to_a.each{|oid, value| + if oid == "CN" +- reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+") +- return true if /\A#{reg}\z/i =~ hostname ++ return true if verify_hostname(hostname, value) + end + } + end +@@ -121,11 +119,67 @@ module OpenSSL + end + module_function :verify_certificate_identity + ++ def verify_hostname(hostname, san) # :nodoc: ++ # RFC 5280, IA5String is limited to the set of ASCII characters ++ return false if san =~ /[\x80-\xff]/ ++ return false if hostname =~ /[\x80-\xff]/ ++ ++ # See RFC 6125, section 6.4.1 ++ # Matching is case-insensitive. ++ san_parts = san.downcase.split(".") ++ ++ # TODO: this behavior should probably be more strict ++ return san == hostname if san_parts.size < 2 ++ ++ # Matching is case-insensitive. ++ host_parts = hostname.downcase.split(".") ++ ++ # RFC 6125, section 6.4.3, subitem 2. ++ # If the wildcard character is the only character of the left-most ++ # label in the presented identifier, the client SHOULD NOT compare ++ # against anything but the left-most label of the reference ++ # identifier (e.g., *.example.com would match foo.example.com but ++ # not bar.foo.example.com or example.com). ++ return false unless san_parts.size == host_parts.size ++ ++ # RFC 6125, section 6.4.3, subitem 1. ++ # The client SHOULD NOT attempt to match a presented identifier in ++ # which the wildcard character comprises a label other than the ++ # left-most label (e.g., do not match bar.*.example.net). ++ return false unless verify_wildcard(host_parts.shift, san_parts.shift) ++ ++ san_parts.join(".") == host_parts.join(".") ++ end ++ module_function :verify_hostname ++ ++ def verify_wildcard(domain_component, san_component) # :nodoc: ++ parts = san_component.split("*", -1) ++ ++ return false if parts.size > 2 ++ return san_component == domain_component if parts.size == 1 ++ ++ # RFC 6125, section 6.4.3, subitem 3. ++ # The client SHOULD NOT attempt to match a presented identifier ++ # where the wildcard character is embedded within an A-label or ++ # U-label of an internationalized domain name. ++ return false if domain_component.start_with?("xn--") && san_component != "*" ++ ++ parts[0].length + parts[1].length < domain_component.length && ++ domain_component.start_with?(parts[0]) && ++ domain_component.end_with?(parts[1]) ++ end ++ module_function :verify_wildcard ++ + class SSLSocket + include Buffering + include SocketForwarder + include Nonblock + ++ ## ++ # Perform hostname verification after an SSL connection is established ++ # ++ # This method MUST be called after calling #connect to ensure that the ++ # hostname of a remote peer has been verified. + def post_connection_check(hostname) + unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname) + raise SSLError, "hostname was not match with the server certificate" +--- a/test/openssl/test_ssl.rb ++++ b/test/openssl/test_ssl.rb +@@ -560,6 +560,156 @@ class OpenSSL::TestSSL < Test::Unit::Tes + end + end + ++ def test_verify_hostname ++ assert_equal(true, OpenSSL::SSL.verify_hostname("www.example.com", "*.example.com")) ++ assert_equal(false, OpenSSL::SSL.verify_hostname("www.subdomain.example.com", "*.example.com")) ++ end ++ ++ def test_verify_wildcard ++ assert_equal(false, OpenSSL::SSL.verify_wildcard("foo", "x*")) ++ assert_equal(true, OpenSSL::SSL.verify_wildcard("foo", "foo")) ++ assert_equal(true, OpenSSL::SSL.verify_wildcard("foo", "f*")) ++ assert_equal(true, OpenSSL::SSL.verify_wildcard("foo", "*")) ++ assert_equal(false, OpenSSL::SSL.verify_wildcard("abc*bcd", "abcd")) ++ assert_equal(false, OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", "x*")) ++ assert_equal(false, OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", "*--qdk4b9b")) ++ assert_equal(true, OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", "xn--qdk4b9b")) ++ end ++ ++ # Comments in this test is excerpted from http://tools.ietf.org/html/rfc6125#page-27 ++ def test_post_connection_check_wildcard_san ++ # case-insensitive ASCII comparison ++ # RFC 6125, section 6.4.1 ++ # ++ # "..matching of the reference identifier against the presented identifier ++ # is performed by comparing the set of domain name labels using a ++ # case-insensitive ASCII comparison, as clarified by [DNS-CASE] (e.g., ++ # "WWW.Example.Com" would be lower-cased to "www.example.com" for ++ # comparison purposes) ++ assert_equal(true, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_san('DNS:*.example.com'), 'www.example.com')) ++ assert_equal(true, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_san('DNS:*.Example.COM'), 'www.example.com')) ++ assert_equal(true, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_san('DNS:*.example.com'), 'WWW.Example.COM')) ++ # 1. The client SHOULD NOT attempt to match a presented identifier in ++ # which the wildcard character comprises a label other than the ++ # left-most label (e.g., do not match bar.*.example.net). ++ assert_equal(false, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_san('DNS:www.*.com'), 'www.example.com')) ++ # 2. If the wildcard character is the only character of the left-most ++ # label in the presented identifier, the client SHOULD NOT compare ++ # against anything but the left-most label of the reference ++ # identifier (e.g., *.example.com would match foo.example.com but ++ # not bar.foo.example.com or example.com). ++ assert_equal(true, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_san('DNS:*.example.com'), 'foo.example.com')) ++ assert_equal(false, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_san('DNS:*.example.com'), 'bar.foo.example.com')) ++ # 3. The client MAY match a presented identifier in which the wildcard ++ # character is not the only character of the label (e.g., ++ # baz*.example.net and *baz.example.net and b*z.example.net would ++ # be taken to match baz1.example.net and foobaz.example.net and ++ # buzz.example.net, respectively). ... ++ assert_equal(true, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_san('DNS:baz*.example.com'), 'baz1.example.com')) ++ assert_equal(true, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_san('DNS:*baz.example.com'), 'foobaz.example.com')) ++ assert_equal(true, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_san('DNS:b*z.example.com'), 'buzz.example.com')) ++ # Section 6.4.3 of RFC6125 states that client should NOT match identifier ++ # where wildcard is other than left-most label. ++ # ++ # Also implicitly mentions the wildcard character only in singular form, ++ # and discourages matching against more than one wildcard. ++ # ++ # See RFC 6125, section 7.2, subitem 2. ++ assert_equal(false, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_san('DNS:*b*.example.com'), 'abc.example.com')) ++ assert_equal(false, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_san('DNS:*b*.example.com'), 'ab.example.com')) ++ assert_equal(false, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_san('DNS:*b*.example.com'), 'bc.example.com')) ++ # ... However, the client SHOULD NOT ++ # attempt to match a presented identifier where the wildcard ++ # character is embedded within an A-label or U-label [IDNA-DEFS] of ++ # an internationalized domain name [IDNA-PROTO]. ++ assert_equal(true, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_san('DNS:xn*.example.com'), 'xn1ca.example.com')) ++ # part of A-label ++ assert_equal(false, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_san('DNS:xn--*.example.com'), 'xn--1ca.example.com')) ++ # part of U-label ++ # dNSName in RFC5280 is an IA5String so U-label should NOT be allowed ++ # regardless of wildcard. ++ # ++ # See Section 7.2 of RFC 5280: ++ # IA5String is limited to the set of ASCII characters. ++ assert_equal(false, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_san('DNS:े*.example.com'), 'े1.example.com')) ++ end ++ ++ def test_post_connection_check_wildcard_cn ++ assert_equal(true, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_name('*.example.com'), 'www.example.com')) ++ assert_equal(true, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_name('*.Example.COM'), 'www.example.com')) ++ assert_equal(true, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_name('*.example.com'), 'WWW.Example.COM')) ++ assert_equal(false, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_name('www.*.com'), 'www.example.com')) ++ assert_equal(true, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_name('*.example.com'), 'foo.example.com')) ++ assert_equal(false, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_name('*.example.com'), 'bar.foo.example.com')) ++ assert_equal(true, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_name('baz*.example.com'), 'baz1.example.com')) ++ assert_equal(true, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_name('*baz.example.com'), 'foobaz.example.com')) ++ assert_equal(true, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_name('b*z.example.com'), 'buzz.example.com')) ++ # Section 6.4.3 of RFC6125 states that client should NOT match identifier ++ # where wildcard is other than left-most label. ++ # ++ # Also implicitly mentions the wildcard character only in singular form, ++ # and discourages matching against more than one wildcard. ++ # ++ # See RFC 6125, section 7.2, subitem 2. ++ assert_equal(false, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_name('*b*.example.com'), 'abc.example.com')) ++ assert_equal(false, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_name('*b*.example.com'), 'ab.example.com')) ++ assert_equal(false, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_name('*b*.example.com'), 'bc.example.com')) ++ assert_equal(true, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_name('xn*.example.com'), 'xn1ca.example.com')) ++ assert_equal(false, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_name('xn--*.example.com'), 'xn--1ca.example.com')) ++ # part of U-label ++ # Subject in RFC5280 states case-insensitive ASCII comparison. ++ # ++ # See Section 7.2 of RFC 5280: ++ # IA5String is limited to the set of ASCII characters. ++ assert_equal(false, OpenSSL::SSL.verify_certificate_identity( ++ create_cert_with_name('े*.example.com'), 'े1.example.com')) ++ end ++ ++ def create_cert_with_san(san) ++ ef = OpenSSL::X509::ExtensionFactory.new ++ cert = OpenSSL::X509::Certificate.new ++ cert.subject = OpenSSL::X509::Name.parse("/DC=some/DC=site/CN=Some Site") ++ ext = ef.create_ext('subjectAltName', san) ++ cert.add_extension(ext) ++ cert ++ end ++ ++ def create_cert_with_name(name) ++ cert = OpenSSL::X509::Certificate.new ++ cert.subject = OpenSSL::X509::Name.new([['DC', 'some'], ['DC', 'site'], ['CN', name]]) ++ cert ++ end ++ ++ + end + + end diff --git a/gnu/packages/patches/ruby-1.8-CVE-2017-0898.patch b/gnu/packages/patches/ruby-1.8-CVE-2017-0898.patch new file mode 100644 index 000000000..aba4d356a --- /dev/null +++ b/gnu/packages/patches/ruby-1.8-CVE-2017-0898.patch @@ -0,0 +1,110 @@ +Fix CVE-2017-0898: + +https://www.ruby-lang.org/en/news/2017/09/14/sprintf-buffer-underrun-cve-2017-0898/ +https://bugs.ruby-lang.org/issues/13499 +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-0898 +https://security-tracker.debian.org/tracker/CVE-2017-0898 + +Patch copied from snapshot.debian.org: + +https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz + +Description: security fix for CVE-2017-0898 + +Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=875936 +Reviewed-By: anarcat +Last-Update: 2017-09-26 +Origin: OpenBSD, https://raw.githubusercontent.com/openbsd/ports/master/lang/ruby/1.8/patches/patch-sprintf_c + +$OpenBSD: patch-sprintf_c,v 1.1 2017/09/16 22:54:58 jeremy Exp $ + +--- a/sprintf.c ++++ b/sprintf.c +@@ -728,6 +728,8 @@ rb_str_format(argc, argv, fmt) + #if defined(_WIN32) && !defined(__BORLANDC__) + if (isnan(fval) || isinf(fval)) { + const char *expr; ++ int elen; ++ char sign = '\0'; + + if (isnan(fval)) { + expr = "NaN"; +@@ -736,51 +738,40 @@ rb_str_format(argc, argv, fmt) + expr = "Inf"; + } + need = strlen(expr); +- if ((!isnan(fval) && fval < 0.0) || (flags & FPLUS)) +- need++; +- else if (flags & FSPACE) +- need++; ++ elen = need; ++ i = 0; ++ if (!isnan(fval) && fval < 0.0) ++ sign = '-'; ++ else if (flags & (FPLUS|FSPACE)) ++ sign = (flags & FPLUS) ? '+' : ' '; ++ if (sign) ++ ++need; + if ((flags & FWIDTH) && need < width) + need = width; + +- CHECK(need); +- sprintf(&buf[blen], "%*s", need, ""); ++#define FILL(c, l) do { \ ++ if ((l) <= 0) break;\ ++ CHECK(l);\ ++ FILL_(c, l);\ ++} while (0) ++ ++#define FILL_(c, l) do { \ ++ memset(&buf[blen], (c), (l));\ ++ blen += (l);\ ++} while (0) ++ ++ ++ FILL(' ', need); + if (flags & FMINUS) { +- if (!isnan(fval) && fval < 0.0) +- buf[blen++] = '-'; +- else if (flags & FPLUS) +- buf[blen++] = '+'; +- else if (flags & FSPACE) +- blen++; +- strncpy(&buf[blen], expr, strlen(expr)); +- } +- else if (flags & FZERO) { +- if (!isnan(fval) && fval < 0.0) { +- buf[blen++] = '-'; +- need--; +- } +- else if (flags & FPLUS) { +- buf[blen++] = '+'; +- need--; +- } +- else if (flags & FSPACE) { +- blen++; +- need--; +- } +- while (need-- - strlen(expr) > 0) { +- buf[blen++] = '0'; +- } +- strncpy(&buf[blen], expr, strlen(expr)); ++ if (sign) ++ buf[blen - need--] = sign; ++ memcpy(&buf[blen - need], expr, elen); + } + else { +- if (!isnan(fval) && fval < 0.0) +- buf[blen + need - strlen(expr) - 1] = '-'; +- else if (flags & FPLUS) +- buf[blen + need - strlen(expr) - 1] = '+'; +- strncpy(&buf[blen + need - strlen(expr)], expr, +- strlen(expr)); ++ if (sign) ++ buf[blen - elen - 1] = sign; ++ memcpy(&buf[blen - elen], expr, elen); + } +- blen += strlen(&buf[blen]); + break; + } + #endif /* defined(_WIN32) && !defined(__BORLANDC__) */ diff --git a/gnu/packages/patches/ruby-1.8-CVE-2017-10784.patch b/gnu/packages/patches/ruby-1.8-CVE-2017-10784.patch new file mode 100644 index 000000000..4f13f94ee --- /dev/null +++ b/gnu/packages/patches/ruby-1.8-CVE-2017-10784.patch @@ -0,0 +1,99 @@ +Fix CVE-2017-10784: + +https://www.ruby-lang.org/en/news/2017/09/14/webrick-basic-auth-escape-sequence-injection-cve-2017-10784/ +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-10784 +https://security-tracker.debian.org/tracker/CVE-2017-10784 + +Patch copied from snapshot.debian.org: + +https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz + +From 6617c41292b7d1e097abb8fdb0cab9ddd83c77e7 Mon Sep 17 00:00:00 2001 +From: mame +Date: Thu, 14 Sep 2017 11:16:23 +0000 +Subject: [PATCH] lib/webrick/log.rb: sanitize any type of logs + +It had failed to sanitize some type of exception messages. Reported and +patched by Yusuke Endoh (mame) at https://hackerone.com/reports/223363 + +Patch modified to backport to Ruby 1.8.7.358 for the Debian LTS +project by anarcat. + +git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59897 b2dd03c8-39d4-4d8f-98ff-823fe69b080e +--- + lib/webrick/httpstatus.rb | 4 ---- + lib/webrick/log.rb | 4 ++-- + test/webrick/test_httpauth.rb | 36 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 38 insertions(+), 6 deletions(-) + +--- a/lib/webrick/httpstatus.rb ++++ b/lib/webrick/httpstatus.rb +@@ -13,10 +13,6 @@ module WEBrick + module HTTPStatus + + class Status < StandardError +- def initialize(*args) +- args[0] = AccessLog.escape(args[0]) unless args.empty? +- super(*args) +- end + class << self + attr_reader :code, :reason_phrase + end +--- a/lib/webrick/log.rb ++++ b/lib/webrick/log.rb +@@ -61,10 +61,10 @@ module WEBrick + + def format(arg) + str = if arg.is_a?(Exception) +- "#{arg.class}: #{arg.message}\n\t" << ++ "#{arg.class}: #{AccessLog.escape(arg.message)}\n\t" << + arg.backtrace.join("\n\t") << "\n" + elsif arg.respond_to?(:to_str) +- arg.to_str ++ AccessLog.escape(arg.to_str) + else + arg.inspect + end +--- a/test/webrick/test_httpauth.rb ++++ b/test/webrick/test_httpauth.rb +@@ -79,4 +79,40 @@ class TestWEBrickHTTPAuth < Test::Unit:: + } + tmpfile.close(true) + end ++ ++ def test_bad_username_with_control_characters ++ log_tester = lambda {|log, access_log| ++ assert_equal(2, log.length) ++ assert_match(/ERROR Basic WEBrick's realm: foo\\ebar: the user is not allowed./, log[0]) ++ assert_match(/ERROR WEBrick::HTTPStatus::Unauthorized/, log[1]) ++ } ++ TestWEBrick.start_httpserver{|server, addr, port, log| ++ realm = "WEBrick's realm" ++ path = "/basic_auth" ++ ++ Tempfile.open("test_webrick_auth") { |tmpfile| ++ tmpfile.close ++ tmp_pass = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path) ++ tmp_pass.set_passwd(realm, "webrick", "supersecretpassword") ++ tmp_pass.set_passwd(realm, "foo", "supersecretpassword") ++ tmp_pass.flush ++ ++ htpasswd = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path) ++ users = [] ++ htpasswd.each{|user, pass| users << user } ++ server.mount_proc(path){|req, res| ++ auth = WEBrick::HTTPAuth::BasicAuth.new( ++ :Realm => realm, :UserDB => htpasswd, ++ :Logger => server.logger ++ ) ++ auth.authenticate(req, res) ++ res.body = "hoge" ++ } ++ http = Net::HTTP.new(addr, port) ++ g = Net::HTTP::Get.new(path) ++ g.basic_auth("foo\ebar", "passwd") ++ http.request(g){|res| assert_not_equal("hoge", res.body, log.call) } ++ } ++ } ++ end + end diff --git a/gnu/packages/patches/ruby-1.8-CVE-2017-17405.patch b/gnu/packages/patches/ruby-1.8-CVE-2017-17405.patch new file mode 100644 index 000000000..5882946cb --- /dev/null +++ b/gnu/packages/patches/ruby-1.8-CVE-2017-17405.patch @@ -0,0 +1,62 @@ +Fix CVE-2017-17405: + +https://www.ruby-lang.org/en/news/2017/12/14/net-ftp-command-injection-cve-2017-17405/ +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-17405 +https://security-tracker.debian.org/tracker/CVE-2017-17405 + +Patch copied from snapshot.debian.org: + +https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz + +From: =?utf-8?q?Guido_G=C3=BCnther?= +Date: Sun, 24 Dec 2017 16:16:29 +0100 +Subject: CVE-2017-17405: command injection attacks via Net::FTP + +--- + lib/net/ftp.rb | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/lib/net/ftp.rb b/lib/net/ftp.rb +index 369aba8..bfa6c4b 100644 +--- a/lib/net/ftp.rb ++++ b/lib/net/ftp.rb +@@ -494,10 +494,10 @@ module Net + blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data + if @resume + rest_offset = File.size?(localfile) +- f = open(localfile, "a") ++ f = File.open(localfile, "a") + else + rest_offset = nil +- f = open(localfile, "w") ++ f = File.open(localfile, "w") + end + begin + f.binmode +@@ -516,7 +516,7 @@ module Net + # line at a time. + # + def gettextfile(remotefile, localfile = File.basename(remotefile), &block) # :yield: line +- f = open(localfile, "w") ++ f = File.open(localfile, "w") + begin + retrlines("RETR " + remotefile) do |line| + f.puts(line) +@@ -556,7 +556,7 @@ module Net + else + rest_offset = nil + end +- f = open(localfile) ++ f = File.open(localfile) + begin + f.binmode + storbinary("STOR " + remotefile, f, blocksize, rest_offset, &block) +@@ -571,7 +571,7 @@ module Net + # passing in the transmitted data one line at a time. + # + def puttextfile(localfile, remotefile = File.basename(localfile), &block) # :yield: line +- f = open(localfile) ++ f = File.open(localfile) + begin + storlines("STOR " + remotefile, f, &block) + ensure diff --git a/gnu/packages/patches/ruby-1.8-CVE-2017-17742-pre.patch b/gnu/packages/patches/ruby-1.8-CVE-2017-17742-pre.patch new file mode 100644 index 000000000..2e5a3a776 --- /dev/null +++ b/gnu/packages/patches/ruby-1.8-CVE-2017-17742-pre.patch @@ -0,0 +1,161 @@ +Prepare to fix CVE-2017-17742: + +Patch copied from snapshot.debian.org: + +https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz + +Index: ruby1.9.1/test/webrick/test_httpresponse.rb +=================================================================== +--- /dev/null ++++ ruby1.9.1/test/webrick/test_httpresponse.rb +@@ -0,0 +1,150 @@ ++require "webrick" ++require "minitest/autorun" ++require "stringio" ++ ++module WEBrick ++ class TestHTTPResponse < MiniTest::Unit::TestCase ++ class FakeLogger ++ attr_reader :messages ++ ++ def initialize ++ @messages = [] ++ end ++ ++ def warn msg ++ @messages << msg ++ end ++ end ++ ++ attr_reader :config, :logger, :res ++ ++ def setup ++ super ++ @logger = FakeLogger.new ++ @config = Config::HTTP ++ @config[:Logger] = logger ++ @res = HTTPResponse.new config ++ @res.keep_alive = true ++ end ++ ++ def test_304_does_not_log_warning ++ res.status = 304 ++ res.setup_header ++ assert_equal 0, logger.messages.length ++ end ++ ++ def test_204_does_not_log_warning ++ res.status = 204 ++ res.setup_header ++ ++ assert_equal 0, logger.messages.length ++ end ++ ++ def test_1xx_does_not_log_warnings ++ res.status = 105 ++ res.setup_header ++ ++ assert_equal 0, logger.messages.length ++ end ++ ++ def test_send_body_io ++ IO.pipe {|body_r, body_w| ++ body_w.write 'hello' ++ body_w.close ++ ++ @res.body = body_r ++ ++ IO.pipe {|r, w| ++ ++ @res.send_body w ++ ++ w.close ++ ++ assert_equal 'hello', r.read ++ } ++ } ++ assert_equal 0, logger.messages.length ++ end ++ ++ def test_send_body_string ++ @res.body = 'hello' ++ ++ IO.pipe {|r, w| ++ @res.send_body w ++ ++ w.close ++ ++ assert_equal 'hello', r.read ++ } ++ assert_equal 0, logger.messages.length ++ end ++ ++ def test_send_body_string_io ++ @res.body = StringIO.new 'hello' ++ ++ IO.pipe {|r, w| ++ @res.send_body w ++ ++ w.close ++ ++ assert_equal 'hello', r.read ++ } ++ assert_equal 0, logger.messages.length ++ end ++ ++ def test_send_body_io_chunked ++ @res.chunked = true ++ ++ IO.pipe {|body_r, body_w| ++ ++ body_w.write 'hello' ++ body_w.close ++ ++ @res.body = body_r ++ ++ IO.pipe {|r, w| ++ @res.send_body w ++ ++ w.close ++ ++ r.binmode ++ assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read ++ } ++ } ++ assert_equal 0, logger.messages.length ++ end ++ ++ def test_send_body_string_chunked ++ @res.chunked = true ++ ++ @res.body = 'hello' ++ ++ IO.pipe {|r, w| ++ @res.send_body w ++ ++ w.close ++ ++ r.binmode ++ assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read ++ } ++ assert_equal 0, logger.messages.length ++ end ++ ++ def test_send_body_string_io_chunked ++ @res.chunked = true ++ ++ @res.body = StringIO.new 'hello' ++ ++ IO.pipe {|r, w| ++ @res.send_body w ++ ++ w.close ++ ++ r.binmode ++ assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read ++ } ++ assert_equal 0, logger.messages.length ++ end ++ end ++end ++ diff --git a/gnu/packages/patches/ruby-1.8-CVE-2017-17742.patch b/gnu/packages/patches/ruby-1.8-CVE-2017-17742.patch new file mode 100644 index 000000000..0c15073c8 --- /dev/null +++ b/gnu/packages/patches/ruby-1.8-CVE-2017-17742.patch @@ -0,0 +1,132 @@ +Fix CVE-2017-17742: + +https://www.ruby-lang.org/en/news/2018/03/28/http-response-splitting-in-webrick-cve-2017-17742/ +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-17742 +https://security-tracker.debian.org/tracker/CVE-2017-17742 + +Patch copied from snapshot.debian.org: + +https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz + +From bbda1a027475bf7ce5e1a9583a7b55d0be71c8fe Mon Sep 17 00:00:00 2001 +From: usa +Date: Wed, 28 Mar 2018 14:50:27 +0000 +Subject: [PATCH 3/3] merge revision(s) 62968: + + webrick: prevent response splitting and header injection + + Original patch by tenderlove (with minor style adjustments). + + * lib/webrick/httpresponse.rb (send_header): call check_header + (check_header): raise on embedded CRLF in header value + * test/webrick/test_httpresponse.rb + (test_prevent_response_splitting_headers): new test + * (test_prevent_response_splitting_cookie_headers): ditto + +git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_2@63022 b2dd03c8-39d4-4d8f-98ff-823fe69b080e +--- + ChangeLog | 12 ++++++++++++ + lib/webrick/httpresponse.rb | 27 +++++++++++++++++++++++++-- + test/webrick/test_httpresponse.rb | 22 ++++++++++++++++++++++ + version.h | 2 +- + 4 files changed, 60 insertions(+), 3 deletions(-) + +Index: ruby1.8/lib/webrick/httpresponse.rb +=================================================================== +--- ruby1.8.orig/lib/webrick/httpresponse.rb ++++ ruby1.8/lib/webrick/httpresponse.rb +@@ -16,6 +16,9 @@ require 'webrick/httpstatus' + + module WEBrick + class HTTPResponse ++ class InvalidHeader < StandardError ++ end ++ + BUFSIZE = 1024*4 + + attr_reader :http_version, :status, :header +@@ -171,14 +174,19 @@ module WEBrick + data = status_line() + @header.each{|key, value| + tmp = key.gsub(/\bwww|^te$|\b\w/){|s| s.upcase } +- data << "#{tmp}: #{value}" << CRLF ++ data << "#{tmp}: #{check_header(value)}" << CRLF + } + @cookies.each{|cookie| +- data << "Set-Cookie: " << cookie.to_s << CRLF ++ data << "Set-Cookie: " << check_header(cookie.to_s) << CRLF + } + data << CRLF + _write_data(socket, data) + end ++ rescue InvalidHeader => e ++ @header.clear ++ @cookies.clear ++ set_error e ++ retry + end + + def send_body(socket) # :nodoc: +@@ -225,6 +233,22 @@ module WEBrick + host, port = @config[:ServerName], @config[:Port] + end + ++ error_body(backtrace, ex, host, port) ++ end ++ ++ private ++ ++ def check_header(header_value) ++ if header_value =~ /\r\n/ ++ raise InvalidHeader ++ else ++ header_value ++ end ++ end ++ ++ # :stopdoc: ++ ++ def error_body(backtrace, ex, host, port) + @body = '' + @body << <<-_end_of_html_ + +Index: ruby1.8/test/webrick/test_httpresponse.rb +=================================================================== +--- ruby1.8.orig/test/webrick/test_httpresponse.rb ++++ ruby1.8/test/webrick/test_httpresponse.rb +@@ -1,6 +1,7 @@ + require "webrick" + require "minitest/autorun" + require "stringio" ++require "net/http" + + module WEBrick + class TestHTTPResponse < MiniTest::Unit::TestCase +@@ -27,6 +28,27 @@ module WEBrick + @res.keep_alive = true + end + ++ def test_prevent_response_splitting_headers ++ res['X-header'] = "malicious\r\nCookie: hack" ++ io = StringIO.new ++ res.send_response io ++ io.rewind ++ res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io)) ++ assert_equal '500', res.code ++ refute_match 'hack', io.string ++ end ++ ++ def test_prevent_response_splitting_cookie_headers ++ user_input = "malicious\r\nCookie: hack" ++ res.cookies << WEBrick::Cookie.new('author', user_input) ++ io = StringIO.new ++ res.send_response io ++ io.rewind ++ res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io)) ++ assert_equal '500', res.code ++ refute_match 'hack', io.string ++ end ++ + def test_304_does_not_log_warning + res.status = 304 + res.setup_header diff --git a/gnu/packages/patches/ruby-1.8-CVE-2017-17790.patch b/gnu/packages/patches/ruby-1.8-CVE-2017-17790.patch new file mode 100644 index 000000000..d1faa3a4d --- /dev/null +++ b/gnu/packages/patches/ruby-1.8-CVE-2017-17790.patch @@ -0,0 +1,32 @@ +Fix CVE-2017-17790: + +https://github.com/ruby/ruby/pull/1777 +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-17790 +https://security-tracker.debian.org/tracker/CVE-2017-17790 + +Patch copied from snapshot.debian.org: + +https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz + +From: =?utf-8?q?Guido_G=C3=BCnther?= +Date: Sun, 24 Dec 2017 16:19:08 +0100 +Subject: CVE-2017-17790: Fixed command injection in + Resolv::Hosts#lazy_initialize + +--- + lib/resolv.rb | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/resolv.rb b/lib/resolv.rb +index 5cc0313..417fe0c 100644 +--- a/lib/resolv.rb ++++ b/lib/resolv.rb +@@ -186,7 +186,7 @@ class Resolv + unless @initialized + @name2addr = {} + @addr2name = {} +- open(@filename) {|f| ++ File.open(@filename) {|f| + f.each {|line| + line.sub!(/#.*/, '') + addr, hostname, *aliases = line.split(/\s+/) diff --git a/gnu/packages/patches/ruby-1.8-CVE-2018-6914.patch b/gnu/packages/patches/ruby-1.8-CVE-2018-6914.patch new file mode 100644 index 000000000..75705db68 --- /dev/null +++ b/gnu/packages/patches/ruby-1.8-CVE-2018-6914.patch @@ -0,0 +1,99 @@ +Fix CVE-2018-6914: + +https://www.ruby-lang.org/en/news/2018/03/28/unintentional-file-and-directory-creation-with-directory-traversal-cve-2018-6914/ +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-6914 +https://security-tracker.debian.org/tracker/CVE-2018-6914 + +Patch copied from snapshot.debian.org: + +https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz + +Origin: backport, e9ddf2ba41a0bffe1047e33576affd48808c5d0b +Reviewed-by: Santiago R.R + +From e9ddf2ba41a0bffe1047e33576affd48808c5d0b Mon Sep 17 00:00:00 2001 +From: usa +Date: Wed, 28 Mar 2018 14:34:14 +0000 +Subject: [PATCH 2/4] merge revision(s) 62990: + + Ignore file separator from tmpfile/tmpdir name. + + From: SHIBATA Hiroshi + +git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_2@63017 b2dd03c8-39d4-4d8f-98ff-823fe69b080e +--- + ChangeLog | 4 ++++ + lib/tmpdir.rb | 2 ++ + test/test_tempfile.rb | 28 +++++++++++++++++++++++++++- + test/test_tmpdir.rb | 34 ++++++++++++++++++++++++++++++++++ + version.h | 2 +- + 5 files changed, 68 insertions(+), 2 deletions(-) + +Index: ruby1.8/lib/tmpdir.rb +=================================================================== +--- ruby1.8.orig/lib/tmpdir.rb ++++ ruby1.8/lib/tmpdir.rb +@@ -110,6 +110,8 @@ class Dir + else + raise ArgumentError, "unexpected prefix_suffix: #{prefix_suffix.inspect}" + end ++ prefix = prefix.delete("#{File::SEPARATOR}#{File::ALT_SEPARATOR}") ++ suffix &&= suffix.delete("#{File::SEPARATOR}#{File::ALT_SEPARATOR}") + tmpdir ||= Dir.tmpdir + t = Time.now.strftime("%Y%m%d") + n = nil +Index: ruby1.8/test/test_tempfile.rb +=================================================================== +--- /dev/null ++++ ruby1.8/test/test_tempfile.rb +@@ -0,0 +1,37 @@ ++require 'test/unit' ++require 'tempfile' ++require './ruby/envutil' ++ ++class TestTempfile < Test::Unit::TestCase ++ def initialize(*) ++ super ++ @tempfile = nil ++ end ++ ++ TRAVERSAL_PATH = Array.new(Dir.pwd.split('/').count, '..').join('/') + Dir.pwd + '/' ++ ++ def test_open_traversal_dir ++ expect = Dir.glob(TRAVERSAL_PATH + '*').count ++ t = Tempfile.open([TRAVERSAL_PATH, 'foo']) ++ actual = Dir.glob(TRAVERSAL_PATH + '*').count ++ assert_equal expect, actual ++ ensure ++ t.close! ++ end ++ ++ def test_new_traversal_dir ++ expect = Dir.glob(TRAVERSAL_PATH + '*').count ++ t = Tempfile.new(TRAVERSAL_PATH + 'foo') ++ actual = Dir.glob(TRAVERSAL_PATH + '*').count ++ assert_equal expect, actual ++ ensure ++ t.close! ++ end ++ ++ def test_create_traversal_dir ++ expect = Dir.glob(TRAVERSAL_PATH + '*').count ++ Tempfile.create(TRAVERSAL_PATH + 'foo') ++ actual = Dir.glob(TRAVERSAL_PATH + '*').count ++ assert_equal expect, actual ++ end ++end +Index: ruby1.8/lib/tempfile.rb +=================================================================== +--- ruby1.8.orig/lib/tempfile.rb ++++ ruby1.8/lib/tempfile.rb +@@ -79,6 +79,8 @@ class Tempfile < DelegateClass(File) + else + prefix, suffix = basename, '' + end ++ prefix = prefix.delete("#{File::SEPARATOR}#{File::ALT_SEPARATOR}") ++ suffix &&= suffix.delete("#{File::SEPARATOR}#{File::ALT_SEPARATOR}") + + t = Time.now.strftime("%Y%m%d") + path = "#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}-#{n}#{suffix}" diff --git a/gnu/packages/patches/ruby-1.8-CVE-2018-8777+CVE-2017-17742-pre.patch b/gnu/packages/patches/ruby-1.8-CVE-2018-8777+CVE-2017-17742-pre.patch new file mode 100644 index 000000000..76d74e48e --- /dev/null +++ b/gnu/packages/patches/ruby-1.8-CVE-2018-8777+CVE-2017-17742-pre.patch @@ -0,0 +1,366 @@ +Prepare to fix CVE-2018-8777 and CVE-2017-17742: + +Patch copied from snapshot.debian.org: + +https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz + +From 19cb3fa9e0621004a9dc08e90884c512c75dac57 Mon Sep 17 00:00:00 2001 +From: usa +Date: Wed, 28 Mar 2018 14:44:20 +0000 +Subject: [PATCH 1/3] merge revision(s) 60584,62954-62959,63008: +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + + webrick: support Proc objects as body responses + + * lib/webrick/httpresponse.rb (send_body): call send_body_proc + (send_body_proc): new method + (class ChunkedWrapper): new class + + * test/webrick/test_httpresponse.rb (test_send_body_proc): new test + (test_send_body_proc_chunked): ditto + [Feature #855] + + webrick: favor .write over << method + + This will make the next change to use IO.copy_stream + easier-to-read. When we can drop Ruby 2.4 support in a few + years, this will allow us to use writev(2) with multiple + arguments for headers and chunked responses. + + * lib/webrick/cgi.rb (write): new wrapper method + lib/webrick/httpresponse.rb: (send_header): use socket.write + (send_body_io): ditto + (send_body_string): ditto + (send_body_proc): ditto + (_write_data): ditto + (ChunkedWrapper#write): ditto + (_send_file): ditto + ------------------------------------------------------------------------ + r62954 | normal | 2018-03-28 17:05:52 +0900 (ौओख, 28 3 2018) | 14 lines + + webrick/httpresponse: IO.copy_stream for regular files + + Remove the redundant _send_file method since its functionality + is unnecessary with IO.copy_stream. IO.copy_stream also allows + the use of sendfile under some OSes to speed up copies to + non-TLS sockets. + + Testing with "curl >/dev/null" and "ruby -run -e httpd" to + read a 1G file over Linux loopback reveals a reduction from + around ~0.770 to ~0.490 seconds on the client side. + + * lib/webrick/httpresponse.rb (send_body_io): use IO.copy_stream + (_send_file): remove + [Feature #14237] + ------------------------------------------------------------------------ + r62955 | normal | 2018-03-28 17:05:57 +0900 (ौओख, 28 3 2018) | 10 lines + + webrick: use IO.copy_stream for single range response + + This is also compatible with range responses generated + by Rack::File (tested with rack 2.0.3). + + * lib/webrick/httpresponse.rb (send_body_io): use Content-Range + * lib/webrick/httpservlet/filehandler.rb (make_partial_content): + use File object for the single range case + * test/webrick/test_filehandler.rb (get_res_body): use send_body + to test result + ------------------------------------------------------------------------ + r62956 | normal | 2018-03-28 17:06:02 +0900 (ौओख, 28 3 2018) | 7 lines + + test/webrick/test_filehandler.rb: stricter multipart range test + + We need to ensure we generate compatibile output in + the face of future changes + + * test/webrick/test_filehandler.rb (test_make_partial_content): + check response body + ------------------------------------------------------------------------ + r62957 | normal | 2018-03-28 17:06:08 +0900 (ौओख, 28 3 2018) | 8 lines + + webrick: quiet warning for multi-part ranges + + Content-Length is ignored by WEBrick::HTTPResponse even if we + calculate it, so instead we chunk responses to HTTP/1.1 clients + and terminate HTTP/1.0 connections. + + * lib/webrick/httpservlet/filehandler.rb (make_partial_content): + quiet warning + ------------------------------------------------------------------------ + r62958 | normal | 2018-03-28 17:06:13 +0900 (ौओख, 28 3 2018) | 7 lines + + webrick/httpresponse: make ChunkedWrapper copy_stream-compatible + + The .write method needs to return the number of bytes written + to avoid confusing IO.copy_stream. + + * lib/webrick/httpresponse.rb (ChunkedWrapper#write): return bytes written + (ChunkedWrapper#<<): return self + ------------------------------------------------------------------------ + r62959 | normal | 2018-03-28 17:06:18 +0900 (ौओख, 28 3 2018) | 9 lines + + webrick: use IO.copy_stream for multipart response + + Use the new Proc response body feature to generate a multipart + range response dynamically. We use a flat array to minimize + object overhead as much as possible; as many ranges may fit + into an HTTP request header. + + * lib/webrick/httpservlet/filehandler.rb (multipart_body): new method + (make_partial_content): use multipart_body + + get rid of test error/failure on Windows introduced at r62955 + + * lib/webrick/httpresponse.rb (send_body_io): use seek if NotImplementedError + is raised in IO.copy_stream with offset. + + * lib/webrick/httpservlet/filehandler.rb (multipart_body): ditto. + + +git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_2@63020 b2dd03c8-39d4-4d8f-98ff-823fe69b080e +--- + ChangeLog | 98 ++++++++++++++++++++++++++++++++++ + lib/webrick/httpresponse.rb | 68 ++++++++++++++++------- + lib/webrick/httpservlet/filehandler.rb | 65 ++++++++++++++-------- + test/webrick/test_filehandler.rb | 31 +++++++---- + test/webrick/test_httpresponse.rb | 33 ++++++++++++ + version.h | 2 +- + 6 files changed, 244 insertions(+), 53 deletions(-) + +Index: ruby1.8/lib/webrick/httpresponse.rb +=================================================================== +--- ruby1.8.orig/lib/webrick/httpresponse.rb ++++ ruby1.8/lib/webrick/httpresponse.rb +@@ -181,10 +181,13 @@ module WEBrick + end + end + +- def send_body(socket) +- case @body +- when IO then send_body_io(socket) +- else send_body_string(socket) ++ def send_body(socket) # :nodoc: ++ if @body.respond_to? :readpartial then ++ send_body_io(socket) ++ elsif @body.respond_to?(:call) then ++ send_body_proc(socket) ++ else ++ send_body_string(socket) + end + end + +@@ -268,9 +271,20 @@ module WEBrick + end + _write_data(socket, "0#{CRLF}#{CRLF}") + else +- size = @header['content-length'].to_i +- _send_file(socket, @body, 0, size) +- @sent_size = size ++ if %r{\Abytes (\d+)-(\d+)/\d+\z} =~ @header['content-range'] ++ offset = $1.to_i ++ size = $2.to_i - offset + 1 ++ else ++ offset = nil ++ size = @header['content-length'] ++ size = size.to_i if size ++ end ++ begin ++ @sent_size = IO.copy_stream(@body, socket, size, offset) ++ rescue NotImplementedError ++ @body.seek(offset, IO::SEEK_SET) ++ @sent_size = IO.copy_stream(@body, socket, size) ++ end + end + ensure + @body.close +@@ -299,24 +313,41 @@ module WEBrick + end + end + +- def _send_file(output, input, offset, size) +- while offset > 0 +- sz = BUFSIZE < offset ? BUFSIZE : offset +- buf = input.read(sz) +- offset -= buf.size ++ def send_body_proc(socket) ++ if @request_method == "HEAD" ++ # do nothing ++ elsif chunked? ++ @body.call(ChunkedWrapper.new(socket, self)) ++ _write_data(socket, "0#{CRLF}#{CRLF}") ++ else ++ size = @header['content-length'].to_i ++ @body.call(socket) ++ @sent_size = size + end ++ end + +- if size == 0 +- while buf = input.read(BUFSIZE) +- _write_data(output, buf) +- end +- else +- while size > 0 +- sz = BUFSIZE < size ? BUFSIZE : size +- buf = input.read(sz) +- _write_data(output, buf) +- size -= buf.size +- end ++ class ChunkedWrapper ++ def initialize(socket, resp) ++ @socket = socket ++ @resp = resp ++ end ++ ++ def write(buf) ++ return 0 if buf.empty? ++ socket = @socket ++ @resp.instance_eval { ++ size = buf.bytesize ++ data = "#{size.to_s(16)}#{CRLF}#{buf}#{CRLF}" ++ _write_data(socket, data) ++ data.clear ++ @sent_size += size ++ size ++ } ++ end ++ ++ def <<(*buf) ++ write(buf) ++ self + end + end + +Index: ruby1.8/lib/webrick/httpservlet/filehandler.rb +=================================================================== +--- ruby1.8.orig/lib/webrick/httpservlet/filehandler.rb ++++ ruby1.8/lib/webrick/httpservlet/filehandler.rb +@@ -69,6 +69,35 @@ module WEBrick + return false + end + ++ # returns a lambda for webrick/httpresponse.rb send_body_proc ++ def multipart_body(body, parts, boundary, mtype, filesize) ++ lambda do |socket| ++ begin ++ begin ++ first = parts.shift ++ last = parts.shift ++ socket.write( ++ "--#{boundary}#{CRLF}" \ ++ "Content-Type: #{mtype}#{CRLF}" \ ++ "Content-Range: bytes #{first}-#{last}/#{filesize}#{CRLF}" \ ++ "#{CRLF}" ++ ) ++ ++ begin ++ IO.copy_stream(body, socket, last - first + 1, first) ++ rescue NotImplementedError ++ body.seek(first, IO::SEEK_SET) ++ IO.copy_stream(body, socket, last - first + 1) ++ end ++ socket.write(CRLF) ++ end while parts[0] ++ socket.write("--#{boundary}--#{CRLF}") ++ ensure ++ body.close ++ end ++ end ++ end ++ + def make_partial_content(req, res, filename, filesize) + mtype = HTTPUtils::mime_type(filename, @config[:MimeTypes]) + unless ranges = HTTPUtils::parse_range_header(req['range']) +@@ -79,37 +108,27 @@ module WEBrick + if ranges.size > 1 + time = Time.now + boundary = "#{time.sec}_#{time.usec}_#{Process::pid}" +- body = '' +- ranges.each{|range| +- first, last = prepare_range(range, filesize) +- next if first < 0 +- io.pos = first +- content = io.read(last-first+1) +- body << "--" << boundary << CRLF +- body << "Content-Type: #{mtype}" << CRLF +- body << "Content-Range: bytes #{first}-#{last}/#{filesize}" << CRLF +- body << CRLF +- body << content +- body << CRLF ++ parts = [] ++ ranges.each {|range| ++ prange = prepare_range(range, filesize) ++ next if prange[0] < 0 ++ parts.concat(prange) + } +- raise HTTPStatus::RequestRangeNotSatisfiable if body.empty? +- body << "--" << boundary << "--" << CRLF ++ raise HTTPStatus::RequestRangeNotSatisfiable if parts.empty? + res["content-type"] = "multipart/byteranges; boundary=#{boundary}" +- res.body = body ++ if req.http_version < '1.1' ++ res['connection'] = 'close' ++ else ++ res.chunked = true ++ end ++ res.body = multipart_body(io.dup, parts, boundary, mtype, filesize) + elsif range = ranges[0] + first, last = prepare_range(range, filesize) + raise HTTPStatus::RequestRangeNotSatisfiable if first < 0 +- if last == filesize - 1 +- content = io.dup +- content.pos = first +- else +- io.pos = first +- content = io.read(last-first+1) +- end + res['content-type'] = mtype + res['content-range'] = "bytes #{first}-#{last}/#{filesize}" + res['content-length'] = last - first + 1 +- res.body = content ++ res.body = io.dup + else + raise HTTPStatus::BadRequest + end +Index: ruby1.8/test/webrick/test_filehandler.rb +=================================================================== +--- ruby1.8.orig/test/webrick/test_filehandler.rb ++++ ruby1.8/test/webrick/test_filehandler.rb +@@ -14,7 +14,10 @@ class WEBrick::TestFileHandler < Test::U + end + + def get_res_body(res) +- return res.body.read rescue res.body ++ sio = StringIO.new ++ sio.binmode ++ res.send_body(sio) ++ sio.string + end + + def make_range_request(range_spec) +@@ -66,6 +69,23 @@ class WEBrick::TestFileHandler < Test::U + + res = make_range_response(filename, "bytes=0-0, -2") + assert_match(%r{^multipart/byteranges}, res["content-type"]) ++ body = get_res_body(res) ++ boundary = /; boundary=(.+)/.match(res['content-type'])[1] ++ off = filesize - 2 ++ last = filesize - 1 ++ ++ exp = "--#{boundary}\r\n" \ ++ "Content-Type: text/plain\r\n" \ ++ "Content-Range: bytes 0-0/#{filesize}\r\n" \ ++ "\r\n" \ ++ "#{IO.read(__FILE__, 1)}\r\n" \ ++ "--#{boundary}\r\n" \ ++ "Content-Type: text/plain\r\n" \ ++ "Content-Range: bytes #{off}-#{last}/#{filesize}\r\n" \ ++ "\r\n" \ ++ "#{IO.read(__FILE__, 2, off)}\r\n" \ ++ "--#{boundary}--\r\n" ++ assert_equal exp, body + end + + def test_filehandler diff --git a/gnu/packages/patches/ruby-1.8-CVE-2018-8777.patch b/gnu/packages/patches/ruby-1.8-CVE-2018-8777.patch new file mode 100644 index 000000000..5a279a4c7 --- /dev/null +++ b/gnu/packages/patches/ruby-1.8-CVE-2018-8777.patch @@ -0,0 +1,394 @@ +Fix CVE-2018-8777: + +https://www.ruby-lang.org/en/news/2018/03/28/large-request-dos-in-webrick-cve-2018-8777/ +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8777 +https://security-tracker.debian.org/tracker/CVE-2018-8777 + +Patch copied from snapshot.debian.org: + +https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz + +From a45622669bb1ff18d3ee9b411128acd839c4263e Mon Sep 17 00:00:00 2001 +From: usa +Date: Wed, 28 Mar 2018 14:47:30 +0000 +Subject: [PATCH 2/3] merge revision(s) 62960-62965: +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + + webrick: use IO.copy_stream for multipart response + + Use the new Proc response body feature to generate a multipart + range response dynamically. We use a flat array to minimize + object overhead as much as possible; as many ranges may fit + into an HTTP request header. + + * lib/webrick/httpservlet/filehandler.rb (multipart_body): new method + (make_partial_content): use multipart_body + ------------------------------------------------------------------------ + r62960 | normal | 2018-03-28 17:06:23 +0900 (ौओख, 28 3 2018) | 13 lines + + webrick/httprequest: limit request headers size + + We use the same 112 KB limit started (AFAIK) by Mongrel, Thin, + and Puma to prevent malicious users from using up all the memory + with a single request. This also limits the damage done by + excessive ranges in multipart Range: requests. + + Due to the way we rely on IO#gets and the desire to keep + the code simple, the actual maximum header may be 4093 bytes + larger than 112 KB, but we're splitting hairs at that point. + + * lib/webrick/httprequest.rb: define MAX_HEADER_LENGTH + (read_header): raise when headers exceed max length + ------------------------------------------------------------------------ + r62961 | normal | 2018-03-28 17:06:28 +0900 (ौओख, 28 3 2018) | 9 lines + + webrick/httpservlet/cgihandler: reduce memory use + + WEBrick::HTTPRequest#body can be passed a block to process the + body in chunks. Use this feature to avoid building a giant + string in memory. + + * lib/webrick/httpservlet/cgihandler.rb (do_GET): + avoid reading entire request body into memory + (do_POST is aliased to do_GET, so it handles bodies) + ------------------------------------------------------------------------ + r62962 | normal | 2018-03-28 17:06:34 +0900 (ौओख, 28 3 2018) | 7 lines + + webrick/httprequest: raise correct exception + + "BadRequest" alone does not resolve correctly, it is in the + HTTPStatus namespace. + + * lib/webrick/httprequest.rb (read_chunked): use correct exception + * test/webrick/test_httpserver.rb (test_eof_in_chunk): new test + ------------------------------------------------------------------------ + r62963 | normal | 2018-03-28 17:06:39 +0900 (ौओख, 28 3 2018) | 9 lines + + webrick/httprequest: use InputBufferSize for chunked requests + + While WEBrick::HTTPRequest#body provides a Proc interface + for streaming large request bodies, clients must not force + the server to use an excessively large chunk size. + + * lib/webrick/httprequest.rb (read_chunk_size): limit each + read and block.call to :InputBufferSize in config. + * test/webrick/test_httpserver.rb (test_big_chunks): new test + ------------------------------------------------------------------------ + r62964 | normal | 2018-03-28 17:06:44 +0900 (ौओख, 28 3 2018) | 9 lines + + webrick: add test for Digest auth-int + + No changes to the actual code, this is a new test for + a feature for which no tests existed. I don't understand + the Digest authentication code well at all, but this is + necessary for the subsequent change. + + * test/webrick/test_httpauth.rb (test_digest_auth_int): new test + (credentials_for_request): support bodies with POST + ------------------------------------------------------------------------ + r62965 | normal | 2018-03-28 17:06:49 +0900 (ौओख, 28 3 2018) | 18 lines + + webrick/httpauth/digestauth: stream req.body + + WARNING! WARNING! WARNING! LIKELY BROKEN CHANGE + + Pass a proc to WEBrick::HTTPRequest#body to avoid reading a + potentially large request body into memory during + authentication. + + WARNING! this will break apps completely which want to do + something with the body besides calculating the MD5 digest + of it. + + Also, keep in mind that probably nobody uses "auth-int". + Servers such as Apache, lighttpd, nginx don't seem to + support it; nor does curl when using POST/PUT bodies; + and we didn't have tests for it until now... + + * lib/webrick/httpauth/digestauth.rb (_authenticate): stream req.body + +git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_2@63021 b2dd03c8-39d4-4d8f-98ff-823fe69b080e +--- + ChangeLog | 83 ++++++++++++++++++++++++++++++++ + lib/webrick/httpauth/digestauth.rb | 8 ++-- + lib/webrick/httprequest.rb | 23 ++++++--- + lib/webrick/httpservlet/cgihandler.rb | 4 +- + test/webrick/test_httpauth.rb | 90 ++++++++++++++++++++++++++++++++++- + test/webrick/test_httpserver.rb | 67 ++++++++++++++++++++++++++ + version.h | 2 +- + 7 files changed, 262 insertions(+), 15 deletions(-) + +Index: ruby1.8/lib/webrick/httpauth/digestauth.rb +=================================================================== +--- ruby1.8.orig/lib/webrick/httpauth/digestauth.rb ++++ ruby1.8/lib/webrick/httpauth/digestauth.rb +@@ -176,9 +176,11 @@ module WEBrick + ha2 = hexdigest(req.request_method, auth_req['uri']) + ha2_res = hexdigest("", auth_req['uri']) + elsif auth_req['qop'] == "auth-int" +- ha2 = hexdigest(req.request_method, auth_req['uri'], +- hexdigest(req.body)) +- ha2_res = hexdigest("", auth_req['uri'], hexdigest(res.body)) ++ body_digest = @h.new ++ req.body { |chunk| body_digest.update(chunk) } ++ body_digest = body_digest.hexdigest ++ ha2 = hexdigest(req.request_method, auth_req['uri'], body_digest) ++ ha2_res = hexdigest("", auth_req['uri'], body_digest) + end + + if auth_req['qop'] == "auth" || auth_req['qop'] == "auth-int" +Index: ruby1.8/lib/webrick/httprequest.rb +=================================================================== +--- ruby1.8.orig/lib/webrick/httprequest.rb ++++ ruby1.8/lib/webrick/httprequest.rb +@@ -221,8 +221,17 @@ module WEBrick + + private + ++ MAX_URI_LENGTH = 2083 # :nodoc: ++ ++ # same as Mongrel, Thin and Puma ++ MAX_HEADER_LENGTH = (112 * 1024) # :nodoc: ++ + def read_request_line(socket) +- @request_line = read_line(socket) if socket ++ @request_line = read_line(socket, MAX_URI_LENGTH) if socket ++ @request_bytes = @request_line.bytesize ++ if @request_bytes >= MAX_URI_LENGTH and @request_line[-1, 1] != LF ++ raise HTTPStatus::RequestURITooLarge ++ end + @request_time = Time.now + raise HTTPStatus::EOFError unless @request_line + if /^(\S+)\s+(\S+?)(?:\s+HTTP\/(\d+\.\d+))?\r?\n/mo =~ @request_line +@@ -239,6 +248,9 @@ module WEBrick + if socket + while line = read_line(socket) + break if /\A(#{CRLF}|#{LF})\z/om =~ line ++ if (@request_bytes += line.bytesize) > MAX_HEADER_LENGTH ++ raise HTTPStatus::RequestEntityTooLarge, 'headers too large' ++ end + @raw_header << line + end + end +@@ -304,17 +316,15 @@ module WEBrick + def read_chunked(socket, block) + chunk_size, = read_chunk_size(socket) + while chunk_size > 0 +- data = "" +- while data.size < chunk_size +- tmp = read_data(socket, chunk_size-data.size) # read chunk-data +- break unless tmp +- data << tmp +- end +- if data.nil? || data.size != chunk_size +- raise BadRequest, "bad chunk data size." +- end ++ begin ++ sz = [ chunk_size, BUFSIZE ].min ++ data = read_data(socket, sz) # read chunk-data ++ if data.nil? || data.bytesize != sz ++ raise HTTPStatus::BadRequest, "bad chunk data size." ++ end ++ block.call(data) ++ end while (chunk_size -= sz) > 0 + read_line(socket) # skip CRLF +- block.call(data) + chunk_size, = read_chunk_size(socket) + end + read_header(socket) # trailer + CRLF +Index: ruby1.8/lib/webrick/httpservlet/cgihandler.rb +=================================================================== +--- ruby1.8.orig/lib/webrick/httpservlet/cgihandler.rb ++++ ruby1.8/lib/webrick/httpservlet/cgihandler.rb +@@ -53,9 +53,7 @@ module WEBrick + cgi_in.write("%8d" % dump.size) + cgi_in.write(dump) + +- if req.body and req.body.size > 0 +- cgi_in.write(req.body) +- end ++ req.body { |chunk| cgi_in.write(chunk) } + ensure + cgi_in.close + status = $?.exitstatus +Index: ruby1.8/test/webrick/test_httpauth.rb +=================================================================== +--- ruby1.8.orig/test/webrick/test_httpauth.rb ++++ ruby1.8/test/webrick/test_httpauth.rb +@@ -3,6 +3,7 @@ require "net/http" + require "tempfile" + require "webrick" + require "webrick/httpauth/basicauth" ++require "stringio" + require File.join(File.dirname(__FILE__), "utils.rb") + + class TestWEBrickHTTPAuth < Test::Unit::TestCase +@@ -115,4 +116,98 @@ class TestWEBrickHTTPAuth < Test::Unit:: + } + } + end ++ ++ def test_digest_auth_int ++ TestWEBrick.start_httpserver{|server, addr, port, log| ++ realm = "wb auth-int realm" ++ path = "/digest_auth_int" ++ ++ Tempfile.create("test_webrick_auth_int") {|tmpfile| ++ tmpfile.close ++ tmp_pass = WEBrick::HTTPAuth::Htdigest.new(tmpfile.path) ++ tmp_pass.set_passwd(realm, "foo", "Hunter2") ++ tmp_pass.flush ++ ++ htdigest = WEBrick::HTTPAuth::Htdigest.new(tmpfile.path) ++ users = [] ++ htdigest.each{|user, pass| users << user } ++ assert_equal %w(foo), users ++ ++ auth = WEBrick::HTTPAuth::DigestAuth.new( ++ :Realm => realm, :UserDB => htdigest, ++ :Algorithm => 'MD5', ++ :Logger => server.logger, ++ :Qop => %w(auth-int), ++ ) ++ server.mount_proc(path){|req, res| ++ auth.authenticate(req, res) ++ res.body = "bbb" ++ } ++ Net::HTTP.start(addr, port) do |http| ++ post = Net::HTTP::Post.new(path) ++ params = {} ++ data = 'hello=world' ++ body = StringIO.new(data) ++ post.content_length = data.bytesize ++ post['Content-Type'] = 'application/x-www-form-urlencoded' ++ post.body_stream = body ++ ++ http.request(post) do |res| ++ assert_equal('401', res.code, log.call) ++ res["www-authenticate"].scan(DIGESTRES_) do |key, quoted, token| ++ params[key.downcase] = token || quoted.delete('\\') ++ end ++ params['uri'] = "http://#{addr}:#{port}#{path}" ++ end ++ ++ body.rewind ++ cred = credentials_for_request('foo', 'Hunter3', params, body) ++ post['Authorization'] = cred ++ post.body_stream = body ++ http.request(post){|res| ++ assert_equal('401', res.code, log.call) ++ assert_not_equal("bbb", res.body, log.call) ++ } ++ ++ body.rewind ++ cred = credentials_for_request('foo', 'Hunter2', params, body) ++ post['Authorization'] = cred ++ post.body_stream = body ++ http.request(post){|res| assert_equal("bbb", res.body, log.call)} ++ end ++ } ++ } ++ end ++ ++ private ++ def credentials_for_request(user, password, params, body = nil) ++ cnonce = "hoge" ++ nonce_count = 1 ++ ha1 = "#{user}:#{params['realm']}:#{password}" ++ if body ++ dig = Digest::MD5.new ++ while buf = body.read(16384) ++ dig.update(buf) ++ end ++ body.rewind ++ ha2 = "POST:#{params['uri']}:#{dig.hexdigest}" ++ else ++ ha2 = "GET:#{params['uri']}" ++ end ++ ++ request_digest = ++ "#{Digest::MD5.hexdigest(ha1)}:" \ ++ "#{params['nonce']}:#{'%08x' % nonce_count}:#{cnonce}:#{params['qop']}:" \ ++ "#{Digest::MD5.hexdigest(ha2)}" ++ "Digest username=\"#{user}\"" \ ++ ", realm=\"#{params['realm']}\"" \ ++ ", nonce=\"#{params['nonce']}\"" \ ++ ", uri=\"#{params['uri']}\"" \ ++ ", qop=#{params['qop']}" \ ++ ", nc=#{'%08x' % nonce_count}" \ ++ ", cnonce=\"#{cnonce}\"" \ ++ ", response=\"#{Digest::MD5.hexdigest(request_digest)}\"" \ ++ ", opaque=\"#{params['opaque']}\"" \ ++ ", algorithm=#{params['algorithm']}" ++ end + end +Index: ruby1.8/test/webrick/test_httpserver.rb +=================================================================== +--- ruby1.8.orig/test/webrick/test_httpserver.rb ++++ ruby1.8/test/webrick/test_httpserver.rb +@@ -257,4 +257,63 @@ class TestWEBrickHTTPServer < Test::Unit + assert_equal(started, 1) + assert_equal(stopped, 1) + end ++ ++ def test_gigantic_request_header ++ TestWEBrick.start_httpserver{|server, addr, port, log| ++ server.mount('/', WEBrick::HTTPServlet::FileHandler, __FILE__) ++ TCPSocket.open(addr, port) do |c| ++ c.write("GET / HTTP/1.0\r\n") ++ junk = "X-Junk: #{' ' * 1024}\r\n" ++ assert_raise(Errno::ECONNRESET, Errno::EPIPE) do ++ loop { c.write(junk) } ++ end ++ end ++ } ++ end ++ ++ def test_eof_in_chunk ++ TestWEBrick.start_httpserver{|server, addr, port, log| ++ server.mount_proc('/', ->(req, res) { res.body = req.body }) ++ TCPSocket.open(addr, port) do |c| ++ c.write("POST / HTTP/1.1\r\nHost: example.com\r\n" \ ++ "Transfer-Encoding: chunked\r\n\r\n5\r\na") ++ c.shutdown(Socket::SHUT_WR) # trigger EOF in server ++ res = c.read ++ assert_match %r{\AHTTP/1\.1 400 }, res ++ end ++ } ++ end ++ ++ def test_big_chunks ++ nr_out = 3 ++ buf = 'big' # 3 bytes is bigger than 2! ++ config = { :InputBufferSize => 2 }.freeze ++ total = 0 ++ all = '' ++ TestWEBrick.start_httpserver(config){|server, addr, port, log| ++ server.mount_proc('/', ->(req, res) { ++ err = [] ++ ret = req.body do |chunk| ++ n = chunk.bytesize ++ n > config[:InputBufferSize] and err << "#{n} > :InputBufferSize" ++ total += n ++ all << chunk ++ end ++ ret.nil? or err << 'req.body should return nil' ++ (buf * nr_out) == all or err << 'input body does not match expected' ++ res.header['connection'] = 'close' ++ res.body = err.join("\n") ++ }) ++ TCPSocket.open(addr, port) do |c| ++ c.write("POST / HTTP/1.1\r\nHost: example.com\r\n" \ ++ "Transfer-Encoding: chunked\r\n\r\n") ++ chunk = "#{buf.bytesize.to_s(16)}\r\n#{buf}\r\n" ++ nr_out.times { c.write(chunk) } ++ c.write("0\r\n\r\n") ++ head, body = c.read.split("\r\n\r\n") ++ assert_match %r{\AHTTP/1\.1 200 OK}, head ++ assert_nil body ++ end ++ } ++ end + end diff --git a/gnu/packages/patches/ruby-1.8-CVE-2018-8778.patch b/gnu/packages/patches/ruby-1.8-CVE-2018-8778.patch new file mode 100644 index 000000000..f37cf0771 --- /dev/null +++ b/gnu/packages/patches/ruby-1.8-CVE-2018-8778.patch @@ -0,0 +1,67 @@ +Fix CVE-2018-8778: + +https://www.ruby-lang.org/en/news/2018/03/28/buffer-under-read-unpack-cve-2018-8778/ +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8778 +https://security-tracker.debian.org/tracker/CVE-2018-8778 + +Patch copied from snapshot.debian.org: + +https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz + +From 4cd92d7b13002161a3452a0fe278b877901a8859 Mon Sep 17 00:00:00 2001 +From: usa +Date: Wed, 28 Mar 2018 14:38:39 +0000 +Subject: [PATCH 4/4] merge revision(s) 62992: + + pack.c: fix underflow + + * pack.c (pack_unpack_internal): get rid of underflow. + https://hackerone.com/reports/298246 + +git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_2@63019 b2dd03c8-39d4-4d8f-98ff-823fe69b080e +--- + ChangeLog | 7 +++++++ + pack.c | 2 +- + test/ruby/test_pack.rb | 3 +++ + version.h | 2 +- + 4 files changed, 12 insertions(+), 2 deletions(-) + +Index: ruby1.8/pack.c +=================================================================== +--- ruby1.8.orig/pack.c ++++ ruby1.8/pack.c +@@ -13,6 +13,7 @@ + #include "ruby.h" + #include + #include ++#include + + #define GCC_VERSION_SINCE(major, minor, patchlevel) \ + (defined(__GNUC__) && !defined(__INTEL_COMPILER) && \ +@@ -1385,7 +1386,12 @@ pack_unpack(str, fmt) + p++; + } + else if (ISDIGIT(*p)) { ++ errno = 0; + len = strtoul(p, (char**)&p, 10); ++ if (len < 0 || errno) { ++ rb_raise(rb_eRangeError, "pack length too big"); ++ } ++ + } + else { + len = (type != '@'); +Index: ruby1.8/test/ruby/test_pack.rb +=================================================================== +--- ruby1.8.orig/test/ruby/test_pack.rb ++++ ruby1.8/test/ruby/test_pack.rb +@@ -306,4 +306,9 @@ class TestPack < Test::Unit::TestCase + assert_equal(["10ef"], "\x10\xef".unpack("H4")) + assert_equal(["10ef"], "\x10\xef".unpack("H5")) + end ++ ++ def test_pack_unpack_atmark ++ pos = (1 << [nil].pack("p").bytesize * 8) - 100 # -100 ++ assert_raise(RangeError) {"0123456789".unpack("@#{pos}C10")} ++ end + end diff --git a/gnu/packages/patches/ruby-1.8-CVE-2018-8779.patch b/gnu/packages/patches/ruby-1.8-CVE-2018-8779.patch new file mode 100644 index 000000000..eb875facb --- /dev/null +++ b/gnu/packages/patches/ruby-1.8-CVE-2018-8779.patch @@ -0,0 +1,99 @@ +Fix CVE-2018-8779: + +https://www.ruby-lang.org/en/news/2018/03/28/poisoned-nul-byte-unixsocket-cve-2018-8779/ +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8779 +https://security-tracker.debian.org/tracker/CVE-2018-8779 + +Patch copied from snapshot.debian.org: + +https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz + +Origin: backport, 47165eed264d357e78e27371cfef20d5c2bde5d9 +Reviewed-by: Santiago R.R + +From 47165eed264d357e78e27371cfef20d5c2bde5d9 Mon Sep 17 00:00:00 2001 +From: usa +Date: Wed, 28 Mar 2018 14:36:23 +0000 +Subject: [PATCH 3/4] merge revision(s) 62991,63000: + + unixsocket.c: check NUL bytes + + * ext/socket/unixsocket.c (rsock_init_unixsock): check NUL bytes. + https://hackerone.com/reports/302997 + + unixsocket.c: abstract namespace + + * ext/socket/unixsocket.c (unixsock_path_value): fix r62991 for + Linux abstract namespace. + +git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_2@63018 b2dd03c8-39d4-4d8f-98ff-823fe69b080e +--- + ChangeLog | 12 ++++++++++++ + ext/socket/unixsocket.c | 24 +++++++++++++++++++++++- + test/socket/test_unix.rb | 10 ++++++++++ + version.h | 2 +- + 4 files changed, 46 insertions(+), 2 deletions(-) + +Index: ruby1.8/test/socket/test_unix.rb +=================================================================== +--- ruby1.8.orig/test/socket/test_unix.rb ++++ ruby1.8/test/socket/test_unix.rb +@@ -39,6 +39,16 @@ class TestUNIXSocket < Test::Unit::TestC + File.unlink path if path && File.socket?(path) + end + ++ def test_open_nul_byte ++ tmpfile = Tempfile.new("s") ++ path = tmpfile.path ++ tmpfile.close(true) ++ assert_raise(ArgumentError) {UNIXServer.open(path+"\0")} ++ assert_raise(ArgumentError) {UNIXSocket.open(path+"\0")} ++ ensure ++ File.unlink path if path && File.socket?(path) ++ end ++ + def test_addr + bound_unix_socket(UNIXServer) {|serv, path| + c = UNIXSocket.new(path) +Index: ruby1.8/ext/socket/socket.c +=================================================================== +--- ruby1.8.orig/ext/socket/socket.c ++++ ruby1.8/ext/socket/socket.c +@@ -1623,6 +1623,28 @@ unixsock_connect_internal(arg) + } + + static VALUE ++unixsock_path_value(VALUE path) ++{ ++#ifdef __linux__ ++#define TO_STR_FOR_LINUX_ABSTRACT_NAMESPACE 0 ++ ++ VALUE name = path; ++#if TO_STR_FOR_LINUX_ABSTRACT_NAMESPACE ++ const int isstr = !NIL_P(name = rb_check_string_type(name)); ++#else ++ const int isstr = RB_TYPE_P(name, T_STRING); ++#endif ++ if (isstr) { ++ if (RSTRING_LEN(name) == 0 || RSTRING_PTR(name)[0] == '\0') { ++ rb_check_safe_obj(name); ++ return name; /* ignore encoding */ ++ } ++ } ++#endif ++ return rb_get_path(path); ++} ++ ++static VALUE + init_unixsock(sock, path, server) + VALUE sock; + VALUE path; +@@ -1632,7 +1654,7 @@ init_unixsock(sock, path, server) + int fd, status; + rb_io_t *fptr; + +- SafeStringValue(path); ++ path = unixsock_path_value(path); + fd = ruby_socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + rb_sys_fail("socket(2)"); diff --git a/gnu/packages/patches/ruby-1.8-CVE-2018-8780+CVE-2018-8779-pre.patch b/gnu/packages/patches/ruby-1.8-CVE-2018-8780+CVE-2018-8779-pre.patch new file mode 100644 index 000000000..c7640db14 --- /dev/null +++ b/gnu/packages/patches/ruby-1.8-CVE-2018-8780+CVE-2018-8779-pre.patch @@ -0,0 +1,52 @@ +Prepare to fix CVE-2018-{8780,8779}: + +Patch copied from snapshot.debian.org: + +https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz + +Index: ruby1.8/file.c +=================================================================== +--- ruby1.8.orig/file.c ++++ ruby1.8/file.c +@@ -110,6 +110,41 @@ VALUE rb_cFile; + VALUE rb_mFileTest; + VALUE rb_cStat; + ++#define insecure_obj_p(obj, level) ((level) >= 4 || ((level) > 0 && OBJ_TAINTED(obj))) ++ ++static VALUE ++rb_get_path_check(VALUE obj, int level) ++{ ++ VALUE tmp; ++ ID to_path; ++ /* skip encoding check - unavailable */ ++ ++ if (insecure_obj_p(obj, level)) { ++ rb_raise(rb_eSecurityError, "Insecure operation: -r"); ++ } ++ ++ /* skip check funcall - unvailable */ ++ tmp = obj; ++ StringValue(tmp); ++ ++ /* skip file_path_convert; useful in WIN32 */ ++ if (obj != tmp && insecure_obj_p(tmp, level)) { ++ rb_raise(rb_eSecurityError, "Insecure operation: -r"); ++ } ++ /* skip encoding check */ ++ ++ StringValueCStr(tmp); ++ ++ return rb_str_new4(tmp); ++} ++ ++VALUE ++rb_get_path(VALUE obj) ++{ ++ return rb_get_path_check(obj, rb_safe_level()); ++} ++ ++ + static long apply2files _((void (*)(const char *, void *), VALUE, void *)); + static long + apply2files(func, vargs, arg) diff --git a/gnu/packages/patches/ruby-1.8-CVE-2018-8780.patch b/gnu/packages/patches/ruby-1.8-CVE-2018-8780.patch new file mode 100644 index 000000000..5bbc8508c --- /dev/null +++ b/gnu/packages/patches/ruby-1.8-CVE-2018-8780.patch @@ -0,0 +1,114 @@ +Fix CVE-2018-8780: + +https://www.ruby-lang.org/en/news/2018/03/28/poisoned-nul-byte-dir-cve-2018-8780/ +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8780 +https://security-tracker.debian.org/tracker/CVE-2018-8780 + +Patch copied from snapshot.debian.org: + +https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz + +From 143eb22f1877815dd802f7928959c5f93d4c7bb3 Mon Sep 17 00:00:00 2001 +From: usa +Date: Wed, 28 Mar 2018 14:27:51 +0000 +Subject: [PATCH 1/4] merge revision(s) 62989: + + dir.c: check NUL bytes + + * dir.c (GlobPathValue): should be used in rb_push_glob only. + other methods should use FilePathValue. + https://hackerone.com/reports/302338 + + * dir.c (rb_push_glob): expand GlobPathValue + +git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_2@63015 b2dd03c8-39d4-4d8f-98ff-823fe69b080e +--- + ChangeLog | 10 ++++++++++ + dir.c | 22 ++++++++++------------ + test/ruby/test_dir.rb | 4 ++++ + version.h | 10 +++++----- + 4 files changed, 29 insertions(+), 17 deletions(-) + +Index: ruby1.8/dir.c +=================================================================== +--- ruby1.8.orig/dir.c ++++ ruby1.8/dir.c +@@ -392,7 +392,7 @@ dir_initialize(dir, dirname) + { + struct dir_data *dp; + +- SafeStringValue(dirname); ++ FilePathValue(dirname); + Data_Get_Struct(dir, struct dir_data, dp); + if (dp->dir) closedir(dp->dir); + if (dp->path) free(dp->path); +@@ -1629,8 +1629,15 @@ rb_push_glob(str, flags) /* '\0' is deli + long offset = 0; + VALUE ary; + ++ /* can contain null bytes as separators */ ++ if (!RB_TYPE_P((str), T_STRING)) { ++ FilePathValue(str); ++ } ++ else { ++ rb_check_safe_obj(str); ++ /* unable to check encoding */ ++ } + ary = rb_ary_new(); +- SafeStringValue(str); + + while (offset < RSTRING_LEN(str)) { + int status = push_glob(ary, RSTRING(str)->ptr + offset, flags); +@@ -1660,7 +1667,7 @@ dir_globs(argc, argv, flags) + for (i = 0; i < argc; ++i) { + int status; + VALUE str = argv[i]; +- SafeStringValue(str); ++ FilePathValue(str); + status = push_glob(ary, RSTRING(str)->ptr, flags); + if (status) GLOB_JUMP_TAG(status); + } +Index: ruby1.8/ruby.h +=================================================================== +--- ruby1.8.orig/ruby.h ++++ ruby1.8/ruby.h +@@ -257,6 +257,9 @@ void rb_check_safe_str _((VALUE)); + /* obsolete macro - use SafeStringValue(v) */ + #define Check_SafeStr(v) rb_check_safe_str((VALUE)(v)) + ++VALUE rb_get_path(VALUE); ++#define FilePathValue(v) (RB_GC_GUARD(v) = rb_get_path(v)) ++ + void rb_secure _((int)); + RUBY_EXTERN int ruby_safe_level; + #define rb_safe_level() (ruby_safe_level) +@@ -740,6 +743,15 @@ rb_type(obj) + return BUILTIN_TYPE(obj); + } + ++#define RB_TYPE_P(obj, type) ( \ ++ ((type) == T_FIXNUM) ? FIXNUM_P(obj) : \ ++ ((type) == T_TRUE) ? ((obj) == Qtrue) : \ ++ ((type) == T_FALSE) ? ((obj) == Qfalse) : \ ++ ((type) == T_NIL) ? ((obj) == Qnil) : \ ++ ((type) == T_UNDEF) ? ((obj) == Qundef) : \ ++ ((type) == T_SYMBOL) ? SYMBOL_P(obj) : \ ++ (!SPECIAL_CONST_P(obj) && BUILTIN_TYPE(obj) == (type))) ++ + static inline int + #if defined(HAVE_PROTOTYPES) + rb_special_const_p(VALUE obj) +Index: ruby1.8/test/ruby/test_dir.rb +=================================================================== +--- ruby1.8.orig/test/ruby/test_dir.rb ++++ ruby1.8/test/ruby/test_dir.rb +@@ -39,4 +39,9 @@ class TestDir < Test::Unit::TestCase + dir.close + end + end ++ ++ def test_foreach ++ assert_equal(Dir.foreach(ROOT).to_a.sort, %w(. ..) + (?a..?z).to_a) ++ assert_raise(ArgumentError) {Dir.foreach(ROOT+"\0").to_a} ++ end + end diff --git a/gnu/packages/ruby.scm b/gnu/packages/ruby.scm index 2fde01685..93f801fa6 100644 --- a/gnu/packages/ruby.scm +++ b/gnu/packages/ruby.scm @@ -177,7 +177,25 @@ a focus on simplicity and productivity.") "/ruby-" version ".tar.bz2")) (sha256 (base32 - "1qq7khilwkayrhwmzlxk83scrmiqfi7lgsn4c63znyvz2c1lgqxl")))) + "1qq7khilwkayrhwmzlxk83scrmiqfi7lgsn4c63znyvz2c1lgqxl")) + (patches + (search-patches "ruby-1.8-CVE-2013-4164.patch" + "ruby-1.8-CVE-2014-8080.patch" + "ruby-1.8-CVE-2014-8090.patch" + "ruby-1.8-CVE-2015-1855.patch" + "ruby-1.8-CVE-2017-10784.patch" + "ruby-1.8-CVE-2017-0898.patch" + "ruby-1.8-CVE-2017-17405.patch" + "ruby-1.8-CVE-2017-17790.patch" + "ruby-1.8-CVE-2018-8780+CVE-2018-8779-pre.patch" + "ruby-1.8-CVE-2018-8780.patch" + "ruby-1.8-CVE-2018-6914.patch" + "ruby-1.8-CVE-2018-8779.patch" + "ruby-1.8-CVE-2018-8778.patch" + "ruby-1.8-CVE-2018-8777+CVE-2017-17742-pre.patch" + "ruby-1.8-CVE-2018-8777.patch" + "ruby-1.8-CVE-2017-17742-pre.patch" + "ruby-1.8-CVE-2017-17742.patch")))) (native-search-paths '()) (arguments `(#:test-target "test" -- 2.19.2