How to handle servername indication with openssl library from server

DonCorleone hamed_gibago at yahoo.com
Wed Jun 19 12:22:12 UTC 2019


I've develepted some windows server side socket in c
and want to add sni server name indication to support sni

but servername callback never called and cant get servername
is there any suggestion?

I've defined some functions for initializing ssl before main function:

    void init_openssl()
    {
        SSL_load_error_strings();
        OpenSSL_add_ssl_algorithms();
    }
    
    SSL_CTX *create_context()
    {
        const SSL_METHOD *method;
        SSL_CTX *ctx;
    
        //method = SSLv23_server_method();
        method = TLSv1_1_server_method();
    
        ctx = SSL_CTX_new(method);
        if (!ctx) {
            perror("Unable to create SSL context");
            ERR_print_errors_fp(stderr);
            exit(EXIT_FAILURE);
        }
    
        return ctx;
    }
    
    void configure_context(SSL_CTX *ctx)
    {
        
        SSL_CTX_set_ecdh_auto(ctx, 1);
    
        /* Set the key and cert */
        if (SSL_CTX_use_certificate_file(ctx, "somesite.cer", SSL_FILETYPE_PEM) <= 0) {
            ERR_print_errors_fp(stderr);
    
            exit(EXIT_FAILURE);
        }
    
        if (SSL_CTX_use_PrivateKey_file(ctx, "key.pem", SSL_FILETYPE_PEM) <= 0) {
            ERR_print_errors_fp(stderr);
    
            exit(EXIT_FAILURE);
        }
    }
    
    static int ssl_servername_cb(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);
    }
    

and here is my main function: 

    int main()
    {
    
    SSL_CTX *ctx;
    
        init_openssl();
        ctx = create_context();
    
        configure_context(ctx);
        
        SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
        
    
    
        WSADATA wsaData;
        int iResult;
    
        SOCKET ListenSocket = INVALID_SOCKET;
        SOCKET ClientSocket = INVALID_SOCKET;
    
        struct addrinfo *result = NULL;
        struct addrinfo hints;
    
        int iSendResult;
        char recvbuf[DEFAULT_BUFLEN];
        int recvbuflen = DEFAULT_BUFLEN;
    
        // Initialize Winsock
        iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
        if (iResult != 0) {
            printf("WSAStartup failed with error: %d\n", iResult);
            return 1;
        }
    
        ZeroMemory(&hints, sizeof(hints));
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;
        hints.ai_flags = AI_PASSIVE;
    
        // Resolve the server address and port
        //iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
        iResult = getaddrinfo("192.168.200.1", DEFAULT_PORT, &hints, &result);
        //iResult = getaddrinfo("127.0.0.1", DEFAULT_PORT, &hints, &result);
        
        if (iResult != 0) {
            printf("getaddrinfo failed with error: %d\n", iResult);
            WSACleanup();
            return 1;
        }
    
        // Create a SOCKET for connecting to server    
        ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
        if (ListenSocket == INVALID_SOCKET) {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            freeaddrinfo(result);
            WSACleanup();
            return 1;
        }
    
        // Setup the TCP listening socket    
        iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            printf("bind failed with error: %d\n", WSAGetLastError());
            freeaddrinfo(result);
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        }
    
        freeaddrinfo(result);
    
        iResult = listen(ListenSocket, SOMAXCONN);
        if (iResult == SOCKET_ERROR) {
            printf("listen failed with error: %d\n", WSAGetLastError());
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        }
    
        // Accept a client socket        
        ClientSocket = accept(ListenSocket, NULL, NULL);    
        SSL *ssl;
        
        if (ClientSocket == INVALID_SOCKET) {
            printf("accept failed with error: %d\n", WSAGetLastError());
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        }
    
        // No longer need server socket
        closesocket(ListenSocket);
    
        // Receive until the peer shuts down the connection
        do {
            
            ssl = SSL_new(ctx);
            SSL_set_fd(ssl, ListenSocket);
            //int rr = SSL_accept(ssl);
    
            iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
            
            //int type=SSL_get_servername_type(ssl);
            //const char[] x=SSL_get_servername(ssl, type);
            //const char *zx= SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
            
            if (iResult > 0) {
                printf("Bytes received: %d\n", iResult);
    
                // Echo the buffer back to the sender
                iSendResult = send(ClientSocket, recvbuf, iResult, 0);
                if (iSendResult == SOCKET_ERROR) {
                    printf("send failed with error: %d\n", WSAGetLastError());
                    closesocket(ClientSocket);
                    WSACleanup();
                    return 1;
                }
                printf("Bytes sent: %d\n", iSendResult);
            }
            else if (iResult == 0)
                printf("Connection closing...\n");
            else {
                printf("recv failed with error: %d\n", WSAGetLastError());
                closesocket(ClientSocket);
                WSACleanup();
                return 1;
            }
    
        } while (iResult > 0);
    
    return 0;
    }

In do while function I've tried to call 

    const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
but didn't find anything.
I know that clienthello handshake is in first bytes that is received from socket.

    iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);

And I receive 219 bytes of data. I need to handle servername and find it, and load certificate file and do continuous job, and maybe after that keep going with higher level in c# sslstream class.
Any suggestion?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mta.openssl.org/pipermail/openssl-users/attachments/20190619/6ea38764/attachment.html>


More information about the openssl-users mailing list