207

has anyone with the iOS 9 beta 1 had this issue?

I use standard NSURLConnection to connect to a webservice and as soon as a call is made to the webservice i get the below error. This is currently working in iOS 8.3

Possible beta bug? any ideas or thoughts would be great ! I know its very early in iOS 9 development

Here is the full error:

CFNetwork SSLHandshake failed (-9824) NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)

 NSURLRequest * urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://mywebserviceurl"]];
        NSURLResponse * response = nil;
        NSError * error = nil;
        NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest
                                                  returningResponse:&response
                                                              error:&error];
Nitin Gohel
  • 49,482
  • 17
  • 105
  • 144
user3099837
  • 3,931
  • 5
  • 15
  • 13

11 Answers11

310

iOS 9 and OSX 10.11 require TLSv1.2 SSL for all hosts you plan to request data from unless you specify exception domains in your app's Info.plist file.

The syntax for the Info.plist configuration looks like this:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>yourserver.com</key>
    <dict>
      <!--Include to allow subdomains-->
      <key>NSIncludesSubdomains</key>
      <true/>
      <!--Include to allow insecure HTTP requests-->
      <key>NSExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <!--Include to specify minimum TLS version-->
      <key>NSExceptionMinimumTLSVersion</key>
      <string>TLSv1.1</string>
    </dict>
  </dict>
</dict>

If your application (a third-party web browser, for instance) needs to connect to arbitrary hosts, you can configure it like this:

<key>NSAppTransportSecurity</key>
<dict>
    <!--Connect to anything (this is probably BAD)-->
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

If you're having to do this, it's probably best to update your servers to use TLSv1.2 and SSL, if they're not already doing so. This should be considered a temporary workaround.

As of today, the prerelease documentation makes no mention of any of these configuration options in any specific way. Once it does, I'll update the answer to link to the relevant documentation.

yo.ian.g
  • 1,354
  • 2
  • 14
  • 21
Steven Peterson
  • 3,138
  • 1
  • 15
  • 9
  • Thank you so much for this response, hopefully the documentation will mention what the key will be to make the domain exceptions. Thanks again, your answer is very clear and i know many others are seeing the same thing under the ios9 beta forums – user3099837 Jun 09 '15 at 00:04
  • can you post the link of documentation? – yuhua Jun 09 '15 at 00:41
  • i think its so new they havent update their docs yet, when they do he said he would update answer. – user3099837 Jun 09 '15 at 00:45
  • 1
    App Transport Security (ATS) lets an app add a declaration to its Info.plist file that specifies the domains with which it needs secure communication. ATS prevents accidental disclosure, provides secure default behavior, and is easy to adopt. You should adopt ATS as soon as possible, regardless of whether you’re creating a new app or updating an existing one. If you’re developing a new app, you should use HTTPS exclusively. If you have an existing app, you should use HTTPS as much as you can right now, and create a plan for migrating the rest of your app as soon as possible. – user3099837 Jun 09 '15 at 01:03
  • The above may be what @StevenPeterson was talking about ! Its just not very detailed yet. aka what the keys are etc – user3099837 Jun 09 '15 at 01:06
  • 1
    At the moment, this paragraph can be found here: https://developer.apple.com/library/prerelease/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS9.html#//apple_ref/doc/uid/TP40016198-DontLinkElementID_13 – Steven Peterson Jun 09 '15 at 01:41
  • @StevenPeterson your exactly right steven that works perfectly! i agree with you it would be better to either A) use TSL 1.2 or B) add a whitelist domains, hopefully they share those keys so we can add them too. Just out of curiosity how did you come up with that, did you get some documentation at wwdc ? Thanks again – user3099837 Jun 09 '15 at 04:10
  • 1
    @user3099837 Believe it or not, I actually used a raw text search app called EasyFind, and looked for the phrase "AppTransport", and I found a plist in the Xcode 7 bundle that has these keys. I found some other keys as well (NSExceptionDomains, NSTemporaryExceptionAllowsInsecureHTTPLoads, for example) but couldn't get them to work. I imagine we'll know the right way to format these entries in the coming days. – Steven Peterson Jun 09 '15 at 06:07
  • Updated to include more information about domain-specific exceptions. – Steven Peterson Jun 10 '15 at 18:30
  • 2
    @StevenPeterson hey steve i cant seem to get the exceptions domain example to work , do you have any ideas by chance, i just copied and pasted into .plist changed TLSv1.1 to TLSv1.0 and the domain to our domain without the https:// etc – user3099837 Jun 10 '15 at 19:05
  • 27
    Sorry for the long chat but i figured it out i needed to disable NSTemporaryExceptionRequiresForwardSecrecy – user3099837 Jun 10 '15 at 20:13
  • Your answer works for me and when i checked the TLS Version for my server at SSLLabs it shows TLS 1.2 and SSL 3 – lost found Jun 11 '15 at 15:13
  • I am not sure if the requests are being blocked because SSL 3 is insecure – lost found Jun 11 '15 at 15:22
  • What's the key "NSTemporaryExceptionMinimumTLSVersion" used for? – Rashmi Ranjan mallick Jun 15 '15 at 10:05
  • 2
    @RashmiRanjanmallick NSTemporaryExceptionMinimumTLSVersion is used to tell ATS that you're working with a non 1.2 server. For example, use this if you are trying to connect to a host which uses TLS 1.0. You must also use NSTemporaryExceptionRequiresForwardSecrecy set to false, as user3099837 indicated above. – Womble Jun 17 '15 at 03:49
  • Ok!! Actually our server supports SSLv3.0 (Insecure), TLSv1.0 and TLSv1.2. It doesn't support TLS1.1. I got this information from sslabs.com. I tried to add an exception for my server url using your answer. But, it fails everytime. Can you please help me in this case. Note: my server url format can be like https://m.myurl.com or https://m.anotherstring.myurl.com. It's not a random url. Basically I connect to two servers with above formats. – Rashmi Ranjan mallick Jun 17 '15 at 07:33
  • Bingo. I knew it had to do with ipv6 but didn't know where to modify. Thank you – VaporwareWolf Jun 24 '15 at 17:26
  • 2
    http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/ - This is the blog where the answer is sourced from. – Sean Dev Jul 28 '15 at 14:00
  • For those that have Facebook integrated in their app and receive this since Xcode beta 5, check this link: https://developers.facebook.com/docs/ios/ios9 for their exceptions. Also look at the changelogs, as I write this, v4.6.0 is in beta that states `The SDK is Xcode 7 and iOS 9 beta 5 compatible.` Just wait till it is released I should say..: https://developers.facebook.com/docs/ios/change-log-4.x/ – CularBytes Aug 19 '15 at 21:07
  • 1
    The technical note from Apple has been updated a few days ago: https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/ In particular, the key names were changed in the latest beta. – julien_c Aug 27 '15 at 16:10
  • My app is currently in iOS8 SDK and the ipa which I am having has been tested in iOS9 beta 5 and it works and I am still using XCode 6.4 (I have a combination of http as well as https). Just wanted to know whether am I safe till they make XCode7 and iOS9 SDK mandatory? – anoop4real Sep 08 '15 at 08:14
  • what if my server uses TLS 1.2?? why am I getting the error?? – Frade Oct 15 '15 at 10:16
  • @Frade did you work this out? I'm having the same issue. – Sam Heather Mar 23 '16 at 19:37
  • 1
    @SamHeather, I think it was the server's certificate that was expired. but I really don't remember for sure – Frade Mar 29 '16 at 16:42
66

In iOS 10+, the TLS string MUST be of the form "TLSv1.0". It can't just be "1.0". (Sigh)


The following combination of the other Answers works.

Let's say you are trying to connect to a host (YOUR_HOST.COM) that only has TLS 1.0.

Add these to your app's Info.plist

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>YOUR_HOST.COM</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.0</string>
            <key>NSTemporaryExceptionRequiresForwardSecrecy</key>
            <false/>
        </dict>
    </dict>
</dict>
Womble
  • 4,607
  • 2
  • 31
  • 45
  • 9
    Seems that adding `NSTemporaryExceptionRequiresForwardSecrecy` did the trick for me, thanks! – Josh Valdivieso Oct 15 '15 at 20:04
  • 2
    This version didn't work for me on iOS9.1 - I needed to use the TLSVersion string format in one of the other answers NSTemporaryExceptionMinimumTLSVersion TLSv1.1 – 300baud Nov 02 '15 at 11:05
  • This works but my question is: does that mean my app doesn't use ssl when these parameters are on and data isn't encrypted? – theDC May 14 '16 at 16:45
33

For more info Configuring App Transport Security Exceptions in iOS 9 and OSX 10.11

Curiously, you’ll notice that the connection attempts to change the http protocol to https to protect against mistakes in your code where you may have accidentally misconfigured the URL. In some cases, this might actually work, but it’s also confusing.

This Shipping an App With App Transport Security covers some good debugging tips

ATS Failure

Most ATS failures will present as CFErrors with a code in the -9800 series. These are defined in the Security/SecureTransport.h header

2015-08-23 06:34:42.700 SelfSignedServerATSTest[3792:683731] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)

CFNETWORK_DIAGNOSTICS

Set the environment variable CFNETWORK_DIAGNOSTICS to 1 in order to get more information on the console about the failure

nscurl

The tool will run through several different combinations of ATS exceptions, trying a secure connection to the given host under each ATS configuration and reporting the result.

nscurl --ats-diagnostics https://example.com
onmyway133
  • 45,645
  • 31
  • 257
  • 263
2

If your backend uses a secure connection ant you get using NSURLSession

CFNetwork SSLHandshake failed (-9801)
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9801)

you need to check your server configuration especially to get ATS version and SSL certificate Info:

Instead of just Allowing Insecure Connection by setting NSExceptionAllowsInsecureHTTPLoads = YES , instead you need to Allow Lowered Security in case your server do not meet the min requirement (v1.2) for ATS (or better to fix server side).

Allowing Lowered Security to a Single Server

<key>NSExceptionDomains</key>
<dict>
    <key>api.yourDomaine.com</key>
    <dict>
        <key>NSExceptionMinimumTLSVersion</key>
        <string>TLSv1.0</string>
        <key>NSExceptionRequiresForwardSecrecy</key>
        <false/>
    </dict>
</dict>

use openssl client to investigate certificate and get your server configuration using openssl client :

openssl s_client  -connect api.yourDomaine.com:port //(you may need to specify port or  to try with https://... or www.)

..find at the end

SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES256-SHA
    Session-ID: //
    Session-ID-ctx: 
    Master-Key: //
    Key-Arg   : None
    Start Time: 1449693038
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)

App Transport Security (ATS) require Transport Layer Security (TLS) protocol version 1.2.

Requirements for Connecting Using ATS:

The requirements for a web service connection to use App Transport Security (ATS) involve the server, connection ciphers, and certificates, as follows:

Certificates must be signed with one of the following types of keys:

  • Secure Hash Algorithm 2 (SHA-2) key with a digest length of at least 256 (that is, SHA-256 or greater)

  • Elliptic-Curve Cryptography (ECC) key with a size of at least 256 bits

  • Rivest-Shamir-Adleman (RSA) key with a length of at least 2048 bits An invalid certificate results in a hard failure and no connection.

The following connection ciphers support forward secrecy (FS) and work with ATS:

TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

Update: it turns out that openssl only provide the minimal protocol version Protocol : TLSv1 links

Community
  • 1
  • 1
Idali
  • 1,023
  • 7
  • 10
  • the question remains is is it possible to interpretate openssl info to find out if the server meets requirement. Also Protocol : TLSv1 may be the makor version instead of 1.x – Idali Dec 10 '15 at 00:04
  • I make it general, in case using port – Idali Dec 10 '15 at 00:09
  • The answer leaves more questions open than answered. It seems an issue may be the mappings between what openssl reports and the Apple documentation. It is not possible from the openssl output to determine if TLS 1.2 is supported. The answer also does not allow to determine if Perfect Forward Secrecy is supported. – zaph Dec 10 '15 at 13:08
2

After two days of attempts and failures, what worked for me is this code of womble

with One change, according to this post we should stop using sub-keys associated with the NSExceptionDomains dictionary of that kind of Convention

  NSTemporaryExceptionMinimumTLSVersion

And use at the new Convention

  NSExceptionMinimumTLSVersion

instead.

apple documentation

my code

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>YOUR_HOST.COM</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSExceptionMinimumTLSVersion</key>
                <string>TLSv1.0</string>
                <key>NSExceptionRequiresForwardSecrecy</key>
                <false/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
        </dict>
    </dict>
Community
  • 1
  • 1
1

Another useful tool is nmap (brew install nmap)

nmap --script ssl-enum-ciphers -p 443 google.com

Gives output

Starting Nmap 7.12 ( https://nmap.org ) at 2016-08-11 17:25 IDT
Nmap scan report for google.com (172.217.23.46)
Host is up (0.061s latency).
Other addresses for google.com (not scanned): 2a00:1450:4009:80a::200e
PORT    STATE SERVICE
443/tcp open  https
| ssl-enum-ciphers: 
|   TLSv1.0: 
|     ciphers: 
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|   TLSv1.1: 
|     ciphers: 
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: client
|_  least strength: C

Nmap done: 1 IP address (1 host up) scanned in 5.48 seconds
Ryan Heitner
  • 13,119
  • 6
  • 77
  • 119
0

This error was showing up in the logs sometimes when I was using a buggy/crashy Cordova iOS version. It went away when I upgraded or downgraded cordova iOS.

The server I was connecting to was using TLSv1.2 SSL so I knew that was not the problem.

im3r3k
  • 503
  • 1
  • 7
  • 14
0

In your project .plist file in add this permission :

<key>NSAppTransportSecurity</key>
<dict>
    <!--Connect to anything (this is probably BAD)-->
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
Hiren Dhamecha
  • 658
  • 5
  • 15
0

The syntax for the Info.plist configuration

   <key>NSAppTransportSecurity</key>
   <dict>
   <key>NSExceptionDomains</key>
    <dict>
    <key>yourserver.com</key>
   <dict>
  <!--Include to allow subdomains-->
  <key>NSIncludesSubdomains</key>
  <true/>
  <!--Include to allow insecure HTTP requests-->
  <key>NSExceptionAllowsInsecureHTTPLoads</key>
  <true/>
  <!--Include to specify minimum TLS version-->
  <key>NSExceptionMinimumTLSVersion</key>
  <string>TLSv1.1</string>
   </dict>
 </dict>

ALOK KUMAR
  • 745
  • 5
  • 7
0

Updated Answer (post-WWDC 2016):

iOS apps will require secure HTTPS connections by the end of 2016. Trying turn ATS off may get your app rejected in the future.

App Transport Security, or ATS, is a feature that Apple introduced in iOS 9. When ATS is enabled, it forces an app to connect to web services over an HTTPS connection rather than non secure HTTP.

However, developers can still switch ATS off and allow their apps to send data over an HTTP connection as mentioned in above answers. At the end of 2016, Apple will make ATS mandatory for all developers who hope to submit their apps to the App Store. link

Nicolas Miari
  • 16,006
  • 8
  • 81
  • 189
0

The device I tested at had wrong time set. So when I tried accessing a page with a certificate that would run out soon it would deny access because the device though the certificate had expired. To fix, set proper time on the device!

Warpzit
  • 27,966
  • 19
  • 103
  • 155