I have developed an IOS App that is communicating with a Server using HTTPs (I'm also the developer of the server, it's embedding a Tomcat server).
This App is working without any issues with IOS8 but it's not with IOS9.
I get the following error when sending an HTTPs request:
Session download has failed : Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo=0x7fa9c44b2e40 {NSErrorFailingURLStringKey=https://127.0.0.1:8443/MyServer/MyApp, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, NSErrorFailingURLKey=https://127.0.0.1:8443/MyServer/MyApp, _kCFStreamErrorCodeKey=-9802, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made.}
Based on Apple documentation when the error Code=-1200 happens it's because TLSv1.1 instead of TLSv1.2. I have verified with an openSSL command and my server is using TLSv1.2.
When setting in the info.plist the property NSAllowsArbitraryLoads = true, the error disappear but I don't want to keep it like this.
My server is using a self signed certificate, maybe it's the cause of the issue? Below is the code I'm using for didReceiveChallenge
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
[RequestURLUtilities dumpChallenge:challenge];
if (challenge.protectionSpace != Nil) {
NSURLProtectionSpace *protection = challenge.protectionSpace;
SecTrustRef sslState = protection.serverTrust;
if (sslState == Nil) {
NSLog(@"%s Warning: empty serverTrust",__PRETTY_FUNCTION__);
}
if ([protection.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
NSLog(@"%s => NSURLAuthenticationMethodServerTrust", __PRETTY_FUNCTION__);
// warning normaly I should check the validity of the SecTrustRef before to trust
NSURLCredential* credential = [NSURLCredential credentialForTrust:sslState];
// Put in command for test
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
} else {
NSLog(@"%s => Called for another challenge", __PRETTY_FUNCTION__);
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, NULL);
}
}
Should I create my own CA and then my own certificates? How to proceed? What is missing? Any help will be greatly appreciated.
Sebastien.