diff --git a/lib/sslgen.c b/lib/sslgen.c index dee06e89c..d9b5c4715 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 + /* 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 182dd8f24..c7f5f0092 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 b9560e508..69328f66a 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);