361 lines
15 KiB
Diff
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
|
|
|