diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c | 1777 |
1 files changed, 1777 insertions, 0 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 new file mode 100644 index 0000000..c352e94 --- /dev/null +++ b/libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c | |||
@@ -0,0 +1,1777 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include <config.h> | ||
3 | #endif | ||
4 | |||
5 | #if USE_GNUTLS | ||
6 | # include <gnutls/gnutls.h> | ||
7 | # include <gnutls/x509.h> | ||
8 | # include <gcrypt.h> | ||
9 | #elif USE_OPENSSL | ||
10 | # include <openssl/ssl.h> | ||
11 | # include <openssl/err.h> | ||
12 | # include <openssl/dh.h> | ||
13 | #endif | ||
14 | |||
15 | #ifdef HAVE_WS2TCPIP_H | ||
16 | # include <ws2tcpip.h> | ||
17 | #endif | ||
18 | |||
19 | #include "Ecore.h" | ||
20 | #include "ecore_con_private.h" | ||
21 | |||
22 | EAPI int ECORE_CON_EVENT_CLIENT_UPGRADE = 0; | ||
23 | EAPI int ECORE_CON_EVENT_SERVER_UPGRADE = 0; | ||
24 | |||
25 | static int _init_con_ssl_init_count = 0; | ||
26 | |||
27 | #ifdef USE_GNUTLS | ||
28 | # ifdef EINA_HAVE_THREADS | ||
29 | GCRY_THREAD_OPTION_PTHREAD_IMPL; | ||
30 | # endif | ||
31 | |||
32 | static int _client_connected = 0; | ||
33 | |||
34 | # define SSL_SUFFIX(ssl_func) ssl_func ## _gnutls | ||
35 | # define _ECORE_CON_SSL_AVAILABLE 1 | ||
36 | |||
37 | #elif USE_OPENSSL | ||
38 | |||
39 | # define SSL_SUFFIX(ssl_func) ssl_func ## _openssl | ||
40 | # define _ECORE_CON_SSL_AVAILABLE 2 | ||
41 | |||
42 | #else | ||
43 | # define SSL_SUFFIX(ssl_func) ssl_func ## _none | ||
44 | # define _ECORE_CON_SSL_AVAILABLE 0 | ||
45 | |||
46 | #endif | ||
47 | |||
48 | #if USE_GNUTLS | ||
49 | static void | ||
50 | _gnutls_print_errors(void *conn, int type, int ret) | ||
51 | { | ||
52 | char buf[1024]; | ||
53 | |||
54 | if (!ret) return; | ||
55 | |||
56 | snprintf(buf, sizeof(buf), "GNUTLS error: %s - %s", gnutls_strerror_name(ret), gnutls_strerror(ret)); | ||
57 | if (type == ECORE_CON_EVENT_CLIENT_ERROR) | ||
58 | ecore_con_event_client_error(conn, buf); | ||
59 | else | ||
60 | ecore_con_event_server_error(conn, buf); | ||
61 | } | ||
62 | |||
63 | #ifdef ISCOMFITOR | ||
64 | static void | ||
65 | _gnutls_log_func(int level, | ||
66 | const char *str) | ||
67 | { | ||
68 | DBG("|<%d>| %s", level, str); | ||
69 | } | ||
70 | #endif | ||
71 | |||
72 | static const char * | ||
73 | SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_description_t status) | ||
74 | { | ||
75 | switch (status) | ||
76 | { | ||
77 | case GNUTLS_HANDSHAKE_HELLO_REQUEST: | ||
78 | return "Hello request"; | ||
79 | |||
80 | case GNUTLS_HANDSHAKE_CLIENT_HELLO: | ||
81 | return "Client hello"; | ||
82 | |||
83 | case GNUTLS_HANDSHAKE_SERVER_HELLO: | ||
84 | return "Server hello"; | ||
85 | |||
86 | case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET: | ||
87 | return "New session ticket"; | ||
88 | |||
89 | case GNUTLS_HANDSHAKE_CERTIFICATE_PKT: | ||
90 | return "Certificate packet"; | ||
91 | |||
92 | case GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE: | ||
93 | return "Server key exchange"; | ||
94 | |||
95 | case GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST: | ||
96 | return "Certificate request"; | ||
97 | |||
98 | case GNUTLS_HANDSHAKE_SERVER_HELLO_DONE: | ||
99 | return "Server hello done"; | ||
100 | |||
101 | case GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY: | ||
102 | return "Certificate verify"; | ||
103 | |||
104 | case GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE: | ||
105 | return "Client key exchange"; | ||
106 | |||
107 | case GNUTLS_HANDSHAKE_FINISHED: | ||
108 | return "Finished"; | ||
109 | |||
110 | case GNUTLS_HANDSHAKE_SUPPLEMENTAL: | ||
111 | return "Supplemental"; | ||
112 | } | ||
113 | return NULL; | ||
114 | } | ||
115 | |||
116 | #elif USE_OPENSSL | ||
117 | |||
118 | static void | ||
119 | _openssl_print_errors(void *conn, int type) | ||
120 | { | ||
121 | char buf[1024]; | ||
122 | do | ||
123 | { | ||
124 | unsigned long err; | ||
125 | |||
126 | err = ERR_get_error(); | ||
127 | if (!err) break; | ||
128 | snprintf(buf, sizeof(buf), "OpenSSL error: %s", ERR_reason_error_string(err)); | ||
129 | if (type == ECORE_CON_EVENT_CLIENT_ERROR) | ||
130 | ecore_con_event_client_error(conn, buf); | ||
131 | else | ||
132 | ecore_con_event_server_error(conn, buf); | ||
133 | |||
134 | } while (1); | ||
135 | } | ||
136 | |||
137 | static Eina_Bool | ||
138 | _openssl_name_verify(const char *name, const char *svrname) | ||
139 | { | ||
140 | if (name[0] == '*') | ||
141 | { | ||
142 | /* we allow *.domain.TLD with a wildcard, but nothing else */ | ||
143 | const char *p, *s; | ||
144 | |||
145 | EINA_SAFETY_ON_TRUE_RETURN_VAL((name[1] != '.') || (!name[2]), EINA_FALSE); | ||
146 | p = strchr(name + 1, '*'); | ||
147 | EINA_SAFETY_ON_TRUE_RETURN_VAL(!!p, EINA_FALSE); | ||
148 | /* verify that we have a domain of at least *.X.TLD and not *.TLD */ | ||
149 | p = strchr(name + 2, '.'); | ||
150 | EINA_SAFETY_ON_TRUE_RETURN_VAL(!p, EINA_FALSE); | ||
151 | s = strchr(svrname, '.'); | ||
152 | EINA_SAFETY_ON_TRUE_RETURN_VAL(!s, EINA_FALSE); | ||
153 | /* same as above for the stored name */ | ||
154 | EINA_SAFETY_ON_TRUE_RETURN_VAL(!strchr(s + 1, '.'), EINA_FALSE); | ||
155 | EINA_SAFETY_ON_TRUE_RETURN_VAL(strcasecmp(s, name + 1), EINA_FALSE); | ||
156 | } | ||
157 | else | ||
158 | EINA_SAFETY_ON_TRUE_RETURN_VAL(strcasecmp(name, svrname), EINA_FALSE); | ||
159 | return EINA_TRUE; | ||
160 | } | ||
161 | |||
162 | #endif | ||
163 | |||
164 | #define SSL_ERROR_CHECK_GOTO_ERROR(X) \ | ||
165 | do \ | ||
166 | { \ | ||
167 | if ((X)) \ | ||
168 | { \ | ||
169 | ERR("Error at %s:%s:%d!", __FILE__, __PRETTY_FUNCTION__, __LINE__); \ | ||
170 | goto error; \ | ||
171 | } \ | ||
172 | } \ | ||
173 | while (0) | ||
174 | |||
175 | static Ecore_Con_Ssl_Error | ||
176 | SSL_SUFFIX(_ecore_con_ssl_init) (void); | ||
177 | static Ecore_Con_Ssl_Error | ||
178 | SSL_SUFFIX(_ecore_con_ssl_shutdown) (void); | ||
179 | |||
180 | static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_cafile_add) (Ecore_Con_Server * svr, const char *ca_file); | ||
181 | static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_crl_add) (Ecore_Con_Server * svr, const char *crl_file); | ||
182 | static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_cert_add) (Ecore_Con_Server * svr, const char *cert); | ||
183 | static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_privkey_add) (Ecore_Con_Server * svr, const char *key_file); | ||
184 | |||
185 | static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_server_prepare) (Ecore_Con_Server * svr, int ssl_type); | ||
186 | static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_server_init) (Ecore_Con_Server * svr); | ||
187 | static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_server_shutdown) (Ecore_Con_Server *svr); | ||
188 | static int SSL_SUFFIX(_ecore_con_ssl_server_read) (Ecore_Con_Server *svr, unsigned char *buf, int size); | ||
189 | static int SSL_SUFFIX(_ecore_con_ssl_server_write) (Ecore_Con_Server *svr, const unsigned char *buf, int size); | ||
190 | |||
191 | static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_client_init) (Ecore_Con_Client * cl); | ||
192 | static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_client_shutdown) (Ecore_Con_Client *cl); | ||
193 | static int SSL_SUFFIX(_ecore_con_ssl_client_read) (Ecore_Con_Client * cl, | ||
194 | unsigned char *buf, int size); | ||
195 | static int SSL_SUFFIX(_ecore_con_ssl_client_write) (Ecore_Con_Client * cl, | ||
196 | const unsigned char *buf, int size); | ||
197 | |||
198 | /* | ||
199 | * General SSL API | ||
200 | */ | ||
201 | |||
202 | Ecore_Con_Ssl_Error | ||
203 | ecore_con_ssl_init(void) | ||
204 | { | ||
205 | if (!_init_con_ssl_init_count++) | ||
206 | { | ||
207 | SSL_SUFFIX(_ecore_con_ssl_init) (); | ||
208 | #if _ECORE_CON_SSL_AVAILABLE != 0 | ||
209 | ECORE_CON_EVENT_CLIENT_UPGRADE = ecore_event_type_new(); | ||
210 | ECORE_CON_EVENT_SERVER_UPGRADE = ecore_event_type_new(); | ||
211 | #endif | ||
212 | } | ||
213 | |||
214 | return _init_con_ssl_init_count; | ||
215 | } | ||
216 | |||
217 | Ecore_Con_Ssl_Error | ||
218 | ecore_con_ssl_shutdown(void) | ||
219 | { | ||
220 | if (!--_init_con_ssl_init_count) | ||
221 | SSL_SUFFIX(_ecore_con_ssl_shutdown) (); | ||
222 | |||
223 | return _init_con_ssl_init_count; | ||
224 | } | ||
225 | |||
226 | Ecore_Con_Ssl_Error | ||
227 | ecore_con_ssl_server_prepare(Ecore_Con_Server *svr, | ||
228 | int ssl_type) | ||
229 | { | ||
230 | if (!ssl_type) | ||
231 | return ECORE_CON_SSL_ERROR_NONE; | ||
232 | return SSL_SUFFIX(_ecore_con_ssl_server_prepare) (svr, ssl_type); | ||
233 | } | ||
234 | |||
235 | Ecore_Con_Ssl_Error | ||
236 | ecore_con_ssl_server_init(Ecore_Con_Server *svr) | ||
237 | { | ||
238 | if (!(svr->type & ECORE_CON_SSL)) | ||
239 | return ECORE_CON_SSL_ERROR_NONE; | ||
240 | return SSL_SUFFIX(_ecore_con_ssl_server_init) (svr); | ||
241 | } | ||
242 | |||
243 | Ecore_Con_Ssl_Error | ||
244 | ecore_con_ssl_server_shutdown(Ecore_Con_Server *svr) | ||
245 | { | ||
246 | if (!(svr->type & ECORE_CON_SSL)) | ||
247 | return ECORE_CON_SSL_ERROR_NONE; | ||
248 | return SSL_SUFFIX(_ecore_con_ssl_server_shutdown) (svr); | ||
249 | } | ||
250 | |||
251 | int | ||
252 | ecore_con_ssl_server_read(Ecore_Con_Server *svr, | ||
253 | unsigned char *buf, | ||
254 | int size) | ||
255 | { | ||
256 | return SSL_SUFFIX(_ecore_con_ssl_server_read) (svr, buf, size); | ||
257 | } | ||
258 | |||
259 | int | ||
260 | ecore_con_ssl_server_write(Ecore_Con_Server *svr, | ||
261 | const unsigned char *buf, | ||
262 | int size) | ||
263 | { | ||
264 | return SSL_SUFFIX(_ecore_con_ssl_server_write) (svr, buf, size); | ||
265 | } | ||
266 | |||
267 | Ecore_Con_Ssl_Error | ||
268 | ecore_con_ssl_client_init(Ecore_Con_Client *cl) | ||
269 | { | ||
270 | if (!(cl->host_server->type & ECORE_CON_SSL)) | ||
271 | return ECORE_CON_SSL_ERROR_NONE; | ||
272 | return SSL_SUFFIX(_ecore_con_ssl_client_init) (cl); | ||
273 | } | ||
274 | |||
275 | Ecore_Con_Ssl_Error | ||
276 | ecore_con_ssl_client_shutdown(Ecore_Con_Client *cl) | ||
277 | { | ||
278 | if (!(cl->host_server->type & ECORE_CON_SSL)) | ||
279 | return ECORE_CON_SSL_ERROR_NONE; | ||
280 | return SSL_SUFFIX(_ecore_con_ssl_client_shutdown) (cl); | ||
281 | } | ||
282 | |||
283 | int | ||
284 | ecore_con_ssl_client_read(Ecore_Con_Client *cl, | ||
285 | unsigned char *buf, | ||
286 | int size) | ||
287 | { | ||
288 | return SSL_SUFFIX(_ecore_con_ssl_client_read) (cl, buf, size); | ||
289 | } | ||
290 | |||
291 | int | ||
292 | ecore_con_ssl_client_write(Ecore_Con_Client *cl, | ||
293 | const unsigned char *buf, | ||
294 | int size) | ||
295 | { | ||
296 | return SSL_SUFFIX(_ecore_con_ssl_client_write) (cl, buf, size); | ||
297 | } | ||
298 | |||
299 | /** | ||
300 | * Returns if SSL support is available | ||
301 | * @return 1 if SSL is available and provided by gnutls, 2 if provided by openssl, | ||
302 | * 0 if it is not available. | ||
303 | * @ingroup Ecore_Con_Client_Group | ||
304 | */ | ||
305 | EAPI int | ||
306 | ecore_con_ssl_available_get(void) | ||
307 | { | ||
308 | return _ECORE_CON_SSL_AVAILABLE; | ||
309 | } | ||
310 | |||
311 | /** | ||
312 | * @addtogroup Ecore_Con_SSL_Group Ecore Connection SSL Functions | ||
313 | * | ||
314 | * Functions that operate on Ecore connection objects pertaining to SSL. | ||
315 | * | ||
316 | * @{ | ||
317 | */ | ||
318 | |||
319 | /** | ||
320 | * @brief Enable certificate verification on a server object | ||
321 | * | ||
322 | * Call this function on a server object before main loop has started | ||
323 | * to enable verification of certificates against loaded certificates. | ||
324 | * @param svr The server object | ||
325 | */ | ||
326 | EAPI void | ||
327 | ecore_con_ssl_server_verify(Ecore_Con_Server *svr) | ||
328 | { | ||
329 | if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) | ||
330 | { | ||
331 | ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_ssl_server_verify"); | ||
332 | return; | ||
333 | } | ||
334 | svr->verify = EINA_TRUE; | ||
335 | } | ||
336 | |||
337 | /** | ||
338 | * @brief Enable hostname-based certificate verification on a server object | ||
339 | * | ||
340 | * Call this function on a server object before main loop has started | ||
341 | * to enable verification of certificates using ONLY their hostnames. | ||
342 | * @param svr The server object | ||
343 | * @note This function has no effect when used on a listening server created by | ||
344 | * ecore_con_server_add | ||
345 | * @since 1.1 | ||
346 | */ | ||
347 | EAPI void | ||
348 | ecore_con_ssl_server_verify_basic(Ecore_Con_Server *svr) | ||
349 | { | ||
350 | if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) | ||
351 | { | ||
352 | ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, __func__); | ||
353 | return; | ||
354 | } | ||
355 | svr->verify_basic = EINA_TRUE; | ||
356 | } | ||
357 | |||
358 | /** | ||
359 | * @brief Add an ssl certificate for use in ecore_con functions. | ||
360 | * | ||
361 | * Use this function to add a SSL PEM certificate. | ||
362 | * Simply specify the cert here to use it in the server object for connecting or listening. | ||
363 | * If there is an error loading the certificate, an error will automatically be logged. | ||
364 | * @param cert The path to the certificate. | ||
365 | * @return EINA_FALSE if the file cannot be loaded, otherwise EINA_TRUE. | ||
366 | */ | ||
367 | |||
368 | EAPI Eina_Bool | ||
369 | ecore_con_ssl_server_cert_add(Ecore_Con_Server *svr, | ||
370 | const char *cert) | ||
371 | { | ||
372 | if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) | ||
373 | { | ||
374 | ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_ssl_server_cert_add"); | ||
375 | return EINA_FALSE; | ||
376 | } | ||
377 | |||
378 | return SSL_SUFFIX(_ecore_con_ssl_server_cert_add) (svr, cert); | ||
379 | } | ||
380 | |||
381 | /** | ||
382 | * @brief Add an ssl CA file for use in ecore_con functions. | ||
383 | * | ||
384 | * Use this function to add a SSL PEM CA file. | ||
385 | * Simply specify the file here to use it in the server object for connecting or listening. | ||
386 | * If there is an error loading the CAs, an error will automatically be logged. | ||
387 | * @param ca_file The path to the CA file. | ||
388 | * @return EINA_FALSE if the file cannot be loaded, otherwise EINA_TRUE. | ||
389 | */ | ||
390 | |||
391 | EAPI Eina_Bool | ||
392 | ecore_con_ssl_server_cafile_add(Ecore_Con_Server *svr, | ||
393 | const char *ca_file) | ||
394 | { | ||
395 | if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) | ||
396 | { | ||
397 | ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_ssl_server_cafile_add"); | ||
398 | return EINA_FALSE; | ||
399 | } | ||
400 | |||
401 | return SSL_SUFFIX(_ecore_con_ssl_server_cafile_add) (svr, ca_file); | ||
402 | } | ||
403 | |||
404 | /** | ||
405 | * @brief Add an ssl private key for use in ecore_con functions. | ||
406 | * | ||
407 | * Use this function to add a SSL PEM private key | ||
408 | * Simply specify the key file here to use it in the server object for connecting or listening. | ||
409 | * If there is an error loading the key, an error will automatically be logged. | ||
410 | * @param key_file The path to the key file. | ||
411 | * @return EINA_FALSE if the file cannot be loaded, | ||
412 | * otherwise EINA_TRUE. | ||
413 | */ | ||
414 | |||
415 | EAPI Eina_Bool | ||
416 | ecore_con_ssl_server_privkey_add(Ecore_Con_Server *svr, | ||
417 | const char *key_file) | ||
418 | { | ||
419 | if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) | ||
420 | { | ||
421 | ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_ssl_server_privkey_add"); | ||
422 | return EINA_FALSE; | ||
423 | } | ||
424 | |||
425 | return SSL_SUFFIX(_ecore_con_ssl_server_privkey_add) (svr, key_file); | ||
426 | } | ||
427 | |||
428 | /** | ||
429 | * @brief Add an ssl CRL for use in ecore_con functions. | ||
430 | * | ||
431 | * Use this function to add a SSL PEM CRL file | ||
432 | * Simply specify the CRL file here to use it in the server object for connecting or listening. | ||
433 | * If there is an error loading the CRL, an error will automatically be logged. | ||
434 | * @param crl_file The path to the CRL file. | ||
435 | * @return EINA_FALSE if the file cannot be loaded, | ||
436 | * otherwise EINA_TRUE. | ||
437 | */ | ||
438 | |||
439 | EAPI Eina_Bool | ||
440 | ecore_con_ssl_server_crl_add(Ecore_Con_Server *svr, | ||
441 | const char *crl_file) | ||
442 | { | ||
443 | if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) | ||
444 | { | ||
445 | ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_ssl_server_crl_add"); | ||
446 | return EINA_FALSE; | ||
447 | } | ||
448 | |||
449 | return SSL_SUFFIX(_ecore_con_ssl_server_crl_add) (svr, crl_file); | ||
450 | } | ||
451 | |||
452 | /** | ||
453 | * @brief Upgrade a connection to a specified level of encryption | ||
454 | * | ||
455 | * Use this function to begin an SSL handshake on a connection (STARTTLS or similar). | ||
456 | * Once the upgrade has been completed, an ECORE_CON_EVENT_SERVER_UPGRADE event will be emitted. | ||
457 | * The connection should be treated as disconnected until the next event. | ||
458 | * @param svr The server object | ||
459 | * @param ssl_type The SSL connection type (ONLY). | ||
460 | * @return EINA_FALSE if the connection cannot be upgraded, otherwise EINA_TRUE. | ||
461 | * @note This function is NEVER to be used on a server object created with ecore_con_server_add | ||
462 | * @warning Setting a wrong value for @p compl_type WILL mess up your program. | ||
463 | * @since 1.1 | ||
464 | */ | ||
465 | |||
466 | EAPI Eina_Bool | ||
467 | ecore_con_ssl_server_upgrade(Ecore_Con_Server *svr, Ecore_Con_Type ssl_type) | ||
468 | { | ||
469 | if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) | ||
470 | { | ||
471 | ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, __func__); | ||
472 | return EINA_FALSE; | ||
473 | } | ||
474 | #if _ECORE_CON_SSL_AVAILABLE == 0 | ||
475 | return EINA_FALSE; | ||
476 | #endif | ||
477 | |||
478 | if (!svr->ssl_prepared) | ||
479 | { | ||
480 | if (ecore_con_ssl_server_prepare(svr, ssl_type)) | ||
481 | return EINA_FALSE; | ||
482 | } | ||
483 | svr->type |= ssl_type; | ||
484 | svr->upgrade = EINA_TRUE; | ||
485 | svr->handshaking = EINA_TRUE; | ||
486 | svr->ssl_state = ECORE_CON_SSL_STATE_INIT; | ||
487 | return !SSL_SUFFIX(_ecore_con_ssl_server_init) (svr); | ||
488 | } | ||
489 | |||
490 | /** | ||
491 | * @brief Upgrade a connection to a specified level of encryption | ||
492 | * | ||
493 | * Use this function to begin an SSL handshake on a connection (STARTTLS or similar). | ||
494 | * 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. | ||
496 | * @param cl The client object | ||
497 | * @param compl_type The SSL connection type (ONLY). | ||
498 | * @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. | ||
500 | * @since 1.1 | ||
501 | */ | ||
502 | |||
503 | EAPI Eina_Bool | ||
504 | ecore_con_ssl_client_upgrade(Ecore_Con_Client *cl, Ecore_Con_Type ssl_type) | ||
505 | { | ||
506 | if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT)) | ||
507 | { | ||
508 | ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, __func__); | ||
509 | return EINA_FALSE; | ||
510 | } | ||
511 | #if _ECORE_CON_SSL_AVAILABLE == 0 | ||
512 | return EINA_FALSE; | ||
513 | #endif | ||
514 | |||
515 | if (!cl->host_server->ssl_prepared) | ||
516 | { | ||
517 | if (ecore_con_ssl_server_prepare(cl->host_server, ssl_type)) | ||
518 | return EINA_FALSE; | ||
519 | } | ||
520 | cl->host_server->type |= ssl_type; | ||
521 | cl->upgrade = EINA_TRUE; | ||
522 | cl->host_server->upgrade = EINA_TRUE; | ||
523 | cl->handshaking = EINA_TRUE; | ||
524 | cl->ssl_state = ECORE_CON_SSL_STATE_INIT; | ||
525 | return SSL_SUFFIX(_ecore_con_ssl_client_init) (cl); | ||
526 | } | ||
527 | |||
528 | /** | ||
529 | * @} | ||
530 | */ | ||
531 | |||
532 | #if USE_GNUTLS | ||
533 | |||
534 | /* | ||
535 | * GnuTLS | ||
536 | */ | ||
537 | |||
538 | static Ecore_Con_Ssl_Error | ||
539 | _ecore_con_ssl_init_gnutls(void) | ||
540 | { | ||
541 | #ifdef EINA_HAVE_THREADS | ||
542 | if (gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread)) | ||
543 | WRN("YOU ARE USING PTHREADS, BUT I CANNOT INITIALIZE THREADSAFE GCRYPT OPERATIONS!"); | ||
544 | #endif | ||
545 | if (gnutls_global_init()) | ||
546 | return ECORE_CON_SSL_ERROR_INIT_FAILED; | ||
547 | |||
548 | #ifdef ISCOMFITOR | ||
549 | gnutls_global_set_log_level(9); | ||
550 | gnutls_global_set_log_function(_gnutls_log_func); | ||
551 | #endif | ||
552 | return ECORE_CON_SSL_ERROR_NONE; | ||
553 | } | ||
554 | |||
555 | static Ecore_Con_Ssl_Error | ||
556 | _ecore_con_ssl_shutdown_gnutls(void) | ||
557 | { | ||
558 | gnutls_global_deinit(); | ||
559 | |||
560 | return ECORE_CON_SSL_ERROR_NONE; | ||
561 | } | ||
562 | |||
563 | static Ecore_Con_Ssl_Error | ||
564 | _ecore_con_ssl_server_prepare_gnutls(Ecore_Con_Server *svr, | ||
565 | int ssl_type) | ||
566 | { | ||
567 | int ret; | ||
568 | |||
569 | if (ssl_type & ECORE_CON_USE_SSL2) | ||
570 | return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED; | ||
571 | |||
572 | switch (ssl_type) | ||
573 | { | ||
574 | case ECORE_CON_USE_SSL3: | ||
575 | case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT: | ||
576 | case ECORE_CON_USE_TLS: | ||
577 | case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT: | ||
578 | case ECORE_CON_USE_MIXED: | ||
579 | case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT: | ||
580 | break; | ||
581 | |||
582 | default: | ||
583 | return ECORE_CON_SSL_ERROR_NONE; | ||
584 | } | ||
585 | |||
586 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_certificate_allocate_credentials(&svr->cert)); | ||
587 | |||
588 | if (svr->use_cert) | ||
589 | { | ||
590 | if (svr->created) | ||
591 | { | ||
592 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_dh_params_init(&svr->dh_params)); | ||
593 | INF("Generating DH params"); | ||
594 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_dh_params_generate2(svr->dh_params, 1024)); | ||
595 | |||
596 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_anon_allocate_server_credentials(&svr->anoncred_s)); | ||
597 | /* TODO: implement PSK */ | ||
598 | // SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_psk_allocate_server_credentials(&svr->pskcred_s)); | ||
599 | |||
600 | gnutls_anon_set_server_dh_params(svr->anoncred_s, svr->dh_params); | ||
601 | gnutls_certificate_set_dh_params(svr->cert, svr->dh_params); | ||
602 | //gnutls_psk_set_server_dh_params(svr->pskcred_s, svr->dh_params); | ||
603 | INF("DH params successfully generated and applied!"); | ||
604 | } | ||
605 | else | ||
606 | { | ||
607 | //SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_psk_allocate_client_credentials(&svr->pskcred_c)); | ||
608 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_anon_allocate_client_credentials(&svr->anoncred_c)); | ||
609 | } | ||
610 | } | ||
611 | |||
612 | svr->ssl_prepared = EINA_TRUE; | ||
613 | return ECORE_CON_SSL_ERROR_NONE; | ||
614 | |||
615 | error: | ||
616 | _gnutls_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR, ret); | ||
617 | _ecore_con_ssl_server_shutdown_gnutls(svr); | ||
618 | return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; | ||
619 | } | ||
620 | |||
621 | |||
622 | static Ecore_Con_Ssl_Error | ||
623 | _ecore_con_ssl_server_init_gnutls(Ecore_Con_Server *svr) | ||
624 | { | ||
625 | const gnutls_datum_t *cert_list; | ||
626 | unsigned int iter, cert_list_size; | ||
627 | gnutls_x509_crt_t cert = NULL; | ||
628 | const char *priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0:+VERS-SSL3.0"; | ||
629 | int ret = 0; | ||
630 | |||
631 | switch (svr->ssl_state) | ||
632 | { | ||
633 | case ECORE_CON_SSL_STATE_DONE: | ||
634 | return ECORE_CON_SSL_ERROR_NONE; | ||
635 | |||
636 | case ECORE_CON_SSL_STATE_INIT: | ||
637 | if (svr->type & ECORE_CON_USE_SSL2) /* not supported because of security issues */ | ||
638 | return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED; | ||
639 | |||
640 | switch (svr->type & ECORE_CON_SSL) | ||
641 | { | ||
642 | case ECORE_CON_USE_SSL3: | ||
643 | case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT: | ||
644 | priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:!VERS-TLS1.0:!VERS-TLS1.1"; | ||
645 | break; | ||
646 | |||
647 | case ECORE_CON_USE_TLS: | ||
648 | case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT: | ||
649 | priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:!VERS-SSL3.0"; | ||
650 | break; | ||
651 | |||
652 | case ECORE_CON_USE_MIXED: | ||
653 | case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT: | ||
654 | break; | ||
655 | |||
656 | default: | ||
657 | return ECORE_CON_SSL_ERROR_NONE; | ||
658 | } | ||
659 | |||
660 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_init(&svr->session, GNUTLS_CLIENT)); | ||
661 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_enable_client(svr->session)); | ||
662 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_server_name_set(svr->session, GNUTLS_NAME_DNS, svr->name, strlen(svr->name))); | ||
663 | INF("Applying priority string: %s", priority); | ||
664 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_priority_set_direct(svr->session, priority, NULL)); | ||
665 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(svr->session, GNUTLS_CRD_CERTIFICATE, svr->cert)); | ||
666 | // SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(svr->session, GNUTLS_CRD_PSK, svr->pskcred_c)); | ||
667 | if (!svr->use_cert) | ||
668 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(svr->session, GNUTLS_CRD_ANON, svr->anoncred_c)); | ||
669 | |||
670 | gnutls_dh_set_prime_bits(svr->session, 512); | ||
671 | gnutls_transport_set_ptr(svr->session, (gnutls_transport_ptr_t)((intptr_t)svr->fd)); | ||
672 | svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; | ||
673 | |||
674 | case ECORE_CON_SSL_STATE_HANDSHAKING: | ||
675 | if (!svr->session) | ||
676 | { | ||
677 | DBG("Server was previously lost, going to error condition"); | ||
678 | goto error; | ||
679 | } | ||
680 | ret = gnutls_handshake(svr->session); | ||
681 | DBG("calling gnutls_handshake(): returned with '%s'", gnutls_strerror_name(ret)); | ||
682 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_error_is_fatal(ret)); | ||
683 | if (!ret) | ||
684 | { | ||
685 | svr->handshaking = EINA_FALSE; | ||
686 | svr->ssl_state = ECORE_CON_SSL_STATE_DONE; | ||
687 | } | ||
688 | else | ||
689 | { | ||
690 | if (gnutls_record_get_direction(svr->session)) | ||
691 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); | ||
692 | else | ||
693 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ); | ||
694 | return ECORE_CON_SSL_ERROR_NONE; | ||
695 | } | ||
696 | |||
697 | default: | ||
698 | break; | ||
699 | } | ||
700 | |||
701 | if ((!svr->verify) && (!svr->verify_basic)) | ||
702 | /* not verifying certificates, so we're done! */ | ||
703 | return ECORE_CON_SSL_ERROR_NONE; | ||
704 | if (svr->verify) | ||
705 | { | ||
706 | /* use CRL/CA lists to verify */ | ||
707 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_certificate_verify_peers2(svr->session, &iter)); | ||
708 | if (iter & GNUTLS_CERT_INVALID) | ||
709 | ERR("The certificate is not trusted."); | ||
710 | else if (iter & GNUTLS_CERT_SIGNER_NOT_FOUND) | ||
711 | ERR("The certificate hasn't got a known issuer."); | ||
712 | else if (iter & GNUTLS_CERT_REVOKED) | ||
713 | ERR("The certificate has been revoked."); | ||
714 | else if (iter & GNUTLS_CERT_EXPIRED) | ||
715 | ERR("The certificate has expired"); | ||
716 | else if (iter & GNUTLS_CERT_NOT_ACTIVATED) | ||
717 | ERR("The certificate is not yet activated"); | ||
718 | |||
719 | if (iter) | ||
720 | goto error; | ||
721 | } | ||
722 | if (gnutls_certificate_type_get(svr->session) != GNUTLS_CRT_X509) | ||
723 | { | ||
724 | ERR("Warning: PGP certificates are not yet supported!"); | ||
725 | goto error; | ||
726 | } | ||
727 | |||
728 | 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); | ||
730 | |||
731 | 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)); | ||
733 | |||
734 | SSL_ERROR_CHECK_GOTO_ERROR(!gnutls_x509_crt_check_hostname(cert, svr->name)); | ||
735 | gnutls_x509_crt_deinit(cert); | ||
736 | DBG("SSL certificate verification succeeded!"); | ||
737 | return ECORE_CON_SSL_ERROR_NONE; | ||
738 | |||
739 | error: | ||
740 | _gnutls_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR, ret); | ||
741 | if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) || (ret == GNUTLS_E_FATAL_ALERT_RECEIVED)) | ||
742 | ERR("Also received alert: %s", gnutls_alert_get_name(gnutls_alert_get(svr->session))); | ||
743 | if (svr->session && (svr->ssl_state != ECORE_CON_SSL_STATE_DONE)) | ||
744 | { | ||
745 | ERR("last out: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_out(svr->session))); | ||
746 | ERR("last in: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_in(svr->session))); | ||
747 | } | ||
748 | if (cert) | ||
749 | gnutls_x509_crt_deinit(cert); | ||
750 | _ecore_con_ssl_server_shutdown_gnutls(svr); | ||
751 | return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; | ||
752 | } | ||
753 | |||
754 | static Eina_Bool | ||
755 | _ecore_con_ssl_server_cafile_add_gnutls(Ecore_Con_Server *svr, | ||
756 | const char *ca_file) | ||
757 | { | ||
758 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_certificate_set_x509_trust_file(svr->cert, ca_file, | ||
759 | GNUTLS_X509_FMT_PEM) < 1); | ||
760 | |||
761 | return EINA_TRUE; | ||
762 | error: | ||
763 | ERR("Could not load CA file!"); | ||
764 | return EINA_FALSE; | ||
765 | } | ||
766 | |||
767 | static Eina_Bool | ||
768 | _ecore_con_ssl_server_crl_add_gnutls(Ecore_Con_Server *svr, | ||
769 | const char *crl_file) | ||
770 | { | ||
771 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_certificate_set_x509_crl_file(svr->cert, crl_file, | ||
772 | GNUTLS_X509_FMT_PEM) < 1); | ||
773 | |||
774 | return EINA_TRUE; | ||
775 | error: | ||
776 | ERR("Could not load CRL file!"); | ||
777 | return EINA_FALSE; | ||
778 | } | ||
779 | |||
780 | static Eina_Bool | ||
781 | _ecore_con_ssl_server_privkey_add_gnutls(Ecore_Con_Server *svr, | ||
782 | const char *key_file) | ||
783 | { | ||
784 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_certificate_set_x509_key_file(svr->cert, svr->cert_file, key_file, | ||
785 | GNUTLS_X509_FMT_PEM)); | ||
786 | |||
787 | return EINA_TRUE; | ||
788 | error: | ||
789 | ERR("Could not load certificate/key file!"); | ||
790 | return EINA_FALSE; | ||
791 | } | ||
792 | |||
793 | static Eina_Bool | ||
794 | _ecore_con_ssl_server_cert_add_gnutls(Ecore_Con_Server *svr, | ||
795 | const char *cert_file) | ||
796 | { | ||
797 | if (!(svr->cert_file = strdup(cert_file))) | ||
798 | return EINA_FALSE; | ||
799 | |||
800 | return EINA_TRUE; | ||
801 | } | ||
802 | |||
803 | static Ecore_Con_Ssl_Error | ||
804 | _ecore_con_ssl_server_shutdown_gnutls(Ecore_Con_Server *svr) | ||
805 | { | ||
806 | if (svr->session) | ||
807 | { | ||
808 | gnutls_bye(svr->session, GNUTLS_SHUT_RDWR); | ||
809 | gnutls_deinit(svr->session); | ||
810 | } | ||
811 | |||
812 | free(svr->cert_file); | ||
813 | svr->cert_file = NULL; | ||
814 | if (svr->cert) | ||
815 | gnutls_certificate_free_credentials(svr->cert); | ||
816 | svr->cert = NULL; | ||
817 | |||
818 | if ((svr->type & ECORE_CON_SSL) && svr->created) | ||
819 | { | ||
820 | if (svr->dh_params) | ||
821 | { | ||
822 | gnutls_dh_params_deinit(svr->dh_params); | ||
823 | svr->dh_params = NULL; | ||
824 | } | ||
825 | if (svr->anoncred_s) | ||
826 | gnutls_anon_free_server_credentials(svr->anoncred_s); | ||
827 | // if (svr->pskcred_s) | ||
828 | // gnutls_psk_free_server_credentials(svr->pskcred_s); | ||
829 | |||
830 | svr->anoncred_s = NULL; | ||
831 | svr->pskcred_s = NULL; | ||
832 | } | ||
833 | else if (svr->type & ECORE_CON_SSL) | ||
834 | { | ||
835 | if (svr->anoncred_c) | ||
836 | gnutls_anon_free_client_credentials(svr->anoncred_c); | ||
837 | // if (svr->pskcred_c) | ||
838 | // gnutls_psk_free_client_credentials(svr->pskcred_c); | ||
839 | |||
840 | svr->anoncred_c = NULL; | ||
841 | svr->pskcred_c = NULL; | ||
842 | } | ||
843 | |||
844 | svr->session = NULL; | ||
845 | |||
846 | return ECORE_CON_SSL_ERROR_NONE; | ||
847 | } | ||
848 | |||
849 | static int | ||
850 | _ecore_con_ssl_server_read_gnutls(Ecore_Con_Server *svr, | ||
851 | unsigned char *buf, | ||
852 | int size) | ||
853 | { | ||
854 | int num; | ||
855 | |||
856 | if (svr->ssl_state == ECORE_CON_SSL_STATE_HANDSHAKING) | ||
857 | { | ||
858 | DBG("Continuing gnutls handshake"); | ||
859 | if (!_ecore_con_ssl_server_init_gnutls(svr)) | ||
860 | return 0; | ||
861 | return -1; | ||
862 | } | ||
863 | |||
864 | num = gnutls_record_recv(svr->session, buf, size); | ||
865 | if (num > 0) | ||
866 | return num; | ||
867 | |||
868 | if (num == GNUTLS_E_REHANDSHAKE) | ||
869 | { | ||
870 | WRN("Rehandshake request ignored"); | ||
871 | return 0; | ||
872 | |||
873 | svr->handshaking = EINA_TRUE; | ||
874 | svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; | ||
875 | if (!_ecore_con_ssl_server_init_gnutls(svr)) | ||
876 | return 0; | ||
877 | } | ||
878 | else if ((!gnutls_error_is_fatal(num)) && (num != GNUTLS_E_SUCCESS)) | ||
879 | return 0; | ||
880 | |||
881 | return -1; | ||
882 | } | ||
883 | |||
884 | static int | ||
885 | _ecore_con_ssl_server_write_gnutls(Ecore_Con_Server *svr, | ||
886 | const unsigned char *buf, | ||
887 | int size) | ||
888 | { | ||
889 | int num; | ||
890 | |||
891 | if (svr->ssl_state == ECORE_CON_SSL_STATE_HANDSHAKING) | ||
892 | { | ||
893 | DBG("Continuing gnutls handshake"); | ||
894 | if (!_ecore_con_ssl_server_init_gnutls(svr)) | ||
895 | return 0; | ||
896 | return -1; | ||
897 | } | ||
898 | |||
899 | num = gnutls_record_send(svr->session, buf, size); | ||
900 | if (num > 0) | ||
901 | return num; | ||
902 | |||
903 | if (num == GNUTLS_E_REHANDSHAKE) | ||
904 | { | ||
905 | WRN("Rehandshake request ignored"); | ||
906 | return 0; | ||
907 | /* this is only partly functional I think? */ | ||
908 | svr->handshaking = EINA_TRUE; | ||
909 | svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; | ||
910 | if (!_ecore_con_ssl_server_init_gnutls(svr)) | ||
911 | return 0; | ||
912 | } | ||
913 | else if (!gnutls_error_is_fatal(num)) | ||
914 | return 0; | ||
915 | |||
916 | return -1; | ||
917 | } | ||
918 | |||
919 | static Ecore_Con_Ssl_Error | ||
920 | _ecore_con_ssl_client_init_gnutls(Ecore_Con_Client *cl) | ||
921 | { | ||
922 | const gnutls_datum_t *cert_list; | ||
923 | unsigned int iter, cert_list_size; | ||
924 | const char *priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0:+VERS-SSL3.0"; | ||
925 | int ret = 0; | ||
926 | |||
927 | switch (cl->ssl_state) | ||
928 | { | ||
929 | case ECORE_CON_SSL_STATE_DONE: | ||
930 | return ECORE_CON_SSL_ERROR_NONE; | ||
931 | |||
932 | case ECORE_CON_SSL_STATE_INIT: | ||
933 | if (cl->host_server->type & ECORE_CON_USE_SSL2) /* not supported because of security issues */ | ||
934 | return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED; | ||
935 | |||
936 | switch (cl->host_server->type & ECORE_CON_SSL) | ||
937 | { | ||
938 | case ECORE_CON_USE_SSL3: | ||
939 | case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT: | ||
940 | priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:!VERS-TLS1.0:!VERS-TLS1.1"; | ||
941 | break; | ||
942 | |||
943 | case ECORE_CON_USE_TLS: | ||
944 | case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT: | ||
945 | priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:!VERS-SSL3.0"; | ||
946 | break; | ||
947 | |||
948 | case ECORE_CON_USE_MIXED: | ||
949 | case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT: | ||
950 | break; | ||
951 | |||
952 | default: | ||
953 | return ECORE_CON_SSL_ERROR_NONE; | ||
954 | } | ||
955 | |||
956 | _client_connected++; | ||
957 | |||
958 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_init(&cl->session, GNUTLS_SERVER)); | ||
959 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_key_generate(&cl->session_ticket)); | ||
960 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_enable_server(cl->session, &cl->session_ticket)); | ||
961 | INF("Applying priority string: %s", priority); | ||
962 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_priority_set_direct(cl->session, priority, NULL)); | ||
963 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_CERTIFICATE, cl->host_server->cert)); | ||
964 | // SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_PSK, cl->host_server->pskcred_s)); | ||
965 | if (!cl->host_server->use_cert) | ||
966 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_ANON, cl->host_server->anoncred_s)); | ||
967 | |||
968 | gnutls_certificate_server_set_request(cl->session, GNUTLS_CERT_REQUEST); | ||
969 | |||
970 | gnutls_dh_set_prime_bits(cl->session, 2048); | ||
971 | gnutls_transport_set_ptr(cl->session, (gnutls_transport_ptr_t)((intptr_t)cl->fd)); | ||
972 | cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; | ||
973 | |||
974 | case ECORE_CON_SSL_STATE_HANDSHAKING: | ||
975 | if (!cl->session) | ||
976 | { | ||
977 | DBG("Client was previously lost, going to error condition"); | ||
978 | goto error; | ||
979 | } | ||
980 | DBG("calling gnutls_handshake()"); | ||
981 | ret = gnutls_handshake(cl->session); | ||
982 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_error_is_fatal(ret)); | ||
983 | |||
984 | if (!ret) | ||
985 | { | ||
986 | cl->handshaking = EINA_FALSE; | ||
987 | cl->ssl_state = ECORE_CON_SSL_STATE_DONE; | ||
988 | } | ||
989 | else | ||
990 | { | ||
991 | if (gnutls_record_get_direction(cl->session)) | ||
992 | ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE); | ||
993 | else | ||
994 | ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ); | ||
995 | return ECORE_CON_SSL_ERROR_NONE; | ||
996 | } | ||
997 | |||
998 | default: | ||
999 | break; | ||
1000 | } | ||
1001 | |||
1002 | if (!cl->host_server->verify) | ||
1003 | /* not verifying certificates, so we're done! */ | ||
1004 | return ECORE_CON_SSL_ERROR_NONE; | ||
1005 | /* use CRL/CA lists to verify */ | ||
1006 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_certificate_verify_peers2(cl->session, &iter)); | ||
1007 | if (iter & GNUTLS_CERT_INVALID) | ||
1008 | ERR("The certificate is not trusted."); | ||
1009 | else if (iter & GNUTLS_CERT_SIGNER_NOT_FOUND) | ||
1010 | ERR("The certificate hasn't got a known issuer."); | ||
1011 | else if (iter & GNUTLS_CERT_REVOKED) | ||
1012 | ERR("The certificate has been revoked."); | ||
1013 | else if (iter & GNUTLS_CERT_EXPIRED) | ||
1014 | ERR("The certificate has expired"); | ||
1015 | else if (iter & GNUTLS_CERT_NOT_ACTIVATED) | ||
1016 | ERR("The certificate is not yet activated"); | ||
1017 | |||
1018 | if (iter) | ||
1019 | goto error; | ||
1020 | if (gnutls_certificate_type_get(cl->session) != GNUTLS_CRT_X509) | ||
1021 | { | ||
1022 | ERR("Warning: PGP certificates are not yet supported!"); | ||
1023 | goto error; | ||
1024 | } | ||
1025 | |||
1026 | 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); | ||
1028 | |||
1029 | /* | ||
1030 | gnutls_x509_crt_t cert = NULL; | ||
1031 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_init(&cert)); | ||
1032 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER)); | ||
1033 | |||
1034 | SSL_ERROR_CHECK_GOTO_ERROR(!gnutls_x509_crt_check_hostname(cert, cl->host_server->name)); | ||
1035 | gnutls_x509_crt_deinit(cert); | ||
1036 | */ | ||
1037 | DBG("SSL certificate verification succeeded!"); | ||
1038 | return ECORE_CON_SSL_ERROR_NONE; | ||
1039 | |||
1040 | error: | ||
1041 | _gnutls_print_errors(cl, ECORE_CON_EVENT_CLIENT_ERROR, ret); | ||
1042 | if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) || (ret == GNUTLS_E_FATAL_ALERT_RECEIVED)) | ||
1043 | ERR("Also received alert: %s", gnutls_alert_get_name(gnutls_alert_get(cl->session))); | ||
1044 | if (cl->session && (cl->ssl_state != ECORE_CON_SSL_STATE_DONE)) | ||
1045 | { | ||
1046 | ERR("last out: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_out(cl->session))); | ||
1047 | ERR("last in: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_in(cl->session))); | ||
1048 | } | ||
1049 | /* | ||
1050 | if (cert) | ||
1051 | gnutls_x509_crt_deinit(cert); | ||
1052 | */ | ||
1053 | _ecore_con_ssl_client_shutdown_gnutls(cl); | ||
1054 | return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; | ||
1055 | } | ||
1056 | |||
1057 | static Ecore_Con_Ssl_Error | ||
1058 | _ecore_con_ssl_client_shutdown_gnutls(Ecore_Con_Client *cl) | ||
1059 | { | ||
1060 | if (cl->session) | ||
1061 | { | ||
1062 | gnutls_bye(cl->session, GNUTLS_SHUT_RDWR); | ||
1063 | gnutls_deinit(cl->session); | ||
1064 | gnutls_free(cl->session_ticket.data); | ||
1065 | cl->session_ticket.data = NULL; | ||
1066 | } | ||
1067 | |||
1068 | cl->session = NULL; | ||
1069 | |||
1070 | return ECORE_CON_SSL_ERROR_NONE; | ||
1071 | } | ||
1072 | |||
1073 | static int | ||
1074 | _ecore_con_ssl_client_read_gnutls(Ecore_Con_Client *cl, | ||
1075 | unsigned char *buf, | ||
1076 | int size) | ||
1077 | { | ||
1078 | int num; | ||
1079 | |||
1080 | if (cl->ssl_state == ECORE_CON_SSL_STATE_HANDSHAKING) | ||
1081 | { | ||
1082 | if (!_ecore_con_ssl_client_init_gnutls(cl)) | ||
1083 | return 0; | ||
1084 | return -1; | ||
1085 | } | ||
1086 | |||
1087 | num = gnutls_record_recv(cl->session, buf, size); | ||
1088 | if (num > 0) | ||
1089 | return num; | ||
1090 | |||
1091 | if (num == GNUTLS_E_REHANDSHAKE) | ||
1092 | { | ||
1093 | WRN("Rehandshake request ignored"); | ||
1094 | return 0; | ||
1095 | cl->handshaking = EINA_TRUE; | ||
1096 | cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; | ||
1097 | if (!_ecore_con_ssl_client_init_gnutls(cl)) | ||
1098 | return 0; | ||
1099 | WRN("Rehandshake request ignored"); | ||
1100 | return 0; | ||
1101 | } | ||
1102 | else if ((!gnutls_error_is_fatal(num)) && (num != GNUTLS_E_SUCCESS)) | ||
1103 | return 0; | ||
1104 | |||
1105 | return -1; | ||
1106 | } | ||
1107 | |||
1108 | static int | ||
1109 | _ecore_con_ssl_client_write_gnutls(Ecore_Con_Client *cl, | ||
1110 | const unsigned char *buf, | ||
1111 | int size) | ||
1112 | { | ||
1113 | int num; | ||
1114 | |||
1115 | if (cl->ssl_state == ECORE_CON_SSL_STATE_HANDSHAKING) | ||
1116 | { | ||
1117 | if (!_ecore_con_ssl_client_init_gnutls(cl)) | ||
1118 | return 0; | ||
1119 | return -1; | ||
1120 | } | ||
1121 | |||
1122 | num = gnutls_record_send(cl->session, buf, size); | ||
1123 | if (num > 0) | ||
1124 | return num; | ||
1125 | |||
1126 | if (num == GNUTLS_E_REHANDSHAKE) | ||
1127 | { | ||
1128 | WRN("Rehandshake request ignored"); | ||
1129 | return 0; | ||
1130 | cl->handshaking = EINA_TRUE; | ||
1131 | cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; | ||
1132 | if (!_ecore_con_ssl_client_init_gnutls(cl)) | ||
1133 | return 0; | ||
1134 | } | ||
1135 | else if (!gnutls_error_is_fatal(num)) | ||
1136 | return 0; | ||
1137 | |||
1138 | return -1; | ||
1139 | } | ||
1140 | |||
1141 | #elif USE_OPENSSL && !USE_GNUTLS | ||
1142 | |||
1143 | /* | ||
1144 | * OpenSSL | ||
1145 | */ | ||
1146 | |||
1147 | static Ecore_Con_Ssl_Error | ||
1148 | _ecore_con_ssl_init_openssl(void) | ||
1149 | { | ||
1150 | SSL_library_init(); | ||
1151 | SSL_load_error_strings(); | ||
1152 | OpenSSL_add_all_algorithms(); | ||
1153 | |||
1154 | return ECORE_CON_SSL_ERROR_NONE; | ||
1155 | } | ||
1156 | |||
1157 | static Ecore_Con_Ssl_Error | ||
1158 | _ecore_con_ssl_shutdown_openssl(void) | ||
1159 | { | ||
1160 | ERR_free_strings(); | ||
1161 | EVP_cleanup(); | ||
1162 | return ECORE_CON_SSL_ERROR_NONE; | ||
1163 | } | ||
1164 | |||
1165 | static Ecore_Con_Ssl_Error | ||
1166 | _ecore_con_ssl_server_prepare_openssl(Ecore_Con_Server *svr, | ||
1167 | int ssl_type) | ||
1168 | { | ||
1169 | long options; | ||
1170 | int dh = 0; | ||
1171 | |||
1172 | if (ssl_type & ECORE_CON_USE_SSL2) | ||
1173 | return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED; | ||
1174 | |||
1175 | switch (ssl_type) | ||
1176 | { | ||
1177 | case ECORE_CON_USE_SSL3: | ||
1178 | case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT: | ||
1179 | if (!svr->created) | ||
1180 | SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv3_client_method()))); | ||
1181 | else | ||
1182 | SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv3_server_method()))); | ||
1183 | break; | ||
1184 | |||
1185 | case ECORE_CON_USE_TLS: | ||
1186 | case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT: | ||
1187 | if (!svr->created) | ||
1188 | SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(TLSv1_client_method()))); | ||
1189 | else | ||
1190 | SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(TLSv1_server_method()))); | ||
1191 | break; | ||
1192 | |||
1193 | case ECORE_CON_USE_MIXED: | ||
1194 | case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT: | ||
1195 | if (!svr->created) | ||
1196 | SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv23_client_method()))); | ||
1197 | else | ||
1198 | SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))); | ||
1199 | options = SSL_CTX_get_options(svr->ssl_ctx); | ||
1200 | SSL_CTX_set_options(svr->ssl_ctx, options | SSL_OP_NO_SSLv2 | SSL_OP_SINGLE_DH_USE); | ||
1201 | break; | ||
1202 | |||
1203 | default: | ||
1204 | return ECORE_CON_SSL_ERROR_NONE; | ||
1205 | } | ||
1206 | |||
1207 | if ((!svr->use_cert) && svr->created) | ||
1208 | { | ||
1209 | DH *dh_params; | ||
1210 | INF("Generating DH params"); | ||
1211 | SSL_ERROR_CHECK_GOTO_ERROR(!(dh_params = DH_new())); | ||
1212 | SSL_ERROR_CHECK_GOTO_ERROR(!DH_generate_parameters_ex(dh_params, 1024, DH_GENERATOR_5, NULL)); | ||
1213 | SSL_ERROR_CHECK_GOTO_ERROR(!DH_check(dh_params, &dh)); | ||
1214 | SSL_ERROR_CHECK_GOTO_ERROR((dh & DH_CHECK_P_NOT_PRIME) || (dh & DH_CHECK_P_NOT_SAFE_PRIME)); | ||
1215 | SSL_ERROR_CHECK_GOTO_ERROR(!DH_generate_key(dh_params)); | ||
1216 | SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_tmp_dh(svr->ssl_ctx, dh_params)); | ||
1217 | DH_free(dh_params); | ||
1218 | INF("DH params successfully generated and applied!"); | ||
1219 | SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_cipher_list(svr->ssl_ctx, "aNULL:!eNULL:!LOW:!EXPORT:@STRENGTH")); | ||
1220 | } | ||
1221 | else if (!svr->use_cert) | ||
1222 | SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_cipher_list(svr->ssl_ctx, "aNULL:!eNULL:!LOW:!EXPORT:!ECDH:RSA:AES:!PSK:@STRENGTH")); | ||
1223 | |||
1224 | return ECORE_CON_SSL_ERROR_NONE; | ||
1225 | |||
1226 | error: | ||
1227 | if (dh) | ||
1228 | { | ||
1229 | if (dh & DH_CHECK_P_NOT_PRIME) | ||
1230 | ERR("openssl error: dh_params could not generate a prime!"); | ||
1231 | else | ||
1232 | ERR("openssl error: dh_params could not generate a safe prime!"); | ||
1233 | } | ||
1234 | else | ||
1235 | _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR); | ||
1236 | _ecore_con_ssl_server_shutdown_openssl(svr); | ||
1237 | return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; | ||
1238 | } | ||
1239 | |||
1240 | static Ecore_Con_Ssl_Error | ||
1241 | _ecore_con_ssl_server_init_openssl(Ecore_Con_Server *svr) | ||
1242 | { | ||
1243 | int ret = -1; | ||
1244 | |||
1245 | switch (svr->ssl_state) | ||
1246 | { | ||
1247 | case ECORE_CON_SSL_STATE_DONE: | ||
1248 | return ECORE_CON_SSL_ERROR_NONE; | ||
1249 | |||
1250 | case ECORE_CON_SSL_STATE_INIT: | ||
1251 | SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl = SSL_new(svr->ssl_ctx))); | ||
1252 | |||
1253 | SSL_ERROR_CHECK_GOTO_ERROR(!SSL_set_fd(svr->ssl, svr->fd)); | ||
1254 | SSL_set_connect_state(svr->ssl); | ||
1255 | svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; | ||
1256 | |||
1257 | case ECORE_CON_SSL_STATE_HANDSHAKING: | ||
1258 | if (!svr->ssl) | ||
1259 | { | ||
1260 | DBG("Server was previously lost, going to error condition"); | ||
1261 | goto error; | ||
1262 | } | ||
1263 | ret = SSL_do_handshake(svr->ssl); | ||
1264 | svr->ssl_err = SSL_get_error(svr->ssl, ret); | ||
1265 | SSL_ERROR_CHECK_GOTO_ERROR((svr->ssl_err == SSL_ERROR_SYSCALL) || (svr->ssl_err == SSL_ERROR_SSL)); | ||
1266 | |||
1267 | if (ret == 1) | ||
1268 | { | ||
1269 | svr->handshaking = EINA_FALSE; | ||
1270 | svr->ssl_state = ECORE_CON_SSL_STATE_DONE; | ||
1271 | } | ||
1272 | else | ||
1273 | { | ||
1274 | if (svr->ssl_err == SSL_ERROR_WANT_READ) | ||
1275 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ); | ||
1276 | else if (svr->ssl_err == SSL_ERROR_WANT_WRITE) | ||
1277 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); | ||
1278 | return ECORE_CON_SSL_ERROR_NONE; | ||
1279 | } | ||
1280 | |||
1281 | default: | ||
1282 | break; | ||
1283 | } | ||
1284 | |||
1285 | #ifdef ISCOMFITOR | ||
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)) | ||
1303 | /* not verifying certificates, so we're done! */ | ||
1304 | return ECORE_CON_SSL_ERROR_NONE; | ||
1305 | |||
1306 | { | ||
1307 | X509 *cert; | ||
1308 | SSL_set_verify(svr->ssl, SSL_VERIFY_PEER, NULL); | ||
1309 | /* use CRL/CA lists to verify */ | ||
1310 | cert = SSL_get_peer_certificate(svr->ssl); | ||
1311 | if (cert) | ||
1312 | { | ||
1313 | char buf[256] = {0}; | ||
1314 | 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 | { | ||
1321 | X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, buf, sizeof(buf)); | ||
1322 | SSL_ERROR_CHECK_GOTO_ERROR(!_openssl_name_verify(buf, svr->name)); | ||
1323 | } | ||
1324 | } | ||
1325 | } | ||
1326 | |||
1327 | DBG("SSL certificate verification succeeded!"); | ||
1328 | |||
1329 | return ECORE_CON_SSL_ERROR_NONE; | ||
1330 | |||
1331 | error: | ||
1332 | _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR); | ||
1333 | _ecore_con_ssl_server_shutdown_openssl(svr); | ||
1334 | return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; | ||
1335 | } | ||
1336 | |||
1337 | static Eina_Bool | ||
1338 | _ecore_con_ssl_server_cafile_add_openssl(Ecore_Con_Server *svr, | ||
1339 | const char *ca_file) | ||
1340 | { | ||
1341 | SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_load_verify_locations(svr->ssl_ctx, ca_file, NULL)); | ||
1342 | return EINA_TRUE; | ||
1343 | |||
1344 | error: | ||
1345 | _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR); | ||
1346 | return EINA_FALSE; | ||
1347 | } | ||
1348 | |||
1349 | static Eina_Bool | ||
1350 | _ecore_con_ssl_server_crl_add_openssl(Ecore_Con_Server *svr, | ||
1351 | const char *crl_file) | ||
1352 | { | ||
1353 | X509_STORE *st; | ||
1354 | X509_LOOKUP *lu; | ||
1355 | static Eina_Bool flag = EINA_FALSE; | ||
1356 | |||
1357 | SSL_ERROR_CHECK_GOTO_ERROR(!(st = SSL_CTX_get_cert_store(svr->ssl_ctx))); | ||
1358 | SSL_ERROR_CHECK_GOTO_ERROR(!(lu = X509_STORE_add_lookup(st, X509_LOOKUP_file()))); | ||
1359 | SSL_ERROR_CHECK_GOTO_ERROR(X509_load_crl_file(lu, crl_file, X509_FILETYPE_PEM) < 1); | ||
1360 | if (!flag) | ||
1361 | { | ||
1362 | X509_STORE_set_flags(st, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); | ||
1363 | flag = EINA_TRUE; | ||
1364 | } | ||
1365 | |||
1366 | return EINA_TRUE; | ||
1367 | |||
1368 | error: | ||
1369 | _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR); | ||
1370 | return EINA_FALSE; | ||
1371 | } | ||
1372 | |||
1373 | static Eina_Bool | ||
1374 | _ecore_con_ssl_server_privkey_add_openssl(Ecore_Con_Server *svr, | ||
1375 | const char *key_file) | ||
1376 | { | ||
1377 | FILE *fp = NULL; | ||
1378 | EVP_PKEY *privkey = NULL; | ||
1379 | |||
1380 | if (!(fp = fopen(key_file, "r"))) | ||
1381 | goto error; | ||
1382 | |||
1383 | SSL_ERROR_CHECK_GOTO_ERROR(!(privkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL))); | ||
1384 | |||
1385 | fclose(fp); | ||
1386 | SSL_ERROR_CHECK_GOTO_ERROR(SSL_CTX_use_PrivateKey(svr->ssl_ctx, privkey) < 1); | ||
1387 | SSL_ERROR_CHECK_GOTO_ERROR(SSL_CTX_check_private_key(svr->ssl_ctx) < 1); | ||
1388 | |||
1389 | return EINA_TRUE; | ||
1390 | |||
1391 | error: | ||
1392 | if (fp) | ||
1393 | fclose(fp); | ||
1394 | _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR); | ||
1395 | return EINA_FALSE; | ||
1396 | } | ||
1397 | |||
1398 | static Eina_Bool | ||
1399 | _ecore_con_ssl_server_cert_add_openssl(Ecore_Con_Server *svr, | ||
1400 | const char *cert_file) | ||
1401 | { | ||
1402 | FILE *fp = NULL; | ||
1403 | X509 *cert = NULL; | ||
1404 | |||
1405 | if (!(fp = fopen(cert_file, "r"))) | ||
1406 | goto error; | ||
1407 | |||
1408 | SSL_ERROR_CHECK_GOTO_ERROR(!(cert = PEM_read_X509(fp, NULL, NULL, NULL))); | ||
1409 | |||
1410 | fclose(fp); | ||
1411 | |||
1412 | SSL_ERROR_CHECK_GOTO_ERROR(SSL_CTX_use_certificate(svr->ssl_ctx, cert) < 1); | ||
1413 | |||
1414 | return EINA_TRUE; | ||
1415 | |||
1416 | error: | ||
1417 | if (fp) | ||
1418 | fclose(fp); | ||
1419 | _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR); | ||
1420 | return EINA_FALSE; | ||
1421 | } | ||
1422 | |||
1423 | static Ecore_Con_Ssl_Error | ||
1424 | _ecore_con_ssl_server_shutdown_openssl(Ecore_Con_Server *svr) | ||
1425 | { | ||
1426 | if (svr->ssl) | ||
1427 | { | ||
1428 | if (!SSL_shutdown(svr->ssl)) | ||
1429 | SSL_shutdown(svr->ssl); | ||
1430 | |||
1431 | SSL_free(svr->ssl); | ||
1432 | } | ||
1433 | |||
1434 | if (svr->ssl_ctx) | ||
1435 | SSL_CTX_free(svr->ssl_ctx); | ||
1436 | |||
1437 | svr->ssl = NULL; | ||
1438 | svr->ssl_ctx = NULL; | ||
1439 | svr->ssl_err = SSL_ERROR_NONE; | ||
1440 | |||
1441 | return ECORE_CON_SSL_ERROR_NONE; | ||
1442 | } | ||
1443 | |||
1444 | static int | ||
1445 | _ecore_con_ssl_server_read_openssl(Ecore_Con_Server *svr, | ||
1446 | unsigned char *buf, | ||
1447 | int size) | ||
1448 | { | ||
1449 | int num; | ||
1450 | |||
1451 | if (!svr->ssl) return -1; | ||
1452 | num = SSL_read(svr->ssl, buf, size); | ||
1453 | svr->ssl_err = SSL_get_error(svr->ssl, num); | ||
1454 | |||
1455 | if (svr->fd_handler) | ||
1456 | { | ||
1457 | if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_READ) | ||
1458 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ); | ||
1459 | else if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_WRITE) | ||
1460 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); | ||
1461 | } | ||
1462 | |||
1463 | if ((svr->ssl_err == SSL_ERROR_ZERO_RETURN) || | ||
1464 | (svr->ssl_err == SSL_ERROR_SYSCALL) || | ||
1465 | (svr->ssl_err == SSL_ERROR_SSL)) | ||
1466 | return -1; | ||
1467 | |||
1468 | if (num < 0) | ||
1469 | return 0; | ||
1470 | |||
1471 | return num; | ||
1472 | } | ||
1473 | |||
1474 | static int | ||
1475 | _ecore_con_ssl_server_write_openssl(Ecore_Con_Server *svr, | ||
1476 | const unsigned char *buf, | ||
1477 | int size) | ||
1478 | { | ||
1479 | int num; | ||
1480 | |||
1481 | num = SSL_write(svr->ssl, buf, size); | ||
1482 | svr->ssl_err = SSL_get_error(svr->ssl, num); | ||
1483 | |||
1484 | if (svr->fd_handler) | ||
1485 | { | ||
1486 | if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_READ) | ||
1487 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ); | ||
1488 | else if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_WRITE) | ||
1489 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); | ||
1490 | } | ||
1491 | |||
1492 | if ((svr->ssl_err == SSL_ERROR_ZERO_RETURN) || | ||
1493 | (svr->ssl_err == SSL_ERROR_SYSCALL) || | ||
1494 | (svr->ssl_err == SSL_ERROR_SSL)) | ||
1495 | return -1; | ||
1496 | |||
1497 | if (num < 0) | ||
1498 | return 0; | ||
1499 | |||
1500 | return num; | ||
1501 | } | ||
1502 | |||
1503 | static Ecore_Con_Ssl_Error | ||
1504 | _ecore_con_ssl_client_init_openssl(Ecore_Con_Client *cl) | ||
1505 | { | ||
1506 | int ret = -1; | ||
1507 | switch (cl->ssl_state) | ||
1508 | { | ||
1509 | case ECORE_CON_SSL_STATE_DONE: | ||
1510 | return ECORE_CON_SSL_ERROR_NONE; | ||
1511 | |||
1512 | case ECORE_CON_SSL_STATE_INIT: | ||
1513 | SSL_ERROR_CHECK_GOTO_ERROR(!(cl->ssl = SSL_new(cl->host_server->ssl_ctx))); | ||
1514 | |||
1515 | SSL_ERROR_CHECK_GOTO_ERROR(!SSL_set_fd(cl->ssl, cl->fd)); | ||
1516 | SSL_set_accept_state(cl->ssl); | ||
1517 | cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; | ||
1518 | |||
1519 | case ECORE_CON_SSL_STATE_HANDSHAKING: | ||
1520 | if (!cl->ssl) | ||
1521 | { | ||
1522 | DBG("Client was previously lost, going to error condition"); | ||
1523 | goto error; | ||
1524 | } | ||
1525 | ret = SSL_do_handshake(cl->ssl); | ||
1526 | cl->ssl_err = SSL_get_error(cl->ssl, ret); | ||
1527 | SSL_ERROR_CHECK_GOTO_ERROR((cl->ssl_err == SSL_ERROR_SYSCALL) || (cl->ssl_err == SSL_ERROR_SSL)); | ||
1528 | if (ret == 1) | ||
1529 | { | ||
1530 | cl->handshaking = EINA_FALSE; | ||
1531 | cl->ssl_state = ECORE_CON_SSL_STATE_DONE; | ||
1532 | } | ||
1533 | else | ||
1534 | { | ||
1535 | if (cl->ssl_err == SSL_ERROR_WANT_READ) | ||
1536 | ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ); | ||
1537 | else if (cl->ssl_err == SSL_ERROR_WANT_WRITE) | ||
1538 | ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE); | ||
1539 | return ECORE_CON_SSL_ERROR_NONE; | ||
1540 | } | ||
1541 | |||
1542 | default: | ||
1543 | break; | ||
1544 | } | ||
1545 | |||
1546 | #ifdef ISCOMFITOR | ||
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) | ||
1565 | /* not verifying certificates, so we're done! */ | ||
1566 | return ECORE_CON_SSL_ERROR_NONE; | ||
1567 | SSL_set_verify(cl->ssl, SSL_VERIFY_PEER, NULL); | ||
1568 | /* use CRL/CA lists to verify */ | ||
1569 | if (SSL_get_peer_certificate(cl->ssl)) | ||
1570 | SSL_ERROR_CHECK_GOTO_ERROR(SSL_get_verify_result(cl->ssl)); | ||
1571 | |||
1572 | return ECORE_CON_SSL_ERROR_NONE; | ||
1573 | |||
1574 | error: | ||
1575 | _openssl_print_errors(cl, ECORE_CON_EVENT_CLIENT_ERROR); | ||
1576 | _ecore_con_ssl_client_shutdown_openssl(cl); | ||
1577 | return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; | ||
1578 | } | ||
1579 | |||
1580 | static Ecore_Con_Ssl_Error | ||
1581 | _ecore_con_ssl_client_shutdown_openssl(Ecore_Con_Client *cl) | ||
1582 | { | ||
1583 | if (cl->ssl) | ||
1584 | { | ||
1585 | if (!SSL_shutdown(cl->ssl)) | ||
1586 | SSL_shutdown(cl->ssl); | ||
1587 | |||
1588 | SSL_free(cl->ssl); | ||
1589 | } | ||
1590 | |||
1591 | cl->ssl = NULL; | ||
1592 | cl->ssl_err = SSL_ERROR_NONE; | ||
1593 | |||
1594 | return ECORE_CON_SSL_ERROR_NONE; | ||
1595 | } | ||
1596 | |||
1597 | static int | ||
1598 | _ecore_con_ssl_client_read_openssl(Ecore_Con_Client *cl, | ||
1599 | unsigned char *buf, | ||
1600 | int size) | ||
1601 | { | ||
1602 | int num; | ||
1603 | |||
1604 | if (!cl->ssl) return -1; | ||
1605 | num = SSL_read(cl->ssl, buf, size); | ||
1606 | cl->ssl_err = SSL_get_error(cl->ssl, num); | ||
1607 | |||
1608 | if (cl->fd_handler) | ||
1609 | { | ||
1610 | if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_READ) | ||
1611 | ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ); | ||
1612 | else if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_WRITE) | ||
1613 | ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE); | ||
1614 | } | ||
1615 | |||
1616 | if ((cl->ssl_err == SSL_ERROR_ZERO_RETURN) || | ||
1617 | (cl->ssl_err == SSL_ERROR_SYSCALL) || | ||
1618 | (cl->ssl_err == SSL_ERROR_SSL)) | ||
1619 | return -1; | ||
1620 | |||
1621 | if (num < 0) | ||
1622 | return 0; | ||
1623 | |||
1624 | return num; | ||
1625 | } | ||
1626 | |||
1627 | static int | ||
1628 | _ecore_con_ssl_client_write_openssl(Ecore_Con_Client *cl, | ||
1629 | const unsigned char *buf, | ||
1630 | int size) | ||
1631 | { | ||
1632 | int num; | ||
1633 | |||
1634 | num = SSL_write(cl->ssl, buf, size); | ||
1635 | cl->ssl_err = SSL_get_error(cl->ssl, num); | ||
1636 | |||
1637 | if (cl->fd_handler) | ||
1638 | { | ||
1639 | if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_READ) | ||
1640 | ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ); | ||
1641 | else if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_WRITE) | ||
1642 | ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE); | ||
1643 | } | ||
1644 | |||
1645 | if ((cl->ssl_err == SSL_ERROR_ZERO_RETURN) || | ||
1646 | (cl->ssl_err == SSL_ERROR_SYSCALL) || | ||
1647 | (cl->ssl_err == SSL_ERROR_SSL)) | ||
1648 | return -1; | ||
1649 | |||
1650 | if (num < 0) | ||
1651 | return 0; | ||
1652 | |||
1653 | return num; | ||
1654 | } | ||
1655 | |||
1656 | #else | ||
1657 | |||
1658 | /* | ||
1659 | * No Ssl | ||
1660 | */ | ||
1661 | |||
1662 | static Ecore_Con_Ssl_Error | ||
1663 | _ecore_con_ssl_init_none(void) | ||
1664 | { | ||
1665 | return ECORE_CON_SSL_ERROR_NONE; | ||
1666 | } | ||
1667 | |||
1668 | static Ecore_Con_Ssl_Error | ||
1669 | _ecore_con_ssl_shutdown_none(void) | ||
1670 | { | ||
1671 | return ECORE_CON_SSL_ERROR_NONE; | ||
1672 | } | ||
1673 | |||
1674 | static Ecore_Con_Ssl_Error | ||
1675 | _ecore_con_ssl_server_prepare_none(Ecore_Con_Server *svr __UNUSED__, | ||
1676 | int ssl_type __UNUSED__) | ||
1677 | { | ||
1678 | return ECORE_CON_SSL_ERROR_NONE; | ||
1679 | } | ||
1680 | |||
1681 | 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__) | ||
1689 | { | ||
1690 | return ECORE_CON_SSL_ERROR_NOT_SUPPORTED; | ||
1691 | } | ||
1692 | |||
1693 | static Eina_Bool | ||
1694 | _ecore_con_ssl_server_cafile_add_none(Ecore_Con_Server *svr __UNUSED__, | ||
1695 | const char *ca_file __UNUSED__) | ||
1696 | { | ||
1697 | return EINA_FALSE; | ||
1698 | } | ||
1699 | |||
1700 | static Eina_Bool | ||
1701 | _ecore_con_ssl_server_cert_add_none(Ecore_Con_Server *svr __UNUSED__, | ||
1702 | const char *cert_file __UNUSED__) | ||
1703 | { | ||
1704 | return EINA_FALSE; | ||
1705 | } | ||
1706 | |||
1707 | static Eina_Bool | ||
1708 | _ecore_con_ssl_server_privkey_add_none(Ecore_Con_Server *svr __UNUSED__, | ||
1709 | const char *key_file __UNUSED__) | ||
1710 | { | ||
1711 | return EINA_FALSE; | ||
1712 | } | ||
1713 | |||
1714 | static Eina_Bool | ||
1715 | _ecore_con_ssl_server_crl_add_none(Ecore_Con_Server *svr __UNUSED__, | ||
1716 | const char *crl_file __UNUSED__) | ||
1717 | { | ||
1718 | return EINA_FALSE; | ||
1719 | } | ||
1720 | |||
1721 | static Ecore_Con_Ssl_Error | ||
1722 | _ecore_con_ssl_server_shutdown_none(Ecore_Con_Server *svr __UNUSED__) | ||
1723 | { | ||
1724 | return ECORE_CON_SSL_ERROR_NOT_SUPPORTED; | ||
1725 | } | ||
1726 | |||
1727 | static int | ||
1728 | _ecore_con_ssl_server_read_none(Ecore_Con_Server *svr __UNUSED__, | ||
1729 | unsigned char *buf __UNUSED__, | ||
1730 | int size __UNUSED__) | ||
1731 | { | ||
1732 | return -1; | ||
1733 | } | ||
1734 | |||
1735 | static int | ||
1736 | _ecore_con_ssl_server_write_none(Ecore_Con_Server *svr __UNUSED__, | ||
1737 | const unsigned char *buf __UNUSED__, | ||
1738 | int size __UNUSED__) | ||
1739 | { | ||
1740 | return -1; | ||
1741 | } | ||
1742 | |||
1743 | 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__) | ||
1751 | { | ||
1752 | return ECORE_CON_SSL_ERROR_NOT_SUPPORTED; | ||
1753 | } | ||
1754 | |||
1755 | static Ecore_Con_Ssl_Error | ||
1756 | _ecore_con_ssl_client_shutdown_none(Ecore_Con_Client *cl __UNUSED__) | ||
1757 | { | ||
1758 | return ECORE_CON_SSL_ERROR_NOT_SUPPORTED; | ||
1759 | } | ||
1760 | |||
1761 | static int | ||
1762 | _ecore_con_ssl_client_read_none(Ecore_Con_Client *cl __UNUSED__, | ||
1763 | unsigned char *buf __UNUSED__, | ||
1764 | int size __UNUSED__) | ||
1765 | { | ||
1766 | return -1; | ||
1767 | } | ||
1768 | |||
1769 | static int | ||
1770 | _ecore_con_ssl_client_write_none(Ecore_Con_Client *cl __UNUSED__, | ||
1771 | const unsigned char *buf __UNUSED__, | ||
1772 | int size __UNUSED__) | ||
1773 | { | ||
1774 | return -1; | ||
1775 | } | ||
1776 | |||
1777 | #endif | ||