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
*/
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
*/
};
/**
+ * @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
*/
};
/**
+ * @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
*/
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 */
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);
/**
* @}
{
/* 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);
}
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);
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);
}
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;
_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 */
{
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);
#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
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_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_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,
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);
/*
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;
}
}
/**
+ * @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);
+}
+
+/**
* @}
*/
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:
return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
}
+
static Ecore_Con_Ssl_Error
_ecore_con_ssl_server_init_gnutls(Ecore_Con_Server *svr)
{
}
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__)
{
return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
}
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__)
{
return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;