darwinssl: fix SSL client certificate not found on MacOS Sierra

Reviewed-by: Nick Zitzmann

Closes #1105
This commit is contained in:
David Schweikert 2016-11-04 15:18:16 +01:00 коммит произвёл Daniel Stenberg
Родитель 0744506cd2
Коммит 7c9b9add6f
1 изменённых файлов: 45 добавлений и 9 удалений

Просмотреть файл

@ -883,14 +883,18 @@ static OSStatus CopyIdentityWithLabel(char *label,
SecIdentityRef *out_cert_and_key)
{
OSStatus status = errSecItemNotFound;
CFArrayRef keys_list;
CFIndex keys_list_count;
CFIndex i;
CFStringRef common_name;
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
/* SecItemCopyMatching() was introduced in iOS and Snow Leopard.
kSecClassIdentity was introduced in Lion. If both exist, let's use them
to find the certificate. */
if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) {
CFTypeRef keys[4];
CFTypeRef values[4];
CFTypeRef keys[5];
CFTypeRef values[5];
CFDictionaryRef query_dict;
CFStringRef label_cf = CFStringCreateWithCString(NULL, label,
kCFStringEncodingUTF8);
@ -900,21 +904,53 @@ static OSStatus CopyIdentityWithLabel(char *label,
keys[0] = kSecClass;
values[1] = kCFBooleanTrue; /* we want a reference */
keys[1] = kSecReturnRef;
values[2] = kSecMatchLimitOne; /* one is enough, thanks */
values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the
* label matching below worked correctly */
keys[2] = kSecMatchLimit;
/* identity searches need a SecPolicyRef in order to work */
values[3] = SecPolicyCreateSSL(false, label_cf);
values[3] = SecPolicyCreateSSL(false, NULL);
keys[3] = kSecMatchPolicy;
/* match the name of the certificate (doesn't work in macOS 10.12.1) */
values[4] = label_cf;
keys[4] = kSecAttrLabel;
query_dict = CFDictionaryCreate(NULL, (const void **)keys,
(const void **)values, 4L,
&kCFCopyStringDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
(const void **)values, 5L,
&kCFCopyStringDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFRelease(values[3]);
CFRelease(label_cf);
/* Do we have a match? */
status = SecItemCopyMatching(query_dict, (CFTypeRef *)out_cert_and_key);
status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list);
/* Because kSecAttrLabel matching doesn't work with kSecClassIdentity,
* we need to find the correct identity ourselves */
if(status == noErr) {
keys_list_count = CFArrayGetCount(keys_list);
*out_cert_and_key = NULL;
for(i=0; i<keys_list_count; i++) {
OSStatus err = noErr;
SecCertificateRef cert = NULL;
*out_cert_and_key =
(SecIdentityRef) CFArrayGetValueAtIndex(keys_list, i);
err = SecIdentityCopyCertificate(*out_cert_and_key, &cert);
if(err == noErr) {
SecCertificateCopyCommonName(cert, &common_name);
if(CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) {
CFRelease(cert);
CFRelease(common_name);
status = noErr;
break;
}
CFRelease(common_name);
}
*out_cert_and_key = NULL;
status = 1;
CFRelease(cert);
}
}
CFRelease(query_dict);
CFRelease(label_cf);
}
else {
#if CURL_SUPPORT_MAC_10_6