web-dev-qa-db-fra.com

iOS 8 a rompu la connexion SSL dans mon application - CFNetwork SSLHandshake a échoué (-9806)

Mon application se connecte simplement à un serveur Web sur un appareil domestique et lit du HTML. Cela fonctionne bien lorsque vous utilisez http, mais maintenant sur iOS 8 lorsque vous utilisez https, cela ne fonctionne pas.

J'utilise AFNetworking v1 et je remplace les vérifications SSL en utilisant ces méthodes de remplacement (Oui, je sais que dans des circonstances normales, cela ne devrait pas être fait et n'est pas sûr, etc., mais c'est un autre sujet).

[self setAuthenticationChallengeBlock:^(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge) {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
            [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
        }
    }];

[self setAuthenticationAgainstProtectionSpaceBlock:^BOOL(NSURLConnection *connection, NSURLProtectionSpace *protectionSpace) {
        if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]) {
                return YES; // Self-signed cert will be accepted
        }
        // If no other authentication is required, return NO for everything else
        // Otherwise maybe YES for NSURLAuthenticationMethodDefault and etc.
        return NO;
    }];

Maintenant, avec iOS 8, je reçois une erreur comme celle-ci:

CFNetwork SSLHandshake a échoué (-9806)

CFNetwork SSLHandshake a échoué (-9806)

CFNetwork SSLHandshake a échoué (-9806)

Échec du chargement HTTP de NSURLConnection/CFURLConnection (kCFStreamErrorDomainSSL, -9806)

Erreur lors de la connexion: Error Domain = NSURLErrorDomain Code = -1200 "Une erreur SSL s'est produite et une connexion sécurisée au serveur ne peut pas être établie." UserInfo = 0x7b66c110 {NSLocalizedDescription = Une erreur SSL s'est produite et une connexion sécurisée au serveur ne peut pas être établie., NSLocalizedRecoverySuggestion = Voulez-vous quand même vous connecter au serveur?, _KCFStreamErrorCodeKey = -9806, NSErrorFailingURLStringKey = https://xxx.xxx.xxx.xxx:443/live.htm , _kCFStreamErrorDomainKey = 3, NSUnderlyingError = 0x7c0d8a20 "Une erreur SSL s'est produite et une connexion sécurisée au serveur ne peut pas être établie.", NSErrorFailingURLKey = https://xxx.xxx.xxx.xxx:443/Info.live.htm }

J'ai essayé de passer à FSNetworking, et cela sometimes fonctionne lors de la définition de ceci:

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

    if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    {
        NSLog(@"Ignoring SSL");
        SecTrustRef trust = challenge.protectionSpace.serverTrust;
        NSURLCredential *cred;
        cred = [NSURLCredential credentialForTrust:trust];
        [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];
        return;
    }
}

Cependant, en faisant 2 requêtes simultanées, une seule réussira et une échouera avec une erreur similaire à celle ci-dessus. Une seule demande semble atteindre le point de priorité SSL.

Quelqu'un peut-il faire la lumière sur ce qui a changé dans iOS 8 pour casser cela et comment puis-je le résoudre?

Merci

14
Darren

J'ai rencontré le même genre de problème avec iOS 8.

Scénario:

  1. Les appels vers notre serveur https fonctionnent
  2. Ouvrez une URL https depuis notre serveur dans un UIWebView
  3. Tous les futurs NSURLConnections échouent avec une erreur SSLHandshake

useCredential:forAuthenticationChallenge était à l'origine de cette erreur (mais uniquement après l'ouverture d'une page dans https hébergée sur le même serveur) lorsque nous avons appelé les méthodes SecTrust * juste après.

Ce code a déclenché l'erreur:

[challenge.sender useCredential:urlCredential forAuthenticationChallenge:challenge];
SecTrustRef trustRef = [[challenge protectionSpace] serverTrust];
CFIndex count = SecTrustGetCertificateCount(trustRef);

Mais celui-ci n'a pas:

SecTrustRef trustRef = [[challenge protectionSpace] serverTrust];
CFIndex count = SecTrustGetCertificateCount(trustRef);
[challenge.sender useCredential:urlCredential forAuthenticationChallenge:challenge];

Je ne comprends pas pourquoi cela a provoqué l'échec de SSLHandshake sur iOS 8 mais pas iOS 7. Peut-être qu'AFNetworking fait quelque chose après useCredential:forAuthenticationChallenge qui est à l'origine du même problème.

9
Simon Watiau

L'erreur que vous voyez se trouve dans SecureTransport.h. Il s'agit d'une erreur au niveau du transport: la connexion a échoué car elle a été abandonnée.

Un certain nombre de choses pourraient en être la cause, à la fois sur le client et sur le serveur. Cela est plus susceptible de se produire si le serveur demande au client un certificat et que le client n'en fournit pas, auquel cas le serveur décide d'abandonner. Si le serveur demande au client un certificat, votre méthode déléguée doit voir une tentative d'authentification à l'aide d'un certificat client en plus de l'approbation du serveur.

2
quellish