1

I am working on a app that is destined for use in the IT Enterprise. The app will be an extension to a management system that is distributed via VM image to enterprises. The issue with that is that the VM ships with a self signed cert and is locked down. Obviously I am having an issue trusting that cert in iOS. I know I can disable validation, but that is a horrid idea and pointless for an app store destined product. So I am left wondering, what are my options?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
lampwins
  • 920
  • 1
  • 9
  • 25

2 Answers2

1

I know I can disable validation, but that is a horrid idea and pointless for an app store destined product. So I am left wondering, what are my options?

Disabling validation is a bad idea.

You need to implement -(BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace: (NSURLProtectionSpace*)space and - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge in the delegate to trust the server's certificate.

Apple's offical documentation is located at Authentication Challenges and TLS Chain Validation and Overriding TLS Chain Validation Correctly.

You can see an example of it at OWASP's Certificate and Public Key Pinning, in the iOS example.

Because you have a priori knowledge of what the server's certificate is supposed to be, you can compile it directly into your app and leverage it at runtime. There's no need to jump through hoops to put it in a keychain.

Since you have a trusted distribution channel (either the App Store or the organization's Enterprise Store), you don't have to worry about tampering (some hand waiving).

Also see How to use NSURLConnection to connect with SSL for an untrusted cert?, but be careful. Be careful because it essentially disables validation by always returning [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];. I pointed it out because its a SO answer with the iOS functions.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • 1
    Thanks for this. Future readers should note however, that the "simple" solution of disabling all verification should never be considered. I hesitated asking this question because I did not want to put that idea in anyone's mind. Thank you for adding this to your post. – lampwins Jul 13 '14 at 22:54
1

https://github.com/AFNetworking/AFNetworking/issues/2954 The Core Code:

static inline SecTrustRef AFChangeHostForTrust(SecTrustRef trust, NSString * trustHostname)
{
    if ( ! trustHostname || [trustHostname isEqualToString:@""]) {
        return trust;
    }

    CFMutableArrayRef newTrustPolicies = CFArrayCreateMutable(
                                                              kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);

    SecPolicyRef sslPolicy = SecPolicyCreateSSL(true, (CFStringRef)trustHostname);

    CFArrayAppendValue(newTrustPolicies, sslPolicy);


#ifdef MAC_BACKWARDS_COMPATIBILITY
    /* This technique works in OS X (v10.5 and later) */

    SecTrustSetPolicies(trust, newTrustPolicies);
    CFRelease(oldTrustPolicies);

    return trust;
#else
    /* This technique works in iOS 2 and later, or
     OS X v10.7 and later */

    CFMutableArrayRef certificates = CFArrayCreateMutable(
                                                          kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);

    /* Copy the certificates from the original trust object */
    CFIndex count = SecTrustGetCertificateCount(trust);
    CFIndex i=0;
    for (i = 0; i < count; i++) {
        SecCertificateRef item = SecTrustGetCertificateAtIndex(trust, i);
        CFArrayAppendValue(certificates, item);
    }

    /* Create a new trust object */
    SecTrustRef newtrust = NULL;
    if (SecTrustCreateWithCertificates(certificates, newTrustPolicies, &newtrust) != errSecSuccess) {
        /* Probably a good spot to log something. */

        return NULL;
    }

    return newtrust;
#endif
}
iOS122
  • 11
  • 2