diff --git a/package/squid/0001-Fix-OpenSSL-4.0-compatibility.patch b/package/squid/0001-Fix-OpenSSL-4.0-compatibility.patch new file mode 100644 index 0000000000..a0c3abff4f --- /dev/null +++ b/package/squid/0001-Fix-OpenSSL-4.0-compatibility.patch @@ -0,0 +1,368 @@ +From 144a59fec3d7a4bd7f0c3e71934156e1a56ebabc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavol=20=C5=BD=C3=A1=C4=8Dik?= +Date: Wed, 6 May 2026 17:18:58 +0200 +Subject: [PATCH] Fix OpenSSL 4.0 compatibility + +Replace direct ASN1 structure field access with accessor functions. +and use ASN1_STRING_set() instead of direct field assignment. + +Fix issues caused by X509* API constness changes; in some cases, +casting the const away is necessary to keep compatibility with +OpenSSL 3. + +Downloaded from Fedora: +https://src.fedoraproject.org/rpms/squid/blob/rawhide/f/squid-7.5-openssl4.patch + +Upstream: https://github.com/squid-cache/squid/pull/2501 + +Signed-off-by: Bernd Kuhls +--- + .../cert_generators/file/certificate_db.cc | 2 +- + src/ssl/gadgets.cc | 92 +++++++++++-------- + src/ssl/gadgets.h | 4 +- + src/ssl/support.cc | 18 ++-- + 4 files changed, 66 insertions(+), 50 deletions(-) + +diff --git a/src/security/cert_generators/file/certificate_db.cc b/src/security/cert_generators/file/certificate_db.cc +index 4b729b316..35849aa63 100644 +--- a/src/security/cert_generators/file/certificate_db.cc ++++ b/src/security/cert_generators/file/certificate_db.cc +@@ -335,7 +335,7 @@ Ssl::CertificateDb::addCertAndPrivateKey(std::string const &useKey, const Securi + } + + const auto tm = X509_getm_notAfter(cert.get()); +- row.setValue(cnlExp_date, std::string(reinterpret_cast(tm->data), tm->length).c_str()); ++ row.setValue(cnlExp_date, std::string(reinterpret_cast(ASN1_STRING_get0_data(tm)), ASN1_STRING_length(tm)).c_str()); + const auto subject = OneLineSummary(*X509_get_subject_name(cert.get())); + row.setValue(cnlName, subject.get()); + row.setValue(cnlKey, useKey.c_str()); +diff --git a/src/ssl/gadgets.cc b/src/ssl/gadgets.cc +index 06b8b79dd..100ee6a46 100644 +--- a/src/ssl/gadgets.cc ++++ b/src/ssl/gadgets.cc +@@ -259,20 +259,31 @@ static bool replaceCommonName(Security::CertPointer & cert, std::string const &r + if (cn.length() > 2 && *cn.begin() == '[' && *cn.rbegin() == ']') + cn = cn.substr(1, cn.size()-2); + +- X509_NAME *name = X509_get_subject_name(cert.get()); ++ const X509_NAME *subject = X509_get_subject_name(cert.get()); ++ if (!subject) ++ return false; ++ ++ X509_NAME *name = X509_NAME_dup(subject); + if (!name) + return false; ++ + // Remove the CN part: + int loc = X509_NAME_get_index_by_NID(name, NID_commonName, -1); +- if (loc >=0) { +- X509_NAME_ENTRY *tmp = X509_NAME_get_entry(name, loc); +- X509_NAME_delete_entry(name, loc); ++ if (loc >= 0) { ++ X509_NAME_ENTRY *tmp = X509_NAME_delete_entry(name, loc); + X509_NAME_ENTRY_free(tmp); + } + + // Add a new CN +- return X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_ASC, +- (unsigned char *)(cn.c_str()), -1, -1, 0); ++ if (!X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_ASC, ++ (unsigned char *)(cn.c_str()), -1, -1, 0)) { ++ X509_NAME_free(name); ++ return false; ++ } ++ ++ int ret = X509_set_subject_name(cert.get(), name); ++ X509_NAME_free(name); ++ return ret; + } + + const char *Ssl::CertSignAlgorithmStr[] = { +@@ -301,9 +312,9 @@ static void + printX509Signature(const Security::CertPointer &cert, std::string &out) + { + const ASN1_BIT_STRING *sig = Ssl::X509_get_signature(cert); +- if (sig && sig->data) { +- const unsigned char *s = sig->data; +- for (int i = 0; i < sig->length; ++i) { ++ if (sig && ASN1_STRING_get0_data(sig)) { ++ const unsigned char *s = ASN1_STRING_get0_data(sig); ++ for (int i = 0; i < ASN1_STRING_length(sig); ++i) { + char hex[3]; + snprintf(hex, sizeof(hex), "%02x", s[i]); + out.append(hex); +@@ -377,7 +388,7 @@ mimicAuthorityKeyId(Security::CertPointer &cert, Security::CertPointer const &mi + X509_EXTENSION *ext; + // Check if the issuer has the Subject Key Identifier extension + const int indx = X509_get_ext_by_NID(issuerCert.get(), NID_subject_key_identifier, -1); +- if (indx >= 0 && (ext = X509_get_ext(issuerCert.get(), indx))) { ++ if (indx >= 0 && (ext = const_cast(X509_get_ext(issuerCert.get(), indx)))) { + issuerKeyId.reset((ASN1_OCTET_STRING *)X509V3_EXT_d2i(ext)); + } + } +@@ -418,8 +429,7 @@ mimicAuthorityKeyId(Security::CertPointer &cert, Security::CertPointer const &mi + unsigned char *ext_der = nullptr; + int ext_len = ASN1_item_i2d((ASN1_VALUE *)theAuthKeyId.get(), &ext_der, ASN1_ITEM_ptr(method->it)); + Ssl::ASN1_OCTET_STRING_Pointer extOct(ASN1_OCTET_STRING_new()); +- extOct.get()->data = ext_der; +- extOct.get()->length = ext_len; ++ ASN1_STRING_set(extOct.get(), ext_der, ext_len); + Ssl::X509_EXTENSION_Pointer extAuthKeyId(X509_EXTENSION_create_by_NID(nullptr, NID_authority_key_identifier, 0, extOct.get())); + if (!extAuthKeyId.get()) + return false; +@@ -471,7 +481,7 @@ mimicExtensions(Security::CertPointer & cert, Security::CertPointer const &mimic + int nid; + for (int i = 0; (nid = extensions[i]) != 0; ++i) { + const int pos = X509_get_ext_by_NID(mimicCert.get(), nid, -1); +- if (X509_EXTENSION *ext = X509_get_ext(mimicCert.get(), pos)) { ++ if (X509_EXTENSION *ext = const_cast(X509_get_ext(mimicCert.get(), pos))) { + // Mimic extension exactly. + if (X509_add_ext(cert.get(), ext, -1)) + ++added; +@@ -482,7 +492,7 @@ mimicExtensions(Security::CertPointer & cert, Security::CertPointer const &mimic + // that the more stringent requirements are met. + + const int p = X509_get_ext_by_NID(cert.get(), NID_key_usage, -1); +- if ((ext = X509_get_ext(cert.get(), p)) != nullptr) { ++ if ((ext = const_cast(X509_get_ext(cert.get(), p))) != nullptr) { + ASN1_BIT_STRING *keyusage = (ASN1_BIT_STRING *)X509V3_EXT_d2i(ext); + ASN1_BIT_STRING_set_bit(keyusage, KeyEncipherment, 1); + +@@ -495,8 +505,7 @@ mimicExtensions(Security::CertPointer & cert, Security::CertPointer const &mimic + (const ASN1_ITEM *)ASN1_ITEM_ptr(method->it)); + + ASN1_OCTET_STRING *ext_oct = ASN1_OCTET_STRING_new(); +- ext_oct->data = ext_der; +- ext_oct->length = ext_len; ++ ASN1_STRING_set(ext_oct, ext_der, ext_len); + X509_EXTENSION_set_data(ext, ext_oct); + + ASN1_OCTET_STRING_free(ext_oct); +@@ -518,7 +527,7 @@ mimicExtensions(Security::CertPointer & cert, Security::CertPointer const &mimic + SBuf + Ssl::AsnToSBuf(const ASN1_STRING &buffer) + { +- return SBuf(reinterpret_cast(buffer.data), buffer.length); ++ return SBuf(reinterpret_cast(ASN1_STRING_get0_data(&buffer)), ASN1_STRING_length(&buffer)); + } + + /// OpenSSL ASN1_STRING_to_UTF8() wrapper +@@ -547,7 +556,7 @@ Ssl::ParseAsSimpleDomainNameOrIp(const SBuf &text) + } + + std::optional +-Ssl::ParseCommonNameAt(X509_NAME &name, const int cnIndex) ++Ssl::ParseCommonNameAt(const X509_NAME &name, const int cnIndex) + { + const auto cn = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(&name, cnIndex)); + if (!cn) { +@@ -576,7 +585,7 @@ Ssl::ParseCommonNameAt(X509_NAME &name, const int cnIndex) + static bool + addAltNameWithSubjectCn(Security::CertPointer &cert) + { +- X509_NAME *name = X509_get_subject_name(cert.get()); ++ const X509_NAME *name = X509_get_subject_name(cert.get()); + if (!name) + return false; + +@@ -610,7 +619,7 @@ static bool buildCertificate(Security::CertPointer & cert, Ssl::CertificatePrope + // returns a pointer to the existing subject name. Nothing to clean here. + if (properties.mimicCert.get()) { + // Leave subject empty if we cannot extract it from true cert. +- if (X509_NAME *name = X509_get_subject_name(properties.mimicCert.get())) { ++ if (const X509_NAME *name = X509_get_subject_name(properties.mimicCert.get())) { + // X509_set_subject_name will call X509_dup for name + X509_set_subject_name(cert.get(), name); + } +@@ -656,7 +665,7 @@ static bool buildCertificate(Security::CertPointer & cert, Ssl::CertificatePrope + bool useCommonNameAsAltName = true; + // mimic the alias and possibly subjectAltName + if (properties.mimicCert.get()) { +- unsigned char *alStr; ++ const unsigned char *alStr; + int alLen; + alStr = X509_alias_get0(properties.mimicCert.get(), &alLen); + if (alStr) { +@@ -667,7 +676,7 @@ static bool buildCertificate(Security::CertPointer & cert, Ssl::CertificatePrope + // certificates with CN unrelated to subjectAltNames. + if (!properties.setCommonName) { + int pos = X509_get_ext_by_NID(properties.mimicCert.get(), NID_subject_alt_name, -1); +- X509_EXTENSION *ext=X509_get_ext(properties.mimicCert.get(), pos); ++ X509_EXTENSION *ext = const_cast(X509_get_ext(properties.mimicCert.get(), pos)); + if (ext) { + if (X509_add_ext(cert.get(), ext, -1)) + ++addedExtensions; +@@ -922,20 +931,23 @@ Ssl::WritePrivateKey(Ssl::BIO_Pointer &bio, const Security::PrivateKeyPointer &p + } + + Ssl::UniqueCString +-Ssl::OneLineSummary(X509_NAME &name) ++Ssl::OneLineSummary(const X509_NAME &name) + { + return Ssl::UniqueCString(X509_NAME_oneline(&name, nullptr, 0)); + } + + bool Ssl::sslDateIsInTheFuture(char const * date) + { +- ASN1_UTCTIME tm; +- tm.flags = 0; +- tm.type = 23; +- tm.data = (unsigned char *)date; +- tm.length = strlen(date); +- +- return (X509_cmp_current_time(&tm) > 0); ++ ASN1_UTCTIME *tm = ASN1_UTCTIME_new(); ++ if (!tm) ++ return false; ++ if (!ASN1_UTCTIME_set_string(tm, date)) { ++ ASN1_UTCTIME_free(tm); ++ return false; ++ } ++ int result = X509_cmp_current_time(tm); ++ ASN1_UTCTIME_free(tm); ++ return (result > 0); + } + + /// Print the time represented by a ASN1_TIME struct to a string using GeneralizedTime format +@@ -945,14 +957,18 @@ static bool asn1timeToGeneralizedTimeStr(ASN1_TIME *aTime, char *buf, int bufLen + // UTCTime has the form YYMMDDHHMMSS[Z | [+|-]offset] + // GeneralizedTime has the form YYYYMMDDHHMMSS[Z | [+|-] offset] + ++ const unsigned char *data = ASN1_STRING_get0_data(aTime); ++ int length = ASN1_STRING_length(aTime); ++ int type = ASN1_STRING_type(aTime); ++ + // length should have space for data plus 2 extra bytes for the two extra year fields + // plus the '\0' char. +- if ((aTime->length + 3) > bufLen) ++ if ((length + 3) > bufLen) + return false; + + char *str; +- if (aTime->type == V_ASN1_UTCTIME) { +- if (aTime->data[0] > '5') { // RFC 2459, section 4.1.2.5.1 ++ if (type == V_ASN1_UTCTIME) { ++ if (data[0] > '5') { // RFC 2459, section 4.1.2.5.1 + buf[0] = '1'; + buf[1] = '9'; + } else { +@@ -960,11 +976,11 @@ static bool asn1timeToGeneralizedTimeStr(ASN1_TIME *aTime, char *buf, int bufLen + buf[1] = '0'; + } + str = buf +2; +- } else // if (aTime->type == V_ASN1_GENERALIZEDTIME) ++ } else // if (type == V_ASN1_GENERALIZEDTIME) + str = buf; + +- memcpy(str, aTime->data, aTime->length); +- str[aTime->length] = '\0'; ++ memcpy(str, data, length); ++ str[length] = '\0'; + return true; + } + +@@ -996,8 +1012,8 @@ bool Ssl::certificateMatchesProperties(X509 *cert, CertificateProperties const & + return true; + + if (!properties.setCommonName) { +- X509_NAME *cert1_name = X509_get_subject_name(cert); +- X509_NAME *cert2_name = X509_get_subject_name(cert2); ++ const X509_NAME *cert1_name = X509_get_subject_name(cert); ++ const X509_NAME *cert2_name = X509_get_subject_name(cert2); + if (X509_NAME_cmp(cert1_name, cert2_name) != 0) + return false; + } else if (properties.commonName != CommonHostName(cert)) +diff --git a/src/ssl/gadgets.h b/src/ssl/gadgets.h +index e0c60c3a3..4c487596b 100644 +--- a/src/ssl/gadgets.h ++++ b/src/ssl/gadgets.h +@@ -160,7 +160,7 @@ bool WriteX509Certificate(BIO_Pointer &bio, const Security::CertPointer & cert); + bool WritePrivateKey(BIO_Pointer &bio, const Security::PrivateKeyPointer &pkey); + + /// a RAII wrapper for the memory-allocating flavor of X509_NAME_oneline() +-UniqueCString OneLineSummary(X509_NAME &); ++UniqueCString OneLineSummary(const X509_NAME &); + + /** + \ingroup SslCrtdSslAPI +@@ -285,7 +285,7 @@ const char *CommonHostName(X509 *x509); + SBuf AsnToSBuf(const ASN1_STRING &); + + /// interprets X.509 Subject or Issuer name entry (at the given position) as CN +-std::optional ParseCommonNameAt(X509_NAME &, int); ++std::optional ParseCommonNameAt(const X509_NAME &, int); + + /// interprets the given buffer as either a textual representation of an IP + /// address (if possible) or a domain name without wildcard support (otherwise) +diff --git a/src/ssl/support.cc b/src/ssl/support.cc +index e7872035c..09f268a7e 100644 +--- a/src/ssl/support.cc ++++ b/src/ssl/support.cc +@@ -272,23 +272,23 @@ ParseSubjectAltName(const GENERAL_NAME &san) + + // RFC 5280 section 4.2.1.6 signals IPv4/IPv6 address family using data length + +- if (san.d.iPAddress->length == 4) { ++ if (ASN1_STRING_length(san.d.iPAddress) == 4) { + struct in_addr addr; + static_assert(sizeof(addr.s_addr) == 4); +- memcpy(&addr.s_addr, san.d.iPAddress->data, sizeof(addr.s_addr)); ++ memcpy(&addr.s_addr, ASN1_STRING_get0_data(san.d.iPAddress), sizeof(addr.s_addr)); + const Ip::Address ip(addr); + return AnyP::Host::ParseIp(ip); + } + +- if (san.d.iPAddress->length == 16) { ++ if (ASN1_STRING_length(san.d.iPAddress) == 16) { + struct in6_addr addr; + static_assert(sizeof(addr.s6_addr) == 16); +- memcpy(&addr.s6_addr, san.d.iPAddress->data, sizeof(addr.s6_addr)); ++ memcpy(&addr.s6_addr, ASN1_STRING_get0_data(san.d.iPAddress), sizeof(addr.s6_addr)); + const Ip::Address ip(addr); + return AnyP::Host::ParseIp(ip); + } + +- debugs(83, 3, "unexpected length of an IP address SAN: " << san.d.iPAddress->length); ++ debugs(83, 3, "unexpected length of an IP address SAN: " << ASN1_STRING_length(san.d.iPAddress)); + return std::nullopt; + } + +@@ -856,7 +856,7 @@ Ssl::InitClientContext(Security::ContextPointer &ctx, Security::PeerOptions &pee + + /// \ingroup ServerProtocolSSLInternal + static const char * +-ssl_get_attribute(X509_NAME * name, const char *attribute_name) ++ssl_get_attribute(const X509_NAME * name, const char *attribute_name) + { + static char buffer[1024]; + buffer[0] = '\0'; +@@ -879,7 +879,7 @@ ssl_get_attribute(X509_NAME * name, const char *attribute_name) + const char * + Ssl::GetX509UserAttribute(X509 * cert, const char *attribute_name) + { +- X509_NAME *name; ++ const X509_NAME *name; + const char *ret; + + if (!cert) +@@ -933,7 +933,7 @@ const char * + Ssl::GetX509CAAttribute(X509 * cert, const char *attribute_name) + { + +- X509_NAME *name; ++ const X509_NAME *name; + const char *ret; + + if (!cert) +@@ -1484,7 +1484,7 @@ void Ssl::InRamCertificateDbKey(const Ssl::CertificateProperties &certProperties + if (certProperties.mimicCert) { + if (auto *sig = Ssl::X509_get_signature(certProperties.mimicCert)) { + origSignatureAsKey = true; +- key.append((const char *)sig->data, sig->length); ++ key.append((const char *)ASN1_STRING_get0_data(sig), ASN1_STRING_length(sig)); + } + } + +-- +2.47.3 +