diff options
Diffstat (limited to 'libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c')
-rw-r--r-- | libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c | 2113 |
1 files changed, 0 insertions, 2113 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 deleted file mode 100644 index cd8b9c6..0000000 --- a/libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c +++ /dev/null | |||
@@ -1,2113 +0,0 @@ | |||
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 <sys/stat.h> | ||
20 | #include "Ecore.h" | ||
21 | #include "ecore_con_private.h" | ||
22 | |||
23 | EAPI int ECORE_CON_EVENT_CLIENT_UPGRADE = 0; | ||
24 | EAPI int ECORE_CON_EVENT_SERVER_UPGRADE = 0; | ||
25 | |||
26 | static int _init_con_ssl_init_count = 0; | ||
27 | |||
28 | #ifdef USE_GNUTLS | ||
29 | # ifdef EINA_HAVE_THREADS | ||
30 | GCRY_THREAD_OPTION_PTHREAD_IMPL; | ||
31 | # endif | ||
32 | |||
33 | static int _client_connected = 0; | ||
34 | |||
35 | # define SSL_SUFFIX(ssl_func) ssl_func ## _gnutls | ||
36 | # define _ECORE_CON_SSL_AVAILABLE 1 | ||
37 | |||
38 | #elif USE_OPENSSL | ||
39 | |||
40 | # define SSL_SUFFIX(ssl_func) ssl_func ## _openssl | ||
41 | # define _ECORE_CON_SSL_AVAILABLE 2 | ||
42 | |||
43 | #else | ||
44 | # define SSL_SUFFIX(ssl_func) ssl_func ## _none | ||
45 | # define _ECORE_CON_SSL_AVAILABLE 0 | ||
46 | |||
47 | #endif | ||
48 | |||
49 | #if USE_GNUTLS | ||
50 | static void | ||
51 | _gnutls_print_errors(void *conn, int type, int ret) | ||
52 | { | ||
53 | char buf[1024]; | ||
54 | |||
55 | if (!ret) return; | ||
56 | |||
57 | snprintf(buf, sizeof(buf), "GNUTLS error: %s - %s", gnutls_strerror_name(ret), gnutls_strerror(ret)); | ||
58 | if (type == ECORE_CON_EVENT_CLIENT_ERROR) | ||
59 | ecore_con_event_client_error(conn, buf); | ||
60 | else | ||
61 | ecore_con_event_server_error(conn, buf); | ||
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 | |||
84 | #ifdef ISCOMFITOR | ||
85 | static void | ||
86 | _gnutls_log_func(int level, | ||
87 | const char *str) | ||
88 | { | ||
89 | char buf[128]; | ||
90 | strncat(buf, str, strlen(str) - 1); | ||
91 | DBG("|<%d>| %s", level, buf); | ||
92 | } | ||
93 | #endif | ||
94 | |||
95 | static const char * | ||
96 | SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_description_t status) | ||
97 | { | ||
98 | switch (status) | ||
99 | { | ||
100 | case GNUTLS_HANDSHAKE_HELLO_REQUEST: | ||
101 | return "Hello request"; | ||
102 | |||
103 | case GNUTLS_HANDSHAKE_CLIENT_HELLO: | ||
104 | return "Client hello"; | ||
105 | |||
106 | case GNUTLS_HANDSHAKE_SERVER_HELLO: | ||
107 | return "Server hello"; | ||
108 | |||
109 | case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET: | ||
110 | return "New session ticket"; | ||
111 | |||
112 | case GNUTLS_HANDSHAKE_CERTIFICATE_PKT: | ||
113 | return "Certificate packet"; | ||
114 | |||
115 | case GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE: | ||
116 | return "Server key exchange"; | ||
117 | |||
118 | case GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST: | ||
119 | return "Certificate request"; | ||
120 | |||
121 | case GNUTLS_HANDSHAKE_SERVER_HELLO_DONE: | ||
122 | return "Server hello done"; | ||
123 | |||
124 | case GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY: | ||
125 | return "Certificate verify"; | ||
126 | |||
127 | case GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE: | ||
128 | return "Client key exchange"; | ||
129 | |||
130 | case GNUTLS_HANDSHAKE_FINISHED: | ||
131 | return "Finished"; | ||
132 | |||
133 | case GNUTLS_HANDSHAKE_SUPPLEMENTAL: | ||
134 | return "Supplemental"; | ||
135 | } | ||
136 | return NULL; | ||
137 | } | ||
138 | |||
139 | #elif USE_OPENSSL | ||
140 | |||
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 | ||
321 | _openssl_print_errors(void *conn, int type) | ||
322 | { | ||
323 | char buf[1024]; | ||
324 | do | ||
325 | { | ||
326 | unsigned long err; | ||
327 | |||
328 | err = ERR_get_error(); | ||
329 | if (!err) break; | ||
330 | snprintf(buf, sizeof(buf), "OpenSSL error: %s", ERR_reason_error_string(err)); | ||
331 | if (type == ECORE_CON_EVENT_CLIENT_ERROR) | ||
332 | ecore_con_event_client_error(conn, buf); | ||
333 | else | ||
334 | ecore_con_event_server_error(conn, buf); | ||
335 | |||
336 | } while (1); | ||
337 | } | ||
338 | |||
339 | static Eina_Bool | ||
340 | _openssl_name_verify(const char *name, const char *svrname) | ||
341 | { | ||
342 | if (name[0] == '*') | ||
343 | { | ||
344 | /* we allow *.domain.TLD with a wildcard, but nothing else */ | ||
345 | const char *p, *s; | ||
346 | |||
347 | EINA_SAFETY_ON_TRUE_RETURN_VAL((name[1] != '.') || (!name[2]), EINA_FALSE); | ||
348 | p = strchr(name + 1, '*'); | ||
349 | EINA_SAFETY_ON_TRUE_RETURN_VAL(!!p, EINA_FALSE); | ||
350 | /* verify that we have a domain of at least *.X.TLD and not *.TLD */ | ||
351 | p = strchr(name + 2, '.'); | ||
352 | EINA_SAFETY_ON_TRUE_RETURN_VAL(!p, EINA_FALSE); | ||
353 | s = strchr(svrname, '.'); | ||
354 | EINA_SAFETY_ON_TRUE_RETURN_VAL(!s, EINA_FALSE); | ||
355 | /* same as above for the stored name */ | ||
356 | EINA_SAFETY_ON_TRUE_RETURN_VAL(!strchr(s + 1, '.'), EINA_FALSE); | ||
357 | if (strcasecmp(s, name + 1)) | ||
358 | { | ||
359 | ERR("%s != %s", s, name + 1); | ||
360 | return EINA_FALSE; | ||
361 | } | ||
362 | } | ||
363 | else | ||
364 | if (strcasecmp(name, svrname)) | ||
365 | { | ||
366 | ERR("%s != %s", name, svrname); | ||
367 | return EINA_FALSE; | ||
368 | } | ||
369 | return EINA_TRUE; | ||
370 | } | ||
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 | |||
408 | #endif | ||
409 | |||
410 | #define SSL_ERROR_CHECK_GOTO_ERROR(X) \ | ||
411 | do \ | ||
412 | { \ | ||
413 | if ((X)) \ | ||
414 | { \ | ||
415 | ERR("Error at %s:%s:%d!", __FILE__, __PRETTY_FUNCTION__, __LINE__); \ | ||
416 | goto error; \ | ||
417 | } \ | ||
418 | } \ | ||
419 | while (0) | ||
420 | |||
421 | static Ecore_Con_Ssl_Error | ||
422 | SSL_SUFFIX(_ecore_con_ssl_init) (void); | ||
423 | static Ecore_Con_Ssl_Error | ||
424 | SSL_SUFFIX(_ecore_con_ssl_shutdown) (void); | ||
425 | |||
426 | static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_cafile_add) (Ecore_Con_Server * svr, const char *ca_file); | ||
427 | static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_crl_add) (Ecore_Con_Server * svr, const char *crl_file); | ||
428 | static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_cert_add) (Ecore_Con_Server * svr, const char *cert); | ||
429 | static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_privkey_add) (Ecore_Con_Server * svr, const char *key_file); | ||
430 | |||
431 | static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_server_prepare) (Ecore_Con_Server * svr, int ssl_type); | ||
432 | static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_server_init) (Ecore_Con_Server * svr); | ||
433 | static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_server_shutdown) (Ecore_Con_Server *svr); | ||
434 | static int SSL_SUFFIX(_ecore_con_ssl_server_read) (Ecore_Con_Server *svr, unsigned char *buf, int size); | ||
435 | static int SSL_SUFFIX(_ecore_con_ssl_server_write) (Ecore_Con_Server *svr, const unsigned char *buf, int size); | ||
436 | |||
437 | static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_client_init) (Ecore_Con_Client * cl); | ||
438 | static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_client_shutdown) (Ecore_Con_Client *cl); | ||
439 | static int SSL_SUFFIX(_ecore_con_ssl_client_read) (Ecore_Con_Client * cl, | ||
440 | unsigned char *buf, int size); | ||
441 | static int SSL_SUFFIX(_ecore_con_ssl_client_write) (Ecore_Con_Client * cl, | ||
442 | const unsigned char *buf, int size); | ||
443 | |||
444 | /* | ||
445 | * General SSL API | ||
446 | */ | ||
447 | |||
448 | Ecore_Con_Ssl_Error | ||
449 | ecore_con_ssl_init(void) | ||
450 | { | ||
451 | if (!_init_con_ssl_init_count++) | ||
452 | { | ||
453 | SSL_SUFFIX(_ecore_con_ssl_init) (); | ||
454 | #if _ECORE_CON_SSL_AVAILABLE != 0 | ||
455 | ECORE_CON_EVENT_CLIENT_UPGRADE = ecore_event_type_new(); | ||
456 | ECORE_CON_EVENT_SERVER_UPGRADE = ecore_event_type_new(); | ||
457 | #endif | ||
458 | } | ||
459 | |||
460 | return _init_con_ssl_init_count; | ||
461 | } | ||
462 | |||
463 | Ecore_Con_Ssl_Error | ||
464 | ecore_con_ssl_shutdown(void) | ||
465 | { | ||
466 | if (!--_init_con_ssl_init_count) | ||
467 | SSL_SUFFIX(_ecore_con_ssl_shutdown) (); | ||
468 | |||
469 | return _init_con_ssl_init_count; | ||
470 | } | ||
471 | |||
472 | Ecore_Con_Ssl_Error | ||
473 | ecore_con_ssl_server_prepare(Ecore_Con_Server *svr, | ||
474 | int ssl_type) | ||
475 | { | ||
476 | if (!ssl_type) | ||
477 | return ECORE_CON_SSL_ERROR_NONE; | ||
478 | return SSL_SUFFIX(_ecore_con_ssl_server_prepare) (svr, ssl_type); | ||
479 | } | ||
480 | |||
481 | Ecore_Con_Ssl_Error | ||
482 | ecore_con_ssl_server_init(Ecore_Con_Server *svr) | ||
483 | { | ||
484 | if (!(svr->type & ECORE_CON_SSL)) | ||
485 | return ECORE_CON_SSL_ERROR_NONE; | ||
486 | return SSL_SUFFIX(_ecore_con_ssl_server_init) (svr); | ||
487 | } | ||
488 | |||
489 | Ecore_Con_Ssl_Error | ||
490 | ecore_con_ssl_server_shutdown(Ecore_Con_Server *svr) | ||
491 | { | ||
492 | if (!(svr->type & ECORE_CON_SSL)) | ||
493 | return ECORE_CON_SSL_ERROR_NONE; | ||
494 | return SSL_SUFFIX(_ecore_con_ssl_server_shutdown) (svr); | ||
495 | } | ||
496 | |||
497 | int | ||
498 | ecore_con_ssl_server_read(Ecore_Con_Server *svr, | ||
499 | unsigned char *buf, | ||
500 | int size) | ||
501 | { | ||
502 | return SSL_SUFFIX(_ecore_con_ssl_server_read) (svr, buf, size); | ||
503 | } | ||
504 | |||
505 | int | ||
506 | ecore_con_ssl_server_write(Ecore_Con_Server *svr, | ||
507 | const unsigned char *buf, | ||
508 | int size) | ||
509 | { | ||
510 | return SSL_SUFFIX(_ecore_con_ssl_server_write) (svr, buf, size); | ||
511 | } | ||
512 | |||
513 | Ecore_Con_Ssl_Error | ||
514 | ecore_con_ssl_client_init(Ecore_Con_Client *cl) | ||
515 | { | ||
516 | if (!(cl->host_server->type & ECORE_CON_SSL)) | ||
517 | return ECORE_CON_SSL_ERROR_NONE; | ||
518 | return SSL_SUFFIX(_ecore_con_ssl_client_init) (cl); | ||
519 | } | ||
520 | |||
521 | Ecore_Con_Ssl_Error | ||
522 | ecore_con_ssl_client_shutdown(Ecore_Con_Client *cl) | ||
523 | { | ||
524 | if (!(cl->host_server->type & ECORE_CON_SSL)) | ||
525 | return ECORE_CON_SSL_ERROR_NONE; | ||
526 | return SSL_SUFFIX(_ecore_con_ssl_client_shutdown) (cl); | ||
527 | } | ||
528 | |||
529 | int | ||
530 | ecore_con_ssl_client_read(Ecore_Con_Client *cl, | ||
531 | unsigned char *buf, | ||
532 | int size) | ||
533 | { | ||
534 | return SSL_SUFFIX(_ecore_con_ssl_client_read) (cl, buf, size); | ||
535 | } | ||
536 | |||
537 | int | ||
538 | ecore_con_ssl_client_write(Ecore_Con_Client *cl, | ||
539 | const unsigned char *buf, | ||
540 | int size) | ||
541 | { | ||
542 | return SSL_SUFFIX(_ecore_con_ssl_client_write) (cl, buf, size); | ||
543 | } | ||
544 | |||
545 | /** | ||
546 | * Returns if SSL support is available | ||
547 | * @return 1 if SSL is available and provided by gnutls, 2 if provided by openssl, | ||
548 | * 0 if it is not available. | ||
549 | * @ingroup Ecore_Con_Client_Group | ||
550 | */ | ||
551 | EAPI int | ||
552 | ecore_con_ssl_available_get(void) | ||
553 | { | ||
554 | return _ECORE_CON_SSL_AVAILABLE; | ||
555 | } | ||
556 | |||
557 | /** | ||
558 | * @addtogroup Ecore_Con_SSL_Group Ecore Connection SSL Functions | ||
559 | * | ||
560 | * Functions that operate on Ecore connection objects pertaining to SSL. | ||
561 | * | ||
562 | * @{ | ||
563 | */ | ||
564 | |||
565 | /** | ||
566 | * @brief Enable certificate verification on a server object | ||
567 | * | ||
568 | * Call this function on a server object before main loop has started | ||
569 | * to enable verification of certificates against loaded certificates. | ||
570 | * @param svr The server object | ||
571 | */ | ||
572 | EAPI void | ||
573 | ecore_con_ssl_server_verify(Ecore_Con_Server *svr) | ||
574 | { | ||
575 | if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) | ||
576 | { | ||
577 | ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_ssl_server_verify"); | ||
578 | return; | ||
579 | } | ||
580 | svr->verify = EINA_TRUE; | ||
581 | } | ||
582 | |||
583 | /** | ||
584 | * @brief Enable hostname-based certificate verification on a server object | ||
585 | * | ||
586 | * Call this function on a server object before main loop has started | ||
587 | * to enable verification of certificates using ONLY their hostnames. | ||
588 | * @param svr The server object | ||
589 | * @note This function has no effect when used on a listening server created by | ||
590 | * ecore_con_server_add | ||
591 | * @since 1.1 | ||
592 | */ | ||
593 | EAPI void | ||
594 | ecore_con_ssl_server_verify_basic(Ecore_Con_Server *svr) | ||
595 | { | ||
596 | if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) | ||
597 | { | ||
598 | ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, __func__); | ||
599 | return; | ||
600 | } | ||
601 | svr->verify_basic = EINA_TRUE; | ||
602 | } | ||
603 | |||
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 | /** | ||
650 | * @brief Add an ssl certificate for use in ecore_con functions. | ||
651 | * | ||
652 | * Use this function to add a SSL PEM certificate. | ||
653 | * Simply specify the cert here to use it in the server object for connecting or listening. | ||
654 | * If there is an error loading the certificate, an error will automatically be logged. | ||
655 | * @param svr The server object | ||
656 | * @param cert The path to the certificate. | ||
657 | * @return EINA_FALSE if the file cannot be loaded, otherwise EINA_TRUE. | ||
658 | */ | ||
659 | |||
660 | EAPI Eina_Bool | ||
661 | ecore_con_ssl_server_cert_add(Ecore_Con_Server *svr, | ||
662 | const char *cert) | ||
663 | { | ||
664 | if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) | ||
665 | { | ||
666 | ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_ssl_server_cert_add"); | ||
667 | return EINA_FALSE; | ||
668 | } | ||
669 | |||
670 | if (!svr->ssl_prepared) | ||
671 | { | ||
672 | svr->use_cert = EINA_TRUE; | ||
673 | svr->type |= ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT; | ||
674 | if (ecore_con_ssl_server_prepare(svr, svr->type & ECORE_CON_SSL)) | ||
675 | return EINA_FALSE; | ||
676 | } | ||
677 | |||
678 | return SSL_SUFFIX(_ecore_con_ssl_server_cert_add) (svr, cert); | ||
679 | } | ||
680 | |||
681 | /** | ||
682 | * @brief Add an ssl CA file for use in ecore_con functions. | ||
683 | * | ||
684 | * Use this function to add a SSL PEM CA file. | ||
685 | * Simply specify the file here to use it in the server object for connecting or listening. | ||
686 | * If there is an error loading the CAs, an error will automatically be logged. | ||
687 | * @param svr The server object | ||
688 | * @param ca_file The path to the CA file. | ||
689 | * @return EINA_FALSE if the file cannot be loaded, otherwise EINA_TRUE. | ||
690 | * @note since 1.2, this function can load directores | ||
691 | */ | ||
692 | |||
693 | EAPI Eina_Bool | ||
694 | ecore_con_ssl_server_cafile_add(Ecore_Con_Server *svr, | ||
695 | const char *ca_file) | ||
696 | { | ||
697 | if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) | ||
698 | { | ||
699 | ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_ssl_server_cafile_add"); | ||
700 | return EINA_FALSE; | ||
701 | } | ||
702 | |||
703 | if (!svr->ssl_prepared) | ||
704 | { | ||
705 | svr->use_cert = EINA_TRUE; | ||
706 | svr->type |= ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT; | ||
707 | if (ecore_con_ssl_server_prepare(svr, svr->type & ECORE_CON_SSL)) | ||
708 | return EINA_FALSE; | ||
709 | } | ||
710 | |||
711 | return SSL_SUFFIX(_ecore_con_ssl_server_cafile_add) (svr, ca_file); | ||
712 | } | ||
713 | |||
714 | /** | ||
715 | * @brief Add an ssl private key for use in ecore_con functions. | ||
716 | * | ||
717 | * Use this function to add a SSL PEM private key | ||
718 | * Simply specify the key file here to use it in the server object for connecting or listening. | ||
719 | * If there is an error loading the key, an error will automatically be logged. | ||
720 | * @param key_file The path to the key file. | ||
721 | * @return EINA_FALSE if the file cannot be loaded, | ||
722 | * otherwise EINA_TRUE. | ||
723 | */ | ||
724 | |||
725 | EAPI Eina_Bool | ||
726 | ecore_con_ssl_server_privkey_add(Ecore_Con_Server *svr, | ||
727 | const char *key_file) | ||
728 | { | ||
729 | if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) | ||
730 | { | ||
731 | ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_ssl_server_privkey_add"); | ||
732 | return EINA_FALSE; | ||
733 | } | ||
734 | |||
735 | if (!svr->ssl_prepared) | ||
736 | { | ||
737 | svr->use_cert = EINA_TRUE; | ||
738 | svr->type |= ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT; | ||
739 | if (ecore_con_ssl_server_prepare(svr, svr->type & ECORE_CON_SSL)) | ||
740 | return EINA_FALSE; | ||
741 | } | ||
742 | |||
743 | return SSL_SUFFIX(_ecore_con_ssl_server_privkey_add) (svr, key_file); | ||
744 | } | ||
745 | |||
746 | /** | ||
747 | * @brief Add an ssl CRL for use in ecore_con functions. | ||
748 | * | ||
749 | * Use this function to add a SSL PEM CRL file | ||
750 | * Simply specify the CRL file here to use it in the server object for connecting or listening. | ||
751 | * If there is an error loading the CRL, an error will automatically be logged. | ||
752 | * @param svr The server object | ||
753 | * @param crl_file The path to the CRL file. | ||
754 | * @return EINA_FALSE if the file cannot be loaded, | ||
755 | * otherwise EINA_TRUE. | ||
756 | */ | ||
757 | |||
758 | EAPI Eina_Bool | ||
759 | ecore_con_ssl_server_crl_add(Ecore_Con_Server *svr, | ||
760 | const char *crl_file) | ||
761 | { | ||
762 | if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) | ||
763 | { | ||
764 | ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_ssl_server_crl_add"); | ||
765 | return EINA_FALSE; | ||
766 | } | ||
767 | |||
768 | if (!svr->ssl_prepared) | ||
769 | { | ||
770 | svr->use_cert = EINA_TRUE; | ||
771 | svr->type |= ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT; | ||
772 | if (ecore_con_ssl_server_prepare(svr, svr->type & ECORE_CON_SSL)) | ||
773 | return EINA_FALSE; | ||
774 | } | ||
775 | |||
776 | return SSL_SUFFIX(_ecore_con_ssl_server_crl_add) (svr, crl_file); | ||
777 | } | ||
778 | |||
779 | /** | ||
780 | * @brief Upgrade a connection to a specified level of encryption | ||
781 | * | ||
782 | * Use this function to begin an SSL handshake on a connection (STARTTLS or similar). | ||
783 | * Once the upgrade has been completed, an ECORE_CON_EVENT_SERVER_UPGRADE event will be emitted. | ||
784 | * The connection should be treated as disconnected until the next event. | ||
785 | * @param svr The server object | ||
786 | * @param ssl_type The SSL connection type (ONLY). | ||
787 | * @return EINA_FALSE if the connection cannot be upgraded, otherwise EINA_TRUE. | ||
788 | * @note This function is NEVER to be used on a server object created with ecore_con_server_add | ||
789 | * @warning Setting a wrong value for @p compl_type WILL mess up your program. | ||
790 | * @since 1.1 | ||
791 | */ | ||
792 | |||
793 | EAPI Eina_Bool | ||
794 | ecore_con_ssl_server_upgrade(Ecore_Con_Server *svr, Ecore_Con_Type ssl_type) | ||
795 | { | ||
796 | if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) | ||
797 | { | ||
798 | ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, __func__); | ||
799 | return EINA_FALSE; | ||
800 | } | ||
801 | #if _ECORE_CON_SSL_AVAILABLE == 0 | ||
802 | return EINA_FALSE; | ||
803 | #endif | ||
804 | |||
805 | if (!svr->ssl_prepared) | ||
806 | { | ||
807 | if (ecore_con_ssl_server_prepare(svr, ssl_type)) | ||
808 | return EINA_FALSE; | ||
809 | } | ||
810 | if (!svr->use_cert) | ||
811 | svr->type |= ssl_type; | ||
812 | svr->upgrade = EINA_TRUE; | ||
813 | svr->handshaking = EINA_TRUE; | ||
814 | svr->ssl_state = ECORE_CON_SSL_STATE_INIT; | ||
815 | return !SSL_SUFFIX(_ecore_con_ssl_server_init) (svr); | ||
816 | } | ||
817 | |||
818 | /** | ||
819 | * @brief Upgrade a connection to a specified level of encryption | ||
820 | * | ||
821 | * Use this function to begin an SSL handshake on a connection (STARTTLS or similar). | ||
822 | * Once the upgrade has been completed, an ECORE_CON_EVENT_CLIENT_UPGRADE event will be emitted. | ||
823 | * The connection should be treated as disconnected until the next event. | ||
824 | * @param cl The client object | ||
825 | * @param ssl_type The SSL connection type (ONLY). | ||
826 | * @return EINA_FALSE if the connection cannot be upgraded, otherwise EINA_TRUE. | ||
827 | * @warning Setting a wrong value for @p compl_type WILL mess up your program. | ||
828 | * @since 1.1 | ||
829 | */ | ||
830 | |||
831 | EAPI Eina_Bool | ||
832 | ecore_con_ssl_client_upgrade(Ecore_Con_Client *cl, Ecore_Con_Type ssl_type) | ||
833 | { | ||
834 | if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT)) | ||
835 | { | ||
836 | ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, __func__); | ||
837 | return EINA_FALSE; | ||
838 | } | ||
839 | #if _ECORE_CON_SSL_AVAILABLE == 0 | ||
840 | return EINA_FALSE; | ||
841 | #endif | ||
842 | |||
843 | if (!cl->host_server->ssl_prepared) | ||
844 | { | ||
845 | if (ecore_con_ssl_server_prepare(cl->host_server, ssl_type)) | ||
846 | return EINA_FALSE; | ||
847 | } | ||
848 | if (!cl->host_server->use_cert) | ||
849 | cl->host_server->type |= ssl_type; | ||
850 | cl->upgrade = EINA_TRUE; | ||
851 | cl->host_server->upgrade = EINA_TRUE; | ||
852 | cl->handshaking = EINA_TRUE; | ||
853 | cl->ssl_state = ECORE_CON_SSL_STATE_INIT; | ||
854 | return SSL_SUFFIX(_ecore_con_ssl_client_init) (cl); | ||
855 | } | ||
856 | |||
857 | /** | ||
858 | * @} | ||
859 | */ | ||
860 | |||
861 | #if USE_GNUTLS | ||
862 | |||
863 | /* | ||
864 | * GnuTLS | ||
865 | */ | ||
866 | |||
867 | static Ecore_Con_Ssl_Error | ||
868 | _ecore_con_ssl_init_gnutls(void) | ||
869 | { | ||
870 | #ifdef EINA_HAVE_THREADS | ||
871 | if (gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread)) | ||
872 | WRN("YOU ARE USING PTHREADS, BUT I CANNOT INITIALIZE THREADSAFE GCRYPT OPERATIONS!"); | ||
873 | #endif | ||
874 | if (gnutls_global_init()) | ||
875 | return ECORE_CON_SSL_ERROR_INIT_FAILED; | ||
876 | |||
877 | #ifdef ISCOMFITOR | ||
878 | if (eina_log_domain_level_check(_ecore_con_log_dom, EINA_LOG_LEVEL_DBG)) | ||
879 | { | ||
880 | gnutls_global_set_log_level(9); | ||
881 | gnutls_global_set_log_function(_gnutls_log_func); | ||
882 | } | ||
883 | #endif | ||
884 | return ECORE_CON_SSL_ERROR_NONE; | ||
885 | } | ||
886 | |||
887 | static Ecore_Con_Ssl_Error | ||
888 | _ecore_con_ssl_shutdown_gnutls(void) | ||
889 | { | ||
890 | gnutls_global_deinit(); | ||
891 | |||
892 | return ECORE_CON_SSL_ERROR_NONE; | ||
893 | } | ||
894 | |||
895 | static Ecore_Con_Ssl_Error | ||
896 | _ecore_con_ssl_server_prepare_gnutls(Ecore_Con_Server *svr, | ||
897 | int ssl_type) | ||
898 | { | ||
899 | int ret; | ||
900 | |||
901 | if (ssl_type & ECORE_CON_USE_SSL2) | ||
902 | return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED; | ||
903 | |||
904 | switch (ssl_type) | ||
905 | { | ||
906 | case ECORE_CON_USE_SSL3: | ||
907 | case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT: | ||
908 | case ECORE_CON_USE_TLS: | ||
909 | case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT: | ||
910 | case ECORE_CON_USE_MIXED: | ||
911 | case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT: | ||
912 | break; | ||
913 | |||
914 | default: | ||
915 | return ECORE_CON_SSL_ERROR_NONE; | ||
916 | } | ||
917 | |||
918 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_certificate_allocate_credentials(&svr->cert)); | ||
919 | |||
920 | if (svr->use_cert) | ||
921 | { | ||
922 | if (svr->created) | ||
923 | { | ||
924 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_dh_params_init(&svr->dh_params)); | ||
925 | INF("Generating DH params"); | ||
926 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_dh_params_generate2(svr->dh_params, 1024)); | ||
927 | |||
928 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_anon_allocate_server_credentials(&svr->anoncred_s)); | ||
929 | /* TODO: implement PSK */ | ||
930 | // SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_psk_allocate_server_credentials(&svr->pskcred_s)); | ||
931 | |||
932 | gnutls_anon_set_server_dh_params(svr->anoncred_s, svr->dh_params); | ||
933 | gnutls_certificate_set_dh_params(svr->cert, svr->dh_params); | ||
934 | //gnutls_psk_set_server_dh_params(svr->pskcred_s, svr->dh_params); | ||
935 | INF("DH params successfully generated and applied!"); | ||
936 | } | ||
937 | else | ||
938 | { | ||
939 | //SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_psk_allocate_client_credentials(&svr->pskcred_c)); | ||
940 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_anon_allocate_client_credentials(&svr->anoncred_c)); | ||
941 | } | ||
942 | } | ||
943 | |||
944 | svr->ssl_prepared = EINA_TRUE; | ||
945 | return ECORE_CON_SSL_ERROR_NONE; | ||
946 | |||
947 | error: | ||
948 | _gnutls_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR, ret); | ||
949 | _ecore_con_ssl_server_shutdown_gnutls(svr); | ||
950 | return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; | ||
951 | } | ||
952 | |||
953 | |||
954 | static Ecore_Con_Ssl_Error | ||
955 | _ecore_con_ssl_server_init_gnutls(Ecore_Con_Server *svr) | ||
956 | { | ||
957 | const gnutls_datum_t *cert_list; | ||
958 | unsigned int iter, cert_list_size; | ||
959 | gnutls_x509_crt_t cert = NULL; | ||
960 | 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"; | ||
961 | int ret = 0; | ||
962 | |||
963 | switch (svr->ssl_state) | ||
964 | { | ||
965 | case ECORE_CON_SSL_STATE_DONE: | ||
966 | return ECORE_CON_SSL_ERROR_NONE; | ||
967 | |||
968 | case ECORE_CON_SSL_STATE_INIT: | ||
969 | if (svr->type & ECORE_CON_USE_SSL2) /* not supported because of security issues */ | ||
970 | return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED; | ||
971 | |||
972 | switch (svr->type & ECORE_CON_SSL) | ||
973 | { | ||
974 | case ECORE_CON_USE_SSL3: | ||
975 | case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT: | ||
976 | 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"; | ||
977 | break; | ||
978 | |||
979 | case ECORE_CON_USE_TLS: | ||
980 | case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT: | ||
981 | 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"; | ||
982 | break; | ||
983 | |||
984 | case ECORE_CON_USE_MIXED: | ||
985 | case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT: | ||
986 | break; | ||
987 | |||
988 | default: | ||
989 | return ECORE_CON_SSL_ERROR_NONE; | ||
990 | } | ||
991 | |||
992 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_init(&svr->session, GNUTLS_CLIENT)); | ||
993 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_enable_client(svr->session)); | ||
994 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_server_name_set(svr->session, GNUTLS_NAME_DNS, svr->name, strlen(svr->name))); | ||
995 | INF("Applying priority string: %s", priority); | ||
996 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_priority_set_direct(svr->session, priority, NULL)); | ||
997 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(svr->session, GNUTLS_CRD_CERTIFICATE, svr->cert)); | ||
998 | // SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(svr->session, GNUTLS_CRD_PSK, svr->pskcred_c)); | ||
999 | if (!svr->use_cert) | ||
1000 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(svr->session, GNUTLS_CRD_ANON, svr->anoncred_c)); | ||
1001 | |||
1002 | gnutls_dh_set_prime_bits(svr->session, 512); | ||
1003 | gnutls_transport_set_ptr(svr->session, (gnutls_transport_ptr_t)((intptr_t)svr->fd)); | ||
1004 | svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; | ||
1005 | |||
1006 | case ECORE_CON_SSL_STATE_HANDSHAKING: | ||
1007 | if (!svr->session) | ||
1008 | { | ||
1009 | DBG("Server was previously lost, going to error condition"); | ||
1010 | goto error; | ||
1011 | } | ||
1012 | ret = gnutls_handshake(svr->session); | ||
1013 | DBG("calling gnutls_handshake(): returned with '%s'", gnutls_strerror_name(ret)); | ||
1014 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_error_is_fatal(ret)); | ||
1015 | if (!ret) | ||
1016 | { | ||
1017 | svr->handshaking = EINA_FALSE; | ||
1018 | svr->ssl_state = ECORE_CON_SSL_STATE_DONE; | ||
1019 | } | ||
1020 | else | ||
1021 | { | ||
1022 | if (gnutls_record_get_direction(svr->session)) | ||
1023 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); | ||
1024 | else | ||
1025 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ); | ||
1026 | return ECORE_CON_SSL_ERROR_NONE; | ||
1027 | } | ||
1028 | |||
1029 | default: | ||
1030 | break; | ||
1031 | } | ||
1032 | |||
1033 | if ((!svr->verify) && (!svr->verify_basic)) | ||
1034 | /* not verifying certificates, so we're done! */ | ||
1035 | return ECORE_CON_SSL_ERROR_NONE; | ||
1036 | if (svr->verify) | ||
1037 | { | ||
1038 | /* use CRL/CA lists to verify */ | ||
1039 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_certificate_verify_peers2(svr->session, &iter)); | ||
1040 | if (iter & GNUTLS_CERT_INVALID) | ||
1041 | ERR("The certificate is not trusted."); | ||
1042 | else if (iter & GNUTLS_CERT_SIGNER_NOT_FOUND) | ||
1043 | ERR("The certificate hasn't got a known issuer."); | ||
1044 | else if (iter & GNUTLS_CERT_REVOKED) | ||
1045 | ERR("The certificate has been revoked."); | ||
1046 | else if (iter & GNUTLS_CERT_EXPIRED) | ||
1047 | ERR("The certificate has expired"); | ||
1048 | else if (iter & GNUTLS_CERT_NOT_ACTIVATED) | ||
1049 | ERR("The certificate is not yet activated"); | ||
1050 | |||
1051 | if (iter) | ||
1052 | goto error; | ||
1053 | } | ||
1054 | if (gnutls_certificate_type_get(svr->session) != GNUTLS_CRT_X509) | ||
1055 | { | ||
1056 | ERR("Warning: PGP certificates are not yet supported!"); | ||
1057 | goto error; | ||
1058 | } | ||
1059 | |||
1060 | SSL_ERROR_CHECK_GOTO_ERROR(!(cert_list = gnutls_certificate_get_peers(svr->session, &cert_list_size))); | ||
1061 | SSL_ERROR_CHECK_GOTO_ERROR(!cert_list_size); | ||
1062 | |||
1063 | _gnutls_print_session(cert_list, cert_list_size); | ||
1064 | |||
1065 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_init(&cert)); | ||
1066 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER)); | ||
1067 | |||
1068 | SSL_ERROR_CHECK_GOTO_ERROR(!gnutls_x509_crt_check_hostname(cert, svr->verify_name ?: svr->name)); | ||
1069 | gnutls_x509_crt_deinit(cert); | ||
1070 | DBG("SSL certificate verification succeeded!"); | ||
1071 | return ECORE_CON_SSL_ERROR_NONE; | ||
1072 | |||
1073 | error: | ||
1074 | _gnutls_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR, ret); | ||
1075 | if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) || (ret == GNUTLS_E_FATAL_ALERT_RECEIVED)) | ||
1076 | ERR("Also received alert: %s", gnutls_alert_get_name(gnutls_alert_get(svr->session))); | ||
1077 | if (svr->session && (svr->ssl_state != ECORE_CON_SSL_STATE_DONE)) | ||
1078 | { | ||
1079 | ERR("last out: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_out(svr->session))); | ||
1080 | ERR("last in: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_in(svr->session))); | ||
1081 | } | ||
1082 | if (cert) | ||
1083 | gnutls_x509_crt_deinit(cert); | ||
1084 | _ecore_con_ssl_server_shutdown_gnutls(svr); | ||
1085 | return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; | ||
1086 | } | ||
1087 | |||
1088 | static Eina_Bool | ||
1089 | _ecore_con_ssl_server_cafile_add_gnutls(Ecore_Con_Server *svr, | ||
1090 | const char *ca_file) | ||
1091 | { | ||
1092 | struct stat st; | ||
1093 | Eina_Iterator *it; | ||
1094 | const char *file; | ||
1095 | Eina_Bool error = EINA_FALSE; | ||
1096 | |||
1097 | if (stat(ca_file, &st)) return EINA_FALSE; | ||
1098 | if (S_ISDIR(st.st_mode)) | ||
1099 | { | ||
1100 | it = eina_file_ls(ca_file); | ||
1101 | SSL_ERROR_CHECK_GOTO_ERROR(!it); | ||
1102 | EINA_ITERATOR_FOREACH(it, file) | ||
1103 | { | ||
1104 | if (!error) | ||
1105 | { | ||
1106 | if (gnutls_certificate_set_x509_trust_file(svr->cert, file, GNUTLS_X509_FMT_PEM) < 1) | ||
1107 | error++; | ||
1108 | } | ||
1109 | eina_stringshare_del(file); | ||
1110 | } | ||
1111 | eina_iterator_free(it); | ||
1112 | } | ||
1113 | else | ||
1114 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_certificate_set_x509_trust_file(svr->cert, ca_file, | ||
1115 | GNUTLS_X509_FMT_PEM) < 1); | ||
1116 | |||
1117 | return !error; | ||
1118 | error: | ||
1119 | ERR("Could not load CA file!"); | ||
1120 | return EINA_FALSE; | ||
1121 | } | ||
1122 | |||
1123 | static Eina_Bool | ||
1124 | _ecore_con_ssl_server_crl_add_gnutls(Ecore_Con_Server *svr, | ||
1125 | const char *crl_file) | ||
1126 | { | ||
1127 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_certificate_set_x509_crl_file(svr->cert, crl_file, | ||
1128 | GNUTLS_X509_FMT_PEM) < 1); | ||
1129 | |||
1130 | return EINA_TRUE; | ||
1131 | error: | ||
1132 | ERR("Could not load CRL file!"); | ||
1133 | return EINA_FALSE; | ||
1134 | } | ||
1135 | |||
1136 | static Eina_Bool | ||
1137 | _ecore_con_ssl_server_privkey_add_gnutls(Ecore_Con_Server *svr, | ||
1138 | const char *key_file) | ||
1139 | { | ||
1140 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_certificate_set_x509_key_file(svr->cert, svr->cert_file, key_file, | ||
1141 | GNUTLS_X509_FMT_PEM)); | ||
1142 | |||
1143 | return EINA_TRUE; | ||
1144 | error: | ||
1145 | ERR("Could not load certificate/key file!"); | ||
1146 | return EINA_FALSE; | ||
1147 | } | ||
1148 | |||
1149 | static Eina_Bool | ||
1150 | _ecore_con_ssl_server_cert_add_gnutls(Ecore_Con_Server *svr, | ||
1151 | const char *cert_file) | ||
1152 | { | ||
1153 | if (!(svr->cert_file = strdup(cert_file))) | ||
1154 | return EINA_FALSE; | ||
1155 | |||
1156 | return EINA_TRUE; | ||
1157 | } | ||
1158 | |||
1159 | static Ecore_Con_Ssl_Error | ||
1160 | _ecore_con_ssl_server_shutdown_gnutls(Ecore_Con_Server *svr) | ||
1161 | { | ||
1162 | if (svr->session) | ||
1163 | { | ||
1164 | gnutls_bye(svr->session, GNUTLS_SHUT_RDWR); | ||
1165 | gnutls_deinit(svr->session); | ||
1166 | } | ||
1167 | |||
1168 | free(svr->cert_file); | ||
1169 | svr->cert_file = NULL; | ||
1170 | if (svr->cert) | ||
1171 | gnutls_certificate_free_credentials(svr->cert); | ||
1172 | svr->cert = NULL; | ||
1173 | |||
1174 | if ((svr->type & ECORE_CON_SSL) && svr->created) | ||
1175 | { | ||
1176 | if (svr->dh_params) | ||
1177 | { | ||
1178 | gnutls_dh_params_deinit(svr->dh_params); | ||
1179 | svr->dh_params = NULL; | ||
1180 | } | ||
1181 | if (svr->anoncred_s) | ||
1182 | gnutls_anon_free_server_credentials(svr->anoncred_s); | ||
1183 | // if (svr->pskcred_s) | ||
1184 | // gnutls_psk_free_server_credentials(svr->pskcred_s); | ||
1185 | |||
1186 | svr->anoncred_s = NULL; | ||
1187 | svr->pskcred_s = NULL; | ||
1188 | } | ||
1189 | else if (svr->type & ECORE_CON_SSL) | ||
1190 | { | ||
1191 | if (svr->anoncred_c) | ||
1192 | gnutls_anon_free_client_credentials(svr->anoncred_c); | ||
1193 | // if (svr->pskcred_c) | ||
1194 | // gnutls_psk_free_client_credentials(svr->pskcred_c); | ||
1195 | |||
1196 | svr->anoncred_c = NULL; | ||
1197 | svr->pskcred_c = NULL; | ||
1198 | } | ||
1199 | |||
1200 | svr->session = NULL; | ||
1201 | |||
1202 | return ECORE_CON_SSL_ERROR_NONE; | ||
1203 | } | ||
1204 | |||
1205 | static int | ||
1206 | _ecore_con_ssl_server_read_gnutls(Ecore_Con_Server *svr, | ||
1207 | unsigned char *buf, | ||
1208 | int size) | ||
1209 | { | ||
1210 | int num; | ||
1211 | |||
1212 | if (svr->ssl_state == ECORE_CON_SSL_STATE_HANDSHAKING) | ||
1213 | { | ||
1214 | DBG("Continuing gnutls handshake"); | ||
1215 | if (!_ecore_con_ssl_server_init_gnutls(svr)) | ||
1216 | return 0; | ||
1217 | return -1; | ||
1218 | } | ||
1219 | |||
1220 | num = gnutls_record_recv(svr->session, buf, size); | ||
1221 | if (num > 0) | ||
1222 | return num; | ||
1223 | |||
1224 | if (num == GNUTLS_E_REHANDSHAKE) | ||
1225 | { | ||
1226 | WRN("Rehandshake request ignored"); | ||
1227 | return 0; | ||
1228 | |||
1229 | svr->handshaking = EINA_TRUE; | ||
1230 | svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; | ||
1231 | if (!_ecore_con_ssl_server_init_gnutls(svr)) | ||
1232 | return 0; | ||
1233 | } | ||
1234 | else if ((!gnutls_error_is_fatal(num)) && (num != GNUTLS_E_SUCCESS)) | ||
1235 | return 0; | ||
1236 | |||
1237 | return -1; | ||
1238 | } | ||
1239 | |||
1240 | static int | ||
1241 | _ecore_con_ssl_server_write_gnutls(Ecore_Con_Server *svr, | ||
1242 | const unsigned char *buf, | ||
1243 | int size) | ||
1244 | { | ||
1245 | int num; | ||
1246 | |||
1247 | if (svr->ssl_state == ECORE_CON_SSL_STATE_HANDSHAKING) | ||
1248 | { | ||
1249 | DBG("Continuing gnutls handshake"); | ||
1250 | if (!_ecore_con_ssl_server_init_gnutls(svr)) | ||
1251 | return 0; | ||
1252 | return -1; | ||
1253 | } | ||
1254 | |||
1255 | num = gnutls_record_send(svr->session, buf, size); | ||
1256 | if (num > 0) | ||
1257 | return num; | ||
1258 | |||
1259 | if (num == GNUTLS_E_REHANDSHAKE) | ||
1260 | { | ||
1261 | WRN("Rehandshake request ignored"); | ||
1262 | return 0; | ||
1263 | /* this is only partly functional I think? */ | ||
1264 | svr->handshaking = EINA_TRUE; | ||
1265 | svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; | ||
1266 | if (!_ecore_con_ssl_server_init_gnutls(svr)) | ||
1267 | return 0; | ||
1268 | } | ||
1269 | else if (!gnutls_error_is_fatal(num)) | ||
1270 | return 0; | ||
1271 | |||
1272 | return -1; | ||
1273 | } | ||
1274 | |||
1275 | static Ecore_Con_Ssl_Error | ||
1276 | _ecore_con_ssl_client_init_gnutls(Ecore_Con_Client *cl) | ||
1277 | { | ||
1278 | const gnutls_datum_t *cert_list; | ||
1279 | unsigned int iter, cert_list_size; | ||
1280 | 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"; | ||
1281 | int ret = 0; | ||
1282 | |||
1283 | switch (cl->ssl_state) | ||
1284 | { | ||
1285 | case ECORE_CON_SSL_STATE_DONE: | ||
1286 | return ECORE_CON_SSL_ERROR_NONE; | ||
1287 | |||
1288 | case ECORE_CON_SSL_STATE_INIT: | ||
1289 | if (cl->host_server->type & ECORE_CON_USE_SSL2) /* not supported because of security issues */ | ||
1290 | return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED; | ||
1291 | |||
1292 | switch (cl->host_server->type & ECORE_CON_SSL) | ||
1293 | { | ||
1294 | case ECORE_CON_USE_SSL3: | ||
1295 | case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT: | ||
1296 | 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"; | ||
1297 | break; | ||
1298 | |||
1299 | case ECORE_CON_USE_TLS: | ||
1300 | case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT: | ||
1301 | 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"; | ||
1302 | break; | ||
1303 | |||
1304 | case ECORE_CON_USE_MIXED: | ||
1305 | case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT: | ||
1306 | break; | ||
1307 | |||
1308 | default: | ||
1309 | return ECORE_CON_SSL_ERROR_NONE; | ||
1310 | } | ||
1311 | |||
1312 | _client_connected++; | ||
1313 | |||
1314 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_init(&cl->session, GNUTLS_SERVER)); | ||
1315 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_key_generate(&cl->session_ticket)); | ||
1316 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_enable_server(cl->session, &cl->session_ticket)); | ||
1317 | INF("Applying priority string: %s", priority); | ||
1318 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_priority_set_direct(cl->session, priority, NULL)); | ||
1319 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_CERTIFICATE, cl->host_server->cert)); | ||
1320 | // SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_PSK, cl->host_server->pskcred_s)); | ||
1321 | if (!cl->host_server->use_cert) | ||
1322 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_ANON, cl->host_server->anoncred_s)); | ||
1323 | |||
1324 | gnutls_certificate_server_set_request(cl->session, GNUTLS_CERT_REQUEST); | ||
1325 | |||
1326 | gnutls_dh_set_prime_bits(cl->session, 2048); | ||
1327 | gnutls_transport_set_ptr(cl->session, (gnutls_transport_ptr_t)((intptr_t)cl->fd)); | ||
1328 | cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; | ||
1329 | |||
1330 | case ECORE_CON_SSL_STATE_HANDSHAKING: | ||
1331 | if (!cl->session) | ||
1332 | { | ||
1333 | DBG("Client was previously lost, going to error condition"); | ||
1334 | goto error; | ||
1335 | } | ||
1336 | DBG("calling gnutls_handshake()"); | ||
1337 | ret = gnutls_handshake(cl->session); | ||
1338 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_error_is_fatal(ret)); | ||
1339 | |||
1340 | if (!ret) | ||
1341 | { | ||
1342 | cl->handshaking = EINA_FALSE; | ||
1343 | cl->ssl_state = ECORE_CON_SSL_STATE_DONE; | ||
1344 | } | ||
1345 | else | ||
1346 | { | ||
1347 | if (gnutls_record_get_direction(cl->session)) | ||
1348 | ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE); | ||
1349 | else | ||
1350 | ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ); | ||
1351 | return ECORE_CON_SSL_ERROR_NONE; | ||
1352 | } | ||
1353 | |||
1354 | default: | ||
1355 | break; | ||
1356 | } | ||
1357 | |||
1358 | if (!cl->host_server->verify) | ||
1359 | /* not verifying certificates, so we're done! */ | ||
1360 | return ECORE_CON_SSL_ERROR_NONE; | ||
1361 | /* use CRL/CA lists to verify */ | ||
1362 | SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_certificate_verify_peers2(cl->session, &iter)); | ||
1363 | if (iter & GNUTLS_CERT_INVALID) | ||
1364 | ERR("The certificate is not trusted."); | ||
1365 | else if (iter & GNUTLS_CERT_SIGNER_NOT_FOUND) | ||
1366 | ERR("The certificate hasn't got a known issuer."); | ||
1367 | else if (iter & GNUTLS_CERT_REVOKED) | ||
1368 | ERR("The certificate has been revoked."); | ||
1369 | else if (iter & GNUTLS_CERT_EXPIRED) | ||
1370 | ERR("The certificate has expired"); | ||
1371 | else if (iter & GNUTLS_CERT_NOT_ACTIVATED) | ||
1372 | ERR("The certificate is not yet activated"); | ||
1373 | |||
1374 | if (iter) | ||
1375 | goto error; | ||
1376 | if (gnutls_certificate_type_get(cl->session) != GNUTLS_CRT_X509) | ||
1377 | { | ||
1378 | ERR("Warning: PGP certificates are not yet supported!"); | ||
1379 | goto error; | ||
1380 | } | ||
1381 | |||
1382 | SSL_ERROR_CHECK_GOTO_ERROR(!(cert_list = gnutls_certificate_get_peers(cl->session, &cert_list_size))); | ||
1383 | SSL_ERROR_CHECK_GOTO_ERROR(!cert_list_size); | ||
1384 | |||
1385 | _gnutls_print_session(cert_list, cert_list_size); | ||
1386 | /* | ||
1387 | gnutls_x509_crt_t cert = NULL; | ||
1388 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_init(&cert)); | ||
1389 | SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER)); | ||
1390 | |||
1391 | SSL_ERROR_CHECK_GOTO_ERROR(!gnutls_x509_crt_check_hostname(cert, cl->host_server->name)); | ||
1392 | gnutls_x509_crt_deinit(cert); | ||
1393 | */ | ||
1394 | DBG("SSL certificate verification succeeded!"); | ||
1395 | return ECORE_CON_SSL_ERROR_NONE; | ||
1396 | |||
1397 | error: | ||
1398 | _gnutls_print_errors(cl, ECORE_CON_EVENT_CLIENT_ERROR, ret); | ||
1399 | if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) || (ret == GNUTLS_E_FATAL_ALERT_RECEIVED)) | ||
1400 | ERR("Also received alert: %s", gnutls_alert_get_name(gnutls_alert_get(cl->session))); | ||
1401 | if (cl->session && (cl->ssl_state != ECORE_CON_SSL_STATE_DONE)) | ||
1402 | { | ||
1403 | ERR("last out: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_out(cl->session))); | ||
1404 | ERR("last in: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_in(cl->session))); | ||
1405 | } | ||
1406 | /* | ||
1407 | if (cert) | ||
1408 | gnutls_x509_crt_deinit(cert); | ||
1409 | */ | ||
1410 | _ecore_con_ssl_client_shutdown_gnutls(cl); | ||
1411 | return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; | ||
1412 | } | ||
1413 | |||
1414 | static Ecore_Con_Ssl_Error | ||
1415 | _ecore_con_ssl_client_shutdown_gnutls(Ecore_Con_Client *cl) | ||
1416 | { | ||
1417 | if (cl->session) | ||
1418 | { | ||
1419 | gnutls_bye(cl->session, GNUTLS_SHUT_RDWR); | ||
1420 | gnutls_deinit(cl->session); | ||
1421 | gnutls_free(cl->session_ticket.data); | ||
1422 | cl->session_ticket.data = NULL; | ||
1423 | } | ||
1424 | |||
1425 | cl->session = NULL; | ||
1426 | |||
1427 | return ECORE_CON_SSL_ERROR_NONE; | ||
1428 | } | ||
1429 | |||
1430 | static int | ||
1431 | _ecore_con_ssl_client_read_gnutls(Ecore_Con_Client *cl, | ||
1432 | unsigned char *buf, | ||
1433 | int size) | ||
1434 | { | ||
1435 | int num; | ||
1436 | |||
1437 | if (cl->ssl_state == ECORE_CON_SSL_STATE_HANDSHAKING) | ||
1438 | { | ||
1439 | if (!_ecore_con_ssl_client_init_gnutls(cl)) | ||
1440 | return 0; | ||
1441 | return -1; | ||
1442 | } | ||
1443 | |||
1444 | num = gnutls_record_recv(cl->session, buf, size); | ||
1445 | if (num > 0) | ||
1446 | return num; | ||
1447 | |||
1448 | if (num == GNUTLS_E_REHANDSHAKE) | ||
1449 | { | ||
1450 | WRN("Rehandshake request ignored"); | ||
1451 | return 0; | ||
1452 | cl->handshaking = EINA_TRUE; | ||
1453 | cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; | ||
1454 | if (!_ecore_con_ssl_client_init_gnutls(cl)) | ||
1455 | return 0; | ||
1456 | WRN("Rehandshake request ignored"); | ||
1457 | return 0; | ||
1458 | } | ||
1459 | else if ((!gnutls_error_is_fatal(num)) && (num != GNUTLS_E_SUCCESS)) | ||
1460 | return 0; | ||
1461 | |||
1462 | return -1; | ||
1463 | } | ||
1464 | |||
1465 | static int | ||
1466 | _ecore_con_ssl_client_write_gnutls(Ecore_Con_Client *cl, | ||
1467 | const unsigned char *buf, | ||
1468 | int size) | ||
1469 | { | ||
1470 | int num; | ||
1471 | |||
1472 | if (cl->ssl_state == ECORE_CON_SSL_STATE_HANDSHAKING) | ||
1473 | { | ||
1474 | if (!_ecore_con_ssl_client_init_gnutls(cl)) | ||
1475 | return 0; | ||
1476 | return -1; | ||
1477 | } | ||
1478 | |||
1479 | num = gnutls_record_send(cl->session, buf, size); | ||
1480 | if (num > 0) | ||
1481 | return num; | ||
1482 | |||
1483 | if (num == GNUTLS_E_REHANDSHAKE) | ||
1484 | { | ||
1485 | WRN("Rehandshake request ignored"); | ||
1486 | return 0; | ||
1487 | cl->handshaking = EINA_TRUE; | ||
1488 | cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; | ||
1489 | if (!_ecore_con_ssl_client_init_gnutls(cl)) | ||
1490 | return 0; | ||
1491 | } | ||
1492 | else if (!gnutls_error_is_fatal(num)) | ||
1493 | return 0; | ||
1494 | |||
1495 | return -1; | ||
1496 | } | ||
1497 | |||
1498 | #elif USE_OPENSSL && !USE_GNUTLS | ||
1499 | |||
1500 | /* | ||
1501 | * OpenSSL | ||
1502 | */ | ||
1503 | |||
1504 | static Ecore_Con_Ssl_Error | ||
1505 | _ecore_con_ssl_init_openssl(void) | ||
1506 | { | ||
1507 | SSL_library_init(); | ||
1508 | SSL_load_error_strings(); | ||
1509 | OpenSSL_add_all_algorithms(); | ||
1510 | |||
1511 | return ECORE_CON_SSL_ERROR_NONE; | ||
1512 | } | ||
1513 | |||
1514 | static Ecore_Con_Ssl_Error | ||
1515 | _ecore_con_ssl_shutdown_openssl(void) | ||
1516 | { | ||
1517 | ERR_free_strings(); | ||
1518 | EVP_cleanup(); | ||
1519 | return ECORE_CON_SSL_ERROR_NONE; | ||
1520 | } | ||
1521 | |||
1522 | static Ecore_Con_Ssl_Error | ||
1523 | _ecore_con_ssl_server_prepare_openssl(Ecore_Con_Server *svr, | ||
1524 | int ssl_type) | ||
1525 | { | ||
1526 | long options; | ||
1527 | int dh = 0; | ||
1528 | |||
1529 | if (ssl_type & ECORE_CON_USE_SSL2) | ||
1530 | return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED; | ||
1531 | |||
1532 | switch (ssl_type) | ||
1533 | { | ||
1534 | case ECORE_CON_USE_SSL3: | ||
1535 | case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT: | ||
1536 | if (!svr->created) | ||
1537 | SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv3_client_method()))); | ||
1538 | else | ||
1539 | SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv3_server_method()))); | ||
1540 | break; | ||
1541 | |||
1542 | case ECORE_CON_USE_TLS: | ||
1543 | case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT: | ||
1544 | if (!svr->created) | ||
1545 | SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(TLSv1_client_method()))); | ||
1546 | else | ||
1547 | SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(TLSv1_server_method()))); | ||
1548 | break; | ||
1549 | |||
1550 | case ECORE_CON_USE_MIXED: | ||
1551 | case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT: | ||
1552 | if (!svr->created) | ||
1553 | SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv23_client_method()))); | ||
1554 | else | ||
1555 | SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))); | ||
1556 | options = SSL_CTX_get_options(svr->ssl_ctx); | ||
1557 | SSL_CTX_set_options(svr->ssl_ctx, options | SSL_OP_NO_SSLv2 | SSL_OP_SINGLE_DH_USE); | ||
1558 | break; | ||
1559 | |||
1560 | default: | ||
1561 | return ECORE_CON_SSL_ERROR_NONE; | ||
1562 | } | ||
1563 | |||
1564 | if ((!svr->use_cert) && svr->created) | ||
1565 | { | ||
1566 | DH *dh_params; | ||
1567 | INF("Generating DH params"); | ||
1568 | SSL_ERROR_CHECK_GOTO_ERROR(!(dh_params = DH_new())); | ||
1569 | SSL_ERROR_CHECK_GOTO_ERROR(!DH_generate_parameters_ex(dh_params, 1024, DH_GENERATOR_5, NULL)); | ||
1570 | SSL_ERROR_CHECK_GOTO_ERROR(!DH_check(dh_params, &dh)); | ||
1571 | SSL_ERROR_CHECK_GOTO_ERROR((dh & DH_CHECK_P_NOT_PRIME) || (dh & DH_CHECK_P_NOT_SAFE_PRIME)); | ||
1572 | SSL_ERROR_CHECK_GOTO_ERROR(!DH_generate_key(dh_params)); | ||
1573 | SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_tmp_dh(svr->ssl_ctx, dh_params)); | ||
1574 | DH_free(dh_params); | ||
1575 | INF("DH params successfully generated and applied!"); | ||
1576 | SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_cipher_list(svr->ssl_ctx, "aNULL:!eNULL:!LOW:!EXPORT:@STRENGTH")); | ||
1577 | } | ||
1578 | else if (!svr->use_cert) | ||
1579 | SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_cipher_list(svr->ssl_ctx, "aNULL:!eNULL:!LOW:!EXPORT:!ECDH:RSA:AES:!PSK:@STRENGTH")); | ||
1580 | |||
1581 | return ECORE_CON_SSL_ERROR_NONE; | ||
1582 | |||
1583 | error: | ||
1584 | if (dh) | ||
1585 | { | ||
1586 | if (dh & DH_CHECK_P_NOT_PRIME) | ||
1587 | ERR("openssl error: dh_params could not generate a prime!"); | ||
1588 | else | ||
1589 | ERR("openssl error: dh_params could not generate a safe prime!"); | ||
1590 | } | ||
1591 | else | ||
1592 | _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR); | ||
1593 | _ecore_con_ssl_server_shutdown_openssl(svr); | ||
1594 | return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; | ||
1595 | } | ||
1596 | |||
1597 | static Ecore_Con_Ssl_Error | ||
1598 | _ecore_con_ssl_server_init_openssl(Ecore_Con_Server *svr) | ||
1599 | { | ||
1600 | int ret = -1; | ||
1601 | |||
1602 | switch (svr->ssl_state) | ||
1603 | { | ||
1604 | case ECORE_CON_SSL_STATE_DONE: | ||
1605 | return ECORE_CON_SSL_ERROR_NONE; | ||
1606 | |||
1607 | case ECORE_CON_SSL_STATE_INIT: | ||
1608 | SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl = SSL_new(svr->ssl_ctx))); | ||
1609 | |||
1610 | SSL_ERROR_CHECK_GOTO_ERROR(!SSL_set_fd(svr->ssl, svr->fd)); | ||
1611 | SSL_set_connect_state(svr->ssl); | ||
1612 | svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; | ||
1613 | |||
1614 | case ECORE_CON_SSL_STATE_HANDSHAKING: | ||
1615 | if (!svr->ssl) | ||
1616 | { | ||
1617 | DBG("Server was previously lost, going to error condition"); | ||
1618 | goto error; | ||
1619 | } | ||
1620 | ret = SSL_do_handshake(svr->ssl); | ||
1621 | svr->ssl_err = SSL_get_error(svr->ssl, ret); | ||
1622 | SSL_ERROR_CHECK_GOTO_ERROR((svr->ssl_err == SSL_ERROR_SYSCALL) || (svr->ssl_err == SSL_ERROR_SSL)); | ||
1623 | |||
1624 | if (ret == 1) | ||
1625 | { | ||
1626 | svr->handshaking = EINA_FALSE; | ||
1627 | svr->ssl_state = ECORE_CON_SSL_STATE_DONE; | ||
1628 | } | ||
1629 | else | ||
1630 | { | ||
1631 | if (svr->ssl_err == SSL_ERROR_WANT_READ) | ||
1632 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ); | ||
1633 | else if (svr->ssl_err == SSL_ERROR_WANT_WRITE) | ||
1634 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); | ||
1635 | return ECORE_CON_SSL_ERROR_NONE; | ||
1636 | } | ||
1637 | |||
1638 | default: | ||
1639 | break; | ||
1640 | } | ||
1641 | |||
1642 | _openssl_print_session(svr->ssl); | ||
1643 | if ((!svr->verify) && (!svr->verify_basic)) | ||
1644 | /* not verifying certificates, so we're done! */ | ||
1645 | return ECORE_CON_SSL_ERROR_NONE; | ||
1646 | |||
1647 | { | ||
1648 | X509 *cert; | ||
1649 | SSL_set_verify(svr->ssl, SSL_VERIFY_PEER, NULL); | ||
1650 | /* use CRL/CA lists to verify */ | ||
1651 | cert = SSL_get_peer_certificate(svr->ssl); | ||
1652 | if (cert) | ||
1653 | { | ||
1654 | char *c; | ||
1655 | int clen; | ||
1656 | int name = 0; | ||
1657 | |||
1658 | if (svr->verify) | ||
1659 | { | ||
1660 | int err; | ||
1661 | |||
1662 | err = SSL_get_verify_result(svr->ssl); | ||
1663 | _openssl_print_verify_error(err); | ||
1664 | SSL_ERROR_CHECK_GOTO_ERROR(err); | ||
1665 | } | ||
1666 | clen = X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_subject_alt_name, NULL, 0); | ||
1667 | if (clen > 0) | ||
1668 | name = NID_subject_alt_name; | ||
1669 | else | ||
1670 | clen = X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, NULL, 0); | ||
1671 | SSL_ERROR_CHECK_GOTO_ERROR(clen < 1); | ||
1672 | if (!name) name = NID_commonName; | ||
1673 | c = alloca(++clen); | ||
1674 | X509_NAME_get_text_by_NID(X509_get_subject_name(cert), name, c, clen); | ||
1675 | INF("CERT NAME: %s\n", c); | ||
1676 | SSL_ERROR_CHECK_GOTO_ERROR(!_openssl_name_verify(c, svr->verify_name ?: svr->name)); | ||
1677 | } | ||
1678 | } | ||
1679 | |||
1680 | DBG("SSL certificate verification succeeded!"); | ||
1681 | |||
1682 | return ECORE_CON_SSL_ERROR_NONE; | ||
1683 | |||
1684 | error: | ||
1685 | _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR); | ||
1686 | _ecore_con_ssl_server_shutdown_openssl(svr); | ||
1687 | return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; | ||
1688 | } | ||
1689 | |||
1690 | static Eina_Bool | ||
1691 | _ecore_con_ssl_server_cafile_add_openssl(Ecore_Con_Server *svr, | ||
1692 | const char *ca_file) | ||
1693 | { | ||
1694 | struct stat st; | ||
1695 | |||
1696 | if (stat(ca_file, &st)) return EINA_FALSE; | ||
1697 | if (S_ISDIR(st.st_mode)) | ||
1698 | SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_load_verify_locations(svr->ssl_ctx, NULL, ca_file)); | ||
1699 | else | ||
1700 | SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_load_verify_locations(svr->ssl_ctx, ca_file, NULL)); | ||
1701 | return EINA_TRUE; | ||
1702 | |||
1703 | error: | ||
1704 | _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR); | ||
1705 | return EINA_FALSE; | ||
1706 | } | ||
1707 | |||
1708 | static Eina_Bool | ||
1709 | _ecore_con_ssl_server_crl_add_openssl(Ecore_Con_Server *svr, | ||
1710 | const char *crl_file) | ||
1711 | { | ||
1712 | X509_STORE *st; | ||
1713 | X509_LOOKUP *lu; | ||
1714 | static Eina_Bool flag = EINA_FALSE; | ||
1715 | |||
1716 | SSL_ERROR_CHECK_GOTO_ERROR(!(st = SSL_CTX_get_cert_store(svr->ssl_ctx))); | ||
1717 | SSL_ERROR_CHECK_GOTO_ERROR(!(lu = X509_STORE_add_lookup(st, X509_LOOKUP_file()))); | ||
1718 | SSL_ERROR_CHECK_GOTO_ERROR(X509_load_crl_file(lu, crl_file, X509_FILETYPE_PEM) < 1); | ||
1719 | if (!flag) | ||
1720 | { | ||
1721 | X509_STORE_set_flags(st, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); | ||
1722 | flag = EINA_TRUE; | ||
1723 | } | ||
1724 | |||
1725 | return EINA_TRUE; | ||
1726 | |||
1727 | error: | ||
1728 | _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR); | ||
1729 | return EINA_FALSE; | ||
1730 | } | ||
1731 | |||
1732 | static Eina_Bool | ||
1733 | _ecore_con_ssl_server_privkey_add_openssl(Ecore_Con_Server *svr, | ||
1734 | const char *key_file) | ||
1735 | { | ||
1736 | FILE *fp = NULL; | ||
1737 | EVP_PKEY *privkey = NULL; | ||
1738 | |||
1739 | if (!(fp = fopen(key_file, "r"))) | ||
1740 | goto error; | ||
1741 | |||
1742 | SSL_ERROR_CHECK_GOTO_ERROR(!(privkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL))); | ||
1743 | |||
1744 | fclose(fp); | ||
1745 | SSL_ERROR_CHECK_GOTO_ERROR(SSL_CTX_use_PrivateKey(svr->ssl_ctx, privkey) < 1); | ||
1746 | SSL_ERROR_CHECK_GOTO_ERROR(SSL_CTX_check_private_key(svr->ssl_ctx) < 1); | ||
1747 | |||
1748 | return EINA_TRUE; | ||
1749 | |||
1750 | error: | ||
1751 | if (fp) | ||
1752 | fclose(fp); | ||
1753 | _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR); | ||
1754 | return EINA_FALSE; | ||
1755 | } | ||
1756 | |||
1757 | static Eina_Bool | ||
1758 | _ecore_con_ssl_server_cert_add_openssl(Ecore_Con_Server *svr, | ||
1759 | const char *cert_file) | ||
1760 | { | ||
1761 | FILE *fp = NULL; | ||
1762 | X509 *cert = NULL; | ||
1763 | |||
1764 | if (!(fp = fopen(cert_file, "r"))) | ||
1765 | goto error; | ||
1766 | |||
1767 | SSL_ERROR_CHECK_GOTO_ERROR(!(cert = PEM_read_X509(fp, NULL, NULL, NULL))); | ||
1768 | |||
1769 | fclose(fp); | ||
1770 | |||
1771 | SSL_ERROR_CHECK_GOTO_ERROR(SSL_CTX_use_certificate(svr->ssl_ctx, cert) < 1); | ||
1772 | |||
1773 | return EINA_TRUE; | ||
1774 | |||
1775 | error: | ||
1776 | if (fp) | ||
1777 | fclose(fp); | ||
1778 | _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR); | ||
1779 | return EINA_FALSE; | ||
1780 | } | ||
1781 | |||
1782 | static Ecore_Con_Ssl_Error | ||
1783 | _ecore_con_ssl_server_shutdown_openssl(Ecore_Con_Server *svr) | ||
1784 | { | ||
1785 | if (svr->ssl) | ||
1786 | { | ||
1787 | if (!SSL_shutdown(svr->ssl)) | ||
1788 | SSL_shutdown(svr->ssl); | ||
1789 | |||
1790 | SSL_free(svr->ssl); | ||
1791 | } | ||
1792 | |||
1793 | if (svr->ssl_ctx) | ||
1794 | SSL_CTX_free(svr->ssl_ctx); | ||
1795 | |||
1796 | svr->ssl = NULL; | ||
1797 | svr->ssl_ctx = NULL; | ||
1798 | svr->ssl_err = SSL_ERROR_NONE; | ||
1799 | |||
1800 | return ECORE_CON_SSL_ERROR_NONE; | ||
1801 | } | ||
1802 | |||
1803 | static int | ||
1804 | _ecore_con_ssl_server_read_openssl(Ecore_Con_Server *svr, | ||
1805 | unsigned char *buf, | ||
1806 | int size) | ||
1807 | { | ||
1808 | int num; | ||
1809 | |||
1810 | if (!svr->ssl) return -1; | ||
1811 | num = SSL_read(svr->ssl, buf, size); | ||
1812 | svr->ssl_err = SSL_get_error(svr->ssl, num); | ||
1813 | |||
1814 | if (svr->fd_handler) | ||
1815 | { | ||
1816 | if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_READ) | ||
1817 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ); | ||
1818 | else if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_WRITE) | ||
1819 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); | ||
1820 | } | ||
1821 | |||
1822 | if ((svr->ssl_err == SSL_ERROR_ZERO_RETURN) || | ||
1823 | (svr->ssl_err == SSL_ERROR_SYSCALL) || | ||
1824 | (svr->ssl_err == SSL_ERROR_SSL)) | ||
1825 | return -1; | ||
1826 | |||
1827 | if (num < 0) | ||
1828 | return 0; | ||
1829 | |||
1830 | return num; | ||
1831 | } | ||
1832 | |||
1833 | static int | ||
1834 | _ecore_con_ssl_server_write_openssl(Ecore_Con_Server *svr, | ||
1835 | const unsigned char *buf, | ||
1836 | int size) | ||
1837 | { | ||
1838 | int num; | ||
1839 | |||
1840 | num = SSL_write(svr->ssl, buf, size); | ||
1841 | svr->ssl_err = SSL_get_error(svr->ssl, num); | ||
1842 | |||
1843 | if (svr->fd_handler) | ||
1844 | { | ||
1845 | if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_READ) | ||
1846 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ); | ||
1847 | else if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_WRITE) | ||
1848 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); | ||
1849 | } | ||
1850 | |||
1851 | if ((svr->ssl_err == SSL_ERROR_ZERO_RETURN) || | ||
1852 | (svr->ssl_err == SSL_ERROR_SYSCALL) || | ||
1853 | (svr->ssl_err == SSL_ERROR_SSL)) | ||
1854 | return -1; | ||
1855 | |||
1856 | if (num < 0) | ||
1857 | return 0; | ||
1858 | |||
1859 | return num; | ||
1860 | } | ||
1861 | |||
1862 | static Ecore_Con_Ssl_Error | ||
1863 | _ecore_con_ssl_client_init_openssl(Ecore_Con_Client *cl) | ||
1864 | { | ||
1865 | int ret = -1; | ||
1866 | switch (cl->ssl_state) | ||
1867 | { | ||
1868 | case ECORE_CON_SSL_STATE_DONE: | ||
1869 | return ECORE_CON_SSL_ERROR_NONE; | ||
1870 | |||
1871 | case ECORE_CON_SSL_STATE_INIT: | ||
1872 | SSL_ERROR_CHECK_GOTO_ERROR(!(cl->ssl = SSL_new(cl->host_server->ssl_ctx))); | ||
1873 | |||
1874 | SSL_ERROR_CHECK_GOTO_ERROR(!SSL_set_fd(cl->ssl, cl->fd)); | ||
1875 | SSL_set_accept_state(cl->ssl); | ||
1876 | cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; | ||
1877 | |||
1878 | case ECORE_CON_SSL_STATE_HANDSHAKING: | ||
1879 | if (!cl->ssl) | ||
1880 | { | ||
1881 | DBG("Client was previously lost, going to error condition"); | ||
1882 | goto error; | ||
1883 | } | ||
1884 | ret = SSL_do_handshake(cl->ssl); | ||
1885 | cl->ssl_err = SSL_get_error(cl->ssl, ret); | ||
1886 | SSL_ERROR_CHECK_GOTO_ERROR((cl->ssl_err == SSL_ERROR_SYSCALL) || (cl->ssl_err == SSL_ERROR_SSL)); | ||
1887 | if (ret == 1) | ||
1888 | { | ||
1889 | cl->handshaking = EINA_FALSE; | ||
1890 | cl->ssl_state = ECORE_CON_SSL_STATE_DONE; | ||
1891 | } | ||
1892 | else | ||
1893 | { | ||
1894 | if (cl->ssl_err == SSL_ERROR_WANT_READ) | ||
1895 | ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ); | ||
1896 | else if (cl->ssl_err == SSL_ERROR_WANT_WRITE) | ||
1897 | ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE); | ||
1898 | return ECORE_CON_SSL_ERROR_NONE; | ||
1899 | } | ||
1900 | |||
1901 | default: | ||
1902 | break; | ||
1903 | } | ||
1904 | |||
1905 | _openssl_print_session(cl->ssl); | ||
1906 | if (!cl->host_server->verify) | ||
1907 | /* not verifying certificates, so we're done! */ | ||
1908 | return ECORE_CON_SSL_ERROR_NONE; | ||
1909 | SSL_set_verify(cl->ssl, SSL_VERIFY_PEER, NULL); | ||
1910 | /* use CRL/CA lists to verify */ | ||
1911 | if (SSL_get_peer_certificate(cl->ssl)) | ||
1912 | { | ||
1913 | int err; | ||
1914 | |||
1915 | err = SSL_get_verify_result(cl->ssl); | ||
1916 | _openssl_print_verify_error(err); | ||
1917 | SSL_ERROR_CHECK_GOTO_ERROR(err); | ||
1918 | } | ||
1919 | |||
1920 | return ECORE_CON_SSL_ERROR_NONE; | ||
1921 | |||
1922 | error: | ||
1923 | _openssl_print_errors(cl, ECORE_CON_EVENT_CLIENT_ERROR); | ||
1924 | _ecore_con_ssl_client_shutdown_openssl(cl); | ||
1925 | return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; | ||
1926 | } | ||
1927 | |||
1928 | static Ecore_Con_Ssl_Error | ||
1929 | _ecore_con_ssl_client_shutdown_openssl(Ecore_Con_Client *cl) | ||
1930 | { | ||
1931 | if (cl->ssl) | ||
1932 | { | ||
1933 | if (!SSL_shutdown(cl->ssl)) | ||
1934 | SSL_shutdown(cl->ssl); | ||
1935 | |||
1936 | SSL_free(cl->ssl); | ||
1937 | } | ||
1938 | |||
1939 | cl->ssl = NULL; | ||
1940 | cl->ssl_err = SSL_ERROR_NONE; | ||
1941 | |||
1942 | return ECORE_CON_SSL_ERROR_NONE; | ||
1943 | } | ||
1944 | |||
1945 | static int | ||
1946 | _ecore_con_ssl_client_read_openssl(Ecore_Con_Client *cl, | ||
1947 | unsigned char *buf, | ||
1948 | int size) | ||
1949 | { | ||
1950 | int num; | ||
1951 | |||
1952 | if (!cl->ssl) return -1; | ||
1953 | num = SSL_read(cl->ssl, buf, size); | ||
1954 | cl->ssl_err = SSL_get_error(cl->ssl, num); | ||
1955 | |||
1956 | if (cl->fd_handler) | ||
1957 | { | ||
1958 | if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_READ) | ||
1959 | ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ); | ||
1960 | else if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_WRITE) | ||
1961 | ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE); | ||
1962 | } | ||
1963 | |||
1964 | if ((cl->ssl_err == SSL_ERROR_ZERO_RETURN) || | ||
1965 | (cl->ssl_err == SSL_ERROR_SYSCALL) || | ||
1966 | (cl->ssl_err == SSL_ERROR_SSL)) | ||
1967 | return -1; | ||
1968 | |||
1969 | if (num < 0) | ||
1970 | return 0; | ||
1971 | |||
1972 | return num; | ||
1973 | } | ||
1974 | |||
1975 | static int | ||
1976 | _ecore_con_ssl_client_write_openssl(Ecore_Con_Client *cl, | ||
1977 | const unsigned char *buf, | ||
1978 | int size) | ||
1979 | { | ||
1980 | int num; | ||
1981 | |||
1982 | num = SSL_write(cl->ssl, buf, size); | ||
1983 | cl->ssl_err = SSL_get_error(cl->ssl, num); | ||
1984 | |||
1985 | if (cl->fd_handler) | ||
1986 | { | ||
1987 | if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_READ) | ||
1988 | ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ); | ||
1989 | else if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_WRITE) | ||
1990 | ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE); | ||
1991 | } | ||
1992 | |||
1993 | if ((cl->ssl_err == SSL_ERROR_ZERO_RETURN) || | ||
1994 | (cl->ssl_err == SSL_ERROR_SYSCALL) || | ||
1995 | (cl->ssl_err == SSL_ERROR_SSL)) | ||
1996 | return -1; | ||
1997 | |||
1998 | if (num < 0) | ||
1999 | return 0; | ||
2000 | |||
2001 | return num; | ||
2002 | } | ||
2003 | |||
2004 | #else | ||
2005 | |||
2006 | /* | ||
2007 | * No Ssl | ||
2008 | */ | ||
2009 | |||
2010 | static Ecore_Con_Ssl_Error | ||
2011 | _ecore_con_ssl_init_none(void) | ||
2012 | { | ||
2013 | return ECORE_CON_SSL_ERROR_NONE; | ||
2014 | } | ||
2015 | |||
2016 | static Ecore_Con_Ssl_Error | ||
2017 | _ecore_con_ssl_shutdown_none(void) | ||
2018 | { | ||
2019 | return ECORE_CON_SSL_ERROR_NONE; | ||
2020 | } | ||
2021 | |||
2022 | static Ecore_Con_Ssl_Error | ||
2023 | _ecore_con_ssl_server_prepare_none(Ecore_Con_Server *svr __UNUSED__, | ||
2024 | int ssl_type __UNUSED__) | ||
2025 | { | ||
2026 | return ECORE_CON_SSL_ERROR_NONE; | ||
2027 | } | ||
2028 | |||
2029 | static Ecore_Con_Ssl_Error | ||
2030 | _ecore_con_ssl_server_init_none(Ecore_Con_Server *svr __UNUSED__) | ||
2031 | { | ||
2032 | return ECORE_CON_SSL_ERROR_NOT_SUPPORTED; | ||
2033 | } | ||
2034 | |||
2035 | static Eina_Bool | ||
2036 | _ecore_con_ssl_server_cafile_add_none(Ecore_Con_Server *svr __UNUSED__, | ||
2037 | const char *ca_file __UNUSED__) | ||
2038 | { | ||
2039 | return EINA_FALSE; | ||
2040 | } | ||
2041 | |||
2042 | static Eina_Bool | ||
2043 | _ecore_con_ssl_server_cert_add_none(Ecore_Con_Server *svr __UNUSED__, | ||
2044 | const char *cert_file __UNUSED__) | ||
2045 | { | ||
2046 | return EINA_FALSE; | ||
2047 | } | ||
2048 | |||
2049 | static Eina_Bool | ||
2050 | _ecore_con_ssl_server_privkey_add_none(Ecore_Con_Server *svr __UNUSED__, | ||
2051 | const char *key_file __UNUSED__) | ||
2052 | { | ||
2053 | return EINA_FALSE; | ||
2054 | } | ||
2055 | |||
2056 | static Eina_Bool | ||
2057 | _ecore_con_ssl_server_crl_add_none(Ecore_Con_Server *svr __UNUSED__, | ||
2058 | const char *crl_file __UNUSED__) | ||
2059 | { | ||
2060 | return EINA_FALSE; | ||
2061 | } | ||
2062 | |||
2063 | static Ecore_Con_Ssl_Error | ||
2064 | _ecore_con_ssl_server_shutdown_none(Ecore_Con_Server *svr __UNUSED__) | ||
2065 | { | ||
2066 | return ECORE_CON_SSL_ERROR_NOT_SUPPORTED; | ||
2067 | } | ||
2068 | |||
2069 | static int | ||
2070 | _ecore_con_ssl_server_read_none(Ecore_Con_Server *svr __UNUSED__, | ||
2071 | unsigned char *buf __UNUSED__, | ||
2072 | int size __UNUSED__) | ||
2073 | { | ||
2074 | return -1; | ||
2075 | } | ||
2076 | |||
2077 | static int | ||
2078 | _ecore_con_ssl_server_write_none(Ecore_Con_Server *svr __UNUSED__, | ||
2079 | const unsigned char *buf __UNUSED__, | ||
2080 | int size __UNUSED__) | ||
2081 | { | ||
2082 | return -1; | ||
2083 | } | ||
2084 | |||
2085 | static Ecore_Con_Ssl_Error | ||
2086 | _ecore_con_ssl_client_init_none(Ecore_Con_Client *cl __UNUSED__) | ||
2087 | { | ||
2088 | return ECORE_CON_SSL_ERROR_NOT_SUPPORTED; | ||
2089 | } | ||
2090 | |||
2091 | static Ecore_Con_Ssl_Error | ||
2092 | _ecore_con_ssl_client_shutdown_none(Ecore_Con_Client *cl __UNUSED__) | ||
2093 | { | ||
2094 | return ECORE_CON_SSL_ERROR_NOT_SUPPORTED; | ||
2095 | } | ||
2096 | |||
2097 | static int | ||
2098 | _ecore_con_ssl_client_read_none(Ecore_Con_Client *cl __UNUSED__, | ||
2099 | unsigned char *buf __UNUSED__, | ||
2100 | int size __UNUSED__) | ||
2101 | { | ||
2102 | return -1; | ||
2103 | } | ||
2104 | |||
2105 | static int | ||
2106 | _ecore_con_ssl_client_write_none(Ecore_Con_Client *cl __UNUSED__, | ||
2107 | const unsigned char *buf __UNUSED__, | ||
2108 | int size __UNUSED__) | ||
2109 | { | ||
2110 | return -1; | ||
2111 | } | ||
2112 | |||
2113 | #endif | ||