Reputation: 251
I'm fighting with a client certificate authentication. When a server needs a credential (a certificate in this case), this method is invoked from NSURLConnection delegate:
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
I want to load a certificate from a file, fill a credential and run this method:
[[challenge sender] useCredential:[self credential] forAuthenticationChallenge:challenge];
But I don't know how to initialize (or fill) a SecIdentityRef parameter. Here is my code that creates the credentials:
NSString *certPath = [[NSBundle mainBundle] pathForResource:@"certificate" ofType:@"cer"];
NSData *certData = [[NSData alloc] initWithContentsOfFile:certPath];
SecIdentityRef myIdentity; // ???
SecCertificateRef myCert = SecCertificateCreateWithData(NULL, (CFDataRef)certData);
[certData release];
SecCertificateRef certArray[1] = { myCert };
CFArrayRef myCerts = CFArrayCreate(NULL, (void *)certArray, 1, NULL);
CFRelease(myCert);
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity
certificates:(NSArray *)myCerts
persistence:NSURLCredentialPersistencePermanent];
CFRelease(myCerts);
Does anybody know how to solve it? Thanks.
I've finally found the solution, but a new problem is here:
my client doesn't send the certificate to the server. After the server asks for the certificate, the application runs this method:
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
and I fill the credential (like I mentioned above), but the connection ends with an error: NSURLErrorDomain -1206. According to the server logs the client certificate is not sent by the application.
Has anybody any experience with this behaviour? Do I need to somehow verify the certificate in the application? Or anything else to make it work? I can provide my current code if it helps. Thanks for any ideas...
Upvotes: 21
Views: 14790
Reputation: 1422
You can also search for identity in keychain if you store this information there:
+ (SecIdentityRef)dumpSecIdentityRef
{
OSStatus err;
CFArrayRef result;
CFIndex resultCount;
CFIndex resultIndex;
result = NULL;
err = SecItemCopyMatching((__bridge CFDictionaryRef) [NSDictionary dictionaryWithObjectsAndKeys:
(__bridge id)kSecClassIdentity,
kSecClass, kSecMatchLimitAll,
kSecMatchLimit, kCFBooleanTrue,
kSecReturnRef, kCFBooleanTrue,
kSecReturnAttributes, nil],
(CFTypeRef *) &result);
if ((result != NULL) && (err == noErr)) {
NSMutableArray *identitiesArray = [NSMutableArray new];
resultCount = CFArrayGetCount(result);
for (resultIndex = 0; resultIndex < resultCount; resultIndex++) {
NSDictionary * thisResult;
thisResult = (__bridge NSDictionary *) CFArrayGetValueAtIndex(result, resultIndex);
NSLog(@"%@", (__bridge id)(result));
[identitiesArray addObject:thisResult];
}
CFRelease(result);
//TO DO - choose correct identity object from array.
SecIdentityRef myIdentity = (__bridge SecIdentityRef)([[identitiesArray objectAtIndex:0] valueForKey:@"v_Ref"]);
return myIdentity;
}
return nil;
}
Upvotes: 1
Reputation: 251
I use these steps:
and the rest (a credential initialization) is the same as in my question... I can put here more code if you want. Note that there is a bug (http://openradar.appspot.com/7090030) in the iphone simulator, so it is not possible to work with a lot of certifcates in the simulator.
Upvotes: 4
Reputation: 251
Of course the problem was with the iPhone simulator in xcode :) After updating to version 3.1 it started to work...
Upvotes: 0