diff options
author | Mikkel Krautz <mikkel@krautz.dk> | 2013-09-17 05:30:00 +0400 |
---|---|---|
committer | Mikkel Krautz <mikkel@krautz.dk> | 2013-09-17 05:30:00 +0400 |
commit | 53ab89ff153b5c5efe09c011042a10fbdea6b99f (patch) | |
tree | 366587c16491c686958abf1e2395a1d6e9015904 /Source | |
parent | 90ebcd64d34907f06ca67c711eb4fd344e9cb03c (diff) |
MUCertificateDiskImportViewController: use MKCertificate (OpenSSL) for most of the heavy lifting when importing. Fixes StartSSL client cert chain import.
We now use the new certificatesWithPKCS12:password: method on MKCertificate
to convert a PKCS12 blob into an array of MKCertificates, instead of depending on SecPKCS12Import
for the whole import process.
For the leaf, we export it and its private key as a separate PKCS12 blob and *only* use
SecPKCS12Import on that, yielding us a SecIdentityRef we can import into the app's keychain.
For the non-leaf certificates, we simply iterate through them, convert them to SecCertificateRefs
and import them into the keychain.
Fixes #71.
Diffstat (limited to 'Source')
-rw-r--r-- | Source/Classes/MUCertificateDiskImportViewController.m | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/Source/Classes/MUCertificateDiskImportViewController.m b/Source/Classes/MUCertificateDiskImportViewController.m index 6555985..a9ec146 100644 --- a/Source/Classes/MUCertificateDiskImportViewController.m +++ b/Source/Classes/MUCertificateDiskImportViewController.m @@ -162,14 +162,15 @@ static void ShowAlertDialog(NSString *title, NSString *msg) { NSString *pkcs12File = [[documentDirs objectAtIndex:0] stringByAppendingFormat:@"/%@", fileName]; NSData *pkcs12Data = [NSData dataWithContentsOfFile:pkcs12File]; - MKCertificate *tmpCert = [MKCertificate certificateWithPKCS12:pkcs12Data password:password]; - if (tmpCert == nil) { + NSArray *chain = [MKCertificate certificatesWithPKCS12:pkcs12Data password:password]; + if ([chain count] == 0) { [self showPasswordDialog]; [[self tableView] deselectRowAtIndexPath:_attemptIndexPath animated:YES]; return; } - NSData *transformedPkcs12Data = [tmpCert exportPKCS12WithPassword:@""]; + MKCertificate *leaf = [chain objectAtIndex:0]; + NSData *transformedPkcs12Data = [leaf exportPKCS12WithPassword:@""]; if (transformedPkcs12Data == nil) { ShowAlertDialog(NSLocalizedString(@"Import Error", nil), NSLocalizedString(@"Mumble was unable to export the specified certificate.", @@ -182,13 +183,19 @@ static void ShowAlertDialog(NSString *title, NSString *msg) { NSArray *items = nil; OSStatus err = SecPKCS12Import((CFDataRef)transformedPkcs12Data, (CFDictionaryRef)dict, (CFArrayRef *)&items); - if (err == errSecSuccess && [items count] > 0) { + if (err == errSecSuccess && [items count] > 0) { // Add all elements except the leaf certificate to the keychain - NSDictionary *pkcsDict = [items objectAtIndex:0]; - NSArray *chain = [pkcsDict objectForKey:(NSString *)kSecImportItemCertChain]; for (int i = 1; i < [chain count]; i++) { + MKCertificate *cert = [chain objectAtIndex:i]; + SecCertificateRef secCert = SecCertificateCreateWithData(NULL, (CFDataRef)[cert certificate]); + if (secCert == NULL) { + ShowAlertDialog(NSLocalizedString(@"Import Error", nil), + NSLocalizedString(@"Mumble was unable to import one of the intermediate certificates in the certificate chain.", nil)); + continue; + } + NSDictionary *op = [NSDictionary dictionaryWithObjectsAndKeys: - [chain objectAtIndex:i], kSecValueRef, nil]; + (id)secCert, kSecValueRef, nil]; err = SecItemAdd((CFDictionaryRef)op, NULL); if (err != noErr) { if (err == errSecDuplicateItem) { @@ -198,9 +205,12 @@ static void ShowAlertDialog(NSString *title, NSString *msg) { NSLocalizedString(@"Mumble was unable to import one of the intermediate certificates in the certificate chain.", nil)); } } + + CFRelease(secCert); } // Get the SecIdentityRef, and add it to the keychain + NSDictionary *pkcsDict = [items objectAtIndex:0]; SecIdentityRef identity = (SecIdentityRef)[pkcsDict objectForKey:(id)kSecImportItemIdentity]; NSDictionary *op = [NSDictionary dictionaryWithObjectsAndKeys: (id)identity, kSecValueRef, |