Submitted by:            Douglas R. Reno <renodr at linuxfromscratch dot org>
Date:                    2026-05-14
Initial Package Version: 7.99
Upstream Status:         Pending
Origin:                  Upstream PR#3331
Description:             Fixes compiling nmap with OpenSSL-4 by adjusting it to
                         use getter functions (ASN1_STRING_get0_data and
                         ASN1_STRING_length), and by changing OPENSSL_atexit to
                         atexit.

diff -Naurp nmap-7.99.orig/ncat/ncat_connect.c nmap-7.99/ncat/ncat_connect.c
--- nmap-7.99.orig/ncat/ncat_connect.c	2026-02-25 14:43:12.000000000 -0600
+++ nmap-7.99/ncat/ncat_connect.c	2026-05-14 15:51:41.766723390 -0500
@@ -237,7 +237,7 @@ static void connect_report(nsock_iod nsi
 #ifdef HAVE_OPENSSL
         if (nsock_iod_check_ssl(nsi)) {
             X509 *cert;
-            X509_NAME *subject;
+            const X509_NAME *subject;
             char digest_buf[SHA1_STRING_LENGTH + 1];
             char *fp;
 
diff -Naurp nmap-7.99.orig/ncat/ncat_ssl.c nmap-7.99/ncat/ncat_ssl.c
--- nmap-7.99.orig/ncat/ncat_ssl.c	2026-02-16 16:33:40.000000000 -0600
+++ nmap-7.99/ncat/ncat_ssl.c	2026-05-14 15:51:41.766884174 -0500
@@ -262,10 +262,10 @@ static int wildcard_match(const char *pa
 static int cert_match_dnsname(X509 *cert, const char *hostname,
     unsigned int *num_checked)
 {
-    X509_EXTENSION *ext;
+    const X509_EXTENSION *ext;
     STACK_OF(GENERAL_NAME) *gen_names;
     const X509V3_EXT_METHOD *method;
-    unsigned char *data;
+    const unsigned char *data;
     int i;
 
     if (num_checked != NULL)
@@ -287,8 +287,8 @@ static int cert_match_dnsname(X509 *cert
 
     /* We must copy this address into a temporary variable because ASN1_item_d2i
        increments it. We don't want it to corrupt ext->value->data. */
-    ASN1_OCTET_STRING* asn1_str = X509_EXTENSION_get_data(ext);
-    data = asn1_str->data;
+    const ASN1_OCTET_STRING* asn1_str = X509_EXTENSION_get_data(ext);
+    data = ASN1_STRING_get0_data(asn1_str);
     /* Here we rely on the fact that the internal representation (the "i" in
        "i2d") for NID_subject_alt_name is STACK_OF(GENERAL_NAME). Converting it
        to a stack of CONF_VALUE with a i2v method is not satisfactory, because a
@@ -296,15 +296,17 @@ static int cert_match_dnsname(X509 *cert
        presence of null bytes. */
 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
     if (method->it != NULL) {
-        ASN1_OCTET_STRING* asn1_str_a = X509_EXTENSION_get_data(ext);
+        const ASN1_OCTET_STRING* asn1_str_a = X509_EXTENSION_get_data(ext);
+        int length = ASN1_STRING_length(asn1_str_a);
         gen_names = (STACK_OF(GENERAL_NAME) *) ASN1_item_d2i(NULL,
             (const unsigned char **) &data,
-            asn1_str_a->length, ASN1_ITEM_ptr(method->it));
+            length, ASN1_ITEM_ptr(method->it));
     } else {
-        ASN1_OCTET_STRING* asn1_str_b = X509_EXTENSION_get_data(ext);
+        const ASN1_OCTET_STRING* asn1_str_b = X509_EXTENSION_get_data(ext);
+        int length = ASN1_STRING_length(asn1_str_b);
         gen_names = (STACK_OF(GENERAL_NAME) *) method->d2i(NULL,
             (const unsigned char **) &data,
-            asn1_str_b->length);
+            length);
     }
 #else
     gen_names = (STACK_OF(GENERAL_NAME) *) method->d2i(NULL,
@@ -371,9 +373,9 @@ static int less_specific(const unsigned
     return num_components(a, a_len) < num_components(b, b_len);
 }
 
-static int most_specific_commonname(X509_NAME *subject, const char **result)
+static int most_specific_commonname(const X509_NAME *subject, const char **result)
 {
-    ASN1_STRING *best, *cur;
+    const ASN1_STRING *best, *cur;
     int i;
 
     i = -1;
@@ -407,7 +409,7 @@ static int most_specific_commonname(X509
    components, the one that comes later in the certificate is more specific. */
 static int cert_match_commonname(X509 *cert, const char *hostname)
 {
-    X509_NAME *subject;
+    const X509_NAME *subject;
     const char *commonname;
     int n;
 
@@ -470,7 +472,7 @@ int ssl_post_connect_check(SSL *ssl, con
    "Making Certificates"; and apps/req.c in the OpenSSL source. */
 static int ssl_gen_cert(X509 **cert, EVP_PKEY **key)
 {
-    X509_NAME *subj;
+    const X509_NAME *subj;
     X509_EXTENSION *ext;
     X509V3_CTX ctx;
     const char *commonName = "localhost";
@@ -527,7 +529,7 @@ static int ssl_gen_cert(X509 **cert, EVP
     subj = X509_get_subject_name(*cert);
     if (o.target != NULL)
         commonName = o.target;
-    if (X509_NAME_add_entry_by_txt(subj, "commonName", MBSTRING_ASC,
+    if (X509_NAME_add_entry_by_txt((X509_NAME *) subj, "commonName", MBSTRING_ASC,
         (unsigned char *) commonName, -1, -1, 0) == 0) {
         goto err;
     }
diff -Naurp nmap-7.99.orig/nse_ssl_cert.cc nmap-7.99/nse_ssl_cert.cc
--- nmap-7.99.orig/nse_ssl_cert.cc	2026-02-16 16:33:40.000000000 -0600
+++ nmap-7.99/nse_ssl_cert.cc	2026-05-14 15:52:39.724992034 -0500
@@ -194,14 +194,14 @@ static void obj_to_key(lua_State *L, con
 /* This is a helper function for l_get_ssl_certificate. It builds a table from
    the given X509_NAME, using keys returned from obj_to_key as keys. The result
    is pushed on the stack. */
-static void x509_name_to_table(lua_State *L, X509_NAME *name)
+static void x509_name_to_table(lua_State *L, const X509_NAME *name)
 {
   int i;
 
   lua_createtable(L, 0, X509_NAME_entry_count(name));
 
   for (i = 0; i < X509_NAME_entry_count(name); i++) {
-    X509_NAME_ENTRY *entry;
+    const X509_NAME_ENTRY *entry;
     const ASN1_OBJECT *obj;
     const ASN1_STRING *value;
 
@@ -210,7 +210,7 @@ static void x509_name_to_table(lua_State
     value = X509_NAME_ENTRY_get_data(entry);
 
     obj_to_key(L, obj);
-    lua_pushlstring(L, (const char *) value->data, value->length);
+    lua_pushlstring(L, (const char *) ASN1_STRING_get0_data(value), ASN1_STRING_length(value));
 
     lua_settable(L, -3);
   }
@@ -224,7 +224,7 @@ static bool x509_extensions_to_table(lua
   lua_createtable(L, sk_X509_EXTENSION_num(exts), 0);
 
   for (int i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
-    ASN1_OBJECT *obj;
+    const ASN1_OBJECT *obj;
     X509_EXTENSION *ext;
     char *value = NULL;
     BIO *out;
@@ -298,14 +298,16 @@ static int parse_int(const unsigned char
    -1 on a parse error. */
 static int time_to_tm(const ASN1_TIME *t, struct tm *result)
 {
+  const unsigned char *data = ASN1_STRING_get0_data(t);
+  int length = ASN1_STRING_length(t);
   const unsigned char *p;
 
-  p = t->data;
-  if (t->length == 13 && t->data[t->length - 1] == 'Z') {
+  p = data;
+  if (length == 13 && data[length - 1] == 'Z') {
     /* yymmddhhmmssZ */
     int year;
 
-    year = parse_int(t->data, 2);
+    year = parse_int(data, 2);
     if (year < 0)
       return -1;
     /* "In coming up with the worlds least efficient machine-readable time
@@ -318,13 +320,13 @@ static int time_to_tm(const ASN1_TIME *t
       result->tm_year = 2000 + year;
     else
       result->tm_year = 1900 + year;
-    p = t->data + 2;
-  } else if (t->length == 15 && t->data[t->length - 1] == 'Z') {
+    p = data + 2;
+  } else if (length == 15 && data[length - 1] == 'Z') {
     /* yyyymmddhhmmssZ */
-    result->tm_year = parse_int(t->data, 4);
+    result->tm_year = parse_int(data, 4);
     if (result->tm_year < 0)
       return -1;
-    p = t->data + 4;
+    p = data + 4;
   } else {
     return -1;
   }
@@ -385,7 +387,7 @@ static void asn1_time_to_obj(lua_State *
   } else if (time_to_tm(s, &tm) == 0) {
       tm_to_table(L, &tm);
   } else {
-      lua_pushlstring(L, (const char *) s->data, s->length);
+      lua_pushlstring(L, (const char *) ASN1_STRING_get0_data(s), ASN1_STRING_length(s));
   }
 }
 
@@ -568,7 +570,7 @@ int l_get_ssl_certificate(lua_State *L)
 static int parse_ssl_cert(lua_State *L, X509 *cert)
 {
   struct cert_userdata *udata;
-  X509_NAME *subject, *issuer;
+  const X509_NAME *subject, *issuer;
   EVP_PKEY *pubkey;
   int pkey_type;
 
diff -Naurp nmap-7.99.orig/nsock/src/nsock_ssl.c nmap-7.99/nsock/src/nsock_ssl.c
--- nmap-7.99.orig/nsock/src/nsock_ssl.c	2026-02-25 14:43:12.000000000 -0600
+++ nmap-7.99/nsock/src/nsock_ssl.c	2026-05-14 15:51:41.767095344 -0500
@@ -118,7 +118,11 @@ static SSL_CTX *ssl_init_helper(const SS
     SSL_load_error_strings();
     SSL_library_init();
 #else
+#if OPENSSL_VERSION_NUMBER < 0x40000000L
     OPENSSL_atexit(nsock_ssl_atexit);
+#else
+    atexit(nsock_ssl_atexit);
+#endif
 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
     if (NULL == OSSL_PROVIDER_load(NULL, "legacy"))
     {
