我正在尝试在OS X
应用程序的服务器端实现服务器名称指示:服务器应根据客户端提供的对等主机名选择证书。
有人知道是否可以使用Security.framework
实现这一目标吗?
SSLSetCertificate
只获取一个叶子证书,我找不到任何基于主机名提供证书的回调。
例如,在openSSL中,为此目的有SSL_CTX_set_tlsext_servername_callback。
非常感谢任何帮助。
答案 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
}