squid/squid-7.5-openssl4.patch
2026-05-07 17:49:54 +02:00

361 lines
15 KiB
Diff

From 00a8938a5561ae11c6e4d563c67ee85621499e18 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavol=20=C5=BD=C3=A1=C4=8Dik?= <pzacik@redhat.com>
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.
---
.../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 4b729b3..35849aa 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<char *>(tm->data), tm->length).c_str());
+ row.setValue(cnlExp_date, std::string(reinterpret_cast<const char *>(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 06b8b79..100ee6a 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_EXTENSION *>(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_EXTENSION *>(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_EXTENSION *>(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<const char *>(buffer.data), buffer.length);
+ return SBuf(reinterpret_cast<const char *>(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<AnyP::Host>
-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_EXTENSION *>(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 e0c60c3..4c48759 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<AnyP::Host> ParseCommonNameAt(X509_NAME &, int);
+std::optional<AnyP::Host> 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 e787203..09f268a 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.53.0