Determining Trust With NSURLConnection and NSURLProtectionSpace

放肆的年华 提交于 2019-11-28 07:37:21

So I spent a few days researching this. It looks like while the NSURLConnection API cannot determine if a certificate is trusted, there's a method in the Security Framework that handels that. So here's the code I came up with:

-(void)connection:(NSURLConnection *)connection
didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{   

    if ([challenge previousFailureCount] > 0) {
        [[challenge sender] cancelAuthenticationChallenge:challenge];
        NSLog(@"Bad Username Or Password");
        badUsernameAndPassword = YES;
        finished = YES;
        return;
    }

    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    {

        SecTrustResultType result;
        //This takes the serverTrust object and checkes it against your keychain
        SecTrustEvaluate(challenge.protectionSpace.serverTrust, &result);

        if (appDelegate._allowInvalidCert)
        {
            [challenge.sender useCredential:
             [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                 forAuthenticationChallenge: challenge];
        }
        //When testing this against a trusted server I got kSecTrustResultUnspecified every time. But the other two match the description of a trusted server
        else if(result == kSecTrustResultProceed || result == kSecTrustResultConfirm ||  result == kSecTrustResultUnspecified){
            [challenge.sender useCredential:
             [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                 forAuthenticationChallenge: challenge];
        }
        else
        {
            //Asks the user for trust
            TrustGenerator *tg = [[TrustGenerator alloc] init];

            if ([tg getTrust:challenge.protectionSpace])
            {

                //May need to add a method to add serverTrust to the keychain like Firefox's "Add Excpetion"
                [challenge.sender useCredential:
                 [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                     forAuthenticationChallenge: challenge];
            }
            else {
                [[challenge sender] cancelAuthenticationChallenge:challenge];
            }
        }
    }
    else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodDefault) {
        NSURLCredential *newCredential = [NSURLCredential credentialWithUser:_username password:_password persistence:NSURLCredentialPersistenceNone];
        [[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
    }
}

If the result is kSecTrustResultConfirm, you should actually ask the user if it's a trusted server.

The answer above just works if you have a CA trusted Certificate, because in this case your are using the apple allowed CA certificates for validating.

If you have self-signed certificates you should use your own CA server certificate for checking if it is valid...

I found an good (bit confusing) here. It covers too a dual handshake....

Hope it help some !

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!