14
votes

In iOS 9, I am hitting a request for the url https://s3.amazonaws.com/furniture.retailcatalog.us/products/2061/6262u9665.jpg using basic NSURLConnection.

NSOperationQueue *completionQueue = [NSOperationQueue mainQueue];
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    self.mURLSession = [NSURLSession sessionWithConfiguration:configuration delegate:nil delegateQueue:completionQueue];

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://s3.amazonaws.com/furniture.retailcatalog.us/products/2061/6262u9665.jpg"]];
    NSURLSessionDataTask *dataTask = [self.mURLSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSLog(@"%@",error);
    }];
    [dataTask resume];

But getting this error

Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, NSUnderlyingError=0x7c1075e0 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorCodeKey=-9802, _kCFStreamErrorDomainKey=3, kCFStreamPropertySSLPeerTrust=, kCFStreamPropertySSLPeerCertificates={type = immutable, count = 3, values = ( 0 : 1 : 2 : )}}}, _kCFStreamErrorCodeKey=-9802, NSErrorFailingURLStringKey=https://s3.amazonaws.com/furniture.retailcatalog.us/products/2061/6262u9665.jpg, NSErrorPeerCertificateChainKey={type = immutable, count = 3, values = ( 0 : 1 : 2 : )}, NSErrorClientCertificateStateKey=0, NSURLErrorFailingURLPeerTrustErrorKey=, NSErrorFailingURLKey=https://s3.amazonaws.com/furniture.retailcatalog.us/products/2061/6262u9665.jpg}

Even though this is https connection,why am I getting this strange error. Can anyone please let me know.

4
I'm not too knowledgeable about this issue, but I believe just having HTTPS isn't enough on iOS 9 -- your connection also needs to use at least TLS 1.2. You can google around and find a service that will tell you if you have that on for this server. That was the reason for this error when I saw it a while ago.Ben Pious

4 Answers

27
votes

As per the Apple tech note, App Transport Security requires SHA-2. The S3 (and CloudFront) certificates are using SHA-1, which is why this failure is occurring.

The workaround is to set the NSExceptionRequiresForwardSecrecy to false. (This is until AWS moves to SHA-2 (by September 30th, 2015)).

SHA-1 Signature

7
votes

I encountered this with Amazon S3 as well. Unfortunately, I can't tell you why this is happening - S3 appears to meet the forward secrecy requirements (at least according to this answer):

Adams-MacBook-Pro:tmp Adam$ curl -kvI https://s3.amazonaws.com
* Rebuilt URL to: https://s3.amazonaws.com/
*   Trying 54.231.32.128...
* Connected to s3.amazonaws.com (54.231.32.128) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

The workaround, which I found here is to add an exception to your app's Info.plist file to not require forward secrecy:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>s3.amazonaws.com</key>
        <dict>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
        </dict>
    </dict>
</dict>

As far as I can tell, this is the minimum amount you can reduce the built-in security in order to connect to Amazon S3.

2
votes

With help from the other answers provided here, and here, I fixed my app that needs to connect to multiple cloudfront.net subdomains with this addition to the plist:

        <key>NSAppTransportSecurity</key>
        <dict>
            <key>NSExceptionDomains</key>
            <dict>
                <key>cloudfront.net</key>
                    <dict>
                    <!--Include to allow subdomains-->
                    <key>NSIncludesSubdomains</key>
                    <true/>
                    <key>NSExceptionRequiresForwardSecrecy</key>
                    <false/>
                </dict>
            </dict>
        </dict>
0
votes

For me the solution was to add this exception for the domain:

<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>xxx.com</key>
        <dict>
            <key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
</dict>