I'm trying to connect my app to a development server that has a server certificate with the wrong hostname, but it is signed by a trusted anchor certificate. When I evaluate the server trust object, it fails as expected. I am trying to change the trust evaluation policy for the server's hostname, but it doesn't seem to help.
// In -connection:willSendRequestForAuthenticationChallenge:
// NSURLAuthenticationMethodServerTrust
SecTrustRef trust = [challenge.protectionSpace serverTrust];
SecTrustResultType trustResult;
SecTrustEvaluate(trust, &trustResult);
// trustResult == kSecTrustResultRecoverableTrustFailure
SecPolicyRef policyOverride = SecPolicyCreateSSL(true, (CFStringRef)@"devhost");
CFArrayRef policies = (CFArrayRef)@[policyOverride];
SecTrustSetPolicies(trust, policies);
CFRelease(policyOverride);
SecTrustEvaluate(trust, &trustResult);
// trustResult == kSecTrustResultRecoverableTrustFailure
As far as I understand, the second time I call SecTrustEvaluate(), it should be returning kSecTrustResultUnspecified
. I have connected to the dev server using "devhost" when I initialized the NSURLConnection, and challenge.protectionSpace.host == @"devhost"
as well. What am I doing wrong here?
I was using the wrong host name in the call to SecPolicyCreateSSL
.
When using SecPolicyCreateSSL
to override hostname validation, the hostname argument should be one that matches the certificate you're validating. Then the validation pretends that the host you're communicating with has the newly specified hostname.
In my case, the server has a certificate for "*.mydomain.tld", so I call
SecPolicyCreateSSL(true, (CFStringRef)@"devhost.mydomain.tld");
and then the certificate chain can be successfully validated.