Package: wvstreams
Followup-For: Bug #1138443
X-Debbugs-Cc: [email protected]
Control: tags -1 patch ftbfs

Dear Maintainer,

The previous patch was incomplete. Please find the updated patch as attached.

-- System Information:
Debian Release: trixie/sid
  APT prefers noble-updates
  APT policy: (500, 'noble-updates'), (500, 'noble-security'), (500, 'noble'), 
(100, 'noble-backports')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 6.8.0-117-generic (SMP w/12 CPU threads; PREEMPT)
Kernel taint flags: TAINT_WARN
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
Description: Fix FTBFS with OpenSSL 4.0
 OpenSSL 4.0 constifies X509 accessor return types and makes ASN1_STRING
 opaque. Create mutable X509_NAME via X509_NAME_new(), populate it, and
 set it on the cert/CSR via X509_set_*_name()/X509_REQ_set_subject_name()
 (which copy internally) instead of mutating the const pointer. Use const
 for read-only X509_EXTENSION/ASN1_STRING return values. Replace direct
 struct member access with ASN1_STRING accessor functions.
Bug-Ubuntu: https://bugs.launchpad.net/bugs/2154991
Bug-Debian: https://bugs.debian.org/1138443
Forwarded: no

Index: wvstreams/crypto/wvcrl.cc
===================================================================
--- wvstreams.orig/crypto/wvcrl.cc      2026-06-25 17:11:18.173814302 +0200
+++ wvstreams/crypto/wvcrl.cc   2026-06-25 17:11:18.166814252 +0200
@@ -56,10 +56,11 @@
 
     // most of this copied from wvx509.cc, sigh
     ASN1_OCTET_STRING *ikeyid = NULL;
+    const X509_EXTENSION *src_ext;
     X509_EXTENSION *ext;
     int i = X509_get_ext_by_NID(ca.cert, NID_subject_key_identifier, -1);
-    if ((i >= 0) && (ext = X509_get_ext(ca.cert, i)))
-        ikeyid = static_cast<ASN1_OCTET_STRING *>(X509V3_EXT_d2i(ext));
+    if ((i >= 0) && (src_ext = X509_get_ext(ca.cert, i)))
+        ikeyid = static_cast<ASN1_OCTET_STRING 
*>(X509V3_EXT_d2i(const_cast<X509_EXTENSION *>(src_ext)));
 
     if (ikeyid)
     {
@@ -169,7 +170,7 @@
                              &i, NULL));
     if (aki)
     {
-        char *tmp = hex_to_string(aki->keyid->data, aki->keyid->length); 
+        char *tmp = hex_to_string(ASN1_STRING_get0_data(aki->keyid), 
ASN1_STRING_length(aki->keyid)); 
         WvString str(tmp);
         
         OPENSSL_free(tmp);
Index: wvstreams/crypto/wvx509.cc
===================================================================
--- wvstreams.orig/crypto/wvx509.cc     2026-06-25 17:11:18.173814302 +0200
+++ wvstreams/crypto/wvx509.cc  2026-06-25 17:12:43.110432569 +0200
@@ -306,11 +306,17 @@
 
     X509_REQ_set_pubkey(certreq, pk);
 
-    name = X509_REQ_get_subject_name(certreq);
-
     debug("Creating Certificate request for %s\n", subject);
+    if ((name = X509_NAME_new()) == NULL)
+    {
+        debug(WvLog::Warning, "Error creating X509_NAME");
+        X509_REQ_free(certreq);
+        EVP_PKEY_free(pk);
+        return WvString::null;
+    }
     set_name_entry(name, subject);
     X509_REQ_set_subject_name(certreq, name);
+    X509_NAME_free(name);
     char *sub_name = X509_NAME_oneline(X509_REQ_get_subject_name(certreq), 
                                       0, 0);
     debug("SubjectDN: %s\n", sub_name);
@@ -606,9 +612,12 @@
 {
     CHECK_CERT_EXISTS_SET("issuer");
 
-    X509_NAME *name = X509_get_issuer_name(cert);
+    X509_NAME *name;
+    if ((name = X509_NAME_new()) == NULL)
+        return;
     set_name_entry(name, issuer);
     X509_set_issuer_name(cert, name);
+    X509_NAME_free(name);
 }
 
 
@@ -616,7 +625,7 @@
 {
     CHECK_CERT_EXISTS_SET("issuer");
 
-    X509_NAME *casubj = X509_get_subject_name(cacert.cert);
+    const X509_NAME *casubj = X509_get_subject_name(cacert.cert);
     X509_set_issuer_name(cert, casubj);
 }
 
@@ -636,13 +645,16 @@
 {    
     CHECK_CERT_EXISTS_SET("subject");
 
-    X509_NAME *name = X509_get_subject_name(cert);
+    X509_NAME *name;
+    if ((name = X509_NAME_new()) == NULL)
+        return;
     set_name_entry(name, subject);
     X509_set_subject_name(cert, name);
+    X509_NAME_free(name);
 }
 
 
-void WvX509::set_subject(X509_NAME *name)
+void WvX509::set_subject(const X509_NAME *name)
 {
     CHECK_CERT_EXISTS_SET("subject");
 
@@ -799,7 +811,7 @@
         ca = constraints->ca;
         if (constraints->pathlen)
         {
-            if ((constraints->pathlen->type == V_ASN1_NEG_INTEGER) || !ca)
+            if ((ASN1_STRING_type(constraints->pathlen) == V_ASN1_NEG_INTEGER) 
|| !ca)
             {
                 debug("Path length type not valid when getting basic "
                       "constraints.\n");
@@ -1153,16 +1165,16 @@
     int index = X509_get_ext_by_NID(cert, nid, -1);
     if (index >= 0)
     {
-        X509_EXTENSION *ext = X509_get_ext(cert, index);
+        const X509_EXTENSION *ext = X509_get_ext(cert, index);
         
         if (ext)
         {
-            X509V3_EXT_METHOD *method = (X509V3_EXT_METHOD 
*)X509V3_EXT_get(ext);
-            ASN1_OCTET_STRING *ext_data_str = X509_EXTENSION_get_data(ext);
+            X509V3_EXT_METHOD *method = (X509V3_EXT_METHOD 
*)X509V3_EXT_get(const_cast<X509_EXTENSION *>(ext));
+            const ASN1_OCTET_STRING *ext_data_str = 
X509_EXTENSION_get_data(const_cast<X509_EXTENSION *>(ext));
             if (!method)
             {
                 WvDynBuf buf;
-                buf.put(ext_data_str->data, ext_data_str->length);
+                buf.put(ASN1_STRING_get0_data(ext_data_str), 
ASN1_STRING_length(ext_data_str));
                 retval = buf.getstr();
             }
             else
@@ -1173,21 +1185,21 @@
                 // even though it's const (at least as of version 0.9.8e). 
                 // gah.
 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
-                const unsigned char * ext_value_data = ext_data_str->data;
+                const unsigned char * ext_value_data = 
ASN1_STRING_get0_data(ext_data_str);
 #else
-                unsigned char *ext_value_data = ext->value->data;
+                unsigned char *ext_value_data = 
ASN1_STRING_get0_data(ext_data_str);
 #endif
                 if (method->it)
                 {
                     ext_data = ASN1_item_d2i(NULL, &ext_value_data,
-                                             ext_data_str->length, 
+                                             ASN1_STRING_length(ext_data_str), 
                                              ASN1_ITEM_ptr(method->it));
                     TRACE("Applied generic conversion!\n");
                 }
                 else
                 {
                     ext_data = method->d2i(NULL, &ext_value_data,
-                                           ext_data_str->length);
+                                           ASN1_STRING_length(ext_data_str));
                     TRACE("Applied method specific conversion!\n");
                 }
                 
@@ -1339,7 +1351,7 @@
 }
 
 
-static time_t ASN1_TIME_to_time_t(ASN1_TIME *t)
+static time_t ASN1_TIME_to_time_t(const ASN1_TIME *t)
 {
     struct tm newtime;
     char *p = NULL;
@@ -1347,7 +1359,7 @@
     memset(&d,'\0',sizeof(d));    
     memset(&newtime,'\0',sizeof newtime);
     
-    if (t->type == V_ASN1_GENERALIZEDTIME) 
+    if (ASN1_STRING_type(t) == V_ASN1_GENERALIZEDTIME) 
     {
          // For time values >= 2050, OpenSSL uses
          // ASN1_GENERALIZEDTIME - which we'll worry about
@@ -1355,7 +1367,7 @@
        return 0;
     }
 
-    p = (char *)t->data;
+    p = (char *)ASN1_STRING_get0_data(t);
     sscanf(p,"%2s%2s%2s%2s%2s%2sZ", d, &d[3], &d[6], &d[9], &d[12], &d[15]);
     
     int year = strtol(d, (char **)NULL, 10);
@@ -1448,11 +1460,11 @@
     CHECK_CERT_EXISTS_SET("ski");
 
     ASN1_OCTET_STRING *oct = ASN1_OCTET_STRING_new();
-    ASN1_BIT_STRING *pk = X509_get0_pubkey_bitstr(cert);
+    const ASN1_BIT_STRING *pk = X509_get0_pubkey_bitstr(cert);
     unsigned char pkey_dig[EVP_MAX_MD_SIZE];
     unsigned int diglen;
 
-    EVP_Digest(pk->data, pk->length, pkey_dig, &diglen, EVP_sha1(), NULL);
+    EVP_Digest(ASN1_STRING_get0_data(pk), ASN1_STRING_length(pk), pkey_dig, 
&diglen, EVP_sha1(), NULL);
 
     ASN1_OCTET_STRING_set(oct, pkey_dig, diglen);
     X509_EXTENSION *ext = X509V3_EXT_i2d(NID_subject_key_identifier, 0, 
@@ -1470,10 +1482,11 @@
     // can't set a meaningful AKI for subordinate certification without the 
     // parent having an SKI
     ASN1_OCTET_STRING *ikeyid = NULL;
+    const X509_EXTENSION *src_ext;
     X509_EXTENSION *ext;
     int i = X509_get_ext_by_NID(cacert.cert, NID_subject_key_identifier, -1);
-    if ((i >= 0) && (ext = X509_get_ext(cacert.cert, i)))
-        ikeyid = static_cast<ASN1_OCTET_STRING *>(X509V3_EXT_d2i(ext));
+    if ((i >= 0) && (src_ext = X509_get_ext(cacert.cert, i)))
+        ikeyid = static_cast<ASN1_OCTET_STRING 
*>(X509V3_EXT_d2i(const_cast<X509_EXTENSION *>(src_ext)));
 
     if (!ikeyid)
         return;
Index: wvstreams/include/wvx509.h
===================================================================
--- wvstreams.orig/include/wvx509.h     2026-06-25 17:11:18.173814302 +0200
+++ wvstreams/include/wvx509.h  2026-06-25 17:11:18.167814259 +0200
@@ -161,7 +161,7 @@
      */
     WvString get_subject() const;
     void set_subject(WvStringParm name);
-    void set_subject(X509_NAME *name);
+    void set_subject(const X509_NAME *name);
 
     /**
      * get and set the serialNumber field of the certificate

Reply via email to