I'm using NSULConnection to send data to a webservice over SSL. The server is signed with a wildcard certificate (*.mydomain.com). The certificate is using RES SHA256 and TLS 1.2 and is signed by a CA. I'm trying to send my data using the following code:
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] init];
[req setTimeoutInterval:60];
[req setHTTPMethod:@"POST"];
// ... Set content type and add data to body ... //
[req setURL:@"https://subdomain.mydomain.com/service/"];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSLog(@"Starting Upload");
NSURLSessionDataTask *task = [session dataTaskWithRequest:req
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
// .. Handle Completion .. //
}];
[task resume];
When I run the above code I get the following output.
CFNetwork SSLHandshake failed (-9801) NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9801)
So, I tried adding the exceptions explained in this post: CFNetwork SSLHandshake failed iOS 9
But had no luck in getting the error to resolve itself. I then switched to using http instead of https, while leaving in the configuration changes explained above and it did work. However, that is far from an ideal solution. The http is fine for testing, but this app will be handling data where SSL is required. How can I get the SSL working?
Edit
Here are the results of running nscurl --ats-diagnostics on the https version of my service url
================================================================================ Default ATS Secure Connection --- ATS Default Connection Result : PASS --- ================================================================================ Allowing Arbitrary Loads --- Allow All Loads Result : PASS --- ================================================================================ Configuring TLS exceptions for **** --- TLSv1.2 Result : PASS --- --- TLSv1.1 Result : PASS --- --- TLSv1.0 Result : PASS --- ================================================================================ Configuring PFS exceptions for **** --- Disabling Perfect Forward Secrecy Result : PASS --- ================================================================================ Configuring PFS exceptions and allowing insecure HTTP for **** --- Disabling Perfect Forward Secrecy and Allowing Insecure HTTP Result : PASS --- ================================================================================ Configuring TLS exceptions with PFS disabled for **** --- TLSv1.2 with PFS disabled Result : PASS --- --- TLSv1.1 with PFS disabled Result : PASS --- --- TLSv1.0 with PFS disabled Result : PASS --- ================================================================================ Configuring TLS exceptions with PFS disabled and insecure HTTP allowed for **** --- TLSv1.2 with PFS disabled and insecure HTTP allowed Result : PASS --- --- TLSv1.1 with PFS disabled and insecure HTTP allowed Result : PASS --- --- TLSv1.0 with PFS disabled and insecure HTTP allowed Result : PASS --- ================================================================================
Edit 2
Here are the exceptions I added:
<dict>
<key>mydomain.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>1.0</string>
<key>NSTemporaryExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
</dict>
Result of curl -v
* CAfile: /opt/local/share/curl/curl-ca-bundle.crt CApath: none * SSLv3, TLS handshake, Client hello (1): * SSLv3, TLS handshake, Server hello (2): * SSLv3, TLS handshake, CERT (11): * SSLv3, TLS handshake, Server key exchange (12): * SSLv3, TLS handshake, Server finished (14): * SSLv3, TLS handshake, Client key exchange (16): * SSLv3, TLS change cipher, Client hello (1): * SSLv3, TLS handshake, Finished (20): * SSLv3, TLS change cipher, Client hello (1): * SSLv3, TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-SHA384 * Server certificate: * subject: C=XXX; ST=XXX; L=XXX; O=XXX; CN=*.mydomain.com * start date: 2015-08-17 00:00:00 GMT * expire date: 2018-11-14 12:00:00 GMT * subjectAltName: subdomain.mydomain.com matched * issuer: C=US; O=DigiCert Inc; CN=DigiCert SHA2 Secure Server CA * SSL certificate verify ok.
Result of openssl s_client -connect
CONNECTED(00000003)
depth=1 C = US, O = DigiCert Inc, CN = DigiCert SHA2 Secure Server CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
0 s:/C=XXX/ST=XXX/L=XXX/O=XXX/CN=*.mydomain.com
i:/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
1 s:/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
.
.
.
-----END CERTIFICATE-----
subject=/C=XXX/ST=XXX/L=XXX/O=XXX/CN=*.mydomain.com
issuer=/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
---
No client certificate CA names sent
---
SSL handshake has read 3033 bytes and written 490 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-SHA384
Session-ID: XXX
Session-ID-ctx:
Master-Key: XXX
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1454971371
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)
---