Add support for GNU TLS in ecore_con.
authorcedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 30 Oct 2008 15:26:11 +0000 (15:26 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 30 Oct 2008 15:26:11 +0000 (15:26 +0000)
git-svn-id: http://svn.enlightenment.org/svn/e/trunk/ecore@37329 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

configure.ac
src/lib/ecore_con/Makefile.am
src/lib/ecore_con/ecore_con.c
src/lib/ecore_con/ecore_con_private.h
src/lib/ecore_con/ecore_con_ssl.c [new file with mode: 0644]
src/lib/ecore_ipc/ecore_ipc_private.h

index fb194fd..960c48d 100644 (file)
@@ -111,6 +111,35 @@ dnl check common functions and headers
 AC_CHECK_FUNCS(gettimeofday)
 AC_CHECK_FUNCS(strlcpy)
 
+dnl gnutls
+want_gnutls="yes"
+have_gnutls="no"
+AC_ARG_ENABLE(gnutls,
+  AC_HELP_STRING(
+    [--disable-gnutls],
+    [disable gnutls support]
+  ),
+  [ want_gnutls=$enableval ]
+)
+
+if test "x$want_gnutls" = "xyes"; then
+    PKG_CHECK_MODULES([TLS2], [gnutls >= 2.0.0], [
+        AC_DEFINE(USE_GNUTLS2, 1, [Use GnuTLS 2 or higher])
+       have_gnutls2="yes"
+       ], [
+       have_gnutls2="no"
+       ])
+    PKG_CHECK_MODULES([TLS], [gnutls], [
+        AC_DEFINE(USE_GNUTLS, 1, [Use GnuTLS])
+        requirements_ecore_con="$requirements_ecore_con gnutls"
+        # no need to add it to req_ecore_ipc, since they
+        # depends on ecore_con anyway.
+        have_gnutls="yes"
+    ], [
+        have_gnutls="no"
+    ])
+fi
+
 dnl openssl
 want_openssl="yes"
 have_openssl="no"
@@ -940,12 +969,24 @@ fi
 echo "  Ecore_Desktop................: $have_ecore_desktop"
 echo "  Ecore_Con....................: $have_ecore_con"
 if test "x$have_ecore_con" = "xyes" ; then
-  echo "    OpenSSL....................: $have_openssl"
+  echo -n "    OpenSSL....................: $have_openssl"
+if test "x$have_gnutls" = "xyes" ; then
+  echo " (disabled)"
+else
+  echo
+fi
+  echo "    GnuTLS.....................: $have_gnutls"
   echo "    CURL.......................: $have_curl"
 fi
 echo "  Ecore_Ipc....................: $have_ecore_ipc"
 if test "x$have_ecore_con" = "xyes" ; then
-  echo "    OpenSSL....................: $have_openssl"
+  echo -n "    OpenSSL....................: $have_openssl"
+if test "x$have_gnutls" = "xyes" ; then
+  echo " (disabled)"
+else
+  echo
+fi
+  echo "    GnuTLS.....................: $have_gnutls"
 fi
 echo "  Ecore_Config.................: $have_ecore_config"
 echo "  Ecore_IMF....................: $have_ecore_imf"
index b1923f5..2bf5575 100644 (file)
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 -I$(top_builddir)/src/lib/ecore_con \
 -I$(top_srcdir)/src/lib/ecore \
 -I$(top_srcdir)/src/lib/ecore_con \
-@SSL_CFLAGS@ @CURL_CFLAGS@ @EINA_CFLAGS@
+@SSL_CFLAGS@ @CURL_CFLAGS@ @EINA_CFLAGS@ @TLS_CFLAGS@
 
 if BUILD_ECORE_CON
 
@@ -17,12 +17,13 @@ libecore_con_la_SOURCES = \
 ecore_con.c \
 ecore_con_dns.c \
 ecore_con_info.c \
+ecore_con_ssl.c \
 ecore_con_url.c \
 ecore_con_private.h
 
 libecore_con_la_LIBADD = \
 $(top_builddir)/src/lib/ecore/libecore.la \
-@SSL_LIBS@ @CURL_LIBS@ @EINA_LIBS@
+@SSL_LIBS@ @CURL_LIBS@ @EINA_LIBS@ @TLS_LIBS@
 
 libecore_con_la_LDFLAGS = -version-info @version_info@
 
@@ -35,5 +36,6 @@ EXTRA_DIST = \
 ecore_con.c \
 ecore_con_dns.c \
 ecore_con_info.c \
+ecore_con_ssl.c \
 ecore_con_url.c \
 ecore_con_private.h
index ceb339c..07eea62 100644 (file)
 
 #include <config.h>
 
-#if USE_OPENSSL
-#include <time.h>
-#endif
-
 #include "Ecore.h"
 #include "ecore_private.h"
 #include "Ecore_Con.h"
@@ -60,27 +56,6 @@ EAPI int ECORE_CON_EVENT_SERVER_DATA = 0;
 static Ecore_List *servers = NULL;
 static int init_count = 0;
 
-#if USE_OPENSSL
-static int ssl_init_count = 0;
-static int _ecore_con_init_ssl(Ecore_Con_Server *svr);
-static int _ecore_con_shutdown_ssl(Ecore_Con_Server *svr);
-static int _ecore_con_free_ssl(Ecore_Con_Server *svr);
-
-# define INIT_SSL(svr) _ecore_con_init_ssl(svr)
-# define SHUTDOWN_SSL(svr) _ecore_con_shutdown_ssl(svr)
-# define FREE_SSL(svr) _ecore_con_free_ssl(svr)
-# define UNSET_SSL(svr)                \
-  do {                         \
-    svr->ssl = NULL;           \
-    svr->ssl_ctx = NULL;       \
-  } while (0)
-#else
-# define INIT_SSL(svr) 0
-# define SHUTDOWN_SSL(svr) 0
-# define FREE_SSL(svr) 0
-# define UNSET_SSL(svr) 0
-#endif
-
 #define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
 #define LENGTH_OF_ABSTRACT_SOCKADDR_UN(s, path) (strlen(path) + 1 + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
 
@@ -111,6 +86,7 @@ ecore_con_init(void)
    ECORE_CON_EVENT_SERVER_DATA = ecore_event_type_new();
 
    /* TODO Remember return value, if it fails, use gethostbyname() */
+   ecore_con_ssl_init();
    ecore_con_dns_init();
    ecore_con_info_init();
 
@@ -137,6 +113,7 @@ ecore_con_shutdown(void)
 
    ecore_con_info_shutdown();
    ecore_con_dns_shutdown();
+   ecore_con_ssl_shutdown();
 
    ecore_shutdown();
 
@@ -203,8 +180,7 @@ ecore_con_server_add(Ecore_Con_Type compl_type, const char *name, int port,
    svr->client_limit = -1;
    svr->clients = ecore_list_new();
    svr->ppid = getpid();
-   /* Set ssl and ssl_ctx fields to NULL */
-   UNSET_SSL(svr);
+   ecore_con_ssl_server_prepare(svr);
 
    type = compl_type & ECORE_CON_TYPE;
 
@@ -292,8 +268,6 @@ ecore_con_server_add(Ecore_Con_Type compl_type, const char *name, int port,
                                    _ecore_con_svr_handler, svr, NULL, NULL);
        umask(pmode);
        if (!svr->fd_handler) goto error;
-
-       INIT_SSL(svr);
      }
 
    if (type == ECORE_CON_REMOTE_TCP)
@@ -321,7 +295,7 @@ ecore_con_server_add(Ecore_Con_Type compl_type, const char *name, int port,
    if (svr->fd_handler) ecore_main_fd_handler_del(svr->fd_handler);
    if (svr->write_buf) free(svr->write_buf);
    if (svr->ip) free(svr->ip);
-   FREE_SSL(svr);
+   ecore_con_ssl_server_shutdown(svr);
    free(svr);
    return NULL;
 }
@@ -379,7 +353,7 @@ ecore_con_server_connect(Ecore_Con_Type compl_type, const char *name, int port,
    svr->reject_excess_clients = 0;
    svr->client_limit = -1;
    svr->clients = ecore_list_new();
-   UNSET_SSL(svr);
+   ecore_con_ssl_server_prepare(svr);
 
    type = compl_type & ECORE_CON_TYPE;
 
@@ -450,6 +424,10 @@ ecore_con_server_connect(Ecore_Con_Type compl_type, const char *name, int port,
          }
        svr->path = strdup(buf);
        if (!svr->path) goto error;
+
+       if (svr->type & ECORE_CON_SSL)
+         ecore_con_ssl_server_init(svr);
+
        svr->fd_handler =
          ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
                                    _ecore_con_cl_handler, svr, NULL, NULL);
@@ -492,7 +470,7 @@ ecore_con_server_connect(Ecore_Con_Type compl_type, const char *name, int port,
    if (svr->path) free(svr->path);
    if (svr->fd >= 0) close(svr->fd);
    if (svr->fd_handler) ecore_main_fd_handler_del(svr->fd_handler);
-   FREE_SSL(svr);
+   ecore_con_ssl_server_shutdown(svr);
    free(svr);
    return NULL;
 }
@@ -884,21 +862,6 @@ ecore_con_client_flush(Ecore_Con_Client *cl)
    _ecore_con_client_flush(cl);
 }
 
-/**
- * Returns if SSL support is available
- * @return  1 if SSL is available, 0 if it is not.
- * @ingroup Ecore_Con_Client_Group
- */
-EAPI int
-ecore_con_ssl_available_get(void)
-{
-#if USE_OPENSSL
-   return 1;
-#else
-   return 0;
-#endif
-}
-
 static void
 _ecore_con_server_free(Ecore_Con_Server *svr)
 {
@@ -926,8 +889,7 @@ _ecore_con_server_free(Ecore_Con_Server *svr)
    if ((svr->created) && (svr->path) && (svr->ppid == getpid()))
      unlink(svr->path);
    if (svr->fd >= 0) close(svr->fd);
-   SHUTDOWN_SSL(svr);
-   FREE_SSL(svr);
+   ecore_con_ssl_server_shutdown(svr);
    if (svr->name) free(svr->name);
    if (svr->path) free(svr->path);
    if (svr->ip) free(svr->ip);
@@ -962,112 +924,6 @@ _ecore_con_client_free(Ecore_Con_Client *cl)
    free(cl);
 }
 
-static int
-_ecore_con_svr_handler(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
-{
-   Ecore_Con_Server   *svr;
-   int                 new_fd;
-   struct sockaddr_in  incoming;
-   size_t              size_in;
-
-   svr = data;
-   if (svr->dead) return 1;
-   if (svr->delete_me) return 1;
-   if ((svr->client_limit >= 0) && (!svr->reject_excess_clients))
-     {
-       if (ecore_list_count(svr->clients) >= svr->client_limit) return 1;
-     }
-   /* a new client */
-   size_in = sizeof(struct sockaddr_in);
-   new_fd = accept(svr->fd, (struct sockaddr *)&incoming, (socklen_t *)&size_in);
-   if (new_fd >= 0)
-     {
-       Ecore_Con_Client *cl;
-       char buf[64];
-       uint32_t ip;
-
-       if ((svr->client_limit >= 0) && (svr->reject_excess_clients))
-         {
-            close(new_fd);
-            return 1;
-         }
-
-       cl = calloc(1, sizeof(Ecore_Con_Client));
-       if (!cl)
-         {
-            close(new_fd);
-            return 1;
-         }
-       fcntl(new_fd, F_SETFL, O_NONBLOCK);
-       fcntl(new_fd, F_SETFD, FD_CLOEXEC);
-       cl->fd = new_fd;
-       cl->server = svr;
-       cl->fd_handler =
-         ecore_main_fd_handler_add(cl->fd, ECORE_FD_READ,
-                                   _ecore_con_svr_cl_handler, cl, NULL, NULL);
-       ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT);
-       ecore_list_append(svr->clients, cl);
-       if (!svr->path)
-         {
-            ip = incoming.sin_addr.s_addr;
-            snprintf(buf, sizeof(buf),
-                     "%i.%i.%i.%i",
-                     (ip      ) & 0xff,
-                     (ip >> 8 ) & 0xff,
-                     (ip >> 16) & 0xff,
-                     (ip >> 24) & 0xff);
-            cl->ip = strdup(buf);
-         }
-       if (!cl->delete_me)
-         {
-            Ecore_Con_Event_Client_Add *e;
-
-            e = calloc(1, sizeof(Ecore_Con_Event_Client_Add));
-            if (e)
-              {
-                 cl->event_count++;
-                 e->client = cl;
-                 ecore_event_add(ECORE_CON_EVENT_CLIENT_ADD, e,
-                                 _ecore_con_event_client_add_free, NULL);
-              }
-         }
-     }
-   return 1;
-}
-
-#if USE_OPENSSL
-/* Tries to connect an Ecore_Con_Server to an SSL host.
- * Returns 1 on success, -1 on fatal errors and 0 if the caller
- * should try again later.
- */
-static int
-svr_try_connect_ssl(Ecore_Con_Server *svr)
-{
-   int res, ssl_err, flag = 0;
-
-   if (!ssl_init_count)
-     {
-       SSL_library_init();
-       SSL_load_error_strings();
-     }
-   ssl_init_count++;
-
-   res = SSL_connect(svr->ssl);
-   if (res == 1) return ECORE_CON_CONNECTED;
-   ssl_err = SSL_get_error(svr->ssl, res);
-
-   if (ssl_err == SSL_ERROR_NONE) return ECORE_CON_CONNECTED;
-   if (ssl_err == SSL_ERROR_WANT_READ)       flag = ECORE_FD_READ;
-   else if (ssl_err == SSL_ERROR_WANT_WRITE) flag = ECORE_FD_WRITE;
-   else return ECORE_CON_DISCONNECTED;
-   if (svr->fd_handler)
-     {
-       if (flag) ecore_main_fd_handler_active_set(svr->fd_handler, flag);
-     }
-   return ECORE_CON_INPROGRESS;
-}
-#endif
-
 static void
 kill_server(Ecore_Con_Server *svr)
 {
@@ -1114,13 +970,10 @@ _ecore_con_cb_tcp_listen(void *data, Ecore_Con_Info *net_info)
                               _ecore_con_svr_handler, svr, NULL, NULL);
    if (!svr->fd_handler) goto error;
 
-   if (INIT_SSL(svr))
-     goto error;
-
    return;
 
    error:
-   FREE_SSL(svr);
+   ecore_con_ssl_server_shutdown(svr);
    kill_server(svr);
 }
 
@@ -1168,13 +1021,10 @@ _ecore_con_cb_udp_listen(void *data, Ecore_Con_Info *net_info)
    if (!svr->fd_handler) goto error;
    svr->ip = strdup(net_info->ip);
 
-   if (INIT_SSL(svr))
-     goto error;
-
    return;
 
    error:
-   FREE_SSL(svr);
+   ecore_con_ssl_server_shutdown(svr);
    kill_server(svr);
 }
 
@@ -1195,28 +1045,29 @@ _ecore_con_cb_tcp_connect(void *data, Ecore_Con_Info *net_info)
      goto error;
    if (connect(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0)
      {
-       if (errno != EINPROGRESS)
-         goto error;
-       svr->connecting = 1;
-       svr->fd_handler =
-         ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ | ECORE_FD_WRITE,
-                                   _ecore_con_cl_handler, svr, NULL, NULL);
+       if (errno != EINPROGRESS)
+        goto error;
+       svr->connecting = 1;
+       svr->fd_handler =
+        ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ | ECORE_FD_WRITE,
+                                  _ecore_con_cl_handler, svr, NULL, NULL);
      }
    else
      svr->fd_handler =
-     ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
-                              _ecore_con_cl_handler, svr, NULL, NULL);
+       ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
+                                _ecore_con_cl_handler, svr, NULL, NULL);
+
+   if (svr->type & ECORE_CON_SSL)
+     if (ecore_con_ssl_server_init(svr))
+       goto error;
 
    if (!svr->fd_handler) goto error;
    svr->ip = strdup(net_info->ip);
 
-   if (INIT_SSL(svr))
-     goto error;
-
    return;
 
    error:
-   FREE_SSL(svr);
+   ecore_con_ssl_server_shutdown(svr);
    kill_server(svr);
 }
 
@@ -1244,13 +1095,10 @@ _ecore_con_cb_udp_connect(void *data, Ecore_Con_Info *net_info)
    if (!svr->fd_handler) goto error;
    svr->ip = strdup(net_info->ip);
 
-   if (INIT_SSL(svr))
-     goto error;
-
    return;
 
    error:
-   FREE_SSL(svr);
+   ecore_con_ssl_server_shutdown(svr);
    kill_server(svr);
 }
 
@@ -1305,15 +1153,11 @@ svr_try_connect_plain(Ecore_Con_Server *svr)
 /* returns 1 on success, 0 on failure */
 static Ecore_Con_State svr_try_connect(Ecore_Con_Server *svr)
 {
-#if USE_OPENSSL
-   if (!svr->ssl)
-     {
-#endif
-       return svr_try_connect_plain(svr);
-#if USE_OPENSSL
-     }
-   else
-     switch (svr_try_connect_ssl(svr)) {
+  if (!(svr->type & ECORE_CON_SSL))
+    return svr_try_connect_plain(svr);
+  else
+    {
+      switch (ecore_con_ssl_server_try(svr)) {
       case ECORE_CON_CONNECTED:
        return svr_try_connect_plain(svr);
       case ECORE_CON_DISCONNECTED:
@@ -1321,18 +1165,98 @@ static Ecore_Con_State svr_try_connect(Ecore_Con_Server *svr)
        return ECORE_CON_DISCONNECTED;
       default:
        return ECORE_CON_INPROGRESS;
-     }
-#endif
+      }
+    }
 }
 
+static int
+_ecore_con_svr_handler(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
+{
+   Ecore_Con_Server   *svr;
+   int                 new_fd;
+   struct sockaddr_in  incoming;
+   size_t              size_in;
+
+   svr = data;
+   if (svr->dead) return 1;
+   if (svr->delete_me) return 1;
+   if ((svr->client_limit >= 0) && (!svr->reject_excess_clients))
+     {
+       if (ecore_list_count(svr->clients) >= svr->client_limit) return 1;
+     }
+   /* a new client */
+   size_in = sizeof(struct sockaddr_in);
+
+   new_fd = accept(svr->fd, (struct sockaddr *)&incoming, (socklen_t *)&size_in);
+   if (new_fd >= 0)
+     {
+       Ecore_Con_Client *cl;
+       char buf[64];
+       uint32_t ip;
+
+       if ((svr->client_limit >= 0) && (svr->reject_excess_clients))
+         {
+            close(new_fd);
+            return 1;
+         }
+
+       cl = calloc(1, sizeof(Ecore_Con_Client));
+       if (!cl)
+         {
+            close(new_fd);
+            return 1;
+         }
+
+       fcntl(new_fd, F_SETFL, O_NONBLOCK);
+       fcntl(new_fd, F_SETFD, FD_CLOEXEC);
+       cl->fd = new_fd;
+       cl->server = svr;
+
+       if ((svr->type & ECORE_CON_SSL) &&
+           (ecore_con_ssl_client_init(cl)))
+         {
+           close(new_fd);
+           ecore_con_ssl_client_shutdown(svr);
+           return 1;
+         }
+
+       cl->fd_handler =
+         ecore_main_fd_handler_add(cl->fd, ECORE_FD_READ,
+                                   _ecore_con_svr_cl_handler, cl, NULL, NULL);
+       ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT);
+       ecore_list_append(svr->clients, cl);
+       if (!svr->path)
+         {
+            ip = incoming.sin_addr.s_addr;
+            snprintf(buf, sizeof(buf),
+                     "%i.%i.%i.%i",
+                     (ip      ) & 0xff,
+                     (ip >> 8 ) & 0xff,
+                     (ip >> 16) & 0xff,
+                     (ip >> 24) & 0xff);
+            cl->ip = strdup(buf);
+         }
+       if (!cl->delete_me)
+         {
+            Ecore_Con_Event_Client_Add *e;
+
+            e = calloc(1, sizeof(Ecore_Con_Event_Client_Add));
+            if (e)
+              {
+                 cl->event_count++;
+                 e->client = cl;
+                 ecore_event_add(ECORE_CON_EVENT_CLIENT_ADD, e,
+                                 _ecore_con_event_client_add_free, NULL);
+              }
+         }
+     }
+   return 1;
+}
 
 static int
 _ecore_con_cl_handler(void *data, Ecore_Fd_Handler *fd_handler)
 {
    Ecore_Con_Server   *svr;
-#if USE_OPENSSL
-   int ssl_err = SSL_ERROR_NONE;
-#endif
 
    svr = data;
    if (svr->dead) return 1;
@@ -1347,100 +1271,56 @@ _ecore_con_cl_handler(void *data, Ecore_Fd_Handler *fd_handler)
 
        for (;;)
          {
-            int num, lost_server;
-            char buf[READBUFSIZ];
-
-            lost_server = 0;
-#if USE_OPENSSL
-            if (!svr->ssl)
-              {
-#endif
-                 if ((num = read(svr->fd, buf, READBUFSIZ)) < 1)
-                   {
-                      lost_server = ((errno == EIO) ||
-                                     (errno == EBADF) ||
-                                     (errno == EPIPE) ||
-                                     (errno == EINVAL) ||
-                                     (errno == ENOSPC) ||
-                                     (num == 0));
-                      /* is num == 0 is right - when the server closes us
-                       * off we will get this (as this is called when select
-                       * tells us there is data to read!)
-                       */
-                   }
-#if USE_OPENSSL
-              }
-            else
-              {
-                 num = SSL_read(svr->ssl, buf, READBUFSIZ);
-                 if (num < 1)
-                   {
-                      ssl_err = SSL_get_error(svr->ssl, num);
-                      lost_server = (ssl_err == SSL_ERROR_ZERO_RETURN);
-                      if (ssl_err == SSL_ERROR_SYSCALL)
-                        {
-                           if (num == 0) lost_server = 1;
-                           else
-                             {
-                                lost_server = ((errno == EIO) ||
-                                               (errno == EBADF) ||
-                                               (errno == EPIPE) ||
-                                               (errno == EINVAL) ||
-                                               (errno == ENOSPC) ||
-                                               (errno == ECONNRESET));
-                             }
-                        }
-                   }
-                 else
-                   ssl_err = SSL_ERROR_NONE;
-              }
-#endif
-            if (num < 1)
-              {
-                 if (inbuf)
-                   {
-                      if (!svr->delete_me)
-                        {
-                           Ecore_Con_Event_Server_Data *e;
-
-                           e = calloc(1, sizeof(Ecore_Con_Event_Server_Data));
-                           if (e)
-                             {
-                                svr->event_count++;
-                                e->server = svr;
-                                e->data = inbuf;
-                                e->size = inbuf_num;
-                                ecore_event_add(ECORE_CON_EVENT_SERVER_DATA, e,
-                                                _ecore_con_event_server_data_free,
-                                                NULL);
-                             }
-                        }
-                   }
-                 if (lost_server)
-                   {
-                      /* we lost our server! */
-                      kill_server(svr);
-                      return 1;
-                   }
-                 break;
-              }
-            else
-              {
-                 inbuf = realloc(inbuf, inbuf_num + num);
-                 memcpy(inbuf + inbuf_num, buf, num);
-                 inbuf_num += num;
-              }
+           int num;
+           int lost_server = 1;
+           char buf[READBUFSIZ];
+
+           if (!(svr->type & ECORE_CON_SSL))
+             {
+               if (((num = read(svr->fd, buf, READBUFSIZ)) < 0) &&
+                   (errno == EAGAIN))
+                 lost_server = 0;
+             }
+           else
+             if (!(num = ecore_con_ssl_server_read(svr, buf, READBUFSIZ)))
+                 lost_server = 0;
+
+           if (num < 1)
+             {
+               if (inbuf && !svr->delete_me)
+                 {
+                   Ecore_Con_Event_Server_Data *e;
+
+                   e = calloc(1, sizeof(Ecore_Con_Event_Server_Data));
+                   if (e)
+                     {
+                       svr->event_count++;
+                       e->server = svr;
+                       e->data = inbuf;
+                       e->size = inbuf_num;
+                       ecore_event_add(ECORE_CON_EVENT_SERVER_DATA, e,
+                                       _ecore_con_event_server_data_free,
+                                       NULL);
+                     }
+                 }
+               if (lost_server) kill_server(svr);
+               break;
+             }
+
+           inbuf = realloc(inbuf, inbuf_num + num);
+           memcpy(inbuf + inbuf_num, buf, num);
+           inbuf_num += num;
          }
 
-#if USE_OPENSSL
-       if (svr->fd_handler)
-         {
-            if (svr->ssl && ssl_err == SSL_ERROR_WANT_READ)
-              ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
-            else if (svr->ssl && ssl_err == SSL_ERROR_WANT_WRITE)
-              ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
-         }
-#endif
+/* #if USE_OPENSSL */
+/*     if (svr->fd_handler) */
+/*       { */
+/*          if (svr->ssl && ssl_err == SSL_ERROR_WANT_READ) */
+/*            ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ); */
+/*          else if (svr->ssl && ssl_err == SSL_ERROR_WANT_WRITE) */
+/*            ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); */
+/*       } */
+/* #endif */
      }
    else if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
      {
@@ -1633,6 +1513,7 @@ _ecore_con_svr_cl_handler(void *data, Ecore_Fd_Handler *fd_handler)
      {
        unsigned char *inbuf = NULL;
        int            inbuf_num = 0;
+       int            lost_client = 1;
 
        for (;;)
          {
@@ -1640,31 +1521,37 @@ _ecore_con_svr_cl_handler(void *data, Ecore_Fd_Handler *fd_handler)
             int num;
 
             errno = 0;
-            num = read(cl->fd, buf, 65536);
+
+            if (!(cl->server->type & ECORE_CON_SSL))
+              {
+                if (((num = read(cl->fd, buf, 65536)) < 0) &&
+                    (errno == EAGAIN))
+                  lost_client = 0;
+              }
+            else
+              if (!(num = ecore_con_ssl_client_read(cl, buf, 65536)))
+                lost_client = 0;
+
             if (num < 1)
               {
-                 if (inbuf)
+                 if (inbuf && !cl->delete_me)
                    {
-                      if (!cl->delete_me)
-                        {
-                           Ecore_Con_Event_Client_Data *e;
-
-                           e = calloc(1, sizeof(Ecore_Con_Event_Client_Data));
-                           if (e)
-                             {
-                                cl->event_count++;
-                                e->client = cl;
-                                e->data = inbuf;
-                                e->size = inbuf_num;
-                                ecore_event_add(ECORE_CON_EVENT_CLIENT_DATA, e,
-                                                _ecore_con_event_client_data_free,
-                                                NULL);
-                             }
-                        }
+                     Ecore_Con_Event_Client_Data *e;
+                     
+                     e = calloc(1, sizeof(Ecore_Con_Event_Client_Data));
+                     if (e)
+                       {
+                         cl->event_count++;
+                         e->client = cl;
+                         e->data = inbuf;
+                         e->size = inbuf_num;
+                         ecore_event_add(ECORE_CON_EVENT_CLIENT_DATA, e,
+                                         _ecore_con_event_client_data_free,
+                                         NULL);
+                       }
                    }
-                 if ((errno == EIO) ||  (errno == EBADF) ||
-                     (errno == EPIPE) || (errno == EINVAL) ||
-                     (errno == ENOSPC) || (num == 0)/* is num == 0 right? */)
+
+                 if (lost_client)
                    {
                       if (!cl->delete_me)
                         {
@@ -1705,9 +1592,6 @@ static void
 _ecore_con_server_flush(Ecore_Con_Server *svr)
 {
    int count, num, lost_server = 0;
-#if USE_OPENSSL
-   int ssl_err = SSL_ERROR_NONE;
-#endif
 
    if (!svr->write_buf) return;
 
@@ -1719,51 +1603,19 @@ _ecore_con_server_flush(Ecore_Con_Server *svr)
       return;
 
    num = svr->write_buf_size - svr->write_buf_offset;
-#if USE_OPENSSL
-   if (!svr->ssl)
-     {
-#endif
-       count = write(svr->fd, svr->write_buf + svr->write_buf_offset, num);
-       if (count < 1)
-         lost_server = (errno == EIO || errno == EBADF ||
-                        errno == EPIPE || errno == EINVAL || errno == ENOSPC);
-#if USE_OPENSSL
-     }
-   else
-     {
-       count = SSL_write(svr->ssl, svr->write_buf + svr->write_buf_offset, num);
 
-       if (count < 1)
-         {
-            ssl_err = SSL_get_error(svr->ssl, count);
-            lost_server = (ssl_err == SSL_ERROR_ZERO_RETURN);
-         }
-     }
-#endif
+   if (!(svr->type & ECORE_CON_SSL))
+     count = write(svr->fd, svr->write_buf + svr->write_buf_offset, num);
+   else
+     count = ecore_con_ssl_server_write(svr, svr->write_buf + svr->write_buf_offset, num);
 
-   if (lost_server)
+   if (count < 0)
      {
        /* we lost our server! */
        kill_server(svr);
        return;
      }
 
-   if (count < 1)
-     {
-#if USE_OPENSSL
-       if (svr->fd_handler)
-         {
-            if (svr->ssl && ssl_err == SSL_ERROR_WANT_READ)
-              ecore_main_fd_handler_active_set(svr->fd_handler,
-                                               ECORE_FD_READ);
-            else if (svr->ssl && ssl_err == SSL_ERROR_WANT_WRITE)
-              ecore_main_fd_handler_active_set(svr->fd_handler,
-                                               ECORE_FD_WRITE);
-         }
-#endif
-       return;
-     }
-
    svr->write_buf_offset += count;
    if (svr->write_buf_offset >= svr->write_buf_size)
      {
@@ -1783,7 +1635,10 @@ _ecore_con_client_flush(Ecore_Con_Client *cl)
 
    if (!cl->buf) return;
    num = cl->buf_size - cl->buf_offset;
-   count = write(cl->fd, cl->buf + cl->buf_offset, num);
+   if (!(cl->server->type & ECORE_CON_SSL))
+     count = write(cl->fd, cl->buf + cl->buf_offset, num);
+   else
+     count = ecore_con_ssl_client_write(cl, cl->buf + cl->buf_offset, num);
    if (count < 1)
      {
        if ((errno == EIO) || (errno == EBADF) || (errno == EPIPE) ||
@@ -1897,60 +1752,3 @@ _ecore_con_event_server_data_free(void *data __UNUSED__, void *ev)
      ecore_con_server_del(e->server);
    free(e);
 }
-
-#if USE_OPENSSL
-
-static int
-_ecore_con_init_ssl(Ecore_Con_Server *svr)
-{
-  if (svr->type & ECORE_CON_SSL)
-    {
-      if (!ssl_init_count)
-       {
-         SSL_library_init();
-         SSL_load_error_strings();
-       }
-      ssl_init_count++;
-
-      switch (svr->type & ECORE_CON_SSL)
-       {
-       case ECORE_CON_USE_SSL2:
-         if (!(svr->ssl_ctx = SSL_CTX_new(SSLv2_client_method())))
-           return 1;
-         break;
-       case ECORE_CON_USE_SSL3:
-         if (!(svr->ssl_ctx = SSL_CTX_new(SSLv3_client_method())))
-           return 1;
-         break;
-       case ECORE_CON_USE_TLS:
-         if (!(svr->ssl_ctx = SSL_CTX_new(TLSv1_client_method())))
-           return 1;
-         break;
-       }
-
-      if (!(svr->ssl = SSL_new(svr->ssl_ctx)))
-       return 1;
-
-      SSL_set_fd(svr->ssl, svr->fd);
-    }
-  return 0;
-}
-
-static int
-_ecore_con_shutdown_ssl(Ecore_Con_Server *svr)
-{
-  if (svr->ssl) SSL_shutdown(svr->ssl);
-  return 0;
-}
-
-static int
-_ecore_con_free_ssl(Ecore_Con_Server *svr)
-{
-  if (svr->ssl) SSL_free(svr->ssl);
-  if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx);
-  UNSET_SSL(svr);
-
-  return 0;
-}
-
-#endif
index ee05b94..db9fb60 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _ECORE_CON_PRIVATE_H
 #define _ECORE_CON_PRIVATE_H
 
+#include "ecore_private.h"
 #include "Ecore_Con.h"
 #include "Ecore_Data.h"
 
 #define ECORE_CON_TYPE 0x0f
 #define ECORE_CON_SSL  0xf0
 
-#if USE_OPENSSL
-#include <openssl/ssl.h>
+#if USE_GNUTLS
+# include <gnutls/gnutls.h>
+#elif USE_OPENSSL
+# include <openssl/ssl.h>
 #endif
 #ifdef HAVE_CURL
 #include <curl/curl.h>
 
 typedef enum _Ecore_Con_State
   {
-     ECORE_CON_CONNECTED,
-     ECORE_CON_DISCONNECTED,
-     ECORE_CON_INPROGRESS
+    ECORE_CON_CONNECTED,
+    ECORE_CON_DISCONNECTED,
+    ECORE_CON_INPROGRESS
   } Ecore_Con_State;
 
+typedef enum _Ecore_Con_Ssl_Error
+  {
+    ECORE_CON_SSL_ERROR_NONE = 0,
+    ECORE_CON_SSL_ERROR_NOT_SUPPORTED,
+    ECORE_CON_SSL_ERROR_INIT_FAILED,
+    ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED,
+    ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED
+  } Ecore_Con_Ssl_Error;
+
 struct _Ecore_Con_Client
 {
    ECORE_MAGIC;
@@ -39,6 +51,13 @@ struct _Ecore_Con_Client
    unsigned char    *buf;
    char             *ip;
    int               event_count;
+#if USE_GNUTLS
+   gnutls_session    session;
+#elif USE_OPENSSL
+   SSL_CTX          *ssl_ctx;
+   SSL              *ssl;
+   int              ssl_err;
+#endif
    char              dead : 1;
    char              delete_me : 1;
 };
@@ -60,9 +79,14 @@ struct _Ecore_Con_Server
    int               event_count;
    int               client_limit;
    pid_t             ppid;
-#if USE_OPENSSL
+#if USE_GNUTLS
+   gnutls_session    session;
+   gnutls_anon_client_credentials_t anoncred_c;
+   gnutls_anon_server_credentials_t anoncred_s;
+#elif USE_OPENSSL
    SSL_CTX          *ssl_ctx;
    SSL              *ssl;
+   int              ssl_err;
 #endif
    char             *ip;
    char              dead : 1;
@@ -114,5 +138,8 @@ int ecore_con_info_tcp_listen(Ecore_Con_Server *svr, Ecore_Con_Info_Cb done_cb,
 int ecore_con_info_udp_connect(Ecore_Con_Server *svr, Ecore_Con_Info_Cb done_cb, void *data);
 int ecore_con_info_udp_listen(Ecore_Con_Server *svr, Ecore_Con_Info_Cb done_cb, void *data);
 int ecore_con_info_mcast_listen(Ecore_Con_Server *svr, Ecore_Con_Info_Cb done_cb, void *data);
+/* from ecore_con_ssl.c */
+Ecore_Con_Ssl_Error ecore_con_ssl_init(void);
+Ecore_Con_Ssl_Error ecore_con_ssl_shutdown(void);
 
 #endif
diff --git a/src/lib/ecore_con/ecore_con_ssl.c b/src/lib/ecore_con/ecore_con_ssl.c
new file mode 100644 (file)
index 0000000..3d81640
--- /dev/null
@@ -0,0 +1,768 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#if USE_GNUTLS
+# include <gnutls/gnutls.h>
+#elif USE_OPENSSL
+# include <openssl/ssl.h>
+#endif
+
+#include "ecore_con_private.h"
+
+static int _init_count = 0;
+
+#if USE_GNUTLS
+static int _client_connected = 0;
+
+# define SSL_SUFFIX(ssl_func) ssl_func##_gnutls
+# define _ECORE_CON_SSL_AVAILABLE 1
+
+#elif USE_OPENSSL
+# define SSL_SUFFIX(ssl_func) ssl_func##_openssl
+# define _ECORE_CON_SSL_AVAILABLE 2
+
+#else
+# define SSL_SUFFIX(ssl_func) ssl_func##_none
+# define _ECORE_CON_SSL_AVAILABLE 0
+
+#endif
+
+static Ecore_Con_Ssl_Error
+SSL_SUFFIX(_ecore_con_ssl_init)(void);
+static Ecore_Con_Ssl_Error
+SSL_SUFFIX(_ecore_con_ssl_shutdown)(void);
+
+static void
+SSL_SUFFIX(_ecore_con_ssl_server_prepare)(Ecore_Con_Server *svr);
+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 Ecore_Con_State
+SSL_SUFFIX(_ecore_con_ssl_server_try)(Ecore_Con_Server *svr);
+static int
+SSL_SUFFIX(_ecore_con_ssl_server_read)(Ecore_Con_Server *svr, char *buf, int size);
+static int
+SSL_SUFFIX(_ecore_con_ssl_server_write)(Ecore_Con_Server *svr, char *buf, int size);
+
+static void
+SSL_SUFFIX(_ecore_con_ssl_client_prepare)(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, char *buf, int size);
+static int
+SSL_SUFFIX(_ecore_con_ssl_client_write)(Ecore_Con_Client *cl, char *buf, int size);
+
+/*
+ * General SSL API
+ */
+
+EAPI Ecore_Con_Ssl_Error
+ecore_con_ssl_init(void)
+{
+  if (!_init_count++)
+    SSL_SUFFIX(_ecore_con_ssl_init)();
+
+  return _init_count;
+}
+
+EAPI Ecore_Con_Ssl_Error
+ecore_con_ssl_shutdown(void)
+{
+  if (!--_init_count)
+    SSL_SUFFIX(_ecore_con_ssl_shutdown)();
+
+  return _init_count;
+}
+
+/**
+ * Returns if SSL support is available
+ * @return  1 if SSL is available, 0 if it is not.
+ * @ingroup Ecore_Con_Client_Group
+ */
+EAPI int
+ecore_con_ssl_available_get(void)
+{
+  return _ECORE_CON_SSL_AVAILABLE;
+}
+
+
+EAPI void
+ecore_con_ssl_server_prepare(Ecore_Con_Server *svr)
+{
+  SSL_SUFFIX(_ecore_con_ssl_server_prepare)(svr);
+}
+
+EAPI Ecore_Con_Ssl_Error
+ecore_con_ssl_server_init(Ecore_Con_Server *svr)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_server_init)(svr);
+}
+
+EAPI Ecore_Con_Ssl_Error
+ecore_con_ssl_server_shutdown(Ecore_Con_Server *svr)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_server_shutdown)(svr);
+}
+
+EAPI Ecore_Con_State
+ecore_con_ssl_server_try(Ecore_Con_Server *svr)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_server_try)(svr);
+}
+
+EAPI int
+ecore_con_ssl_server_read(Ecore_Con_Server *svr, char *buf, int size)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_server_read)(svr, buf, size);
+}
+
+EAPI int
+ecore_con_ssl_server_write(Ecore_Con_Server *svr, char *buf, int size)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_server_write)(svr, buf, size);
+}
+
+EAPI Ecore_Con_Ssl_Error
+ecore_con_ssl_client_init(Ecore_Con_Client *cl)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_client_init)(cl);
+}
+
+EAPI Ecore_Con_Ssl_Error
+ecore_con_ssl_client_shutdown(Ecore_Con_Client *cl)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_client_shutdown)(cl);
+}
+
+EAPI int
+ecore_con_ssl_client_read(Ecore_Con_Client *cl, char *buf, int size)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_client_read)(cl, buf, size);
+}
+
+EAPI int
+ecore_con_ssl_client_write(Ecore_Con_Client *cl, char *buf, int size)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_client_write)(cl, buf, size);
+}
+
+#if USE_GNUTLS
+
+/*
+ * GnuTLS
+ */
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_init_gnutls(void)
+{
+  if (gnutls_global_init())
+    return ECORE_CON_SSL_ERROR_INIT_FAILED;
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_shutdown_gnutls(void)
+{
+  gnutls_global_deinit();
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static void
+_ecore_con_ssl_server_prepare_gnutls(Ecore_Con_Server *svr)
+{
+  svr->session = NULL;
+  svr->anoncred_c = NULL;
+  return;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_server_init_gnutls(Ecore_Con_Server *svr)
+{
+  const int *proto = NULL;
+  gnutls_dh_params_t dh_params;
+  int ret;
+  const int kx[] = { GNUTLS_KX_ANON_DH, 0 };
+  const int ssl3_proto[] = { GNUTLS_SSL3, 0 };
+  const int tls_proto[] = {
+    GNUTLS_TLS1_0,
+    GNUTLS_TLS1_1,
+#ifdef USE_GNUTLS2
+    GNUTLS_TLS1_2,
+#endif
+    0
+  };
+
+  switch (svr->type & ECORE_CON_SSL)
+    {
+    case ECORE_CON_USE_SSL2: /* not supported because of security issues */
+      return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED;
+    case ECORE_CON_USE_SSL3:
+      proto = ssl3_proto;
+      break;
+    case ECORE_CON_USE_TLS:
+      proto = tls_proto;
+      break;
+    default:
+      return ECORE_CON_SSL_ERROR_NONE;
+    }
+
+  gnutls_anon_allocate_client_credentials(&(svr->anoncred_c));
+  gnutls_init(&(svr->session), GNUTLS_CLIENT);
+  gnutls_set_default_priority(svr->session);
+  gnutls_kx_set_priority(svr->session, kx);
+  gnutls_credentials_set(svr->session, GNUTLS_CRD_ANON, svr->anoncred_c);
+  gnutls_kx_set_priority(svr->session, kx);
+  gnutls_protocol_set_priority(svr->session, proto);
+  gnutls_dh_set_prime_bits(svr->session, 512);
+
+  gnutls_transport_set_ptr(svr->session, (gnutls_transport_ptr_t)svr->fd);
+
+  while ((ret = gnutls_handshake(svr->session)) < 0)
+    {
+      if ((ret == GNUTLS_E_AGAIN) ||
+         (ret == GNUTLS_E_INTERRUPTED))
+       continue;
+
+      _ecore_con_ssl_server_shutdown_gnutls(svr);
+      return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+    }
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_server_shutdown_gnutls(Ecore_Con_Server *svr)
+{
+  if (svr->session)
+    {
+      gnutls_bye(svr->session, GNUTLS_SHUT_RDWR);
+      gnutls_deinit(svr->session);
+    }
+  if (svr->anoncred_c)
+    gnutls_anon_free_client_credentials(svr->anoncred_c);
+  _ecore_con_ssl_server_prepare_gnutls(svr);
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+/* Tries to connect an Ecore_Con_Server to an SSL host.
+ * Returns 1 on success, -1 on fatal errors and 0 if the caller
+ * should try again later.
+ */
+static Ecore_Con_State
+_ecore_con_ssl_server_try_gnutls(Ecore_Con_Server *svr)
+{
+   return ECORE_CON_CONNECTED;
+}
+
+static int
+_ecore_con_ssl_server_read_gnutls(Ecore_Con_Server *svr, char *buf, int size)
+{
+  int num;
+
+  num = gnutls_record_recv(svr->session, buf, size);
+  if (num > 0)
+    return num;
+  if ((num == GNUTLS_E_AGAIN) ||
+      (num == GNUTLS_E_REHANDSHAKE) ||
+      (num == GNUTLS_E_INTERRUPTED))
+    return 0;
+  return -1;
+}
+
+static int
+_ecore_con_ssl_server_write_gnutls(Ecore_Con_Server *svr, char *buf, int size)
+{
+  int num;
+
+  num = gnutls_record_send(svr->session, buf, size);
+  if (num > 0)
+    return num;
+  if ((num == GNUTLS_E_AGAIN) ||
+      (num == GNUTLS_E_REHANDSHAKE) ||
+      (num == GNUTLS_E_INTERRUPTED))
+    return 0;
+  return -1;
+}
+
+static void
+_ecore_con_ssl_client_prepare_gnutls(Ecore_Con_Client *cl)
+{
+  cl->session = NULL;
+  if (!_client_connected)
+    cl->server->anoncred_s = NULL;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_client_init_gnutls(Ecore_Con_Client *cl)
+{
+  const int *proto = NULL;
+  gnutls_dh_params_t dh_params;
+  int ret;
+  const int kx[] = { GNUTLS_KX_ANON_DH, 0 };
+  const int ssl3_proto[] = { GNUTLS_SSL3, 0 };
+  const int tls_proto[] = {
+    GNUTLS_TLS1_0,
+    GNUTLS_TLS1_1,
+#ifdef USE_GNUTLS2
+    GNUTLS_TLS1_2,
+#endif
+    0
+  };
+
+  switch (cl->server->type & ECORE_CON_SSL)
+    {
+    case ECORE_CON_USE_SSL2: /* not supported because of security issues */
+      return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED;
+    case ECORE_CON_USE_SSL3:
+      proto = ssl3_proto;
+      break;
+    case ECORE_CON_USE_TLS:
+      proto = tls_proto;
+      break;
+    default:
+      return ECORE_CON_SSL_ERROR_NONE;
+    }
+
+  _client_connected++;
+  if (!cl->server->anoncred_s)
+    {
+      gnutls_anon_allocate_server_credentials(&(cl->server->anoncred_s));
+      gnutls_dh_params_init(&dh_params);
+      gnutls_dh_params_generate2(dh_params, 512);
+      gnutls_anon_set_server_dh_params(cl->server->anoncred_s, dh_params);
+    }
+
+  gnutls_init(&(cl->session), GNUTLS_SERVER);
+  gnutls_set_default_priority(cl->session);
+  gnutls_credentials_set(cl->session, GNUTLS_CRD_ANON, cl->server->anoncred_s);
+
+  gnutls_kx_set_priority(cl->session, kx);
+
+  gnutls_protocol_set_priority(cl->session, proto);
+
+  gnutls_dh_set_prime_bits(cl->session, 512);
+
+  gnutls_transport_set_ptr(cl->session, (gnutls_transport_ptr_t)cl->fd);
+
+  while ((ret = gnutls_handshake(cl->session)) < 0)
+    {
+      if ((ret == GNUTLS_E_AGAIN) ||
+         (ret == GNUTLS_E_INTERRUPTED))
+       continue;
+
+      _ecore_con_ssl_client_shutdown_gnutls(cl);
+      return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+    }
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_client_shutdown_gnutls(Ecore_Con_Client *cl)
+{
+  if (cl->session)
+    {
+      gnutls_bye(cl->session, GNUTLS_SHUT_RDWR);
+      gnutls_deinit(cl->session);
+    }
+  if (cl->server->anoncred_s && !--_client_connected)
+    gnutls_anon_free_server_credentials(cl->server->anoncred_s);
+  _ecore_con_ssl_client_prepare_gnutls(cl);
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static int
+_ecore_con_ssl_client_read_gnutls(Ecore_Con_Client *cl, char *buf, int size)
+{
+  int num;
+
+  num = gnutls_record_recv(cl->session, buf, size);
+  if (num > 0)
+    return num;
+  if ((num == GNUTLS_E_AGAIN) ||
+      (num == GNUTLS_E_REHANDSHAKE) ||
+      (num == GNUTLS_E_INTERRUPTED))
+    return 0;
+  return -1;
+}
+
+static int
+_ecore_con_ssl_client_write_gnutls(Ecore_Con_Client *cl, char *buf, int size)
+{
+  int num;
+
+  num = gnutls_record_send(cl->session, buf, size);
+  if (num > 0)
+    return num;
+  if ((num == GNUTLS_E_AGAIN) ||
+      (num == GNUTLS_E_REHANDSHAKE) ||
+      (num == GNUTLS_E_INTERRUPTED))
+    return 0;
+  return -1;
+}
+
+#elif USE_OPENSSL
+
+/*
+ * OpenSSL
+ */
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_init_openssl(void)
+{
+  SSL_library_init();
+  SSL_load_error_strings();
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_shutdown_openssl(void)
+{
+  // FIXME nothing to do ?
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static void
+_ecore_con_ssl_server_prepare_openssl(Ecore_Con_Server *svr)
+{
+  svr->ssl = NULL;
+  svr->ssl_ctx = NULL;
+  svr->ssl_err = SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_server_init_openssl(Ecore_Con_Server *svr)
+{
+  switch (svr->type & ECORE_CON_SSL)
+    {
+    case ECORE_CON_USE_SSL2:
+      /* Unsafe version of SSL */
+      if (!(svr->ssl_ctx = SSL_CTX_new(SSLv2_client_method())))
+       return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+      break;
+    case ECORE_CON_USE_SSL3:
+      if (!(svr->ssl_ctx = SSL_CTX_new(SSLv3_client_method())))
+       return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+      break;
+    case ECORE_CON_USE_TLS:
+      if (!(svr->ssl_ctx = SSL_CTX_new(TLSv1_client_method())))
+       return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+      break;
+    default:
+      return ECORE_CON_SSL_ERROR_NONE;
+    }
+  if (!(svr->ssl = SSL_new(svr->ssl_ctx)))
+    {
+      SSL_CTX_free(svr->ssl_ctx);
+      return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+    }
+
+  SSL_set_fd(svr->ssl, svr->fd);
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_server_shutdown_openssl(Ecore_Con_Server *svr)
+{
+  if (svr->ssl)
+    {
+      if (!SSL_shutdown(svr->ssl))
+       SSL_shutdown(svr->ssl);
+      SSL_free(svr->ssl);
+    }
+  if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx);
+
+  _ecore_con_ssl_server_prepare_openssl(svr);
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+/* Tries to connect an Ecore_Con_Server to an SSL host.
+ * Returns 1 on success, -1 on fatal errors and 0 if the caller
+ * should try again later.
+ */
+static Ecore_Con_State
+_ecore_con_ssl_server_try_openssl(Ecore_Con_Server *svr)
+{
+   int res, flag = 0;
+
+   if ((res = SSL_connect(svr->ssl)) == 1)
+     return ECORE_CON_CONNECTED;
+
+   svr->ssl_err = SSL_get_error(svr->ssl, res);
+
+   switch (svr->ssl_err)
+     {
+     case SSL_ERROR_NONE:
+       return ECORE_CON_CONNECTED;
+     case SSL_ERROR_WANT_READ:
+       flag = ECORE_FD_READ;
+       break;
+     case SSL_ERROR_WANT_WRITE:
+       flag = ECORE_FD_WRITE;
+       break;
+     default:
+       return ECORE_CON_DISCONNECTED;
+     }
+
+   if (svr->fd_handler && flag)
+     ecore_main_fd_handler_active_set(svr->fd_handler, flag);
+
+   return ECORE_CON_INPROGRESS;
+}
+
+static int
+_ecore_con_ssl_server_read_openssl(Ecore_Con_Server *svr, char *buf, int size)
+{
+  int num;
+
+  num = SSL_read(svr->ssl, buf, size);
+  svr->ssl_err = SSL_get_error(svr->ssl, num);
+
+  if (svr->fd_handler)
+    {
+      if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_READ)
+       ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
+      else if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_WRITE)
+       ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
+    }
+
+  if ((svr->ssl_err == SSL_ERROR_ZERO_RETURN) ||
+      (svr->ssl_err == SSL_ERROR_SYSCALL) ||
+      (svr->ssl_err == SSL_ERROR_SSL))
+    return -1;
+  if (num < 0)
+    return 0;
+  return num;
+}
+
+static int
+_ecore_con_ssl_server_write_openssl(Ecore_Con_Server *svr, char *buf, int size)
+{
+  int num;
+
+  num = SSL_write(svr->ssl, buf, size);
+  svr->ssl_err = SSL_get_error(svr->ssl, num);
+
+  if (svr->fd_handler)
+    {
+      if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_READ)
+       ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
+      else if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_WRITE)
+       ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
+    }
+
+  if ((svr->ssl_err == SSL_ERROR_ZERO_RETURN) ||
+      (svr->ssl_err == SSL_ERROR_SYSCALL) ||
+      (svr->ssl_err == SSL_ERROR_SSL))
+    return -1;
+  if (num < 0)
+    return 0;
+  return num;
+}
+
+static void
+_ecore_con_ssl_client_prepare_openssl(Ecore_Con_Client *cl)
+{
+  cl->ssl = NULL;
+  cl->ssl_ctx = NULL;
+  cl->ssl_err = SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_client_init_openssl(Ecore_Con_Client *cl)
+{
+    switch (cl->server->type & ECORE_CON_SSL)
+    {
+    case ECORE_CON_USE_SSL2:
+      /* Unsafe version of SSL */
+      if (!(cl->ssl_ctx = SSL_CTX_new(SSLv2_client_method())))
+       return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+      break;
+    case ECORE_CON_USE_SSL3:
+      if (!(cl->ssl_ctx = SSL_CTX_new(SSLv3_client_method())))
+       return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+      break;
+    case ECORE_CON_USE_TLS:
+      if (!(cl->ssl_ctx = SSL_CTX_new(TLSv1_client_method())))
+       return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+      break;
+    default:
+      return ECORE_CON_SSL_ERROR_NONE;
+    }
+  if (!(cl->ssl = SSL_new(cl->ssl_ctx)))
+    {
+      SSL_CTX_free(cl->ssl_ctx);
+      return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+    }
+
+  SSL_set_fd(cl->ssl, cl->fd);
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_client_shutdown_openssl(Ecore_Con_Client *cl)
+{
+  if (cl->ssl)
+    {
+      if (!SSL_shutdown(cl->ssl))
+       SSL_shutdown(cl->ssl);
+      SSL_free(cl->ssl);
+    }
+  if (cl->ssl_ctx) SSL_CTX_free(cl->ssl_ctx);
+
+  _ecore_con_ssl_client_prepare_openssl(cl);
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static int
+_ecore_con_ssl_client_read_openssl(Ecore_Con_Client *cl, char *buf, int size)
+{
+  int num;
+
+  num = SSL_read(cl->ssl, buf, size);
+  cl->ssl_err = SSL_get_error(cl->ssl, num);
+
+  if (cl->fd_handler)
+    {
+      if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_READ)
+       ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
+      else if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_WRITE)
+       ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
+    }
+
+  if ((cl->ssl_err == SSL_ERROR_ZERO_RETURN) ||
+      (cl->ssl_err == SSL_ERROR_SYSCALL) ||
+      (cl->ssl_err == SSL_ERROR_SSL))
+    return -1;
+  if (num < 0)
+    return 0;
+  return num;
+}
+
+static int
+_ecore_con_ssl_client_write_openssl(Ecore_Con_Client *cl, char *buf, int size)
+{
+  int num;
+
+  num = SSL_write(cl->ssl, buf, size);
+  cl->ssl_err = SSL_get_error(cl->ssl, num);
+
+  if (cl->fd_handler)
+    {
+      if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_READ)
+       ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
+      else if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_WRITE)
+       ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
+    }
+
+  if ((cl->ssl_err == SSL_ERROR_ZERO_RETURN) ||
+      (cl->ssl_err == SSL_ERROR_SYSCALL) ||
+      (cl->ssl_err == SSL_ERROR_SSL))
+    return -1;
+  if (num < 0)
+    return 0;
+  return num;
+}
+
+#else
+
+/*
+ * No Ssl
+ */
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_init_none(void)
+{
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_shutdown_none(void)
+{
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static void
+_ecore_con_ssl_server_prepare_none(Ecore_Con_Server *svr)
+{
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_server_init_none(Ecore_Con_Server *svr)
+{
+  return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_server_shutdown_none(Ecore_Con_Server *svr)
+{
+  return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
+}
+
+/* Tries to connect an Ecore_Con_Server to an SSL host.
+ * Returns 1 on success, -1 on fatal errors and 0 if the caller
+ * should try again later.
+ */
+static Ecore_Con_State
+_ecore_con_ssl_server_try_none(Ecore_Con_Server *svr)
+{
+  return ECORE_CON_DISCONNECTED;
+}
+
+static int
+_ecore_con_ssl_server_read_none(Ecore_Con_Server *svr, char *buf, int size)
+{
+  return -1;
+}
+
+static int
+_ecore_con_ssl_server_write_none(Ecore_Con_Server *svr, char *buf, int size)
+{
+  return -1;
+}
+
+static void
+_ecore_con_ssl_client_prepare_none(Ecore_Con_Client *cl)
+{
+  return;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_client_init_none(Ecore_Con_Client *cl)
+{
+  return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_client_shutdown_none(Ecore_Con_Client *cl)
+{
+  return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
+}
+
+static int
+_ecore_con_ssl_client_read_none(Ecore_Con_Client *cl, char *buf, int size)
+{
+  return -1;
+}
+
+static int
+_ecore_con_ssl_client_write_none(Ecore_Con_Client *cl, char *buf, int size)
+{
+  return -1;
+}
+
+#endif
index 2eb6f98..f8813a8 100644 (file)
@@ -3,8 +3,10 @@
 
 #include "Ecore_Data.h"
 
-#if USE_OPENSSL
-#include <openssl/ssl.h>
+#if USE_GNUTLS_OPENSSL
+# include <gnutls/openssl.h>
+#elif USE_OPENSSL
+# include <openssl/ssl.h>
 #endif
 
 #define ECORE_MAGIC_IPC_SERVER             0x87786556