I've seen here a few questions but none of them helped me. People resolve issues mostly regenerating server certificates: What is the reason of kSecTrustResultRecoverableTrustFailure?
Suppose I need to make a https connection to server with self-signed certificate. I don't have any internal data from the server such as its private keys. For example the server is https://www.pcwebshop.co.uk/
As far as I understand I can bundle a client certificate into app and use it for verification. Am I right I can obtain a valid client certificate without having any internal data from the server?
I've googled a tutorial here http://www.indelible.org/ink/trusted-ssl-certificates
Here's how I'm obtaining a client certificate
openssl s_client \
-showcerts -connect "${HOST}:443" </dev/null 2>/dev/null | \
openssl x509 -outform DER >"../resources/${HOST}.der"
Here's the code (almost unchanged):
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([self shouldTrustProtectionSpace:challenge.protectionSpace]) {
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]
forAuthenticationChallenge:challenge];
} else {
[challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
}
}
- (BOOL)shouldTrustProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
// load up the bundled certificate
NSString *certPath = [[NSBundle mainBundle] pathForResource:protectionSpace.host ofType:@"der"];
if (certPath == nil)
return NO;
OSStatus status;
NSData *certData = [[NSData alloc] initWithContentsOfFile:certPath];
CFDataRef certDataRef = (__bridge_retained CFDataRef)certData;
SecCertificateRef cert = SecCertificateCreateWithData(NULL, certDataRef);
// establish a chain of trust anchored on our bundled certificate
CFArrayRef certArrayRef = CFArrayCreate(NULL, (void *)&cert, 1, NULL);
SecTrustRef serverTrust = protectionSpace.serverTrust;
status = SecTrustSetAnchorCertificates(serverTrust, certArrayRef);
// status == 0
// verify that trust
SecTrustResultType trustResult;
status = SecTrustEvaluate(serverTrust, &trustResult);
// status == 0
CFRelease(certArrayRef);
CFRelease(cert);
CFRelease(certDataRef);
return trustResult == kSecTrustResultUnspecified;
}
trustResult is always kSecTrustResultRecoverableTrustFailure.
What am I doing wrong? Thank you.
UPDATE: Ok, I found out that the reason is "Server's certificate does not match the URL".
Is it possible to fix the issue from the client side by ignoring the URL (hostname) of the server's certificate?