I was able to solve the problem, the session cache was activated and stored all the sessions and a bug in DTLS caused that twice as much sessions as necessary have been created. The bug will be fixed with an updated version of bugfix #2028.

- Robin


Am 02.09.2009 um 10:47 schrieb Robin Seggelmann:

Hi all,
I have written an DTLS echo server and client for testing purposes. In this case I want to test my new DTLSv1_listen() function, which waits for new connections with responding to ClientHellos with HelloVerifyRequest messages until a ClientHello with a valid cookie arrives. The SSL object can then be used for that connection and DTLSv1_listen() is called with a new SSL object again. Unfortunately the server has a memory leak which I was unable to find yet. According to my debug tools the problem seems to be that some certificates aren't freed. However, there are no leaks in terms of memory that is not accessible anymore. Here is the scheme of my server:

void start_server(int port, in_addr_t* local_address) {

... (variables) ...
        
        THREAD_setup();
        OpenSSL_add_ssl_algorithms();
        SSL_load_error_strings();
        ctx = SSL_CTX_new(DTLSv1_server_method());
        SSL_CTX_set_cipher_list(ctx, "ALL:NULL:eNULL:aNULL");
        pid = getpid();
        if( !SSL_CTX_set_session_id_context(ctx, (void*)&pid, sizeof pid) )
                perror("SSL_CTX_set_session_id_context");
        
if (!SSL_CTX_use_certificate_file(ctx, "certs/server-cert.pem", SSL_FILETYPE_PEM))
                printf("\nERROR: no certificate found!");
        
if (!SSL_CTX_use_PrivateKey_file(ctx, "certs/server-key.pem", SSL_FILETYPE_PEM))
                printf("\nERROR: no private key found!");
        
        if (!SSL_CTX_check_private_key (ctx))
                printf("\nERROR: invalid private key!");
        
        /* Client has to authenticate */
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, dtls_verify_callback);
        
        SSL_CTX_set_read_ahead(ctx, 1);
        SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie);
        SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie);
        
... (create listening socket) ...

        while (1) {
            memset(&client_addr, 0, sizeof(struct sockaddr));

                /* Create BIO */
                bio = BIO_new_dgram(fd, BIO_NOCLOSE);

                /* Set and activate timeouts */
                timeout.tv_sec = 5;
                timeout.tv_usec = 0;
                BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);

                ssl = SSL_new(ctx);

                SSL_set_bio(ssl, bio, bio);
                SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
                
                while (!DTLSv1_listen(ssl, &client_addr));

                info = (struct pass_info*) malloc (sizeof(struct pass_info));
                memcpy(&info->server_addr, &server_addr, sizeof(struct 
sockaddr));
                memcpy(&info->client_addr, &client_addr, sizeof(struct 
sockaddr));
                info->ssl = ssl;

                if (pthread_create( &tid, NULL, connection_handle, info) != 0) {
                        perror("pthread_create");
                        exit(1);
                }
                ERR_remove_state(0);
        }
        
        THREAD_cleanup();
}


The function connection_handle is called when DTLSv1_listen() returned and therefore a new connection is about to be established. The SSL object is passed and the handshake finished before data transmission begins.

void* connection_handle(void *info) {

... (variables) ...

        pthread_detach(pthread_self());

... (created connected socket) ...

        /* Set new fd and set BIO to connected */
        BIO_set_fd(SSL_get_rbio(ssl), fd, BIO_NOCLOSE);
BIO_ctrl(SSL_get_rbio(ssl), BIO_CTRL_DGRAM_SET_CONNECTED, 0, client_addr);

        /* Finish handshake */
        if(SSL_accept(ssl) <= 0) {
                perror("SSL_accept");
                goto cleanup;
        }
        
... (read and write until client disconnects) ...
        
        SSL_shutdown(ssl);

cleanup:
        close(fd);
        free(info);
        SSL_free(ssl);
        ERR_remove_state(0);
        pthread_exit( (void *) NULL );
}

Any suggestions where I forgot any free or threading function? I also read about a built-in memory leak detection in OpenSSL but didn't find anything in the documentation. Since it might help, how do I use that? When I use a shell script which continously starts a client which connects, sends some messages and disconnects, the server is working fine but constantly allocats memory which is never freed. Since the client initiates the shutdown, there is no problem with an unfinished shutdown process. The server's SSL_shutdown() always returns 1.

Regards,
Robin
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to