Skip to content

Commit

Permalink
darwinssl: Don't import client certificates into Keychain on macOS
Browse files Browse the repository at this point in the history
Closes #2085
  • Loading branch information
Dair Grant authored and bagder committed Jan 25, 2018
1 parent 9a230ba commit f8475c6
Showing 1 changed file with 61 additions and 12 deletions.
73 changes: 61 additions & 12 deletions lib/vtls/darwinssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit f8475c6

Please sign in to comment.