I'm writing some API code that does http requests, and I've been using [NSUrlConnection:sendAsynchronousRequest:queue:completionHandler] for the calls, as it makes it pretty easy to write simple handlers, and also so that I don't have to have different classes with different delegates for each call.
The problem that I'm having is that it seems that the only way to accept self-signed certificates is to have a delegate that implements a couple of functions saying that the certificate is okay. Is there any way to do this with the asynchronous method that uses blocks?
No, but the delegate calls are not all that hard. This is the code you need:
1) Make this a file static
static CFArrayRef certs;
2) DO this in your initialize:
// I had a crt certificate, needed a der one, so found this site:
// http://fixunix.com/openssl/537621-re-der-crt-file-conversion.html
// and did this from Terminal: openssl x509 -in crt.crt -outform der -out crt.der
NSString *path = [[NSBundle mainBundle] pathForResource:@"<your name>" ofType:@"der"];
assert(path);
NSData *data = [NSData dataWithContentsOfFile:path];
assert(data);
SecCertificateRef rootcert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)data);
if(rootcert) {
const void *array[1] = { rootcert };
certs = CFArrayCreate(NULL, array, 1, &kCFTypeArrayCallBacks);
CFRelease(rootcert); // for completeness, really does not matter
} else {
NSLog(@"BIG TROUBLE - ROOT CERTIFICATE FAILED!");
}
3) Then add this method:
- (void)connection:(NSURLConnection *)conn didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
#pragma unused(conn)
// NSLog(@"didReceiveAuthenticationChallenge %@ FAILURES=%zd", [[challenge protectionSpace] authenticationMethod], (ssize_t)[challenge previousFailureCount]);
/* Setup */
NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];
assert(protectionSpace);
SecTrustRef trust = [protectionSpace serverTrust];
assert(trust);
CFRetain(trust); // Don't know when ARC might release protectionSpace
NSURLCredential *credential = [NSURLCredential credentialForTrust:trust];
BOOL trusted = NO;
OSStatus err;
SecTrustResultType trustResult = 0;
err = SecTrustSetAnchorCertificates(trust, certs);
if (err == noErr) {
err = SecTrustEvaluate(trust, &trustResult);
if(err == noErr) {
// http://developer.apple.com/library/mac/#qa/qa1360/_index.html
switch(trustResult) {
case kSecTrustResultProceed:
case kSecTrustResultConfirm:
case kSecTrustResultUnspecified:
trusted = YES;
break;
}
}
}
CFRelease(trust);
// Return based on whether we decided to trust or not
if (trusted) {
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
} else {
NSLog(@"Trust evaluation failed");
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With