MKSG-MugunthKumar / MKNetworkKit

Modern NSURLSession based Networking Framework with built in authentication and HTTP 1.1 caching standards support for iOS 8+ devices
http://mk.sg/8w
3.06k stars 755 forks source link

Validating private CA signed server certificate fails #412

Open zpfaltersack opened 10 years ago

zpfaltersack commented 10 years ago

I have sub-classed MKNetworkOperation in order to hijack the process whereby the server's TLS certificate is validated. The intention is to allow people to configure a server certificate from a private certificate authority. For testing purposes I have included my test server's public certificate as a resource. I overrode the delegate function "connection:willSendRequestForAuthenticationChallenge:" (basically copy/pasted from MKNetworkOperation and then pared down to address the 2 specific cases I want to support). The portion that addresses server authentication is as follows:

    NSData *iosTrustedCertDerData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"cert_name" ofType:@"cer"]];
    SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef) iosTrustedCertDerData);

    SecTrustRef trust = [[challenge protectionSpace] serverTrust];
    NSArray* trustArray = [NSArray arrayWithObjects:(__bridge id)(certificate), nil];
    SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef) trustArray);
    CFRelease(certificate);

    SecTrustResultType result;
    SecTrustEvaluate(trust, &result);

    if(result == kSecTrustResultProceed || result == kSecTrustResultUnspecified)
      //The cert is valid, but user has not explicitly accepted/denied. Ok to proceed (Ch 15: iOS PTL :Pg 269)
      [challenge.sender useCredential:[NSURLCredential credentialForTrust:trust] forAuthenticationChallenge:challenge];
    else {
      // invalid or revoked certificate
      if(self.shouldContinueWithInvalidCertificate)
        [challenge.sender useCredential:[NSURLCredential credentialForTrust:trust] forAuthenticationChallenge:challenge];
      else
        [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
    }

So, in the first case if I do NOT include the code to set custom trust anchors but I DO set the flag to continue with an invalid certificate, then I can get through fine.

If I DO include the code to set custom trust anchors, I get the expected kSecTrustResultUnspecified but the network framework rejects my connection nonetheless.

What I find odd is, the exact same call is made in these two cases but one fails and one does not. I'm honestly not sure this is a MKNetworkKit issue per se, but I'm hoping someone here has tried something similar and can point out what's wrong.

Another option I considered was saving the server certificate in the app keychain but that failed as well and I was making more headway with this solution.

I've only been in objective-c for a couple months so there is a distinct possibility I'm just using all of this stuff incorrectly :p

Thanks in advance for any help!