d738b9
From 62eb62a3db7d40a44f26c3e563cfa22b1f05d93d Mon Sep 17 00:00:00 2001
d738b9
From: Greg Hudson <ghudson@mit.edu>
d738b9
Date: Tue, 17 Oct 2017 18:50:15 -0400
d738b9
Subject: [PATCH] Fix PKINIT cert matching data construction
d738b9
d738b9
Rewrite X509_NAME_oneline_ex() and its call sites to use dynamic
d738b9
allocation and to perform proper error checking.
d738b9
d738b9
ticket: 8617
d738b9
target_version: 1.16
d738b9
target_version: 1.15-next
d738b9
target_version: 1.14-next
d738b9
tags: pullup
d738b9
d738b9
(cherry picked from commit fbb687db1088ddd894d975996e5f6a4252b9a2b4)
d738b9
---
d738b9
 .../preauth/pkinit/pkinit_crypto_openssl.c    | 67 +++++++------------
d738b9
 1 file changed, 25 insertions(+), 42 deletions(-)
d738b9
d738b9
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
d738b9
index f70aab5b3..34ed7afaf 100644
d738b9
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
d738b9
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
d738b9
@@ -5052,33 +5052,29 @@ out:
d738b9
     return retval;
d738b9
 }
d738b9
 
d738b9
-/*
d738b9
- * Return a string format of an X509_NAME in buf where
d738b9
- * size is an in/out parameter.  On input it is the size
d738b9
- * of the buffer, and on output it is the actual length
d738b9
- * of the name.
d738b9
- * If buf is NULL, returns the length req'd to hold name
d738b9
- */
d738b9
-static char *
d738b9
-X509_NAME_oneline_ex(X509_NAME * a,
d738b9
-                     char *buf,
d738b9
-                     unsigned int *size,
d738b9
-                     unsigned long flag)
d738b9
+static krb5_error_code
d738b9
+rfc2253_name(X509_NAME *name, char **str_out)
d738b9
 {
d738b9
-    BIO *out = NULL;
d738b9
+    BIO *b = NULL;
d738b9
+    char *str;
d738b9
 
d738b9
-    out = BIO_new(BIO_s_mem ());
d738b9
-    if (X509_NAME_print_ex(out, a, 0, flag) > 0) {
d738b9
-        if (buf != NULL && (*size) >  (unsigned int) BIO_number_written(out)) {
d738b9
-            memset(buf, 0, *size);
d738b9
-            BIO_read(out, buf, (int) BIO_number_written(out));
d738b9
-        }
d738b9
-        else {
d738b9
-            *size = BIO_number_written(out);
d738b9
-        }
d738b9
-    }
d738b9
-    BIO_free(out);
d738b9
-    return (buf);
d738b9
+    *str_out = NULL;
d738b9
+    b = BIO_new(BIO_s_mem());
d738b9
+    if (b == NULL)
d738b9
+        return ENOMEM;
d738b9
+    if (X509_NAME_print_ex(b, name, 0, XN_FLAG_SEP_COMMA_PLUS) < 0)
d738b9
+        goto error;
d738b9
+    str = calloc(BIO_number_written(b) + 1, 1);
d738b9
+    if (str == NULL)
d738b9
+        goto error;
d738b9
+    BIO_read(b, str, BIO_number_written(b));
d738b9
+    BIO_free(b);
d738b9
+    *str_out = str;
d738b9
+    return 0;
d738b9
+
d738b9
+error:
d738b9
+    BIO_free(b);
d738b9
+    return ENOMEM;
d738b9
 }
d738b9
 
d738b9
 /*
d738b9
@@ -5144,8 +5140,6 @@ get_matching_data(krb5_context context,
d738b9
     pkinit_cert_matching_data *md = NULL;
d738b9
     krb5_principal *pkinit_sans = NULL, *upn_sans = NULL;
d738b9
     size_t i, j;
d738b9
-    char buf[DN_BUF_LEN];
d738b9
-    unsigned int bufsize = sizeof(buf);
d738b9
 
d738b9
     *md_out = NULL;
d738b9
 
d738b9
@@ -5153,23 +5147,12 @@ get_matching_data(krb5_context context,
d738b9
     if (md == NULL)
d738b9
         goto cleanup;
d738b9
 
d738b9
-    /* Get the subject name (in rfc2253 format). */
d738b9
-    X509_NAME_oneline_ex(X509_get_subject_name(cert), buf, &bufsize,
d738b9
-                         XN_FLAG_SEP_COMMA_PLUS);
d738b9
-    md->subject_dn = strdup(buf);
d738b9
-    if (md->subject_dn == NULL) {
d738b9
-        ret = ENOMEM;
d738b9
+    ret = rfc2253_name(X509_get_subject_name(cert), &md->subject_dn);
d738b9
+    if (ret)
d738b9
         goto cleanup;
d738b9
-    }
d738b9
-
d738b9
-    /* Get the issuer name (in rfc2253 format). */
d738b9
-    X509_NAME_oneline_ex(X509_get_issuer_name(cert), buf, &bufsize,
d738b9
-                         XN_FLAG_SEP_COMMA_PLUS);
d738b9
-    md->issuer_dn = strdup(buf);
d738b9
-    if (md->issuer_dn == NULL) {
d738b9
-        ret = ENOMEM;
d738b9
+    ret = rfc2253_name(X509_get_issuer_name(cert), &md->issuer_dn);
d738b9
+    if (ret)
d738b9
         goto cleanup;
d738b9
-    }
d738b9
 
d738b9
     /* Get the SAN data. */
d738b9
     ret = crypto_retrieve_X509_sans(context, plg_cryptoctx, req_cryptoctx,