+ecore_con_ssl_server_upgrade
authordiscomfitor <discomfitor@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 15 Jun 2011 18:58:34 +0000 (18:58 +0000)
committerdiscomfitor <discomfitor@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 15 Jun 2011 18:58:34 +0000 (18:58 +0000)
+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

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/ecore@60359 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

ChangeLog
src/lib/ecore_con/Ecore_Con.h
src/lib/ecore_con/ecore_con.c
src/lib/ecore_con/ecore_con_ares.c
src/lib/ecore_con/ecore_con_private.h
src/lib/ecore_con/ecore_con_ssl.c

index 12008fc..5e2fb47 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 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.
index 4d9460f..25a945c 100644 (file)
@@ -146,6 +146,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
  */
@@ -164,6 +170,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
  */
@@ -215,6 +227,15 @@ struct _Ecore_Con_Event_Client_Add
 };
 
 /**
+ * @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
  */
@@ -243,6 +264,15 @@ struct _Ecore_Con_Event_Server_Add
 };
 
 /**
+ * @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);
 
 /**
  * @}
index 6450781..4074ea4 100644 (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);
index f66ac09..95369d6 100644 (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
index f484b2d..0e8057c 100644 (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 */
index 1b74999..a6cbe47 100644 (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_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);
 
 /*
@@ -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;
 }
@@ -410,6 +406,82 @@ ecore_con_ssl_server_crl_add(Ecore_Con_Server *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_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)
 {
@@ -1539,6 +1613,12 @@ _ecore_con_ssl_server_prepare_none(Ecore_Con_Server *svr __UNUSED__,
 }
 
 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;
@@ -1595,6 +1675,12 @@ _ecore_con_ssl_server_write_none(Ecore_Con_Server *svr __UNUSED__,
 }
 
 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;