summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@samsung.com>2015-01-26 15:49:05 +0100
committerCedric BAIL <cedric@osg.samsung.com>2015-02-16 14:47:48 +0100
commitd56a8f9fd01c2b8c453b8619cc8c63339d50fe51 (patch)
tree2c6d330975cac60bfac670874154c4f79629c9a6
parenta69aa000ee96b6f1c59bb50df1c0a0a79a55bfc9 (diff)
downloadefl-d56a8f9fd01c2b8c453b8619cc8c63339d50fe51.tar.gz
emile: Add SSL support.
-rw-r--r--src/lib/ecore_con/ecore_con_ssl.c2
-rw-r--r--src/lib/emile/Emile.h36
-rw-r--r--src/lib/emile/emile_cipher.c110
-rw-r--r--src/lib/emile/emile_cipher_gnutls.c312
-rw-r--r--src/lib/emile/emile_cipher_openssl.c844
-rw-r--r--src/lib/emile/emile_main.c2
-rw-r--r--src/lib/emile/emile_private.h8
7 files changed, 1311 insertions, 3 deletions
diff --git a/src/lib/ecore_con/ecore_con_ssl.c b/src/lib/ecore_con/ecore_con_ssl.c
index 7e416ec8ee..5d7bbcbb2b 100644
--- a/src/lib/ecore_con/ecore_con_ssl.c
+++ b/src/lib/ecore_con/ecore_con_ssl.c
@@ -1498,8 +1498,6 @@ _ecore_con_ssl_client_write_gnutls(Ecore_Con_Client *obj,
*/
static Ecore_Con_Ssl_Error
-
-static Ecore_Con_Ssl_Error
_ecore_con_ssl_server_prepare_openssl(Ecore_Con_Server *obj,
int ssl_type)
{
diff --git a/src/lib/emile/Emile.h b/src/lib/emile/Emile.h
index b97c30eafe..47a9186d3b 100644
--- a/src/lib/emile/Emile.h
+++ b/src/lib/emile/Emile.h
@@ -106,7 +106,24 @@ EAPI int emile_shutdown(void);
* @}
*/
+typedef struct _Emile_SSL Emile_SSL;
+
+typedef enum
+{
+ EMILE_SSLv23,
+ EMILE_SSLv3,
+ EMILE_TLSv1
+} Emile_Cipher_Type;
+
+typedef enum
+{
+ EMILE_WANT_NOTHING = 0,
+ EMILE_WANT_READ = 1,
+ EMILE_WANT_WRITE = 3
+} Emile_Want_Type;
+
EAPI Eina_Bool emile_cipher_init(void);
+EAPI const char *emile_cipher_module_get(void);
EAPI Eina_Binbuf *emile_binbuf_cipher(const Eina_Binbuf *in,
const char *key, unsigned int length);
@@ -114,6 +131,25 @@ EAPI Eina_Binbuf *emile_binbuf_cipher(const Eina_Binbuf *in,
EAPI Eina_Binbuf *emile_binbuf_decipher(const Eina_Binbuf *in,
const char *key, unsigned int length);
+EAPI Emile_SSL *emile_cipher_server_listen(Emile_Cipher_Type t);
+EAPI Emile_SSL *emile_cipher_client_connect(Emile_SSL *server, int fd);
+EAPI Emile_SSL *emile_cipher_server_connect(Emile_Cipher_Type t);
+EAPI Eina_Bool emile_cipher_free(Emile_SSL *emile);
+
+EAPI Eina_Bool emile_cipher_cafile_add(Emile_SSL *emile, const char *file);
+EAPI Eina_Bool emile_cipher_cert_add(Emile_SSL *emile, const char *file);
+EAPI Eina_Bool emile_cipher_privkey_add(Emile_SSL *emile, const char *file);
+EAPI Eina_Bool emile_cipher_crl_add(Emile_SSL *emile, const char *file);
+EAPI int emile_cipher_read(Emile_SSL *emile, Eina_Binbuf *buffer);
+EAPI int emile_cipher_write(Emile_SSL *emile, const Eina_Binbuf *buffer);
+EAPI const char *emile_cipher_error_get(const Emile_SSL *emile);
+EAPI Eina_Bool emile_cipher_verify_name_set(Emile_SSL *emile, const char *name);
+EAPI const char *emile_cipher_verify_name_get(const Emile_SSL *emile);
+EAPI void emile_cipher_verify_set(Emile_SSL *emile, Eina_Bool verify);
+EAPI void emile_cipher_verify_basic_set(Emile_SSL *emile, Eina_Bool verify_basic);
+EAPI Eina_Bool emile_cipher_verify_get(const Emile_SSL *emile);
+EAPI Eina_Bool emile_cipher_verify_basic_get(const Emile_SSL *emile);
+
typedef enum
{
EMILE_ZLIB,
diff --git a/src/lib/emile/emile_cipher.c b/src/lib/emile/emile_cipher.c
index 3af06886b9..3c5fd185cc 100644
--- a/src/lib/emile/emile_cipher.c
+++ b/src/lib/emile/emile_cipher.c
@@ -28,3 +28,113 @@ emile_binbuf_decipher(const Eina_Binbuf *data EINA_UNUSED,
{
return NULL;
}
+
+EAPI Emile_SSL *
+emile_cipher_server_listen(Emile_Cipher_Type t EINA_UNUSED)
+{
+ return NULL;
+}
+
+EAPI Emile_SSL *
+emile_cipher_client_connect(Emile_SSL *server EINA_UNUSED, int fd EINA_UNUSED)
+{
+ return NULL;
+}
+
+EAPI Emile_SSL *
+emile_cipher_server_connect(Emile_Cipher_Type t EINA_UNUSED)
+{
+ return NULL;
+}
+
+EAPI Eina_Bool
+emile_cipher_free(Emile_SSL *emile EINA_UNUSED)
+{
+ return EINA_TRUE;
+}
+
+EAPI Eina_Bool
+emile_cipher_cafile_add(Emile_SSL *emile EINA_UNUSED,
+ const char *file EINA_UNUSED)
+{
+ return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+emile_cipher_cert_add(Emile_SSL *emile EINA_UNUSED,
+ const char *file EINA_UNUSED)
+{
+ return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+emile_cipher_privkey_add(Emile_SSL *emile EINA_UNUSED,
+ const char *file EINA_UNUSED)
+{
+ return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+emile_cipher_crl_add(Emile_SSL *emile EINA_UNUSED,
+ const char *file EINA_UNUSED)
+{
+ return EINA_FALSE;
+}
+
+EAPI int
+emile_cipher_read(Emile_SSL *emile EINA_UNUSED,
+ Eina_Binbuf *buffer EINA_UNUSED)
+{
+ return EINA_FALSE;
+}
+
+EAPI int
+emile_cipher_write(Emile_SSL *emile EINA_UNUSED,
+ const Eina_Binbuf *buffer EINA_UNUSED)
+{
+ return EINA_FALSE;
+}
+
+
+EAPI const char *
+emile_cipher_error_get(const Emile_SSL *emile EINA_UNUSED)
+{
+ return NULL;
+}
+
+EAPI Eina_Bool
+emile_cipher_verify_name_set(Emile_SSL *emile EINA_UNUSED,
+ const char *name EINA_UNUSED)
+{
+ return EINA_FALSE;
+}
+
+EAPI const char *
+emile_cipher_verify_name_get(const Emile_SSL *emile EINA_UNUSED)
+{
+ return NULL;
+}
+
+EAPI void
+emile_cipher_verify_set(Emile_SSL *emile EINA_UNUSED,
+ Eina_Bool verify EINA_UNUSED)
+{
+}
+
+EAPI void
+emile_cipher_verify_basic_set(Emile_SSL *emile EINA_UNUSED,
+ Eina_Bool verify_basic EINA_UNUSED)
+{
+}
+
+EAPI Eina_Bool
+emile_cipher_verify_get(const Emile_SSL *emile EINA_UNUSED)
+{
+ return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+emile_cipher_verify_basic_get(const Emile_SSL *emile EINA_UNUSED)
+{
+ return EINA_FALSE;
+}
diff --git a/src/lib/emile/emile_cipher_gnutls.c b/src/lib/emile/emile_cipher_gnutls.c
index f69d25d346..ed48af5f92 100644
--- a/src/lib/emile/emile_cipher_gnutls.c
+++ b/src/lib/emile/emile_cipher_gnutls.c
@@ -19,6 +19,37 @@
#define MAX_KEY_LEN 32
#define MAX_IV_LEN 16
+struct _Emile_SSL
+{
+ const char *last_error;
+ const char *cert_file;
+ const char *name;
+
+ gnutls_certificate_credentials_t cert;
+ gnutls_session_t session;
+
+ union {
+ struct {
+ gnutls_datum_t session_ticket;
+ } client;
+ struct {
+ gnutls_anon_client_credentials_t anoncred_c;
+ gnutls_anon_server_credentials_t anoncred_s;
+ gnutls_psk_client_credentials_t pskcred_c;
+ gnutls_psk_server_credentials_t pskcred_s;
+ char *cert_file;
+ gnutls_dh_params_t dh_params;
+ } server;
+ } u;
+
+ Emile_Cipher_Type t;
+ Emile_SSL_State ssl_state;
+
+ Eina_Bool server : 1;
+ Eina_Bool verify : 1;
+ Eina_Bool verify_basic : 1;
+};
+
static int
_emile_thread_mutex_init(void **priv)
{
@@ -383,3 +414,284 @@ on_error:
return NULL;
}
+
+
+EAPI Eina_Bool
+emile_cipher_cafile_add(Emile_SSL *emile, const char *file)
+{
+ struct stat st;
+ int count = 0;
+
+ if (stat(file, &st)) return EINA_FALSE;
+ if (S_ISDIR(st.st_mode))
+ {
+ Eina_File_Direct_Info *info;
+ Eina_Iterator *it;
+ int err;
+
+ it = eina_file_direct_ls(file);
+ EINA_ITERATOR_FOREACH(it, info)
+ {
+ if (info->type != EINA_FILE_REG &&
+ info->type != EINA_FILE_LNK)
+ continue;
+
+ err = gnutls_certificate_set_x509_trust_file(emile->cert,
+ info->path,
+ GNUTLS_X509_FMT_PEM);
+ if (err > 0) count += err;
+ else DBG("File '%s' could not be loaded.", info->path);
+ }
+ eina_iterator_free(it);
+ }
+ else
+ {
+ count = gnutls_certificate_set_x509_trust_file(emile->cert,
+ file,
+ GNUTLS_X509_FMT_PEM);
+ if (count <= 0) DBG("File '%s' could not be loaded.", file);
+ }
+
+ return count > 0 ? EINA_TRUE : EINA_FALSE;
+}
+
+EAPI Eina_Bool
+emile_cipher_privkey_add(Emile_SSL *emile, const char *file)
+{
+ int err;
+
+ err = gnutls_certificate_set_x509_key_file(emile->cert,
+ emile->cert_file,
+ file,
+ GNUTLS_X509_FMT_PEM);
+
+ if (err <= 0) DBG("Could not load certificate/key '%s'.", file);
+ return err > 0 ? EINA_TRUE : EINA_FALSE;
+}
+
+EAPI Eina_Bool
+emile_cipher_crl_add(Emile_SSL *emile, const char *file)
+{
+ int err;
+
+ err = gnutls_certificate_set_x509_crl_file(emile->cert,
+ file,
+ GNUTLS_X509_FMT_PEM);
+ if (err <= 0) DBG("Could not load CRL '%s'.", file);
+ return err > 0 ? EINA_TRUE : EINA_FALSE;
+}
+
+EAPI Emile_SSL *
+emile_cipher_server_listen(Emile_Cipher_Type t)
+{
+ Emile_SSL *r;
+ int ret;
+
+ if (t != EMILE_SSLv23 &&
+ t != EMILE_SSLv3 &&
+ t != EMILE_TLSv1)
+ return NULL;
+
+ r = calloc(1, sizeof (Emile_SSL));
+ if (!r) return NULL;
+
+ ret = gnutls_certificate_allocate_credentials(&r->cert);
+ if (ret) goto on_error;
+
+ r->t = t;
+ r->server = EINA_TRUE;
+
+ return r;
+
+ on_error:
+ ERR("GNUTLS error: %s - %s.",
+ gnutls_strerror_name(ret),
+ gnutls_strerror(ret));
+ emile_cipher_free(r);
+ return NULL;
+}
+
+EAPI Emile_SSL *
+emile_cipher_client_connect(Emile_SSL *server, int fd)
+{
+}
+
+EAPI Emile_SSL *
+emile_cipher_server_connect(Emile_Cipher_Type t)
+{
+ const char *priority = "NORMAL:%VERIFY_ALLOW_X509_V1_CA_CRT";
+ Emile_SSL *r;
+ int ret;
+
+ switch (t)
+ {
+ case EMILE_SSLv23:
+ break;
+ case EMILE_SSLv3:
+ priority = "NORMAL:%VERIFY_ALLOW_X509_V1_CA_CRT:!VERS-TLS1.0:!VERS-TLS1.1:!VERS-TLS1.2";
+ break;
+ case EMILE_TLSv1:
+ priority = "NORMAL:%VERIFY_ALLOW_X509_V1_CA_CRT:!VERS-SSL3.0";
+ break;
+ default:
+ return NULL;
+ }
+
+ r = calloc(1, sizeof (Emile_SSL));
+ if (!r) return NULL;
+
+ r->server = EINA_FALSE;
+
+ ret = gnutls_certificate_allocate_credentials(&r->cert);
+ if (ret) goto on_error;
+
+ ret = gnutls_init(&r->session, GNUTLS_CLIENT);
+ if (ret) goto on_error;
+
+ ret = gnutls_session_ticket_enable_client(r->session);
+ if (ret) goto on_error;
+
+ // FIXME: Delay that until later access
+
+ ret = gnutls_server_name_set(r->session, GNUTLS_NAME_DNS,
+ r->name, strlen(r->name));
+ if (ret) goto on_error;
+
+ ret = gnutls_priority_set_direct(r->session, priority, NULL);
+ if (ret) goto on_error;
+
+ gnutls_handshake_set_private_extensions(r->session, 1);
+ ret = gnutls_credentials_set(r->session, GNUTLS_CRD_CERTIFICATE, r->cert));
+
+ return r;
+}
+
+EAPI Eina_Bool
+emile_cipher_free(Emile_SSL *emile)
+{
+}
+
+EAPI Eina_Bool
+emile_cipher_cafile_add(Emile_SSL *emile, const char *file)
+{
+ Eina_File_Direct_Info *info;
+ Eina_Iterator *it;
+ struct stat st;
+ int count = 0;
+ int ret;
+
+ if (stat(file, &st)) return EINA_FALSE;
+ if (S_ISDIR(st.st_mode))
+ {
+ it = eina_file_direct_ls(file);
+ EINA_ITERATOR_FOREACH(it, info)
+ {
+ if (!(info->type == EINA_FILE_UNKNOWN ||
+ info->type == EINA_FILE_REG ||
+ info->type == EINA_FILE_LNK))
+ continue ;
+
+ ret = gnutls_certificate_set_x509_trust_file(emile->cert,
+ file,
+ GNUTLS_X509_FMT_PEM);
+ if (ret > 0) count += ret;
+ }
+ eina_iterator_free(it);
+ }
+ else
+ {
+ ret = gnutls_certificate_set_x509_trust_file(emile->cert,
+ file,
+ GNUTLS_X509_FMT_PEM);
+ if (ret > 0) count += ret;
+ }
+
+ if (!count) ERR("Could not load CA file from '%s'.", file);
+ return !count ? EINA_FALSE : EINA_TRUE;
+}
+
+EAPI Eina_Bool
+emile_cipher_cert_add(Emile_SSL *emile, const char *file)
+{
+ return eina_stringshare_replace(&emile->cert_file, file);
+}
+
+EAPI Eina_Bool
+emile_cipher_privkey_add(Emile_SSL *emile, const char *file)
+{
+ int ret;
+
+ ret = gnutls_certificate_set_x509_key_file(emile->cert,
+ emile->cert_file,
+ file,
+ GNUTLS_X509_FMT_PEM);
+ if (ret)
+ ERR("Could not load certificate/key file ('%s'/'%s').",
+ emile->cert_file, file);
+ return ret ? EINA_FALSE : EINA_TRUE;
+}
+
+EAPI Eina_Bool
+emile_cipher_crl_add(Emile_SSL *emile, const char *file)
+{
+ int ret;
+
+ ret = gnutls_certificate_set_x509_crl_file(emile->cert, file,
+ GNUTLS_X509_FMT_PEM);
+ if (ret)
+ ERR("Could not load CRL file from '%s'.", file);
+ return ret ? EINA_FALSE : EINA_TRUE;
+}
+
+EAPI int
+emile_cipher_read(Emile_SSL *emile, Eina_Binbuf *buffer)
+{
+}
+
+EAPI int
+emile_cipher_write(Emile_SSL *emile, const Eina_Binbuf *buffer)
+{
+}
+
+EAPI const char *
+emile_cipher_error_get(const Emile_SSL *emile)
+{
+ return emile->last_error;
+}
+
+EAPI Eina_Bool
+emile_cipher_verify_name_set(Emile_SSL *emile, const char *name)
+{
+ return eina_stringshare_replace(&emile->name, name);
+}
+
+EAPI const char *
+emile_cipher_verify_name_get(const Emile_SSL *emile)
+{
+ return emile->name;
+}
+
+EAPI void
+emile_cipher_verify_set(Emile_SSL *emile, Eina_Bool verify)
+{
+ emile->verify = verify;
+}
+
+EAPI void
+emile_cipher_verify_basic_set(Emile_SSL *emile, Eina_Bool verify_basic)
+{
+ emile->verify_basic = verify_basic;
+}
+
+EAPI Eina_Bool
+emile_cipher_verify_get(const Emile_SSL *emile)
+{
+ return emile->verify;
+}
+
+EAPI Eina_Bool
+emile_cipher_verify_basic_get(const Emile_SSL *emile)
+{
+ return emile->verify_basic;
+}
+
diff --git a/src/lib/emile/emile_cipher_openssl.c b/src/lib/emile/emile_cipher_openssl.c
index fdb36a5f8e..6c3e746c37 100644
--- a/src/lib/emile/emile_cipher_openssl.c
+++ b/src/lib/emile/emile_cipher_openssl.c
@@ -10,6 +10,9 @@
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/dh.h>
#include <Eina.h>
@@ -20,6 +23,29 @@
#define MAX_KEY_LEN EVP_MAX_KEY_LENGTH
#define MAX_IV_LEN EVP_MAX_IV_LENGTH
+struct _Emile_SSL
+{
+ Emile_SSL *parent;
+ SSL_CTX *ssl_ctx;
+ SSL *ssl;
+
+ const char *last_error;
+ const char *verify_name;
+
+ int ssl_err;
+ Emile_SSL_State ssl_state;
+ Emile_Want_Type ssl_want;
+
+ Eina_Bool server : 1;
+ Eina_Bool listen : 1;
+ Eina_Bool connecting : 1;
+ Eina_Bool handshaking : 1;
+ Eina_Bool upgrade : 1;
+ Eina_Bool crl_flag : 1;
+ Eina_Bool verify : 1;
+ Eina_Bool verify_basic : 1;
+};
+
Eina_Bool
_emile_cipher_init(void)
{
@@ -281,3 +307,821 @@ on_error:
return NULL;
}
+
+EAPI Emile_SSL *
+emile_cipher_server_listen(Emile_Cipher_Type t)
+{
+ Emile_SSL *r;
+ DH *dh_params = NULL;
+ int options;
+ int dh = 0;
+
+ if (!emile_cipher_init()) return NULL;
+
+ r = calloc(1, sizeof (Emile_SSL));
+ if (!r) return NULL;
+
+ switch (t)
+ {
+ case EMILE_SSLv23:
+ r->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
+ if (!r->ssl_ctx) goto on_error;
+ options = SSL_CTX_get_options(r->ssl_ctx);
+ SSL_CTX_set_options(r->ssl_ctx,
+ options | SSL_OP_NO_SSLv2 | SSL_OP_SINGLE_DH_USE);
+ break;
+ case EMILE_SSLv3:
+ r->ssl_ctx = SSL_CTX_new(SSLv3_server_method());
+ break;
+ case EMILE_TLSv1:
+ r->ssl_ctx = SSL_CTX_new(TLSv1_server_method());
+ break;
+ default:
+ free(r);
+ return NULL;
+ }
+
+ if (!r->ssl_ctx) goto on_error;
+
+ dh_params = DH_new();
+ if (!dh_params) goto on_error;
+ if (!DH_generate_parameters_ex(dh_params, 1024, DH_GENERATOR_5, NULL))
+ goto on_error;
+ if (!DH_check(dh_params, &dh))
+ goto on_error;
+ if ((dh & DH_CHECK_P_NOT_PRIME) || (dh & DH_CHECK_P_NOT_SAFE_PRIME))
+ goto on_error;
+ if (!DH_generate_key(dh_params))
+ goto on_error;
+ if (!SSL_CTX_set_tmp_dh(r->ssl_ctx, dh_params))
+ goto on_error;
+
+ DH_free(dh_params);
+ INF("DH params successfully generated and applied!");
+
+ if (!SSL_CTX_set_cipher_list(r->ssl_ctx,
+ "aNULL:!eNULL:!LOW:!EXPORT:@STRENGTH"))
+ goto on_error;
+
+ return r;
+
+ on_error:
+ if (dh)
+ {
+ if (dh & DH_CHECK_P_NOT_PRIME)
+ ERR("openssl error: dh_params could not generate a prime!");
+ else
+ ERR("openssl error: dh_params could not generate a safe prime!");
+ }
+ else
+ {
+ ERR("openssl error: %s.", ERR_reason_error_string(ERR_get_error()));
+ }
+ emile_cipher_free(r);
+ return NULL;
+}
+
+static void
+_emile_cipher_print_verify_error(int error)
+{
+ switch (error)
+ {
+#define ERROR(X) \
+case (X): \
+ ERR("%s", #X); \
+ break
+#ifdef X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
+ ERROR(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT);
+#endif
+#ifdef X509_V_ERR_UNABLE_TO_GET_CRL
+ ERROR(X509_V_ERR_UNABLE_TO_GET_CRL);
+#endif
+#ifdef X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE
+ ERROR(X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE);
+#endif
+#ifdef X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE
+ ERROR(X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE);
+#endif
+#ifdef X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY
+ ERROR(X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY);
+#endif
+#ifdef X509_V_ERR_CERT_SIGNATURE_FAILURE
+ ERROR(X509_V_ERR_CERT_SIGNATURE_FAILURE);
+#endif
+#ifdef X509_V_ERR_CRL_SIGNATURE_FAILURE
+ ERROR(X509_V_ERR_CRL_SIGNATURE_FAILURE);
+#endif
+#ifdef X509_V_ERR_CERT_NOT_YET_VALID
+ ERROR(X509_V_ERR_CERT_NOT_YET_VALID);
+#endif
+#ifdef X509_V_ERR_CERT_HAS_EXPIRED
+ ERROR(X509_V_ERR_CERT_HAS_EXPIRED);
+#endif
+#ifdef X509_V_ERR_CRL_NOT_YET_VALID
+ ERROR(X509_V_ERR_CRL_NOT_YET_VALID);
+#endif
+#ifdef X509_V_ERR_CRL_HAS_EXPIRED
+ ERROR(X509_V_ERR_CRL_HAS_EXPIRED);
+#endif
+#ifdef X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD
+ ERROR(X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD);
+#endif
+#ifdef X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD
+ ERROR(X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD);
+#endif
+#ifdef X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD
+ ERROR(X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD);
+#endif
+#ifdef X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD
+ ERROR(X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
+#endif
+#ifdef X509_V_ERR_OUT_OF_MEM
+ ERROR(X509_V_ERR_OUT_OF_MEM);
+#endif
+#ifdef X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
+ ERROR(X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT);
+#endif
+#ifdef X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
+ ERROR(X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN);
+#endif
+#ifdef X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
+ ERROR(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY);
+#endif
+#ifdef X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
+ ERROR(X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE);
+#endif
+#ifdef X509_V_ERR_CERT_CHAIN_TOO_LONG
+ ERROR(X509_V_ERR_CERT_CHAIN_TOO_LONG);
+#endif
+#ifdef X509_V_ERR_CERT_REVOKED
+ ERROR(X509_V_ERR_CERT_REVOKED);
+#endif
+#ifdef X509_V_ERR_INVALID_CA
+ ERROR(X509_V_ERR_INVALID_CA);
+#endif
+#ifdef X509_V_ERR_PATH_LENGTH_EXCEEDED
+ ERROR(X509_V_ERR_PATH_LENGTH_EXCEEDED);
+#endif
+#ifdef X509_V_ERR_INVALID_PURPOSE
+ ERROR(X509_V_ERR_INVALID_PURPOSE);
+#endif
+#ifdef X509_V_ERR_CERT_UNTRUSTED
+ ERROR(X509_V_ERR_CERT_UNTRUSTED);
+#endif
+#ifdef X509_V_ERR_CERT_REJECTED
+ ERROR(X509_V_ERR_CERT_REJECTED);
+#endif
+ /* These are 'informational' when looking for issuer cert */
+#ifdef X509_V_ERR_SUBJECT_ISSUER_MISMATCH
+ ERROR(X509_V_ERR_SUBJECT_ISSUER_MISMATCH);
+#endif
+#ifdef X509_V_ERR_AKID_SKID_MISMATCH
+ ERROR(X509_V_ERR_AKID_SKID_MISMATCH);
+#endif
+#ifdef X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH
+ ERROR(X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH);
+#endif
+#ifdef X509_V_ERR_KEYUSAGE_NO_CERTSIGN
+ ERROR(X509_V_ERR_KEYUSAGE_NO_CERTSIGN);
+#endif
+
+#ifdef X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER
+ ERROR(X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER);
+#endif
+#ifdef X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION
+ ERROR(X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION);
+#endif
+#ifdef X509_V_ERR_KEYUSAGE_NO_CRL_SIGN
+ ERROR(X509_V_ERR_KEYUSAGE_NO_CRL_SIGN);
+#endif
+#ifdef X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION
+ ERROR(X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION);
+#endif
+#ifdef X509_V_ERR_INVALID_NON_CA
+ ERROR(X509_V_ERR_INVALID_NON_CA);
+#endif
+#ifdef X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED
+ ERROR(X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED);
+#endif
+#ifdef X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE
+ ERROR(X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE);
+#endif
+#ifdef X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED
+ ERROR(X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED);
+#endif
+
+#ifdef X509_V_ERR_INVALID_EXTENSION
+ ERROR(X509_V_ERR_INVALID_EXTENSION);
+#endif
+#ifdef X509_V_ERR_INVALID_POLICY_EXTENSION
+ ERROR(X509_V_ERR_INVALID_POLICY_EXTENSION);
+#endif
+#ifdef X509_V_ERR_NO_EXPLICIT_POLICY
+ ERROR(X509_V_ERR_NO_EXPLICIT_POLICY);
+#endif
+#ifdef X509_V_ERR_DIFFERENT_CRL_SCOPE
+ ERROR(X509_V_ERR_DIFFERENT_CRL_SCOPE);
+#endif
+#ifdef X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE
+ ERROR(X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE);
+#endif
+
+#ifdef X509_V_ERR_UNNESTED_RESOURCE
+ ERROR(X509_V_ERR_UNNESTED_RESOURCE);
+#endif
+
+#ifdef X509_V_ERR_PERMITTED_VIOLATION
+ ERROR(X509_V_ERR_PERMITTED_VIOLATION);
+#endif
+#ifdef X509_V_ERR_EXCLUDED_VIOLATION
+ ERROR(X509_V_ERR_EXCLUDED_VIOLATION);
+#endif
+#ifdef X509_V_ERR_SUBTREE_MINMAX
+ ERROR(X509_V_ERR_SUBTREE_MINMAX);
+#endif
+#ifdef X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE
+ ERROR(X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE);
+#endif
+#ifdef X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX
+ ERROR(X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX);
+#endif
+#ifdef X509_V_ERR_UNSUPPORTED_NAME_SYNTAX
+ ERROR(X509_V_ERR_UNSUPPORTED_NAME_SYNTAX);
+#endif
+#ifdef X509_V_ERR_CRL_PATH_VALIDATION_ERROR
+ ERROR(X509_V_ERR_CRL_PATH_VALIDATION_ERROR);
+#endif
+
+ /* The application is not happy */
+#ifdef X509_V_ERR_APPLICATION_VERIFICATION
+ ERROR(X509_V_ERR_APPLICATION_VERIFICATION);
+#endif
+ }
+#undef ERROR
+}
+
+static void
+_emile_cipher_session_print(SSL *ssl)
+{
+ Eina_Strbuf *str;
+ SSL_SESSION *s;
+ STACK_OF(X509) *sk;
+ BIO *b;
+ BUF_MEM *bptr;
+ char log[4096];
+
+ if (!eina_log_domain_level_check(_emile_log_dom_global, EINA_LOG_LEVEL_DBG))
+ return ;
+
+ str = eina_strbuf_new();
+ if (!str) return ;
+
+ log[0] = '\0';
+ b = BIO_new(BIO_s_mem());
+ sk = SSL_get_peer_cert_chain(ssl);
+ if (sk)
+ {
+ int i;
+
+ DBG("CERTIFICATES:");
+ for (i = 0; i < sk_X509_num(sk); i++)
+ {
+ char *p;
+
+ p = X509_NAME_oneline(X509_get_subject_name(sk_X509_value(sk, i)),
+ log, sizeof (log));
+ DBG("%2d s:%s", i, p);
+ p = X509_NAME_oneline(X509_get_issuer_name(sk_X509_value(sk, i)),
+ log, sizeof(log));
+ DBG(" i:%s", p);
+
+ PEM_write_bio_X509(b, sk_X509_value(sk, i));
+ BIO_get_mem_ptr(b, &bptr);
+ eina_strbuf_append_length(str, bptr->data, bptr->length);
+ DBG("%s", eina_strbuf_string_get(str));
+ eina_strbuf_reset(str);
+ BIO_free(b);
+ }
+ }
+
+ s = SSL_get_session(ssl);
+ SSL_SESSION_print(b, s);
+ BIO_get_mem_ptr(b, &bptr);
+ eina_strbuf_append_length(str, bptr->data, bptr->length);
+ DBG("%s", eina_strbuf_string_get(str));
+ eina_strbuf_free(str);
+ BIO_free(b);
+}
+
+static void
+_emile_cipher_client_handshake(Emile_SSL *client)
+{
+ X509 *cert;
+ int ret = -1;
+
+ if (!client) return ;
+
+ switch (client->ssl_state)
+ {
+ case EMILE_SSL_STATE_INIT:
+ client->ssl_state = EMILE_SSL_STATE_HANDSHAKING;
+ client->handshaking = EINA_TRUE;
+
+ case EMILE_SSL_STATE_HANDSHAKING:
+ if (!client->ssl) goto on_error;
+
+ ret = SSL_do_handshake(client->ssl);
+ client->ssl_err = SSL_get_error(client->ssl, ret);
+
+ if ((client->ssl_err == SSL_ERROR_SYSCALL) ||
+ (client->ssl_err == SSL_ERROR_SSL))
+ goto on_error;
+
+ if (ret != 1)
+ {
+ if (client->ssl_err == SSL_ERROR_WANT_READ)
+ client->ssl_want = EMILE_WANT_READ;
+ else if (client->ssl_err == SSL_ERROR_WANT_WRITE)
+ client->ssl_want = EMILE_WANT_WRITE;
+
+ return ;
+ }
+
+ client->handshaking = EINA_FALSE;
+ client->ssl_state = EMILE_SSL_STATE_DONE;
+ case EMILE_SSL_STATE_DONE:
+ break;
+ case EMILE_SSL_STATE_ERROR:
+ goto on_error;
+ }
+
+ _emile_cipher_session_print(client->ssl);
+ if (!client->parent->verify &&
+ !client->parent->verify_basic)
+ return ;
+
+ SSL_set_verify(client->ssl, SSL_VERIFY_PEER, NULL);
+ /* use CRL/CA lists to verify */
+ cert = SSL_get_peer_certificate(client->ssl);
+ if (cert)
+ {
+ const char *verify_name;
+ char *cert_name;
+ char *s;
+ int clen;
+ int err;
+ int name = 0;
+
+ if (client->parent->verify)
+ {
+ err = SSL_get_verify_result(client->ssl);
+ _emile_cipher_print_verify_error(err);
+ if (err) goto on_error;
+ }
+
+ clen = X509_NAME_get_text_by_NID(X509_get_subject_name(cert),
+ NID_subject_alt_name,
+ NULL, 0);
+ if (clen > 0)
+ {
+ name = NID_subject_alt_name;
+ }
+ else
+ {
+ clen = X509_NAME_get_text_by_NID(X509_get_subject_name(cert),
+ NID_commonName,
+ NULL, 0);
+ if (clen <= 0) goto on_error;
+ name = NID_commonName;
+ }
+
+ cert_name = alloca(++clen);
+ X509_NAME_get_text_by_NID(X509_get_subject_name(cert),
+ name, cert_name, clen);
+ verify_name = client->parent->verify_name;
+
+ INF("Cert name: '%s' vs verify name: '%s'.", cert_name, verify_name);
+
+ if (!verify_name) goto on_error;
+ if (strcasecmp(cert_name, verify_name)) goto on_error;
+ if (verify_name[0] != '*') goto on_error;
+
+ /* verify that their is only one wildcard in the client cert name */
+ if (strchr(cert_name + 1, '*')) goto on_error;
+ /* verify that we have a domain of at least *.X.TLD and not *.TLD */
+ if (!strchr(cert_name + 2, '.')) goto on_error;
+ s = strchr(verify_name, '.');
+ if (!s) goto on_error;
+ /* same as above for the stored name */
+ if (!strchr(s + 1, '.')) goto on_error;
+ if (strcasecmp(s, verify_name + 1)) goto on_error;
+
+ DBG("Successfully verified certificate.");
+ }
+
+ return ;
+
+ on_error:
+ DBG("Failed to finish handshake.");
+ client->ssl_state = EMILE_SSL_STATE_ERROR;
+ return ;
+}
+
+EAPI Emile_SSL *
+emile_cipher_client_connect(Emile_SSL *server, int fd)
+{
+ Emile_SSL *r;
+
+ if (!server) return NULL;
+
+ r = calloc(1, sizeof (Emile_SSL));
+ if (!r) return NULL;
+
+ r->parent = server;
+ r->ssl = SSL_new(r->parent->ssl_ctx);
+ if (!r->ssl) goto on_error;
+
+ if (!SSL_set_fd(r->ssl, fd))
+ goto on_error;
+
+ SSL_set_accept_state(r->ssl);
+
+ _emile_cipher_client_handshake(r);
+
+ if (r->ssl_state == EMILE_SSL_STATE_ERROR) goto on_error;
+
+ return r;
+
+ on_error:
+ emile_cipher_free(r);
+ return NULL;
+}
+
+EAPI Emile_SSL *
+emile_cipher_server_connect(Emile_Cipher_Type t)
+{
+ Emile_SSL *r;
+ const char *msg;
+ int options;
+ int dh = 0;
+
+ if (!emile_cipher_init()) return NULL;
+
+ r = calloc(1, sizeof (Emile_SSL));
+ if (!r) return NULL;
+
+ switch (t)
+ {
+ case EMILE_SSLv23:
+ r->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
+ if (!r->ssl_ctx) goto on_error;
+ options = SSL_CTX_get_options(r->ssl_ctx);
+ SSL_CTX_set_options(r->ssl_ctx,
+ options | SSL_OP_NO_SSLv2 | SSL_OP_SINGLE_DH_USE);
+ break;
+ case EMILE_SSLv3:
+ r->ssl_ctx = SSL_CTX_new(SSLv3_client_method());
+ break;
+ case EMILE_TLSv1:
+ r->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
+ break;
+ default:
+ free(r);
+ return NULL;
+ }
+
+ if (!SSL_CTX_set_cipher_list(r->ssl_ctx,
+ "aNULL:!eNULL:!LOW:!EXPORT:!ECDH:RSA:AES:!PSK:@STRENGTH"))
+ goto on_error;
+
+ return r;
+
+ on_error:
+ if (dh)
+ {
+ if (dh & DH_CHECK_P_NOT_PRIME)
+ msg = "dh_params could not generate a prime!";
+ else
+ msg = "dh_params could not generate a safe prime!";
+ }
+ else
+ {
+ msg = ERR_reason_error_string(ERR_get_error());
+ }
+
+ ERR("OpenSSL error: '%s'.", msg);
+ emile_cipher_free(r);
+ return NULL;
+}
+
+EAPI Eina_Bool
+emile_cipher_free(Emile_SSL *emile)
+{
+ if (!emile) return EINA_FALSE;
+
+ eina_stringshare_del(emile->last_error);
+ emile->last_error = NULL;
+
+ eina_stringshare_del(emile->verify_name);
+ emile->verify_name = NULL;
+
+ if (emile->ssl)
+ {
+ if (!SSL_shutdown(emile->ssl))
+ SSL_shutdown(emile->ssl);
+
+ SSL_free(emile->ssl);
+ }
+ emile->ssl = NULL;
+
+ if (emile->ssl_ctx)
+ SSL_CTX_free(emile->ssl_ctx);
+ emile->ssl_ctx = NULL;
+
+ free(emile);
+ return EINA_TRUE;
+}
+
+EAPI Eina_Bool
+emile_cipher_cafile_add(Emile_SSL *emile, const char *file)
+{
+ struct stat st;
+ unsigned long err;
+
+ if (stat(file, &st)) return EINA_FALSE;
+ if (S_ISDIR(st.st_mode))
+ {
+ if (!SSL_CTX_load_verify_locations(emile->ssl_ctx, NULL, file))
+ goto on_error;
+ }
+ else
+ {
+ if (!SSL_CTX_load_verify_locations(emile->ssl_ctx, file, NULL))
+ goto on_error;
+ }
+
+ return EINA_TRUE;
+
+ on_error:
+ err = ERR_peek_last_error();
+ if (!err) return EINA_FALSE;
+
+ DBG("OpenSSL error: '%s'.", ERR_reason_error_string(err));
+ eina_stringshare_replace(&emile->last_error, ERR_reason_error_string(err));
+ return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+emile_cipher_cert_add(Emile_SSL *emile, const char *file)
+{
+ Eina_File *f;
+ void *m;
+ X509 *cert = NULL;
+ BIO *bio = NULL;
+ int err;
+
+ f = eina_file_open(file, EINA_FALSE);
+ if (!f) return EINA_FALSE;
+
+ m = eina_file_map_all(f, EINA_FILE_WILLNEED);
+ if (!m) goto on_error;
+
+ bio = BIO_new_mem_buf(m, eina_file_size_get(f));
+ if (!bio) goto on_error;
+
+ cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+ if (!cert) goto on_error;
+
+ if (SSL_CTX_use_certificate(emile->ssl_ctx, cert) < 1)
+ goto on_error;
+
+ eina_file_map_free(f, m);
+ eina_file_close(f);
+ BIO_free(bio);
+
+ return EINA_TRUE;
+
+ on_error:
+ err = ERR_peek_last_error();
+
+ if (m) eina_file_map_free(f, m);
+ if (f) eina_file_close(f);
+ if (bio) BIO_free(bio);
+
+ if (!err) return EINA_FALSE;
+
+ DBG("OpenSSL error: '%s'.", ERR_reason_error_string(err));
+ eina_stringshare_replace(&emile->last_error, ERR_reason_error_string(err));
+ return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+emile_cipher_privkey_add(Emile_SSL *emile, const char *file)
+{
+ Eina_File *f;
+ void *m;
+ EVP_PKEY *privkey = NULL;
+ BIO *bio = NULL;
+ int err;
+
+ f = eina_file_open(file, EINA_FALSE);
+ if (!f) return EINA_FALSE;
+
+ m = eina_file_map_all(f, EINA_FILE_WILLNEED);
+ if (!m) goto on_error;
+
+ bio = BIO_new_mem_buf(m, eina_file_size_get(f));
+ if (!bio) goto on_error;
+
+ privkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
+ if (!privkey) goto on_error;
+
+ eina_file_map_free(f, m);
+ m = NULL;
+
+ eina_file_close(f);
+ f = NULL;
+
+ if (SSL_CTX_use_PrivateKey(emile->ssl_ctx, privkey) < 1)
+ goto on_error;
+
+ if (SSL_CTX_check_private_key(emile->ssl_ctx) < 1)
+ goto on_error;
+
+ BIO_free(bio);
+
+ return EINA_TRUE;
+
+ on_error:
+ err = ERR_peek_last_error();
+
+ if (m) eina_file_map_free(f, m);
+ if (f) eina_file_close(f);
+ if (bio) BIO_free(bio);
+
+ if (!err) return EINA_FALSE;
+
+ DBG("OpenSSL error: '%s'.", ERR_reason_error_string(err));
+ eina_stringshare_replace(&emile->last_error, ERR_reason_error_string(err));
+ return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+emile_cipher_crl_add(Emile_SSL *emile, const char *file)
+{
+ X509_LOOKUP *lu;
+ X509_STORE *st;
+ int err;
+
+ st = SSL_CTX_get_cert_store(emile->ssl_ctx);
+ if (!st) goto on_error;
+
+ lu = X509_STORE_add_lookup(st, X509_LOOKUP_file());
+ if (!lu) goto on_error;
+
+ if (X509_load_crl_file(lu, file, X509_FILETYPE_PEM) < 1)
+ goto on_error;
+
+ if (!emile->crl_flag)
+ {
+ X509_STORE_set_flags(st,
+ X509_V_FLAG_CRL_CHECK |
+ X509_V_FLAG_CRL_CHECK_ALL);
+ emile->crl_flag = EINA_TRUE;
+ }
+
+ return EINA_TRUE;
+
+ on_error:
+ err = ERR_peek_last_error();
+ if (!err) return EINA_FALSE;
+
+ DBG("OpenSSL error: '%s'.", ERR_reason_error_string(err));
+ eina_stringshare_replace(&emile->last_error, ERR_reason_error_string(err));
+ return EINA_FALSE;
+}
+
+EAPI int
+emile_cipher_read(Emile_SSL *emile, Eina_Binbuf *buffer)
+{
+ int err;
+ int num;
+
+ if (!emile->ssl) return -1;
+ if (eina_binbuf_length_get(buffer) <= 0) return 0;
+
+ num = SSL_read(emile->ssl,
+ (void*) eina_binbuf_string_get(buffer),
+ eina_binbuf_length_get(buffer));
+ emile->ssl_err = SSL_get_error(emile->ssl, num);
+
+ switch (emile->ssl_err)
+ {
+ case SSL_ERROR_WANT_READ: emile->ssl_want = EMILE_WANT_READ; break;
+ case SSL_ERROR_WANT_WRITE: emile->ssl_want = EMILE_WANT_WRITE; break;
+ case SSL_ERROR_ZERO_RETURN:
+ case SSL_ERROR_SYSCALL:
+ case SSL_ERROR_SSL:
+ err = ERR_peek_last_error();
+ if (!err) return -1;
+
+ DBG("OpenSSL error: '%s'.", ERR_reason_error_string(err));
+ eina_stringshare_replace(&emile->last_error, ERR_reason_error_string(err));
+ return -1;
+
+ default:
+ emile->ssl_want = EMILE_WANT_NOTHING;
+ break;
+ }
+
+ if (emile->ssl_state == EMILE_SSL_STATE_HANDSHAKING)
+ _emile_cipher_client_handshake(emile);
+ if (emile->ssl_state == EMILE_SSL_STATE_ERROR)
+ return -1;
+
+ return num < 0 ? 0 : num;
+}
+
+EAPI int
+emile_cipher_write(Emile_SSL *emile, const Eina_Binbuf *buffer)
+{
+ int num;
+ int err;
+
+ if (!emile->ssl) return -1;
+ if (eina_binbuf_length_get(buffer) <= 0) return 0;
+
+ num = SSL_write(emile->ssl,
+ (void*) eina_binbuf_string_get(buffer),
+ eina_binbuf_length_get(buffer));
+ emile->ssl_err = SSL_get_error(emile->ssl, num);
+
+ switch (emile->ssl_err)
+ {
+ case SSL_ERROR_WANT_READ: emile->ssl_want = EMILE_WANT_READ; break;
+ case SSL_ERROR_WANT_WRITE: emile->ssl_want = EMILE_WANT_WRITE; break;
+ case SSL_ERROR_ZERO_RETURN:
+ case SSL_ERROR_SYSCALL:
+ case SSL_ERROR_SSL:
+ err = ERR_peek_last_error();
+ if (!err) return -1;
+
+ DBG("OpenSSL error: '%s'.", ERR_reason_error_string(err));
+ eina_stringshare_replace(&emile->last_error, ERR_reason_error_string(err));
+ return -1;
+
+ default:
+ emile->ssl_want = EMILE_WANT_NOTHING;
+ break;
+ }
+
+ if (emile->ssl_state == EMILE_SSL_STATE_HANDSHAKING)
+ _emile_cipher_client_handshake(emile);
+ if (emile->ssl_state == EMILE_SSL_STATE_ERROR)
+ return -1;
+
+ return num < 0 ? 0 : num;
+}
+
+EAPI const char *
+emile_cipher_error_get(const Emile_SSL *emile)
+{
+ return emile->last_error;
+}
+
+EAPI Eina_Bool
+emile_cipher_verify_name_set(Emile_SSL *emile, const char *name)
+{
+ return eina_stringshare_replace(&emile->verify_name, name);
+}
+
+EAPI const char *
+emile_cipher_verify_name_get(const Emile_SSL *emile)
+{
+ return emile->verify_name;
+}
+
+EAPI void
+emile_cipher_verify_set(Emile_SSL *emile, Eina_Bool verify)
+{
+ emile->verify = verify;
+}
+
+EAPI void
+emile_cipher_verify_basic_set(Emile_SSL *emile, Eina_Bool verify_basic)
+{
+ emile->verify_basic = verify_basic;
+}
+
+EAPI Eina_Bool
+emile_cipher_verify_get(const Emile_SSL *emile)
+{
+ return emile->verify;
+}
+
+EAPI Eina_Bool
+emile_cipher_verify_basic_get(const Emile_SSL *emile)
+{
+ return emile->verify_basic;
+}
+
diff --git a/src/lib/emile/emile_main.c b/src/lib/emile/emile_main.c
index d5939e8ad8..eb18a61de5 100644
--- a/src/lib/emile/emile_main.c
+++ b/src/lib/emile/emile_main.c
@@ -73,7 +73,7 @@ emile_shutdown(void)
EINA_LOG_STATE_START,
EINA_LOG_STATE_SHUTDOWN);
- if (_emile_cipher_init)
+ if (_emile_cipher_inited)
{
#ifdef HAVE_GNUTLS
/* Note that gnutls has a leak where it doesnt free stuff it alloced
diff --git a/src/lib/emile/emile_private.h b/src/lib/emile/emile_private.h
index e6b4763f40..f6a005d44a 100644
--- a/src/lib/emile/emile_private.h
+++ b/src/lib/emile/emile_private.h
@@ -24,6 +24,14 @@ extern int _emile_log_dom_global;
#endif /* ifdef CRI */
#define CRI(...) EINA_LOG_DOM_CRIT(_emile_log_dom_global, __VA_ARGS__)
+typedef enum
+{
+ EMILE_SSL_STATE_INIT = 0,
+ EMILE_SSL_STATE_HANDSHAKING,
+ EMILE_SSL_STATE_DONE,
+ EMILE_SSL_STATE_ERROR
+} Emile_SSL_State;
+
Eina_Bool _emile_cipher_init(void);
#endif /* EMILE_PRIVATE_H_ */