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) ---
curl -v insert_url_here
andopenssl s_client -connect insert_domain_here:443
? – jcaron