iOS Untrusted Server Certificate
Had a problem recently with iOS 3.0 where it did not trust my server’s SSL certificate.
Newer versions do, so iOS 3.0 must simply not have the root certificates.
There are two ways to solve this: one is to blindly accept all certificates. That’s bad – as you lose the identify protection that SSL provides (and subject your users to man-in-the-middle attacks). It’s also harder, as you have to apply this to *every* connection (and if you use a UIWebView that may not be possible). But if you really want, the info is here.
The better approach is to include the root certificates of the certificate authority (no need for your actual certificate) in your App. This just makes the iPhone trust your CA, and will even work if you re-issue the cert in the future with the same CA (no need to update the app).
To trust a certificate, simply add this method:
// ref: http://stackoverflow.com/questions/1746005/importing-an-ssl-cert-under-the-iphone-sdk
+ (void) trustCert:(NSString*)filename ext:(NSString*)ext
{
// NB. certificate must be in DER format (SecCertificateCreateWithData will return nil if not)
// To convert, on the command line type: openssl x509 -in your_cert_name.cer -out UTN-your_cert_name.der -outform DER
OSStatus err;
NSString * path;
NSData * data;
SecCertificateRef cert;
path = [[NSBundle mainBundle] pathForResource:filename ofType:ext];
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 || err == errSecDuplicateItem);
CFRelease(cert);
}
I got that method from here, but added a check to see if the cert was already imported (and not assert on that case).
If you don’t have your certificates on hand, you will need to export all the certificates in the chain of trust. I did this from Firefox using the view certificate -> export feature. Export all certs in the tree, except your server’s one itself (this one is not needed). For me, this meant 3 certificates.
Make sure your cert is in DER format. You can convert the typical ASCII
CER format (such as the ones exported through Firefox) into DER in this way on the command line:
openssl x509 -in your_cert_name.cer -out UTN-your_cert_name.der -outform DER
Add your .der file to your project (all targets).
Then, just call this line before you use the cert:
[YourClass trustCert:@"your_cert_name" ext:@"der"];
For me, I had to trust all 3 certificates in the chain. The only cert I didn’t need to bundle was the one for my server itself.
WARNING: due to the way this code works, you only have to call it *once* and it keeps the cert in your app’s keychain (I think). Even if you delete the app, the cert remains there. So take care when testing your code. I think if you change the bundle identifier for your app, it would be like a fresh install. Remember, deleting the app will not delete the cert from that app’s keychain, so this can fool you into thinking the code is no longer needed (or something).
Importantly – this code only solves your cert issues from WITHIN your App. To solve them from Mobile Safari (these are two, mutually exclusive solutions), you need to create a mobile config file containing all your root certificates, and get the user to install it. You can do that with the iPhone Configuration Utility, create the config and send users to that URL on their iPhones.
Link Shorteners and the Eternal URL
URLs are (or should be) eternal. Once you create some content and slap it up on the web, people will start referencing it. If you change the URL or remove the content, then these references break – which is sad.
Enter link shorteners. All of a sudden, you are referencing a whole bunch of content (your own, and others) through an additional 3rd party. So now you not only have to worry about whether the referenced content will still be there, but also that the link shortener hasn’t run out of money and closed up shop too.
A big problem I see is that link shorteners earn no money (read: operating costs) when you simply click the links. They *do* get brand recognition, which helps drive people to their site to shorten links of their own (which in turn can earn money through ad impressions, etc). But what happens when we’ve all moved on to something new. The link shortener won’t be earning as much money (nobody shortning urls any more), but still has to pay to keep their infrastructure online.
This troubles me. And, with log.ly – a new link shortener for Geospike.com I am also now a link shortener operator!
To combat this potential issue, I propose the following idea: Somebody reputable (The Internet Archive would be a good candidate) creates a global link shortener database with 3 basic keys [domain, link key, full link]. Link shorteners can then periodically – or just when they go bust – import their database into this master database.
Then, if they do go bust, then can transfer their domain to The Internet Archive, to operate the links on a read-only basis. In the event such a transfer is not possible (such as Libya suddenly commandeering all .ly domains), then at least people could manually look up the short link through a form on The Internet Archive’s website. If link shorteners operators are concerned about people farming the DB, then perhaps the archive could be private, while said link shortener is in active operation.
Without such a service, the situation link shortener operators would face if they became unprofitable would be to keep paying the bills for the good of humanity, or hear a great many URLs cry out in terror before being suddenly silenced.
The short URL for this post is: http://b.log.ly/fmD1EG ;-)
