Add support for GNU TLS in ecore_con.

SVN revision: 37329
This commit is contained in:
Cedric BAIL 2008-10-30 15:26:11 +00:00
parent 8748f83f01
commit 6d2ca9c036
6 changed files with 1052 additions and 414 deletions

View 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"

View 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

View File

@ -10,10 +10,6 @@
#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];
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

View 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"
@ -11,8 +12,10 @@
#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>
@ -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

View File

@ -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

View 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