Я пытаюсь использовать следующий код для обработки соединений SSL в iOS. Он отлично работает на реальном устройстве, и сертификат выдается полностью доверенным центром сертификации. Сбой при попытке запустить его из юнит-теста. Кто-нибудь еще видел такое поведение или знает обходной путь?
- (BOOL) connection:(NSURLConnection *)aConnection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
NSString *authenticationMethod = protectionSpace.authenticationMethod;
NSLog(@"Authentication method: %@", authenticationMethod);
return [authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void) connection:(NSURLConnection *)aConnection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSLog(@"Challenge: %@", challenge);
NSURLCredential *proposedCredential = [challenge proposedCredential];
NSLog(@"proposedCredential = %@", proposedCredential);
NSURLProtectionSpace *protectionSpace = challenge.protectionSpace;
NSLog(@"protectionSpace = %@", protectionSpace);
NSString *host = protectionSpace.host;
NSLog(@"Trust host: %@", host);
id <NSURLAuthenticationChallengeSender> sender = challenge.sender;
NSLog(@"sender = %@", sender);
if ([protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
if ([trustedHosts containsObject:host]) {
SecTrustRef trust = protectionSpace.serverTrust;
NSLog(@"trust %p", trust);
NSURLCredential *credential = [NSURLCredential credentialForTrust:trust];
NSLog(@"Credential: %@", credential);
SecTrustResultType result;
OSStatus status = SecTrustEvaluate(trust, &result);
NSLog(@"Trust result: %lu", result);
NSLog(@"OSStatus = %li", status);
NSError *error = [challenge error];
NSLog(@"error = %@", error);
[sender useCredential:credential forAuthenticationChallenge:challenge];
NSLog(@"Using credential");
} else {
[sender performDefaultHandlingForAuthenticationChallenge:challenge];
}
} else {
[sender performDefaultHandlingForAuthenticationChallenge:challenge];
}
}
Результат теста в AppCode выглядит следующим образом:
2012-03-06 14:35:09.656 otest[5696:7803] About to login
2012-03-06 14:35:09.656 otest[5696:7803] AccountVerificationService - postAccountInfo
2012-03-06 14:35:09.658 otest[5696:7803] POST url: https://secure.example.com/user/verify
2012-03-06 14:35:09.662 otest[5696:7803] Login called
2012-03-06 14:35:09.949 otest[5696:7803] Authentication method: NSURLAuthenticationMethodServerTrust
2012-03-06 14:35:09.953 otest[5696:7803] Challenge: <NSURLAuthenticationChallenge: 0x1b8ded0>
2012-03-06 14:35:09.956 otest[5696:7803] proposedCredential = (null)
2012-03-06 14:35:09.956 otest[5696:7803] protectionSpace = <NSURLProtectionSpace: 0x1b8df00>
2012-03-06 14:35:09.957 otest[5696:7803] Trust host: secure.example.com
2012-03-06 14:35:09.958 otest[5696:7803] sender = <NSURLConnection: 0x1b8d0d0>
2012-03-06 14:35:09.958 otest[5696:7803] trust 0x1d8fb90
2012-03-06 14:35:09.962 otest[5696:7803] Credential: <NSURLCredential: 0x1b8e460>: (null)
2012-03-06 14:35:09.983 otest[5696:7803] Trust result: 7
2012-03-06 14:35:10.001 otest[5696:7803] OSStatus = 0
2012-03-06 14:35:10.011 otest[5696:7803] error = (null)
Process finished with exit code 138
Отладка обратного следа:
thread #4: tid = 0x3603, 0x0039a841 CoreFoundation`CFArrayGetCount + 17, stop reason = EXC_BAD_ACCESS (code=2, address=0x0)
frame #0: 0x0039a841 CoreFoundation`CFArrayGetCount + 17
frame #1: 0x00dad4f4 Security`SecTrustCopyExceptions + 35
frame #2: 0x00b318e4 CFNetwork`SocketStream::securityAcceptPeerTrust_NoLock(unsigned char) + 150
frame #3: 0x00b3a154 CFNetwork`SocketStream::setProperty(void const*, __CFString const*, void const*) + 2754
frame #4: 0x00b39688 CFNetwork`virtual thunk to SocketStream::setProperty(void const*, __CFString const*, void const*) + 43
frame #5: 0x00b3ad3b CFNetwork`ReadStreamCallbacks::_setProperty(__CFReadStream*, __CFString const*, void const*, void*) + 53
frame #6: 0x00429b40 CoreFoundation`CFReadStreamSetProperty + 160
frame #7: 0x00b3acee CFNetwork`HTTPReadFilter::streamSetProperty(__CFReadStream*, __CFString const*, void const*) + 266
frame #8: 0x00bd4381 CFNetwork`non-virtual thunk to HTTPReadFilter::streamSetProperty(__CFReadStream*, __CFString const*, void const*) + 41
frame #9: 0x00b37488 CFNetwork`CFNetworkReadStream::httpStreamSetProperty(__CFReadStream*, __CFString const*, void const*, void*) + 38
frame #10: 0x00429b40 CoreFoundation`CFReadStreamSetProperty + 160
frame #11: 0x00b41b88 CFNetwork`HTTPNetStreamInfo::streamSetProperty(__CFReadStream*, __CFString const*, void const*) + 404
frame #12: 0x00b419ec CFNetwork`non-virtual thunk to HTTPNetStreamInfo::streamSetProperty(__CFReadStream*, __CFString const*, void const*) + 41
frame #13: 0x00b37488 CFNetwork`CFNetworkReadStream::httpStreamSetProperty(__CFReadStream*, __CFString const*, void const*, void*) + 38
frame #14: 0x00429b40 CoreFoundation`CFReadStreamSetProperty + 160
frame #15: 0x00be3e7b CFNetwork`HTTPProtocol::useCredential(_CFURLCredential const*, _CFURLAuthChallenge*) + 125
frame #16: 0x00bfa9e3 CFNetwork`URLConnectionLoader::loaderUseCredential(_CFURLCredential const*) + 117
frame #17: 0x00bfa4ce CFNetwork`URLConnectionLoader::LoaderConnectionEventQueue::processAllEventsAndConsumePayload(XConnectionEventInfo<XLoaderEvent, XLoaderEventParams>*, long) + 140
frame #18: 0x00b228b7 CFNetwork`URLConnectionLoader::processEvents() + 107
frame #19: 0x00bf716b CFNetwork`non-virtual thunk to URLConnectionInstanceData::multiplexerClientPerform() + 21
frame #20: 0x00b21137 CFNetwork`MultiplexerSource::perform() + 259
frame #21: 0x0045e97f CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
frame #22: 0x003c1b73 CoreFoundation`__CFRunLoopDoSources0 + 243
frame #23: 0x003c1454 CoreFoundation`__CFRunLoopRun + 1012
frame #24: 0x003c0db4 CoreFoundation`CFRunLoopRunSpecific + 212
frame #25: 0x003c0ccb CoreFoundation`CFRunLoopRunInMode + 123
frame #26: 0x00108e40 Foundation`+[NSURLConnection(Loader) _resourceLoadLoop:] + 398
frame #27: 0x0001a4e6 Foundation`-[NSThread main] + 76
frame #28: 0x0001a457 Foundation`__NSThread__main__ + 1258
frame #29: 0x94d8fed9 libsystem_c.dylib`_pthread_start + 335