未调用SSL_CTX_set_tlsext_servername_callback回调函数

时间:2014-03-24 10:45:17

标签: c++ c ssl openssl

我正在编写https服务器,我需要在使用SNI的ssl_accept()之前从客户端获取主机名。我正在使用SSL_CTX_set_tlsext_servername_callback()来接收主机名,但根本不会调用回调。这是我的代码的一部分

// Server Name Indication callback from OpenSSL
static int serverNameCallback(SSL *ssl, int *ad, void *arg) 
{
    if (ssl == NULL)
        return SSL_TLSEXT_ERR_NOACK;

    const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
    printf("ServerName: %s\n", servername);
}

int main()
{
    //some code 
    const SSL_METHOD *method;
    SSL_CTX *ctx;

    method = SSLv3_server_method();  
    ctx = SSL_CTX_new(method);   
    if ( ctx == NULL )
    { 
        printf("SSL_ctx_new() error\n");
    }

    int ret = SSL_CTX_set_tlsext_servername_callback(ctx, serverNameCallback);
}

2 个答案:

答案 0 :(得分:4)

  

我正在编写https服务器,我需要在使用SNI的ssl_accept()之前从客户端获取主机名。

您不会致电SSL_CTX_set_tlsext_servername_callback。 OpenSSL库将在握手期间为您调用它。

对于SSLv2和SSLv3客户端,您的SNI回调是而不是。那是因为SNI是TLS扩展。

如果客户端是Windows XP(或类似的不使用带有TLS的扩展名),则会调用您的SNI回调,但servername将为NULL。在这种情况下,您应该使用默认服务器上下文。

如果客户端正在使用TLS并发送服务器名称,那么将调用您的SNI回调。在回调中,您应该(1)确定默认证书和上下文是否正常。如果没问题,则返回SSL_TLSEXT_ERR_OK。 (2)如果您可以提供更合适的证书,请使用SSL_set_SSL_CTX交换新的上下文并返回SSL_TLSEXT_ERR_OK

如果您遇到错误(例如NULL servername),则应返回SSL_TLSEXT_ERR_NOACK。您还可以返回另外两个错误代码。两者都是致命的,IIRC。

回调的实施细节见Serving multiple domains in one box with SNI

答案 1 :(得分:1)

SSL握手在ssl_accept内完成。服务器名称在握手中传输。因此,回调只能在ssl_accept中调用,而不能在之前调用。