summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@samsung.com>2015-03-17 08:50:13 +0100
committerCedric BAIL <cedric@osg.samsung.com>2015-03-17 09:58:18 +0100
commita089d8cd7bd1386a7aa64774e17925a17e8e00bc (patch)
tree10032de8d8a8d29f41635eb9525b8bd617cca702 /src
parent0f5184bbe4d40dc0c6793d46ab1906b692c76a9b (diff)
emile: Add SSL support.
Diffstat (limited to 'src')
-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 c52567beaf..3ca865b277 100644
--- a/src/lib/ecore_con/ecore_con_ssl.c
+++ b/src/lib/ecore_con/ecore_con_ssl.c
@@ -1372,8 +1372,6 @@ _ecore_con_ssl_client_write_gnutls(Ecore_Con_Client *obj,
1372 */ 1372 */
1373 1373
1374static Ecore_Con_Ssl_Error 1374static Ecore_Con_Ssl_Error
1375
1376static Ecore_Con_Ssl_Error
1377_ecore_con_ssl_server_prepare_openssl(Ecore_Con_Server *obj, 1375_ecore_con_ssl_server_prepare_openssl(Ecore_Con_Server *obj,
1378 int ssl_type) 1376 int ssl_type)
1379{ 1377{
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);
106 * @} 106 * @}
107 */ 107 */
108 108
109typedef struct _Emile_SSL Emile_SSL;
110
111typedef enum
112{
113 EMILE_SSLv23,
114 EMILE_SSLv3,
115 EMILE_TLSv1
116} Emile_Cipher_Type;
117
118typedef enum
119{
120 EMILE_WANT_NOTHING = 0,
121 EMILE_WANT_READ = 1,
122 EMILE_WANT_WRITE = 3
123} Emile_Want_Type;
124
109EAPI Eina_Bool emile_cipher_init(void); 125EAPI Eina_Bool emile_cipher_init(void);
126EAPI const char *emile_cipher_module_get(void);
110 127
111EAPI Eina_Binbuf *emile_binbuf_cipher(const Eina_Binbuf *in, 128EAPI Eina_Binbuf *emile_binbuf_cipher(const Eina_Binbuf *in,
112 const char *key, unsigned int length); 129 const char *key, unsigned int length);
@@ -114,6 +131,25 @@ EAPI Eina_Binbuf *emile_binbuf_cipher(const Eina_Binbuf *in,
114EAPI Eina_Binbuf *emile_binbuf_decipher(const Eina_Binbuf *in, 131EAPI Eina_Binbuf *emile_binbuf_decipher(const Eina_Binbuf *in,
115 const char *key, unsigned int length); 132 const char *key, unsigned int length);
116 133
134EAPI Emile_SSL *emile_cipher_server_listen(Emile_Cipher_Type t);
135EAPI Emile_SSL *emile_cipher_client_connect(Emile_SSL *server, int fd);
136EAPI Emile_SSL *emile_cipher_server_connect(Emile_Cipher_Type t);
137EAPI Eina_Bool emile_cipher_free(Emile_SSL *emile);
138
139EAPI Eina_Bool emile_cipher_cafile_add(Emile_SSL *emile, const char *file);
140EAPI Eina_Bool emile_cipher_cert_add(Emile_SSL *emile, const char *file);
141EAPI Eina_Bool emile_cipher_privkey_add(Emile_SSL *emile, const char *file);
142EAPI Eina_Bool emile_cipher_crl_add(Emile_SSL *emile, const char *file);
143EAPI int emile_cipher_read(Emile_SSL *emile, Eina_Binbuf *buffer);
144EAPI int emile_cipher_write(Emile_SSL *emile, const Eina_Binbuf *buffer);
145EAPI const char *emile_cipher_error_get(const Emile_SSL *emile);
146EAPI Eina_Bool emile_cipher_verify_name_set(Emile_SSL *emile, const char *name);
147EAPI const char *emile_cipher_verify_name_get(const Emile_SSL *emile);
148EAPI void emile_cipher_verify_set(Emile_SSL *emile, Eina_Bool verify);
149EAPI void emile_cipher_verify_basic_set(Emile_SSL *emile, Eina_Bool verify_basic);
150EAPI Eina_Bool emile_cipher_verify_get(const Emile_SSL *emile);
151EAPI Eina_Bool emile_cipher_verify_basic_get(const Emile_SSL *emile);
152
117typedef enum 153typedef enum
118{ 154{
119 EMILE_ZLIB, 155 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,
28{ 28{
29 return NULL; 29 return NULL;
30} 30}
31
32EAPI Emile_SSL *
33emile_cipher_server_listen(Emile_Cipher_Type t EINA_UNUSED)
34{
35 return NULL;
36}
37
38EAPI Emile_SSL *
39emile_cipher_client_connect(Emile_SSL *server EINA_UNUSED, int fd EINA_UNUSED)
40{
41 return NULL;
42}
43
44EAPI Emile_SSL *
45emile_cipher_server_connect(Emile_Cipher_Type t EINA_UNUSED)
46{
47 return NULL;
48}
49
50EAPI Eina_Bool
51emile_cipher_free(Emile_SSL *emile EINA_UNUSED)
52{
53 return EINA_TRUE;
54}
55
56EAPI Eina_Bool
57emile_cipher_cafile_add(Emile_SSL *emile EINA_UNUSED,
58 const char *file EINA_UNUSED)
59{
60 return EINA_FALSE;
61}
62
63EAPI Eina_Bool
64emile_cipher_cert_add(Emile_SSL *emile EINA_UNUSED,
65 const char *file EINA_UNUSED)
66{
67 return EINA_FALSE;
68}
69
70EAPI Eina_Bool
71emile_cipher_privkey_add(Emile_SSL *emile EINA_UNUSED,
72 const char *file EINA_UNUSED)
73{
74 return EINA_FALSE;
75}
76
77EAPI Eina_Bool
78emile_cipher_crl_add(Emile_SSL *emile EINA_UNUSED,
79 const char *file EINA_UNUSED)
80{
81 return EINA_FALSE;
82}
83
84EAPI int
85emile_cipher_read(Emile_SSL *emile EINA_UNUSED,
86 Eina_Binbuf *buffer EINA_UNUSED)
87{
88 return EINA_FALSE;
89}
90
91EAPI int
92emile_cipher_write(Emile_SSL *emile EINA_UNUSED,
93 const Eina_Binbuf *buffer EINA_UNUSED)
94{
95 return EINA_FALSE;
96}
97
98
99EAPI const char *
100emile_cipher_error_get(const Emile_SSL *emile EINA_UNUSED)
101{
102 return NULL;
103}
104
105EAPI Eina_Bool
106emile_cipher_verify_name_set(Emile_SSL *emile EINA_UNUSED,
107 const char *name EINA_UNUSED)
108{
109 return EINA_FALSE;
110}
111
112EAPI const char *
113emile_cipher_verify_name_get(const Emile_SSL *emile EINA_UNUSED)
114{
115 return NULL;
116}
117
118EAPI void
119emile_cipher_verify_set(Emile_SSL *emile EINA_UNUSED,
120 Eina_Bool verify EINA_UNUSED)
121{
122}
123
124EAPI void
125emile_cipher_verify_basic_set(Emile_SSL *emile EINA_UNUSED,
126 Eina_Bool verify_basic EINA_UNUSED)
127{
128}
129
130EAPI Eina_Bool
131emile_cipher_verify_get(const Emile_SSL *emile EINA_UNUSED)
132{
133 return EINA_FALSE;
134}
135
136EAPI Eina_Bool
137emile_cipher_verify_basic_get(const Emile_SSL *emile EINA_UNUSED)
138{
139 return EINA_FALSE;
140}
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 @@
19#define MAX_KEY_LEN 32 19#define MAX_KEY_LEN 32
20#define MAX_IV_LEN 16 20#define MAX_IV_LEN 16
21 21
22struct _Emile_SSL
23{
24 const char *last_error;
25 const char *cert_file;
26 const char *name;
27
28 gnutls_certificate_credentials_t cert;
29 gnutls_session_t session;
30
31 union {
32 struct {
33 gnutls_datum_t session_ticket;
34 } client;
35 struct {
36 gnutls_anon_client_credentials_t anoncred_c;
37 gnutls_anon_server_credentials_t anoncred_s;
38 gnutls_psk_client_credentials_t pskcred_c;
39 gnutls_psk_server_credentials_t pskcred_s;
40 char *cert_file;
41 gnutls_dh_params_t dh_params;
42 } server;
43 } u;
44
45 Emile_Cipher_Type t;
46 Emile_SSL_State ssl_state;
47
48 Eina_Bool server : 1;
49 Eina_Bool verify : 1;
50 Eina_Bool verify_basic : 1;
51};
52
22static int 53static int
23_emile_thread_mutex_init(void **priv) 54_emile_thread_mutex_init(void **priv)
24{ 55{
@@ -383,3 +414,284 @@ on_error:
383 414
384 return NULL; 415 return NULL;
385} 416}
417
418
419EAPI Eina_Bool
420emile_cipher_cafile_add(Emile_SSL *emile, const char *file)
421{
422 struct stat st;
423 int count = 0;
424
425 if (stat(file, &st)) return EINA_FALSE;
426 if (S_ISDIR(st.st_mode))
427 {
428 Eina_File_Direct_Info *info;
429 Eina_Iterator *it;
430 int err;
431
432 it = eina_file_direct_ls(file);
433 EINA_ITERATOR_FOREACH(it, info)
434 {
435 if (info->type != EINA_FILE_REG &&
436 info->type != EINA_FILE_LNK)
437 continue;
438
439 err = gnutls_certificate_set_x509_trust_file(emile->cert,
440 info->path,
441 GNUTLS_X509_FMT_PEM);
442 if (err > 0) count += err;
443 else DBG("File '%s' could not be loaded.", info->path);
444 }
445 eina_iterator_free(it);
446 }
447 else
448 {
449 count = gnutls_certificate_set_x509_trust_file(emile->cert,
450 file,
451 GNUTLS_X509_FMT_PEM);
452 if (count <= 0) DBG("File '%s' could not be loaded.", file);
453 }
454
455 return count > 0 ? EINA_TRUE : EINA_FALSE;
456}
457
458EAPI Eina_Bool
459emile_cipher_privkey_add(Emile_SSL *emile, const char *file)
460{
461 int err;
462
463 err = gnutls_certificate_set_x509_key_file(emile->cert,
464 emile->cert_file,
465 file,
466 GNUTLS_X509_FMT_PEM);
467
468 if (err <= 0) DBG("Could not load certificate/key '%s'.", file);
469 return err > 0 ? EINA_TRUE : EINA_FALSE;
470}
471
472EAPI Eina_Bool
473emile_cipher_crl_add(Emile_SSL *emile, const char *file)
474{
475 int err;
476
477 err = gnutls_certificate_set_x509_crl_file(emile->cert,
478 file,
479 GNUTLS_X509_FMT_PEM);
480 if (err <= 0) DBG("Could not load CRL '%s'.", file);
481 return err > 0 ? EINA_TRUE : EINA_FALSE;
482}
483
484EAPI Emile_SSL *
485emile_cipher_server_listen(Emile_Cipher_Type t)
486{
487 Emile_SSL *r;
488 int ret;
489
490 if (t != EMILE_SSLv23 &&
491 t != EMILE_SSLv3 &&
492 t != EMILE_TLSv1)
493 return NULL;
494
495 r = calloc(1, sizeof (Emile_SSL));
496 if (!r) return NULL;
497
498 ret = gnutls_certificate_allocate_credentials(&r->cert);
499 if (ret) goto on_error;
500
501 r->t = t;
502 r->server = EINA_TRUE;
503
504 return r;
505
506 on_error:
507 ERR("GNUTLS error: %s - %s.",
508 gnutls_strerror_name(ret),
509 gnutls_strerror(ret));
510 emile_cipher_free(r);
511 return NULL;
512}
513
514EAPI Emile_SSL *
515emile_cipher_client_connect(Emile_SSL *server, int fd)
516{
517}
518
519EAPI Emile_SSL *
520emile_cipher_server_connect(Emile_Cipher_Type t)
521{
522 const char *priority = "NORMAL:%VERIFY_ALLOW_X509_V1_CA_CRT";
523 Emile_SSL *r;
524 int ret;
525
526 switch (t)
527 {
528 case EMILE_SSLv23:
529 break;
530 case EMILE_SSLv3:
531 priority = "NORMAL:%VERIFY_ALLOW_X509_V1_CA_CRT:!VERS-TLS1.0:!VERS-TLS1.1:!VERS-TLS1.2";
532 break;
533 case EMILE_TLSv1:
534 priority = "NORMAL:%VERIFY_ALLOW_X509_V1_CA_CRT:!VERS-SSL3.0";
535 break;
536 default:
537 return NULL;
538 }
539
540 r = calloc(1, sizeof (Emile_SSL));
541 if (!r) return NULL;
542
543 r->server = EINA_FALSE;
544
545 ret = gnutls_certificate_allocate_credentials(&r->cert);
546 if (ret) goto on_error;
547
548 ret = gnutls_init(&r->session, GNUTLS_CLIENT);
549 if (ret) goto on_error;
550
551 ret = gnutls_session_ticket_enable_client(r->session);
552 if (ret) goto on_error;
553
554 // FIXME: Delay that until later access
555
556 ret = gnutls_server_name_set(r->session, GNUTLS_NAME_DNS,
557 r->name, strlen(r->name));
558 if (ret) goto on_error;
559
560 ret = gnutls_priority_set_direct(r->session, priority, NULL);
561 if (ret) goto on_error;
562
563 gnutls_handshake_set_private_extensions(r->session, 1);
564 ret = gnutls_credentials_set(r->session, GNUTLS_CRD_CERTIFICATE, r->cert));
565
566 return r;
567}
568
569EAPI Eina_Bool
570emile_cipher_free(Emile_SSL *emile)
571{
572}
573
574EAPI Eina_Bool
575emile_cipher_cafile_add(Emile_SSL *emile, const char *file)
576{
577 Eina_File_Direct_Info *info;
578 Eina_Iterator *it;
579 struct stat st;
580 int count = 0;
581 int ret;
582
583 if (stat(file, &st)) return EINA_FALSE;
584 if (S_ISDIR(st.st_mode))
585 {
586 it = eina_file_direct_ls(file);
587 EINA_ITERATOR_FOREACH(it, info)
588 {
589 if (!(info->type == EINA_FILE_UNKNOWN ||
590 info->type == EINA_FILE_REG ||
591 info->type == EINA_FILE_LNK))
592 continue ;
593
594 ret = gnutls_certificate_set_x509_trust_file(emile->cert,
595 file,
596 GNUTLS_X509_FMT_PEM);
597 if (ret > 0) count += ret;
598 }
599 eina_iterator_free(it);
600 }
601 else
602 {
603 ret = gnutls_certificate_set_x509_trust_file(emile->cert,
604 file,
605 GNUTLS_X509_FMT_PEM);
606 if (ret > 0) count += ret;
607 }
608
609 if (!count) ERR("Could not load CA file from '%s'.", file);
610 return !count ? EINA_FALSE : EINA_TRUE;
611}
612
613EAPI Eina_Bool
614emile_cipher_cert_add(Emile_SSL *emile, const char *file)
615{
616 return eina_stringshare_replace(&emile->cert_file, file);
617}
618
619EAPI Eina_Bool
620emile_cipher_privkey_add(Emile_SSL *emile, const char *file)
621{
622 int ret;
623
624 ret = gnutls_certificate_set_x509_key_file(emile->cert,
625 emile->cert_file,
626 file,
627 GNUTLS_X509_FMT_PEM);
628 if (ret)
629 ERR("Could not load certificate/key file ('%s'/'%s').",
630 emile->cert_file, file);
631 return ret ? EINA_FALSE : EINA_TRUE;
632}
633
634EAPI Eina_Bool
635emile_cipher_crl_add(Emile_SSL *emile, const char *file)
636{
637 int ret;
638
639 ret = gnutls_certificate_set_x509_crl_file(emile->cert, file,
640 GNUTLS_X509_FMT_PEM);
641 if (ret)
642 ERR("Could not load CRL file from '%s'.", file);
643 return ret ? EINA_FALSE : EINA_TRUE;
644}
645
646EAPI int
647emile_cipher_read(Emile_SSL *emile, Eina_Binbuf *buffer)
648{
649}
650
651EAPI int
652emile_cipher_write(Emile_SSL *emile, const Eina_Binbuf *buffer)
653{
654}
655
656EAPI const char *
657emile_cipher_error_get(const Emile_SSL *emile)
658{
659 return emile->last_error;
660}
661
662EAPI Eina_Bool
663emile_cipher_verify_name_set(Emile_SSL *emile, const char *name)
664{
665 return eina_stringshare_replace(&emile->name, name);
666}
667
668EAPI const char *
669emile_cipher_verify_name_get(const Emile_SSL *emile)
670{
671 return emile->name;
672}
673
674EAPI void
675emile_cipher_verify_set(Emile_SSL *emile, Eina_Bool verify)
676{
677 emile->verify = verify;
678}
679
680EAPI void
681emile_cipher_verify_basic_set(Emile_SSL *emile, Eina_Bool verify_basic)
682{
683 emile->verify_basic = verify_basic;
684}
685
686EAPI Eina_Bool
687emile_cipher_verify_get(const Emile_SSL *emile)
688{
689 return emile->verify;
690}
691
692EAPI Eina_Bool
693emile_cipher_verify_basic_get(const Emile_SSL *emile)
694{
695 return emile->verify_basic;
696}
697
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 @@
10#include <openssl/evp.h> 10#include <openssl/evp.h>
11#include <openssl/hmac.h> 11#include <openssl/hmac.h>
12#include <openssl/rand.h> 12#include <openssl/rand.h>
13#include <openssl/ssl.h>
14#include <openssl/err.h>
15#include <openssl/dh.h>
13 16
14#include <Eina.h> 17#include <Eina.h>
15 18
@@ -20,6 +23,29 @@
20#define MAX_KEY_LEN EVP_MAX_KEY_LENGTH 23#define MAX_KEY_LEN EVP_MAX_KEY_LENGTH
21#define MAX_IV_LEN EVP_MAX_IV_LENGTH 24#define MAX_IV_LEN EVP_MAX_IV_LENGTH
22 25
26struct _Emile_SSL
27{
28 Emile_SSL *parent;
29 SSL_CTX *ssl_ctx;
30 SSL *ssl;
31
32 const char *last_error;
33 const char *verify_name;
34
35 int ssl_err;
36 Emile_SSL_State ssl_state;
37 Emile_Want_Type ssl_want;
38
39 Eina_Bool server : 1;
40 Eina_Bool listen : 1;
41 Eina_Bool connecting : 1;
42 Eina_Bool handshaking : 1;
43 Eina_Bool upgrade : 1;
44 Eina_Bool crl_flag : 1;
45 Eina_Bool verify : 1;
46 Eina_Bool verify_basic : 1;
47};
48
23Eina_Bool 49Eina_Bool
24_emile_cipher_init(void) 50_emile_cipher_init(void)
25{ 51{
@@ -281,3 +307,821 @@ on_error:
281 307
282 return NULL; 308 return NULL;
283} 309}
310
311EAPI Emile_SSL *
312emile_cipher_server_listen(Emile_Cipher_Type t)
313{
314 Emile_SSL *r;
315 DH *dh_params = NULL;
316 int options;
317 int dh = 0;
318
319 if (!emile_cipher_init()) return NULL;
320
321 r = calloc(1, sizeof (Emile_SSL));
322 if (!r) return NULL;
323
324 switch (t)
325 {
326 case EMILE_SSLv23:
327 r->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
328 if (!r->ssl_ctx) goto on_error;
329 options = SSL_CTX_get_options(r->ssl_ctx);
330 SSL_CTX_set_options(r->ssl_ctx,
331 options | SSL_OP_NO_SSLv2 | SSL_OP_SINGLE_DH_USE);
332 break;
333 case EMILE_SSLv3:
334 r->ssl_ctx = SSL_CTX_new(SSLv3_server_method());
335 break;
336 case EMILE_TLSv1:
337 r->ssl_ctx = SSL_CTX_new(TLSv1_server_method());
338 break;
339 default:
340 free(r);
341 return NULL;
342 }
343
344 if (!r->ssl_ctx) goto on_error;
345
346 dh_params = DH_new();
347 if (!dh_params) goto on_error;
348 if (!DH_generate_parameters_ex(dh_params, 1024, DH_GENERATOR_5, NULL))
349 goto on_error;
350 if (!DH_check(dh_params, &dh))
351 goto on_error;
352 if ((dh & DH_CHECK_P_NOT_PRIME) || (dh & DH_CHECK_P_NOT_SAFE_PRIME))
353 goto on_error;
354 if (!DH_generate_key(dh_params))
355 goto on_error;
356 if (!SSL_CTX_set_tmp_dh(r->ssl_ctx, dh_params))
357 goto on_error;
358
359 DH_free(dh_params);
360 INF("DH params successfully generated and applied!");
361
362 if (!SSL_CTX_set_cipher_list(r->ssl_ctx,
363 "aNULL:!eNULL:!LOW:!EXPORT:@STRENGTH"))
364 goto on_error;
365
366 return r;
367
368 on_error:
369 if (dh)
370 {
371 if (dh & DH_CHECK_P_NOT_PRIME)
372 ERR("openssl error: dh_params could not generate a prime!");
373 else
374 ERR("openssl error: dh_params could not generate a safe prime!");
375 }
376 else
377 {
378 ERR("openssl error: %s.", ERR_reason_error_string(ERR_get_error()));
379 }
380 emile_cipher_free(r);
381 return NULL;
382}
383
384static void
385_emile_cipher_print_verify_error(int error)
386{
387 switch (error)
388 {
389#define ERROR(X) \
390case (X): \
391 ERR("%s", #X); \
392 break
393#ifdef X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
394 ERROR(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT);
395#endif
396#ifdef X509_V_ERR_UNABLE_TO_GET_CRL
397 ERROR(X509_V_ERR_UNABLE_TO_GET_CRL);
398#endif
399#ifdef X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE
400 ERROR(X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE);
401#endif
402#ifdef X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE
403 ERROR(X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE);
404#endif
405#ifdef X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY
406 ERROR(X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY);
407#endif
408#ifdef X509_V_ERR_CERT_SIGNATURE_FAILURE
409 ERROR(X509_V_ERR_CERT_SIGNATURE_FAILURE);
410#endif
411#ifdef X509_V_ERR_CRL_SIGNATURE_FAILURE
412 ERROR(X509_V_ERR_CRL_SIGNATURE_FAILURE);
413#endif
414#ifdef X509_V_ERR_CERT_NOT_YET_VALID
415 ERROR(X509_V_ERR_CERT_NOT_YET_VALID);
416#endif
417#ifdef X509_V_ERR_CERT_HAS_EXPIRED
418 ERROR(X509_V_ERR_CERT_HAS_EXPIRED);
419#endif
420#ifdef X509_V_ERR_CRL_NOT_YET_VALID
421 ERROR(X509_V_ERR_CRL_NOT_YET_VALID);
422#endif
423#ifdef X509_V_ERR_CRL_HAS_EXPIRED
424 ERROR(X509_V_ERR_CRL_HAS_EXPIRED);
425#endif
426#ifdef X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD
427 ERROR(X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD);
428#endif
429#ifdef X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD
430 ERROR(X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD);
431#endif
432#ifdef X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD
433 ERROR(X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD);
434#endif
435#ifdef X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD
436 ERROR(X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
437#endif
438#ifdef X509_V_ERR_OUT_OF_MEM
439 ERROR(X509_V_ERR_OUT_OF_MEM);
440#endif
441#ifdef X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
442 ERROR(X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT);
443#endif
444#ifdef X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
445 ERROR(X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN);
446#endif
447#ifdef X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
448 ERROR(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY);
449#endif
450#ifdef X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
451 ERROR(X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE);
452#endif
453#ifdef X509_V_ERR_CERT_CHAIN_TOO_LONG
454 ERROR(X509_V_ERR_CERT_CHAIN_TOO_LONG);
455#endif
456#ifdef X509_V_ERR_CERT_REVOKED
457 ERROR(X509_V_ERR_CERT_REVOKED);
458#endif
459#ifdef X509_V_ERR_INVALID_CA
460 ERROR(X509_V_ERR_INVALID_CA);
461#endif
462#ifdef X509_V_ERR_PATH_LENGTH_EXCEEDED
463 ERROR(X509_V_ERR_PATH_LENGTH_EXCEEDED);
464#endif
465#ifdef X509_V_ERR_INVALID_PURPOSE
466 ERROR(X509_V_ERR_INVALID_PURPOSE);
467#endif
468#ifdef X509_V_ERR_CERT_UNTRUSTED
469 ERROR(X509_V_ERR_CERT_UNTRUSTED);
470#endif
471#ifdef X509_V_ERR_CERT_REJECTED
472 ERROR(X509_V_ERR_CERT_REJECTED);
473#endif
474 /* These are 'informational' when looking for issuer cert */
475#ifdef X509_V_ERR_SUBJECT_ISSUER_MISMATCH
476 ERROR(X509_V_ERR_SUBJECT_ISSUER_MISMATCH);
477#endif
478#ifdef X509_V_ERR_AKID_SKID_MISMATCH
479 ERROR(X509_V_ERR_AKID_SKID_MISMATCH);
480#endif
481#ifdef X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH
482 ERROR(X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH);
483#endif
484#ifdef X509_V_ERR_KEYUSAGE_NO_CERTSIGN
485 ERROR(X509_V_ERR_KEYUSAGE_NO_CERTSIGN);
486#endif
487
488#ifdef X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER
489 ERROR(X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER);
490#endif
491#ifdef X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION
492 ERROR(X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION);
493#endif
494#ifdef X509_V_ERR_KEYUSAGE_NO_CRL_SIGN
495 ERROR(X509_V_ERR_KEYUSAGE_NO_CRL_SIGN);
496#endif
497#ifdef X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION
498 ERROR(X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION);
499#endif
500#ifdef X509_V_ERR_INVALID_NON_CA
501 ERROR(X509_V_ERR_INVALID_NON_CA);
502#endif
503#ifdef X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED
504 ERROR(X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED);
505#endif
506#ifdef X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE
507 ERROR(X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE);
508#endif
509#ifdef X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED
510 ERROR(X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED);
511#endif
512
513#ifdef X509_V_ERR_INVALID_EXTENSION
514 ERROR(X509_V_ERR_INVALID_EXTENSION);
515#endif
516#ifdef X509_V_ERR_INVALID_POLICY_EXTENSION
517 ERROR(X509_V_ERR_INVALID_POLICY_EXTENSION);
518#endif
519#ifdef X509_V_ERR_NO_EXPLICIT_POLICY
520 ERROR(X509_V_ERR_NO_EXPLICIT_POLICY);
521#endif
522#ifdef X509_V_ERR_DIFFERENT_CRL_SCOPE
523 ERROR(X509_V_ERR_DIFFERENT_CRL_SCOPE);
524#endif
525#ifdef X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE
526 ERROR(X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE);
527#endif
528
529#ifdef X509_V_ERR_UNNESTED_RESOURCE
530 ERROR(X509_V_ERR_UNNESTED_RESOURCE);
531#endif
532
533#ifdef X509_V_ERR_PERMITTED_VIOLATION
534 ERROR(X509_V_ERR_PERMITTED_VIOLATION);
535#endif
536#ifdef X509_V_ERR_EXCLUDED_VIOLATION
537 ERROR(X509_V_ERR_EXCLUDED_VIOLATION);
538#endif
539#ifdef X509_V_ERR_SUBTREE_MINMAX
540 ERROR(X509_V_ERR_SUBTREE_MINMAX);
541#endif
542#ifdef X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE
543 ERROR(X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE);
544#endif
545#ifdef X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX
546 ERROR(X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX);
547#endif
548#ifdef X509_V_ERR_UNSUPPORTED_NAME_SYNTAX
549 ERROR(X509_V_ERR_UNSUPPORTED_NAME_SYNTAX);
550#endif
551#ifdef X509_V_ERR_CRL_PATH_VALIDATION_ERROR
552 ERROR(X509_V_ERR_CRL_PATH_VALIDATION_ERROR);
553#endif
554
555 /* The application is not happy */
556#ifdef X509_V_ERR_APPLICATION_VERIFICATION
557 ERROR(X509_V_ERR_APPLICATION_VERIFICATION);
558#endif
559 }
560#undef ERROR
561}
562
563static void
564_emile_cipher_session_print(SSL *ssl)
565{
566 Eina_Strbuf *str;
567 SSL_SESSION *s;
568 STACK_OF(X509) *sk;
569 BIO *b;
570 BUF_MEM *bptr;
571 char log[4096];
572
573 if (!eina_log_domain_level_check(_emile_log_dom_global, EINA_LOG_LEVEL_DBG))
574 return ;
575
576 str = eina_strbuf_new();
577 if (!str) return ;
578
579 log[0] = '\0';
580 b = BIO_new(BIO_s_mem());
581 sk = SSL_get_peer_cert_chain(ssl);
582 if (sk)
583 {
584 int i;
585
586 DBG("CERTIFICATES:");
587 for (i = 0; i < sk_X509_num(sk); i++)
588 {
589 char *p;
590
591 p = X509_NAME_oneline(X509_get_subject_name(sk_X509_value(sk, i)),
592 log, sizeof (log));
593 DBG("%2d s:%s", i, p);
594 p = X509_NAME_oneline(X509_get_issuer_name(sk_X509_value(sk, i)),
595 log, sizeof(log));
596 DBG(" i:%s", p);
597
598 PEM_write_bio_X509(b, sk_X509_value(sk, i));
599 BIO_get_mem_ptr(b, &bptr);
600 eina_strbuf_append_length(str, bptr->data, bptr->length);
601 DBG("%s", eina_strbuf_string_get(str));
602 eina_strbuf_reset(str);
603 BIO_free(b);
604 }
605 }
606
607 s = SSL_get_session(ssl);
608 SSL_SESSION_print(b, s);
609 BIO_get_mem_ptr(b, &bptr);
610 eina_strbuf_append_length(str, bptr->data, bptr->length);
611 DBG("%s", eina_strbuf_string_get(str));
612 eina_strbuf_free(str);
613 BIO_free(b);
614}
615
616static void
617_emile_cipher_client_handshake(Emile_SSL *client)
618{
619 X509 *cert;
620 int ret = -1;
621
622 if (!client) return ;
623
624 switch (client->ssl_state)
625 {
626 case EMILE_SSL_STATE_INIT:
627 client->ssl_state = EMILE_SSL_STATE_HANDSHAKING;
628 client->handshaking = EINA_TRUE;
629
630 case EMILE_SSL_STATE_HANDSHAKING:
631 if (!client->ssl) goto on_error;
632
633 ret = SSL_do_handshake(client->ssl);
634 client->ssl_err = SSL_get_error(client->ssl, ret);
635
636 if ((client->ssl_err == SSL_ERROR_SYSCALL) ||
637 (client->ssl_err == SSL_ERROR_SSL))
638 goto on_error;
639
640 if (ret != 1)
641 {
642 if (client->ssl_err == SSL_ERROR_WANT_READ)
643 client->ssl_want = EMILE_WANT_READ;
644 else if (client->ssl_err == SSL_ERROR_WANT_WRITE)
645 client->ssl_want = EMILE_WANT_WRITE;
646
647 return ;
648 }
649
650 client->handshaking = EINA_FALSE;
651 client->ssl_state = EMILE_SSL_STATE_DONE;
652 case EMILE_SSL_STATE_DONE:
653 break;
654 case EMILE_SSL_STATE_ERROR:
655 goto on_error;
656 }
657
658 _emile_cipher_session_print(client->ssl);
659 if (!client->parent->verify &&
660 !client->parent->verify_basic)
661 return ;
662
663 SSL_set_verify(client->ssl, SSL_VERIFY_PEER, NULL);
664 /* use CRL/CA lists to verify */
665 cert = SSL_get_peer_certificate(client->ssl);
666 if (cert)
667 {
668 const char *verify_name;
669 char *cert_name;
670 char *s;
671 int clen;
672 int err;
673 int name = 0;
674
675 if (client->parent->verify)
676 {
677 err = SSL_get_verify_result(client->ssl);
678 _emile_cipher_print_verify_error(err);
679 if (err) goto on_error;
680 }
681
682 clen = X509_NAME_get_text_by_NID(X509_get_subject_name(cert),
683 NID_subject_alt_name,
684 NULL, 0);
685 if (clen > 0)
686 {
687 name = NID_subject_alt_name;
688 }
689 else
690 {
691 clen = X509_NAME_get_text_by_NID(X509_get_subject_name(cert),
692 NID_commonName,
693 NULL, 0);
694 if (clen <= 0) goto on_error;
695 name = NID_commonName;
696 }
697
698 cert_name = alloca(++clen);
699 X509_NAME_get_text_by_NID(X509_get_subject_name(cert),
700 name, cert_name, clen);
701 verify_name = client->parent->verify_name;
702
703 INF("Cert name: '%s' vs verify name: '%s'.", cert_name, verify_name);
704
705 if (!verify_name) goto on_error;
706 if (strcasecmp(cert_name, verify_name)) goto on_error;
707 if (verify_name[0] != '*') goto on_error;
708
709 /* verify that their is only one wildcard in the client cert name */
710 if (strchr(cert_name + 1, '*')) goto on_error;
711 /* verify that we have a domain of at least *.X.TLD and not *.TLD */
712 if (!strchr(cert_name + 2, '.')) goto on_error;
713 s = strchr(verify_name, '.');
714 if (!s) goto on_error;
715 /* same as above for the stored name */
716 if (!strchr(s + 1, '.')) goto on_error;
717 if (strcasecmp(s, verify_name + 1)) goto on_error;
718
719 DBG("Successfully verified certificate.");
720 }
721
722 return ;
723
724 on_error:
725 DBG("Failed to finish handshake.");
726 client->ssl_state = EMILE_SSL_STATE_ERROR;
727 return ;
728}
729
730EAPI Emile_SSL *
731emile_cipher_client_connect(Emile_SSL *server, int fd)
732{
733 Emile_SSL *r;
734
735 if (!server) return NULL;
736
737 r = calloc(1, sizeof (Emile_SSL));
738 if (!r) return NULL;
739
740 r->parent = server;
741 r->ssl = SSL_new(r->parent->ssl_ctx);
742 if (!r->ssl) goto on_error;
743
744 if (!SSL_set_fd(r->ssl, fd))
745 goto on_error;
746
747 SSL_set_accept_state(r->ssl);
748
749 _emile_cipher_client_handshake(r);
750
751 if (r->ssl_state == EMILE_SSL_STATE_ERROR) goto on_error;
752
753 return r;
754
755 on_error:
756 emile_cipher_free(r);
757 return NULL;
758}
759
760EAPI Emile_SSL *
761emile_cipher_server_connect(Emile_Cipher_Type t)
762{
763 Emile_SSL *r;
764 const char *msg;
765 int options;
766 int dh = 0;
767
768 if (!emile_cipher_init()) return NULL;
769
770 r = calloc(1, sizeof (Emile_SSL));
771 if (!r) return NULL;
772
773 switch (t)
774 {
775 case EMILE_SSLv23:
776 r->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
777 if (!r->ssl_ctx) goto on_error;
778 options = SSL_CTX_get_options(r->ssl_ctx);
779 SSL_CTX_set_options(r->ssl_ctx,
780 options | SSL_OP_NO_SSLv2 | SSL_OP_SINGLE_DH_USE);
781 break;
782 case EMILE_SSLv3:
783 r->ssl_ctx = SSL_CTX_new(SSLv3_client_method());
784 break;
785 case EMILE_TLSv1:
786 r->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
787 break;
788 default:
789 free(r);
790 return NULL;
791 }
792
793 if (!SSL_CTX_set_cipher_list(r->ssl_ctx,
794 "aNULL:!eNULL:!LOW:!EXPORT:!ECDH:RSA:AES:!PSK:@STRENGTH"))
795 goto on_error;
796
797 return r;
798
799 on_error:
800 if (dh)
801 {
802 if (dh & DH_CHECK_P_NOT_PRIME)
803 msg = "dh_params could not generate a prime!";
804 else
805 msg = "dh_params could not generate a safe prime!";
806 }
807 else
808 {
809 msg = ERR_reason_error_string(ERR_get_error());
810 }
811
812 ERR("OpenSSL error: '%s'.", msg);
813 emile_cipher_free(r);
814 return NULL;
815}
816
817EAPI Eina_Bool
818emile_cipher_free(Emile_SSL *emile)
819{
820 if (!emile) return EINA_FALSE;
821
822 eina_stringshare_del(emile->last_error);
823 emile->last_error = NULL;
824
825 eina_stringshare_del(emile->verify_name);
826 emile->verify_name = NULL;
827
828 if (emile->ssl)
829 {
830 if (!SSL_shutdown(emile->ssl))
831 SSL_shutdown(emile->ssl);
832
833 SSL_free(emile->ssl);
834 }
835 emile->ssl = NULL;
836
837 if (emile->ssl_ctx)
838 SSL_CTX_free(emile->ssl_ctx);
839 emile->ssl_ctx = NULL;
840
841 free(emile);
842 return EINA_TRUE;
843}
844
845EAPI Eina_Bool
846emile_cipher_cafile_add(Emile_SSL *emile, const char *file)
847{
848 struct stat st;
849 unsigned long err;
850
851 if (stat(file, &st)) return EINA_FALSE;
852 if (S_ISDIR(st.st_mode))
853 {
854 if (!SSL_CTX_load_verify_locations(emile->ssl_ctx, NULL, file))
855 goto on_error;
856 }
857 else
858 {
859 if (!SSL_CTX_load_verify_locations(emile->ssl_ctx, file, NULL))
860 goto on_error;
861 }
862
863 return EINA_TRUE;
864
865 on_error:
866 err = ERR_peek_last_error();
867 if (!err) return EINA_FALSE;
868
869 DBG("OpenSSL error: '%s'.", ERR_reason_error_string(err));
870 eina_stringshare_replace(&emile->last_error, ERR_reason_error_string(err));
871 return EINA_FALSE;
872}
873
874EAPI Eina_Bool
875emile_cipher_cert_add(Emile_SSL *emile, const char *file)
876{
877 Eina_File *f;
878 void *m;
879 X509 *cert = NULL;
880 BIO *bio = NULL;
881 int err;
882
883 f = eina_file_open(file, EINA_FALSE);
884 if (!f) return EINA_FALSE;
885
886 m = eina_file_map_all(f, EINA_FILE_WILLNEED);
887 if (!m) goto on_error;
888
889 bio = BIO_new_mem_buf(m, eina_file_size_get(f));
890 if (!bio) goto on_error;
891
892 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
893 if (!cert) goto on_error;
894
895 if (SSL_CTX_use_certificate(emile->ssl_ctx, cert) < 1)
896 goto on_error;
897
898 eina_file_map_free(f, m);
899 eina_file_close(f);
900 BIO_free(bio);
901
902 return EINA_TRUE;
903
904 on_error:
905 err = ERR_peek_last_error();
906
907 if (m) eina_file_map_free(f, m);
908 if (f) eina_file_close(f);
909 if (bio) BIO_free(bio);
910
911 if (!err) return EINA_FALSE;
912
913 DBG("OpenSSL error: '%s'.", ERR_reason_error_string(err));
914 eina_stringshare_replace(&emile->last_error, ERR_reason_error_string(err));
915 return EINA_FALSE;
916}
917
918EAPI Eina_Bool
919emile_cipher_privkey_add(Emile_SSL *emile, const char *file)
920{
921 Eina_File *f;
922 void *m;
923 EVP_PKEY *privkey = NULL;
924 BIO *bio = NULL;
925 int err;
926
927 f = eina_file_open(file, EINA_FALSE);
928 if (!f) return EINA_FALSE;
929
930 m = eina_file_map_all(f, EINA_FILE_WILLNEED);
931 if (!m) goto on_error;
932
933 bio = BIO_new_mem_buf(m, eina_file_size_get(f));
934 if (!bio) goto on_error;
935
936 privkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
937 if (!privkey) goto on_error;
938
939 eina_file_map_free(f, m);
940 m = NULL;
941
942 eina_file_close(f);
943 f = NULL;
944
945 if (SSL_CTX_use_PrivateKey(emile->ssl_ctx, privkey) < 1)
946 goto on_error;
947
948 if (SSL_CTX_check_private_key(emile->ssl_ctx) < 1)
949 goto on_error;
950
951 BIO_free(bio);
952
953 return EINA_TRUE;
954
955 on_error:
956 err = ERR_peek_last_error();
957
958 if (m) eina_file_map_free(f, m);
959 if (f) eina_file_close(f);
960 if (bio) BIO_free(bio);
961
962 if (!err) return EINA_FALSE;
963
964 DBG("OpenSSL error: '%s'.", ERR_reason_error_string(err));
965 eina_stringshare_replace(&emile->last_error, ERR_reason_error_string(err));
966 return EINA_FALSE;
967}
968
969EAPI Eina_Bool
970emile_cipher_crl_add(Emile_SSL *emile, const char *file)
971{
972 X509_LOOKUP *lu;
973 X509_STORE *st;
974 int err;
975
976 st = SSL_CTX_get_cert_store(emile->ssl_ctx);
977 if (!st) goto on_error;
978
979 lu = X509_STORE_add_lookup(st, X509_LOOKUP_file());
980 if (!lu) goto on_error;
981
982 if (X509_load_crl_file(lu, file, X509_FILETYPE_PEM) < 1)
983 goto on_error;
984
985 if (!emile->crl_flag)
986 {
987 X509_STORE_set_flags(st,
988 X509_V_FLAG_CRL_CHECK |
989 X509_V_FLAG_CRL_CHECK_ALL);
990 emile->crl_flag = EINA_TRUE;
991 }
992
993 return EINA_TRUE;
994
995 on_error:
996 err = ERR_peek_last_error();
997 if (!err) return EINA_FALSE;
998
999 DBG("OpenSSL error: '%s'.", ERR_reason_error_string(err));
1000 eina_stringshare_replace(&emile->last_error, ERR_reason_error_string(err));
1001 return EINA_FALSE;
1002}
1003
1004EAPI int
1005emile_cipher_read(Emile_SSL *emile, Eina_Binbuf *buffer)
1006{
1007 int err;
1008 int num;
1009
1010 if (!emile->ssl) return -1;
1011 if (eina_binbuf_length_get(buffer) <= 0) return 0;
1012
1013 num = SSL_read(emile->ssl,
1014 (void*) eina_binbuf_string_get(buffer),
1015 eina_binbuf_length_get(buffer));
1016 emile->ssl_err = SSL_get_error(emile->ssl, num);
1017
1018 switch (emile->ssl_err)
1019 {
1020 case SSL_ERROR_WANT_READ: emile->ssl_want = EMILE_WANT_READ; break;
1021 case SSL_ERROR_WANT_WRITE: emile->ssl_want = EMILE_WANT_WRITE; break;
1022 case SSL_ERROR_ZERO_RETURN:
1023 case SSL_ERROR_SYSCALL:
1024 case SSL_ERROR_SSL:
1025 err = ERR_peek_last_error();
1026 if (!err) return -1;
1027
1028 DBG("OpenSSL error: '%s'.", ERR_reason_error_string(err));
1029 eina_stringshare_replace(&emile->last_error, ERR_reason_error_string(err));
1030 return -1;
1031
1032 default:
1033 emile->ssl_want = EMILE_WANT_NOTHING;
1034 break;
1035 }
1036
1037 if (emile->ssl_state == EMILE_SSL_STATE_HANDSHAKING)
1038 _emile_cipher_client_handshake(emile);
1039 if (emile->ssl_state == EMILE_SSL_STATE_ERROR)
1040 return -1;
1041
1042 return num < 0 ? 0 : num;
1043}
1044
1045EAPI int
1046emile_cipher_write(Emile_SSL *emile, const Eina_Binbuf *buffer)
1047{
1048 int num;
1049 int err;
1050
1051 if (!emile->ssl) return -1;
1052 if (eina_binbuf_length_get(buffer) <= 0) return 0;
1053
1054 num = SSL_write(emile->ssl,
1055 (void*) eina_binbuf_string_get(buffer),
1056 eina_binbuf_length_get(buffer));
1057 emile->ssl_err = SSL_get_error(emile->ssl, num);
1058
1059 switch (emile->ssl_err)
1060 {
1061 case SSL_ERROR_WANT_READ: emile->ssl_want = EMILE_WANT_READ; break;
1062 case SSL_ERROR_WANT_WRITE: emile->ssl_want = EMILE_WANT_WRITE; break;
1063 case SSL_ERROR_ZERO_RETURN:
1064 case SSL_ERROR_SYSCALL:
1065 case SSL_ERROR_SSL:
1066 err = ERR_peek_last_error();
1067 if (!err) return -1;
1068
1069 DBG("OpenSSL error: '%s'.", ERR_reason_error_string(err));
1070 eina_stringshare_replace(&emile->last_error, ERR_reason_error_string(err));
1071 return -1;
1072
1073 default:
1074 emile->ssl_want = EMILE_WANT_NOTHING;
1075 break;
1076 }
1077
1078 if (emile->ssl_state == EMILE_SSL_STATE_HANDSHAKING)
1079 _emile_cipher_client_handshake(emile);
1080 if (emile->ssl_state == EMILE_SSL_STATE_ERROR)
1081 return -1;
1082
1083 return num < 0 ? 0 : num;
1084}
1085
1086EAPI const char *
1087emile_cipher_error_get(const Emile_SSL *emile)
1088{
1089 return emile->last_error;
1090}
1091
1092EAPI Eina_Bool
1093emile_cipher_verify_name_set(Emile_SSL *emile, const char *name)
1094{
1095 return eina_stringshare_replace(&emile->verify_name, name);
1096}
1097
1098EAPI const char *
1099emile_cipher_verify_name_get(const Emile_SSL *emile)
1100{
1101 return emile->verify_name;
1102}
1103
1104EAPI void
1105emile_cipher_verify_set(Emile_SSL *emile, Eina_Bool verify)
1106{
1107 emile->verify = verify;
1108}
1109
1110EAPI void
1111emile_cipher_verify_basic_set(Emile_SSL *emile, Eina_Bool verify_basic)
1112{
1113 emile->verify_basic = verify_basic;
1114}
1115
1116EAPI Eina_Bool
1117emile_cipher_verify_get(const Emile_SSL *emile)
1118{
1119 return emile->verify;
1120}
1121
1122EAPI Eina_Bool
1123emile_cipher_verify_basic_get(const Emile_SSL *emile)
1124{
1125 return emile->verify_basic;
1126}
1127
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)
73 EINA_LOG_STATE_START, 73 EINA_LOG_STATE_START,
74 EINA_LOG_STATE_SHUTDOWN); 74 EINA_LOG_STATE_SHUTDOWN);
75 75
76 if (_emile_cipher_init) 76 if (_emile_cipher_inited)
77 { 77 {
78#ifdef HAVE_GNUTLS 78#ifdef HAVE_GNUTLS
79 /* Note that gnutls has a leak where it doesnt free stuff it alloced 79 /* 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;
24#endif /* ifdef CRI */ 24#endif /* ifdef CRI */
25#define CRI(...) EINA_LOG_DOM_CRIT(_emile_log_dom_global, __VA_ARGS__) 25#define CRI(...) EINA_LOG_DOM_CRIT(_emile_log_dom_global, __VA_ARGS__)
26 26
27typedef enum
28{
29 EMILE_SSL_STATE_INIT = 0,
30 EMILE_SSL_STATE_HANDSHAKING,
31 EMILE_SSL_STATE_DONE,
32 EMILE_SSL_STATE_ERROR
33} Emile_SSL_State;
34
27Eina_Bool _emile_cipher_init(void); 35Eina_Bool _emile_cipher_init(void);
28 36
29#endif /* EMILE_PRIVATE_H_ */ 37#endif /* EMILE_PRIVATE_H_ */