From 0bbca7c75d42ef7166255311e00b91162eeaaa70 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Wed, 28 Jul 2010 18:25:46 +0000 Subject: [PATCH] fix cert support, split functions for client/server note: crl checking and cert verification do not currently function SVN revision: 50603 --- legacy/ecore/src/lib/ecore_con/Ecore_Con.h | 26 +- legacy/ecore/src/lib/ecore_con/ecore_con.c | 58 ++- .../src/lib/ecore_con/ecore_con_private.h | 6 +- .../ecore/src/lib/ecore_con/ecore_con_ssl.c | 424 +++++++++++++----- 4 files changed, 384 insertions(+), 130 deletions(-) diff --git a/legacy/ecore/src/lib/ecore_con/Ecore_Con.h b/legacy/ecore/src/lib/ecore_con/Ecore_Con.h index 2146bb5457..bc7ba4d7c7 100644 --- a/legacy/ecore/src/lib/ecore_con/Ecore_Con.h +++ b/legacy/ecore/src/lib/ecore_con/Ecore_Con.h @@ -213,7 +213,10 @@ EAPI extern int ECORE_CON_EVENT_URL_PROGRESS; /** A URL object has made progress EAPI int ecore_con_init(void); EAPI int ecore_con_shutdown(void); -EAPI Eina_Bool ecore_con_ssl_cert_add(const char *cert); +EAPI Eina_Bool ecore_con_server_ssl_cert_add(const char *cert); +EAPI Eina_Bool ecore_con_client_ssl_cert_add(const char *cert_file, + const char *crl_file, + const char *key_file); EAPI Ecore_Con_Server *ecore_con_server_add(Ecore_Con_Type type, const char *name, int port, @@ -229,9 +232,11 @@ EAPI Eina_List * ecore_con_server_clients_get(Ecore_Con_Server *svr); EAPI int ecore_con_server_send(Ecore_Con_Server *svr, const void *data, int size); -EAPI void ecore_con_server_client_limit_set(Ecore_Con_Server *svr, - int client_limit, - char reject_excess_clients); +EAPI void ecore_con_server_client_limit_set( + Ecore_Con_Server *svr, + int client_limit, + char + reject_excess_clients); EAPI char * ecore_con_server_ip_get(Ecore_Con_Server *svr); EAPI void ecore_con_server_flush(Ecore_Con_Server *svr); @@ -257,11 +262,14 @@ EAPI void ecore_con_url_destroy(Ecore_Con_Url *url_con); EAPI void ecore_con_url_data_set(Ecore_Con_Url *url_con, void *data); EAPI void * ecore_con_url_data_get(Ecore_Con_Url *url_con); -EAPI void ecore_con_url_additional_header_add(Ecore_Con_Url *url_con, - const char *key, - const char *value); -EAPI void ecore_con_url_additional_headers_clear(Ecore_Con_Url *url_con); -EAPI const Eina_List * ecore_con_url_response_headers_get(Ecore_Con_Url *url_con); +EAPI void ecore_con_url_additional_header_add( + Ecore_Con_Url *url_con, + const char *key, + const char *value); +EAPI void ecore_con_url_additional_headers_clear( + Ecore_Con_Url *url_con); +EAPI const Eina_List * ecore_con_url_response_headers_get( + Ecore_Con_Url *url_con); EAPI int ecore_con_url_url_set(Ecore_Con_Url *url_con, const char *url); EAPI void ecore_con_url_fd_set(Ecore_Con_Url *url_con, int fd); diff --git a/legacy/ecore/src/lib/ecore_con/ecore_con.c b/legacy/ecore/src/lib/ecore_con/ecore_con.c index e6b87ac511..2e8dcc53f7 100644 --- a/legacy/ecore/src/lib/ecore_con/ecore_con.c +++ b/legacy/ecore/src/lib/ecore_con/ecore_con.c @@ -206,7 +206,7 @@ ecore_con_server_add(Ecore_Con_Type compl_type, const char *name, int port, Ecore_Con_Type type; if (port < 0 || !name) - return NULL; /* local user socket: FILE: ~/.ecore/[name]/[port] */ + return NULL; /* local user socket: FILE: ~/.ecore/[name]/[port] */ /* local system socket: FILE: /tmp/.ecore_service|[name]|[port] */ /* remote system socket: TCP/IP: [name]:[port] */ @@ -317,7 +317,7 @@ ecore_con_server_connect(Ecore_Con_Type compl_type, const char *name, int port, Ecore_Con_Type type; if (!name) - return NULL; /* local user socket: FILE: ~/.ecore/[name]/[port] */ + return NULL; /* local user socket: FILE: ~/.ecore/[name]/[port] */ /* local system socket: FILE: /tmp/.ecore_service|[name]|[port] */ /* remote system socket: TCP/IP: [name]:[port] */ @@ -910,29 +910,57 @@ on_error: } /** - * Add an ssl certificate for use in ecore_con functions. + * Add an ssl certificate for use in ecore_con_server functions. * - * Use this function to add a SSL PEM certificate to your ecore_con clients - * and servers. Simply specify the cert here to make it available, - * then OR the @ref ECORE_CON_LOAD_CERT flag into the @ref ecore_con_server_add or - * @ref ecore_con_server_connect call to use it. If there is an error loading the - * certificate upon creating the connection, an error will be automatically logged. + * Use this function to add a SSL PEM certificate. + * Simply specify the cert here to make it available, + * then OR the @ref ECORE_CON_LOAD_CERT flag into the @ref ecore_con_server_connect + * call to use it. If there is an error loading the certificate upon creating + * the connection, an error will be automatically logged. * @param cert The path to the certificate. - * @return EINA_FALSE if the file does not exist or does not end with the 'pem' suffix, + * @return EINA_FALSE if the file cannot be loaded, * otherwise EINA_TRUE. + * @note Currently certificate verification is not implemented. */ EAPI Eina_Bool -ecore_con_ssl_cert_add(const char *cert) +ecore_con_server_ssl_cert_add(const char *cert) { - struct stat st; - if (stat(cert, - &st) || !eina_str_has_extension(cert, "pem")) + if (!eina_str_has_extension(cert, "pem")) return EINA_FALSE; - _ecore_con_ssl_cert_add(cert); - return EINA_TRUE; + return ecore_con_ssl_server_cert_add(cert); +} + +/** + * @brief Add an ssl certificate for use in ecore_con_client functions. + * + * Use this function to add a SSL PEM certificate. + * Simply specify the cert here to make it available, + * then OR the @ref ECORE_CON_LOAD_CERT flag into the @ref ecore_con_server_add + * call to use it. If there is an error loading the certificate upon creating + * the connection, an error will be automatically logged. + * @param cert_file The path to the certificate. + * @param crl_file The path to the CRL file + * @param key_file The path to the private key file. If not specified, the private key + * from the cert will be loaded. + * @return EINA_FALSE if the file cannot be loaded, + * otherwise EINA_TRUE. + * @note Currently CRL file adding and certificate verification is not implemented, + * so specifying it here has no effect. + */ + +EAPI Eina_Bool +ecore_con_client_ssl_cert_add(const char *cert_file, + const char *crl_file, + const char *key_file) +{ + + if (!eina_str_has_extension(cert_file, "pem")) + return EINA_FALSE; + + return ecore_con_ssl_client_cert_add(cert_file, crl_file, key_file); } static void 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 439cbac8f1..feaa9aa7e7 100644 --- a/legacy/ecore/src/lib/ecore_con/ecore_con_private.h +++ b/legacy/ecore/src/lib/ecore_con/ecore_con_private.h @@ -211,8 +211,10 @@ int ecore_con_info_mcast_listen(Ecore_Con_Server *svr, /* from ecore_con_ssl.c */ Ecore_Con_Ssl_Error ecore_con_ssl_init(void); Ecore_Con_Ssl_Error ecore_con_ssl_shutdown(void); -void _ecore_con_ssl_server_cert_add(Ecore_Con_Server *svr, - const char *cert); +Eina_Bool ecore_con_ssl_server_cert_add(const char *cert); +Eina_Bool ecore_con_ssl_client_cert_add(const char *cert_file, + const char *crl_file, + const char *key_file); void ecore_con_ssl_server_prepare(Ecore_Con_Server *svr); Ecore_Con_Ssl_Error ecore_con_ssl_server_init(Ecore_Con_Server *svr); Ecore_Con_Ssl_Error ecore_con_ssl_server_shutdown(Ecore_Con_Server *svr); diff --git a/legacy/ecore/src/lib/ecore_con/ecore_con_ssl.c b/legacy/ecore/src/lib/ecore_con/ecore_con_ssl.c index 5613ffdc1d..1978885119 100644 --- a/legacy/ecore/src/lib/ecore_con/ecore_con_ssl.c +++ b/legacy/ecore/src/lib/ecore_con/ecore_con_ssl.c @@ -8,6 +8,8 @@ #if USE_GNUTLS # include +# include +# include #elif USE_OPENSSL # include # include @@ -19,16 +21,22 @@ #include "Ecore.h" #include "ecore_con_private.h" +#include +#include static int _init_con_ssl_init_count = 0; #if USE_GNUTLS -static int _client_connected = 0; +# ifdef EFL_HAVE_PTHREAD +GCRY_THREAD_OPTION_PTHREAD_IMPL; +# endif +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 @@ -38,39 +46,62 @@ static int _client_connected = 0; #endif -static const char *certificate = NULL; +#if USE_GNUTLS +static gnutls_certificate_credentials_t client_cert = NULL; +static gnutls_certificate_credentials_t server_cert = NULL; +#elif USE_OPENSSL +static EVP_PKEY *private_key = NULL; +static int private_count = 0; +static X509 *client_cert = NULL; +static X509 *server_cert = NULL; +#endif + +static int client_count = 0; +static int server_count = 0; static Ecore_Con_Ssl_Error -SSL_SUFFIX(_ecore_con_ssl_init) (void); + SSL_SUFFIX(_ecore_con_ssl_init) (void); static Ecore_Con_Ssl_Error -SSL_SUFFIX(_ecore_con_ssl_shutdown) (void); + SSL_SUFFIX(_ecore_con_ssl_shutdown) (void); -static void -SSL_SUFFIX(_ecore_con_ssl_server_prepare) (Ecore_Con_Server * svr); +static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_client_cert_add) (const char * + cert_file, + const char * + crl_file, + const char * + key_file); +static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_cert_add) (const char *cert); + +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); + 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); + 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); + SSL_SUFFIX(_ecore_con_ssl_server_try) (Ecore_Con_Server * svr); static int -SSL_SUFFIX(_ecore_con_ssl_server_read) (Ecore_Con_Server * svr, + SSL_SUFFIX(_ecore_con_ssl_server_read) (Ecore_Con_Server * svr, unsigned char *buf, int size); static int -SSL_SUFFIX(_ecore_con_ssl_server_write) (Ecore_Con_Server * svr, + SSL_SUFFIX(_ecore_con_ssl_server_write) (Ecore_Con_Server * + svr, unsigned char *buf, int size); static void -SSL_SUFFIX(_ecore_con_ssl_client_prepare) (Ecore_Con_Client * cl); + 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); + 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); + SSL_SUFFIX(_ecore_con_ssl_client_shutdown) (Ecore_Con_Client * + cl); static int -SSL_SUFFIX(_ecore_con_ssl_client_read) (Ecore_Con_Client * cl, + SSL_SUFFIX(_ecore_con_ssl_client_read) (Ecore_Con_Client * cl, unsigned char *buf, int size); static int -SSL_SUFFIX(_ecore_con_ssl_client_write) (Ecore_Con_Client * cl, + SSL_SUFFIX(_ecore_con_ssl_client_write) (Ecore_Con_Client * cl, unsigned char *buf, int size); /* @@ -81,7 +112,7 @@ Ecore_Con_Ssl_Error ecore_con_ssl_init(void) { if (!_init_con_ssl_init_count++) - SSL_SUFFIX(_ecore_con_ssl_init) (); + SSL_SUFFIX(_ecore_con_ssl_init) (); return _init_con_ssl_init_count; } @@ -91,22 +122,17 @@ ecore_con_ssl_shutdown(void) { if (!--_init_con_ssl_init_count) { - if (certificate) - eina_stringshare_del(certificate); - - certificate = NULL; + client_count = 0; + server_count = 0; +#ifdef USE_OPENSSL + private_count = 0; +#endif SSL_SUFFIX(_ecore_con_ssl_shutdown) (); } return _init_con_ssl_init_count; } -void -_ecore_con_ssl_cert_add(const char *cert) -{ - eina_stringshare_replace(&certificate, cert); -} - /** * Returns if SSL support is available * @return 1 if SSL is available, 0 if it is not. @@ -122,7 +148,7 @@ ecore_con_ssl_available_get(void) void ecore_con_ssl_server_prepare(Ecore_Con_Server *svr) { - SSL_SUFFIX(_ecore_con_ssl_server_prepare) (svr); + SSL_SUFFIX(_ecore_con_ssl_server_prepare) (svr); } Ecore_Con_Ssl_Error @@ -131,6 +157,12 @@ ecore_con_ssl_server_init(Ecore_Con_Server *svr) return SSL_SUFFIX(_ecore_con_ssl_server_init) (svr); } +Eina_Bool +ecore_con_ssl_server_cert_add(const char *cert) +{ + return SSL_SUFFIX(_ecore_con_ssl_server_cert_add) (cert); +} + Ecore_Con_Ssl_Error ecore_con_ssl_server_shutdown(Ecore_Con_Server *svr) { @@ -161,6 +193,15 @@ ecore_con_ssl_client_init(Ecore_Con_Client *cl) return SSL_SUFFIX(_ecore_con_ssl_client_init) (cl); } +Eina_Bool +ecore_con_ssl_client_cert_add(const char *cert_file, + const char *crl_file, + const char *key_file) +{ + return SSL_SUFFIX(_ecore_con_ssl_client_cert_add) (cert_file, crl_file, + key_file); +} + Ecore_Con_Ssl_Error ecore_con_ssl_client_shutdown(Ecore_Con_Client *cl) { @@ -188,6 +229,12 @@ ecore_con_ssl_client_write(Ecore_Con_Client *cl, unsigned char *buf, int size) static Ecore_Con_Ssl_Error _ecore_con_ssl_init_gnutls(void) { +#ifdef EFL_HAVE_PTHREAD + if (gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread)) + WRN( + "YOU ARE USING PTHREADS, BUT I CANNOT INITIALIZE THREADSAFE GCRYPT OPERATIONS!"); + +#endif if (gnutls_global_init()) return ECORE_CON_SSL_ERROR_INIT_FAILED; @@ -207,7 +254,6 @@ _ecore_con_ssl_server_prepare_gnutls(Ecore_Con_Server *svr) { svr->session = NULL; svr->anoncred_c = NULL; - svr->cert = NULL; return; } @@ -244,39 +290,27 @@ _ecore_con_ssl_server_init_gnutls(Ecore_Con_Server *svr) return ECORE_CON_SSL_ERROR_NONE; } - if (certificate && (svr->type & ECORE_CON_LOAD_CERT)) + if (server_cert && (svr->type & ECORE_CON_LOAD_CERT)) { - - gnutls_certificate_allocate_credentials(&(svr->cert)); - ret = gnutls_certificate_set_x509_trust_file(svr->cert, certificate, - GNUTLS_X509_FMT_PEM); - if (ret < 1) - { - ERR("ssl cert load failed: %s", gnutls_strerror(ret)); - if (svr->cert) - { - gnutls_certificate_free_credentials(svr->cert); - svr->cert = NULL; - } - } + svr->cert = server_cert; + server_count++; } - if (!svr->cert) - gnutls_anon_allocate_client_credentials(&(svr->anoncred_c)); - gnutls_init(&(svr->session), GNUTLS_CLIENT); - svr->cert = NULL; gnutls_set_default_priority(svr->session); gnutls_kx_set_priority(svr->session, kx); if (svr->cert) gnutls_credentials_set(svr->session, GNUTLS_CRD_CERTIFICATE, svr->cert); else - gnutls_credentials_set(svr->session, GNUTLS_CRD_ANON, svr->anoncred_c); + { + gnutls_anon_allocate_client_credentials(&svr->anoncred_c); + gnutls_credentials_set(svr->session, GNUTLS_CRD_ANON, svr->anoncred_c); + } - gnutls_kx_set_priority(svr->session, kx); + gnutls_kx_set_priority(svr->session, kx); gnutls_protocol_set_priority(svr->session, proto); - gnutls_dh_set_prime_bits(svr->session, 512); + gnutls_dh_set_prime_bits(svr->session, 2048); gnutls_transport_set_ptr(svr->session, (gnutls_transport_ptr_t)svr->fd); @@ -293,6 +327,32 @@ _ecore_con_ssl_server_init_gnutls(Ecore_Con_Server *svr) return ECORE_CON_SSL_ERROR_NONE; } +static Eina_Bool +_ecore_con_ssl_server_cert_add_gnutls(const char *cert_file) +{ + gnutls_certificate_credentials_t cert = NULL; + + /* cert load */ + if (gnutls_certificate_set_x509_trust_file(cert, cert_file, + GNUTLS_X509_FMT_PEM) < 0) + goto on_error; + + gnutls_certificate_free_credentials(cert); + if ((server_cert) && ((--server_count) < 1)) + gnutls_certificate_free_credentials(server_cert); + + server_cert = cert; + server_count = 1; + + return EINA_TRUE; + +on_error: + if (cert) + gnutls_certificate_free_credentials(cert); + + return EINA_FALSE; +} + static Ecore_Con_Ssl_Error _ecore_con_ssl_server_shutdown_gnutls(Ecore_Con_Server *svr) { @@ -302,8 +362,12 @@ _ecore_con_ssl_server_shutdown_gnutls(Ecore_Con_Server *svr) gnutls_deinit(svr->session); } - if (svr->cert) - gnutls_certificate_free_credentials(svr->cert); + if ((svr->type & ECORE_CON_LOAD_CERT) && (server_cert) && + (--server_count < 1)) + { + gnutls_certificate_free_credentials(server_cert); + server_cert = NULL; + } else if (svr->anoncred_c) gnutls_anon_free_client_credentials(svr->anoncred_c); @@ -405,48 +469,39 @@ _ecore_con_ssl_client_init_gnutls(Ecore_Con_Client *cl) _client_connected++; - if (certificate && (cl->server->type & ECORE_CON_LOAD_CERT)) - { + gnutls_dh_params_init(&dh_params); + gnutls_dh_params_generate2(dh_params, 1024); - gnutls_certificate_allocate_credentials(&(cl->server->cert)); - ret = - gnutls_certificate_set_x509_trust_file(cl->server->cert, certificate, - GNUTLS_X509_FMT_PEM); - if (ret < 1) - { - ERR("ssl cert load failed: %s", gnutls_strerror(ret)); - if (cl->server->cert) - { - gnutls_certificate_free_credentials(cl->server->cert); - cl->server->cert = NULL; - } - } + if (client_cert && (cl->server->type & ECORE_CON_LOAD_CERT)) + { + cl->server->cert = client_cert; + client_count++; + gnutls_certificate_set_dh_params(cl->server->cert, dh_params); } - if (!cl->server->anoncred_s && !cl->server->cert) + if ((!cl->server->anoncred_s) && (!cl->server->cert)) { 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); - if (!cl->server->cert) - gnutls_credentials_set(cl->session, - GNUTLS_CRD_CERTIFICATE, - cl->server->cert); + if (cl->server->cert) + { + gnutls_credentials_set(cl->session, + GNUTLS_CRD_CERTIFICATE, + cl->server->cert); + gnutls_certificate_server_set_request(cl->session, GNUTLS_CERT_REQUEST); + } else gnutls_credentials_set(cl->session, GNUTLS_CRD_ANON, cl->server->anoncred_s); - gnutls_kx_set_priority(cl->session, kx); + 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) @@ -459,6 +514,7 @@ _ecore_con_ssl_client_init_gnutls(Ecore_Con_Client *cl) return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; } + /* TODO: add cert verification support */ return ECORE_CON_SSL_ERROR_NONE; } @@ -471,20 +527,67 @@ _ecore_con_ssl_client_shutdown_gnutls(Ecore_Con_Client *cl) gnutls_deinit(cl->session); } - if (!cl->server->cert && cl->server->anoncred_s && - !--_client_connected) - gnutls_anon_free_server_credentials( - cl->server->anoncred_s); - else if (cl->server->cert && - !--_client_connected) - gnutls_certificate_free_credentials( - cl->server->cert); + if (cl->server->anoncred_s && !--_client_connected) + gnutls_anon_free_server_credentials(cl->server->anoncred_s); + + if ((cl->server->type & ECORE_CON_LOAD_CERT) && (client_cert) && + (--client_count < 1)) + { + gnutls_certificate_free_credentials(client_cert); + client_cert = NULL; + } _ecore_con_ssl_client_prepare_gnutls(cl); return ECORE_CON_SSL_ERROR_NONE; } +static Eina_Bool +_ecore_con_ssl_client_cert_add_gnutls(const char *cert_file, + const char *crl_file, + const char *key_file) +{ + gnutls_certificate_credentials_t cert = NULL; + + if (gnutls_certificate_allocate_credentials(&cert) < 0) + return EINA_FALSE; + + /* cert load */ + if (gnutls_certificate_set_x509_trust_file(cert, cert_file, + GNUTLS_X509_FMT_PEM) < 0) + goto on_error; + + /* private key load */ + if (gnutls_certificate_set_x509_key_file(cert, cert_file, key_file, + GNUTLS_X509_FMT_PEM) < 0) + goto on_error; + +#if 0 + //TODO: uncomment once we implement cert checking + if (crl_file) + /* CRL file load */ + if (gnutls_certificate_set_x509_crl_mem(cert, crl_file, + GNUTLS_X509_FMT_PEM) < 0) + goto on_error; + +} +#endif + + if ((client_cert) && ((--client_count) < 1)) + gnutls_certificate_free_credentials(client_cert); + + client_cert = cert; + client_count = 1; + + return EINA_TRUE; + +on_error: + if (cert) + gnutls_certificate_free_credentials(cert); + + return EINA_FALSE; +} + static int _ecore_con_ssl_client_read_gnutls(Ecore_Con_Client *cl, unsigned char *buf, int size) @@ -590,21 +693,54 @@ _ecore_con_ssl_server_init_openssl(Ecore_Con_Server *svr) return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; } - if (certificate && (svr->type & ECORE_CON_LOAD_CERT)) - //FIXME: just log and go on without cert if loading fails? - if (!SSL_CTX_use_certificate_file(svr->ssl_ctx, certificate, - SSL_FILETYPE_PEM) || - !SSL_CTX_use_PrivateKey_file(svr->ssl_ctx, certificate, - SSL_FILETYPE_PEM) || - !SSL_CTX_check_private_key(svr->ssl_ctx)) - ERR( - "ssl cert load failed: %s", ERR_reason_error_string(ERR_get_error())); + if (server_cert && (svr->type & ECORE_CON_LOAD_CERT)) + { + //FIXME: just log and go on without cert if loading fails? + if (!SSL_CTX_use_certificate(svr->ssl_ctx, server_cert)) + ERR( + "ssl cert load failed: %s", ERR_reason_error_string(ERR_get_error())); + + server_count++; + } SSL_set_fd(svr->ssl, svr->fd); return ECORE_CON_SSL_ERROR_NONE; } +static Eina_Bool +_ecore_con_ssl_server_cert_add_openssl(const char *cert_file) +{ + FILE *fp; + X509 *cert; + const X509 *tmp2; + + + if (!(fp = fopen(certificate_file, "r"))) + goto on_error; + + if (!(cert = PEM_read_X509(fp, NULL, NULL, NULL))) + goto on_error; + + fclose(fp); + + + if ((server_cert) && (--server_count < 1)) + X509_free(server_cert); + + server_cert = cert; + + server_count = 1; + + return EINA_TRUE; + +on_error: + if (fp) + fclose(fp); + + return EINA_FALSE; +} + static Ecore_Con_Ssl_Error _ecore_con_ssl_server_shutdown_openssl(Ecore_Con_Server *svr) { @@ -616,6 +752,13 @@ _ecore_con_ssl_server_shutdown_openssl(Ecore_Con_Server *svr) SSL_free(svr->ssl); } + if ((svr->type & ECORE_CON_LOAD_CERT) && (server_cert) && + (--server_count < 1)) + { + X509_free(server_cert); + server_cert = NULL; + } + if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx); @@ -775,21 +918,79 @@ _ecore_con_ssl_client_init_openssl(Ecore_Con_Client *cl) return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; } - if (certificate && (cl->server->type & ECORE_CON_LOAD_CERT)) - //FIXME: just log and go on without cert if loading fails? - if (!SSL_CTX_use_certificate_file(cl->server->ssl_ctx, certificate, - SSL_FILETYPE_PEM) || - !SSL_CTX_use_PrivateKey_file(cl->server->ssl_ctx, certificate, - SSL_FILETYPE_PEM) || - !SSL_CTX_check_private_key(cl->server->ssl_ctx)) - ERR( - "ssl cert load failed: %s", ERR_reason_error_string(ERR_get_error())); + if ((client_cert) && (private_key) && + (cl->server->type & ECORE_CON_LOAD_CERT)) + { + //FIXME: just log and go on without cert if loading fails? + if (!SSL_CTX_use_certificate(cl->server->ssl_ctx, client_cert) || + !SSL_CTX_use_PrivateKey(cl->server->ssl_ctx, private_key) || + !SSL_CTX_check_private_key(cl->server->ssl_ctx)) + ERR( + "ssl cert load failed: %s", ERR_reason_error_string(ERR_get_error())); + + client_count++; + private_count++; + } SSL_set_fd(cl->ssl, cl->fd); return ECORE_CON_SSL_ERROR_NONE; } + +static Eina_Bool +_ecore_con_ssl_client_cert_add_openssl(const char *cert_file, + const char *crl_file, + const char *key_file) +{ + FILE *fp = NULL; + EVP_PKEY *privkey = NULL; + X509 *cert = NULL; + + if (!(fp = fopen(cert_file, "r"))) + goto on_error; + + if (!(cert = PEM_read_X509(fp, NULL, NULL, NULL))) + goto on_error; + + if (key_file) + { + fclose(fp); + if (!(fp = fopen(key_file, "r"))) + goto on_error; + } + + if (!(privkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL))) + goto on_error; + + fclose(fp); + + if ((client_cert) && (--client_count < 1)) + X509_free(client_cert); + + if ((private_key) && ((--private_count) < 1)) + EVP_KEY_free(private_key); + + private_key = privkey; + client_cert = cert; + + private_count = client_count = 1; + + return EINA_TRUE; + +on_error: + if (fp) + fclose(fp); + + if (cert) + X509_free(cert); + + if (privkey) + EVP_KEY_free(privkey); + + return EINA_FALSE; +} + static Ecore_Con_Ssl_Error _ecore_con_ssl_client_shutdown_openssl(Ecore_Con_Client *cl) { @@ -802,7 +1003,22 @@ _ecore_con_ssl_client_shutdown_openssl(Ecore_Con_Client *cl) } if (cl->ssl_ctx) - SSL_CTX_free(cl->ssl_ctx); + { + SSL_CTX_free(cl->ssl_ctx); + if ((cl->server->type & ECORE_CON_LOAD_CERT) && (client_cert) && + (--client_count < 1)) + { + X509_free(client_cert); + client_cert = NULL; + } + + if ((cl->server->type & ECORE_CON_LOAD_CERT) && (private_key) && + (--private_count < 1)) + { + EVP_PKEY_free(private_key); + private_key = NULL; + } + } _ecore_con_ssl_client_prepare_openssl(cl);