├── Procfile ├── bin ├── compile └── detect ├── Gemfile ├── config.ru ├── .buildpacks ├── Gemfile.lock ├── README.md └── patches ├── tcmalloc_declare_memalign_volatile.patch ├── 5384967a015be227e16af7a332a50d45e14ed0ad.patch ├── 34ba44f94a62c63ddf02a045b6f4edcd6eab4989.patch └── CVE-2015-1855.patch /Procfile: -------------------------------------------------------------------------------- 1 | web: ./build_ree.sh 2 | -------------------------------------------------------------------------------- /bin/compile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | exit 0 4 | -------------------------------------------------------------------------------- /bin/detect: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "ree-buildpack" 4 | exit 0 5 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | ruby "2.2.0" 4 | 5 | gem "unicorn" 6 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | run Proc.new {[200,{'Content-Type' => 'text/plain'}, ["hello world"]]} 2 | -------------------------------------------------------------------------------- /.buildpacks: -------------------------------------------------------------------------------- 1 | https://github.com/Genius/ree-1.8.7-heroku.git 2 | https://codon-buildpacks.s3.amazonaws.com/buildpacks/heroku/ruby.tgz 3 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | kgio (2.9.3) 5 | rack (1.6.1) 6 | raindrops (0.13.0) 7 | unicorn (4.9.0) 8 | kgio (~> 2.6) 9 | rack 10 | raindrops (~> 0.7) 11 | 12 | PLATFORMS 13 | ruby 14 | 15 | DEPENDENCIES 16 | unicorn 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Build and serve custom REE 2 | 3 | This repo contains both a buildpack and application which is used to build and 4 | serve tarballs of Genius's custom REE. It's pretty easy to setup and the build 5 | will take place as part of launching the `web` process before python's 6 | `SimpleHTTPServer` serves the tarball with `app/vendor/ruby-1.8.7`. 7 | 8 | It's best to use an ephemeral application to build REE: 9 | 10 | ```shell 11 | 12 | heroku create --buildpack https://github.com/ddollar/heroku-buildpack-multi.git 13 | git push heroku master 14 | heroku logs -t # this will show you output of `make` running on the dyno 15 | heroku open # open up the URL where the tarball is available after build 16 | ``` 17 | 18 | 19 | -------------------------------------------------------------------------------- /patches/tcmalloc_declare_memalign_volatile.patch: -------------------------------------------------------------------------------- 1 | diff --git a/distro/google-perftools-1.7/src/tcmalloc.cc b/distro/google-perftools-1.7/src/tcmalloc.cc 2 | index 8d94d20..0769425 100644 3 | --- a/distro/google-perftools-1.7/src/tcmalloc.cc 4 | +++ b/distro/google-perftools-1.7/src/tcmalloc.cc 5 | @@ -137,6 +137,13 @@ 6 | # define WIN32_DO_PATCHING 1 7 | #endif 8 | 9 | +// GLibc 2.14+ requires the hook functions be declared volatile, based on the value of the 10 | +// define __MALLOC_HOOK_VOLATILE. For compatibility with older/non-GLibc implementations, 11 | +// provide an empty definition. 12 | +#if !defined(__MALLOC_HOOK_VOLATILE) 13 | +#define __MALLOC_HOOK_VOLATILE 14 | +#endif 15 | + 16 | using STL_NAMESPACE::max; 17 | using STL_NAMESPACE::numeric_limits; 18 | using STL_NAMESPACE::vector; 19 | @@ -1669,5 +1676,5 @@ static void *MemalignOverride(size_t align, size_t size, const void *caller) 20 | MallocHook::InvokeNewHook(result, size); 21 | return result; 22 | } 23 | -void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride; 24 | +void *(*__MALLOC_HOOK_VOLATILE __memalign_hook)(size_t, size_t, const void *) = MemalignOverride; 25 | #endif // #ifndef TCMALLOC_FOR_DEBUGALLOCATION 26 | -------------------------------------------------------------------------------- /patches/5384967a015be227e16af7a332a50d45e14ed0ad.patch: -------------------------------------------------------------------------------- 1 | From 5384967a015be227e16af7a332a50d45e14ed0ad Mon Sep 17 00:00:00 2001 2 | From: usa 3 | Date: Fri, 22 Nov 2013 04:18:47 +0000 4 | Subject: [PATCH] merge revision(s) 43780: 5 | 6 | * util.c (ruby_strtod): BigMath requires more precision. 7 | 8 | git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_9_3@43782 b2dd03c8-39d4-4d8f-98ff-823fe69b080e 9 | --- 10 | util.c | 2 +- 11 | version.h | 2 +- 12 | 2 files changed, 2 insertions(+), 2 deletions(-) 13 | 14 | diff --git a/util.c b/util.c 15 | index e98efc6..54a1604 100644 16 | --- a/util.c 17 | +++ b/util.c 18 | @@ -2209,7 +2209,7 @@ ruby_strtod(const char *s00, char **se) 19 | for (; c >= '0' && c <= '9'; c = *++s) { 20 | have_dig: 21 | nz++; 22 | - if (nf > DBL_DIG * 2) continue; 23 | + if (nf > DBL_DIG * 4) continue; 24 | if (c -= '0') { 25 | nf += nz; 26 | for (i = 1; i < nz; i++) 27 | diff --git a/version.h b/version.h 28 | index 6773217..878532b 100644 29 | --- a/version.h 30 | +++ b/version.h 31 | @@ -2,7 +2,7 @@ 32 | #define RUBY_RELEASE_DATE "2013-11-26" 33 | #define RUBY_VERSION_CODE 187 34 | #define RUBY_RELEASE_CODE 20131126 35 | -#define RUBY_PATCHLEVEL 359 36 | +#define RUBY_PATCHLEVEL 360 37 | 38 | #define RUBY_VERSION_MAJOR 1 39 | #define RUBY_VERSION_MINOR 8 40 | -------------------------------------------------------------------------------- /patches/34ba44f94a62c63ddf02a045b6f4edcd6eab4989.patch: -------------------------------------------------------------------------------- 1 | From 34ba44f94a62c63ddf02a045b6f4edcd6eab4989 Mon Sep 17 00:00:00 2001 2 | From: nagachika 3 | Date: Fri, 22 Nov 2013 04:00:39 +0000 4 | Subject: [PATCH] cherry pick 46cd2f4 for CVE-2013-4164 5 | 6 | merge revision(s) 43775: 7 | 8 | * util.c (ruby_strtod): ignore too long fraction part, which does not 9 | affect the result. 10 | 11 | git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_0_0@43778 b2dd03c8-39d4-4d8f-98ff-823fe69b080e 12 | 13 | Conflicts: 14 | ChangeLog 15 | test/ruby/test_float.rb 16 | version.h 17 | --- 18 | ChangeLog | 5 +++++ 19 | test/ruby/test_float.rb | 6 ++++++ 20 | util.c | 14 ++++++++++++-- 21 | version.h | 10 +++++----- 22 | 4 files changed, 28 insertions(+), 7 deletions(-) 23 | 24 | diff --git a/ChangeLog b/ChangeLog 25 | index a09237e..e37c7e0 100644 26 | --- a/ChangeLog 27 | +++ b/ChangeLog 28 | @@ -1,3 +1,8 @@ 29 | +Fri Nov 22 12:46:08 2013 Nobuyoshi Nakada 30 | + 31 | + * util.c (ruby_strtod): ignore too long fraction part, which does not 32 | + affect the result. 33 | + 34 | Wed Feb 8 14:06:59 2012 Hiroshi Nakamura 35 | 36 | * ext/openssl/ossl_ssl.c: Add SSL constants and allow to unset SSL 37 | diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb 38 | index b6e643d..6daf061 100644 39 | --- a/test/ruby/test_float.rb 40 | +++ b/test/ruby/test_float.rb 41 | @@ -171,4 +171,10 @@ def test_cmp 42 | assert_raise(ArgumentError) { 1.0 < nil } 43 | assert_raise(ArgumentError) { 1.0 <= nil } 44 | end 45 | + 46 | + def test_long_string 47 | + assert_separately([], <<-'end;') 48 | + assert_in_epsilon(10.0, ("1."+"1"*300000).to_f*9) 49 | + end; 50 | + end 51 | end 52 | diff --git a/util.c b/util.c 53 | index 62f3368..e98efc6 100644 54 | --- a/util.c 55 | +++ b/util.c 56 | @@ -892,6 +892,11 @@ extern void *MALLOC(size_t); 57 | #else 58 | #define MALLOC malloc 59 | #endif 60 | +#ifdef FREE 61 | +extern void FREE(void*); 62 | +#else 63 | +#define FREE free 64 | +#endif 65 | 66 | #ifndef Omit_Private_Memory 67 | #ifndef PRIVATE_MEM 68 | @@ -1176,7 +1181,7 @@ Balloc(int k) 69 | #endif 70 | 71 | ACQUIRE_DTOA_LOCK(0); 72 | - if ((rv = freelist[k]) != 0) { 73 | + if (k <= Kmax && (rv = freelist[k]) != 0) { 74 | freelist[k] = rv->next; 75 | } 76 | else { 77 | @@ -1186,7 +1191,7 @@ Balloc(int k) 78 | #else 79 | len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) 80 | /sizeof(double); 81 | - if (pmem_next - private_mem + len <= PRIVATE_mem) { 82 | + if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) { 83 | rv = (Bigint*)pmem_next; 84 | pmem_next += len; 85 | } 86 | @@ -1205,6 +1210,10 @@ static void 87 | Bfree(Bigint *v) 88 | { 89 | if (v) { 90 | + if (v->k > Kmax) { 91 | + FREE(v); 92 | + return; 93 | + } 94 | ACQUIRE_DTOA_LOCK(0); 95 | v->next = freelist[v->k]; 96 | freelist[v->k] = v; 97 | @@ -2200,6 +2209,7 @@ ruby_strtod(const char *s00, char **se) 98 | for (; c >= '0' && c <= '9'; c = *++s) { 99 | have_dig: 100 | nz++; 101 | + if (nf > DBL_DIG * 2) continue; 102 | if (c -= '0') { 103 | nf += nz; 104 | for (i = 1; i < nz; i++) 105 | diff --git a/version.h b/version.h 106 | index d6f16f5..6773217 100644 107 | --- a/version.h 108 | +++ b/version.h 109 | @@ -1,15 +1,15 @@ 110 | #define RUBY_VERSION "1.8.7" 111 | -#define RUBY_RELEASE_DATE "2012-02-08" 112 | +#define RUBY_RELEASE_DATE "2013-11-26" 113 | #define RUBY_VERSION_CODE 187 114 | -#define RUBY_RELEASE_CODE 20120208 115 | -#define RUBY_PATCHLEVEL 358 116 | +#define RUBY_RELEASE_CODE 20131126 117 | +#define RUBY_PATCHLEVEL 359 118 | 119 | #define RUBY_VERSION_MAJOR 1 120 | #define RUBY_VERSION_MINOR 8 121 | #define RUBY_VERSION_TEENY 7 122 | #define RUBY_RELEASE_YEAR 2012 123 | -#define RUBY_RELEASE_MONTH 2 124 | -#define RUBY_RELEASE_DAY 8 125 | +#define RUBY_RELEASE_MONTH 11 126 | +#define RUBY_RELEASE_DAY 26 127 | 128 | #ifdef RUBY_EXTERN 129 | RUBY_EXTERN const char ruby_version[]; 130 | -------------------------------------------------------------------------------- /patches/CVE-2015-1855.patch: -------------------------------------------------------------------------------- 1 | From c651259238f4bff98bc6a7ead5bdfe5aa9317531 Mon Sep 17 00:00:00 2001 2 | From: Mat Brown 3 | Date: Wed, 29 Apr 2015 11:22:42 -0400 4 | Subject: [PATCH] Apply backported patch for CVE-2015-1855 5 | 6 | --- 7 | ext/openssl/lib/openssl/ssl-internal.rb | 63 +++++++++++++- 8 | test/openssl/test_ssl.rb | 150 ++++++++++++++++++++++++++++++++ 9 | 2 files changed, 209 insertions(+), 4 deletions(-) 10 | 11 | diff --git a/ext/openssl/lib/openssl/ssl-internal.rb b/ext/openssl/lib/openssl/ssl-internal.rb 12 | index abf0e8d..2c985e7 100644 13 | --- a/ext/openssl/lib/openssl/ssl-internal.rb 14 | +++ b/ext/openssl/lib/openssl/ssl-internal.rb 15 | @@ -93,8 +93,7 @@ module OpenSSL 16 | ext.value.split(/,\s+/).each{|general_name| 17 | if /\ADNS:(.*)/ =~ general_name 18 | should_verify_common_name = false 19 | - reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+") 20 | - return true if /\A#{reg}\z/i =~ hostname 21 | + return true if verify_hostname(hostname, $1) 22 | elsif /\AIP Address:(.*)/ =~ general_name 23 | should_verify_common_name = false 24 | return true if $1 == hostname 25 | @@ -104,8 +103,7 @@ module OpenSSL 26 | if should_verify_common_name 27 | cert.subject.to_a.each{|oid, value| 28 | if oid == "CN" 29 | - reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+") 30 | - return true if /\A#{reg}\z/i =~ hostname 31 | + return true if verify_hostname(hostname, value) 32 | end 33 | } 34 | end 35 | @@ -113,11 +111,68 @@ module OpenSSL 36 | end 37 | module_function :verify_certificate_identity 38 | 39 | + def verify_hostname(hostname, san) # :nodoc: 40 | + # RFC 5280, IA5String is limited to the set of ASCII characters 41 | + ascii_only = /\A[\x00-\x80]*\z/ 42 | + return false unless ascii_only =~ san 43 | + return false unless ascii_only =~ hostname 44 | + 45 | + # See RFC 6125, section 6.4.1 46 | + # Matching is case-insensitive. 47 | + san_parts = san.downcase.split(".") 48 | + 49 | + # TODO: this behavior should probably be more strict 50 | + return san == hostname if san_parts.size < 2 51 | + 52 | + # Matching is case-insensitive. 53 | + host_parts = hostname.downcase.split(".") 54 | + 55 | + # RFC 6125, section 6.4.3, subitem 2. 56 | + # If the wildcard character is the only character of the left-most 57 | + # label in the presented identifier, the client SHOULD NOT compare 58 | + # against anything but the left-most label of the reference 59 | + # identifier (e.g., *.example.com would match foo.example.com but 60 | + # not bar.foo.example.com or example.com). 61 | + return false unless san_parts.size == host_parts.size 62 | + 63 | + # RFC 6125, section 6.4.3, subitem 1. 64 | + # The client SHOULD NOT attempt to match a presented identifier in 65 | + # which the wildcard character comprises a label other than the 66 | + # left-most label (e.g., do not match bar.*.example.net). 67 | + return false unless verify_wildcard(host_parts.shift, san_parts.shift) 68 | + 69 | + san_parts.join(".") == host_parts.join(".") 70 | + end 71 | + module_function :verify_hostname 72 | + 73 | + def verify_wildcard(domain_component, san_component) # :nodoc: 74 | + parts = san_component.split("*", -1) 75 | + 76 | + return false if parts.size > 2 77 | + return san_component == domain_component if parts.size == 1 78 | + 79 | + # RFC 6125, section 6.4.3, subitem 3. 80 | + # The client SHOULD NOT attempt to match a presented identifier 81 | + # where the wildcard character is embedded within an A-label or 82 | + # U-label of an internationalized domain name. 83 | + return false if domain_component.start_with?("xn--") && san_component != "*" 84 | + 85 | + parts[0].length + parts[1].length < domain_component.length && 86 | + domain_component.start_with?(parts[0]) && 87 | + domain_component.end_with?(parts[1]) 88 | + end 89 | + module_function :verify_wildcard 90 | + 91 | class SSLSocket 92 | include Buffering 93 | include SocketForwarder 94 | include Nonblock 95 | 96 | + ## 97 | + # Perform hostname verification after an SSL connection is established 98 | + # 99 | + # This method MUST be called after calling #connect to ensure that the 100 | + # hostname of a remote peer has been verified. 101 | def post_connection_check(hostname) 102 | unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname) 103 | raise SSLError, "hostname was not match with the server certificate" 104 | diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb 105 | index 177b684..6b2aa43 100644 106 | --- a/test/openssl/test_ssl.rb 107 | +++ b/test/openssl/test_ssl.rb 108 | @@ -411,6 +411,156 @@ class OpenSSL::TestSSL < Test::Unit::TestCase 109 | } 110 | end 111 | 112 | + def test_verify_hostname 113 | + assert_equal(true, OpenSSL::SSL.verify_hostname("www.example.com", "*.example.com")) 114 | + assert_equal(false, OpenSSL::SSL.verify_hostname("www.subdomain.example.com", "*.example.com")) 115 | + end 116 | + 117 | + def test_verify_wildcard 118 | + assert_equal(false, OpenSSL::SSL.verify_wildcard("foo", "x*")) 119 | + assert_equal(true, OpenSSL::SSL.verify_wildcard("foo", "foo")) 120 | + assert_equal(true, OpenSSL::SSL.verify_wildcard("foo", "f*")) 121 | + assert_equal(true, OpenSSL::SSL.verify_wildcard("foo", "*")) 122 | + assert_equal(false, OpenSSL::SSL.verify_wildcard("abc*bcd", "abcd")) 123 | + assert_equal(false, OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", "x*")) 124 | + assert_equal(false, OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", "*--qdk4b9b")) 125 | + assert_equal(true, OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", "xn--qdk4b9b")) 126 | + end 127 | + 128 | + # Comments in this test is excerpted from http://tools.ietf.org/html/rfc6125#page-27 129 | + def test_post_connection_check_wildcard_san 130 | + # case-insensitive ASCII comparison 131 | + # RFC 6125, section 6.4.1 132 | + # 133 | + # "..matching of the reference identifier against the presented identifier 134 | + # is performed by comparing the set of domain name labels using a 135 | + # case-insensitive ASCII comparison, as clarified by [DNS-CASE] (e.g., 136 | + # "WWW.Example.Com" would be lower-cased to "www.example.com" for 137 | + # comparison purposes) 138 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 139 | + create_cert_with_san('DNS:*.example.com'), 'www.example.com')) 140 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 141 | + create_cert_with_san('DNS:*.Example.COM'), 'www.example.com')) 142 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 143 | + create_cert_with_san('DNS:*.example.com'), 'WWW.Example.COM')) 144 | + # 1. The client SHOULD NOT attempt to match a presented identifier in 145 | + # which the wildcard character comprises a label other than the 146 | + # left-most label (e.g., do not match bar.*.example.net). 147 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 148 | + create_cert_with_san('DNS:www.*.com'), 'www.example.com')) 149 | + # 2. If the wildcard character is the only character of the left-most 150 | + # label in the presented identifier, the client SHOULD NOT compare 151 | + # against anything but the left-most label of the reference 152 | + # identifier (e.g., *.example.com would match foo.example.com but 153 | + # not bar.foo.example.com or example.com). 154 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 155 | + create_cert_with_san('DNS:*.example.com'), 'foo.example.com')) 156 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 157 | + create_cert_with_san('DNS:*.example.com'), 'bar.foo.example.com')) 158 | + # 3. The client MAY match a presented identifier in which the wildcard 159 | + # character is not the only character of the label (e.g., 160 | + # baz*.example.net and *baz.example.net and b*z.example.net would 161 | + # be taken to match baz1.example.net and foobaz.example.net and 162 | + # buzz.example.net, respectively). ... 163 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 164 | + create_cert_with_san('DNS:baz*.example.com'), 'baz1.example.com')) 165 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 166 | + create_cert_with_san('DNS:*baz.example.com'), 'foobaz.example.com')) 167 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 168 | + create_cert_with_san('DNS:b*z.example.com'), 'buzz.example.com')) 169 | + # Section 6.4.3 of RFC6125 states that client should NOT match identifier 170 | + # where wildcard is other than left-most label. 171 | + # 172 | + # Also implicitly mentions the wildcard character only in singular form, 173 | + # and discourages matching against more than one wildcard. 174 | + # 175 | + # See RFC 6125, section 7.2, subitem 2. 176 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 177 | + create_cert_with_san('DNS:*b*.example.com'), 'abc.example.com')) 178 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 179 | + create_cert_with_san('DNS:*b*.example.com'), 'ab.example.com')) 180 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 181 | + create_cert_with_san('DNS:*b*.example.com'), 'bc.example.com')) 182 | + # ... However, the client SHOULD NOT 183 | + # attempt to match a presented identifier where the wildcard 184 | + # character is embedded within an A-label or U-label [IDNA-DEFS] of 185 | + # an internationalized domain name [IDNA-PROTO]. 186 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 187 | + create_cert_with_san('DNS:xn*.example.com'), 'xn1ca.example.com')) 188 | + # part of A-label 189 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 190 | + create_cert_with_san('DNS:xn--*.example.com'), 'xn--1ca.example.com')) 191 | + # part of U-label 192 | + # dNSName in RFC5280 is an IA5String so U-label should NOT be allowed 193 | + # regardless of wildcard. 194 | + # 195 | + # See Section 7.2 of RFC 5280: 196 | + # IA5String is limited to the set of ASCII characters. 197 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 198 | + create_cert_with_san('DNS:á*.example.com'), 'á1.example.com')) 199 | + end 200 | + 201 | + def test_post_connection_check_wildcard_cn 202 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 203 | + create_cert_with_name('*.example.com'), 'www.example.com')) 204 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 205 | + create_cert_with_name('*.Example.COM'), 'www.example.com')) 206 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 207 | + create_cert_with_name('*.example.com'), 'WWW.Example.COM')) 208 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 209 | + create_cert_with_name('www.*.com'), 'www.example.com')) 210 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 211 | + create_cert_with_name('*.example.com'), 'foo.example.com')) 212 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 213 | + create_cert_with_name('*.example.com'), 'bar.foo.example.com')) 214 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 215 | + create_cert_with_name('baz*.example.com'), 'baz1.example.com')) 216 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 217 | + create_cert_with_name('*baz.example.com'), 'foobaz.example.com')) 218 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 219 | + create_cert_with_name('b*z.example.com'), 'buzz.example.com')) 220 | + # Section 6.4.3 of RFC6125 states that client should NOT match identifier 221 | + # where wildcard is other than left-most label. 222 | + # 223 | + # Also implicitly mentions the wildcard character only in singular form, 224 | + # and discourages matching against more than one wildcard. 225 | + # 226 | + # See RFC 6125, section 7.2, subitem 2. 227 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 228 | + create_cert_with_name('*b*.example.com'), 'abc.example.com')) 229 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 230 | + create_cert_with_name('*b*.example.com'), 'ab.example.com')) 231 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 232 | + create_cert_with_name('*b*.example.com'), 'bc.example.com')) 233 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 234 | + create_cert_with_name('xn*.example.com'), 'xn1ca.example.com')) 235 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 236 | + create_cert_with_name('xn--*.example.com'), 'xn--1ca.example.com')) 237 | + # part of U-label 238 | + # Subject in RFC5280 states case-insensitive ASCII comparison. 239 | + # 240 | + # See Section 7.2 of RFC 5280: 241 | + # IA5String is limited to the set of ASCII characters. 242 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 243 | + create_cert_with_name('á*.example.com'), 'á1.example.com')) 244 | + end 245 | + 246 | + def create_cert_with_san(san) 247 | + ef = OpenSSL::X509::ExtensionFactory.new 248 | + cert = OpenSSL::X509::Certificate.new 249 | + cert.subject = OpenSSL::X509::Name.parse("/DC=some/DC=site/CN=Some Site") 250 | + ext = ef.create_ext('subjectAltName', san) 251 | + cert.add_extension(ext) 252 | + cert 253 | + end 254 | + 255 | + def create_cert_with_name(name) 256 | + cert = OpenSSL::X509::Certificate.new 257 | + cert.subject = OpenSSL::X509::Name.new([['DC', 'some'], ['DC', 'site'], ['CN', name]]) 258 | + cert 259 | + end 260 | + 261 | + 262 | def test_client_session 263 | last_session = nil 264 | start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port| 265 | -- 266 | 2.3.0 267 | 268 | --------------------------------------------------------------------------------