diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c | 471 |
1 files changed, 402 insertions, 69 deletions
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c b/libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c index c352e94..6104632 100644 --- a/libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c +++ b/libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c | |||
@@ -16,6 +16,7 @@ | |||
16 | # include <ws2tcpip.h> | 16 | # include <ws2tcpip.h> |
17 | #endif | 17 | #endif |
18 | 18 | ||
19 | #include <sys/stat.h> | ||
19 | #include "Ecore.h" | 20 | #include "Ecore.h" |
20 | #include "ecore_con_private.h" | 21 | #include "ecore_con_private.h" |
21 | 22 | ||
@@ -60,12 +61,34 @@ _gnutls_print_errors(void *conn, int type, int ret) | |||
60 | ecore_con_event_server_error(conn, buf); | 61 | ecore_con_event_server_error(conn, buf); |
61 | } | 62 | } |
62 | 63 | ||
64 | static void | ||
65 | _gnutls_print_session(const gnutls_datum_t *cert_list, unsigned int cert_list_size) | ||
66 | { | ||
67 | char *c = NULL; | ||
68 | gnutls_x509_crt_t crt; | ||
69 | unsigned int x; | ||
70 | |||
71 | if (!eina_log_domain_level_check(_ecore_con_log_dom, EINA_LOG_LEVEL_DBG)) return; | ||
72 | for (x = 0; x < cert_list_size; x++) | ||
73 | { | ||
74 | gnutls_x509_crt_init(&crt); | ||
75 | gnutls_x509_crt_import(crt, &cert_list[x], GNUTLS_X509_FMT_DER); | ||
76 | gnutls_x509_crt_print(crt, GNUTLS_CRT_PRINT_FULL, (gnutls_datum_t*)&c); | ||
77 | INF("CERTIFICATE:\n%s", c); | ||
78 | gnutls_free(c); | ||
79 | gnutls_x509_crt_deinit(crt); | ||
80 | crt = NULL; | ||
81 | } | ||
82 | } | ||
83 | |||
63 | #ifdef ISCOMFITOR | 84 | #ifdef ISCOMFITOR |
64 | static void | 85 | static void |
65 | _gnutls_log_func(int level, | 86 | _gnutls_log_func(int level, |
66 | const char *str) | 87 | const char *str) |
67 | { | 88 | { |
68 | DBG("|<%d>| %s", level, str); | 89 | char buf[128]; |
90 | strncat(buf, str, strlen(str) - 1); | ||
91 | DBG("|<%d>| %s", level, buf); | ||
69 | } | 92 | } |
70 | #endif | 93 | #endif |
71 | 94 | ||
@@ -116,6 +139,185 @@ SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_description_t status) | |||
116 | #elif USE_OPENSSL | 139 | #elif USE_OPENSSL |
117 | 140 | ||
118 | static void | 141 | static void |
142 | _openssl_print_verify_error(int error) | ||
143 | { | ||
144 | switch (error) | ||
145 | { | ||
146 | #define ERROR(X) \ | ||
147 | case (X): \ | ||
148 | ERR("%s", #X); \ | ||
149 | break | ||
150 | #ifdef X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT | ||
151 | ERROR(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT); | ||
152 | #endif | ||
153 | #ifdef X509_V_ERR_UNABLE_TO_GET_CRL | ||
154 | ERROR(X509_V_ERR_UNABLE_TO_GET_CRL); | ||
155 | #endif | ||
156 | #ifdef X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE | ||
157 | ERROR(X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE); | ||
158 | #endif | ||
159 | #ifdef X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE | ||
160 | ERROR(X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE); | ||
161 | #endif | ||
162 | #ifdef X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY | ||
163 | ERROR(X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY); | ||
164 | #endif | ||
165 | #ifdef X509_V_ERR_CERT_SIGNATURE_FAILURE | ||
166 | ERROR(X509_V_ERR_CERT_SIGNATURE_FAILURE); | ||
167 | #endif | ||
168 | #ifdef X509_V_ERR_CRL_SIGNATURE_FAILURE | ||
169 | ERROR(X509_V_ERR_CRL_SIGNATURE_FAILURE); | ||
170 | #endif | ||
171 | #ifdef X509_V_ERR_CERT_NOT_YET_VALID | ||
172 | ERROR(X509_V_ERR_CERT_NOT_YET_VALID); | ||
173 | #endif | ||
174 | #ifdef X509_V_ERR_CERT_HAS_EXPIRED | ||
175 | ERROR(X509_V_ERR_CERT_HAS_EXPIRED); | ||
176 | #endif | ||
177 | #ifdef X509_V_ERR_CRL_NOT_YET_VALID | ||
178 | ERROR(X509_V_ERR_CRL_NOT_YET_VALID); | ||
179 | #endif | ||
180 | #ifdef X509_V_ERR_CRL_HAS_EXPIRED | ||
181 | ERROR(X509_V_ERR_CRL_HAS_EXPIRED); | ||
182 | #endif | ||
183 | #ifdef X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD | ||
184 | ERROR(X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD); | ||
185 | #endif | ||
186 | #ifdef X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD | ||
187 | ERROR(X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD); | ||
188 | #endif | ||
189 | #ifdef X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD | ||
190 | ERROR(X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD); | ||
191 | #endif | ||
192 | #ifdef X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD | ||
193 | ERROR(X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD); | ||
194 | #endif | ||
195 | #ifdef X509_V_ERR_OUT_OF_MEM | ||
196 | ERROR(X509_V_ERR_OUT_OF_MEM); | ||
197 | #endif | ||
198 | #ifdef X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT | ||
199 | ERROR(X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT); | ||
200 | #endif | ||
201 | #ifdef X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN | ||
202 | ERROR(X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN); | ||
203 | #endif | ||
204 | #ifdef X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY | ||
205 | ERROR(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY); | ||
206 | #endif | ||
207 | #ifdef X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE | ||
208 | ERROR(X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE); | ||
209 | #endif | ||
210 | #ifdef X509_V_ERR_CERT_CHAIN_TOO_LONG | ||
211 | ERROR(X509_V_ERR_CERT_CHAIN_TOO_LONG); | ||
212 | #endif | ||
213 | #ifdef X509_V_ERR_CERT_REVOKED | ||
214 | ERROR(X509_V_ERR_CERT_REVOKED); | ||
215 | #endif | ||
216 | #ifdef X509_V_ERR_INVALID_CA | ||
217 | ERROR(X509_V_ERR_INVALID_CA); | ||
218 | #endif | ||
219 | #ifdef X509_V_ERR_PATH_LENGTH_EXCEEDED | ||
220 | ERROR(X509_V_ERR_PATH_LENGTH_EXCEEDED); | ||
221 | #endif | ||
222 | #ifdef X509_V_ERR_INVALID_PURPOSE | ||
223 | ERROR(X509_V_ERR_INVALID_PURPOSE); | ||
224 | #endif | ||
225 | #ifdef X509_V_ERR_CERT_UNTRUSTED | ||
226 | ERROR(X509_V_ERR_CERT_UNTRUSTED); | ||
227 | #endif | ||
228 | #ifdef X509_V_ERR_CERT_REJECTED | ||
229 | ERROR(X509_V_ERR_CERT_REJECTED); | ||
230 | #endif | ||
231 | /* These are 'informational' when looking for issuer cert */ | ||
232 | #ifdef X509_V_ERR_SUBJECT_ISSUER_MISMATCH | ||
233 | ERROR(X509_V_ERR_SUBJECT_ISSUER_MISMATCH); | ||
234 | #endif | ||
235 | #ifdef X509_V_ERR_AKID_SKID_MISMATCH | ||
236 | ERROR(X509_V_ERR_AKID_SKID_MISMATCH); | ||
237 | #endif | ||
238 | #ifdef X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH | ||
239 | ERROR(X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH); | ||
240 | #endif | ||
241 | #ifdef X509_V_ERR_KEYUSAGE_NO_CERTSIGN | ||
242 | ERROR(X509_V_ERR_KEYUSAGE_NO_CERTSIGN); | ||
243 | #endif | ||
244 | |||
245 | #ifdef X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER | ||
246 | ERROR(X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER); | ||
247 | #endif | ||
248 | #ifdef X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION | ||
249 | ERROR(X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION); | ||
250 | #endif | ||
251 | #ifdef X509_V_ERR_KEYUSAGE_NO_CRL_SIGN | ||
252 | ERROR(X509_V_ERR_KEYUSAGE_NO_CRL_SIGN); | ||
253 | #endif | ||
254 | #ifdef X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION | ||
255 | ERROR(X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION); | ||
256 | #endif | ||
257 | #ifdef X509_V_ERR_INVALID_NON_CA | ||
258 | ERROR(X509_V_ERR_INVALID_NON_CA); | ||
259 | #endif | ||
260 | #ifdef X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED | ||
261 | ERROR(X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED); | ||
262 | #endif | ||
263 | #ifdef X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE | ||
264 | ERROR(X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE); | ||
265 | #endif | ||
266 | #ifdef X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED | ||
267 | ERROR(X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED); | ||
268 | #endif | ||
269 | |||
270 | #ifdef X509_V_ERR_INVALID_EXTENSION | ||
271 | ERROR(X509_V_ERR_INVALID_EXTENSION); | ||
272 | #endif | ||
273 | #ifdef X509_V_ERR_INVALID_POLICY_EXTENSION | ||
274 | ERROR(X509_V_ERR_INVALID_POLICY_EXTENSION); | ||
275 | #endif | ||
276 | #ifdef X509_V_ERR_NO_EXPLICIT_POLICY | ||
277 | ERROR(X509_V_ERR_NO_EXPLICIT_POLICY); | ||
278 | #endif | ||
279 | #ifdef X509_V_ERR_DIFFERENT_CRL_SCOPE | ||
280 | ERROR(X509_V_ERR_DIFFERENT_CRL_SCOPE); | ||
281 | #endif | ||
282 | #ifdef X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE | ||
283 | ERROR(X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE); | ||
284 | #endif | ||
285 | |||
286 | #ifdef X509_V_ERR_UNNESTED_RESOURCE | ||
287 | ERROR(X509_V_ERR_UNNESTED_RESOURCE); | ||
288 | #endif | ||
289 | |||
290 | #ifdef X509_V_ERR_PERMITTED_VIOLATION | ||
291 | ERROR(X509_V_ERR_PERMITTED_VIOLATION); | ||
292 | #endif | ||
293 | #ifdef X509_V_ERR_EXCLUDED_VIOLATION | ||
294 | ERROR(X509_V_ERR_EXCLUDED_VIOLATION); | ||
295 | #endif | ||
296 | #ifdef X509_V_ERR_SUBTREE_MINMAX | ||
297 | ERROR(X509_V_ERR_SUBTREE_MINMAX); | ||
298 | #endif | ||
299 | #ifdef X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE | ||
300 | ERROR(X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE); | ||
301 | #endif | ||
302 | #ifdef X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX | ||
303 | ERROR(X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX); | ||
304 | #endif | ||
305 | #ifdef X509_V_ERR_UNSUPPORTED_NAME_SYNTAX | ||
306 | ERROR(X509_V_ERR_UNSUPPORTED_NAME_SYNTAX); | ||
307 | #endif | ||
308 | #ifdef X509_V_ERR_CRL_PATH_VALIDATION_ERROR | ||
309 | ERROR(X509_V_ERR_CRL_PATH_VALIDATION_ERROR); | ||
310 | #endif | ||
311 | |||
312 | /* The application is not happy */ | ||
313 | #ifdef X509_V_ERR_APPLICATION_VERIFICATION | ||
314 | ERROR(X509_V_ERR_APPLICATION_VERIFICATION); | ||
315 | #endif | ||
316 | } | ||
317 | #undef ERROR | ||
318 | } | ||
319 | |||
320 | static void | ||
119 | _openssl_print_errors(void *conn, int type) | 321 | _openssl_print_errors(void *conn, int type) |
120 | { | 322 | { |
121 | char buf[1024]; | 323 | char buf[1024]; |
@@ -152,13 +354,57 @@ _openssl_name_verify(const char *name, const char *svrname) | |||
152 | EINA_SAFETY_ON_TRUE_RETURN_VAL(!s, EINA_FALSE); | 354 | EINA_SAFETY_ON_TRUE_RETURN_VAL(!s, EINA_FALSE); |
153 | /* same as above for the stored name */ | 355 | /* same as above for the stored name */ |
154 | EINA_SAFETY_ON_TRUE_RETURN_VAL(!strchr(s + 1, '.'), EINA_FALSE); | 356 | EINA_SAFETY_ON_TRUE_RETURN_VAL(!strchr(s + 1, '.'), EINA_FALSE); |
155 | EINA_SAFETY_ON_TRUE_RETURN_VAL(strcasecmp(s, name + 1), EINA_FALSE); | 357 | if (strcasecmp(s, name + 1)) |
358 | { | ||
359 | ERR("%s != %s", s, name + 1); | ||
360 | return EINA_FALSE; | ||
361 | } | ||
156 | } | 362 | } |
157 | else | 363 | else |
158 | EINA_SAFETY_ON_TRUE_RETURN_VAL(strcasecmp(name, svrname), EINA_FALSE); | 364 | if (strcasecmp(name, svrname)) |
365 | { | ||
366 | ERR("%s != %s", name, svrname); | ||
367 | return EINA_FALSE; | ||
368 | } | ||
159 | return EINA_TRUE; | 369 | return EINA_TRUE; |
160 | } | 370 | } |
161 | 371 | ||
372 | static void | ||
373 | _openssl_print_session(SSL *ssl) | ||
374 | { | ||
375 | /* print session info into DBG */ | ||
376 | SSL_SESSION *s; | ||
377 | STACK_OF(X509) *sk; | ||
378 | BIO *b; | ||
379 | char log[4096], *p; | ||
380 | int x; | ||
381 | |||
382 | if (!eina_log_domain_level_check(_ecore_con_log_dom, EINA_LOG_LEVEL_DBG)) return; | ||
383 | |||
384 | memset(log, 0, sizeof(log)); | ||
385 | b = BIO_new(BIO_s_mem()); | ||
386 | sk = SSL_get_peer_cert_chain(ssl); | ||
387 | if (sk) | ||
388 | { | ||
389 | DBG("CERTIFICATES:"); | ||
390 | for (x = 0; x < sk_X509_num(sk); x++) | ||
391 | { | ||
392 | p = X509_NAME_oneline(X509_get_subject_name(sk_X509_value(sk, x)), log, sizeof(log)); | ||
393 | DBG("%2d s:%s", x, p); | ||
394 | p = X509_NAME_oneline(X509_get_issuer_name(sk_X509_value(sk, x)), log, sizeof(log)); | ||
395 | DBG(" i:%s", p); | ||
396 | PEM_write_X509(stderr, sk_X509_value(sk, x)); | ||
397 | } | ||
398 | } | ||
399 | s = SSL_get_session(ssl); | ||
400 | SSL_SESSION_print(b, s); | ||
401 | fprintf(stderr, "\n"); | ||
402 | while (BIO_read(b, log, sizeof(log)) > 0) | ||
403 | fprintf(stderr, "%s", log); | ||
404 | |||
405 | BIO_free(b); | ||
406 | } | ||
407 | |||
162 | #endif | 408 | #endif |
163 | 409 | ||
164 | #define SSL_ERROR_CHECK_GOTO_ERROR(X) \ | 410 | #define SSL_ERROR_CHECK_GOTO_ERROR(X) \ |
@@ -356,6 +602,51 @@ ecore_con_ssl_server_verify_basic(Ecore_Con_Server *svr) | |||
356 | } | 602 | } |
357 | 603 | ||
358 | /** | 604 | /** |
605 | * @brief Set the hostname to verify against in certificate verification | ||
606 | * | ||
607 | * Sometimes the certificate hostname will not match the hostname that you are | ||
608 | * connecting to, and will instead match a different name. An example of this is | ||
609 | * that if you connect to talk.google.com to use Google Talk, you receive Google's | ||
610 | * certificate for gmail.com. This certificate should be trusted, and so you must call | ||
611 | * this function with "gmail.com" as @p name. | ||
612 | * See RFC2818 for more details. | ||
613 | * @param svr The server object | ||
614 | * @param name The hostname to verify against | ||
615 | * @since 1.2 | ||
616 | */ | ||
617 | EAPI void | ||
618 | ecore_con_ssl_server_verify_name_set(Ecore_Con_Server *svr, const char *name) | ||
619 | { | ||
620 | if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) | ||
621 | { | ||
622 | ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, __func__); | ||
623 | return; | ||
624 | } | ||
625 | eina_stringshare_replace(&svr->verify_name, name); | ||
626 | } | ||
627 | |||
628 | /** | ||
629 | * @brief Get the hostname to verify against in certificate verification | ||
630 | * | ||
631 | * This function returns the name which will be used to validate the SSL certificate | ||
632 | * common name (CN) or alt name (subjectAltName). It will default to the @p name | ||
633 | * param in ecore_con_server_connect(), but can be changed with ecore_con_ssl_server_verify_name_set(). | ||
634 | * @param svr The server object | ||
635 | * @return The hostname which will be used | ||
636 | * @since 1.2 | ||
637 | */ | ||
638 | EAPI const char * | ||
639 | ecore_con_ssl_server_verify_name_get(Ecore_Con_Server *svr) | ||
640 | { | ||
641 | if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) | ||
642 | { | ||
643 | ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, __func__); | ||
644 | return NULL; | ||
645 | } | ||
646 | return svr->verify_name ?: svr->name; | ||
647 | } | ||
648 | |||
649 | /** | ||
359 | * @brief Add an ssl certificate for use in ecore_con functions. | 650 | * @brief Add an ssl certificate for use in ecore_con functions. |
360 | * | 651 | * |
361 | * Use this function to add a SSL PEM certificate. | 652 | * Use this function to add a SSL PEM certificate. |
@@ -375,6 +666,14 @@ ecore_con_ssl_server_cert_add(Ecore_Con_Server *svr, | |||
375 | return EINA_FALSE; | 666 | return EINA_FALSE; |
376 | } | 667 | } |
377 | 668 | ||
669 | if (!svr->ssl_prepared) | ||
670 | { | ||
671 | svr->use_cert = EINA_TRUE; | ||
672 | svr->type |= ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT; | ||
673 | if (ecore_con_ssl_server_prepare(svr, svr->type & ECORE_CON_SSL)) | ||
674 | return EINA_FALSE; | ||
675 | } | ||
676 | |||
378 | return SSL_SUFFIX(_ecore_con_ssl_server_cert_add) (svr, cert); | 677 | return SSL_SUFFIX(_ecore_con_ssl_server_cert_add) (svr, cert); |
379 | } | 678 | } |
380 | 679 | ||
@@ -386,6 +685,7 @@ ecore_con_ssl_server_cert_add(Ecore_Con_Server *svr, | |||
386 | * If there is an error loading the CAs, an error will automatically be logged. | 685 | * If there is an error loading the CAs, an error will automatically be logged. |
387 | * @param ca_file The path to the CA file. | 686 | * @param ca_file The path to the CA file. |
388 | * @return EINA_FALSE if the file cannot be loaded, otherwise EINA_TRUE. | 687 | * @return EINA_FALSE if the file cannot be loaded, otherwise EINA_TRUE. |
688 | * @note since 1.2, this function can load directores | ||
389 | */ | 689 | */ |
390 | 690 | ||
391 | EAPI Eina_Bool | 691 | EAPI Eina_Bool |
@@ -398,6 +698,14 @@ ecore_con_ssl_server_cafile_add(Ecore_Con_Server *svr, | |||
398 | return EINA_FALSE; | 698 | return EINA_FALSE; |
399 | } | 699 | } |
400 | 700 | ||
701 | if (!svr->ssl_prepared) | ||
702 | { | ||
703 | svr->use_cert = EINA_TRUE; | ||
704 | svr->type |= ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT; | ||
705 | if (ecore_con_ssl_server_prepare(svr, svr->type & ECORE_CON_SSL)) | ||
706 | return EINA_FALSE; | ||
707 | } | ||
708 | |||
401 | return SSL_SUFFIX(_ecore_con_ssl_server_cafile_add) (svr, ca_file); | 709 | return SSL_SUFFIX(_ecore_con_ssl_server_cafile_add) (svr, ca_file); |
402 | } | 710 | } |
403 | 711 | ||
@@ -422,6 +730,14 @@ ecore_con_ssl_server_privkey_add(Ecore_Con_Server *svr, | |||
422 | return EINA_FALSE; | 730 | return EINA_FALSE; |
423 | } | 731 | } |
424 | 732 | ||
733 | if (!svr->ssl_prepared) | ||
734 | { | ||
735 | svr->use_cert = EINA_TRUE; | ||
736 | svr->type |= ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT; | ||
737 | if (ecore_con_ssl_server_prepare(svr, svr->type & ECORE_CON_SSL)) | ||
738 | return EINA_FALSE; | ||
739 | } | ||
740 | |||
425 | return SSL_SUFFIX(_ecore_con_ssl_server_privkey_add) (svr, key_file); | 741 | return SSL_SUFFIX(_ecore_con_ssl_server_privkey_add) (svr, key_file); |
426 | } | 742 | } |
427 | 743 | ||
@@ -446,6 +762,14 @@ ecore_con_ssl_server_crl_add(Ecore_Con_Server *svr, | |||
446 | return EINA_FALSE; | 762 | return EINA_FALSE; |
447 | } | 763 | } |
448 | 764 | ||
765 | if (!svr->ssl_prepared) | ||
766 | { | ||
767 | svr->use_cert = EINA_TRUE; | ||
768 | svr->type |= ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT; | ||
769 | if (ecore_con_ssl_server_prepare(svr, svr->type & ECORE_CON_SSL)) | ||
770 | return EINA_FALSE; | ||
771 | } | ||
772 | |||
449 | return SSL_SUFFIX(_ecore_con_ssl_server_crl_add) (svr, crl_file); | 773 | return SSL_SUFFIX(_ecore_con_ssl_server_crl_add) (svr, crl_file); |
450 | } | 774 | } |
451 | 775 | ||
@@ -480,7 +804,8 @@ ecore_con_ssl_server_upgrade(Ecore_Con_Server *svr, Ecore_Con_Type ssl_type) | |||
480 | if (ecore_con_ssl_server_prepare(svr, ssl_type)) | 804 | if (ecore_con_ssl_server_prepare(svr, ssl_type)) |
481 | return EINA_FALSE; | 805 | return EINA_FALSE; |
482 | } | 806 | } |
483 | svr->type |= ssl_type; | 807 | if (!svr->use_cert) |
808 | svr->type |= ssl_type; | ||
484 | svr->upgrade = EINA_TRUE; | 809 | svr->upgrade = EINA_TRUE; |
485 | svr->handshaking = EINA_TRUE; | 810 | svr->handshaking = EINA_TRUE; |
486 | svr->ssl_state = ECORE_CON_SSL_STATE_INIT; | 811 | svr->ssl_state = ECORE_CON_SSL_STATE_INIT; |
@@ -494,7 +819,7 @@ ecore_con_ssl_server_upgrade(Ecore_Con_Server *svr, Ecore_Con_Type ssl_type) | |||
494 | * Once the upgrade has been completed, an ECORE_CON_EVENT_CLIENT_UPGRADE event will be emitted. | 819 | * Once the upgrade has been completed, an ECORE_CON_EVENT_CLIENT_UPGRADE event will be emitted. |
495 | * The connection should be treated as disconnected until the next event. | 820 | * The connection should be treated as disconnected until the next event. |
496 | * @param cl The client object | 821 | * @param cl The client object |
497 | * @param compl_type The SSL connection type (ONLY). | 822 | * @param ssl_type The SSL connection type (ONLY). |
498 | * @return EINA_FALSE if the connection cannot be upgraded, otherwise EINA_TRUE. | 823 | * @return EINA_FALSE if the connection cannot be upgraded, otherwise EINA_TRUE. |
499 | * @warning Setting a wrong value for @p compl_type WILL mess up your program. | 824 | * @warning Setting a wrong value for @p compl_type WILL mess up your program. |
500 | * @since 1.1 | 825 | * @since 1.1 |
@@ -517,7 +842,8 @@ ecore_con_ssl_client_upgrade(Ecore_Con_Client *cl, Ecore_Con_Type ssl_type) | |||
517 | if (ecore_con_ssl_server_prepare(cl->host_server, ssl_type)) | 842 | if (ecore_con_ssl_server_prepare(cl->host_server, ssl_type)) |
518 | return EINA_FALSE; | 843 | return EINA_FALSE; |
519 | } | 844 | } |
520 | cl->host_server->type |= ssl_type; | 845 | if (!cl->host_server->use_cert) |
846 | cl->host_server->type |= ssl_type; | ||
521 | cl->upgrade = EINA_TRUE; | 847 | cl->upgrade = EINA_TRUE; |
522 | cl->host_server->upgrade = EINA_TRUE; | 848 | cl->host_server->upgrade = EINA_TRUE; |
523 | cl->handshaking = EINA_TRUE; | 849 | cl->handshaking = EINA_TRUE; |
@@ -546,8 +872,11 @@ _ecore_con_ssl_init_gnutls(void) | |||
546 | return ECORE_CON_SSL_ERROR_INIT_FAILED; | 872 | return ECORE_CON_SSL_ERROR_INIT_FAILED; |
547 | 873 | ||
548 | #ifdef ISCOMFITOR | 874 | #ifdef ISCOMFITOR |
549 | gnutls_global_set_log_level(9); | 875 | if (eina_log_domain_level_check(_ecore_con_log_dom, EINA_LOG_LEVEL_DBG)) |
550 | gnutls_global_set_log_function(_gnutls_log_func); | 876 | { |
877 | gnutls_global_set_log_level(9); | ||
878 | gnutls_global_set_log_function(_gnutls_log_func); | ||
879 | } | ||
551 | #endif | 880 | #endif |
552 | return ECORE_CON_SSL_ERROR_NONE; | 881 | return ECORE_CON_SSL_ERROR_NONE; |
553 | } | 882 | } |
@@ -728,10 +1057,12 @@ _ecore_con_ssl_server_init_gnutls(Ecore_Con_Server *svr) | |||
728 | SSL_ERROR_CHECK_GOTO_ERROR(!(cert_list = gnutls_certificate_get_peers(svr->session, &cert_list_size))); | 1057 | SSL_ERROR_CHECK_GOTO_ERROR(!(cert_list = gnutls_certificate_get_peers(svr->session, &cert_list_size))); |
729 | SSL_ERROR_CHECK_GOTO_ERROR(!cert_list_size); | 1058 | SSL_ERROR_CHECK_GOTO_ERROR(!cert_list_size); |
730 | 1059 | ||
1060 | _gnutls_print_session(cert_list, cert_list_size); | ||
1061 | |||
731 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_init(&cert)); | 1062 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_init(&cert)); |
732 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER)); | 1063 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER)); |
733 | 1064 | ||
734 | SSL_ERROR_CHECK_GOTO_ERROR(!gnutls_x509_crt_check_hostname(cert, svr->name)); | 1065 | SSL_ERROR_CHECK_GOTO_ERROR(!gnutls_x509_crt_check_hostname(cert, svr->verify_name ?: svr->name)); |
735 | gnutls_x509_crt_deinit(cert); | 1066 | gnutls_x509_crt_deinit(cert); |
736 | DBG("SSL certificate verification succeeded!"); | 1067 | DBG("SSL certificate verification succeeded!"); |
737 | return ECORE_CON_SSL_ERROR_NONE; | 1068 | return ECORE_CON_SSL_ERROR_NONE; |
@@ -755,10 +1086,32 @@ static Eina_Bool | |||
755 | _ecore_con_ssl_server_cafile_add_gnutls(Ecore_Con_Server *svr, | 1086 | _ecore_con_ssl_server_cafile_add_gnutls(Ecore_Con_Server *svr, |
756 | const char *ca_file) | 1087 | const char *ca_file) |
757 | { | 1088 | { |
758 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_certificate_set_x509_trust_file(svr->cert, ca_file, | 1089 | struct stat st; |
759 | GNUTLS_X509_FMT_PEM) < 1); | 1090 | Eina_Iterator *it; |
1091 | const char *file; | ||
1092 | Eina_Bool error = EINA_FALSE; | ||
760 | 1093 | ||
761 | return EINA_TRUE; | 1094 | if (stat(ca_file, &st)) return EINA_FALSE; |
1095 | if (S_ISDIR(st.st_mode)) | ||
1096 | { | ||
1097 | it = eina_file_ls(ca_file); | ||
1098 | SSL_ERROR_CHECK_GOTO_ERROR(!it); | ||
1099 | EINA_ITERATOR_FOREACH(it, file) | ||
1100 | { | ||
1101 | if (!error) | ||
1102 | { | ||
1103 | if (gnutls_certificate_set_x509_trust_file(svr->cert, file, GNUTLS_X509_FMT_PEM) < 1) | ||
1104 | error++; | ||
1105 | } | ||
1106 | eina_stringshare_del(file); | ||
1107 | } | ||
1108 | eina_iterator_free(it); | ||
1109 | } | ||
1110 | else | ||
1111 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_certificate_set_x509_trust_file(svr->cert, ca_file, | ||
1112 | GNUTLS_X509_FMT_PEM) < 1); | ||
1113 | |||
1114 | return !error; | ||
762 | error: | 1115 | error: |
763 | ERR("Could not load CA file!"); | 1116 | ERR("Could not load CA file!"); |
764 | return EINA_FALSE; | 1117 | return EINA_FALSE; |
@@ -1026,6 +1379,7 @@ _ecore_con_ssl_client_init_gnutls(Ecore_Con_Client *cl) | |||
1026 | SSL_ERROR_CHECK_GOTO_ERROR(!(cert_list = gnutls_certificate_get_peers(cl->session, &cert_list_size))); | 1379 | SSL_ERROR_CHECK_GOTO_ERROR(!(cert_list = gnutls_certificate_get_peers(cl->session, &cert_list_size))); |
1027 | SSL_ERROR_CHECK_GOTO_ERROR(!cert_list_size); | 1380 | SSL_ERROR_CHECK_GOTO_ERROR(!cert_list_size); |
1028 | 1381 | ||
1382 | _gnutls_print_session(cert_list, cert_list_size); | ||
1029 | /* | 1383 | /* |
1030 | gnutls_x509_crt_t cert = NULL; | 1384 | gnutls_x509_crt_t cert = NULL; |
1031 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_init(&cert)); | 1385 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_init(&cert)); |
@@ -1282,23 +1636,7 @@ _ecore_con_ssl_server_init_openssl(Ecore_Con_Server *svr) | |||
1282 | break; | 1636 | break; |
1283 | } | 1637 | } |
1284 | 1638 | ||
1285 | #ifdef ISCOMFITOR | 1639 | _openssl_print_session(svr->ssl); |
1286 | { | ||
1287 | /* print session info into DBG */ | ||
1288 | SSL_SESSION *s; | ||
1289 | BIO *b; | ||
1290 | char log[4096]; | ||
1291 | |||
1292 | memset(log, 0, sizeof(log)); | ||
1293 | s = SSL_get_session(svr->ssl); | ||
1294 | b = BIO_new(BIO_s_mem()); | ||
1295 | SSL_SESSION_print(b, s); | ||
1296 | while (BIO_read(b, log, sizeof(log)) > 0) | ||
1297 | DBG("%s", log); | ||
1298 | |||
1299 | BIO_free(b); | ||
1300 | } | ||
1301 | #endif | ||
1302 | if ((!svr->verify) && (!svr->verify_basic)) | 1640 | if ((!svr->verify) && (!svr->verify_basic)) |
1303 | /* not verifying certificates, so we're done! */ | 1641 | /* not verifying certificates, so we're done! */ |
1304 | return ECORE_CON_SSL_ERROR_NONE; | 1642 | return ECORE_CON_SSL_ERROR_NONE; |
@@ -1310,17 +1648,29 @@ _ecore_con_ssl_server_init_openssl(Ecore_Con_Server *svr) | |||
1310 | cert = SSL_get_peer_certificate(svr->ssl); | 1648 | cert = SSL_get_peer_certificate(svr->ssl); |
1311 | if (cert) | 1649 | if (cert) |
1312 | { | 1650 | { |
1313 | char buf[256] = {0}; | 1651 | char *c; |
1652 | int clen; | ||
1653 | int name = 0; | ||
1654 | |||
1314 | if (svr->verify) | 1655 | if (svr->verify) |
1315 | SSL_ERROR_CHECK_GOTO_ERROR(SSL_get_verify_result(svr->ssl)); | ||
1316 | X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_subject_alt_name, buf, sizeof(buf)); | ||
1317 | if (buf[0]) | ||
1318 | SSL_ERROR_CHECK_GOTO_ERROR(!_openssl_name_verify(buf, svr->name)); | ||
1319 | else | ||
1320 | { | 1656 | { |
1321 | X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, buf, sizeof(buf)); | 1657 | int err; |
1322 | SSL_ERROR_CHECK_GOTO_ERROR(!_openssl_name_verify(buf, svr->name)); | 1658 | |
1659 | err = SSL_get_verify_result(svr->ssl); | ||
1660 | _openssl_print_verify_error(err); | ||
1661 | SSL_ERROR_CHECK_GOTO_ERROR(err); | ||
1323 | } | 1662 | } |
1663 | clen = X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_subject_alt_name, NULL, 0); | ||
1664 | if (clen > 0) | ||
1665 | name = NID_subject_alt_name; | ||
1666 | else | ||
1667 | clen = X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, NULL, 0); | ||
1668 | SSL_ERROR_CHECK_GOTO_ERROR(clen < 1); | ||
1669 | if (!name) name = NID_commonName; | ||
1670 | c = alloca(++clen); | ||
1671 | X509_NAME_get_text_by_NID(X509_get_subject_name(cert), name, c, clen); | ||
1672 | INF("CERT NAME: %s\n", c); | ||
1673 | SSL_ERROR_CHECK_GOTO_ERROR(!_openssl_name_verify(c, svr->verify_name ?: svr->name)); | ||
1324 | } | 1674 | } |
1325 | } | 1675 | } |
1326 | 1676 | ||
@@ -1338,7 +1688,13 @@ static Eina_Bool | |||
1338 | _ecore_con_ssl_server_cafile_add_openssl(Ecore_Con_Server *svr, | 1688 | _ecore_con_ssl_server_cafile_add_openssl(Ecore_Con_Server *svr, |
1339 | const char *ca_file) | 1689 | const char *ca_file) |
1340 | { | 1690 | { |
1341 | SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_load_verify_locations(svr->ssl_ctx, ca_file, NULL)); | 1691 | struct stat st; |
1692 | |||
1693 | if (stat(ca_file, &st)) return EINA_FALSE; | ||
1694 | if (S_ISDIR(st.st_mode)) | ||
1695 | SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_load_verify_locations(svr->ssl_ctx, NULL, ca_file)); | ||
1696 | else | ||
1697 | SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_load_verify_locations(svr->ssl_ctx, ca_file, NULL)); | ||
1342 | return EINA_TRUE; | 1698 | return EINA_TRUE; |
1343 | 1699 | ||
1344 | error: | 1700 | error: |
@@ -1543,31 +1899,20 @@ _ecore_con_ssl_client_init_openssl(Ecore_Con_Client *cl) | |||
1543 | break; | 1899 | break; |
1544 | } | 1900 | } |
1545 | 1901 | ||
1546 | #ifdef ISCOMFITOR | 1902 | _openssl_print_session(cl->ssl); |
1547 | { | ||
1548 | /* print session info into DBG */ | ||
1549 | SSL_SESSION *s; | ||
1550 | BIO *b; | ||
1551 | char log[4096]; | ||
1552 | |||
1553 | memset(log, 0, sizeof(log)); | ||
1554 | s = SSL_get_session(cl->ssl); | ||
1555 | b = BIO_new(BIO_s_mem()); | ||
1556 | SSL_SESSION_print(b, s); | ||
1557 | while (BIO_read(b, log, sizeof(log)) > 0) | ||
1558 | DBG("%s", log); | ||
1559 | |||
1560 | BIO_free(b); | ||
1561 | } | ||
1562 | #endif | ||
1563 | |||
1564 | if (!cl->host_server->verify) | 1903 | if (!cl->host_server->verify) |
1565 | /* not verifying certificates, so we're done! */ | 1904 | /* not verifying certificates, so we're done! */ |
1566 | return ECORE_CON_SSL_ERROR_NONE; | 1905 | return ECORE_CON_SSL_ERROR_NONE; |
1567 | SSL_set_verify(cl->ssl, SSL_VERIFY_PEER, NULL); | 1906 | SSL_set_verify(cl->ssl, SSL_VERIFY_PEER, NULL); |
1568 | /* use CRL/CA lists to verify */ | 1907 | /* use CRL/CA lists to verify */ |
1569 | if (SSL_get_peer_certificate(cl->ssl)) | 1908 | if (SSL_get_peer_certificate(cl->ssl)) |
1570 | SSL_ERROR_CHECK_GOTO_ERROR(SSL_get_verify_result(cl->ssl)); | 1909 | { |
1910 | int err; | ||
1911 | |||
1912 | err = SSL_get_verify_result(cl->ssl); | ||
1913 | _openssl_print_verify_error(err); | ||
1914 | SSL_ERROR_CHECK_GOTO_ERROR(err); | ||
1915 | } | ||
1571 | 1916 | ||
1572 | return ECORE_CON_SSL_ERROR_NONE; | 1917 | return ECORE_CON_SSL_ERROR_NONE; |
1573 | 1918 | ||
@@ -1679,12 +2024,6 @@ _ecore_con_ssl_server_prepare_none(Ecore_Con_Server *svr __UNUSED__, | |||
1679 | } | 2024 | } |
1680 | 2025 | ||
1681 | static Ecore_Con_Ssl_Error | 2026 | static Ecore_Con_Ssl_Error |
1682 | _ecore_con_ssl_server_upgrade_none(Ecore_Con_Server *svr __UNUSED__) | ||
1683 | { | ||
1684 | return ECORE_CON_SSL_ERROR_NOT_SUPPORTED; | ||
1685 | } | ||
1686 | |||
1687 | static Ecore_Con_Ssl_Error | ||
1688 | _ecore_con_ssl_server_init_none(Ecore_Con_Server *svr __UNUSED__) | 2027 | _ecore_con_ssl_server_init_none(Ecore_Con_Server *svr __UNUSED__) |
1689 | { | 2028 | { |
1690 | return ECORE_CON_SSL_ERROR_NOT_SUPPORTED; | 2029 | return ECORE_CON_SSL_ERROR_NOT_SUPPORTED; |
@@ -1741,12 +2080,6 @@ _ecore_con_ssl_server_write_none(Ecore_Con_Server *svr __UNUSED__, | |||
1741 | } | 2080 | } |
1742 | 2081 | ||
1743 | static Ecore_Con_Ssl_Error | 2082 | static Ecore_Con_Ssl_Error |
1744 | _ecore_con_ssl_client_upgrade_none(Ecore_Con_Client *cl __UNUSED__) | ||
1745 | { | ||
1746 | return ECORE_CON_SSL_ERROR_NOT_SUPPORTED; | ||
1747 | } | ||
1748 | |||
1749 | static Ecore_Con_Ssl_Error | ||
1750 | _ecore_con_ssl_client_init_none(Ecore_Con_Client *cl __UNUSED__) | 2083 | _ecore_con_ssl_client_init_none(Ecore_Con_Client *cl __UNUSED__) |
1751 | { | 2084 | { |
1752 | return ECORE_CON_SSL_ERROR_NOT_SUPPORTED; | 2085 | return ECORE_CON_SSL_ERROR_NOT_SUPPORTED; |