From bb9b841c8492e3841bb70a9222b22d9b6518d81e Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 27 Sep 2022 06:55:17 -0400 Subject: [PATCH] import ruby-3.0.4-160.el9_0 --- .gitignore | 2 +- .ruby.metadata | 2 +- ...ruby-3.1.0-Fix-stack-buffer-overflow.patch | 70 -- ...-for-allocating-heap-pages-in-the-GC.patch | 359 ++++++++++ SOURCES/ruby-3.1.1-ossl_ocsp-use-null.patch | 31 + .../ruby-3.1.2-ossl-tests-replace-sha1.patch | 647 ++++++++++++++++++ SPECS/ruby.spec | 49 +- 7 files changed, 1080 insertions(+), 80 deletions(-) delete mode 100644 SOURCES/ruby-3.1.0-Fix-stack-buffer-overflow.patch create mode 100644 SOURCES/ruby-3.1.0-Use-mmap-for-allocating-heap-pages-in-the-GC.patch create mode 100644 SOURCES/ruby-3.1.1-ossl_ocsp-use-null.patch create mode 100644 SOURCES/ruby-3.1.2-ossl-tests-replace-sha1.patch diff --git a/.gitignore b/.gitignore index 9aaa189..a915dc1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/ruby-3.0.3.tar.xz +SOURCES/ruby-3.0.4.tar.xz diff --git a/.ruby.metadata b/.ruby.metadata index 5b07c5f..34cda36 100644 --- a/.ruby.metadata +++ b/.ruby.metadata @@ -1 +1 @@ -c1e6dac2b8c08afbbee39e25e325c84e1cab7c17 SOURCES/ruby-3.0.3.tar.xz +14461adca874d42a06a11851029dec877d9d28de SOURCES/ruby-3.0.4.tar.xz diff --git a/SOURCES/ruby-3.1.0-Fix-stack-buffer-overflow.patch b/SOURCES/ruby-3.1.0-Fix-stack-buffer-overflow.patch deleted file mode 100644 index 4e842ff..0000000 --- a/SOURCES/ruby-3.1.0-Fix-stack-buffer-overflow.patch +++ /dev/null @@ -1,70 +0,0 @@ -From cc44179cb8419b0e48ef9baa6f1722603643c1a0 Mon Sep 17 00:00:00 2001 -From: Nobuyoshi Nakada -Date: Tue, 17 Aug 2021 22:01:57 +0900 -Subject: [PATCH] Fix stack buffer overflow - -https://hackerone.com/reports/1306859 ---- - include/ruby/internal/memory.h | 6 +++--- - random.c | 7 ++----- - 2 files changed, 5 insertions(+), 8 deletions(-) - -diff --git a/include/ruby/internal/memory.h b/include/ruby/internal/memory.h -index 7d24df4945..64f3101fc2 100644 ---- a/include/ruby/internal/memory.h -+++ b/include/ruby/internal/memory.h -@@ -110,18 +110,18 @@ extern void *alloca(); - ((var) = RBIMPL_CAST((type *)ruby_xrealloc2((void *)(var), (n), sizeof(type)))) - - #define ALLOCA_N(type,n) \ -- RBIMPL_CAST((type *)alloca(rbimpl_size_mul_or_raise(sizeof(type), (n)))) -+ RBIMPL_CAST((type *)(!(n) ? NULL : alloca(rbimpl_size_mul_or_raise(sizeof(type), (n))))) - - /* allocates _n_ bytes temporary buffer and stores VALUE including it - * in _v_. _n_ may be evaluated twice. */ - #define RB_ALLOCV(v, n) \ - ((n) < RUBY_ALLOCV_LIMIT ? \ -- ((v) = 0, alloca(n)) : \ -+ ((v) = 0, !(n) ? NULL : alloca(n)) : \ - rb_alloc_tmp_buffer(&(v), (n))) - #define RB_ALLOCV_N(type, v, n) \ - RBIMPL_CAST((type *) \ - (((size_t)(n) < RUBY_ALLOCV_LIMIT / sizeof(type)) ? \ -- ((v) = 0, alloca((n) * sizeof(type))) : \ -+ ((v) = 0, !(n) ? NULL : alloca((n) * sizeof(type))) : \ - rb_alloc_tmp_buffer2(&(v), (n), sizeof(type)))) - #define RB_ALLOCV_END(v) rb_free_tmp_buffer(&(v)) - -diff --git a/random.c b/random.c -index 7567d13dd7..4d70c17116 100644 ---- a/random.c -+++ b/random.c -@@ -369,15 +369,12 @@ rand_init(const rb_random_interface_t *rng, rb_random_t *rnd, VALUE seed) - int sign; - - len = rb_absint_numwords(seed, 32, NULL); -+ if (len == 0) len = 1; - buf = ALLOCV_N(uint32_t, buf0, len); - sign = rb_integer_pack(seed, buf, len, sizeof(uint32_t), 0, - INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER); - if (sign < 0) - sign = -sign; -- if (len == 0) { -- buf[0] = 0; -- len = 1; -- } - if (len > 1) { - if (sign != 2 && buf[len-1] == 1) /* remove leading-zero-guard */ - len--; -@@ -814,7 +811,7 @@ rand_mt_init(rb_random_t *rnd, const uint32_t *buf, size_t len) - { - struct MT *mt = &((rb_random_mt_t *)rnd)->mt; - if (len <= 1) { -- init_genrand(mt, buf[0]); -+ init_genrand(mt, len ? buf[0] : 0); - } - else { - init_by_array(mt, buf, (int)len); --- -2.34.1 - diff --git a/SOURCES/ruby-3.1.0-Use-mmap-for-allocating-heap-pages-in-the-GC.patch b/SOURCES/ruby-3.1.0-Use-mmap-for-allocating-heap-pages-in-the-GC.patch new file mode 100644 index 0000000..512be18 --- /dev/null +++ b/SOURCES/ruby-3.1.0-Use-mmap-for-allocating-heap-pages-in-the-GC.patch @@ -0,0 +1,359 @@ +From bcab8c3cd877506de75f50e0f9ed98827ed554b0 Mon Sep 17 00:00:00 2001 +From: Peter Zhu +Date: Tue, 23 Feb 2021 16:28:56 -0500 +Subject: [PATCH] Use mmap for allocating heap pages + +--- + configure.ac | 16 ++++ + gc.c | 149 ++++++++++++++++++++++++++--------- + test/ruby/test_gc_compact.rb | 41 ++++++---- + 3 files changed, 155 insertions(+), 51 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 2dcebdde9f..b1b190004d 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1944,6 +1944,7 @@ AC_CHECK_FUNCS(memmem) + AC_CHECK_FUNCS(mkfifo) + AC_CHECK_FUNCS(mknod) + AC_CHECK_FUNCS(mktime) ++AC_CHECK_FUNCS(mmap) + AC_CHECK_FUNCS(openat) + AC_CHECK_FUNCS(pipe2) + AC_CHECK_FUNCS(poll) +@@ -2666,6 +2667,21 @@ main(int argc, char *argv[]) + rb_cv_fork_with_pthread=yes)]) + test x$rb_cv_fork_with_pthread = xyes || AC_DEFINE(CANNOT_FORK_WITH_PTHREAD) + ]) ++ ++AC_CHECK_HEADERS([sys/user.h]) ++AS_IF([test "x$ac_cv_func_mmap" = xyes], [ ++ AC_CACHE_CHECK([whether PAGE_SIZE is compile-time const], rb_cv_const_page_size, ++ [malloc_headers=`sed -n '/MALLOC_HEADERS_BEGIN/,/MALLOC_HEADERS_END/p' ${srcdir}/gc.c` ++ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$malloc_headers ++ typedef char conftest_page[PAGE_SIZE]; ++ ]], [[]])], ++ [rb_cv_const_page_size=yes], ++ [rb_cv_const_page_size=no])]) ++]) ++AS_IF([test "x$rb_cv_const_page_size" = xyes], ++ [AC_DEFINE(HAVE_CONST_PAGE_SIZE, 1)], ++ [AC_DEFINE(HAVE_CONST_PAGE_SIZE, 0)] ++) + } + + : "runtime section" && { +diff --git a/gc.c b/gc.c +index f6acf3e117..6f8e5f242d 100644 +--- a/gc.c ++++ b/gc.c +@@ -32,6 +32,7 @@ + #include + #include + ++/* MALLOC_HEADERS_BEGIN */ + #ifndef HAVE_MALLOC_USABLE_SIZE + # ifdef _WIN32 + # define HAVE_MALLOC_USABLE_SIZE +@@ -54,6 +55,12 @@ + # endif + #endif + ++#if !defined(PAGE_SIZE) && defined(HAVE_SYS_USER_H) ++/* LIST_HEAD conflicts with sys/queue.h on macOS */ ++# include ++#endif ++/* MALLOC_HEADERS_END */ ++ + #ifdef HAVE_SYS_TIME_H + # include + #endif +@@ -821,6 +828,25 @@ enum { + HEAP_PAGE_BITMAP_SIZE = (BITS_SIZE * HEAP_PAGE_BITMAP_LIMIT), + HEAP_PAGE_BITMAP_PLANES = 4 /* RGENGC: mark, unprotected, uncollectible, marking */ + }; ++#define HEAP_PAGE_ALIGN (1 << HEAP_PAGE_ALIGN_LOG) ++#define HEAP_PAGE_SIZE HEAP_PAGE_ALIGN ++ ++#ifdef HAVE_MMAP ++# if HAVE_CONST_PAGE_SIZE ++/* If we have the HEAP_PAGE and it is a constant, then we can directly use it. */ ++static const bool USE_MMAP_ALIGNED_ALLOC = (PAGE_SIZE <= HEAP_PAGE_SIZE); ++# elif defined(PAGE_MAX_SIZE) && (PAGE_MAX_SIZE <= HEAP_PAGE_SIZE) ++/* PAGE_SIZE <= HEAP_PAGE_SIZE */ ++static const bool USE_MMAP_ALIGNED_ALLOC = true; ++# else ++/* Otherwise, fall back to determining if we can use mmap during runtime. */ ++# define USE_MMAP_ALIGNED_ALLOC (use_mmap_aligned_alloc != false) ++ ++static bool use_mmap_aligned_alloc; ++# endif ++#elif !defined(__MINGW32__) && !defined(_WIN32) ++static const bool USE_MMAP_ALIGNED_ALLOC = false; ++#endif + + struct heap_page { + short total_slots; +@@ -1760,14 +1786,14 @@ heap_unlink_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *pag + heap->total_slots -= page->total_slots; + } + +-static void rb_aligned_free(void *ptr); ++static void rb_aligned_free(void *ptr, size_t size); + + static void + heap_page_free(rb_objspace_t *objspace, struct heap_page *page) + { + heap_allocated_pages--; + objspace->profile.total_freed_pages++; +- rb_aligned_free(GET_PAGE_BODY(page->start)); ++ rb_aligned_free(GET_PAGE_BODY(page->start), HEAP_PAGE_SIZE); + free(page); + } + +@@ -1819,7 +1845,7 @@ heap_page_allocate(rb_objspace_t *objspace) + /* assign heap_page entry */ + page = calloc1(sizeof(struct heap_page)); + if (page == 0) { +- rb_aligned_free(page_body); ++ rb_aligned_free(page_body, HEAP_PAGE_SIZE); + rb_memerror(); + } + +@@ -3159,15 +3185,18 @@ Init_heap(void) + { + rb_objspace_t *objspace = &rb_objspace; + +-#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) +- /* If Ruby's heap pages are not a multiple of the system page size, we +- * cannot use mprotect for the read barrier, so we must disable automatic +- * compaction. */ +- int pagesize; +- pagesize = (int)sysconf(_SC_PAGE_SIZE); +- if ((HEAP_PAGE_SIZE % pagesize) != 0) { +- ruby_enable_autocompact = 0; +- } ++#if defined(HAVE_MMAP) && !HAVE_CONST_PAGE_SIZE && !defined(PAGE_MAX_SIZE) ++ /* Need to determine if we can use mmap at runtime. */ ++# ifdef PAGE_SIZE ++ /* If the PAGE_SIZE macro can be used. */ ++ use_mmap_aligned_alloc = PAGE_SIZE <= HEAP_PAGE_SIZE; ++# elif defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) ++ /* If we can use sysconf to determine the page size. */ ++ use_mmap_aligned_alloc = sysconf(_SC_PAGE_SIZE) <= HEAP_PAGE_SIZE; ++# else ++ /* Otherwise we can't determine the system page size, so don't use mmap. */ ++ use_mmap_aligned_alloc = FALSE; ++# endif + #endif + + objspace->next_object_id = INT2FIX(OBJ_ID_INITIAL); +@@ -8533,6 +8562,14 @@ gc_start_internal(rb_execution_context_t *ec, VALUE self, VALUE full_mark, VALUE + + /* For now, compact implies full mark / sweep, so ignore other flags */ + if (RTEST(compact)) { ++ /* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for ++ * the read barrier, so we must disable compaction. */ ++#if !defined(__MINGW32__) && !defined(_WIN32) ++ if (!USE_MMAP_ALIGNED_ALLOC) { ++ rb_raise(rb_eNotImpError, "Compaction isn't available on this platform"); ++ } ++#endif ++ + reason |= GPR_FLAG_COMPACT; + } else { + if (!RTEST(full_mark)) reason &= ~GPR_FLAG_FULL_MARK; +@@ -9944,16 +9981,14 @@ gc_disable(rb_execution_context_t *ec, VALUE _) + static VALUE + gc_set_auto_compact(rb_execution_context_t *ec, VALUE _, VALUE v) + { +-#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) +- /* If Ruby's heap pages are not a multiple of the system page size, we +- * cannot use mprotect for the read barrier, so we must disable automatic +- * compaction. */ +- int pagesize; +- pagesize = (int)sysconf(_SC_PAGE_SIZE); +- if ((HEAP_PAGE_SIZE % pagesize) != 0) { ++ /* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for ++ * the read barrier, so we must disable automatic compaction. */ ++#if !defined(__MINGW32__) && !defined(_WIN32) ++ if (!USE_MMAP_ALIGNED_ALLOC) { + rb_raise(rb_eNotImpError, "Automatic compaction isn't available on this platform"); + } + #endif ++ + ruby_enable_autocompact = RTEST(v); + return v; + } +@@ -10350,22 +10385,54 @@ rb_aligned_malloc(size_t alignment, size_t size) + #elif defined _WIN32 + void *_aligned_malloc(size_t, size_t); + res = _aligned_malloc(size, alignment); +-#elif defined(HAVE_POSIX_MEMALIGN) +- if (posix_memalign(&res, alignment, size) == 0) { +- return res; ++#else ++ if (USE_MMAP_ALIGNED_ALLOC) { ++ GC_ASSERT(alignment % sysconf(_SC_PAGE_SIZE) == 0); ++ ++ char *ptr = mmap(NULL, alignment + size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ++ if (ptr == MAP_FAILED) { ++ return NULL; ++ } ++ ++ char *aligned = ptr + alignment; ++ aligned -= ((VALUE)aligned & (alignment - 1)); ++ GC_ASSERT(aligned > ptr); ++ GC_ASSERT(aligned <= ptr + alignment); ++ ++ size_t start_out_of_range_size = aligned - ptr; ++ GC_ASSERT(start_out_of_range_size % sysconf(_SC_PAGE_SIZE) == 0); ++ if (start_out_of_range_size > 0) { ++ if (munmap(ptr, start_out_of_range_size)) { ++ rb_bug("rb_aligned_malloc: munmap failed for start"); ++ } ++ } ++ ++ size_t end_out_of_range_size = alignment - start_out_of_range_size; ++ GC_ASSERT(end_out_of_range_size % sysconf(_SC_PAGE_SIZE) == 0); ++ if (end_out_of_range_size > 0) { ++ if (munmap(aligned + size, end_out_of_range_size)) { ++ rb_bug("rb_aligned_malloc: munmap failed for end"); ++ } ++ } ++ ++ res = (void *)aligned; + } + else { +- return NULL; ++# if defined(HAVE_POSIX_MEMALIGN) ++ if (posix_memalign(&res, alignment, size) != 0) { ++ return NULL; ++ } ++# elif defined(HAVE_MEMALIGN) ++ res = memalign(alignment, size); ++# else ++ char* aligned; ++ res = malloc(alignment + size + sizeof(void*)); ++ aligned = (char*)res + alignment + sizeof(void*); ++ aligned -= ((VALUE)aligned & (alignment - 1)); ++ ((void**)aligned)[-1] = res; ++ res = (void*)aligned; ++# endif + } +-#elif defined(HAVE_MEMALIGN) +- res = memalign(alignment, size); +-#else +- char* aligned; +- res = malloc(alignment + size + sizeof(void*)); +- aligned = (char*)res + alignment + sizeof(void*); +- aligned -= ((VALUE)aligned & (alignment - 1)); +- ((void**)aligned)[-1] = res; +- res = (void*)aligned; + #endif + + /* alignment must be a power of 2 */ +@@ -10375,16 +10442,26 @@ rb_aligned_malloc(size_t alignment, size_t size) + } + + static void +-rb_aligned_free(void *ptr) ++rb_aligned_free(void *ptr, size_t size) + { + #if defined __MINGW32__ + __mingw_aligned_free(ptr); + #elif defined _WIN32 + _aligned_free(ptr); +-#elif defined(HAVE_MEMALIGN) || defined(HAVE_POSIX_MEMALIGN) +- free(ptr); + #else +- free(((void**)ptr)[-1]); ++ if (USE_MMAP_ALIGNED_ALLOC) { ++ GC_ASSERT(size % sysconf(_SC_PAGE_SIZE) == 0); ++ if (munmap(ptr, size)) { ++ rb_bug("rb_aligned_free: munmap failed"); ++ } ++ } ++ else { ++# if defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN) ++ free(ptr); ++# else ++ free(((void**)ptr)[-1]); ++# endif ++ } + #endif + } + +diff --git a/test/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb +index 4a8cff33f4..f5cab55ba7 100644 +--- a/test/ruby/test_gc_compact.rb ++++ b/test/ruby/test_gc_compact.rb +@@ -4,12 +4,32 @@ + require 'etc' + + class TestGCCompact < Test::Unit::TestCase +- class AutoCompact < Test::Unit::TestCase ++ module SupportsCompact + def setup + skip "autocompact not supported on this platform" unless supports_auto_compact? + super + end + ++ private ++ ++ def supports_auto_compact? ++ return true unless defined?(Etc::SC_PAGE_SIZE) ++ ++ begin ++ return GC::INTERNAL_CONSTANTS[:HEAP_PAGE_SIZE] % Etc.sysconf(Etc::SC_PAGE_SIZE) == 0 ++ rescue NotImplementedError ++ rescue ArgumentError ++ end ++ ++ true ++ end ++ end ++ ++ include SupportsCompact ++ ++ class AutoCompact < Test::Unit::TestCase ++ include SupportsCompact ++ + def test_enable_autocompact + before = GC.auto_compact + GC.auto_compact = true +@@ -59,26 +79,17 @@ def test_implicit_compaction_does_something + ensure + GC.auto_compact = before + end +- +- private +- +- def supports_auto_compact? +- return true unless defined?(Etc::SC_PAGE_SIZE) +- +- begin +- return GC::INTERNAL_CONSTANTS[:HEAP_PAGE_SIZE] % Etc.sysconf(Etc::SC_PAGE_SIZE) == 0 +- rescue NotImplementedError +- rescue ArgumentError +- end +- +- true +- end + end + + def os_page_size + return true unless defined?(Etc::SC_PAGE_SIZE) + end + ++ def setup ++ skip "autocompact not supported on this platform" unless supports_auto_compact? ++ super ++ end ++ + def test_gc_compact_stats + list = [] + +-- +2.30.1 (Apple Git-130) + diff --git a/SOURCES/ruby-3.1.1-ossl_ocsp-use-null.patch b/SOURCES/ruby-3.1.1-ossl_ocsp-use-null.patch new file mode 100644 index 0000000..d6d39ef --- /dev/null +++ b/SOURCES/ruby-3.1.1-ossl_ocsp-use-null.patch @@ -0,0 +1,31 @@ +--- ext/openssl/ossl_ocsp.c.orig 2022-04-07 16:40:13.263752886 +0200 ++++ ext/openssl/ossl_ocsp.c 2022-04-07 16:45:56.818971187 +0200 +@@ -382,7 +382,7 @@ + if (!NIL_P(flags)) + flg = NUM2INT(flags); + if (NIL_P(digest)) +- md = EVP_sha1(); ++ md = NULL; + else + md = ossl_evp_get_digestbyname(digest); + if (NIL_P(certs)) +@@ -1033,7 +1033,7 @@ + if (!NIL_P(flags)) + flg = NUM2INT(flags); + if (NIL_P(digest)) +- md = EVP_sha1(); ++ md = NULL; + else + md = ossl_evp_get_digestbyname(digest); + if (NIL_P(certs)) +--- test/openssl/test_ocsp.rb.orig 2022-04-08 08:20:31.400739869 +0200 ++++ test/openssl/test_ocsp.rb 2022-04-08 08:20:37.208727488 +0200 +@@ -99,7 +99,7 @@ + request.sign(@cert, @cert_key, [@ca_cert], 0) + asn1 = OpenSSL::ASN1.decode(request.to_der) + assert_equal cid.to_der, asn1.value[0].value.find { |a| a.tag_class == :UNIVERSAL }.value[0].value[0].to_der +- assert_equal OpenSSL::ASN1.ObjectId("sha1WithRSAEncryption").to_der, asn1.value[1].value[0].value[0].value[0].to_der ++ assert_equal OpenSSL::ASN1.ObjectId("sha256WithRSAEncryption").to_der, asn1.value[1].value[0].value[0].value[0].to_der + assert_equal @cert.to_der, asn1.value[1].value[0].value[2].value[0].value[0].to_der + assert_equal @ca_cert.to_der, asn1.value[1].value[0].value[2].value[0].value[1].to_der + assert_equal asn1.to_der, OpenSSL::OCSP::Request.new(asn1.to_der).to_der diff --git a/SOURCES/ruby-3.1.2-ossl-tests-replace-sha1.patch b/SOURCES/ruby-3.1.2-ossl-tests-replace-sha1.patch new file mode 100644 index 0000000..176101c --- /dev/null +++ b/SOURCES/ruby-3.1.2-ossl-tests-replace-sha1.patch @@ -0,0 +1,647 @@ +diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb +index fedcb93..53ad621 100644 +--- a/ext/openssl/extconf.rb ++++ b/ext/openssl/extconf.rb +@@ -174,6 +174,7 @@ have_func("SSL_CTX_set_post_handshake_auth") + + # added in 1.1.1 + have_func("EVP_PKEY_check") ++have_func("SSL_CTX_set_ciphersuites") + + # added in 3.0.0 + have_func("TS_VERIFY_CTX_set_certs(NULL, NULL)", "openssl/ts.h") +diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h +index 4b51268..2ab8aea 100644 +--- a/ext/openssl/ossl.h ++++ b/ext/openssl/ossl.h +@@ -43,13 +43,13 @@ + #ifndef LIBRESSL_VERSION_NUMBER + # define OSSL_IS_LIBRESSL 0 + # define OSSL_OPENSSL_PREREQ(maj, min, pat) \ +- (OPENSSL_VERSION_NUMBER >= (maj << 28) | (min << 20) | (pat << 12)) ++ (OPENSSL_VERSION_NUMBER >= ((maj << 28) | (min << 20) | (pat << 12))) + # define OSSL_LIBRESSL_PREREQ(maj, min, pat) 0 + #else + # define OSSL_IS_LIBRESSL 1 + # define OSSL_OPENSSL_PREREQ(maj, min, pat) 0 + # define OSSL_LIBRESSL_PREREQ(maj, min, pat) \ +- (LIBRESSL_VERSION_NUMBER >= (maj << 28) | (min << 20) | (pat << 12)) ++ (LIBRESSL_VERSION_NUMBER >= ((maj << 28) | (min << 20) | (pat << 12))) + #endif + + #if !defined(OPENSSL_NO_ENGINE) && !OSSL_OPENSSL_PREREQ(3, 0, 0) +diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c +index a61d3ee..0d3fa9a 100644 +--- a/ext/openssl/ossl_asn1.c ++++ b/ext/openssl/ossl_asn1.c +@@ -1510,7 +1510,7 @@ Init_ossl_asn1(void) + * + * An Array that stores the name of a given tag number. These names are + * the same as the name of the tag constant that is additionally defined, +- * e.g. UNIVERSAL_TAG_NAME[2] = "INTEGER" and OpenSSL::ASN1::INTEGER = 2. ++ * e.g. UNIVERSAL_TAG_NAME[2] = "INTEGER" and OpenSSL::ASN1::INTEGER = 2. + * + * == Example usage + * +diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c +index 2a4835a..24d0da4 100644 +--- a/ext/openssl/ossl_pkey.c ++++ b/ext/openssl/ossl_pkey.c +@@ -649,7 +649,7 @@ ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self, int to_der) + } + } + else { +-#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER) ++#if OSSL_OPENSSL_PREREQ(1, 1, 0) || OSSL_LIBRESSL_PREREQ(3, 5, 0) + if (!PEM_write_bio_PrivateKey_traditional(bio, pkey, enc, NULL, 0, + ossl_pem_passwd_cb, + (void *)pass)) { +diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c +index 9a0682a..af262d9 100644 +--- a/ext/openssl/ossl_ssl.c ++++ b/ext/openssl/ossl_ssl.c +@@ -1025,27 +1025,13 @@ ossl_sslctx_get_ciphers(VALUE self) + return ary; + } + +-/* +- * call-seq: +- * ctx.ciphers = "cipher1:cipher2:..." +- * ctx.ciphers = [name, ...] +- * ctx.ciphers = [[name, version, bits, alg_bits], ...] +- * +- * Sets the list of available cipher suites for this context. Note in a server +- * context some ciphers require the appropriate certificates. For example, an +- * RSA cipher suite can only be chosen when an RSA certificate is available. +- */ + static VALUE +-ossl_sslctx_set_ciphers(VALUE self, VALUE v) ++build_cipher_string(VALUE v) + { +- SSL_CTX *ctx; + VALUE str, elem; + int i; + +- rb_check_frozen(self); +- if (NIL_P(v)) +- return v; +- else if (RB_TYPE_P(v, T_ARRAY)) { ++ if (RB_TYPE_P(v, T_ARRAY)) { + str = rb_str_new(0, 0); + for (i = 0; i < RARRAY_LEN(v); i++) { + elem = rb_ary_entry(v, i); +@@ -1059,14 +1059,67 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v) + StringValue(str); + } + ++ return str; ++} ++ ++/* ++ * call-seq: ++ * ctx.ciphers = "cipher1:cipher2:..." ++ * ctx.ciphers = [name, ...] ++ * ctx.ciphers = [[name, version, bits, alg_bits], ...] ++ * ++ * Sets the list of available cipher suites for this context. Note in a server ++ * context some ciphers require the appropriate certificates. For example, an ++ * RSA cipher suite can only be chosen when an RSA certificate is available. ++ */ ++static VALUE ++ossl_sslctx_set_ciphers(VALUE self, VALUE v) ++{ ++ SSL_CTX *ctx; ++ VALUE str; ++ ++ rb_check_frozen(self); ++ if (NIL_P(v)) ++ return v; ++ ++ str = build_cipher_string(v); ++ + GetSSLCTX(self, ctx); +- if (!SSL_CTX_set_cipher_list(ctx, StringValueCStr(str))) { ++ if (!SSL_CTX_set_cipher_list(ctx, StringValueCStr(str))) + ossl_raise(eSSLError, "SSL_CTX_set_cipher_list"); +- } + + return v; + } + ++#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES ++/* ++ * call-seq: ++ * ctx.ciphersuites = "cipher1:cipher2:..." ++ * ctx.ciphersuites = [name, ...] ++ * ctx.ciphersuites = [[name, version, bits, alg_bits], ...] ++ * ++ * Sets the list of available TLSv1.3 cipher suites for this context. ++ */ ++static VALUE ++ossl_sslctx_set_ciphersuites(VALUE self, VALUE v) ++{ ++ SSL_CTX *ctx; ++ VALUE str; ++ ++ rb_check_frozen(self); ++ if (NIL_P(v)) ++ return v; ++ ++ str = build_cipher_string(v); ++ ++ GetSSLCTX(self, ctx); ++ if (!SSL_CTX_set_ciphersuites(ctx, StringValueCStr(str))) ++ ossl_raise(eSSLError, "SSL_CTX_set_ciphersuites"); ++ ++ return v; ++} ++#endif ++ + #if !defined(OPENSSL_NO_EC) + /* + * call-seq: +@@ -2818,6 +2857,9 @@ Init_ossl_ssl(void) + ossl_sslctx_set_minmax_proto_version, 2); + rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0); + rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1); ++#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES ++ rb_define_method(cSSLContext, "ciphersuites=", ossl_sslctx_set_ciphersuites, 1); ++#endif + rb_define_method(cSSLContext, "ecdh_curves=", ossl_sslctx_set_ecdh_curves, 1); + rb_define_method(cSSLContext, "security_level", ossl_sslctx_get_security_level, 0); + rb_define_method(cSSLContext, "security_level=", ossl_sslctx_set_security_level, 1); +diff --git a/test/openssl/test_asn1.rb b/test/openssl/test_asn1.rb +index 0fd7971..c79bc14 100644 +--- a/test/openssl/test_asn1.rb ++++ b/test/openssl/test_asn1.rb +@@ -14,7 +14,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase + ["keyUsage","keyCertSign, cRLSign",true], + ["subjectKeyIdentifier","hash",false], + ] +- dgst = OpenSSL::Digest.new('SHA1') ++ dgst = OpenSSL::Digest.new('SHA256') + cert = OpenSSL::TestUtils.issue_cert( + subj, key, s, exts, nil, nil, digest: dgst, not_before: now, not_after: now+3600) + +@@ -42,7 +42,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase + assert_equal(OpenSSL::ASN1::Sequence, sig.class) + assert_equal(2, sig.value.size) + assert_equal(OpenSSL::ASN1::ObjectId, sig.value[0].class) +- assert_equal("1.2.840.113549.1.1.5", sig.value[0].oid) ++ assert_equal("1.2.840.113549.1.1.11", sig.value[0].oid) + assert_equal(OpenSSL::ASN1::Null, sig.value[1].class) + + dn = tbs_cert.value[3] # issuer +@@ -189,7 +189,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase + assert_equal(OpenSSL::ASN1::Null, pkey.value[0].value[1].class) + + assert_equal(OpenSSL::ASN1::BitString, sig_val.class) +- cululated_sig = key.sign(OpenSSL::Digest.new('SHA1'), tbs_cert.to_der) ++ cululated_sig = key.sign(OpenSSL::Digest.new('SHA256'), tbs_cert.to_der) + assert_equal(cululated_sig, sig_val.value) + end + +diff --git a/test/openssl/test_ns_spki.rb b/test/openssl/test_ns_spki.rb +index ed3be86..383931b 100644 +--- a/test/openssl/test_ns_spki.rb ++++ b/test/openssl/test_ns_spki.rb +@@ -22,7 +22,7 @@ class OpenSSL::TestNSSPI < OpenSSL::TestCase + spki = OpenSSL::Netscape::SPKI.new + spki.challenge = "RandomString" + spki.public_key = key1.public_key +- spki.sign(key1, OpenSSL::Digest.new('SHA1')) ++ spki.sign(key1, OpenSSL::Digest.new('SHA256')) + assert(spki.verify(spki.public_key)) + assert(spki.verify(key1.public_key)) + assert(!spki.verify(key2.public_key)) +diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb +index 726b7db..08213df 100644 +--- a/test/openssl/test_pkey_dsa.rb ++++ b/test/openssl/test_pkey_dsa.rb +@@ -36,8 +36,8 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase + assert_equal true, dsa512.verify(OpenSSL::Digest.new('DSS1'), signature, data) + end + +- signature = dsa512.sign("SHA1", data) +- assert_equal true, dsa512.verify("SHA1", signature, data) ++ signature = dsa512.sign("SHA256", data) ++ assert_equal true, dsa512.verify("SHA256", signature, data) + + signature0 = (<<~'end;').unpack("m")[0] + MCwCFH5h40plgU5Fh0Z4wvEEpz0eE9SnAhRPbkRB8ggsN/vsSEYMXvJwjGg/ +diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb +index ffe5a94..c06fe6f 100644 +--- a/test/openssl/test_pkey_ec.rb ++++ b/test/openssl/test_pkey_ec.rb +@@ -98,8 +98,8 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase + def test_sign_verify + p256 = Fixtures.pkey("p256") + data = "Sign me!" +- signature = p256.sign("SHA1", data) +- assert_equal true, p256.verify("SHA1", signature, data) ++ signature = p256.sign("SHA256", data) ++ assert_equal true, p256.verify("SHA256", signature, data) + + signature0 = (<<~'end;').unpack("m")[0] + MEQCIEOTY/hD7eI8a0qlzxkIt8LLZ8uwiaSfVbjX2dPAvN11AiAQdCYx56Fq +diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb +index 4bb39ed..9e06e43 100644 +--- a/test/openssl/test_pkey_rsa.rb ++++ b/test/openssl/test_pkey_rsa.rb +@@ -80,8 +80,8 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase + def test_sign_verify + rsa1024 = Fixtures.pkey("rsa1024") + data = "Sign me!" +- signature = rsa1024.sign("SHA1", data) +- assert_equal true, rsa1024.verify("SHA1", signature, data) ++ signature = rsa1024.sign("SHA256", data) ++ assert_equal true, rsa1024.verify("SHA256", signature, data) + + signature0 = (<<~'end;').unpack("m")[0] + oLCgbprPvfhM4pjFQiDTFeWI9Sk+Og7Nh9TmIZ/xSxf2CGXQrptlwo7NQ28+ +@@ -113,10 +113,10 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase + def test_sign_verify_raw + key = Fixtures.pkey("rsa-1") + data = "Sign me!" +- hash = OpenSSL::Digest.digest("SHA1", data) +- signature = key.sign_raw("SHA1", hash) +- assert_equal true, key.verify_raw("SHA1", signature, hash) +- assert_equal true, key.verify("SHA1", signature, data) ++ hash = OpenSSL::Digest.digest("SHA256", data) ++ signature = key.sign_raw("SHA256", hash) ++ assert_equal true, key.verify_raw("SHA256", signature, hash) ++ assert_equal true, key.verify("SHA256", signature, data) + + # Too long data + assert_raise(OpenSSL::PKey::PKeyError) { +@@ -129,9 +129,9 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase + "rsa_pss_saltlen" => 20, + "rsa_mgf1_md" => "SHA256" + } +- sig_pss = key.sign_raw("SHA1", hash, pssopts) +- assert_equal true, key.verify("SHA1", sig_pss, data, pssopts) +- assert_equal true, key.verify_raw("SHA1", sig_pss, hash, pssopts) ++ sig_pss = key.sign_raw("SHA256", hash, pssopts) ++ assert_equal true, key.verify("SHA256", sig_pss, data, pssopts) ++ assert_equal true, key.verify_raw("SHA256", sig_pss, hash, pssopts) + end + + def test_sign_verify_raw_legacy +diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb +index a7607da..3ba8b39 100644 +--- a/test/openssl/test_ssl.rb ++++ b/test/openssl/test_ssl.rb +@@ -669,10 +669,16 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase + # buzz.example.net, respectively). ... + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:baz*.example.com'), 'baz1.example.com')) ++ ++ # LibreSSL 3.5.0+ doesn't support other wildcard certificates ++ # (it isn't required to, as RFC states MAY, not MUST) ++ return if libressl?(3, 5, 0) ++ + 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. + # +@@ -1556,8 +1562,101 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase + end + end + ++ def test_ciphersuites_method_tls_connection ++ ssl_ctx = OpenSSL::SSL::SSLContext.new ++ if !tls13_supported? || !ssl_ctx.respond_to?(:ciphersuites=) ++ pend 'TLS 1.3 not supported' ++ end ++ ++ csuite = ['TLS_AES_128_GCM_SHA256', 'TLSv1.3', 128, 128] ++ inputs = [csuite[0], [csuite[0]], [csuite]] ++ ++ start_server do |port| ++ inputs.each do |input| ++ cli_ctx = OpenSSL::SSL::SSLContext.new ++ cli_ctx.min_version = cli_ctx.max_version = OpenSSL::SSL::TLS1_3_VERSION ++ cli_ctx.ciphersuites = input ++ ++ server_connect(port, cli_ctx) do |ssl| ++ assert_equal('TLSv1.3', ssl.ssl_version) ++ if libressl?(3, 4, 0) && !libressl?(3, 5, 0) ++ assert_equal("AEAD-AES128-GCM-SHA256", ssl.cipher[0]) ++ else ++ assert_equal(csuite[0], ssl.cipher[0]) ++ end ++ ssl.puts('abc'); assert_equal("abc\n", ssl.gets) ++ end ++ end ++ end ++ end ++ ++ def test_ciphersuites_method_nil_argument ++ ssl_ctx = OpenSSL::SSL::SSLContext.new ++ pend 'ciphersuites= method is missing' unless ssl_ctx.respond_to?(:ciphersuites=) ++ ++ assert_nothing_raised { ssl_ctx.ciphersuites = nil } ++ end ++ ++ def test_ciphersuites_method_frozen_object ++ ssl_ctx = OpenSSL::SSL::SSLContext.new ++ pend 'ciphersuites= method is missing' unless ssl_ctx.respond_to?(:ciphersuites=) ++ ++ ssl_ctx.freeze ++ assert_raise(FrozenError) { ssl_ctx.ciphersuites = 'TLS_AES_256_GCM_SHA384' } ++ end ++ ++ def test_ciphersuites_method_bogus_csuite ++ ssl_ctx = OpenSSL::SSL::SSLContext.new ++ pend 'ciphersuites= method is missing' unless ssl_ctx.respond_to?(:ciphersuites=) ++ ++ assert_raise_with_message( ++ OpenSSL::SSL::SSLError, ++ /SSL_CTX_set_ciphersuites: no cipher match/i ++ ) { ssl_ctx.ciphersuites = 'BOGUS' } ++ end ++ ++ def test_ciphers_method_tls_connection ++ csuite = ['ECDHE-RSA-AES256-GCM-SHA384', 'TLSv1.2', 256, 256] ++ inputs = [csuite[0], [csuite[0]], [csuite]] ++ ++ start_server do |port| ++ inputs.each do |input| ++ cli_ctx = OpenSSL::SSL::SSLContext.new ++ cli_ctx.min_version = cli_ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION ++ cli_ctx.ciphers = input ++ ++ server_connect(port, cli_ctx) do |ssl| ++ assert_equal('TLSv1.2', ssl.ssl_version) ++ assert_equal(csuite[0], ssl.cipher[0]) ++ ssl.puts('abc'); assert_equal("abc\n", ssl.gets) ++ end ++ end ++ end ++ end ++ ++ def test_ciphers_method_nil_argument ++ ssl_ctx = OpenSSL::SSL::SSLContext.new ++ assert_nothing_raised { ssl_ctx.ciphers = nil } ++ end ++ ++ def test_ciphers_method_frozen_object ++ ssl_ctx = OpenSSL::SSL::SSLContext.new ++ ++ ssl_ctx.freeze ++ assert_raise(FrozenError) { ssl_ctx.ciphers = 'ECDHE-RSA-AES128-SHA' } ++ end ++ ++ def test_ciphers_method_bogus_csuite ++ ssl_ctx = OpenSSL::SSL::SSLContext.new ++ ++ assert_raise_with_message( ++ OpenSSL::SSL::SSLError, ++ /SSL_CTX_set_cipher_list: no cipher match/i ++ ) { ssl_ctx.ciphers = 'BOGUS' } ++ end ++ + def test_connect_works_when_setting_dh_callback_to_nil + pend "TLS 1.2 is not supported" unless tls12_supported? + + ctx_proc = -> ctx { + ctx.ssl_version = :TLSv1_2 +diff --git a/test/openssl/test_x509cert.rb b/test/openssl/test_x509cert.rb +index d696b98..4e2bd0c 100644 +--- a/test/openssl/test_x509cert.rb ++++ b/test/openssl/test_x509cert.rb +@@ -180,6 +180,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase + assert_equal(false, certificate_error_returns_false { cert.verify(@dsa512) }) + cert.serial = 2 + assert_equal(false, cert.verify(@rsa2048)) ++ rescue OpenSSL::X509::CertificateError # RHEL 9 disables SHA1 + end + + def test_sign_and_verify_rsa_md5 +@@ -226,9 +227,8 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase + assert_equal("dsa_with_SHA256", cert.signature_algorithm) + # TODO: need more tests for dsa + sha2 + +- # SHA1 is allowed from OpenSSL 1.0.0 (0.9.8 requires DSS1) +- cert = issue_cert(@ca, @dsa256, 1, [], nil, nil, digest: "sha1") +- assert_equal("dsaWithSHA1", cert.signature_algorithm) ++ cert = issue_cert(@ca, @dsa256, 1, [], nil, nil, digest: "sha512") ++ assert_equal("dsa_with_SHA512", cert.signature_algorithm) + end + + def test_check_private_key +diff --git a/test/openssl/test_x509crl.rb b/test/openssl/test_x509crl.rb +index bcdb0a6..146ee07 100644 +--- a/test/openssl/test_x509crl.rb ++++ b/test/openssl/test_x509crl.rb +@@ -20,7 +20,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase + + cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) + crl = issue_crl([], 1, now, now+1600, [], +- cert, @rsa2048, OpenSSL::Digest.new('SHA1')) ++ cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + assert_equal(1, crl.version) + assert_equal(cert.issuer.to_der, crl.issuer.to_der) + assert_equal(now, crl.last_update) +@@ -57,7 +57,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase + ] + cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) + crl = issue_crl(revoke_info, 1, Time.now, Time.now+1600, [], +- cert, @rsa2048, OpenSSL::Digest.new('SHA1')) ++ cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + revoked = crl.revoked + assert_equal(5, revoked.size) + assert_equal(1, revoked[0].serial) +@@ -98,7 +98,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase + + revoke_info = (1..1000).collect{|i| [i, now, 0] } + crl = issue_crl(revoke_info, 1, Time.now, Time.now+1600, [], +- cert, @rsa2048, OpenSSL::Digest.new('SHA1')) ++ cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + revoked = crl.revoked + assert_equal(1000, revoked.size) + assert_equal(1, revoked[0].serial) +@@ -124,7 +124,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase + + cert = issue_cert(@ca, @rsa2048, 1, cert_exts, nil, nil) + crl = issue_crl([], 1, Time.now, Time.now+1600, crl_exts, +- cert, @rsa2048, OpenSSL::Digest.new('SHA1')) ++ cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + exts = crl.extensions + assert_equal(3, exts.size) + assert_equal("1", exts[0].value) +@@ -160,24 +160,24 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase + assert_equal(false, exts[2].critical?) + + no_ext_crl = issue_crl([], 1, Time.now, Time.now+1600, [], +- cert, @rsa2048, OpenSSL::Digest.new('SHA1')) ++ cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + assert_equal nil, no_ext_crl.authority_key_identifier + end + + def test_crlnumber + cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) + crl = issue_crl([], 1, Time.now, Time.now+1600, [], +- cert, @rsa2048, OpenSSL::Digest.new('SHA1')) ++ cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + assert_match(1.to_s, crl.extensions[0].value) + assert_match(/X509v3 CRL Number:\s+#{1}/m, crl.to_text) + + crl = issue_crl([], 2**32, Time.now, Time.now+1600, [], +- cert, @rsa2048, OpenSSL::Digest.new('SHA1')) ++ cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + assert_match((2**32).to_s, crl.extensions[0].value) + assert_match(/X509v3 CRL Number:\s+#{2**32}/m, crl.to_text) + + crl = issue_crl([], 2**100, Time.now, Time.now+1600, [], +- cert, @rsa2048, OpenSSL::Digest.new('SHA1')) ++ cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + assert_match(/X509v3 CRL Number:\s+#{2**100}/m, crl.to_text) + assert_match((2**100).to_s, crl.extensions[0].value) + end +@@ -185,7 +185,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase + def test_sign_and_verify + cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) + crl = issue_crl([], 1, Time.now, Time.now+1600, [], +- cert, @rsa2048, OpenSSL::Digest.new('SHA1')) ++ cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + assert_equal(false, crl.verify(@rsa1024)) + assert_equal(true, crl.verify(@rsa2048)) + assert_equal(false, crl_error_returns_false { crl.verify(@dsa256) }) +@@ -195,7 +195,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase + + cert = issue_cert(@ca, @dsa512, 1, [], nil, nil) + crl = issue_crl([], 1, Time.now, Time.now+1600, [], +- cert, @dsa512, OpenSSL::Digest.new('SHA1')) ++ cert, @dsa512, OpenSSL::Digest.new('SHA256')) + assert_equal(false, crl_error_returns_false { crl.verify(@rsa1024) }) + assert_equal(false, crl_error_returns_false { crl.verify(@rsa2048) }) + assert_equal(false, crl.verify(@dsa256)) +diff --git a/test/openssl/test_x509req.rb b/test/openssl/test_x509req.rb +index ee9c678..a84b162 100644 +--- a/test/openssl/test_x509req.rb ++++ b/test/openssl/test_x509req.rb +@@ -23,31 +23,31 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase + end + + def test_public_key +- req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) ++ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) + assert_equal(@rsa1024.public_key.to_der, req.public_key.to_der) + req = OpenSSL::X509::Request.new(req.to_der) + assert_equal(@rsa1024.public_key.to_der, req.public_key.to_der) + +- req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA1')) ++ req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA256')) + assert_equal(@dsa512.public_key.to_der, req.public_key.to_der) + req = OpenSSL::X509::Request.new(req.to_der) + assert_equal(@dsa512.public_key.to_der, req.public_key.to_der) + end + + def test_version +- req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) ++ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) + assert_equal(0, req.version) + req = OpenSSL::X509::Request.new(req.to_der) + assert_equal(0, req.version) + +- req = issue_csr(1, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) ++ req = issue_csr(1, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) + assert_equal(1, req.version) + req = OpenSSL::X509::Request.new(req.to_der) + assert_equal(1, req.version) + end + + def test_subject +- req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) ++ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) + assert_equal(@dn.to_der, req.subject.to_der) + req = OpenSSL::X509::Request.new(req.to_der) + assert_equal(@dn.to_der, req.subject.to_der) +@@ -78,9 +78,9 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase + OpenSSL::X509::Attribute.new("msExtReq", attrval), + ] + +- req0 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) ++ req0 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) + attrs.each{|attr| req0.add_attribute(attr) } +- req1 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) ++ req1 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) + req1.attributes = attrs + assert_equal(req0.to_der, req1.to_der) + +@@ -101,7 +101,7 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase + end + + def test_sign_and_verify_rsa_sha1 +- req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) ++ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) + assert_equal(true, req.verify(@rsa1024)) + assert_equal(false, req.verify(@rsa2048)) + assert_equal(false, request_error_returns_false { req.verify(@dsa256) }) +@@ -122,7 +122,7 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase + end + + def test_sign_and_verify_dsa +- req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA1')) ++ req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA256')) + assert_equal(false, request_error_returns_false { req.verify(@rsa1024) }) + assert_equal(false, request_error_returns_false { req.verify(@rsa2048) }) + assert_equal(false, req.verify(@dsa256)) +@@ -137,13 +137,13 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase + end + + def test_dup +- req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) ++ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) + assert_equal(req.to_der, req.dup.to_der) + end + + def test_eq +- req1 = issue_csr(0, @dn, @rsa1024, "sha1") +- req2 = issue_csr(0, @dn, @rsa1024, "sha1") ++ req1 = issue_csr(0, @dn, @rsa1024, "sha512") ++ req2 = issue_csr(0, @dn, @rsa1024, "sha512") + req3 = issue_csr(0, @dn, @rsa1024, "sha256") + + assert_equal false, req1 == 12345 +--- a/test/openssl/test_x509store.rb.orig 2022-07-14 14:07:32.468809273 +0200 ++++ b/test/openssl/test_x509store.rb 2022-07-13 17:27:58.115363595 +0200 +@@ -72,16 +72,16 @@ + + revoke_info = [] + crl1 = issue_crl(revoke_info, 1, now, now+1800, [], +- ca1_cert, @rsa2048, OpenSSL::Digest.new('SHA1')) ++ ca1_cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + revoke_info = [ [2, now, 1], ] + crl1_2 = issue_crl(revoke_info, 2, now, now+1800, [], +- ca1_cert, @rsa2048, OpenSSL::Digest.new('SHA1')) ++ ca1_cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + revoke_info = [ [20, now, 1], ] + crl2 = issue_crl(revoke_info, 1, now, now+1800, [], +- ca2_cert, @rsa1024, OpenSSL::Digest.new('SHA1')) ++ ca2_cert, @rsa1024, OpenSSL::Digest.new('SHA256')) + revoke_info = [] + crl2_2 = issue_crl(revoke_info, 2, now-100, now-1, [], +- ca2_cert, @rsa1024, OpenSSL::Digest.new('SHA1')) ++ ca2_cert, @rsa1024, OpenSSL::Digest.new('SHA256')) + + assert_equal(true, ca1_cert.verify(ca1_cert.public_key)) # self signed + assert_equal(true, ca2_cert.verify(ca1_cert.public_key)) # issued by ca1 +@@ -220,10 +220,10 @@ + + revoke_info = [] + crl1 = issue_crl(revoke_info, 1, now, now+1800, [], +- ca1_cert, @rsa2048, OpenSSL::Digest.new('SHA1')) ++ ca1_cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + revoke_info = [ [2, now, 1], ] + crl2 = issue_crl(revoke_info, 2, now+1800, now+3600, [], +- ca1_cert, @rsa2048, OpenSSL::Digest.new('SHA1')) ++ ca1_cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + store.add_crl(crl1) + assert_raise(OpenSSL::X509::StoreError){ + store.add_crl(crl2) # add CRL issued by same CA twice. diff --git a/SPECS/ruby.spec b/SPECS/ruby.spec index 928801a..ac94c1b 100644 --- a/SPECS/ruby.spec +++ b/SPECS/ruby.spec @@ -1,6 +1,6 @@ %global major_version 3 %global minor_version 0 -%global teeny_version 3 +%global teeny_version 4 %global major_minor_version %{major_version}.%{minor_version} %global ruby_version %{major_minor_version}.%{teeny_version} @@ -22,7 +22,7 @@ %endif -%global release 159 +%global release 160 %{!?release_string:%define release_string %{?development_release:0.}%{release}%{?development_release:.%{development_release}}%{?dist}} # The RubyGems library has to stay out of Ruby directory tree, since the @@ -30,11 +30,11 @@ %global rubygems_dir %{_datadir}/rubygems # Bundled libraries versions -%global rubygems_version 3.2.32 +%global rubygems_version 3.2.33 %global rubygems_molinillo_version 0.7.0 # Default gems. -%global bundler_version 2.2.32 +%global bundler_version 2.2.33 %global bundler_connection_pool_version 2.3.0 %global bundler_fileutils_version 1.4.1 %global bundler_molinillo_version 0.7.0 @@ -164,6 +164,11 @@ Patch18: ruby-3.1.0-addr2line-DW_FORM_ref_addr.patch # Avoid possible timeout errors in TestBugReporter#test_bug_reporter_add. # https://bugs.ruby-lang.org/issues/16492 Patch19: ruby-2.7.1-Timeout-the-test_bug_reporter_add-witout-raising-err.patch +# Fix /test_\(ast_compacts\|compact_count\|complex_hash_keys\|gc_compact_stats\)/ +# test failures on ppc64le. +# https://bugs.ruby-lang.org/issues/18746 +# https://bugs.ruby-lang.org/issues/18394 +Patch20: ruby-3.1.0-Use-mmap-for-allocating-heap-pages-in-the-GC.patch # Allow to exclude test with fully qualified name. # https://bugs.ruby-lang.org/issues/16936 # https://github.com/ruby/ruby/pull/5026 @@ -172,9 +177,6 @@ Patch21: ruby-3.1.0-Properly-exclude-test-cases.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2027099 # https://github.com/rubygems/rubygems/pull/5154 Patch22: rubygems-3.2.33-Fix-loading-operating_system-rb-customizations-too-late.patch -# Fix segfault in `TestArray#test_sample` on s390x. -# https://github.com/ruby/ruby/pull/5239 -Patch23: ruby-3.1.0-Fix-stack-buffer-overflow.patch # OpenSSL 3.0 compatibility patches @@ -249,6 +251,16 @@ Patch57: rubygems-3.3.1-Fix-compatibility-with-OpenSSL3.0.patch # Miscellaneous changes for OpenSSL 3.0 support. # https://github.com/ruby/openssl/pull/481 Patch58: ruby-3.1.0-Miscellaneous-changes-for-OpenSSL-3.0-support-part-2.patch +# C9S/RHEL9 have SHA1 disabled by default, so using the OCSP with +# default arguments on a default C9S/RHEL9 installation will result in an +# OpenSSL error. This patch, when OCSP does not receive a digest explicitly, will +# let OpenSSL decide which digest to use instead of using a default, thus +# preventing usage of disabled digests. +# https://github.com/ruby/openssl/pull/507 +Patch59: ruby-3.1.1-ossl_ocsp-use-null.patch +# Replace SHA1 usage in tests. +# https://github.com/ruby/openssl/pull/511 +Patch60: ruby-3.1.2-ossl-tests-replace-sha1.patch Requires: %{name}-libs%{?_isa} = %{version}-%{release} Suggests: rubypick @@ -688,9 +700,9 @@ rm -rf ext/fiddle/libffi* %patch17 -p1 %patch18 -p1 %patch19 -p1 +%patch20 -p1 %patch21 -p1 %patch22 -p1 -%patch23 -p1 %patch30 -p1 -R %patch31 -p1 %patch40 -p1 @@ -712,6 +724,8 @@ rm -rf ext/fiddle/libffi* %patch56 -p1 %patch57 -p1 %patch58 -p1 +%patch59 +%patch60 -p1 # Provide an example of usage of the tapset: cp -a %{SOURCE3} . @@ -989,8 +1003,17 @@ MSPECOPTS="" # https://bugzilla.redhat.com/show_bug.cgi?id=2040380 mv test/fiddle/test_import.rb{,.disable} +# Part of the RubyGems test suite uses certificates that are using SHA1, +# they fail with default crypty policy, but setting crypto policy to +# LEGACY makes them pass. +# OPENSSL_ENABLE_SHA1_SIGNATURES=1 enables SHA1 for +# OpenSSL in order to enable tests using SHA1 certificates, at least running +# the tests is preferable to not running them at all. +# https://github.com/rubygems/rubygems/issues/5454 +# # Give an option to increase the timeout in tests. # https://bugs.ruby-lang.org/issues/16921 +OPENSSL_ENABLE_SHA1_SIGNATURES=1 \ %{?test_timeout_scale:RUBY_TEST_TIMEOUT_SCALE="%{test_timeout_scale}"} \ make check TESTS="-v $DISABLE_TESTS" MSPECOPT="-fs $MSPECOPTS" @@ -1466,6 +1489,16 @@ mv test/fiddle/test_import.rb{,.disable} %changelog +* Fri Jul 08 2022 Jarek Prokop - 3.0.4-160 +- Upgrade to Ruby 3.0.4. + Resolves: rhbz#2109428 +- OpenSSL test suite fixes due to disabled SHA1. + Related: rbhz#2109428 +- Fix double free in Regexp compilation. + Resolves: CVE-2022-28738 +- Fix buffer overrun in String-to-Float conversion. + Resolves: CVE-2022-28739 + * Thu Feb 10 2022 Vít Ondruch - 3.0.3-159 - Prevent segfaults running with SystemTap. Resolves: rhbz#2015441