How can I accept self-signed whitelisted server certificates in iOS?

I am trying to accept self-signed certificates in NSURLConnection, as many of them are in front of me. The trick is that I only want to accept certificates from the white list of certificates that I trust. I would agree to find out how to accept one certificate. Here is the code I got so far in my NSURLConnectionDelegate:

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { NSString *thePath = [[NSBundle mainBundle] pathForResource:@"trusted" ofType:@"der"]; NSData *certData = [[NSData alloc] initWithContentsOfFile:thePath]; CFDataRef myCertData = (__bridge_retained CFDataRef)certData; SecCertificateRef myCert = SecCertificateCreateWithData(NULL, myCertData); SecPolicyRef myPolicy = SecPolicyCreateBasicX509(); SecCertificateRef certArray[1] = { myCert }; CFArrayRef myCerts = CFArrayCreate(NULL, (void *)certArray, 1, NULL); SecTrustRef myTrust; OSStatus status = SecTrustCreateWithCertificates(myCerts, myPolicy, &myTrust); SecTrustResultType trustResult; if (status == noErr) { status = SecTrustEvaluate(myTrust, &trustResult); } BOOL trusted = NO; if (trustResult == kSecTrustResultUnspecified) { // I never get here. Instead, trustResult is always kSecTrustResultRecoverableTrustFailure trusted = YES; } if (trusted) { [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; } else { [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge]; } CFRelease(myTrust); CFRelease(myCerts); CFRelease(myPolicy); CFRelease(myCert); CFRelease(myCertData); } else { [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge]; } } 

As you can see in the commentary, I never get kSecTrustResultUnspecified, which I expect to receive. I have confirmed that my certificate is correct, and in the correct format (DER).

+6
source share
1 answer

Ok, got it. Turns out you just need to check the trust of the server and actually use the certificate data.

 - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { BOOL trusted = NO; if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { NSString *thePath = [[NSBundle mainBundle] pathForResource:@"trusted" ofType:@"der"]; NSData *certData = [[NSData alloc] initWithContentsOfFile:thePath]; CFDataRef certDataRef = (__bridge_retained CFDataRef)certData; SecCertificateRef cert = SecCertificateCreateWithData(NULL, certDataRef); SecPolicyRef policyRef = SecPolicyCreateBasicX509(); SecCertificateRef certArray[1] = { cert }; CFArrayRef certArrayRef = CFArrayCreate(NULL, (void *)certArray, 1, NULL); SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; SecTrustSetAnchorCertificates(serverTrust, certArrayRef); SecTrustResultType trustResult; SecTrustEvaluate(serverTrust, &trustResult); trusted = (trustResult == kSecTrustResultUnspecified); CFRelease(certArrayRef); CFRelease(policyRef); CFRelease(cert); CFRelease(certDataRef); } if (trusted) { [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; } else { [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge]; } } 
+14
source

Source: https://habr.com/ru/post/916493/


All Articles