6
votes

I have an app that connects directly to hardware routers. Since iOS 9 I updated AFNetworking and now I am getting ssl errors when I attempt to connect over https.

This isn't an iOS 9 App Transport Security issue, as I have added the relevant .plist entry to bypass it and connections work fine over http.

I need to bypass certificate checking as each router has it's own self signed certificate, so I obviously can't add the certificates to my app as every users is different.

I use a AFHTTPRequestOperation subclass for connections and have set self.securityPolicy.allowInvalidCertificates = YES; but I get the following error:

Error during connection: Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={_kCFStreamErrorCodeKey=-9806, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSUnderlyingError=0x7fa9f3611b40 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSErrorFailingURLStringKey=https://myserver.com:4780/Info.htm, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFNetworkCFStreamSSLErrorOriginalValue=-9806, _kCFStreamPropertySSLClientCertificateState=0, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., _kCFStreamErrorDomainKey=3, NSErrorFailingURLKey=https://myserver.com:4780/Info.htm, _kCFStreamErrorCodeKey=-9806}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://myserver.com:4780/Info.htm, NSErrorFailingURLStringKey=https://myserver.com:4780/Info.htm, _kCFStreamErrorDomainKey=3}

I've also tried adding setWillSendRequestForAuthenticationChallengeBlock: however the block never gets called.

Can someone please help?

Thanks

EDIT ----- Setting self.securityPolicy.validatesDomainName = NO; also doesn't work. I wonder if it's a problem with the type of certificate on the hardware.

EDIT 2 ----- Here's the certificate

New, TLSv1/SSLv3, Cipher is DES-CBC3-SHA Server public key is 2048 bit Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE SSL-Session: Protocol : SSLv3 Cipher : DES-CBC3-SHA Session-ID: 010000000C6B8632215649C0665E9DCC9EC59E22F8F021672B6B50B84222A342 Session-ID-ctx: Master-Key: D71EC7D8F7A4A3581E25CDAD9C532B2C7B4DA8B513AF337095496B575F525CFBA02A40797B2D2A4F0B5911EFEFC3623F Key-Arg : None Start Time: 1443102149 Timeout : 300 (sec) Verify return code: 18 (self signed certificate)

EDIT 3 -------- Adding this code to my AFHTTPRequestOperation subclass makes it work on iOS 8, however the block isn't even called on iOS 9.

[self setWillSendRequestForAuthenticationChallengeBlock:^(NSURLConnection * _Nonnull connection, NSURLAuthenticationChallenge * _Nonnull challenge)
    {
        NSLog(@"**** HERE ****");
        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
        {
            [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
        }
        [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
    }];
5
What ATS plist entries have you added?Paulw11
NSAllowsArbitraryLoads = True before adding this, even http connections failed. I believe the ATS is just to force http connections to use https.Darren
Hmm. This duplicate - stackoverflow.com/questions/32634986/… suggests that same fix, but the answer isn't acceptedPaulw11
This one - stackoverflow.com/questions/31505808/… says that you can only support self-signed certs with exception domains, but I have an app that is working with self-signed certs and just NSAllowsArbitraryLoads. It isn't using AFNetworking thoughPaulw11
I believe NSAllowsArbitraryLoads overrides NSExceptionDomains. NSExceptionDomains is just a more refined option.Darren

5 Answers

3
votes
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
securityPolicy.allowInvalidCertificates = YES;
manager.securityPolicy = securityPolicy;
2
votes

I encountered similar problems and in my case I solved it setting the security policy to AFSSLPinningModeNone and obviously allowing the invalid certificates.

An example in Obj-C:

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
securityPolicy.allowInvalidCertificates = YES;
manager.securityPolicy = securityPolicy;

[manager POST:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject)
{
    NSLog(@"Response: %@",responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
    NSLog(@"Error: %@", error);
}];
1
votes

From Apple's documentation:

Default Behavior

All connections using the NSURLConnection, CFURL, or NSURLSession APIs use App Transport Security default behavior in apps built for iOS 9.0 or later, and OS X v10.11 or later. Connections that do not follow the requirements will fail. For more information on various the connection methods, see NSURLConnection Class Reference, CFURL Reference, or NSURLSession Class Reference.

These are the App Transport Security requirements:

The server must support at least Transport Layer Security (TLS) protocol version 1.2. Connection ciphers are limited to those that provide forward secrecy (see the list of ciphers below.) Certificates must be signed using a SHA256 or greater signature hash algorithm, with either a 2048-bit or greater RSA key or a 256-bit or greater Elliptic-Curve (ECC) key. Invalid certificates result in a hard failure and no connection. These are the accepted ciphers:

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

You might want to upgrade the security settings in your hardware to be compatible with above and/or set NSExceptionMinimumTLSVersion to TLSv1.0

0
votes

In your subclass of AFHTTPRequestOperation, implement the following:

- (BOOL)connection:(NSURLConnection *)connection
canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{

    if ([protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        return YES;
    }

   return  [super connection:connection canAuthenticateAgainstProtectionSpace:protectionSpace];
}


- (void)connection:(NSURLConnection *)connection
didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{

    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
        return;
    }

    return [super connection:connection didReceiveAuthenticationChallenge:challenge];
}
0
votes

To allow Invalid SSL Certificate with AFNetworking. Add the following line in AFURLConnectionOperation.h below #import Availability.h

define _AFNETWORKING_ALLOW_INVALID_SSL_CERTIFICATES_ 1