From e839446c2a5558ffd43eb8c381c7485c2d9a210c Mon Sep 17 00:00:00 2001
From: Patrick Monnerat <pm@datasphere.ch>
Date: Mon, 15 Jul 2013 17:26:59 +0200
Subject: [PATCH] ssluse.c,sslgen.c,sslgen.h: move certinfo support to generic
 SSL

---
 lib/sslgen.c |  65 ++++++++++++++++++++++++++++++++
 lib/sslgen.h |   9 +++++
 lib/ssluse.c | 102 ++++++++-------------------------------------------
 3 files changed, 90 insertions(+), 86 deletions(-)

diff --git a/lib/sslgen.c b/lib/sslgen.c
index dee06e89c2..d9b5c47155 100644
--- a/lib/sslgen.c
+++ b/lib/sslgen.c
@@ -31,6 +31,7 @@
    Curl_ossl_ - prefix for OpenSSL ones
    Curl_gtls_ - prefix for GnuTLS ones
    Curl_nss_ - prefix for NSS ones
+   Curl_qssl_ - prefix for QsoSSL ones
    Curl_polarssl_ - prefix for PolarSSL ones
    Curl_cyassl_ - prefix for CyaSSL ones
    Curl_schannel_ - prefix for Schannel SSPI ones
@@ -67,6 +68,7 @@
 #include "cyassl.h"  /* CyaSSL versions */
 #include "curl_schannel.h" /* Schannel SSPI version */
 #include "curl_darwinssl.h" /* SecureTransport (Darwin) version */
+#include "slist.h"
 #include "sendf.h"
 #include "rawstr.h"
 #include "url.h"
@@ -74,6 +76,10 @@
 #include "progress.h"
 #include "share.h"
 #include "timeval.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
 /* The last #include file should be: */
 #include "memdebug.h"
 
@@ -585,6 +591,65 @@ void Curl_ssl_free_certinfo(struct SessionHandle *data)
   }
 }
 
+int Curl_ssl_init_certinfo(struct SessionHandle * data,
+                           int num)
+{
+  struct curl_certinfo * ci = &data->info.certs;
+  struct curl_slist * * table;
+
+  /* Initialize the certificate information structures. Return 0 if OK, else 1.
+   */
+  Curl_ssl_free_certinfo(data);
+  ci->num_of_certs = num;
+  table = calloc((size_t) num, sizeof(struct curl_slist *));
+  if(!table)
+    return 1;
+
+  ci->certinfo = table;
+  return 0;
+}
+
+CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle *data,
+                                    int certnum,
+                                    const char *label,
+                                    const char *value,
+                                    size_t valuelen)
+{
+  struct curl_certinfo * ci = &data->info.certs;
+  char * output;
+  struct curl_slist * nl;
+  CURLcode res = CURLE_OK;
+
+  /* Add an information record for a particular certificate. */
+  output = curl_maprintf("%s:%.*s", label, valuelen, value);
+  if(!output)
+    return CURLE_OUT_OF_MEMORY;
+
+  nl = Curl_slist_append_nodup(ci->certinfo[certnum], output);
+  if(!nl) {
+    free(output);
+    curl_slist_free_all(ci->certinfo[certnum]);
+    res = CURLE_OUT_OF_MEMORY;
+  }
+
+  ci->certinfo[certnum] = nl;
+  return res;
+}
+
+/*
+ * This is a convenience function for push_certinfo_len that takes a zero
+ * terminated value.
+ */
+CURLcode Curl_ssl_push_certinfo(struct SessionHandle *data,
+                                int certnum,
+                                const char *label,
+                                const char *value)
+{
+  size_t valuelen = strlen(value);
+
+  return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen);
+}
+
 /* these functions are only provided by some SSL backends */
 
 #ifdef have_curlssl_random
diff --git a/lib/sslgen.h b/lib/sslgen.h
index 182dd8f244..c7f5f0092d 100644
--- a/lib/sslgen.h
+++ b/lib/sslgen.h
@@ -58,7 +58,16 @@ size_t Curl_ssl_version(char *buffer, size_t size);
 bool Curl_ssl_data_pending(const struct connectdata *conn,
                            int connindex);
 int Curl_ssl_check_cxn(struct connectdata *conn);
+
+/* Certificate information list handling. */
+
 void Curl_ssl_free_certinfo(struct SessionHandle *data);
+int Curl_ssl_init_certinfo(struct SessionHandle * data, int num);
+CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle * data, int certnum,
+                                    const char * label, const char * value,
+                                    size_t valuelen);
+CURLcode Curl_ssl_push_certinfo(struct SessionHandle * data, int certnum,
+                                const char * label, const char * value);
 
 /* Functions to be used by SSL library adaptation functions */
 
diff --git a/lib/ssluse.c b/lib/ssluse.c
index b9560e508d..69328f66a3 100644
--- a/lib/ssluse.c
+++ b/lib/ssluse.c
@@ -43,6 +43,7 @@
 #include "inet_pton.h"
 #include "ssluse.h"
 #include "connect.h"
+#include "slist.h"
 #include "strequal.h"
 #include "select.h"
 #include "sslgen.h"
@@ -1790,60 +1791,6 @@ static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
   return 0;
 }
 
-static CURLcode push_certinfo_len(struct SessionHandle *data,
-                                  int certnum,
-                                  const char *label,
-                                  const char *value,
-                                  size_t valuelen)
-{
-  struct curl_certinfo *ci = &data->info.certs;
-  char *output;
-  struct curl_slist *nl;
-  CURLcode res = CURLE_OK;
-  size_t labellen = strlen(label);
-  size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */
-
-  output = malloc(outlen);
-  if(!output)
-    return CURLE_OUT_OF_MEMORY;
-
-  /* sprintf the label and colon */
-  snprintf(output, outlen, "%s:", label);
-
-  /* memcpy the value (it might not be zero terminated) */
-  memcpy(&output[labellen+1], value, valuelen);
-
-  /* zero terminate the output */
-  output[labellen + 1 + valuelen] = 0;
-
-  /* TODO: we should rather introduce an internal API that can do the
-     equivalent of curl_slist_append but doesn't strdup() the given data as
-     like in this place the extra malloc/free is totally pointless */
-  nl = curl_slist_append(ci->certinfo[certnum], output);
-  free(output);
-  if(!nl) {
-    curl_slist_free_all(ci->certinfo[certnum]);
-    ci->certinfo[certnum] = NULL;
-    res = CURLE_OUT_OF_MEMORY;
-  }
-  else
-    ci->certinfo[certnum] = nl;
-
-  return res;
-}
-
-/* this is a convenience function for push_certinfo_len that takes a zero
-   terminated value */
-static CURLcode push_certinfo(struct SessionHandle *data,
-                              int certnum,
-                              const char *label,
-                              const char *value)
-{
-  size_t valuelen = strlen(value);
-
-  return push_certinfo_len(data, certnum, label, value, valuelen);
-}
-
 static void pubkey_show(struct SessionHandle *data,
                         int num,
                         const char *type,
@@ -1867,7 +1814,7 @@ static void pubkey_show(struct SessionHandle *data,
       left -= 3;
     }
     infof(data, "   %s: %s\n", namebuf, buffer);
-    push_certinfo(data, num, namebuf, buffer);
+    Curl_ssl_push_certinfo(data, num, namebuf, buffer);
     free(buffer);
   }
 }
@@ -1936,7 +1883,7 @@ static int X509V3_ext(struct SessionHandle *data,
     }
     infof(data, "  %s\n", buf);
 
-    push_certinfo(data, certnum, namebuf, buf);
+    Curl_ssl_push_certinfo(data, certnum, namebuf, buf);
 
     BIO_free(bio_out);
 
@@ -1956,7 +1903,7 @@ static void X509_signature(struct SessionHandle *data,
     ptr+=snprintf(ptr, sizeof(buf)-(ptr-buf), "%02x:", sig->data[i]);
 
   infof(data, " Signature: %s\n", buf);
-  push_certinfo(data, numcert, "Signature", buf);
+  Curl_ssl_push_certinfo(data, numcert, "Signature", buf);
 }
 
 static void dumpcert(struct SessionHandle *data, X509 *x, int numcert)
@@ -1972,30 +1919,13 @@ static void dumpcert(struct SessionHandle *data, X509 *x, int numcert)
 
   infof(data, "%s\n", biomem->data);
 
-  push_certinfo_len(data, numcert, "Cert", biomem->data, biomem->length);
+  Curl_ssl_push_certinfo_len(data, numcert,
+                             "Cert", biomem->data, biomem->length);
 
   BIO_free(bio_out);
 
 }
 
-
-static int init_certinfo(struct SessionHandle *data,
-                         int num)
-{
-  struct curl_certinfo *ci = &data->info.certs;
-  struct curl_slist **table;
-
-  Curl_ssl_free_certinfo(data);
-
-  ci->num_of_certs = num;
-  table = calloc((size_t)num, sizeof(struct curl_slist *));
-  if(!table)
-    return 1;
-
-  ci->certinfo = table;
-  return 0;
-}
-
 /*
  * This size was previously 512 which has been reported "too small" without
  * any specifics, so it was enlarged to allow more data to get shown uncut.
@@ -2024,7 +1954,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
   }
 
   numcerts = sk_X509_num(sk);
-  if(init_certinfo(data, numcerts)) {
+  if(Curl_ssl_init_certinfo(data, numcerts)) {
     free(bufp);
     return CURLE_OUT_OF_MEMORY;
   }
@@ -2049,16 +1979,16 @@ static CURLcode get_cert_chain(struct connectdata *conn,
 
     (void)x509_name_oneline(X509_get_subject_name(x), bufp, CERTBUFFERSIZE);
     infof(data, "%2d Subject: %s\n", i, bufp);
-    push_certinfo(data, i, "Subject", bufp);
+    Curl_ssl_push_certinfo(data, i, "Subject", bufp);
 
     (void)x509_name_oneline(X509_get_issuer_name(x), bufp, CERTBUFFERSIZE);
     infof(data, "   Issuer: %s\n", bufp);
-    push_certinfo(data, i, "Issuer", bufp);
+    Curl_ssl_push_certinfo(data, i, "Issuer", bufp);
 
     value = X509_get_version(x);
     infof(data, "   Version: %lu (0x%lx)\n", value+1, value);
     snprintf(bufp, CERTBUFFERSIZE, "%lx", value);
-    push_certinfo(data, i, "Version", bufp); /* hex */
+    Curl_ssl_push_certinfo(data, i, "Version", bufp); /* hex */
 
     num=X509_get_serialNumber(x);
     if(num->length <= 4) {
@@ -2087,30 +2017,30 @@ static CURLcode get_cert_chain(struct connectdata *conn,
         bufp[0]=0;
     }
     if(bufp[0])
-      push_certinfo(data, i, "Serial Number", bufp); /* hex */
+      Curl_ssl_push_certinfo(data, i, "Serial Number", bufp); /* hex */
 
     cinf = x->cert_info;
 
     j = asn1_object_dump(cinf->signature->algorithm, bufp, CERTBUFFERSIZE);
     if(!j) {
       infof(data, "   Signature Algorithm: %s\n", bufp);
-      push_certinfo(data, i, "Signature Algorithm", bufp);
+      Curl_ssl_push_certinfo(data, i, "Signature Algorithm", bufp);
     }
 
     certdate = X509_get_notBefore(x);
     asn1_output(certdate, bufp, CERTBUFFERSIZE);
     infof(data, "   Start date: %s\n", bufp);
-    push_certinfo(data, i, "Start date", bufp);
+    Curl_ssl_push_certinfo(data, i, "Start date", bufp);
 
     certdate = X509_get_notAfter(x);
     asn1_output(certdate, bufp, CERTBUFFERSIZE);
     infof(data, "   Expire date: %s\n", bufp);
-    push_certinfo(data, i, "Expire date", bufp);
+    Curl_ssl_push_certinfo(data, i, "Expire date", bufp);
 
     j = asn1_object_dump(cinf->key->algor->algorithm, bufp, CERTBUFFERSIZE);
     if(!j) {
       infof(data, "   Public Key Algorithm: %s\n", bufp);
-      push_certinfo(data, i, "Public Key Algorithm", bufp);
+      Curl_ssl_push_certinfo(data, i, "Public Key Algorithm", bufp);
     }
 
     pubkey = X509_get_pubkey(x);
@@ -2122,7 +2052,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
         infof(data,  "   RSA Public Key (%d bits)\n",
               BN_num_bits(pubkey->pkey.rsa->n));
         snprintf(bufp, CERTBUFFERSIZE, "%d", BN_num_bits(pubkey->pkey.rsa->n));
-        push_certinfo(data, i, "RSA Public Key", bufp);
+        Curl_ssl_push_certinfo(data, i, "RSA Public Key", bufp);
 
         print_pubkey_BN(rsa, n, i);
         print_pubkey_BN(rsa, e, i);
-- 
GitLab