This is an automated email from the ASF dual-hosted git repository.

markt-asf pushed a commit to branch 1.3.x
in repository https://gitbox.apache.org/repos/asf/tomcat-native.git


The following commit(s) were added to refs/heads/1.3.x by this push:
     new 4a70b839f Further robustness improvements to OCSP AIA parsing
4a70b839f is described below

commit 4a70b839f725bd47659980e58ef4cf6923388a4b
Author: Mark Thomas <[email protected]>
AuthorDate: Fri Aug 28 17:05:29 2026 +0100

    Further robustness improvements to OCSP AIA parsing
---
 native/src/sslutils.c | 63 ++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 45 insertions(+), 18 deletions(-)

diff --git a/native/src/sslutils.c b/native/src/sslutils.c
index 70b328039..b17638ffc 100644
--- a/native/src/sslutils.c
+++ b/native/src/sslutils.c
@@ -31,9 +31,10 @@ extern int WIN32_SSL_password_prompt(tcn_pass_cb_t *data);
 #include <openssl/bio.h>
 #include <openssl/ocsp.h>
 /* defines with the values as seen by the asn1parse -dump openssl command */
-#define ASN1_SEQUENCE 0x30
-#define ASN1_OID      0x06
-#define ASN1_STRING   0x86
+#define ASN1_SEQUENCE           0x30
+#define ASN1_OID                0x06
+#define ASN1_STRING             0x86
+#define MAX_AIA_SEQUENCE_DEPTH  2
 static int ssl_verify_OCSP(X509_STORE_CTX *ctx, int timeout, int verifyFlags);
 static int ssl_ocsp_request(X509 *cert, X509 *issuer, X509_STORE_CTX *ctx, int 
timeout, int verifyFlags);
 #endif
@@ -584,12 +585,16 @@ static void *apr_xrealloc(void *buf, size_t oldlen, 
size_t len, apr_pool_t *p)
  * Updates the pointer to the ASN.1 structure to point to the start of the 
data.
  * Returns 0 on success, 1 on failure.
  */
-static int parse_asn1_length(unsigned char **asn1, int *len) {
+static int parse_asn1_length(unsigned char **asn1, int *remaining, int *len) {
 
     /* Length immediately follows tag so increment before reading first (and
      * possibly only) length byte.
      */
     (*asn1)++;
+    (*remaining)--;
+    if (*remaining < 0) {
+        return 1;
+    }
 
     if (**asn1 & 0x80) {
         // MSB set. Remaining bits are number of bytes used to store the 
length.
@@ -617,6 +622,10 @@ static int parse_asn1_length(unsigned char **asn1, int 
*len) {
         while (i > 0) {
             l <<= 8;
             (*asn1)++;
+            (*remaining)--;
+            if (*remaining < 0) {
+                return 1;
+            }
             l += **asn1;
             i--;
         }
@@ -627,21 +636,27 @@ static int parse_asn1_length(unsigned char **asn1, int 
*len) {
     }
 
     (*asn1)++;
+    (*remaining)--;
+    if (*remaining < 0) {
+        return 1;
+    }
 
     return 0;
 }
 
 /* parses the ocsp url and updates the ocsp_urls and nocsp_urls variables
    returns 0 on success, 1 on failure */
-static int parse_ocsp_url(unsigned char *asn1, char ***ocsp_urls,
+static int parse_ocsp_url(unsigned char *asn1, int remaining, char 
***ocsp_urls,
                           int *nocsp_urls, apr_pool_t *p)
 {
     char **new_ocsp_urls, *ocsp_url;
     int len, err = 0, new_nocsp_urls;
 
     if (*asn1 == ASN1_STRING) {
-        err = parse_asn1_length(&asn1, &len);
-
+        err = parse_asn1_length(&asn1, &remaining, &len);
+        if (!err && len > remaining) {
+            err = 1;
+        }
         if (!err) {
             new_nocsp_urls = *nocsp_urls+1;
             if ((new_ocsp_urls = apr_xrealloc(*ocsp_urls, *nocsp_urls * 
sizeof(char *), new_nocsp_urls * sizeof(char *), p)) == NULL)
@@ -665,16 +680,19 @@ static int parse_ocsp_url(unsigned char *asn1, char 
***ocsp_urls,
 }
 
 /* parses the ANS1 OID and if it is an OCSP OID then calls the parse_ocsp_url 
function */
-static int parse_ASN1_OID(unsigned char *asn1, char ***ocsp_urls, int 
*nocsp_urls, apr_pool_t *p)
+static int parse_ASN1_OID(unsigned char *asn1, int remaining, char 
***ocsp_urls, int *nocsp_urls, apr_pool_t *p)
 {
     int len, err = 0 ;
     const unsigned char OCSP_OID[] = {0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 
0x30, 0x01};
 
-    err = parse_asn1_length(&asn1, &len);
-
+    err = parse_asn1_length(&asn1, &remaining, &len);
+    if (!err && len > remaining) {
+        err = 1;
+    }
     if (!err && len == 8 && memcmp(asn1, OCSP_OID, 8) == 0) {
-        asn1+=len;
-        err = parse_ocsp_url(asn1, ocsp_urls, nocsp_urls, p);
+        asn1 += len;
+        remaining -= len;
+        err = parse_ocsp_url(asn1, remaining, ocsp_urls, nocsp_urls, p);
     }
     return err;
 }
@@ -686,21 +704,29 @@ static int parse_ASN1_OID(unsigned char *asn1, char 
***ocsp_urls, int *nocsp_url
    the same sequence the while loop parses the sequences */
 
 /* This algo was developed with AIA in mind so it was tested only with this 
extension */
-static int parse_ASN1_Sequence(unsigned char *asn1, char ***ocsp_urls,
+static int parse_ASN1_Sequence(unsigned char *asn1, int remaining, int depth, 
char ***ocsp_urls,
                                int *nocsp_urls, apr_pool_t *p)
 {
     int len = 0 , err = 0;
 
-    while (!err && *asn1 != '\0') {
+    while (!err && *asn1 != '\0' && remaining > 0) {
         switch(*asn1) {
             case ASN1_SEQUENCE:
-                err = parse_asn1_length(&asn1, &len);
+                /* Initial call uses depth 0. */
+                if (depth >= MAX_AIA_SEQUENCE_DEPTH) {
+                    return 1;
+                }
+                err = parse_asn1_length(&asn1, &remaining, &len);
                 if (!err) {
-                    err = parse_ASN1_Sequence(asn1, ocsp_urls, nocsp_urls, p);
+                    if (len > remaining) {
+                        err = 1;
+                    } else {
+                        err = parse_ASN1_Sequence(asn1, len, depth + 1, 
ocsp_urls, nocsp_urls, p);
+                    }
                 }
             break;
             case ASN1_OID:
-                err = parse_ASN1_OID(asn1,ocsp_urls,nocsp_urls, p);
+                err = parse_ASN1_OID(asn1, remaining, ocsp_urls, nocsp_urls, 
p);
                 return err;
             break;
             default:
@@ -708,6 +734,7 @@ static int parse_ASN1_Sequence(unsigned char *asn1, char 
***ocsp_urls,
             break;
         }
         asn1+=len;
+        remaining -= len;
     }
     return err;
 }
@@ -733,7 +760,7 @@ static char **decode_OCSP_url(ASN1_OCTET_STRING *os, int 
*numofresponses, apr_po
     if ((response = apr_pcalloc(p, sizeof(char *))) == NULL) {
         return NULL;
     }
-    if (parse_ASN1_Sequence(ocsp_urls, &response, numofresponses, p) ||
+    if (parse_ASN1_Sequence(ocsp_urls, len, 0, &response, numofresponses, p) ||
             *numofresponses ==0) {
         response = NULL;
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to