I also don't have control over the server(s) my application will connect to. This server application generates self-signed certificates for the web API, and the vendor doesn't support using a certificate signed by a CA (even a private one). For now, I'm using code like this to hard-code a set of IPs my application trusts implicitly:
Code Block class cpmSessionDelegate:NSObject, URLSessionDelegate { let trustedHosts:[String] = ["10.20.30.40"] func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { switch challenge.protectionSpace.authenticationMethod { case NSURLAuthenticationMethodServerTrust: if trustedHosts.contains(challenge.protectionSpace.host) { let credential = URLCredential(trust:challenge.protectionSpace.serverTrust!) completionHandler(Foundation.URLSession.AuthChallengeDisposition.useCredential,credential) } default: challenge.sender!.continueWithoutCredential(for: challenge) } } }
This is clearly terrible. Is there a way to tell URLSession I want it to present untrusted certificates to the user and ask for a trust decision? I haven't run across anything like that, but I might be missing it.
If I can't get the system to handle the certificate display and trust prompt, I know I can add certificates to the keychain and set trust properties myself. Is there a standard control to use to show the certificate to the user for verification? Or do I need to use SecCertificateCopyValues and build my own UI in an NSAlert or something?
There is no API to display the contents of a certificate to a user, this could be something that you build yourself once the contents of the certificate is parsed. Keep in mind though that this delegate is operating during a time sensitive context. If the user takes too long to make a decision the request does run the risk of timing out.Is there a way to tell URLSession I want it to present untrusted certificates to the user and ask for a trust decision?
To further interrogate the certificate you could dig into the SecTrust provided by the challenge protection space. A rough example of this could include creating a SSL SecPolicy and setting it on SecTrust to evaluate the SSL certificate chain with SecTrustEvaluateWithError. Based on the result of this you could further dig into this result and the properties of the certificate to make a trust decision.
Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com