summaryrefslogtreecommitdiff
path: root/src/libmowgli/vio/vio_openssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libmowgli/vio/vio_openssl.c')
-rw-r--r--src/libmowgli/vio/vio_openssl.c200
1 files changed, 137 insertions, 63 deletions
diff --git a/src/libmowgli/vio/vio_openssl.c b/src/libmowgli/vio/vio_openssl.c
index 75c83e4..d492c9f 100644
--- a/src/libmowgli/vio/vio_openssl.c
+++ b/src/libmowgli/vio/vio_openssl.c
@@ -30,28 +30,28 @@
#ifdef HAVE_OPENSSL
-typedef struct {
+typedef struct
+{
SSL *ssl_handle;
SSL_CTX *ssl_context;
mowgli_vio_ssl_settings_t settings;
} mowgli_ssl_connection_t;
-static int mowgli_vio_openssl_connect(mowgli_vio_t *vio, mowgli_vio_sockaddr_t *addr);
-static int mowgli_vio_openssl_listen(mowgli_vio_t *vio, int backlog);
-static int mowgli_vio_openssl_accept(mowgli_vio_t *vio, mowgli_vio_t *newvio);
static int mowgli_vio_openssl_client_handshake(mowgli_vio_t *vio, mowgli_ssl_connection_t *connection);
-static int mowgli_vio_openssl_read(mowgli_vio_t *vio, void *buffer, size_t len);
-static int mowgli_vio_openssl_write(mowgli_vio_t *vio, const void *buffer, size_t len);
static int mowgli_openssl_read_or_write(bool read, mowgli_vio_t *vio, void *readbuf, const void *writebuf, size_t len);
-static int mowgli_vio_openssl_close(mowgli_vio_t *vio);
static mowgli_heap_t *ssl_heap = NULL;
static bool openssl_init = false;
-int mowgli_vio_openssl_setssl(mowgli_vio_t *vio, mowgli_vio_ssl_settings_t *settings)
+static mowgli_vio_ops_t *openssl_ops = NULL;
+
+int
+mowgli_vio_openssl_setssl(mowgli_vio_t *vio, mowgli_vio_ssl_settings_t *settings, mowgli_vio_ops_t *ops)
{
- mowgli_ssl_connection_t *connection;
+ mowgli_ssl_connection_t *connection;
+
+ return_val_if_fail(vio, -255);
if (!ssl_heap)
ssl_heap = mowgli_heap_create(sizeof(mowgli_ssl_connection_t), 64, BH_NOW);
@@ -65,13 +65,28 @@ int mowgli_vio_openssl_setssl(mowgli_vio_t *vio, mowgli_vio_ssl_settings_t *sett
/* Greatest compat without being terribly insecure */
connection->settings.ssl_version = MOWGLI_VIO_SSLFLAGS_SSLV3;
+ if (ops == NULL)
+ {
+ if (!openssl_ops)
+ {
+ openssl_ops = mowgli_alloc(sizeof(mowgli_vio_ops_t));
+ memcpy(openssl_ops, &mowgli_vio_default_ops, sizeof(mowgli_vio_ops_t));
+ }
+
+ vio->ops = openssl_ops;
+ }
+ else
+ {
+ vio->ops = ops;
+ }
+
/* Change ops */
- mowgli_vio_set_op(vio, connect, mowgli_vio_openssl_connect);
- mowgli_vio_set_op(vio, read, mowgli_vio_openssl_read);
- mowgli_vio_set_op(vio, write, mowgli_vio_openssl_write);
- mowgli_vio_set_op(vio, close, mowgli_vio_openssl_close);
- mowgli_vio_set_op(vio, accept, mowgli_vio_openssl_accept);
- mowgli_vio_set_op(vio, listen, mowgli_vio_openssl_listen);
+ mowgli_vio_ops_set_op(vio->ops, connect, mowgli_vio_openssl_default_connect);
+ mowgli_vio_ops_set_op(vio->ops, read, mowgli_vio_openssl_default_read);
+ mowgli_vio_ops_set_op(vio->ops, write, mowgli_vio_openssl_default_write);
+ mowgli_vio_ops_set_op(vio->ops, close, mowgli_vio_openssl_default_close);
+ mowgli_vio_ops_set_op(vio->ops, accept, mowgli_vio_openssl_default_accept);
+ mowgli_vio_ops_set_op(vio->ops, listen, mowgli_vio_openssl_default_listen);
/* SSL setup */
if (!openssl_init)
@@ -87,27 +102,39 @@ int mowgli_vio_openssl_setssl(mowgli_vio_t *vio, mowgli_vio_ssl_settings_t *sett
}
/* Returns void so they can be stubs */
-void * mowgli_vio_openssl_getsslhandle(mowgli_vio_t *vio)
+void *
+mowgli_vio_openssl_getsslhandle(mowgli_vio_t *vio)
{
+ return_val_if_fail(vio, NULL);
mowgli_ssl_connection_t *connection = vio->privdata;
return connection->ssl_handle;
}
-void * mowgli_vio_openssl_getsslcontext(mowgli_vio_t *vio)
+void *
+mowgli_vio_openssl_getsslcontext(mowgli_vio_t *vio)
{
+ return_val_if_fail(vio, NULL);
mowgli_ssl_connection_t *connection = vio->privdata;
return connection->ssl_context;
}
-static int mowgli_vio_openssl_connect(mowgli_vio_t *vio, mowgli_vio_sockaddr_t *addr)
+int
+mowgli_vio_openssl_default_connect(mowgli_vio_t *vio, mowgli_vio_sockaddr_t *addr)
{
- vio->error.op = MOWGLI_VIO_ERR_OP_CONNECT;
+ const int fd = mowgli_vio_getfd(vio);
+
+ return_val_if_fail(fd != -1, -255);
+
mowgli_ssl_connection_t *connection = vio->privdata;
- if (connect(vio->fd, (struct sockaddr *)&addr->addr, addr->addrlen) < 0)
+ vio->error.op = MOWGLI_VIO_ERR_OP_CONNECT;
+
+ if (connect(fd, (struct sockaddr *) &addr->addr, addr->addrlen) < 0)
{
if (!mowgli_eventloop_ignore_errno(errno))
+ {
return mowgli_vio_err_errcode(vio, strerror, errno);
+ }
else
{
mowgli_vio_setflag(vio, MOWGLI_VIO_FLAGS_ISCONNECTING, true);
@@ -128,11 +155,16 @@ static int mowgli_vio_openssl_connect(mowgli_vio_t *vio, mowgli_vio_sockaddr_t *
return mowgli_vio_openssl_client_handshake(vio, connection);
}
-static int mowgli_vio_openssl_listen(mowgli_vio_t *vio, int backlog)
+int
+mowgli_vio_openssl_default_listen(mowgli_vio_t *vio, int backlog)
{
- vio->error.op = MOWGLI_VIO_ERR_OP_LISTEN;
+ return_val_if_fail(vio, -255);
+
mowgli_ssl_connection_t *connection = vio->privdata;
const SSL_METHOD *method;
+ const int fd = mowgli_vio_getfd(vio);
+
+ vio->error.op = MOWGLI_VIO_ERR_OP_LISTEN;
switch (connection->settings.ssl_version)
{
@@ -148,21 +180,24 @@ static int mowgli_vio_openssl_listen(mowgli_vio_t *vio, int backlog)
method = TLSv1_server_method();
break;
default:
+
/* Compat method */
method = SSLv23_server_method();
}
-
- connection->ssl_context = SSL_CTX_new((SSL_METHOD *)method);
+
+ connection->ssl_context = SSL_CTX_new((SSL_METHOD *) method);
+
if (connection->ssl_context == NULL)
return mowgli_vio_err_sslerrcode(vio, ERR_get_error());
connection->ssl_handle = SSL_new(connection->ssl_context);
+
if (connection->ssl_handle == NULL)
return mowgli_vio_err_sslerrcode(vio, ERR_get_error());
SSL_set_accept_state(connection->ssl_handle);
SSL_CTX_set_options(connection->ssl_context, SSL_OP_SINGLE_DH_USE);
-
+
if (connection->settings.password_func)
{
SSL_CTX_set_default_passwd_cb(connection->ssl_context, connection->settings.password_func);
@@ -175,10 +210,10 @@ static int mowgli_vio_openssl_listen(mowgli_vio_t *vio, int backlog)
if (SSL_CTX_use_PrivateKey_file(connection->ssl_context, connection->settings.privatekey_path, SSL_FILETYPE_PEM) != 1)
return mowgli_vio_err_sslerrcode(vio, ERR_get_error());
- if (listen(vio->fd, backlog) != 0)
+ if (listen(fd, backlog) != 0)
return mowgli_vio_err_errcode(vio, strerror, errno);
- if (!SSL_set_fd(connection->ssl_handle, vio->fd))
+ if (!SSL_set_fd(connection->ssl_handle, fd))
return mowgli_vio_err_sslerrcode(vio, ERR_get_error());
mowgli_vio_setflag(vio, MOWGLI_VIO_FLAGS_ISSERVER, true);
@@ -187,10 +222,15 @@ static int mowgli_vio_openssl_listen(mowgli_vio_t *vio, int backlog)
return 0;
}
-static int mowgli_vio_openssl_accept(mowgli_vio_t *vio, mowgli_vio_t *newvio)
+int
+mowgli_vio_openssl_default_accept(mowgli_vio_t *vio, mowgli_vio_t *newvio)
{
- int fd;
+ const int fd = mowgli_vio_getfd(vio);
+ int afd;
int ret;
+
+ return_val_if_fail(fd != -1, -255);
+
mowgli_ssl_connection_t *connection = vio->privdata;
mowgli_ssl_connection_t *newconnection;
@@ -204,7 +244,7 @@ static int mowgli_vio_openssl_accept(mowgli_vio_t *vio, mowgli_vio_t *newvio)
return mowgli_vio_error(vio);
}
- if ((fd = accept(vio->fd, (struct sockaddr *)&newvio->addr.addr, &(newvio->addr.addrlen))) < 0)
+ if ((afd = accept(fd, (struct sockaddr *) &newvio->addr.addr, &(newvio->addr.addrlen))) < 0)
{
if (!mowgli_eventloop_ignore_errno(errno))
return mowgli_vio_err_errcode(vio, strerror, errno);
@@ -212,14 +252,14 @@ static int mowgli_vio_openssl_accept(mowgli_vio_t *vio, mowgli_vio_t *newvio)
return 0;
}
- newvio->fd = fd;
+ newvio->io.fd = afd;
- mowgli_vio_openssl_setssl(newvio, &connection->settings);
+ mowgli_vio_openssl_setssl(newvio, &connection->settings, vio->ops);
newconnection = newvio->privdata;
newconnection->ssl_context = connection->ssl_context;
newconnection->ssl_handle = SSL_new(newconnection->ssl_context);
-
- if (!SSL_set_fd(newconnection->ssl_handle, fd))
+
+ if (!SSL_set_fd(newconnection->ssl_handle, afd))
return mowgli_vio_err_sslerrcode(newvio, ERR_get_error());
if ((ret = SSL_accept(newconnection->ssl_handle)) != 1)
@@ -230,9 +270,11 @@ static int mowgli_vio_openssl_accept(mowgli_vio_t *vio, mowgli_vio_t *newvio)
{
case SSL_ERROR_WANT_READ:
mowgli_vio_setflag(vio, MOWGLI_VIO_FLAGS_NEEDREAD, true);
+ MOWGLI_VIO_SETREAD(vio)
return 0;
case SSL_ERROR_WANT_WRITE:
mowgli_vio_setflag(vio, MOWGLI_VIO_FLAGS_NEEDWRITE, true);
+ MOWGLI_VIO_SETWRITE(vio)
return 0;
case SSL_ERROR_ZERO_RETURN:
return 0;
@@ -243,7 +285,7 @@ static int mowgli_vio_openssl_accept(mowgli_vio_t *vio, mowgli_vio_t *newvio)
break;
}
- if(err > 0)
+ if (err > 0)
{
errno = EIO;
return mowgli_vio_err_errcode(vio, strerror, errno);
@@ -259,8 +301,10 @@ static int mowgli_vio_openssl_accept(mowgli_vio_t *vio, mowgli_vio_t *newvio)
return 0;
}
-static int mowgli_vio_openssl_client_handshake(mowgli_vio_t *vio, mowgli_ssl_connection_t *connection)
+static int
+mowgli_vio_openssl_client_handshake(mowgli_vio_t *vio, mowgli_ssl_connection_t *connection)
{
+ const int fd = mowgli_vio_getfd(vio);
int ret;
const SSL_METHOD *method;
@@ -280,41 +324,56 @@ static int mowgli_vio_openssl_client_handshake(mowgli_vio_t *vio, mowgli_ssl_con
method = TLSv1_client_method();
break;
default:
+
/* Compat method */
method = SSLv23_client_method();
}
/* Cast is to eliminate an excessively bogus warning on old OpenSSL --Elizacat */
- connection->ssl_context = SSL_CTX_new((SSL_METHOD *)method);
+ connection->ssl_context = SSL_CTX_new((SSL_METHOD *) method);
+
if (connection->ssl_context == NULL)
return mowgli_vio_err_sslerrcode(vio, ERR_get_error());
connection->ssl_handle = SSL_new(connection->ssl_context);
+
if (connection->ssl_handle == NULL)
return mowgli_vio_err_sslerrcode(vio, ERR_get_error());
-
+
SSL_set_connect_state(connection->ssl_handle);
-
- if (!SSL_set_fd(connection->ssl_handle, vio->fd))
+
+ if (!SSL_set_fd(connection->ssl_handle, fd))
return mowgli_vio_err_sslerrcode(vio, ERR_get_error());
- /* XXX not what we want for blocking sockets if they're in use! */
- SSL_CTX_set_mode(connection->ssl_context, SSL_MODE_ENABLE_PARTIAL_WRITE);
+ if (vio->eventloop)
+ SSL_CTX_set_mode(connection->ssl_context, SSL_MODE_ENABLE_PARTIAL_WRITE);
if ((ret = SSL_connect(connection->ssl_handle)) != 1)
{
- int err = SSL_get_error(connection->ssl_handle, ret);
+ unsigned long err = SSL_get_error(connection->ssl_handle, ret);
+
if (err == SSL_ERROR_WANT_READ)
+ {
mowgli_vio_setflag(vio, MOWGLI_VIO_FLAGS_NEEDREAD, true);
+ MOWGLI_VIO_SETREAD(vio)
+ }
else if (err == SSL_ERROR_WANT_WRITE)
+ {
mowgli_vio_setflag(vio, MOWGLI_VIO_FLAGS_NEEDWRITE, true);
+ MOWGLI_VIO_SETWRITE(vio)
+ }
else if (err == SSL_ERROR_WANT_CONNECT)
{
mowgli_vio_setflag(vio, MOWGLI_VIO_FLAGS_ISCONNECTING, true);
return 0;
}
else
+ {
return mowgli_vio_err_sslerrcode(vio, err);
+ }
+
+ mowgli_vio_setflag(vio, MOWGLI_VIO_FLAGS_ISSSLCONNECTING, false);
+ return 0;
}
/* Connected */
@@ -324,22 +383,25 @@ static int mowgli_vio_openssl_client_handshake(mowgli_vio_t *vio, mowgli_ssl_con
return 0;
}
-#define MOWGLI_VIO_SSL_DOREAD true
-#define MOWGLI_VIO_SSL_DOWRITE false
+# define MOWGLI_VIO_SSL_DOREAD true
+# define MOWGLI_VIO_SSL_DOWRITE false
-static int mowgli_vio_openssl_read(mowgli_vio_t *vio, void *buffer, size_t len)
+int
+mowgli_vio_openssl_default_read(mowgli_vio_t *vio, void *buffer, size_t len)
{
vio->error.op = MOWGLI_VIO_ERR_OP_READ;
return mowgli_openssl_read_or_write(MOWGLI_VIO_SSL_DOREAD, vio, buffer, NULL, len);
}
-static int mowgli_vio_openssl_write(mowgli_vio_t *vio, const void *buffer, size_t len)
+int
+mowgli_vio_openssl_default_write(mowgli_vio_t *vio, const void *buffer, size_t len)
{
vio->error.op = MOWGLI_VIO_ERR_OP_WRITE;
return mowgli_openssl_read_or_write(MOWGLI_VIO_SSL_DOWRITE, vio, NULL, buffer, len);
}
-static int mowgli_openssl_read_or_write(bool read, mowgli_vio_t *vio, void *readbuf, const void *writebuf, size_t len)
+static int
+mowgli_openssl_read_or_write(bool read, mowgli_vio_t *vio, void *readbuf, const void *writebuf, size_t len)
{
mowgli_ssl_connection_t *connection = vio->privdata;
int ret;
@@ -353,10 +415,15 @@ static int mowgli_openssl_read_or_write(bool read, mowgli_vio_t *vio, void *read
return_val_if_fail(connection->ssl_handle != NULL, -1);
- if(read)
- ret = (int)SSL_read(connection->ssl_handle, readbuf, len);
+ if (read)
+ {
+ ret = (int) SSL_read(connection->ssl_handle, readbuf, len);
+ }
else
- ret = (int)SSL_write(connection->ssl_handle, writebuf, len);
+ {
+ ret = (int) SSL_write(connection->ssl_handle, writebuf, len);
+ MOWGLI_VIO_UNSETWRITE(vio)
+ }
if (ret < 0)
{
@@ -364,32 +431,34 @@ static int mowgli_openssl_read_or_write(bool read, mowgli_vio_t *vio, void *read
{
case SSL_ERROR_WANT_READ:
mowgli_vio_setflag(vio, MOWGLI_VIO_FLAGS_NEEDREAD, true);
+ MOWGLI_VIO_SETREAD(vio)
return 0;
case SSL_ERROR_WANT_WRITE:
mowgli_vio_setflag(vio, MOWGLI_VIO_FLAGS_NEEDWRITE, true);
+ MOWGLI_VIO_SETWRITE(vio)
return 0;
case SSL_ERROR_ZERO_RETURN:
return 0;
case SSL_ERROR_SYSCALL:
- if((err = ERR_get_error()) == 0)
+
+ if ((err = ERR_get_error()) == 0)
{
vio->error.type = MOWGLI_VIO_ERR_REMOTE_HANGUP;
mowgli_strlcpy(vio->error.string, "Remote host closed the socket", sizeof(vio->error.string));
- mowgli_vio_setflag(vio, MOWGLI_VIO_FLAGS_ISCONNECTING, false);
- mowgli_vio_setflag(vio, MOWGLI_VIO_FLAGS_ISCLOSED, true);
-
+ MOWGLI_VIO_SET_CLOSED(vio);
+
return mowgli_vio_error(vio);
}
break;
-
+
default:
err = ERR_get_error();
break;
}
- if(err > 0)
+ if (err > 0)
{
errno = EIO;
return mowgli_vio_err_errcode(vio, strerror, errno);
@@ -405,8 +474,10 @@ static int mowgli_openssl_read_or_write(bool read, mowgli_vio_t *vio, void *read
return ret;
}
-static int mowgli_vio_openssl_close(mowgli_vio_t *vio)
+int
+mowgli_vio_openssl_default_close(mowgli_vio_t *vio)
{
+ const int fd = mowgli_vio_getfd(vio);
mowgli_ssl_connection_t *connection = vio->privdata;
return_val_if_fail(connection->ssl_handle != NULL, -1);
@@ -419,29 +490,32 @@ static int mowgli_vio_openssl_close(mowgli_vio_t *vio)
MOWGLI_VIO_SET_CLOSED(vio);
- close(vio->fd);
+ /* FIXME - doesn't verify a proper SSL shutdown! */
+ close(fd);
return 0;
}
#else
-int mowgli_vio_openssl_setssl(mowgli_vio_t *vio, mowgli_vio_ssl_settings_t *settings)
+int
+mowgli_vio_openssl_setssl(mowgli_vio_t *vio, mowgli_vio_ssl_settings_t *settings, mowgli_vio_ops_t *ops)
{
mowgli_log("OpenSSL requested on a VIO object, but mowgli was built without OpenSSL support...");
return -1;
}
-void * mowgli_vio_openssl_getsslhandle(mowgli_vio_t *vio)
+void *
+mowgli_vio_openssl_getsslhandle(mowgli_vio_t *vio)
{
mowgli_log("Cannot get VIO SSL handle as libmowgli was built without OpenSSL support");
return NULL;
}
-void * mowgli_vio_openssl_getsslcontext(mowgli_vio_t *vio)
+void *
+mowgli_vio_openssl_getsslcontext(mowgli_vio_t *vio)
{
mowgli_log("Cannot get VIO SSL context as libmowgli was built without OpenSSL support");
return NULL;
}
#endif
-