efl_net_ssl: do not access torn down sockets.

OpenSSL crashes if given a NULL pointer, then be safe and remember if
we did the tear down -- print error so bugs can be identified more
easily.
This commit is contained in:
Gustavo Sverzut Barbieri 2016-12-09 10:01:57 -02:00
parent c97111bf3c
commit cfc21c16fb
2 changed files with 33 additions and 4 deletions

View File

@ -114,6 +114,7 @@ typedef struct _Efl_Net_Socket_Ssl_Data
Efl_Net_Ssl_Verify_Mode verify_mode;
Eina_Bool hostname_verify;
Eina_Bool did_handshake;
Eina_Bool torndown;
Eina_Bool can_read;
Eina_Bool eos;
Eina_Bool can_write;
@ -131,6 +132,8 @@ efl_net_socket_ssl_handshake_try(Eo *o, Efl_Net_Socket_Ssl_Data *pd)
{
Eina_Error err;
if (pd->torndown) return;
DBG("SSL=%p handshake...", o);
err = efl_net_ssl_conn_handshake(&pd->ssl_conn, &pd->did_handshake);
@ -209,6 +212,7 @@ efl_net_socket_ssl_sock_del(void *data, const Efl_Event *event EINA_UNUSED)
Eo *o = data;
Efl_Net_Socket_Ssl_Data *pd = efl_data_scope_get(o, MY_CLASS);
pd->sock = NULL;
pd->torndown = EINA_TRUE;
efl_net_ssl_conn_teardown(&pd->ssl_conn);
}
@ -226,6 +230,7 @@ efl_net_socket_ssl_sock_connected(void *data, const Efl_Event *event EINA_UNUSED
Efl_Net_Socket_Ssl_Data *pd = efl_data_scope_get(o, MY_CLASS);
Eina_Error err;
if (pd->torndown) return;
efl_ref(o); /* we're emitting callbacks then continuing the workflow */
@ -325,6 +330,7 @@ _efl_net_socket_ssl_verify_mode_set(Eo *o EINA_UNUSED, Efl_Net_Socket_Ssl_Data *
{
pd->verify_mode = verify_mode;
if (!efl_finalized_get(o)) return;
EINA_SAFETY_ON_TRUE_RETURN(pd->torndown);
efl_net_ssl_conn_verify_mode_set(&pd->ssl_conn, pd->verify_mode);
}
@ -340,6 +346,7 @@ _efl_net_socket_ssl_hostname_verify_set(Eo *o EINA_UNUSED, Efl_Net_Socket_Ssl_Da
{
pd->hostname_verify = hostname_verify;
if (!efl_finalized_get(o)) return;
EINA_SAFETY_ON_TRUE_RETURN(pd->torndown);
efl_net_ssl_conn_hostname_verify_set(&pd->ssl_conn, pd->hostname_verify);
}
@ -357,6 +364,10 @@ _efl_net_socket_ssl_hostname_override_set(Eo *o EINA_UNUSED, Efl_Net_Socket_Ssl_
const char *hostname;
eina_stringshare_replace(&pd->hostname_override, hostname_override);
if (!efl_finalized_get(o)) return;
EINA_SAFETY_ON_TRUE_RETURN(pd->torndown);
hostname = pd->hostname_override;
if (!hostname)
{
@ -425,6 +436,7 @@ _efl_net_socket_ssl_efl_object_destructor(Eo *o, Efl_Net_Socket_Ssl_Data *pd)
efl_destructor(efl_super(o, MY_CLASS));
pd->torndown = EINA_TRUE;
efl_net_ssl_conn_teardown(&pd->ssl_conn);
if (pd->sock)
{
@ -454,6 +466,7 @@ _efl_net_socket_ssl_efl_io_closer_close(Eo *o, Efl_Net_Socket_Ssl_Data *pd)
efl_io_reader_can_read_set(o, EINA_FALSE);
efl_io_reader_eos_set(o, EINA_TRUE);
pd->torndown = EINA_TRUE;
efl_net_ssl_conn_teardown(&pd->ssl_conn);
if (efl_io_closer_closed_get(pd->sock))
return 0;
@ -472,6 +485,7 @@ _efl_net_socket_ssl_efl_io_reader_read(Eo *o, Efl_Net_Socket_Ssl_Data *pd, Eina_
Eina_Error err;
EINA_SAFETY_ON_NULL_RETURN_VAL(rw_slice, EINVAL);
EINA_SAFETY_ON_TRUE_RETURN_VAL(pd->torndown, EBADF);
if (!pd->did_handshake)
{
@ -529,6 +543,7 @@ _efl_net_socket_ssl_efl_io_writer_write(Eo *o, Efl_Net_Socket_Ssl_Data *pd, Eina
Eina_Error err;
EINA_SAFETY_ON_NULL_RETURN_VAL(ro_slice, EINVAL);
EINA_SAFETY_ON_TRUE_RETURN_VAL(pd->torndown, EBADF);
if (!pd->did_handshake)
{

View File

@ -373,7 +373,11 @@ efl_net_ssl_conn_teardown(Efl_Net_Ssl_Conn *conn)
static Eina_Error
efl_net_ssl_conn_write(Efl_Net_Ssl_Conn *conn, Eina_Slice *slice)
{
int r = SSL_write(conn->ssl, slice->mem, slice->len);
int r;
EINA_SAFETY_ON_NULL_RETURN_VAL(conn->ssl, EINVAL);
r = SSL_write(conn->ssl, slice->mem, slice->len);
if (r < 0)
{
int ssl_err = SSL_get_error(conn->ssl, r);
@ -391,7 +395,11 @@ efl_net_ssl_conn_write(Efl_Net_Ssl_Conn *conn, Eina_Slice *slice)
static Eina_Error
efl_net_ssl_conn_read(Efl_Net_Ssl_Conn *conn, Eina_Rw_Slice *slice)
{
int r = SSL_read(conn->ssl, slice->mem, slice->len);
int r;
EINA_SAFETY_ON_NULL_RETURN_VAL(conn->ssl, EINVAL);
r = SSL_read(conn->ssl, slice->mem, slice->len);
if (r < 0)
{
int ssl_err = SSL_get_error(conn->ssl, r);
@ -454,6 +462,8 @@ _efl_net_ssl_conn_hostname_verify(Efl_Net_Ssl_Conn *conn)
int family = AF_INET;
int r;
EINA_SAFETY_ON_NULL_RETURN_VAL(conn->ssl, EINVAL);
if ((!conn->hostname) || (conn->hostname[0] == '\0'))
{
ERR("ssl_conn=%p no hostname, cannot verify", conn);
@ -496,14 +506,16 @@ _efl_net_ssl_conn_hostname_verify(Efl_Net_Ssl_Conn *conn)
static Eina_Error
efl_net_ssl_conn_handshake(Efl_Net_Ssl_Conn *conn, Eina_Bool *done)
{
int r = SSL_do_handshake(conn->ssl);
long err_ssl;
const char *err_file;
const char *err_data;
int err_line, err_flags;
int r, err_line, err_flags;
*done = EINA_FALSE;
EINA_SAFETY_ON_NULL_RETURN_VAL(conn->ssl, EINVAL);
r = SSL_do_handshake(conn->ssl);
if (r == 1)
{
_efl_net_ssl_conn_session_debug(conn);
@ -561,6 +573,8 @@ efl_net_ssl_conn_verify_mode_set(Efl_Net_Ssl_Conn *conn, Efl_Net_Ssl_Verify_Mode
{
int ssl_mode;
EINA_SAFETY_ON_NULL_RETURN_VAL(conn->ssl, EINVAL);
switch (verify_mode)
{
case EFL_NET_SSL_VERIFY_MODE_NONE: