21

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...

Durai Amuthan.H
  • 31,670
  • 10
  • 160
  • 241
Kamil
  • 251
  • 1
  • 2
  • 7

3 Answers3

4

I use these steps:

  1. extract SecIdentityRef from the pkcs12 certificate file using SecPKCS12Import function
  2. use SecIdentityCopyCertificate function to get SecCertificateRef

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.

Kamil
  • 251
  • 1
  • 2
  • 7
1

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;
}
lukszar
  • 1,252
  • 10
  • 13
0

Of course the problem was with the iPhone simulator in xcode :) After updating to version 3.1 it started to work...

Kamil
  • 251
  • 1
  • 2
  • 7
  • 3
    Just a tip to make your questions more readable: dont post questions as new answers. It tends to make threads more difficult to read. Remember that your question will probably be useful to someone else and it's important for them to be able to see your process and the final answer. Thanks! – mtmurdock Apr 06 '11 at 19:36