Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check to non default Root Certificate #36

Closed
das-Iro opened this issue Apr 2, 2012 · 2 comments
Closed

Check to non default Root Certificate #36

das-Iro opened this issue Apr 2, 2012 · 2 comments
Milestone

Comments

@das-Iro
Copy link

das-Iro commented Apr 2, 2012

I'd like to use CACert or a custom Root Cert to secure my connections.
I haven't found a way to do it directly do this, so I do it afterwards. This is how it looks like.
Is there a better way of doing this?/Could this (functionality) be implemented directly into GCDAsyncSocket?

kCFStreamSSLAllowsAnyRoot is set to true

- (void)socketDidSecure:(GCDAsyncSocket *)sock
{
    [sock performBlock:^{
        CFReadStreamRef readStream=[sock readStream];

        // Create SecTrustRef from Stream
        CFTypeRef ref=CFReadStreamCopyProperty(readStream, kCFStreamPropertySSLPeerCertificates);
        SecPolicyRef policy = SecPolicyCreateSSL(NO, (__bridge CFStringRef)[sock theHost]);
        SecTrustRef trust = NULL;
        SecTrustCreateWithCertificates(ref, policy, &trust);

        // Get our Root
        NSString *path=[[NSBundle mainBundle] pathForResource:@"CACert-class3" ofType:@"der"];
        NSData *certData=[NSData dataWithContentsOfFile:path];
        SecCertificateRef cert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData);

        // Verify
        SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)[NSArray arrayWithObject:(__bridge id)cert]);
        SecTrustResultType trustResultType = kSecTrustResultInvalid;
        OSStatus status = SecTrustEvaluate(trust, &trustResultType);

        if (status == errSecSuccess) {
            if (trustResultType == kSecTrustResultUnspecified) {
                NSLog(@"%@ is Trustworthy", [sock theHost]);
            } else {
                NSLog(@"%@ is EVIL ;)", [sock theHost]);
            }
        } else {
            NSLog(@"SecTrustEvaluate failed");
        }
    }];
}
@asimihsan
Copy link

This issue's source code was immensely useful for me, and saved me a lot of time.

I think, if you wanted to implement this directly in CocoaAsyncSocket, you'd want to do it before any call to ssl_continueSSLHandshake in GCDAsyncSocket.m. However, I'm not sure.

@robbiehanson robbiehanson added this to the 7.4 milestone Apr 13, 2014
@robbiehanson
Copy link
Owner

In the 7.4 branch, you can now use code like this:

NSDictionary *options = @{
    GCDAsyncSocketManuallyEvaluateTrust : @(YES),
    GCDAsyncSocketSSLPeerName : @"domain.com"
};

[asyncSocket startTLS:options];

along with the new delegate method:

- (void)socket:(GCDAsyncSocket *)sock didReceiveTrust:(SecTrustRef)trust
                                    completionHandler:(void (^)(BOOL shouldTrustPeer))completionHandler
{
    dispatch_queue_t bgQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(bgQueue, ^{

        // ... configure however needed ...

        SecTrustResultType result = kSecTrustResultDeny;
        OSStatus status = SecTrustEvaluate(trust, &result);

        if (status == noErr && (result == kSecTrustResultProceed || result == kSecTrustResultUnspecified)) {
            completionHandler(YES);
        } else {
            completionHandler(NO);
        }
    });
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants