diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/ssl_gnutls.c | 52 | 
1 files changed, 50 insertions, 2 deletions
| diff --git a/lib/ssl_gnutls.c b/lib/ssl_gnutls.c index 8c502969..b698e630 100644 --- a/lib/ssl_gnutls.c +++ b/lib/ssl_gnutls.c @@ -1,7 +1,7 @@    /********************************************************************\    * BitlBee -- An IRC to other IM-networks gateway                     *    *                                                                    * -  * Copyright 2002-2011 Wilmer van der Gaast and others                * +  * Copyright 2002-2012 Wilmer van der Gaast and others                *    \********************************************************************/  /* SSL module - GnuTLS version                                          */ @@ -62,6 +62,8 @@ struct scd  	gnutls_session_t session;  }; +static GHashTable *session_cache; +  static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond );  static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond );  static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ); @@ -96,6 +98,8 @@ void ssl_init( void )  	gnutls_global_set_log_level( 3 );  	*/ +	session_cache = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, g_free ); +	  	atexit( ssl_deinit );  } @@ -103,6 +107,8 @@ static void ssl_deinit( void )  {  	gnutls_global_deinit();  	gnutls_certificate_free_credentials( xcred ); +	g_hash_table_destroy( session_cache ); +	session_cache = NULL;  }  void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data ) @@ -221,6 +227,45 @@ static int verify_certificate_callback( gnutls_session_t session )  	return verifyret;  } +struct ssl_session +{ +	size_t size; +	char data[]; +}; + +static void ssl_cache_add( struct scd *conn ) +{ +	size_t data_size; +	struct ssl_session *data; +	char *hostname; +	 +	if( !conn->hostname ||  +	    gnutls_session_get_data( conn->session, NULL, &data_size ) != 0 ) +		return; +	 +	data = g_malloc( sizeof( struct ssl_session ) + data_size ); +	if( gnutls_session_get_data( conn->session, data->data, &data->size ) != 0 ) +	{ +		g_free( data ); +		return; +	} +	 +	hostname = g_strdup( conn->hostname ); +	g_hash_table_insert( session_cache, hostname, data ); +} + +static void ssl_cache_resume( struct scd *conn ) +{ +	struct ssl_session *data; +	 +	if( conn->hostname && +	    ( data = g_hash_table_lookup( session_cache, conn->hostname ) ) ) +	{ +		gnutls_session_set_data( conn->session, data->data, data->size ); +		g_hash_table_remove( session_cache, conn->hostname ); +	} +} +  char *ssl_verify_strerror( int code )  {  	GString *ret = g_string_new( "" ); @@ -279,6 +324,8 @@ static gboolean ssl_connected( gpointer data, gint source, b_input_condition con  	sock_make_nonblocking( conn->fd );  	gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr_t) GNUTLS_STUPID_CAST conn->fd ); +	ssl_cache_resume( conn ); +	  	return ssl_handshake( data, source, cond );  } @@ -319,7 +366,8 @@ static gboolean ssl_handshake( gpointer data, gint source, b_input_condition con  		{  			/* For now we can't handle non-blocking perfectly everywhere... */  			sock_make_blocking( conn->fd ); -		 +			 +			ssl_cache_add( conn );  			conn->established = TRUE;  			conn->func( conn->data, 0, conn, cond );  		} | 
