SecTrustSetPolicies not work when ATS enabled

I'm using a self-signed certificate. But my host domain maybe different from the certificate or may be IP adresses.

But I find that the code is not working when ATS is turned on.

The weird thing is the domain verification will fail but the pure IP address will be ok.

  // Get remote certificate
  SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
  SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
  
  // Set SSL policies for domain name check
  NSMutableArray *policies = [NSMutableArray array];
  NSString *trustDomain = [NSString stringWithFormat:@"%@:%d",
                           challenge.protectionSpace.host,
                           challenge.protectionSpace.port];
  [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)trustDomain)];
  SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);

The error info is

{

NSErrorClientCertificateStateKey = 0;

....

NSLocalizedDescription = "An SSL error has occurred and a secure connection to the server cannot be made.";

NSLocalizedRecoverySuggestion = "Would you like to connect to the server anyway?";

NSURLErrorFailingURLPeerTrustErrorKey = "<SecTrustRef: 0x14fd8a90>";

NSUnderlyingError = "Error Domain=kCFErrorDomainCFNetwork Code=-1200 \"(null)\" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorCodeKey=-9802, _kCFStreamErrorDomainKey=3, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x14fd8a90>, kCFStreamPropertySSLPeerCertificates=(....)}";

"_kCFStreamErrorCodeKey" = "-9802";

"_kCFStreamErrorDomainKey" = 3;

}

Replies

I'm using a self-signed certificate … But I find that the code is not working when ATS is turned on.

The general rule for ATS is that apps are not able to lower security beyond that specified in their ATS dictionary (the

NSAppTransportSecurity
dictionary in the
Info.plist
). So if “ATS is turned on” means what I think it means (you are building with a modern SDK, which enables ATS, and you don’t have an ATS dictionary that specifically disables ATS for your domain), this is working as expected: ATS is preventing you from lowering security beyond what’s specified in your ATS dictionary, which is exactly what it’s supposed to be doing.

To make this work you’ll need to add an ATS exception that covers your server. If there are no constraints on the DNS name of your server, you’ll need to use

NSAllowsArbitraryLoads
.

The weird thing is the domain verification will fail but the pure IP address will be ok.

Right. ATS is always disabled for IP address URLs.

IMPORTANT This is new in iOS 10. In iOS 9 ATS is always enabled for IP address URLs and there’s no way (other than the heavy hammer than is

NSAllowsArbitraryLoads
) to disable it.

Coming back to the big picture, why are you using a self-signed certificate? Folks do this for lots of different reasons, but in most cases there’s a better approach. If you can explain more about your high-level problem, I should be able to suggest an alternative.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"