如何使用OS X / iOS下的Security.framework实现服务器端服务器名称指示

时间:2015-10-28 10:34:02

标签: ios macos ssl server

我正在尝试在OS X应用程序的服务器端实现服务器名称指示:服务器应根据客户端提供的对等主机名选择证书。 有人知道是否可以使用Security.framework实现这一目标吗? SSLSetCertificate只获取一个叶子证书,我找不到任何基于主机名提供证书的回调。

例如,在openSSL中,为此目的有SSL_CTX_set_tlsext_servername_callback。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

OS X 10.11(El Capitan)中有一项新功能可以实现这一目标。遗憾的是,目前没有关于此功能的文档,但我发现它是如何工作的:

您必须在SSL上下文中启用新选项kSSLSessionOptionBreakOnClientHello

SSLSetSessionOption(context, kSSLSessionOptionBreakOnClientHello, YES);

这会导致握手在从客户端收到主机名后中断,并返回状态errSSLClientHelloReceived。然后,您可以获取主机名,使用它来查找相应的证书并将证书应用于上下文。然后你可以继续握手。

OSStatus status = SSLHandshake(context);

// ...

if(status == errSSLClientHelloReceived) 
{
    size_t hostnameLength;
    SSLGetPeerDomainNameLength(context, &hostnameLength);
    char hostname[hostnameLength];
    SSLGetPeerDomainName(context, hostname, &hostnameLength);

    SecIdentityRef cert = ... ; // Look up certificate using hostname

    SSLSetCertificate(context, (__bridge CFArrayRef)@[(__bridge id) cert]);

    // Repeat from start by calling SSLHandshake 
}