IOS 8 нарушила SSL-соединение в моем приложении - CFNetwork SSLHandshake не удалось (-9806)

Мое приложение просто подключается к веб-серверу на домашнем устройстве и читает некоторый html. Он отлично работает при использовании http, но теперь на iOS 8 при использовании https он не работает.

Я использую AFNetworking v1 и переопределяю проверки SSL с помощью этих методов переопределения (да, я знаю, что в обычных обстоятельствах это не должно быть сделано и небезопасно и т.д., но это другая тема).

[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;
    }];

Теперь с iOS 8 я получаю сообщение об ошибке:

Ошибка CFNetwork SSLHandshake (-9806)

Ошибка CFNetwork SSLHandshake (-9806)

Ошибка CFNetwork SSLHandshake (-9806)

NSURLConnection/CFURLConnection Ошибка загрузки HTTP (kCFStreamErrorDomainSSL, -9806)

Ошибка при подключении: Ошибка домена = NSURLErrorDomain Code = -1200 "Произошла ошибка SSL и невозможно создать безопасное соединение с сервером". UserInfo = 0x7b66c110 {NSLocalizedDescription = Произошла ошибка SSL и не удалось создать безопасное соединение с сервером. NSLocalizedRecoverySuggestion = Хотелось бы подключиться к серверу в любом случае?, _kCFStreamErrorCodeKey = -9806, NSErrorFailingURLStringKey = https://xxx.xxx.xxx.xxx:443/live.htm, _kCFStreamErrorDomainKey = 3, NSUnderlyingError = 0x7c0d8a20 "Произошла ошибка SSL и невозможно создать безопасное соединение с сервером". NSErrorFailingURLKey = https://xxx.xxx.xxx.xxx:443/Info.live.htm}

Я попытался перейти на FSNetworking, и он sometimes работает при настройке:

- (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;
    }
}

Однако, выполняя 2 одновременных запроса, только 1 будет успешным, и один будет терпеть неудачу с аналогичной ошибкой выше. Кажется, что только 1 запрос достигает точки перекрытия SSL.

Кто-нибудь может пролить свет на это и что изменилось в iOS 8, чтобы сломать это, и как я могу это исправить?

Спасибо

Ответы

Ответ 1

Я столкнулся с такой же проблемой с iOS 8.

Сценарий:

  • Звонки на наш https-сервер.
  • Откройте https-URL с нашего сервера в UIWebView
  • Все будущие ошибки NSURLConnection с ошибкой SSLHandshake

useCredential:forAuthenticationChallenge вызывал эту ошибку (но только после открытия страницы в https, размещенной на том же сервере), когда мы сразу вызывали методы SecTrust *.

Этот код вызвал ошибку:

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

Но этого не было:

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

Мне непонятно, почему это вызвало сбой SSLHandshake на iOS 8, но не на iOS 7. Возможно, AFNetworking делает что-то после useCredential:forAuthenticationChallenge, что вызывает ту же проблему.

Ответ 2

Ошибка, которую вы видите, можно найти в SecureTransport.h. Это ошибка транспортного уровня: соединение завершилось неудачно, потому что оно было прервано.

На стороне клиента и сервера может возникнуть ряд причин. Это более вероятно, если сервер запрашивает у клиента сертификат, а клиент не предоставляет его, и в этот момент сервер решает отказаться. Если сервер запрашивает у клиента сертификат, ваш метод делегирования должен увидеть попытку аутентификации с использованием сертификата клиента в дополнение к доверенности сервера.