如何为 SSL 握手配置 CFStream(或 NSStream)? [英] How to configure CFStream (or NSStream) for SSL handshake?

查看:31
本文介绍了如何为 SSL 握手配置 CFStream(或 NSStream)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 CFStream/NSStream 建立 http 连接.我希望能够在三种情况下检测到 SSL 握手失败:

I'm using CFStream/NSStream to make http connections. I want to be able to detect that a SSL handshake fails for three cases:

  • 情况 A:服务器不受信任
  • 情况 B:服务器受信任但要求提供客户端证书
  • 情况 C:服务器不受信任,它要求提供客户端证书

今天没有对我的 CFStream 的 SSL 属性做任何处理,我得到:

Today without doing anithing on the SSL Properties of my CFStream, I get:

  • 情况 A:错误 -9807
  • 情况 B:没有错误但服务器拒绝连接(错误 500)
  • 情况 C:错误 9807

有没有办法配置CFStream来正确区分这3种情况?或者在 SSL 握手期间有一些回调?

Is there a way to configure CFStream to correctly distinguish these 3 cases ? Or to have some callbacks during SSL handshake ?

感谢您的帮助.

推荐答案

前段时间我在使用 SSL 的 CFSockets 中运行了同样的事情.CFStream 处理所有握手的事情.我为 NSStream 添加了一个小类(基本代码来自 Apple,不再有链接,如果我找到它我会添加它).这对我有用.

Some time ago I ran in a same thing with CFSockets using SSL. CFStream handles all the handshake stuff. I wrote a little class addition for NSStream (Base code comes from Apple, don't have the link anymore, if I find it I'll add it). That's what worked for me.

界面

@interface NSStream (FSNetworkAdditions)

+ (void)qNetworkAdditions_getStreamsToHostNamed:(NSString *)hostName
                                           port:(NSInteger)port
                                    inputStream:(out NSInputStream **)inputStreamPtr
                                   outputStream:(out NSOutputStream **)outputStreamPtr;

@end

和实施

#import "FSNetworkAdditions.h"

@implementation NSStream (FSNetworkAdditions)

+ (void)qNetworkAdditions_getStreamsToHostNamed:(NSString *)hostName
                                           port:(NSInteger)port
                                    inputStream:(out NSInputStream **)inputStreamPtr
                                   outputStream:(out NSOutputStream **)outputStreamPtr
{
    CFReadStreamRef     readStream;
    CFWriteStreamRef    writeStream;

    assert(hostName != nil);
    assert( (port > 0) && (port < 65536) );
    assert( (inputStreamPtr != NULL) || (outputStreamPtr != NULL) );

    readStream = NULL;
    writeStream = NULL;

    CFStreamCreatePairWithSocketToHost(
                                       NULL,
                                       (CFStringRef) hostName,
                                       port,
                                       ((inputStreamPtr  != NULL) ? &readStream : NULL),
                                       ((outputStreamPtr != NULL) ? &writeStream : NULL)
                                       );

    NSDictionary *settings = [[NSDictionary alloc] initWithObjectsAndKeys:
                              [NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates,
                              [NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot,
                              [NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredRoots,
                              [NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain,
                              //kCFNull,kCFStreamSSLPeerName,
                              kCFStreamSocketSecurityLevelSSLv3, kCFStreamSSLLevel,
                              [NSNumber numberWithBool:YES], kCFStreamPropertyShouldCloseNativeSocket,
                              nil];

    if (readStream) {
        CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
    }

    if (writeStream) {
        CFWriteStreamSetProperty(writeStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
    }

    if (inputStreamPtr != NULL) {
        *inputStreamPtr  = CFBridgingRelease(readStream);
    }
    if (outputStreamPtr != NULL) {
        *outputStreamPtr = CFBridgingRelease(writeStream);
    }


}

@end

就是这样,您现在可以像这样连接到服务器:

That's it now you can connect to a Server like this:

NSInputStream   *inputStream;
NSOutputStream  *outputStream;
[NSStream qNetworkAdditions_getStreamsToHostNamed:host 
                                             port:port 
                                      inputStream:&inputStream 
                                     outputStream:&outputStream];

        inputStream.delegate  = self;
        outputStream.delegate = self;

其中self"符合 NSStreamDelegate 协议.

Where "self" conforms to the NSStreamDelegate Protocol.

我希望这些片段能有所帮助.

I hope these snippets helps.

这篇关于如何为 SSL 握手配置 CFStream(或 NSStream)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆