diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2005-12-17 02:25:58 +0100 |
---|---|---|
committer | Jelmer Vernooij <jelmer@samba.org> | 2005-12-17 02:25:58 +0100 |
commit | 643dfc4be2e84dc4acb1a446867705e150480210 (patch) | |
tree | 90fe517fcac9490972f64b8cd99ec2f658c71359 /protocols/ssl_gnutls.c | |
parent | 4146a07de5f44f3ea00a3ef0026098b28e7451de (diff) | |
parent | 32c632fb46e58043a2d437c44cad783a59b7aea9 (diff) |
Merge integration
Diffstat (limited to 'protocols/ssl_gnutls.c')
-rw-r--r-- | protocols/ssl_gnutls.c | 81 |
1 files changed, 65 insertions, 16 deletions
diff --git a/protocols/ssl_gnutls.c b/protocols/ssl_gnutls.c index 535d126e..c2eb6906 100644 --- a/protocols/ssl_gnutls.c +++ b/protocols/ssl_gnutls.c @@ -24,11 +24,15 @@ */ #include <gnutls/gnutls.h> +#include <fcntl.h> +#include <unistd.h> #include "proxy.h" #include "ssl_client.h" #include "sock.h" #include "stdlib.h" +int ssl_errno = 0; + static gboolean initialized = FALSE; struct scd @@ -37,6 +41,7 @@ struct scd gpointer data; int fd; gboolean established; + int inpa; gnutls_session session; gnutls_certificate_credentials xcred; @@ -45,7 +50,6 @@ struct scd static void ssl_connected( gpointer data, gint source, GaimInputCondition cond ); - void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data ) { struct scd *conn = g_new0( struct scd, 1 ); @@ -53,6 +57,7 @@ void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data ) conn->fd = proxy_connect( host, port, ssl_connected, conn ); conn->func = func; conn->data = data; + conn->inpa = -1; if( conn->fd < 0 ) { @@ -75,43 +80,87 @@ void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data ) return( conn ); } +static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond ); + static void ssl_connected( gpointer data, gint source, GaimInputCondition cond ) { struct scd *conn = data; if( source == -1 ) - goto ssl_connected_failure; + { + conn->func( conn->data, NULL, cond ); + + gnutls_deinit( conn->session ); + gnutls_certificate_free_credentials( conn->xcred ); + + g_free( conn ); + + return; + } + sock_make_nonblocking( conn->fd ); gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr) conn->fd ); - if( gnutls_handshake( conn->session ) < 0 ) - goto ssl_connected_failure; - - conn->established = TRUE; - conn->func( conn->data, conn, cond ); - return; + ssl_handshake( data, source, cond ); +} + +static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond ) +{ + struct scd *conn = data; + int st; -ssl_connected_failure: - conn->func( conn->data, NULL, cond ); + if( conn->inpa != -1 ) + gaim_input_remove( conn->inpa ); - gnutls_deinit( conn->session ); - gnutls_certificate_free_credentials( conn->xcred ); - if( source >= 0 ) closesocket( source ); - g_free( conn ); + if( ( st = gnutls_handshake( conn->session ) ) < 0 ) + { + if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED ) + { + conn->inpa = gaim_input_add( conn->fd, + gnutls_record_get_direction( conn->session ) ? + GAIM_INPUT_WRITE : GAIM_INPUT_READ, + ssl_handshake, data ); + } + else + { + conn->func( conn->data, NULL, cond ); + + gnutls_deinit( conn->session ); + gnutls_certificate_free_credentials( conn->xcred ); + closesocket( conn->fd ); + + g_free( conn ); + } + } + else + { + /* For now we can't handle non-blocking perfectly everywhere... */ + sock_make_blocking( conn->fd ); + + conn->established = TRUE; + conn->func( conn->data, conn, cond ); + } } int ssl_read( void *conn, char *buf, int len ) { if( !((struct scd*)conn)->established ) - return( 0 ); + { + ssl_errno = SSL_NOHANDSHAKE; + return( -1 ); + } return( gnutls_record_recv( ((struct scd*)conn)->session, buf, len ) ); + } int ssl_write( void *conn, const char *buf, int len ) { if( !((struct scd*)conn)->established ) - return( 0 ); + { + ssl_errno = SSL_NOHANDSHAKE; + return( -1 ); + } return( gnutls_record_send( ((struct scd*)conn)->session, buf, len ) ); } |