1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-22 08:08:50 -05:00

darwinssl: handle long strings in TLS certs

... as the previous fixed length 128 bytes buffer was sometimes too
small.

Fixes #1823
Closes #1831

Reported-by: Benjamin Sergeant
Assisted-by: Bill Pyne, Ray Satiro, Nick Zitzmann
This commit is contained in:
Daniel Stenberg 2017-08-25 16:56:03 +02:00
parent 8a84fcc4b5
commit b3b75d1778
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2

View File

@ -849,7 +849,7 @@ CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
into a string. Some aren't available under iOS or newer cats. So here's into a string. Some aren't available under iOS or newer cats. So here's
a unified function for getting a string describing the certificate that a unified function for getting a string describing the certificate that
ought to work in all cats starting with Leopard. */ ought to work in all cats starting with Leopard. */
CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert) CF_INLINE CFStringRef getsubject(SecCertificateRef cert)
{ {
CFStringRef server_cert_summary = CFSTR("(null)"); CFStringRef server_cert_summary = CFSTR("(null)");
@ -876,6 +876,39 @@ CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert)
return server_cert_summary; return server_cert_summary;
} }
static CURLcode CopyCertSubject(struct Curl_easy *data,
SecCertificateRef cert, char **certp)
{
CFStringRef c = getsubject(cert);
CURLcode result = CURLE_OK;
char *cbuf = NULL;
*certp = NULL;
/* If subject is not UTF-8 then check if it can be converted */
if(!CFStringGetCStringPtr(c, kCFStringEncodingUTF8)) {
size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1;
cbuf = calloc(cbuf_size, 1);
if(cbuf) {
if(!CFStringGetCString(c, cbuf, cbuf_size,
kCFStringEncodingUTF8)) {
failf(data, "SSL: invalid CA certificate subject");
result = CURLE_SSL_CACERT;
}
else
/* pass back the buffer */
*certp = cbuf;
}
else {
failf(data, "SSL: couldn't allocate %zu bytes of memory", cbuf_size);
result = CURLE_OUT_OF_MEMORY;
}
}
if(result)
free(cbuf);
CFRelease(c);
return result;
}
#if CURL_SUPPORT_MAC_10_6 #if CURL_SUPPORT_MAC_10_6
/* The SecKeychainSearch API was deprecated in Lion, and using it will raise /* The SecKeychainSearch API was deprecated in Lion, and using it will raise
deprecation warnings, so let's not compile this unless it's necessary: */ deprecation warnings, so let's not compile this unless it's necessary: */
@ -1418,20 +1451,16 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
/* If we found one, print it out: */ /* If we found one, print it out: */
err = SecIdentityCopyCertificate(cert_and_key, &cert); err = SecIdentityCopyCertificate(cert_and_key, &cert);
if(err == noErr) { if(err == noErr) {
CFStringRef cert_summary = CopyCertSubject(cert); char *certp;
char cert_summary_c[128]; CURLcode result = CopyCertSubject(data, cert, &certp);
if(!result) {
if(cert_summary) { infof(data, "Client certificate: %s\n", certp);
memset(cert_summary_c, 0, 128); free(certp);
if(CFStringGetCString(cert_summary,
cert_summary_c,
128,
kCFStringEncodingUTF8)) {
infof(data, "Client certificate: %s\n", cert_summary_c);
}
CFRelease(cert_summary);
CFRelease(cert);
} }
CFRelease(cert);
if(result)
return result;
} }
certs_c[0] = cert_and_key; certs_c[0] = cert_and_key;
certs = CFArrayCreate(NULL, (const void **)certs_c, 1L, certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
@ -1875,6 +1904,8 @@ static int append_cert_to_array(struct Curl_easy *data,
CFMutableArrayRef array) CFMutableArrayRef array)
{ {
CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen); CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen);
char *certp;
CURLcode result;
if(!certdata) { if(!certdata) {
failf(data, "SSL: failed to allocate array for CA certificate"); failf(data, "SSL: failed to allocate array for CA certificate");
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -1889,25 +1920,10 @@ static int append_cert_to_array(struct Curl_easy *data,
} }
/* Check if cacert is valid. */ /* Check if cacert is valid. */
CFStringRef subject = CopyCertSubject(cacert); result = CopyCertSubject(data, cacert, &certp);
if(subject) { if(result)
char subject_cbuf[128]; return result;
memset(subject_cbuf, 0, 128); free(certp);
if(!CFStringGetCString(subject,
subject_cbuf,
128,
kCFStringEncodingUTF8)) {
CFRelease(cacert);
failf(data, "SSL: invalid CA certificate subject");
return CURLE_SSL_CACERT;
}
CFRelease(subject);
}
else {
CFRelease(cacert);
failf(data, "SSL: invalid CA certificate");
return CURLE_SSL_CACERT;
}
CFArrayAppendValue(array, cacert); CFArrayAppendValue(array, cacert);
CFRelease(cacert); CFRelease(cacert);
@ -2299,8 +2315,6 @@ show_verbose_server_cert(struct connectdata *conn,
{ {
struct Curl_easy *data = conn->data; struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
CFStringRef server_cert_summary;
char server_cert_summary_c[128];
CFArrayRef server_certs = NULL; CFArrayRef server_certs = NULL;
SecCertificateRef server_cert; SecCertificateRef server_cert;
OSStatus err; OSStatus err;
@ -2319,16 +2333,14 @@ show_verbose_server_cert(struct connectdata *conn,
if(err == noErr && trust) { if(err == noErr && trust) {
count = SecTrustGetCertificateCount(trust); count = SecTrustGetCertificateCount(trust);
for(i = 0L ; i < count ; i++) { for(i = 0L ; i < count ; i++) {
CURLcode result;
char *certp;
server_cert = SecTrustGetCertificateAtIndex(trust, i); server_cert = SecTrustGetCertificateAtIndex(trust, i);
server_cert_summary = CopyCertSubject(server_cert); result = CopyCertSubject(data, server_cert, &certp);
memset(server_cert_summary_c, 0, 128); if(!result) {
if(CFStringGetCString(server_cert_summary, infof(data, "Server certificate: %s\n", certp);
server_cert_summary_c, free(certp);
128,
kCFStringEncodingUTF8)) {
infof(data, "Server certificate: %s\n", server_cert_summary_c);
} }
CFRelease(server_cert_summary);
} }
CFRelease(trust); CFRelease(trust);
} }
@ -2347,16 +2359,14 @@ show_verbose_server_cert(struct connectdata *conn,
if(err == noErr && trust) { if(err == noErr && trust) {
count = SecTrustGetCertificateCount(trust); count = SecTrustGetCertificateCount(trust);
for(i = 0L ; i < count ; i++) { for(i = 0L ; i < count ; i++) {
char *certp;
CURLcode result;
server_cert = SecTrustGetCertificateAtIndex(trust, i); server_cert = SecTrustGetCertificateAtIndex(trust, i);
server_cert_summary = CopyCertSubject(server_cert); result = CopyCertSubject(data, server_cert, &certp);
memset(server_cert_summary_c, 0, 128); if(!result) {
if(CFStringGetCString(server_cert_summary, infof(data, "Server certificate: %s\n", certp);
server_cert_summary_c, free(certp);
128,
kCFStringEncodingUTF8)) {
infof(data, "Server certificate: %s\n", server_cert_summary_c);
} }
CFRelease(server_cert_summary);
} }
CFRelease(trust); CFRelease(trust);
} }
@ -2368,18 +2378,15 @@ show_verbose_server_cert(struct connectdata *conn,
if(err == noErr && server_certs) { if(err == noErr && server_certs) {
count = CFArrayGetCount(server_certs); count = CFArrayGetCount(server_certs);
for(i = 0L ; i < count ; i++) { for(i = 0L ; i < count ; i++) {
char *certp;
CURLcode result;
server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
i); i);
result = CopyCertSubject(data, server_cert, &certp);
server_cert_summary = CopyCertSubject(server_cert); if(!result) {
memset(server_cert_summary_c, 0, 128); infof(data, "Server certificate: %s\n", certp);
if(CFStringGetCString(server_cert_summary, free(certp);
server_cert_summary_c,
128,
kCFStringEncodingUTF8)) {
infof(data, "Server certificate: %s\n", server_cert_summary_c);
} }
CFRelease(server_cert_summary);
} }
CFRelease(server_certs); CFRelease(server_certs);
} }
@ -2392,16 +2399,14 @@ show_verbose_server_cert(struct connectdata *conn,
if(err == noErr) { if(err == noErr) {
count = CFArrayGetCount(server_certs); count = CFArrayGetCount(server_certs);
for(i = 0L ; i < count ; i++) { for(i = 0L ; i < count ; i++) {
CURLcode result;
char *certp;
server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i); server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i);
server_cert_summary = CopyCertSubject(server_cert); result = CopyCertSubject(data, server_cert, &certp);
memset(server_cert_summary_c, 0, 128); if(!result) {
if(CFStringGetCString(server_cert_summary, infof(data, "Server certificate: %s\n", certp);
server_cert_summary_c, free(certp);
128,
kCFStringEncodingUTF8)) {
infof(data, "Server certificate: %s\n", server_cert_summary_c);
} }
CFRelease(server_cert_summary);
} }
CFRelease(server_certs); CFRelease(server_certs);
} }