Tworzenie SecCertificateRef dla NSURLConnection Authentication Challenge
Otrzymuję wyzwanie uwierzytelnienia z serwera, z którym próbuje połączyć się moja aplikacja, więc zaimplementowałemconnection:didReceiveAuthenticationChallenge:
metoda. Muszę wysłaćSecCertificateRef
i aSecIdentityRef
. Tożsamość działa, ale certyfikat należy wysłać jakoNSArray
i nie mogę wymyślić, jak przekonwertowaćCFArrayRef
do aNSArray
.
To jest moja metoda tworzenia tożsamości i certyfikatu:
<code>// Returns an array containing the certificate - (CFArrayRef)getCertificate { SecCertificateRef certificate = nil; NSString *thePath = [[NSBundle mainBundle] pathForResource:@"CertificateName" ofType:@"p12"]; NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath]; CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data; certificate = SecCertificateCreateWithData(nil, inPKCS12Data); SecCertificateRef certs[1] = { certificate }; CFArrayRef array = CFArrayCreate(NULL, (const void **) certs, 1, NULL); SecPolicyRef myPolicy = SecPolicyCreateBasicX509(); SecTrustRef myTrust; OSStatus status = SecTrustCreateWithCertificates(array, myPolicy, &myTrust); if (status == noErr) { NSLog(@"No Err creating certificate"); } else { NSLog(@"Possible Err Creating certificate"); } return array; } // Returns the identity - (SecIdentityRef)getClientCertificate { SecIdentityRef identityApp = nil; NSString *thePath = [[NSBundle mainBundle] pathForResource:@"CertificateName" ofType:@"p12"]; NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath]; CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data; CFStringRef password = CFSTR("password"); const void *keys[] = { kSecImportExportPassphrase };//kSecImportExportPassphrase }; const void *values[] = { password }; CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items); CFRelease(options); CFRelease(password); if (securityError == errSecSuccess) { NSLog(@"Success opening p12 certificate. Items: %ld", CFArrayGetCount(items)); CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0); identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity); } else { NSLog(@"Error opening Certificate."); } return identityApp; } </code>
A potem wconnection:didReceiveAuthenticationChallenge:
mam:
<code>- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { if ([challenge previousFailureCount] == 0) { SecIdentityRef identity = [self getClientCertificate]; // Go get a SecIdentityRef CFArrayRef certs = [self getCertificate]; // Get an array of certificates // Convert the CFArrayRef to a NSArray NSArray *myArray = (__bridge NSArray *)certs; // Create the NSURLCredential NSURLCredential *newCredential = [NSURLCredential credentialWithIdentity:identity certificates:certs persistence:NSURLCredentialPersistenceNone]; // Send [challenge.sender useCredential:newCredential forAuthenticationChallenge:challenge]; } else { // Failed [[challenge sender] cancelAuthenticationChallenge:challenge]; } } </code>
Aplikacja ulega awarii, gdyNSURLCredential
jest tworzone. Po dalszej kontroli doszedłem do wniosku, że kiedy nawracamCFArrayRef
do aNSArray
, dane zSecCertificateRef
jest tracone, a tablica zawiera wartość null powodującą awarię.
Jak mogę umieścićSecCertificateRef
wNSArray
? Czy tęskniłem za krokiem, czy po prostu robię to źle?