aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl_openssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl_openssl.c')
-rw-r--r--lib/ssl_openssl.c281
1 files changed, 144 insertions, 137 deletions
diff --git a/lib/ssl_openssl.c b/lib/ssl_openssl.c
index 63937380..c286d509 100644
--- a/lib/ssl_openssl.c
+++ b/lib/ssl_openssl.c
@@ -1,4 +1,4 @@
- /********************************************************************\
+/********************************************************************\
* BitlBee -- An IRC to other IM-networks gateway *
* *
* Copyright 2002-2012 Wilmer van der Gaast and others *
@@ -39,263 +39,270 @@ int ssl_errno = 0;
static gboolean initialized = FALSE;
-struct scd
-{
+struct scd {
ssl_input_function func;
gpointer data;
int fd;
gboolean established;
gboolean verify;
char *hostname;
-
+
int inpa;
- int lasterr; /* Necessary for SSL_get_error */
+ int lasterr; /* Necessary for SSL_get_error */
SSL *ssl;
};
static SSL_CTX *ssl_ctx;
-static void ssl_conn_free( struct scd *conn );
-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 );
+static void ssl_conn_free(struct scd *conn);
+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);
-void ssl_init( void )
+void ssl_init(void)
{
const SSL_METHOD *meth;
-
+
SSL_library_init();
-
+
meth = TLSv1_client_method();
- ssl_ctx = SSL_CTX_new( meth );
-
+ ssl_ctx = SSL_CTX_new(meth);
+
initialized = TRUE;
}
-void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data )
+void *ssl_connect(char *host, int port, gboolean verify, ssl_input_function func, gpointer data)
{
- struct scd *conn = g_new0( struct scd, 1 );
-
- conn->fd = proxy_connect( host, port, ssl_connected, conn );
- if( conn->fd < 0 )
- {
- ssl_conn_free( conn );
+ struct scd *conn = g_new0(struct scd, 1);
+
+ conn->fd = proxy_connect(host, port, ssl_connected, conn);
+ if (conn->fd < 0) {
+ ssl_conn_free(conn);
return NULL;
}
-
+
conn->func = func;
conn->data = data;
conn->inpa = -1;
- conn->hostname = g_strdup( host );
-
+ conn->hostname = g_strdup(host);
+
return conn;
}
-void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data )
+void *ssl_starttls(int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data)
{
- struct scd *conn = g_new0( struct scd, 1 );
-
+ struct scd *conn = g_new0(struct scd, 1);
+
conn->fd = fd;
conn->func = func;
conn->data = data;
conn->inpa = -1;
conn->verify = verify && global.conf->cafile;
- conn->hostname = g_strdup( hostname );
-
+ conn->hostname = g_strdup(hostname);
+
/* This function should be called via a (short) timeout instead of
directly from here, because these SSL calls are *supposed* to be
*completely* asynchronous and not ready yet when this function
(or *_connect, for examle) returns. Also, errors are reported via
the callback function, not via this function's return value.
-
+
In short, doing things like this makes the rest of the code a lot
simpler. */
-
- b_timeout_add( 1, ssl_starttls_real, conn );
-
+
+ b_timeout_add(1, ssl_starttls_real, conn);
+
return conn;
}
-static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond )
+static gboolean ssl_starttls_real(gpointer data, gint source, b_input_condition cond)
{
struct scd *conn = data;
-
- return ssl_connected( conn, conn->fd, B_EV_IO_WRITE );
+
+ return ssl_connected(conn, conn->fd, B_EV_IO_WRITE);
}
-static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
+static gboolean ssl_connected(gpointer data, gint source, b_input_condition cond)
{
struct scd *conn = data;
-
- if( conn->verify )
- {
+
+ if (conn->verify) {
/* Right now we don't have any verification functionality for OpenSSL. */
- conn->func( conn->data, 1, NULL, cond );
- if( source >= 0 ) closesocket( source );
- ssl_conn_free( conn );
+ conn->func(conn->data, 1, NULL, cond);
+ if (source >= 0) {
+ closesocket(source);
+ }
+ ssl_conn_free(conn);
return FALSE;
}
- if( source == -1 )
+ if (source == -1) {
goto ssl_connected_failure;
-
- if( !initialized )
- {
+ }
+
+ if (!initialized) {
ssl_init();
}
-
-
- if( ssl_ctx == NULL )
+
+
+ if (ssl_ctx == NULL) {
goto ssl_connected_failure;
-
- conn->ssl = SSL_new( ssl_ctx );
- if( conn->ssl == NULL )
+ }
+
+ conn->ssl = SSL_new(ssl_ctx);
+ if (conn->ssl == NULL) {
goto ssl_connected_failure;
-
+ }
+
/* We can do at least the handshake with non-blocking I/O */
- sock_make_nonblocking( conn->fd );
- SSL_set_fd( conn->ssl, conn->fd );
-
- if( conn->hostname && !g_ascii_isdigit( conn->hostname[0] ) )
- SSL_set_tlsext_host_name( conn->ssl, conn->hostname );
-
- return ssl_handshake( data, source, cond );
+ sock_make_nonblocking(conn->fd);
+ SSL_set_fd(conn->ssl, conn->fd);
+
+ if (conn->hostname && !g_ascii_isdigit(conn->hostname[0])) {
+ SSL_set_tlsext_host_name(conn->ssl, conn->hostname);
+ }
+
+ return ssl_handshake(data, source, cond);
ssl_connected_failure:
- conn->func( conn->data, 0, NULL, cond );
- ssl_disconnect( conn );
+ conn->func(conn->data, 0, NULL, cond);
+ ssl_disconnect(conn);
return FALSE;
-}
+}
-static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond )
+static gboolean ssl_handshake(gpointer data, gint source, b_input_condition cond)
{
struct scd *conn = data;
int st;
-
- if( ( st = SSL_connect( conn->ssl ) ) < 0 )
- {
- conn->lasterr = SSL_get_error( conn->ssl, st );
- if( conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE )
- {
- conn->func( conn->data, 0, NULL, cond );
- ssl_disconnect( conn );
+
+ if ((st = SSL_connect(conn->ssl)) < 0) {
+ conn->lasterr = SSL_get_error(conn->ssl, st);
+ if (conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE) {
+ conn->func(conn->data, 0, NULL, cond);
+ ssl_disconnect(conn);
return FALSE;
}
-
- conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ), ssl_handshake, data );
+
+ conn->inpa = b_input_add(conn->fd, ssl_getdirection(conn), ssl_handshake, data);
return FALSE;
}
-
+
conn->established = TRUE;
- sock_make_blocking( conn->fd ); /* For now... */
- conn->func( conn->data, 0, conn, cond );
+ sock_make_blocking(conn->fd); /* For now... */
+ conn->func(conn->data, 0, conn, cond);
return FALSE;
}
-int ssl_read( void *conn, char *buf, int len )
+int ssl_read(void *conn, char *buf, int len)
{
int st;
-
- if( !((struct scd*)conn)->established )
- {
+
+ if (!((struct scd*) conn)->established) {
ssl_errno = SSL_NOHANDSHAKE;
return -1;
}
-
- st = SSL_read( ((struct scd*)conn)->ssl, buf, len );
-
+
+ st = SSL_read(((struct scd*) conn)->ssl, buf, len);
+
ssl_errno = SSL_OK;
- if( st <= 0 )
- {
- ((struct scd*)conn)->lasterr = SSL_get_error( ((struct scd*)conn)->ssl, st );
- if( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE )
+ if (st <= 0) {
+ ((struct scd*) conn)->lasterr = SSL_get_error(((struct scd*) conn)->ssl, st);
+ if (((struct scd*) conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*) conn)->lasterr ==
+ SSL_ERROR_WANT_WRITE) {
ssl_errno = SSL_AGAIN;
+ }
}
-
- if( 0 && getenv( "BITLBEE_DEBUG" ) && st > 0 ) write( 1, buf, st );
-
+
+ if (0 && getenv("BITLBEE_DEBUG") && st > 0) {
+ write(1, buf, st);
+ }
+
return st;
}
-int ssl_write( void *conn, const char *buf, int len )
+int ssl_write(void *conn, const char *buf, int len)
{
int st;
-
- if( !((struct scd*)conn)->established )
- {
+
+ if (!((struct scd*) conn)->established) {
ssl_errno = SSL_NOHANDSHAKE;
return -1;
}
-
- st = SSL_write( ((struct scd*)conn)->ssl, buf, len );
-
- if( 0 && getenv( "BITLBEE_DEBUG" ) && st > 0 ) write( 1, buf, st );
-
+
+ st = SSL_write(((struct scd*) conn)->ssl, buf, len);
+
+ if (0 && getenv("BITLBEE_DEBUG") && st > 0) {
+ write(1, buf, st);
+ }
+
ssl_errno = SSL_OK;
- if( st <= 0 )
- {
- ((struct scd*)conn)->lasterr = SSL_get_error( ((struct scd*)conn)->ssl, st );
- if( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE )
+ if (st <= 0) {
+ ((struct scd*) conn)->lasterr = SSL_get_error(((struct scd*) conn)->ssl, st);
+ if (((struct scd*) conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*) conn)->lasterr ==
+ SSL_ERROR_WANT_WRITE) {
ssl_errno = SSL_AGAIN;
+ }
}
-
+
return st;
}
-int ssl_pending( void *conn )
+int ssl_pending(void *conn)
{
- return ( ((struct scd*)conn) && ((struct scd*)conn)->established ) ?
- SSL_pending( ((struct scd*)conn)->ssl ) > 0 : 0;
+ return (((struct scd*) conn) && ((struct scd*) conn)->established) ?
+ SSL_pending(((struct scd*) conn)->ssl) > 0 : 0;
}
-static void ssl_conn_free( struct scd *conn )
+static void ssl_conn_free(struct scd *conn)
{
- SSL_free( conn->ssl );
- g_free( conn->hostname );
- g_free( conn );
-
+ SSL_free(conn->ssl);
+ g_free(conn->hostname);
+ g_free(conn);
+
}
-void ssl_disconnect( void *conn_ )
+void ssl_disconnect(void *conn_)
{
struct scd *conn = conn_;
-
- if( conn->inpa != -1 )
- b_event_remove( conn->inpa );
-
- if( conn->established )
- SSL_shutdown( conn->ssl );
-
- closesocket( conn->fd );
-
- ssl_conn_free( conn );
+
+ if (conn->inpa != -1) {
+ b_event_remove(conn->inpa);
+ }
+
+ if (conn->established) {
+ SSL_shutdown(conn->ssl);
+ }
+
+ closesocket(conn->fd);
+
+ ssl_conn_free(conn);
}
-int ssl_getfd( void *conn )
+int ssl_getfd(void *conn)
{
- return( ((struct scd*)conn)->fd );
+ return(((struct scd*) conn)->fd);
}
-b_input_condition ssl_getdirection( void *conn )
+b_input_condition ssl_getdirection(void *conn)
{
- return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? B_EV_IO_WRITE : B_EV_IO_READ );
+ return(((struct scd*) conn)->lasterr == SSL_ERROR_WANT_WRITE ? B_EV_IO_WRITE : B_EV_IO_READ);
}
-char *ssl_verify_strerror( int code )
+char *ssl_verify_strerror(int code)
{
- return g_strdup( "SSL certificate verification not supported by BitlBee OpenSSL code." );
+ return g_strdup("SSL certificate verification not supported by BitlBee OpenSSL code.");
}
-size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned char *input, size_t input_len, const unsigned char *iv, unsigned char **res)
+size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned char *input, size_t input_len,
+ const unsigned char *iv, unsigned char **res)
{
- int output_length = 0;
+ int output_length = 0;
EVP_CIPHER_CTX ctx;
-
+
*res = g_new0(unsigned char, 72);
-
+
/* Don't set key or IV because we will modify the parameters */
EVP_CIPHER_CTX_init(&ctx);
EVP_CipherInit_ex(&ctx, EVP_des_ede3_cbc(), NULL, NULL, NULL, 1);
@@ -305,8 +312,8 @@ size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned
EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, 1);
EVP_CipherUpdate(&ctx, *res, &output_length, input, input_len);
EVP_CipherFinal_ex(&ctx, *res, &output_length);
- EVP_CIPHER_CTX_cleanup(&ctx);
+ EVP_CIPHER_CTX_cleanup(&ctx);
//EVP_cleanup();
-
+
return output_length;
}