Commit 6186fac9 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Fix handshaking on non-blocking sockets

parent 551ad114
...@@ -74,10 +74,15 @@ typedef struct tls_server_sys_t ...@@ -74,10 +74,15 @@ typedef struct tls_server_sys_t
} tls_server_sys_t; } tls_server_sys_t;
/* client-side session private data */ typedef struct tls_session_sys_t
{
gnutls_session session;
} tls_session_sys_t;
typedef struct tls_client_sys_t typedef struct tls_client_sys_t
{ {
gnutls_session session; struct tls_session_sys_t session;
gnutls_certificate_credentials x509_cred; gnutls_certificate_credentials x509_cred;
} tls_client_sys_t; } tls_client_sys_t;
...@@ -91,9 +96,12 @@ static int ...@@ -91,9 +96,12 @@ static int
gnutls_Send( void *p_session, const void *buf, int i_length ) gnutls_Send( void *p_session, const void *buf, int i_length )
{ {
int val; int val;
tls_session_sys_t *p_sys;
val = gnutls_record_send( *(gnutls_session *)(((tls_session_t *)p_session) p_sys = (tls_session_sys_t *)(((tls_session_t *)p_session)->p_sys);
->p_sys), buf, i_length );
val = gnutls_record_send( p_sys->session, buf, i_length );
/* TODO: handle fatal error */
return val < 0 ? -1 : val; return val < 0 ? -1 : val;
} }
...@@ -107,9 +115,12 @@ static int ...@@ -107,9 +115,12 @@ static int
gnutls_Recv( void *p_session, void *buf, int i_length ) gnutls_Recv( void *p_session, void *buf, int i_length )
{ {
int val; int val;
tls_session_sys_t *p_sys;
p_sys = (tls_session_sys_t *)(((tls_session_t *)p_session)->p_sys);
val = gnutls_record_recv( *(gnutls_session *)(((tls_session_t *)p_session) val = gnutls_record_recv( p_sys->session, buf, i_length );
->p_sys), buf, i_length ); /* TODO: handle fatal error */
return val < 0 ? -1 : val; return val < 0 ? -1 : val;
} }
...@@ -117,29 +128,37 @@ gnutls_Recv( void *p_session, void *buf, int i_length ) ...@@ -117,29 +128,37 @@ gnutls_Recv( void *p_session, void *buf, int i_length )
/***************************************************************************** /*****************************************************************************
* tls_SessionHandshake: * tls_SessionHandshake:
***************************************************************************** *****************************************************************************
* Establishes TLS session with a peer through socket <fd> * Establishes TLS session with a peer through socket <fd>.
* Returns NULL on error (do NOT call tls_SessionClose in case of error or * Returns NULL on error (do NOT call tls_SessionClose in case of error or
* re-use the session structure). * re-use the session structure).
*****************************************************************************/ *****************************************************************************/
static tls_session_t * static tls_session_t *
gnutls_SessionHandshake( tls_session_t *p_session, int fd ) gnutls_SessionHandshake( tls_session_t *p_session, int fd )
{ {
tls_session_sys_t *p_sys;
int val; int val;
gnutls_session *p_sys;
p_sys = (gnutls_session *)(p_session->p_sys); p_sys = (tls_session_sys_t *)(p_session->p_sys);
gnutls_transport_set_ptr (p_sys->session, (gnutls_transport_ptr)fd);
msg_Dbg( p_session->p_tls, "shaking hand..." );
do
/* TODO: handle fatal error */
val = gnutls_handshake( p_sys->session );
while( ( val == GNUTLS_E_AGAIN ) || ( val == GNUTLS_E_INTERRUPTED ) );
gnutls_transport_set_ptr( *p_sys, (gnutls_transport_ptr)fd);
val = gnutls_handshake( *p_sys );
if( val < 0 ) if( val < 0 )
{ {
gnutls_deinit( *p_sys ); gnutls_deinit( p_sys->session );
msg_Err( p_session->p_tls, "TLS handshake failed : %s", msg_Err( p_session->p_tls, "TLS handshake failed : %s",
gnutls_strerror( val ) ); gnutls_strerror( val ) );
free( p_sys ); free( p_sys );
free( p_session ); free( p_session );
return NULL; return NULL;
} }
msg_Dbg( p_session->p_tls, "shaked hand." );
return p_session; return p_session;
} }
...@@ -152,17 +171,17 @@ gnutls_SessionHandshake( tls_session_t *p_session, int fd ) ...@@ -152,17 +171,17 @@ gnutls_SessionHandshake( tls_session_t *p_session, int fd )
static void static void
gnutls_SessionClose( tls_session_t *p_session ) gnutls_SessionClose( tls_session_t *p_session )
{ {
gnutls_session *p_sys; tls_session_sys_t *p_sys;
p_sys = (gnutls_session *)(p_session->p_sys); p_sys = (tls_session_sys_t *)(p_session->p_sys);
/* On the client-side, credentials are re-allocated per session */ /* On the client-side, credentials are re-allocated per session */
if( p_session->p_server == NULL ) if( p_session->p_server == NULL )
gnutls_certificate_free_credentials( ((tls_client_sys_t *)p_sys) gnutls_certificate_free_credentials( ((tls_client_sys_t *)p_sys)
->x509_cred ); ->x509_cred );
gnutls_bye( *p_sys, GNUTLS_SHUT_WR ); gnutls_bye( p_sys->session, GNUTLS_SHUT_WR );
gnutls_deinit( *p_sys ); gnutls_deinit( p_sys->session );
free( p_sys ); free( p_sys );
free( p_session ); free( p_session );
} }
...@@ -213,7 +232,7 @@ gnutls_ClientCreate( tls_t *p_tls, const char *psz_ca_path ) ...@@ -213,7 +232,7 @@ gnutls_ClientCreate( tls_t *p_tls, const char *psz_ca_path )
} }
} }
i_val = gnutls_init( &p_sys->session, GNUTLS_CLIENT ); i_val = gnutls_init( &p_sys->session.session, GNUTLS_CLIENT );
if( i_val != 0 ) if( i_val != 0 )
{ {
msg_Err( p_tls, "Cannot initialize TLS session : %s", msg_Err( p_tls, "Cannot initialize TLS session : %s",
...@@ -223,35 +242,37 @@ gnutls_ClientCreate( tls_t *p_tls, const char *psz_ca_path ) ...@@ -223,35 +242,37 @@ gnutls_ClientCreate( tls_t *p_tls, const char *psz_ca_path )
return NULL; return NULL;
} }
i_val = gnutls_set_default_priority( p_sys->session ); i_val = gnutls_set_default_priority( p_sys->session.session );
if( i_val < 0 ) if( i_val < 0 )
{ {
msg_Err( p_tls, "Cannot set ciphers priorities : %s", msg_Err( p_tls, "Cannot set ciphers priorities : %s",
gnutls_strerror( i_val ) ); gnutls_strerror( i_val ) );
gnutls_deinit( p_sys->session ); gnutls_deinit( p_sys->session.session );
gnutls_certificate_free_credentials( p_sys->x509_cred ); gnutls_certificate_free_credentials( p_sys->x509_cred );
free( p_sys ); free( p_sys );
return NULL; return NULL;
} }
i_val = gnutls_certificate_type_set_priority( p_sys->session, cert_type_priority ); i_val = gnutls_certificate_type_set_priority( p_sys->session.session,
cert_type_priority );
if( i_val < 0 ) if( i_val < 0 )
{ {
msg_Err( p_tls, "Cannot set certificate type priorities : %s", msg_Err( p_tls, "Cannot set certificate type priorities : %s",
gnutls_strerror( i_val ) ); gnutls_strerror( i_val ) );
gnutls_deinit( p_sys->session ); gnutls_deinit( p_sys->session.session );
gnutls_certificate_free_credentials( p_sys->x509_cred ); gnutls_certificate_free_credentials( p_sys->x509_cred );
free( p_sys ); free( p_sys );
return NULL; return NULL;
} }
i_val = gnutls_credentials_set( p_sys->session, GNUTLS_CRD_CERTIFICATE, i_val = gnutls_credentials_set( p_sys->session.session,
GNUTLS_CRD_CERTIFICATE,
p_sys->x509_cred ); p_sys->x509_cred );
if( i_val < 0 ) if( i_val < 0 )
{ {
msg_Err( p_tls, "Cannot set TLS session credentials : %s", msg_Err( p_tls, "Cannot set TLS session credentials : %s",
gnutls_strerror( i_val ) ); gnutls_strerror( i_val ) );
gnutls_deinit( p_sys->session ); gnutls_deinit( p_sys->session.session );
gnutls_certificate_free_credentials( p_sys->x509_cred ); gnutls_certificate_free_credentials( p_sys->x509_cred );
free( p_sys ); free( p_sys );
return NULL; return NULL;
...@@ -260,7 +281,7 @@ gnutls_ClientCreate( tls_t *p_tls, const char *psz_ca_path ) ...@@ -260,7 +281,7 @@ gnutls_ClientCreate( tls_t *p_tls, const char *psz_ca_path )
p_session = malloc( sizeof (struct tls_session_t) ); p_session = malloc( sizeof (struct tls_session_t) );
if( p_session == NULL ) if( p_session == NULL )
{ {
gnutls_deinit( p_sys->session ); gnutls_deinit( p_sys->session.session );
gnutls_certificate_free_credentials( p_sys->x509_cred ); gnutls_certificate_free_credentials( p_sys->x509_cred );
free( p_sys ); free( p_sys );
return NULL; return NULL;
...@@ -288,41 +309,41 @@ static tls_session_t * ...@@ -288,41 +309,41 @@ static tls_session_t *
gnutls_ServerSessionPrepare( tls_server_t *p_server ) gnutls_ServerSessionPrepare( tls_server_t *p_server )
{ {
tls_session_t *p_session; tls_session_t *p_session;
gnutls_session *p_sys; tls_session_sys_t *p_sys;
int val; int i_val;
vlc_value_t bits; vlc_value_t bits;
p_sys = (gnutls_session *)malloc( sizeof(gnutls_session) ); p_sys = (tls_session_sys_t *)malloc( sizeof(struct tls_session_sys_t) );
if( p_sys == NULL ) if( p_sys == NULL )
return NULL; return NULL;
val = gnutls_init( p_sys, GNUTLS_SERVER ); i_val = gnutls_init( &p_sys->session, GNUTLS_SERVER );
if( val != 0 ) if( i_val != 0 )
{ {
msg_Err( p_server->p_tls, "Cannot initialize TLS session : %s", msg_Err( p_server->p_tls, "Cannot initialize TLS session : %s",
gnutls_strerror( val ) ); gnutls_strerror( i_val ) );
free( p_sys ); free( p_sys );
return NULL; return NULL;
} }
val = gnutls_set_default_priority( *p_sys ); i_val = gnutls_set_default_priority( p_sys->session );
if( val < 0 ) if( i_val < 0 )
{ {
msg_Err( p_server->p_tls, "Cannot set ciphers priorities : %s", msg_Err( p_server->p_tls, "Cannot set ciphers priorities : %s",
gnutls_strerror( val ) ); gnutls_strerror( i_val ) );
gnutls_deinit( *p_sys ); gnutls_deinit( p_sys->session );
free( p_sys ); free( p_sys );
return NULL; return NULL;
} }
val = gnutls_credentials_set( *p_sys, GNUTLS_CRD_CERTIFICATE, i_val = gnutls_credentials_set( p_sys->session, GNUTLS_CRD_CERTIFICATE,
((tls_server_sys_t *)(p_server->p_sys)) ((tls_server_sys_t *)(p_server->p_sys))
->x509_cred ); ->x509_cred );
if( val < 0 ) if( i_val < 0 )
{ {
msg_Err( p_server->p_tls, "Cannot set TLS session credentials : %s", msg_Err( p_server->p_tls, "Cannot set TLS session credentials : %s",
gnutls_strerror( val ) ); gnutls_strerror( i_val ) );
gnutls_deinit( *p_sys ); gnutls_deinit( p_sys->session );
free( p_sys ); free( p_sys );
return NULL; return NULL;
} }
...@@ -338,12 +359,12 @@ gnutls_ServerSessionPrepare( tls_server_t *p_server ) ...@@ -338,12 +359,12 @@ gnutls_ServerSessionPrepare( tls_server_t *p_server )
var_Get( p_server->p_tls, "dh-bits", &bits ); var_Get( p_server->p_tls, "dh-bits", &bits );
} }
gnutls_dh_set_prime_bits( *p_sys, bits.i_int ); gnutls_dh_set_prime_bits( p_sys->session, bits.i_int );
p_session = malloc( sizeof (struct tls_session_t) ); p_session = malloc( sizeof (struct tls_session_t) );
if( p_session == NULL ) if( p_session == NULL )
{ {
gnutls_deinit( *p_sys ); gnutls_deinit( p_sys->session );
free( p_sys ); free( p_sys );
return NULL; return NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment