GNUTLS: Reorder all functions to match the other backends

No code was changed in this commit; just entire lines moved up or down.
Ofcourse, most git diff tools won't see it that way.

The diff between the MbedTLS backend and this one is now fairly
minimal.

Note to auditors importing this series of patches for review and
integration: This means you can skip this patch if you don't trust me.
This commit is contained in:
Aaron Jones 2016-09-17 00:50:23 +00:00
parent fe9fba46cf
commit ecfdcb08e8
No known key found for this signature in database
GPG key ID: EC6F86EE9CD840B5

View file

@ -39,14 +39,14 @@
# include <gnutls/crypto.h>
#endif
#define SSL_P(x) *((gnutls_session_t *) ((x)->ssl))
typedef enum
{
RB_FD_TLS_DIRECTION_IN = 0,
RB_FD_TLS_DIRECTION_OUT = 1
} rb_fd_tls_direction;
#define SSL_P(x) *((gnutls_session_t *) ((x)->ssl))
// Server side variables
@ -79,6 +79,10 @@ static ssize_t rb_sock_net_xmit(gnutls_transport_ptr_t, const void *, size_t);
/*
* Internal GNUTLS-specific code
*/
/*
* We only have one certificate to authenticate with, as both a client and server.
*
@ -89,7 +93,6 @@ static ssize_t rb_sock_net_xmit(gnutls_transport_ptr_t, const void *, size_t);
*
* Thus, we use this callback to force GNUTLS to authenticate with our (server) certificate as a client.
*/
static int
rb_ssl_cert_auth_cb(gnutls_session_t session,
const gnutls_datum_t *const req_ca_rdn, const int req_ca_rdn_len,
@ -115,28 +118,6 @@ rb_ssl_cert_auth_cb(gnutls_session_t session,
return 0;
}
static const char *
rb_ssl_strerror(const int err)
{
return gnutls_strerror(err);
}
static ssize_t
rb_sock_net_recv(gnutls_transport_ptr_t context_ptr, void *const buf, const size_t count)
{
const int fd = rb_get_fd((rb_fde_t *)context_ptr);
return recv(fd, buf, count, 0);
}
static ssize_t
rb_sock_net_xmit(gnutls_transport_ptr_t context_ptr, const void *const buf, const size_t count)
{
const int fd = rb_get_fd((rb_fde_t *)context_ptr);
return send(fd, buf, count, 0);
}
static void
rb_ssl_init_fd(rb_fde_t *const F, const rb_fd_tls_direction dir)
{
@ -175,47 +156,6 @@ rb_ssl_init_fd(rb_fde_t *const F, const rb_fd_tls_direction dir)
gnutls_certificate_server_set_request(SSL_P(F), GNUTLS_CERT_REQUEST);
}
void
rb_ssl_shutdown(rb_fde_t *const F)
{
if(F == NULL || F->ssl == NULL)
return;
for(int i = 0; i < 4; i++)
{
int ret = gnutls_bye(SSL_P(F), GNUTLS_SHUT_RDWR);
if(ret != GNUTLS_E_INTERRUPTED && ret != GNUTLS_E_AGAIN)
break;
}
gnutls_deinit(SSL_P(F));
rb_free(F->ssl);
F->ssl = NULL;
}
unsigned int
rb_ssl_handshake_count(rb_fde_t *const F)
{
return F->handshake_count;
}
void
rb_ssl_clear_handshake_count(rb_fde_t *const F)
{
F->handshake_count = 0;
}
static void
rb_ssl_timeout_cb(rb_fde_t *const F, void *const data)
{
lrb_assert(F->accept != NULL);
lrb_assert(F->accept->callback != NULL);
F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data);
}
static void
rb_ssl_accept_common(rb_fde_t *const F, void *const data)
{
@ -263,41 +203,53 @@ rb_ssl_accept_common(rb_fde_t *const F, void *const data)
rb_free(ad);
}
void
rb_ssl_start_accepted(rb_fde_t *const F, ACCB *const cb, void *const data, const int timeout)
static void
rb_ssl_connect_common(rb_fde_t *const F, void *const data)
{
F->type |= RB_FD_SSL;
lrb_assert(F != NULL);
lrb_assert(F->ssl != NULL);
F->accept = rb_malloc(sizeof(struct acceptdata));
F->accept->callback = cb;
F->accept->data = data;
F->accept->addrlen = 0;
(void) memset(&F->accept->S, 0x00, sizeof F->accept->S);
errno = 0;
rb_settimeout(F, timeout, rb_ssl_timeout_cb, NULL);
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_IN);
rb_ssl_accept_common(F, NULL);
const int ret = gnutls_handshake(SSL_P(F));
const int err = errno;
if(ret == GNUTLS_E_AGAIN || (ret == GNUTLS_E_INTERRUPTED && (err == 0 || rb_ignore_errno(err))))
{
unsigned int flags = (gnutls_record_get_direction(SSL_P(F)) == 0) ? RB_SELECT_READ : RB_SELECT_WRITE;
rb_setselect(F, flags, rb_ssl_connect_common, data);
return;
}
void
rb_ssl_accept_setup(rb_fde_t *const srv_F, rb_fde_t *const cli_F, struct sockaddr *const st, const int addrlen)
// These 2 calls may affect errno, which is why we save it above and restore it below
rb_settimeout(F, 0, NULL, NULL);
rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL);
struct ssl_connect *const sconn = data;
if(ret == GNUTLS_E_SUCCESS)
{
cli_F->type |= RB_FD_SSL;
cli_F->accept = rb_malloc(sizeof(struct acceptdata));
cli_F->accept->callback = srv_F->accept->callback;
cli_F->accept->data = srv_F->accept->data;
cli_F->accept->addrlen = (rb_socklen_t) addrlen;
(void) memset(&cli_F->accept->S, 0x00, sizeof cli_F->accept->S);
(void) memcpy(&cli_F->accept->S, st, (size_t) addrlen);
rb_settimeout(cli_F, 10, rb_ssl_timeout_cb, NULL);
rb_ssl_init_fd(cli_F, RB_FD_TLS_DIRECTION_IN);
rb_ssl_accept_common(cli_F, NULL);
F->handshake_count++;
rb_ssl_connect_realcb(F, RB_OK, sconn);
}
else if(ret == GNUTLS_E_INTERRUPTED && err != 0)
{
errno = err;
rb_ssl_connect_realcb(F, RB_ERROR, sconn);
}
else
{
errno = EIO;
F->ssl_errno = (unsigned long) -ret;
rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
}
}
static const char *
rb_ssl_strerror(const int err)
{
return gnutls_strerror(err);
}
static ssize_t
rb_ssl_read_or_write(const int r_or_w, rb_fde_t *const F, void *const rbuf, const void *const wbuf, const size_t count)
@ -330,18 +282,6 @@ rb_ssl_read_or_write(const int r_or_w, rb_fde_t *const F, void *const rbuf, cons
return RB_RW_SSL_ERROR;
}
ssize_t
rb_ssl_read(rb_fde_t *const F, void *const buf, const size_t count)
{
return rb_ssl_read_or_write(0, F, buf, NULL, count);
}
ssize_t
rb_ssl_write(rb_fde_t *const F, const void *const buf, const size_t count)
{
return rb_ssl_read_or_write(1, F, NULL, buf, count);
}
#if (GNUTLS_VERSION_MAJOR < 3)
static void
rb_gcry_random_seed(void *const unused)
@ -350,24 +290,6 @@ rb_gcry_random_seed(void *const unused)
}
#endif
int
rb_init_ssl(void)
{
int ret;
if ((ret = gnutls_global_init()) != GNUTLS_E_SUCCESS)
{
rb_lib_log("%s: gnutls_global_init: %s", __func__, rb_ssl_strerror(ret));
return 0;
}
#if (GNUTLS_VERSION_MAJOR < 3)
rb_event_addish("rb_gcry_random_seed", rb_gcry_random_seed, NULL, 300);
#endif
return 1;
}
static void
rb_free_datum_t(gnutls_datum_t *const datum)
{
@ -432,6 +354,50 @@ rb_load_file_into_datum_t(const char *const file)
return datum;
}
/*
* External GNUTLS-specific code
*/
void
rb_ssl_shutdown(rb_fde_t *const F)
{
if(F == NULL || F->ssl == NULL)
return;
for(int i = 0; i < 4; i++)
{
int ret = gnutls_bye(SSL_P(F), GNUTLS_SHUT_RDWR);
if(ret != GNUTLS_E_INTERRUPTED && ret != GNUTLS_E_AGAIN)
break;
}
gnutls_deinit(SSL_P(F));
rb_free(F->ssl);
F->ssl = NULL;
}
int
rb_init_ssl(void)
{
int ret;
if((ret = gnutls_global_init()) != GNUTLS_E_SUCCESS)
{
rb_lib_log("%s: gnutls_global_init: %s", __func__, rb_ssl_strerror(ret));
return 0;
}
#if (GNUTLS_VERSION_MAJOR < 3)
rb_event_addish("rb_gcry_random_seed", rb_gcry_random_seed, NULL, 300);
#endif
return 1;
}
int
rb_setup_ssl_server(const char *const certfile, const char *keyfile,
const char *const dhfile, const char *const cipherlist)
@ -574,134 +540,6 @@ rb_setup_ssl_server(const char *const certfile, const char *keyfile,
return 1;
}
int
rb_ssl_listen(rb_fde_t *const F, const int backlog, const int defer_accept)
{
int result = rb_listen(F, backlog, defer_accept);
F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL;
return result;
}
static void
rb_ssl_connect_realcb(rb_fde_t *const F, const int status, struct ssl_connect *const sconn)
{
lrb_assert(F != NULL);
lrb_assert(F->connect != NULL);
F->connect->callback = sconn->callback;
F->connect->data = sconn->data;
rb_connect_callback(F, status);
rb_free(sconn);
}
static void
rb_ssl_tryconn_timeout_cb(rb_fde_t *const F, void *const data)
{
rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data);
}
static void
rb_ssl_connect_common(rb_fde_t *const F, void *const data)
{
lrb_assert(F != NULL);
lrb_assert(F->ssl != NULL);
errno = 0;
const int ret = gnutls_handshake(SSL_P(F));
const int err = errno;
if(ret == GNUTLS_E_AGAIN || (ret == GNUTLS_E_INTERRUPTED && (err == 0 || rb_ignore_errno(err))))
{
unsigned int flags = (gnutls_record_get_direction(SSL_P(F)) == 0) ? RB_SELECT_READ : RB_SELECT_WRITE;
rb_setselect(F, flags, rb_ssl_connect_common, data);
return;
}
// These 2 calls may affect errno, which is why we save it above and restore it below
rb_settimeout(F, 0, NULL, NULL);
rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL);
struct ssl_connect *const sconn = data;
if(ret == GNUTLS_E_SUCCESS)
{
F->handshake_count++;
rb_ssl_connect_realcb(F, RB_OK, sconn);
}
else if(ret == GNUTLS_E_INTERRUPTED && err != 0)
{
errno = err;
rb_ssl_connect_realcb(F, RB_ERROR, sconn);
}
else
{
errno = EIO;
F->ssl_errno = (unsigned long) -ret;
rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
}
}
static void
rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data)
{
lrb_assert(F != NULL);
struct ssl_connect *const sconn = data;
if(status != RB_OK)
{
rb_ssl_connect_realcb(F, status, sconn);
return;
}
F->type |= RB_FD_SSL;
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT);
rb_ssl_connect_common(F, sconn);
}
void
rb_connect_tcp_ssl(rb_fde_t *const F, struct sockaddr *const dest, struct sockaddr *const clocal,
const int socklen, CNCB *const callback, void *const data, const int timeout)
{
if(F == NULL)
return;
struct ssl_connect *const sconn = rb_malloc(sizeof *sconn);
sconn->data = data;
sconn->callback = callback;
sconn->timeout = timeout;
rb_connect_tcp(F, dest, clocal, socklen, rb_ssl_tryconn, sconn, timeout);
}
void
rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data, const int timeout)
{
if(F == NULL)
return;
struct ssl_connect *const sconn = rb_malloc(sizeof *sconn);
sconn->data = data;
sconn->callback = callback;
sconn->timeout = timeout;
F->connect = rb_malloc(sizeof(struct conndata));
F->connect->callback = callback;
F->connect->data = data;
F->type |= RB_FD_SSL;
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT);
rb_ssl_connect_common(F, sconn);
}
int
rb_init_prng(const char *const path, prng_seed_t seed_type)
{
@ -787,12 +625,6 @@ rb_get_ssl_certfp(rb_fde_t *const F, uint8_t certfp[const RB_SSL_CERTFP_LEN], co
return (int) hashlen;
}
int
rb_supports_ssl(void)
{
return 1;
}
void
rb_get_ssl_info(char *const buf, const size_t len)
{
@ -819,4 +651,190 @@ rb_ssl_get_cipher(rb_fde_t *const F)
return buf;
}
ssize_t
rb_ssl_read(rb_fde_t *const F, void *const buf, const size_t count)
{
return rb_ssl_read_or_write(0, F, buf, NULL, count);
}
ssize_t
rb_ssl_write(rb_fde_t *const F, const void *const buf, const size_t count)
{
return rb_ssl_read_or_write(1, F, NULL, buf, count);
}
/*
* Internal library-agnostic code
*/
static void
rb_ssl_connect_realcb(rb_fde_t *const F, const int status, struct ssl_connect *const sconn)
{
lrb_assert(F != NULL);
lrb_assert(F->connect != NULL);
F->connect->callback = sconn->callback;
F->connect->data = sconn->data;
rb_connect_callback(F, status);
rb_free(sconn);
}
static void
rb_ssl_timeout_cb(rb_fde_t *const F, void *const data)
{
lrb_assert(F->accept != NULL);
lrb_assert(F->accept->callback != NULL);
F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data);
}
static void
rb_ssl_tryconn_timeout_cb(rb_fde_t *const F, void *const data)
{
rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data);
}
static void
rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data)
{
lrb_assert(F != NULL);
struct ssl_connect *const sconn = data;
if(status != RB_OK)
{
rb_ssl_connect_realcb(F, status, sconn);
return;
}
F->type |= RB_FD_SSL;
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT);
rb_ssl_connect_common(F, sconn);
}
static ssize_t
rb_sock_net_recv(gnutls_transport_ptr_t context_ptr, void *const buf, const size_t count)
{
const int fd = rb_get_fd((rb_fde_t *)context_ptr);
return recv(fd, buf, count, 0);
}
static ssize_t
rb_sock_net_xmit(gnutls_transport_ptr_t context_ptr, const void *const buf, const size_t count)
{
const int fd = rb_get_fd((rb_fde_t *)context_ptr);
return send(fd, buf, count, 0);
}
/*
* External library-agnostic code
*/
int
rb_supports_ssl(void)
{
return 1;
}
unsigned int
rb_ssl_handshake_count(rb_fde_t *const F)
{
return F->handshake_count;
}
void
rb_ssl_clear_handshake_count(rb_fde_t *const F)
{
F->handshake_count = 0;
}
void
rb_ssl_start_accepted(rb_fde_t *const F, ACCB *const cb, void *const data, const int timeout)
{
F->type |= RB_FD_SSL;
F->accept = rb_malloc(sizeof(struct acceptdata));
F->accept->callback = cb;
F->accept->data = data;
F->accept->addrlen = 0;
(void) memset(&F->accept->S, 0x00, sizeof F->accept->S);
rb_settimeout(F, timeout, rb_ssl_timeout_cb, NULL);
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_IN);
rb_ssl_accept_common(F, NULL);
}
void
rb_ssl_accept_setup(rb_fde_t *const srv_F, rb_fde_t *const cli_F, struct sockaddr *const st, const int addrlen)
{
cli_F->type |= RB_FD_SSL;
cli_F->accept = rb_malloc(sizeof(struct acceptdata));
cli_F->accept->callback = srv_F->accept->callback;
cli_F->accept->data = srv_F->accept->data;
cli_F->accept->addrlen = (rb_socklen_t) addrlen;
(void) memset(&cli_F->accept->S, 0x00, sizeof cli_F->accept->S);
(void) memcpy(&cli_F->accept->S, st, (size_t) addrlen);
rb_settimeout(cli_F, 10, rb_ssl_timeout_cb, NULL);
rb_ssl_init_fd(cli_F, RB_FD_TLS_DIRECTION_IN);
rb_ssl_accept_common(cli_F, NULL);
}
int
rb_ssl_listen(rb_fde_t *const F, const int backlog, const int defer_accept)
{
int result = rb_listen(F, backlog, defer_accept);
F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL;
return result;
}
void
rb_connect_tcp_ssl(rb_fde_t *const F, struct sockaddr *const dest, struct sockaddr *const clocal,
const int socklen, CNCB *const callback, void *const data, const int timeout)
{
if(F == NULL)
return;
struct ssl_connect *const sconn = rb_malloc(sizeof *sconn);
sconn->data = data;
sconn->callback = callback;
sconn->timeout = timeout;
rb_connect_tcp(F, dest, clocal, socklen, rb_ssl_tryconn, sconn, timeout);
}
void
rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data, const int timeout)
{
if(F == NULL)
return;
struct ssl_connect *const sconn = rb_malloc(sizeof *sconn);
sconn->data = data;
sconn->callback = callback;
sconn->timeout = timeout;
F->connect = rb_malloc(sizeof(struct conndata));
F->connect->callback = callback;
F->connect->data = data;
F->type |= RB_FD_SSL;
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT);
rb_ssl_connect_common(F, sconn);
}
#endif /* HAVE_GNUTLS */