From 6d2ca9c036fbd45b39996caac500642479436787 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Thu, 30 Oct 2008 15:26:11 +0000 Subject: [PATCH] Add support for GNU TLS in ecore_con. SVN revision: 37329 --- legacy/ecore/configure.ac | 45 +- legacy/ecore/src/lib/ecore_con/Makefile.am | 6 +- legacy/ecore/src/lib/ecore_con/ecore_con.c | 602 +++++--------- .../src/lib/ecore_con/ecore_con_private.h | 39 +- .../ecore/src/lib/ecore_con/ecore_con_ssl.c | 768 ++++++++++++++++++ .../src/lib/ecore_ipc/ecore_ipc_private.h | 6 +- 6 files changed, 1052 insertions(+), 414 deletions(-) create mode 100644 legacy/ecore/src/lib/ecore_con/ecore_con_ssl.c diff --git a/legacy/ecore/configure.ac b/legacy/ecore/configure.ac index fb194fd042..960c48d84b 100644 --- a/legacy/ecore/configure.ac +++ b/legacy/ecore/configure.ac @@ -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" diff --git a/legacy/ecore/src/lib/ecore_con/Makefile.am b/legacy/ecore/src/lib/ecore_con/Makefile.am index b1923f5649..2bf5575e4f 100644 --- a/legacy/ecore/src/lib/ecore_con/Makefile.am +++ b/legacy/ecore/src/lib/ecore_con/Makefile.am @@ -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 diff --git a/legacy/ecore/src/lib/ecore_con/ecore_con.c b/legacy/ecore/src/lib/ecore_con/ecore_con.c index ceb339c93f..07eea62420 100644 --- a/legacy/ecore/src/lib/ecore_con/ecore_con.c +++ b/legacy/ecore/src/lib/ecore_con/ecore_con.c @@ -10,10 +10,6 @@ #include -#if USE_OPENSSL -#include -#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]; + int num; + int lost_server = 1; + 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; + 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; - 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; - } + 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 - } + + if (!(svr->type & ECORE_CON_SSL)) + count = write(svr->fd, svr->write_buf + svr->write_buf_offset, num); else - { - count = SSL_write(svr->ssl, svr->write_buf + svr->write_buf_offset, num); + count = ecore_con_ssl_server_write(svr, 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 (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 diff --git a/legacy/ecore/src/lib/ecore_con/ecore_con_private.h b/legacy/ecore/src/lib/ecore_con/ecore_con_private.h index ee05b94f75..db9fb60092 100644 --- a/legacy/ecore/src/lib/ecore_con/ecore_con_private.h +++ b/legacy/ecore/src/lib/ecore_con/ecore_con_private.h @@ -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" @@ -11,8 +12,10 @@ #define ECORE_CON_TYPE 0x0f #define ECORE_CON_SSL 0xf0 -#if USE_OPENSSL -#include +#if USE_GNUTLS +# include +#elif USE_OPENSSL +# include #endif #ifdef HAVE_CURL #include @@ -22,11 +25,20 @@ 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/legacy/ecore/src/lib/ecore_con/ecore_con_ssl.c b/legacy/ecore/src/lib/ecore_con/ecore_con_ssl.c new file mode 100644 index 0000000000..3d8164041c --- /dev/null +++ b/legacy/ecore/src/lib/ecore_con/ecore_con_ssl.c @@ -0,0 +1,768 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#if USE_GNUTLS +# include +#elif USE_OPENSSL +# include +#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 diff --git a/legacy/ecore/src/lib/ecore_ipc/ecore_ipc_private.h b/legacy/ecore/src/lib/ecore_ipc/ecore_ipc_private.h index 2eb6f98a3c..f8813a8999 100644 --- a/legacy/ecore/src/lib/ecore_ipc/ecore_ipc_private.h +++ b/legacy/ecore/src/lib/ecore_ipc/ecore_ipc_private.h @@ -3,8 +3,10 @@ #include "Ecore_Data.h" -#if USE_OPENSSL -#include +#if USE_GNUTLS_OPENSSL +# include +#elif USE_OPENSSL +# include #endif #define ECORE_MAGIC_IPC_SERVER 0x87786556