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