Hi,Nikos
I have reproduced the core dump with the server/client in the attach. If not 
using the memory-leak patch, the core will not happen.

Regards
Tony

From: [email protected]
To: [email protected]
Date: Fri, 23 Oct 2009 14:28:50 +0000
CC: [email protected]; [email protected]
Subject: RE: Memory leaks are observed for libgnutls in multi-thread mode








Hi,Nikos

 

The server is implemented by myself with gnutls2.9.4 and your patch. To make 
investigation easy, I will build a simplified server based on gnutls demo 
server codes and let you know the results later.

 

 

Regards

Tony

 
> Date: Fri, 23 Oct 2009 10:38:20 +0300
> Subject: Re: Memory leaks are observed for libgnutls in multi-thread mode
> From: [email protected]
> To: [email protected]
> CC: [email protected]; [email protected]
> 
> Thanks. However in order to reproduce it I need to know to which
> server you connect to and which options does this server use?
> 
> 2009/10/23 tangtong <[email protected]>:
> > Hi,Nikos
> >
> > The gnutls-cli built by me will core when I enable TLS1.2. I think the code
> > base I use is a little diffent from what you are using. The following is my
> > steps to setup the build enviorment:
> > 1)Download a gnutls releaes package 2.8.3 and decompress it;
> > 2)Download 2.9.4 snap shot and uncompress it to the directory created in the
> > step 1);
> > 3)Run patch you provide.
> >
> > Seems only snapshot of 2.9.4 is not the whole build env, that's why i
> > decompress it to a build enviorment of 2.8.3.
> >
> > Regards
> > Tony
> >
> >
> >
> >
> >
> >
> >
> >
> >> Date: Thu, 22 Oct 2009 19:31:02 +0300
> >> From: [email protected]
> >> To: [email protected]
> >> CC: [email protected]; [email protected]
> >> Subject: Re: Memory leaks are observed for libgnutls in multi-thread mode
> >>
> >> tangtong wrote:
> >> > Hi,Nikos
> >>
> >> > 2)The patch doesn't support
> >> > "NONE:+VERS-TLS1.2:+AES-256-CBC:+RSA:+SHA256:+COMP-NULL", I t! hink your
> >> > patch disable the tls1.2 support, it will core with the following dump
> >> > info:
> >> > fe9a2bb8 _gcry_md_copy (ffbff33c, 0, 0, febc6ed0, 14f8, fed3805c) + 4
> >> > feca8dfc _gnutls_hash_copy (ffbff338, 365c4, 0, 0, 0, 0) + 80
> >> > fec9e0fc _gnutls_finished (36180, 2, ffbff440, 1, 6, 0) + 84
> >> > fec9edc0 _gnutls_send_handshake_final (0, 0, 0, e, e, 4) + 128
> >> > feca2548 _gnutls_handshake_common (36180, 0, 10, 4, ffffffe0, ffbff551)
> >> > + 30
> >> > feca382c gnutls_handshake (0, 4, 32fc8, 8e8, 17ac, ffbff5c4) + 60
> >> > 000119bc main (1, ffbffa54, ffbffa5c, 22508, 0, 0) + 118
> >> > 000112c8 _start (0, 0, 0, 0, 0, 0) + 5c
> >>
> >> Can you send me information on how I can reproduce this issue? I can use
> >> ./gnutls-cli tls.secg.org --priority
> >> "NONE:+VERS-TLS1.2:+AES-128-CBC:+RSA:+DHE-DSS:+SHA256:+COMP-NULL" to
> >> connect using TLS1.2 without any issues.>
> >> regards,
> >> Nikos
> >
> > ________________________________
> > 全新 Windows 7:寻找最适合您的 PC。 了解详情。
                                          
Messenger保护盾2.0,更安全可靠的Messenger聊天! 现在就下载!                                       
  
_________________________________________________________________
MSN十周年庆典,查看MSN注册时间,赢取神秘大奖
http://10.msn.com.cn
// demo0.cpp : Defines the entry point for the console application.
//

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdexcept>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <inttypes.h>
#include <fcntl.h>
#include <errno.h>
#include <poll.h>
#include <string.h>
#include <unistd.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <gcrypt.h>

#define SA struct sockaddr
#define SOCKET_ERR(err,s) if(err==-1) {perror(s);return(1);}
#define MAX_BUF 1024
#define PORT 5556


void DisplayError(); 


#define CERT_FILE "ttcert.pem"
#define KEY_FILE "ttkey.pem"
#define CAFILE "ca.pem"


gnutls_certificate_credentials_t x509_cred;
gnutls_x509_crt_t crt;
gnutls_x509_privkey_t key;

static gnutls_datum_t load_file (const char *file)
{
FILE *f;
gnutls_datum_t loaded_file = { NULL, 0 };
long filelen;
void *ptr;
if (!(f = fopen (file, "r"))
|| fseek (f, 0, SEEK_END) != 0
|| (filelen = ftell (f)) < 0
|| fseek (f, 0, SEEK_SET) != 0
|| !(ptr = malloc ((size_t) filelen))
|| fread (ptr, 1, (size_t) filelen, f) < (size_t) filelen)
{
return loaded_file;
}
loaded_file.data = (unsigned char*)ptr;
loaded_file.size = (unsigned int) filelen;
return loaded_file;
}
static void
unload_file (gnutls_datum_t data)
{
free (data.data);
}

static void load_keys()
{
int ret;
gnutls_datum_t data;
data = load_file (CERT_FILE);
if (data.data == NULL)
{
fprintf (stderr, "*** Error loading cert file.\n");
return;
}
gnutls_x509_crt_init (&crt);
ret = gnutls_x509_crt_import (crt, &data, GNUTLS_X509_FMT_PEM);
if (ret < 0)
{
fprintf (stderr, "*** Error loading key file: %s\n",
gnutls_strerror (ret));
return;
}
unload_file (data);
data = load_file (KEY_FILE);
if (data.data == NULL)
{
fprintf (stderr, "*** Error loading key file.\n");
return;
}
gnutls_x509_privkey_init (&key);
/*ret = gnutls_x509_privkey_import (key, &data, GNUTLS_X509_FMT_PEM);
if (ret < 0)
{
fprintf (stderr, "*** Error loading key file: %s\n",
gnutls_strerror (ret));
}*/
ret =gnutls_x509_privkey_import_pkcs8(key,&data,GNUTLS_X509_FMT_PEM,"moto",0);
if (ret < 0)
{
fprintf (stderr, "*** Error loading key file: %s\n",
gnutls_strerror (ret));
}

unload_file (data);
}
gnutls_datum_t cacheItem; 
int db_store_func(void *, gnutls_datum_t key,
                                       gnutls_datum_t data)
{
  cacheItem.size = data.size;
  cacheItem.data = (unsigned char*)malloc ((size_t) data.size);
  memcpy(cacheItem.data,data.data,data.size);
  return 0;     
}       

gnutls_datum_t db_retr_func(void *, gnutls_datum_t key)
{
  gnutls_datum_t result = { NULL, 0 };
  result = cacheItem;
  return cacheItem;     
}
int db_remove_func(void *, gnutls_datum_t key)
{
  return 0;     
}

ssize_t pullFunc(gnutls_transport_ptr_t sock, void* buffer ,size_t size)
{
  int ret = read((int)sock, (char*)buffer, size);
  return ret;           
}
ssize_t pushFunc(gnutls_transport_ptr_t sock,const void* buffer, size_t size)
{
  int ret = write((int)sock, (char*)buffer, size);
  return ret;           
}


                               
gnutls_priority_t priority_cache;
static gnutls_session_t initialize_tls_session (void)
{
gnutls_session_t session;
gnutls_init (&session, GNUTLS_SERVER);
gnutls_priority_set (session, priority_cache);
gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509_cred);
// gnutls_db_set_store_function(session,db_store_func);
// gnutls_db_set_retrieve_function(session,db_retr_func);
// gnutls_db_set_remove_function(session,db_remove_func);


/* request client certificate if any.
*/
//gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST);
/* Set maximum compatibility mode. This is only suggested on public webservers
* that need to trade security for compatibility
*/
//gnutls_session_enable_compatibility_mode (session);

gnutls_transport_set_pull_function(session,pullFunc);
gnutls_transport_set_push_function(session,pushFunc);
return session;
}

void print_info (gnutls_session_t session)
{
const char *tmp;
gnutls_credentials_type_t cred;
gnutls_kx_algorithm_t kx;
/* print the key exchange¡¯s algorithm name
*/
kx = gnutls_kx_get (session);
tmp = gnutls_kx_get_name (kx);
printf ("- Key Exchange: %s\n", tmp);
/* Check the authentication type used and switch
* to the appropriate.
*/
cred = gnutls_auth_get_type (session);
switch (cred)
{
case GNUTLS_CRD_IA:
printf ("- TLS/IA session\n");
break;
#ifdef ENABLE_SRP
case GNUTLS_CRD_SRP:
printf ("- SRP session with username %s\n",
gnutls_srp_server_get_username (session));
break;
#endif
case GNUTLS_CRD_PSK:
/* This returns NULL in server side.
*/
if (gnutls_psk_client_get_hint (session) != NULL)
printf ("- PSK authentication. PSK hint ¡¯%s¡¯\n",
gnutls_psk_client_get_hint (session));
/* This returns NULL in client side.
*/
if (gnutls_psk_server_get_username (session) != NULL)
printf ("- PSK authentication. Connected as ¡¯%s¡¯\n",
gnutls_psk_server_get_username (session));
break;
case GNUTLS_CRD_ANON: /* anonymous authentication */
printf ("- Anonymous DH using prime of %d bits\n",
gnutls_dh_get_prime_bits (session));
break;
case GNUTLS_CRD_CERTIFICATE: /* certificate authentication */
/* Check if we have been using ephemeral Diffie-Hellman.
*/
if (kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS)
{
printf ("\n- Ephemeral DH using prime of %d bits\n",
gnutls_dh_get_prime_bits (session));
}
/* if the certificate list is available, then
* print some information about it.
*/
//print_x509_certificate_info (session);
} /* switch */
/* print the protocol¡¯s name (ie TLS 1.0)
*/
tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session));
printf ("- Protocol: %s\n", tmp);
/* print the certificate type of the peer.
* ie X.509
*/
tmp =
gnutls_certificate_type_get_name (gnutls_certificate_type_get (session));
printf ("- Certificate Type: %s\n", tmp);
/* print the compression algorithm (if any)
*/
tmp = gnutls_compression_get_name (gnutls_compression_get (session));
printf ("- Compression: %s\n", tmp);
/* print the name of the cipher used.
* ie 3DES.
*/
tmp = gnutls_cipher_get_name (gnutls_cipher_get (session));
printf ("- Cipher: %s\n", tmp);
/* Print the MAC algorithms name.
* ie SHA1
*/
tmp = gnutls_mac_get_name (gnutls_mac_get (session));
printf ("- MAC: %s\n", tmp);
return;
}

int main(int argc, char* argv[])
{
        int err, listen_sd;
        int sd, ret;
        struct sockaddr_in sa_serv;
        struct sockaddr_in sa_cli;
        int client_len;
        char topbuf[512];
        char buffer[MAX_BUF + 1];
        int optval = 1;
        gnutls_session_t session;
        struct pollfd client;
        bool handshake;

        gnutls_global_init ();
        
        
        gnutls_certificate_allocate_credentials (&x509_cred);
        load_keys();
        ret = gnutls_certificate_set_x509_key(x509_cred,&crt,1,key);
        
        gnutls_priority_init (&priority_cache, "NORMAL:+VERS-TLS1.2", NULL);
        
        if(ret <0)
        {
           fprintf (stderr, "*** Error loading key file: %s\n",
           gnutls_strerror (ret));
        }
        /* Socket operations
        */
        listen_sd = socket (AF_INET, SOCK_STREAM, 0);
        SOCKET_ERR (listen_sd, "socket");
        memset (&sa_serv,0 , sizeof (sa_serv));
        sa_serv.sin_family = AF_INET;
        sa_serv.sin_addr.s_addr = INADDR_ANY;
        sa_serv.sin_port = htons (PORT); /* Server Port number */
        setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval, 
sizeof (int));
        err = bind (listen_sd, (SA *) & sa_serv, sizeof (sa_serv));
        SOCKET_ERR (err, "bind");
        err = listen (listen_sd, 1024);
        SOCKET_ERR (err, "listen");
        printf ("Server ready. Listening to port %d.\n\n", PORT);
        client_len = sizeof (sa_cli);
        while(1)
        {
                char* t = new char[100];
                session = initialize_tls_session ();
                handshake = true;
                //gnutls_transport_set_pull_function(session,pullFunc);
                sd = accept (listen_sd, (SA *)& sa_cli, 
(socklen_t*)&client_len);
                printf ("- connection from %s, port %d\n",
                inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf,sizeof (topbuf)), 
ntohs (sa_cli.sin_port));
                gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
                //int flags = fcntl(sd, F_GETFL, 0);
                //fcntl(sd, F_SETFL, flags | O_NONBLOCK);
                client.fd = sd;
                client.events = POLLRDNORM;

                while(1)
                {
                  ret = poll(&client,1,-1);
                  if(ret > 0)
                  {
                    if(handshake)
                    {   
                        ret = gnutls_handshake (session);
                        if (ret < 0 && gnutls_error_is_fatal (ret))
                        {
                                fprintf (stderr, "*** Handshake has failed 
(%s)\n\n",gnutls_strerror (ret));
                                break;
                        }
                        else if(ret <0)
                        {
                          printf("non-fatal error(%s), go 
on...\n",gnutls_strerror (ret));      
                        }
                        else
                        {
                          printf ("- Handshake was completed\n");
                          print_info(session);
                          handshake = false;
                        }
                     }
                     else
                     {
                        memset (buffer, 0, MAX_BUF + 1);
                        ret = gnutls_record_recv (session, buffer, MAX_BUF);
                        if (ret == 0)
                        {
                                printf ("\n- Peer has closed the GNUTLS 
connection\n");
                                break;
                        }
                        else if (ret < 0)
                        {
                                fprintf (stderr, "\n*** Received corrupted 
data(%d). Closing the connection.\n", ret);
                                break;
                        }
                        else if (ret > 0)
                        {
                                printf("data received, %d %s\n",ret,buffer); 
                                gnutls_record_send (session, buffer, strlen 
(buffer));
                        }
                                
                     }    
                   }
                   else
                   {
                        printf("Socket abnormal situation...\n");
                   }
                } 
                printf("close session and socket\n");
                gnutls_bye (session, GNUTLS_SHUT_RDWR);
                close(sd);
                gnutls_deinit (session);
        }
        close(listen_sd);
        gnutls_certificate_free_credentials(x509_cred);
        gnutls_priority_deinit(priority_cache);
        gnutls_global_deinit();
        printf("end of test!\n");
        while(1)
        {
           sleep(10);   
        }
        return 0;
}



// demo0.cpp : Defines the entry point for the console application.
//

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdexcept>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <inttypes.h>
#include <fcntl.h>
#include <errno.h>
#include <poll.h>
#include <string.h>
#include <unistd.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <gcrypt.h>

#define SA struct sockaddr
#define SOCKET_ERR(err,s) if(err==-1) {perror(s);return(1);}
#define MAX_BUF 1024
#define SERVER "200.61.250.16"
#define PORT 5556 
#define MSG "GET / HTTP/1.0\r\n\r\n"

void DisplayError(); 


#define CAFILE "ttcert.pem"


gnutls_certificate_credentials_t x509_cred;
gnutls_x509_crt_t crt;
gnutls_x509_privkey_t key;

int buildClientSocket(const char* szIpAddress_,int nPort_)
{
    struct sockaddr_in sin;     
    int addr;

    memset(&sin, 0, sizeof(sin));    

    sin.sin_family = AF_INET;    
        addr = inet_addr(szIpAddress_);
        if (addr == -1 )        
        {            
            return -1;//invalid ip address
        }        
        else        
        {               
            sin.sin_addr.s_addr = addr;        
        }            
    
    sin.sin_port = htons((u_short)nPort_);

        int fd = socket(AF_INET, SOCK_STREAM, 0);  
        if (fd < 0) {
        return -1;
    }

    /* Connect the socket to other module*/
        if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
                close(fd);
                return -1;
    }
        return fd;       
}


gnutls_priority_t priority_cache;
static gnutls_session_t initialize_tls_session (void)
{
gnutls_session_t session;
gnutls_init (&session, GNUTLS_SERVER);
gnutls_priority_set (session, priority_cache);
gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509_cred);
/* request client certificate if any.
*/
gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST);
/* Set maximum compatibility mode. This is only suggested on public webservers
* that need to trade security for compatibility
*/
gnutls_session_enable_compatibility_mode (session);
return session;
}

void print_info (gnutls_session_t session)
{
const char *tmp;
gnutls_credentials_type_t cred;
gnutls_kx_algorithm_t kx;
/* print the key exchange¡¯s algorithm name
*/
kx = gnutls_kx_get (session);
tmp = gnutls_kx_get_name (kx);
printf ("- Key Exchange: %s\n", tmp);
/* Check the authentication type used and switch
* to the appropriate.
*/
cred = gnutls_auth_get_type (session);
switch (cred)
{
case GNUTLS_CRD_IA:
printf ("- TLS/IA session\n");
break;
#ifdef ENABLE_SRP
case GNUTLS_CRD_SRP:
printf ("- SRP session with username %s\n",
gnutls_srp_server_get_username (session));
break;
#endif
case GNUTLS_CRD_PSK:
/* This returns NULL in server side.
*/
if (gnutls_psk_client_get_hint (session) != NULL)
printf ("- PSK authentication. PSK hint ¡¯%s¡¯\n",
gnutls_psk_client_get_hint (session));
/* This returns NULL in client side.
*/
if (gnutls_psk_server_get_username (session) != NULL)
printf ("- PSK authentication. Connected as ¡¯%s¡¯\n",
gnutls_psk_server_get_username (session));
break;
case GNUTLS_CRD_ANON: /* anonymous authentication */
printf ("- Anonymous DH using prime of %d bits\n",
gnutls_dh_get_prime_bits (session));
break;
case GNUTLS_CRD_CERTIFICATE: /* certificate authentication */
/* Check if we have been using ephemeral Diffie-Hellman.
*/
if (kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS)
{
printf ("\n- Ephemeral DH using prime of %d bits\n",
gnutls_dh_get_prime_bits (session));
}
/* if the certificate list is available, then
* print some information about it.
*/
//print_x509_certificate_info (session);
} /* switch */
/* print the protocol¡¯s name (ie TLS 1.0)
*/
tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session));
printf ("- Protocol: %s\n", tmp);
/* print the certificate type of the peer.
* ie X.509
*/
tmp =
gnutls_certificate_type_get_name (gnutls_certificate_type_get (session));
printf ("- Certificate Type: %s\n", tmp);
/* print the compression algorithm (if any)
*/
tmp = gnutls_compression_get_name (gnutls_compression_get (session));
printf ("- Compression: %s\n", tmp);
/* print the name of the cipher used.
* ie 3DES.
*/
tmp = gnutls_cipher_get_name (gnutls_cipher_get (session));
printf ("- Cipher: %s\n", tmp);
/* Print the MAC algorithms name.
* ie SHA1
*/
tmp = gnutls_mac_get_name (gnutls_mac_get (session));
printf ("- MAC: %s\n", tmp);
return;
}


int main(int argc, char* argv[])
{
        int ret, sd, ii;
        gnutls_session_t session;
        char buffer[MAX_BUF + 1];
        const char *err;
        gnutls_certificate_credentials_t xcred;
        
        gnutls_global_init ();
        
        gnutls_certificate_allocate_credentials (&xcred);
        gnutls_certificate_set_x509_trust_file (xcred, CAFILE, 
GNUTLS_X509_FMT_PEM);

    for(int i=0;i<1;i++)
    {
        gnutls_init (&session, GNUTLS_CLIENT);
        
        ret = gnutls_priority_set_direct (session, 
"NONE:+VERS-TLS1.2:+AES-256-CBC:+RSA:+SHA256:+COMP-NULL", &err);
        //ret = gnutls_priority_set_direct (session, "NORMAL", &err);
        if (ret < 0)
        {
                if (ret == GNUTLS_E_INVALID_REQUEST)
                {
                        fprintf (stderr, "Syntax error at: %s\n", err);
                }
                exit (1);
        }
        gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred);
        sd = buildClientSocket(SERVER,PORT);
        gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
        ret = gnutls_handshake (session);
        if (ret < 0)
        {
                fprintf (stderr, "*** Handshake failed\n");
                gnutls_perror (ret);
                goto end;
        }       
        else
        {
                printf ("- Handshake was completed\n");
                print_info(session);
        }
        gnutls_record_send (session, MSG, strlen (MSG));
        ret = gnutls_record_recv (session, buffer, MAX_BUF);
        if (ret == 0)
        {
                printf ("- Peer has closed the TLS connection\n");
                goto end;
        }
        else if (ret < 0)
        {
                fprintf (stderr, "*** Error: %s\n", gnutls_strerror (ret));
                goto end;
        }
        printf ("- Received %d bytes: ",ret);
        for (ii = 0; ii < ret; ii++)
        {
                fputc (buffer[ii], stdout);
        }
        gnutls_bye (session, GNUTLS_SHUT_RDWR); 
end:
        close(sd);
        gnutls_deinit (session);
     }
     printf("end of test!\n");
     gnutls_certificate_free_credentials (xcred);
     gnutls_global_deinit ();   
     return 0;
}

_______________________________________________
Help-gnutls mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/help-gnutls

Reply via email to