From f8475c69410dc401974ffe54691c1f44b0577141 Mon Sep 17 00:00:00 2001 From: Dair Grant Date: Wed, 15 Nov 2017 21:30:58 +0000 Subject: darwinssl: Don't import client certificates into Keychain on macOS Closes #2085 --- lib/vtls/darwinssl.c | 73 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 12 deletions(-) diff --git a/lib/vtls/darwinssl.c b/lib/vtls/darwinssl.c index 53a7ec37b..694ac572d 100644 --- a/lib/vtls/darwinssl.c +++ b/lib/vtls/darwinssl.c @@ -1135,28 +1135,77 @@ static OSStatus CopyIdentityFromPKCS12File(const char *cPath, raise linker errors when used on that cat for some reason. */ #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS if(CFURLCreateDataAndPropertiesFromResource(NULL, pkcs_url, &pkcs_data, - NULL, NULL, &status)) { + NULL, NULL, &status)) { + CFArrayRef items = NULL; + + /* On iOS SecPKCS12Import will never add the client certificate to the + * Keychain. + * + * It gives us back a SecIdentityRef that we can use directly. */ +#if CURL_BUILD_IOS const void *cKeys[] = {kSecImportExportPassphrase}; const void *cValues[] = {password}; CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues, password ? 1L : 0L, NULL, NULL); - CFArrayRef items = NULL; - /* Here we go: */ - status = SecPKCS12Import(pkcs_data, options, &items); - if(status == errSecSuccess && items && CFArrayGetCount(items)) { - CFDictionaryRef identity_and_trust = CFArrayGetValueAtIndex(items, 0L); - const void *temp_identity = CFDictionaryGetValue(identity_and_trust, - kSecImportItemIdentity); + if(options != NULL) { + status = SecPKCS12Import(pkcs_data, options, &items); + CFRelease(options); + } + - /* Retain the identity; we don't care about any other data... */ - CFRetain(temp_identity); - *out_cert_and_key = (SecIdentityRef)temp_identity; + /* On macOS SecPKCS12Import will always add the client certificate to + * the Keychain. + * + * As this doesn't match iOS, and apps may not want to see their client + * certificate saved in the the user's keychain, we use SecItemImport + * with a NULL keychain to avoid importing it. + * + * This returns a SecCertificateRef from which we can construct a + * SecIdentityRef. + */ +#elif CURL_BUILD_MAC_10_7 + SecItemImportExportKeyParameters keyParams; + SecExternalFormat inputFormat = kSecFormatPKCS12; + SecExternalItemType inputType = kSecItemTypeCertificate; + + memset(&keyParams, 0x00, sizeof(keyParams)); + keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; + keyParams.passphrase = password; + + status = SecItemImport(pkcs_data, NULL, &inputFormat, &inputType, + 0, &keyParams, NULL, &items); +#endif + + + /* Extract the SecIdentityRef */ + if(status == errSecSuccess && items && CFArrayGetCount(items)) { + CFIndex i, count; + count = CFArrayGetCount(items); + + for(i = 0; i < count; i++) { + CFTypeRef item = (CFTypeRef) CFArrayGetValueAtIndex(items, i); + CFTypeID itemID = CFGetTypeID(item); + + if(itemID == CFDictionaryGetTypeID()) { + CFTypeRef identity = (CFTypeRef) CFDictionaryGetValue( + (CFDictionaryRef) item, + kSecImportItemIdentity); + CFRetain(identity); + *out_cert_and_key = (SecIdentityRef) identity; + break; + } + else if(itemID == SecCertificateGetTypeID()) { + status = SecIdentityCreateWithCertificate(NULL, + (SecCertificateRef) item, + out_cert_and_key); + break; + } + } } if(items) CFRelease(items); - CFRelease(options); CFRelease(pkcs_data); } #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ -- cgit v1.2.1