Skip to content

10.2.x branch cannot build on Fedora 45 due to ASN1_STRING opacity #13427

Closed

Description

@jeredfloyd

Fedora 45 migrates to OpenSSL 4.0. In OpenSSL 4.0, the ASN1_STRING type is now opaque, and accessors must be used, see https://docs.openssl.org/4.0/man7/ossl-guide-migration/#the-asn1_string-type-is-now-opaque

X509HostnameValidator.cc:do_check_string() attempts to access opaque internals and thus will not compile with OpenSSL 4.0

Activity

  1. jeredfloyd commented on Jul 25, 2026

    @jeredfloyd
    ContributorAuthor

    There are a few other items, including const-iness of things. Here's a patch that fixes everything to complete a build successfully on F45. If it looks ok, lmk and I will make it a PR instead. (I haven't yet tested if it creates issues on older releases, but I think it's unlikely.)

    --- src/tscore/X509HostnameValidator.cc.orig	2026-07-25 02:15:34.822042537 +0000
    +++ src/tscore/X509HostnameValidator.cc	2026-07-25 02:15:32.185006059 +0000
    @@ -205,12 +205,12 @@
     {
       bool retval = false;
     
    -  if (!a->data || !a->length || cmp_type != a->type) {
    +  if (!ASN1_STRING_get0_data(a) || !ASN1_STRING_length(a) || cmp_type != ASN1_STRING_type(a)) {
         return false;
       }
    -  retval = equal(a->data, a->length, b, blen);
    +  retval = equal(ASN1_STRING_get0_data(a), ASN1_STRING_length(a), b, blen);
       if (retval && peername) {
    -    *peername = ats_strndup((char *)a->data, a->length);
    +    *peername = ats_strndup((char *)ASN1_STRING_get0_data(a), ASN1_STRING_length(a));
       }
       return retval;
     }
    @@ -218,11 +218,11 @@
     bool
     validate_hostname(X509 *x, const unsigned char *hostname, bool is_ip, char **peername)
     {
    -  GENERAL_NAMES *gens = nullptr;
    -  X509_NAME     *name = nullptr;
    -  int            i;
    -  int            alt_type;
    -  bool           retval = false;
    +  GENERAL_NAMES   *gens = nullptr;
    +  const X509_NAME *name = nullptr;
    +  int             i;
    +  int             alt_type;
    +  bool            retval = false;
       ;
       equal_fn equal;
       size_t   hostname_len = strlen((char *)hostname);
    @@ -267,9 +267,9 @@
       name = X509_get_subject_name(x);
     
       while ((i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) >= 0) {
    -    ASN1_STRING   *str;
    -    int            astrlen;
    -    unsigned char *astr;
    +    const ASN1_STRING   *str;
    +    int                 astrlen;
    +    unsigned char       *astr;
         str = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
         // Convert to UTF-8
         astrlen = ASN1_STRING_to_UTF8(&astr, str);
    --- src/iocore/net/SSLNetVConnection.cc.orig	2026-07-25 02:24:07.789952688 +0000
    +++ src/iocore/net/SSLNetVConnection.cc	2026-07-25 02:25:36.161167556 +0000
    @@ -167,7 +167,7 @@
     }
     
     static void
    -debug_certificate_name(const char *msg, X509_NAME *name)
    +debug_certificate_name(const char *msg, const X509_NAME *name)
     {
       BIO *bio;
     
    --- src/iocore/net/SSLUtils.cc.orig	2026-07-25 02:25:58.022467139 +0000
    +++ src/iocore/net/SSLUtils.cc	2026-07-25 02:37:47.633108283 +0000
    @@ -1104,7 +1104,7 @@
     } /* CheckServerCertNow() */
     
     static char *
    -asn1_strdup(ASN1_STRING *s)
    +asn1_strdup(const ASN1_STRING *s)
     {
       // Make sure we have an 8-bit encoding.
       ink_assert(ASN1_STRING_type(s) == V_ASN1_IA5STRING || ASN1_STRING_type(s) == V_ASN1_UTF8STRING ||
    @@ -2407,7 +2407,7 @@
     
         std::set<std::string> name_set;
         // Grub through the names in the certs
    -    X509_NAME *subject = nullptr;
    +    const X509_NAME *subject = nullptr;
     
         // Insert a key for the subject CN.
         subject = X509_get_subject_name(cert);
    @@ -2420,8 +2420,8 @@
               break;
             }
     
    -        X509_NAME_ENTRY *e  = X509_NAME_get_entry(subject, pos);
    -        ASN1_STRING     *cn = X509_NAME_ENTRY_get_data(e);
    +        const X509_NAME_ENTRY *e  = X509_NAME_get_entry(subject, pos);
    +        const ASN1_STRING     *cn = X509_NAME_ENTRY_get_data(e);
             subj_name           = asn1_strdup(cn);
     
             Dbg(dbg_ctl_ssl_load, "subj '%s' in certificate %s %p", subj_name.get(), data.cert_names_list[i].c_str(), cert);
    --- src/iocore/net/OCSPStapling.cc.orig	2026-07-25 02:41:18.458968716 +0000
    +++ src/iocore/net/OCSPStapling.cc	2026-07-25 02:42:21.478823756 +0000
    @@ -489,7 +489,7 @@
       }
     
       /* Calculate the issuerKey hash, excluding tag and length */
    -  if (!EVP_Digest(issuerKey->data, issuerKey->length, md, &i, dgst, nullptr)) {
    +  if (!EVP_Digest(ASN1_STRING_get0_data(issuerKey), ASN1_STRING_length(issuerKey), md, &i, dgst, nullptr)) {
         goto err;
       }
     
    @@ -515,7 +515,7 @@
     {
       const X509_NAME    *iname;
       const ASN1_INTEGER *serial;
    -  ASN1_BIT_STRING    *ikey;
    +  const ASN1_BIT_STRING    *ikey;
     
       if (!dgst) {
         dgst = EVP_sha1();
    --- src/api/InkAPI.cc.orig	2026-07-25 02:59:52.703119493 +0000
    +++ src/api/InkAPI.cc	2026-07-25 03:00:42.523798053 +0000
    @@ -8307,9 +8307,9 @@
         }
     
         // Extract common name
    -    int              pos              = X509_NAME_get_index_by_NID(X509_get_subject_name(cert.get()), NID_commonName, -1);
    -    X509_NAME_ENTRY *common_name      = X509_NAME_get_entry(X509_get_subject_name(cert.get()), pos);
    -    ASN1_STRING     *common_name_asn1 = X509_NAME_ENTRY_get_data(common_name);
    +    const int              pos              = X509_NAME_get_index_by_NID(X509_get_subject_name(cert.get()), NID_commonName, -1);
    +    const X509_NAME_ENTRY *common_name      = X509_NAME_get_entry(X509_get_subject_name(cert.get()), pos);
    +    const ASN1_STRING     *common_name_asn1 = X509_NAME_ENTRY_get_data(common_name);
         char *common_name_str = reinterpret_cast<char *>(const_cast<unsigned char *>(ASN1_STRING_get0_data(common_name_asn1)));
         if (ASN1_STRING_length(common_name_asn1) != static_cast<int>(strlen(common_name_str))) {
           // Embedded null char
    --- plugins/experimental/sslheaders/expand.cc.orig	2026-07-25 03:13:24.680182258 +0000
    +++ plugins/experimental/sslheaders/expand.cc	2026-07-25 03:15:55.953244848 +0000
    @@ -49,14 +49,14 @@
     static void
     x509_expand_subject(X509 *x509, BIO *bio)
     {
    -  X509_NAME *name = X509_get_subject_name(x509);
    +  const X509_NAME *name = X509_get_subject_name(x509);
       X509_NAME_print_ex(bio, name, 0 /* indent */, XN_FLAG_ONELINE);
     }
     
     static void
     x509_expand_issuer(X509 *x509, BIO *bio)
     {
    -  X509_NAME *name = X509_get_issuer_name(x509);
    +  const X509_NAME *name = X509_get_issuer_name(x509);
       X509_NAME_print_ex(bio, name, 0 /* indent */, XN_FLAG_ONELINE);
     }
     
    @@ -72,8 +72,8 @@
     {
       const ASN1_BIT_STRING *sig;
       X509_get0_signature(&sig, nullptr, x509);
    -  const char *ptr = reinterpret_cast<const char *>(sig->data);
    -  const char *end = ptr + sig->length;
    +  const char *ptr = reinterpret_cast<const char *>(ASN1_STRING_get0_data(sig));
    +  const char *end = ptr + ASN1_STRING_length(sig);
     
       // The canonical OpenSSL way to format the signature seems to be
       // X509_signature_dump(). However that separates each byte with a ':', which is
    --- plugins/certifier/certifier.cc.orig	2026-07-25 03:26:32.808935744 +0000
    +++ plugins/certifier/certifier.cc	2026-07-25 04:02:32.880866169 +0000
    @@ -372,12 +372,18 @@
       X509_gmtime_adj(X509_get_notAfter(cert.get()), static_cast<long>(3650) * 24 * 3600);
     
       // Get handle to subject name
    -  X509_NAME *n = X509_get_subject_name(cert.get());
    +  X509_NAME *n = X509_NAME_dup(X509_get_subject_name(cert.get()));
       // Set common name field
       if (X509_NAME_add_entry_by_txt(n, "CN", MBSTRING_ASC, (unsigned char *)commonName.c_str(), -1, -1, 0) != 1) {
         TSError("[%s] %s: failed to add certificate subject CN", PLUGIN_NAME, __func__);
         return nullptr;
       }
    +  if (X509_set_subject_name(cert.get(), n) != 1) {
    +    TSError("[%s] %s: failed to set certificate subject", PLUGIN_NAME, __func__);
    +    X509_NAME_free(n);
    +    return nullptr;
    +  }
    +  X509_NAME_free(n);
     
       // Set Traffic Server public key
       if (X509_set_pubkey(cert.get(), ca_pkey_scoped.get()) == 0) {
    --- plugins/experimental/cert_reporting_tool/cert_reporting_tool.cc.orig	2026-07-25 04:25:19.072669506 +0000
    +++ plugins/experimental/cert_reporting_tool/cert_reporting_tool.cc	2026-07-25 04:26:01.238251075 +0000
    @@ -65,7 +65,7 @@
             // expiration date, serial number, common name, and subject alternative names
             const ASN1_TIME    *not_after    = X509_get_notAfter(cert);
             const ASN1_INTEGER *serial       = X509_get_serialNumber(cert);
    -        X509_NAME          *subject_name = X509_get_subject_name(cert);
    +        const X509_NAME    *subject_name = X509_get_subject_name(cert);
     
             // Subject name
             BIO *subject_bio = BIO_new(BIO_s_mem());
    --- plugins/experimental/txn_box/plugin/src/ts_util.cc.orig	2026-07-25 04:37:47.324945887 +0000
    +++ plugins/experimental/txn_box/plugin/src/ts_util.cc	2026-07-25 04:39:21.571239702 +0000
    @@ -1106,7 +1106,7 @@
     namespace
     {
       TextView
    -  ssl_value_for(X509_NAME *name, int nid)
    +  ssl_value_for(const X509_NAME *name, int nid)
       {
         if (int loc = X509_NAME_get_index_by_NID(name, nid, -1); loc >= 0) {
           if (auto entry = X509_NAME_get_entry(name, loc); entry != nullptr) {
    
  2. jeredfloyd commented on Jul 25, 2026

    @jeredfloyd
    ContributorAuthor

    All tests then pass on F45 except test_libswoc, constant bane of my ATS maintenance. I haven't looked into it yet:

    bwstring std formats
    -------------------------------------------------------------------------------
    /builddir/build/BUILD/trafficserver-10.2.0-build/trafficserver-10.2.0/lib/swoc/unit_tests/test_bw_format.cc:522
    ...............................................................................
    /builddir/build/BUILD/trafficserver-10.2.0-build/trafficserver-10.2.0/lib/swoc/unit_tests/test_bw_format.cc:529: FAILED:
      REQUIRE( w.view().substr(0, 22) == "Unknown: Unknown error"sv )
    with expansion:
      Unknown: Inappropriate
      ==
      "Unknown: Unknown error"
    
  3. jeredfloyd commented on Jul 25, 2026

    @jeredfloyd
    ContributorAuthor

    FYI, this builds and passes all tests for EPEL 10, so the test_libswoc failure must be a bleeding-edge glibc thing -- it seems to be just matching the wrong invalid index error message so is probably spurious.

  4. added
    Buildwork related to build configuration or environment
    on Jul 27, 2026
  5. JosiahWI commented on Jul 27, 2026

    @JosiahWI
    Contributor

    Thank you for your work to make a patch for this. I looked over the diff and would like to approve it, so it would be great if you could submit a PR. Make the PR against the master branch and we will mark it for backport to 10.2.x.

  6. self-assigned this
    on Jul 27, 2026
  7. jeredfloyd commented on Jul 28, 2026

    @jeredfloyd
    ContributorAuthor

    Will try to get to this today. I think the right approach is that I'll submit this separately against both master and 10.2.x branches?

  8. JosiahWI commented on Jul 28, 2026

    @JosiahWI
    Contributor

    Unless the change does not cherry-pick cleanly, an appointed committer will usually do the cherry-picks for you. All you have to do is add the version milestone corresponding to the backport target branch (10.2.0 in your case, I think) to your master PR, and it will be scheduled for cherry-pick.

    I remembered the above incorrectly. It is the project that is used for backport tracking, not the milestone. This has now been set up on the linked PR.

  9. cmcfarlen commented on Aug 10, 2026

    @cmcfarlen
    Contributor

    @jeredfloyd Could you please confirm that the 10.2.0-rc0 tag does work for your needs now?

  10. jeredfloyd commented on Aug 11, 2026

    @jeredfloyd
    ContributorAuthor

    @cmcfarlen The OpenSSL 4 issues are resolved and builds are (generally) successful for F45 and EL10.

    There are two unrelated issues, but I don't think they necessarily need to hold up release as I can track them down and fix in the RPM spec:

    1. On Fedora 45, a libswoc test fails which seems to be due to a newly introduced error code message conflicting with a hardcoded value in libswoc:
    /builddir/build/BUILD/trafficserver-10.2.0-build/trafficserver-10.2.0/lib/swoc/unit_tests/test_bw_format.cc:529: FAILED:
      REQUIRE( w.view().substr(0, 22) == "Unknown: Unknown error"sv )
    with expansion:
      Unknown: Inappropriate
      ==
      "Unknown: Unknown error"
    
    1. On arch ppc64le, there is an invalid type coercion which does not occur on the 10.1.x branch:
    /builddir/build/BUILD/trafficserver-10.2.0/lib/fastlz/fastlz.cc: In function ‘void flz_maxcopy(void*, const void*)’:
    /builddir/build/BUILD/trafficserver-10.2.0/lib/fastlz/fastlz.cc:178:17: error: invalid conversion from ‘void*’ to ‘uint8_t*’ {aka ‘unsigned char*’} [-fpermissive]
      178 |   fastlz_memcpy(dest, src, MAX_COPY);
          |                 ^~~~
          |                 |
          |                 void*
    /builddir/build/BUILD/trafficserver-10.2.0/lib/fastlz/fastlz.cc:94:36: note:   initializing argument 1 of ‘void fastlz_memcpy(uint8_t*, const uint8_t*, uint32_t)’
       94 | static void fastlz_memcpy(uint8_t* dest, const uint8_t* src, uint32_t count) { memcpy(dest, src, count); }
          |                           ~~~~~~~~~^~~~
    /builddir/build/BUILD/trafficserver-10.2.0/lib/fastlz/fastlz.cc:178:23: error: invalid conversion from ‘const void*’ to ‘const uint8_t*’ {aka ‘const unsigned char*’} [-fpermissive]
      178 |   fastlz_memcpy(dest, src, MAX_COPY);
          |                       ^~~
          |                       |
          |                       const void*
    /builddir/build/BUILD/trafficserver-10.2.0/lib/fastlz/fastlz.cc:94:57: note:   initializing argument 2 of ‘void fastlz_memcpy(uint8_t*, const uint8_t*, uint32_t)’
       94 | static void fastlz_memcpy(uint8_t* dest, const uint8_t* src, uint32_t count) { memcpy(dest, src, count); }
          |                                          ~~~~~~~~~~~~~~~^~~
    

    I'll look at these as I have time (which probably means one of you or Copilot/Claude will get to it first).

  11. jeredfloyd commented on Aug 11, 2026

    @jeredfloyd
    ContributorAuthor

    libswoc build error is fixed by PR #13531

  12. jeredfloyd commented on Aug 11, 2026

    @jeredfloyd
    ContributorAuthor

    fastlz build error is fixed by PR #13532

    This uncovered a different error on ppc64le which is a bit more troubling:

    CacheShm purge sweeps by name when the control layout is foreign
    -------------------------------------------------------------------------------
    /builddir/build/BUILD/trafficserver-10.2.0/src/iocore/cache/unit_tests/test_CacheShm.cc:315
    ...............................................................................
    /builddir/build/BUILD/trafficserver-10.2.0/src/iocore/cache/unit_tests/test_CacheShm.cc:330: FAILED:
      CHECK( report.table_untrusted )
    with expansion:
      false
    /builddir/build/BUILD/trafficserver-10.2.0/src/iocore/cache/unit_tests/test_CacheShm.cc:331: FAILED:
      CHECK_FALSE( segment_exists(stripe_name) )
    with expansion:
      !true
    
  13. jeredfloyd commented on Aug 11, 2026

    @jeredfloyd
    ContributorAuthor

    I've opened #13534 for the new issue. I believe this issue is resolved and can be closed!

  14. linked a pull request that will close this issueResolve OpenSSL 4.0 build issues #13476on Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

10.2.xBuildwork related to build configuration or environment

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions