funa68
funa68

Reputation: 959

When using Client Certificate Authentication, why do I keep getting NSURLErrorDomain Code=-1206?

The following code is me using code from previous posts about ios client certificate authentication. Every says this works, however why does it work for me?!?!

I keep getting the following error:

connection didFailWithError: Error Domain=NSURLErrorDomain Code=-1206 "The server “www.mywebsite.com” requires a client certificate.

I've followed at least 4 posts about this same topic on stackoverflow and 2 on other similar sites. They all say the same thing, except it isn't working.

I know my PKCS12 file works because i emailed it to my ipad, where i installed it on the ipad keychain and i'm able to access and authorize with the certificate identity using Safari. It is just when i'm trying to do it using a NSURLConnection in a 3rd party app, it refuses to allow me to do it.

Any suggestions are welcome, I feel like i've exhausted my options.


    // Download PKCS12 Cert from my FTP server.

    NSString *stringURL = @"ftp://user:password@myipaddress/myclientId.p12";        
    NSString* webStringURL = [stringURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL  *url = [NSURL URLWithString:webStringURL];
    NSData *p12Data = [NSData dataWithContentsOfURL:url];


    if ( p12Data )
    {   
        CFDataRef inP12data = (__bridge CFDataRef)p12Data;

        SecIdentityRef myIdentity;
        SecTrustRef myTrust;
        OSStatus errMsg = NULL;

        // This is the same function that has been reposted in all the other posts about ios client certification authentication.  So i'm not going to repost that.
        errMsg = extractIdentityAndTrust(inP12data, &myIdentity, &myTrust);

        SecCertificateRef myCertificate;
        SecIdentityCopyCertificate(myIdentity, &myCertificate);

        const void *certs[] = { myCertificate };

        CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL);

        NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistenceNone];

        [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];

Upvotes: 3

Views: 4180

Answers (2)

BrightLight
BrightLight

Reputation: 11

Chances are your .p12 contains intermediate certs AND your server required those intermediate certs.

You can verified with wireshark that you code will send in duplicated certificate of the identity but no intermediate certificate in the client certificate response.

If there is the case, you are to also extract the certificate from p12 and pass to create the NSURLCredentials:

int count = SecTrustGetCertificateCount(myTrust);
NSMutableArray* myCertificates = nil;
if (count > 1) {
    myCertificates = [NSMutableArray arrayWithCapacity:SecTrustGetCertificateCount(myTrust)];
    for (int i = 1; i < count; ++i) {  // remove the leaf cert
         [certs addObject:(id)SecTrustGetCertificateAtIndex(myTrust, i)];
    }
}
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:myCertificates persistence:NSURLCredentialPersistenceNone];

Also, passing nil to NSURLCredential should not break any code. see Apple's sample: https://developer.apple.com/library/ios/documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html. But passing empty array @[] to NSURLCredential will crash.

Upvotes: 1

funa68
funa68

Reputation: 959

Error was on this line. Second parameter needs to be set to "nil"

    NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistenceNone];

Changed to:

    NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:nil persistence:NSURLCredentialPersistenceNone];

Upvotes: 2

Related Questions