5

I am using iOS 10. I am evaluating a self signed certificate as below

-(void) connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];

    if ([protectionSpace authenticationMethod] == NSURLAuthenticationMethodServerTrust) {

        SecTrustRef trust = [protectionSpace serverTrust];

        SecPolicyRef policyOverride = SecPolicyCreateSSL(true, (CFStringRef)@"HOSTNAME");
        SecTrustSetPolicies(trust, policyOverride);

        CFMutableArrayRef certificates = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);

        /* Copy the certificates from the original trust object */
        CFIndex count = SecTrustGetCertificateCount(trust);
        CFIndex i=0;
        for (i = 0; i < count; i++) {
            SecCertificateRef item = SecTrustGetCertificateAtIndex(trust, i);
            CFArrayAppendValue(certificates, item);
        }

        /* Create a new trust object */
        SecTrustRef newtrust = NULL;
        if (SecTrustCreateWithCertificates(certificates, policyOverride, &newtrust) != errSecSuccess) {
            /* Probably a good spot to log something. */
            NSLog(@"Error in SecTrustCreateWithCertificates");
            [connection cancel];
            return;
        }

        CFRelease(policyOverride);

        /* Re-evaluate the trust policy. */
        SecTrustResultType secresult = kSecTrustResultInvalid;
        if (SecTrustEvaluate(trust, &secresult) != errSecSuccess) {

            /* Trust evaluation failed. */
            [connection cancel];

            // Perform other cleanup here, as needed.
            return;
        }

        switch (secresult) {
                //case kSecTrustResultInvalid:
                //case kSecTrustResultRecoverableTrustFailure:
            case kSecTrustResultUnspecified: // The OS trusts this certificate implicitly.
            case kSecTrustResultProceed: // The user explicitly told the OS to trust it.
            {
                NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
                [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];

                return;
            }
            default: ;
                /* It's somebody else's key. Fall through. */
                [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
                break;
        }
        /* The server sent a key other than the trusted key. */
        [connection cancel];
        // Perform other cleanup here, as needed.
    }
}

The result after evaluating is 'kSecTrustResultUnspecified' and again the same method 'willSendRequestForAuthenticationChallenge' is being called recursively. Not sure why the method is being called recursively. Let me know any issue with the code.

Thanks

jww
  • 97,681
  • 90
  • 411
  • 885
user2071152
  • 1,161
  • 1
  • 11
  • 25

2 Answers2

2

There are a couple of solutions to this, and I think the simplest one is found here. In summary, you need to check [challenge previousFailureCount] to prevent reentering the method over and over.

Otherwise, from the Apple API documentation, I would suggest something similar to this, which uses a deprecated delegate callback, but could possibly function for you.

Community
  • 1
  • 1
BHendricks
  • 4,423
  • 6
  • 32
  • 59
  • In method 'willSendRequestForAuthenticationChallenge' if ([challenge previousFailureCount]) { [[challenge sender] cancelAuthenticationChallenge:challenge]; } execution does not enter here in if condition. – user2071152 Oct 13 '16 at 14:28
  • so the `previousFailureCount` is 0, then? – BHendricks Oct 13 '16 at 15:49
  • Unable to print the value as its not falling under if condition i assume it should be 0 then. – user2071152 Oct 13 '16 at 19:11
0

It is actually meant to be called recursively. Your code should handle this.

Seems weird at first, but it kind of makes sense... tries to authenticate, fails, so it comes back to the same method (who knows, maybe you want to try a different credential or something).

You can check the previous failure count and reject it yourself, otherwise it will fail and keep returning to your function to authenticate recursively, as is currently happening.

Jordan Smith
  • 10,310
  • 7
  • 68
  • 114