6

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];
    }];
Darren
  • 10,182
  • 20
  • 95
  • 162
  • What ATS plist entries have you added? – Paulw11 Sep 21 '15 at 10:33
  • `NSAllowsArbitraryLoads = True` before adding this, even http connections failed. I believe the ATS is just to force http connections to use https. – Darren Sep 21 '15 at 10:35
  • Hmm. This duplicate - http://stackoverflow.com/questions/32634986/ios9-what-is-the-proper-way-to-update-afnetworking-calls-to-work-with-https-err suggests that same fix, but the answer isn't accepted – Paulw11 Sep 21 '15 at 10:44
  • This one - http://stackoverflow.com/questions/31505808/ios9-ssl-error-with-nsurlsession 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 though – Paulw11 Sep 21 '15 at 10:56
  • I believe `NSAllowsArbitraryLoads` overrides `NSExceptionDomains`. `NSExceptionDomains` is just a more refined option. – Darren Sep 21 '15 at 11:16
  • Have you set `self.securityPolicy.validatesDomainName=NO;` – Paulw11 Sep 21 '15 at 11:51
  • Yes I have tried adding that also. – Darren Sep 21 '15 at 11:53
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/90218/discussion-between-paulw11-and-darren). – Paulw11 Sep 21 '15 at 12:08
  • @Darren did you try to set `self.allowsInvalidSSLCertificate = YES;` in your subclass of `AFHTTPRequestOperation`? – godvsdeity Sep 30 '15 at 17:27
  • `allowsInvalidSSLCertificate` is not found. I also tried searching for it, and it's only found once in AFNetworking and that is in a comment ` If `allowsInvalidSSLCertificate` is set to YES, `connection:willSendRequestForAuthenticationChallenge:` will attempt to have the challenge sender use credentials with invalid SSL certificates.` – Darren Sep 30 '15 at 19:29

5 Answers5

3
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
securityPolicy.allowInvalidCertificates = YES;
manager.securityPolicy = securityPolicy;
Miknash
  • 7,888
  • 3
  • 34
  • 46
2

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);
}];
Massimo Polimeni
  • 4,826
  • 4
  • 27
  • 54
1

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

Community
  • 1
  • 1
Syed Absar
  • 2,274
  • 1
  • 26
  • 45
  • Unfortunately, the hardware cannot be updated. The app connects to users home routers. – Darren Sep 28 '15 at 08:30
  • Surely disabling ATS using the plist entry should override all the ATS stuff? – Darren Sep 28 '15 at 08:30
  • don't disable, set the minimum accepted version instead. – Syed Absar Oct 01 '15 at 09:52
  • Setting the minimum is being more refined than disabling. However disabling doesn't fix the error, so setting the minimum won't either. Besides, minimum TLS Version is a setting for individual domains (I don't know the domain in advance). – Darren Oct 01 '15 at 13:27
0

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];
}
Syed Absar
  • 2,274
  • 1
  • 26
  • 45
0

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

  • As of version 1.2.1, you don't need anymore to set this define. Instead you can set the 'allowsInvalidSSLCertificate' property to YES on AFHTTPRequestOperation, which is much more convenient –  Oct 01 '15 at 09:01
  • 1
    [AFHTTPRequestOperationManager manager].securityPolicy.allowInvalidCertificates = YES; In AFNetworking 2.0, you can use the following: –  Oct 01 '15 at 09:03