My app connects to the Schwab OFX server using NSURLConnection
. Unfortunately the server uses a very recent intermediate certificate that is trusted on the Mac desktop but not yet the iPhone. (Try the URL—you'll get a cert error on iPhone.)
There's no easy way to tell NSURLConnection
to ignore an invalid cert that I know of. Thus I'm trying to import the cert into the Keychain manually and set its trust level but I've hit a block.
I call SecCertificateCreateWithData
successfully to import the certificate from a .cer
file. On the desktop I would then call SecTrustSettingsSetTrustSettings
, but it doesn't exist in the iPhone SDK.
Any workaround?
Apple technical support responded to me promptly with a perfect answer.
First, I am incorrect in saying that Schwab uses "a very recent intermediate certificate that is trusted on the Mac desktop but not yet the iPhone". Intermediate certificates are never in the built-in root certificate store. The issue is that most SSL servers bundle all intermediate certificates needed for verification, but Schwab uses an alternate SSL process that expects you to fetch the intermediate certificate from a URL. The Mac desktop supports intermediate-certificate fetching, but not the current iPhone OS.
Here's the gist of the actual code:
OSStatus err;
NSString * path;
NSData * data;
SecCertificateRef cert;
path = [[NSBundle mainBundle] pathForResource:@"OFX-G3" ofType:@"cer"];
assert(path != nil);
data = [NSData dataWithContentsOfFile:path];
assert(data != nil);
cert = SecCertificateCreateWithData(NULL, (CFDataRef) data);
assert(cert != NULL);
err = SecItemAdd(
(CFDictionaryRef) [NSDictionary dictionaryWithObjectsAndKeys:
(id) kSecClassCertificate, kSecClass,
cert, kSecValueRef,
nil
],
NULL
);
assert(err == noErr);
CFRelease(cert);
This assumes that OFX-G3.cer is the intermediate SSL certificate and is located in the Resources folder.
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