+ecore_con_ssl_server_upgrade

+ecore_con_ssl_client_upgrade
+ECORE_CON_EVENT_SERVER_UPGRADE
+ECORE_CON_EVENT_CLIENT_UPGRADE
new functions for upgrading an existing plaintext connection to SSL/TLS, as seen in STARTTLS and my nightmares


SVN revision: 60359
This commit is contained in:
Mike Blumenkrantz 2011-06-15 18:58:34 +00:00
parent a336a811ec
commit 64731e1dc9
6 changed files with 164 additions and 29 deletions

View File

@ -214,3 +214,9 @@
2011-06-09 Cedric Bail
* Add ecore_pipe_wait (should only called from outside of the main loop).
2011-06-15 Mike Blumenkrantz
* Add ecore_con_ssl_client/server_upgrade to begin asynchronously upgrading an
existing connection to SSL/TLS, emitting ECORE_CON_CLIENT/SERVER_UPGRADE event
upon completion.

View File

@ -145,6 +145,12 @@ typedef struct _Ecore_Con_Url Ecore_Con_Url;
*/
typedef struct _Ecore_Con_Event_Client_Add Ecore_Con_Event_Client_Add;
/**
* @typedef Ecore_Con_Event_Client_Upgrade
* Used as the @p data param for the corresponding event
*/
typedef struct _Ecore_Con_Event_Client_Upgrade Ecore_Con_Event_Client_Upgrade;
/**
* @typedef Ecore_Con_Event_Client_Del
* Used as the @p data param for the corresponding event
@ -163,6 +169,12 @@ typedef struct _Ecore_Con_Event_Client_Error Ecore_Con_Event_Client_Error;
*/
typedef struct _Ecore_Con_Event_Server_Add Ecore_Con_Event_Server_Add;
/**
* @typedef Ecore_Con_Event_Server_Upgrade
* Used as the @p data param for the corresponding event
*/
typedef struct _Ecore_Con_Event_Server_Upgrade Ecore_Con_Event_Server_Upgrade;
/**
* @typedef Ecore_Con_Event_Server_Del
* Used as the @p data param for the corresponding event
@ -214,6 +226,15 @@ struct _Ecore_Con_Event_Client_Add
Ecore_Con_Client *client; /** the client that connected */
};
/**
* @struct _Ecore_Con_Event_Client_Upgrade
* Used as the @p data param for the @ref ECORE_CON_EVENT_CLIENT_UPGRADE event
*/
struct _Ecore_Con_Event_Client_Upgrade
{
Ecore_Con_Client *client; /** the client that completed handshake */
};
/**
* @struct _Ecore_Con_Event_Client_Del
* Used as the @p data param for the @ref ECORE_CON_EVENT_CLIENT_DEL event
@ -242,6 +263,15 @@ struct _Ecore_Con_Event_Server_Add
Ecore_Con_Server *server; /** the server that was connected to */
};
/**
* @struct _Ecore_Con_Event_Server_Upgrade
* Used as the @p data param for the @ref ECORE_CON_EVENT_SERVER_UPGRADE event
*/
struct _Ecore_Con_Event_Server_Upgrade
{
Ecore_Con_Server *server; /** the server that was connected to */
};
/**
* @struct _Ecore_Con_Event_Server_Del
* Used as the @p data param for the @ref ECORE_CON_EVENT_SERVER_DEL event
@ -329,12 +359,16 @@ EAPI extern int ECORE_CON_EVENT_CLIENT_ADD;
EAPI extern int ECORE_CON_EVENT_CLIENT_DEL;
/** A client experienced an error */
EAPI extern int ECORE_CON_EVENT_CLIENT_ERROR;
/** A client connection has been upgraded to SSL */
EAPI extern int ECORE_CON_EVENT_CLIENT_UPGRADE;
/** A server was created */
EAPI extern int ECORE_CON_EVENT_SERVER_ADD;
/** A server connection was lost */
EAPI extern int ECORE_CON_EVENT_SERVER_DEL;
/** A server experienced an error */
EAPI extern int ECORE_CON_EVENT_SERVER_ERROR;
/** A server connection has been upgraded to SSL */
EAPI extern int ECORE_CON_EVENT_SERVER_UPGRADE;
/** A client connected to the server has sent data */
EAPI extern int ECORE_CON_EVENT_CLIENT_DATA;
/** A server connection object has data */
@ -427,6 +461,8 @@ EAPI Eina_Bool ecore_con_ssl_server_privkey_add(Ecore_Con_Server *svr, c
EAPI Eina_Bool ecore_con_ssl_server_crl_add(Ecore_Con_Server *svr, const char *crl_file);
EAPI Eina_Bool ecore_con_ssl_server_cafile_add(Ecore_Con_Server *svr, const char *ca_file);
EAPI void ecore_con_ssl_server_verify(Ecore_Con_Server *svr);
EAPI Eina_Bool ecore_con_ssl_server_upgrade(Ecore_Con_Server *svr, Ecore_Con_Type compl_type);
EAPI Eina_Bool ecore_con_ssl_client_upgrade(Ecore_Con_Client *cl, Ecore_Con_Type compl_type);
/**
* @}

View File

@ -1178,13 +1178,15 @@ ecore_con_event_server_add(Ecore_Con_Server *svr)
{
/* we got our server! */
Ecore_Con_Event_Server_Add *e;
int ev = ECORE_CON_EVENT_SERVER_ADD;
e = calloc(1, sizeof(Ecore_Con_Event_Server_Add));
EINA_SAFETY_ON_NULL_RETURN(e);
svr->event_count++;
e->server = svr;
ecore_event_add(ECORE_CON_EVENT_SERVER_ADD, e,
if (svr->upgrade) ev = ECORE_CON_EVENT_SERVER_UPGRADE;
ecore_event_add(ev, e,
_ecore_con_event_server_add_free, NULL);
}
@ -1234,6 +1236,7 @@ void
ecore_con_event_client_add(Ecore_Con_Client *cl)
{
Ecore_Con_Event_Client_Add *e;
int ev = ECORE_CON_EVENT_CLIENT_ADD;
e = calloc(1, sizeof(Ecore_Con_Event_Client_Add));
EINA_SAFETY_ON_NULL_RETURN(e);
@ -1242,7 +1245,8 @@ ecore_con_event_client_add(Ecore_Con_Client *cl)
cl->host_server->event_count++;
_ecore_con_cl_timer_update(cl);
e->client = cl;
ecore_event_add(ECORE_CON_EVENT_CLIENT_ADD, e,
if (cl->upgrade) ev = ECORE_CON_EVENT_CLIENT_UPGRADE;
ecore_event_add(ev, e,
(Ecore_End_Cb)_ecore_con_event_client_add_free, cl->host_server);
}
@ -2018,7 +2022,7 @@ _ecore_con_svr_tcp_handler(void *data,
ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT);
if (svr->type & ECORE_CON_SSL)
if ((!svr->upgrade) && (svr->type & ECORE_CON_SSL))
{
cl->handshaking = EINA_TRUE;
cl->ssl_state = ECORE_CON_SSL_STATE_INIT;
@ -2284,7 +2288,7 @@ _ecore_con_svr_cl_read(Ecore_Con_Client *cl)
_ecore_con_cl_timer_update(cl);
}
if (!(cl->host_server->type & ECORE_CON_SSL))
if (!(cl->host_server->type & ECORE_CON_SSL) || (!cl->upgrade))
{
num = read(cl->fd, buf, sizeof(buf));
/* 0 is not a valid return value for a tcp socket */
@ -2445,7 +2449,7 @@ _ecore_con_client_flush(Ecore_Con_Client *cl)
{
num = cl->buf_size - cl->buf_offset;
if (num <= 0) return;
if (!(cl->host_server->type & ECORE_CON_SSL))
if (!(cl->host_server->type & ECORE_CON_SSL) || (!cl->upgrade))
count = write(cl->fd, cl->buf + cl->buf_offset, num);
else
count = ecore_con_ssl_client_write(cl, cl->buf + cl->buf_offset, num);

View File

@ -314,7 +314,7 @@ void
ecore_con_info_data_clear(void *info)
{
Ecore_Con_CAres *cares = info;
cares->data = NULL;
if (cares) cares->data = NULL;
}
static Eina_Bool

View File

@ -106,8 +106,9 @@ struct _Ecore_Con_Client
SSL *ssl;
int ssl_err;
#endif
Eina_Bool handshaking : 1;
Ecore_Con_Ssl_State ssl_state;
Eina_Bool handshaking : 1;
Eina_Bool upgrade : 1;
Eina_Bool dead : 1;
Eina_Bool delete_me : 1;
};
@ -152,6 +153,8 @@ struct _Ecore_Con_Server
Eina_Bool created : 1; /* EINA_TRUE if server is our listening server */
Eina_Bool connecting : 1; /* EINA_FALSE if just initialized or connected */
Eina_Bool handshaking : 1; /* EINA_TRUE if server is ssl handshaking */
Eina_Bool upgrade : 1;
Eina_Bool ssl_prepared : 1;
Eina_Bool use_cert : 1; /* EINA_TRUE if using certificate auth */
Ecore_Con_Ssl_State ssl_state; /* current state of ssl handshake on the server */
Eina_Bool verify : 1; /* EINA_TRUE if certificates will be verified */

View File

@ -21,6 +21,9 @@
#include <sys/mman.h>
#include <errno.h>
EAPI int ECORE_CON_EVENT_CLIENT_UPGRADE = 0;
EAPI int ECORE_CON_EVENT_SERVER_UPGRADE = 0;
static int _init_con_ssl_init_count = 0;
#ifdef USE_GNUTLS
@ -157,29 +160,16 @@ static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_cert_add) (Ecore_Con
static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_privkey_add) (Ecore_Con_Server * svr, const char *key_file);
static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_server_prepare) (Ecore_Con_Server * svr, int ssl_type);
static Ecore_Con_Ssl_Error
SSL_SUFFIX(_ecore_con_ssl_server_init) (Ecore_Con_Server * svr);
static Ecore_Con_Ssl_Error
SSL_SUFFIX(_ecore_con_ssl_server_shutdown) (Ecore_Con_Server *
svr);
static int
SSL_SUFFIX(_ecore_con_ssl_server_read) (Ecore_Con_Server * svr,
unsigned char *buf, int size);
static int
SSL_SUFFIX(_ecore_con_ssl_server_write) (Ecore_Con_Server *
svr,
unsigned char *buf, int size);
static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_server_init) (Ecore_Con_Server * svr);
static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_server_shutdown) (Ecore_Con_Server *svr);
static int SSL_SUFFIX(_ecore_con_ssl_server_read) (Ecore_Con_Server *svr, unsigned char *buf, int size);
static int SSL_SUFFIX(_ecore_con_ssl_server_write) (Ecore_Con_Server *svr, unsigned char *buf, int size);
static Ecore_Con_Ssl_Error
SSL_SUFFIX(_ecore_con_ssl_client_init) (Ecore_Con_Client * cl);
static Ecore_Con_Ssl_Error
SSL_SUFFIX(_ecore_con_ssl_client_shutdown) (Ecore_Con_Client *
cl);
static int
SSL_SUFFIX(_ecore_con_ssl_client_read) (Ecore_Con_Client * cl,
static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_client_init) (Ecore_Con_Client * cl);
static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_client_shutdown) (Ecore_Con_Client *cl);
static int SSL_SUFFIX(_ecore_con_ssl_client_read) (Ecore_Con_Client * cl,
unsigned char *buf, int size);
static int
SSL_SUFFIX(_ecore_con_ssl_client_write) (Ecore_Con_Client * cl,
static int SSL_SUFFIX(_ecore_con_ssl_client_write) (Ecore_Con_Client * cl,
unsigned char *buf, int size);
/*
@ -190,7 +180,13 @@ Ecore_Con_Ssl_Error
ecore_con_ssl_init(void)
{
if (!_init_con_ssl_init_count++)
SSL_SUFFIX(_ecore_con_ssl_init) ();
{
SSL_SUFFIX(_ecore_con_ssl_init) ();
#if _ECORE_CON_SSL_AVAILABLE != 0
ECORE_CON_EVENT_CLIENT_UPGRADE = ecore_event_type_new();
ECORE_CON_EVENT_SERVER_UPGRADE = ecore_event_type_new();
#endif
}
return _init_con_ssl_init_count;
}
@ -409,6 +405,82 @@ ecore_con_ssl_server_crl_add(Ecore_Con_Server *svr,
return SSL_SUFFIX(_ecore_con_ssl_server_crl_add) (svr, crl_file);
}
/**
* @brief Upgrade a connection to a specified level of encryption
*
* Use this function to begin an SSL handshake on a connection (STARTTLS or similar).
* Once the upgrade has been completed, an ECORE_CON_EVENT_SERVER_UPGRADE event will be emitted.
* The connection should be treated as disconnected until the next event.
* @param svr The server object
* @param ssl_type The SSL connection type (ONLY).
* @return EINA_FALSE if the connection cannot be upgraded, otherwise EINA_TRUE.
* @note This function is NEVER to be used on a server object created with ecore_con_server_add
* @warning Setting a wrong value for @p compl_type WILL mess up your program.
* @since 1.1
*/
EAPI Eina_Bool
ecore_con_ssl_server_upgrade(Ecore_Con_Server *svr, Ecore_Con_Type ssl_type)
{
if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
{
ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, __func__);
return EINA_FALSE;
}
#if _ECORE_CON_SSL_AVAILABLE == 0
return EINA_FALSE;
#endif
if (!svr->ssl_prepared)
{
if (ecore_con_ssl_server_prepare(svr, ssl_type))
return EINA_FALSE;
}
svr->type |= ssl_type;
svr->upgrade = EINA_TRUE;
svr->handshaking = EINA_TRUE;
svr->ssl_state = ECORE_CON_SSL_STATE_INIT;
return !SSL_SUFFIX(_ecore_con_ssl_server_init) (svr);
}
/**
* @brief Upgrade a connection to a specified level of encryption
*
* Use this function to begin an SSL handshake on a connection (STARTTLS or similar).
* Once the upgrade has been completed, an ECORE_CON_EVENT_CLIENT_UPGRADE event will be emitted.
* The connection should be treated as disconnected until the next event.
* @param cl The client object
* @param compl_type The SSL connection type (ONLY).
* @return EINA_FALSE if the connection cannot be upgraded, otherwise EINA_TRUE.
* @warning Setting a wrong value for @p compl_type WILL mess up your program.
* @since 1.1
*/
EAPI Eina_Bool
ecore_con_ssl_client_upgrade(Ecore_Con_Client *cl, Ecore_Con_Type ssl_type)
{
if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
{
ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, __func__);
return EINA_FALSE;
}
#if _ECORE_CON_SSL_AVAILABLE == 0
return EINA_FALSE;
#endif
if (!cl->host_server->ssl_prepared)
{
if (ecore_con_ssl_server_prepare(cl->host_server, ssl_type))
return EINA_FALSE;
}
cl->host_server->type |= ssl_type;
cl->upgrade = EINA_TRUE;
cl->host_server->upgrade = EINA_TRUE;
cl->handshaking = EINA_TRUE;
cl->ssl_state = ECORE_CON_SSL_STATE_INIT;
return SSL_SUFFIX(_ecore_con_ssl_client_init) (cl);
}
/**
* @}
*/
@ -490,6 +562,7 @@ _ecore_con_ssl_server_prepare_gnutls(Ecore_Con_Server *svr,
SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_anon_allocate_client_credentials(&svr->anoncred_c));
}
svr->ssl_prepared = EINA_TRUE;
return ECORE_CON_SSL_ERROR_NONE;
error:
@ -498,6 +571,7 @@ error:
return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
}
static Ecore_Con_Ssl_Error
_ecore_con_ssl_server_init_gnutls(Ecore_Con_Server *svr)
{
@ -1538,6 +1612,12 @@ _ecore_con_ssl_server_prepare_none(Ecore_Con_Server *svr __UNUSED__,
return ECORE_CON_SSL_ERROR_NONE;
}
static Ecore_Con_Ssl_Error
_ecore_con_ssl_server_upgrade_none(Ecore_Con_Server *svr __UNUSED__)
{
return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
}
static Ecore_Con_Ssl_Error
_ecore_con_ssl_server_init_none(Ecore_Con_Server *svr __UNUSED__)
{
@ -1594,6 +1674,12 @@ _ecore_con_ssl_server_write_none(Ecore_Con_Server *svr __UNUSED__,
return -1;
}
static Ecore_Con_Ssl_Error
_ecore_con_ssl_client_upgrade_none(Ecore_Con_Client *cl __UNUSED__)
{
return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
}
static Ecore_Con_Ssl_Error
_ecore_con_ssl_client_init_none(Ecore_Con_Client *cl __UNUSED__)
{