1 #include <openssl/ssl.h>
2 #include <openssl/err.h>
3 #include <openssl/dh.h>
4
5 struct _Efl_Net_Ssl_Ctx
6 {
7 SSL_CTX *ssl_ctx;
8 Eina_Bool did_certificates;
9 Eina_Bool is_dialer;
10 };
11
12 #if OPENSSL_VERSION_NUMBER < 0x10100000L
13 # define TLS_server_method TLSv1_2_server_method
14 # define TLS_client_method TLSv1_2_client_method
15 #endif
16
17 #define EFL_NET_SSL_CONTEXT_CIPHERS "aRSA+HIGH:+kEDH:+kRSA:!kSRP:!kPSK:+3DES:!MD5"
18
19 #define _efl_net_ssl_ctx_check_errors() \
20 __efl_net_ssl_ctx_check_errors(__FILE__, __LINE__, __func__)
21 static unsigned long
__efl_net_ssl_ctx_check_errors(const char * file,int line,const char * fname)22 __efl_net_ssl_ctx_check_errors(const char *file, int line, const char *fname)
23 {
24 unsigned long first = 0;
25 do
26 {
27 const char *_ssl_err_file, *_ssl_err_data;
28 int _ssl_err_line, _ssl_err_flags;
29 unsigned long _ssl_err = ERR_get_error_line_data(&_ssl_err_file, &_ssl_err_line, &_ssl_err_data, &_ssl_err_flags);
30 if (!_ssl_err) break;
31 if (!first) first = _ssl_err;
32 eina_log_print(_ecore_con_log_dom, EINA_LOG_LEVEL_ERR, file, fname, line,
33 "OpenSSL error %s:%d%s%s: %s",
34 _ssl_err_file, _ssl_err_line,
35 (_ssl_err_flags & ERR_TXT_STRING) ? " " : "",
36 (_ssl_err_flags & ERR_TXT_STRING) ? _ssl_err_data : "",
37 ERR_reason_error_string(_ssl_err));
38 }
39 while (1);
40 return first;
41 }
42
43 static Eina_Error
_efl_net_ssl_ctx_load_lists(Efl_Net_Ssl_Ctx * ctx,Efl_Net_Ssl_Ctx_Config cfg)44 _efl_net_ssl_ctx_load_lists(Efl_Net_Ssl_Ctx *ctx, Efl_Net_Ssl_Ctx_Config cfg)
45 {
46 Eina_List *n, *n_next;
47 const char *path;
48 unsigned certificates_count = eina_list_count(*cfg.certificates);
49 unsigned private_keys_count = eina_list_count(*cfg.private_keys);
50 unsigned certificate_revocation_lists_count = eina_list_count(*cfg.certificate_revocation_lists);
51 unsigned certificate_authorities_count = eina_list_count(*cfg.certificate_authorities);
52 long err_ssl;
53 const char *err_file;
54 const char *err_data;
55 int err_line, err_flags;
56 X509_STORE *x509_store;
57 X509_LOOKUP *x509_lookup;
58 unsigned long x509_store_flags = 0;
59
60 #ifdef X509_V_FLAG_TRUSTED_FIRST
61 x509_store_flags |= X509_V_FLAG_TRUSTED_FIRST;
62 #endif
63
64 if (cfg.load_defaults)
65 {
66 if (SSL_CTX_set_default_verify_paths(ctx->ssl_ctx) != 1)
67 {
68 _efl_net_ssl_ctx_check_errors();
69 ERR("ssl_ctx=%p could not load default paths", ctx);
70 return ENOSYS;
71 }
72 DBG("ssl_ctx=%p loaded default paths", ctx);
73 }
74 else
75 DBG("ssl_ctx=%p did not load default paths", ctx);
76
77 EINA_LIST_FOREACH_SAFE(*cfg.certificates, n, n_next, path)
78 {
79 if ((SSL_CTX_use_certificate_file(ctx->ssl_ctx, path, SSL_FILETYPE_PEM) != 1) &&
80 (SSL_CTX_use_certificate_file(ctx->ssl_ctx, path, SSL_FILETYPE_ASN1) != 1))
81 {
82 err_ssl = ERR_peek_error_line_data(&err_file, &err_line, &err_data, &err_flags);
83
84 _efl_net_ssl_ctx_check_errors();
85 _efl_net_ssl_ctx_check_errors();
86
87 ERR("ssl_ctx=%p could not use certificate from %s [%s:%d%s%s '%s']",
88 ctx, path,
89 err_file, err_line,
90 (err_flags & ERR_TXT_STRING) ? " " : "",
91 (err_flags & ERR_TXT_STRING) ? err_data : "",
92 ERR_reason_error_string(err_ssl));
93 eina_stringshare_del(path);
94 *cfg.certificates = eina_list_remove_list(*cfg.certificates, n);
95 continue;
96 }
97
98 DBG("ssl_ctx=%p loaded certificate '%s'", ctx, path);
99 ctx->did_certificates = EINA_TRUE;
100 }
101 if (certificates_count && !*cfg.certificates)
102 {
103 ERR("ssl_ctx=%p none of the required certificates were loaded!", ctx);
104 return EINVAL;
105 }
106
107 EINA_LIST_FOREACH_SAFE(*cfg.private_keys, n, n_next, path)
108 {
109 if ((SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, path, SSL_FILETYPE_PEM) != 1) &&
110 (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, path, SSL_FILETYPE_ASN1) != 1))
111 {
112 err_ssl = ERR_peek_error_line_data(&err_file, &err_line, &err_data, &err_flags);
113 _efl_net_ssl_ctx_check_errors();
114
115 ERR("ssl_ctx=%p could not use private key from %s [%s:%d%s%s '%s']",
116 ctx, path,
117 err_file, err_line,
118 (err_flags & ERR_TXT_STRING) ? " " : "",
119 (err_flags & ERR_TXT_STRING) ? err_data : "",
120 ERR_reason_error_string(err_ssl));
121 eina_stringshare_del(path);
122 *cfg.private_keys = eina_list_remove_list(*cfg.private_keys, n);
123 continue;
124 }
125
126 if (SSL_CTX_check_private_key(ctx->ssl_ctx) != 1)
127 {
128 err_ssl = ERR_peek_error_line_data(&err_file, &err_line, &err_data, &err_flags);
129 _efl_net_ssl_ctx_check_errors();
130
131 ERR("ssl_ctx=%p could not check private key from %s [%s:%d%s%s '%s']",
132 ctx, path,
133 err_file, err_line,
134 (err_flags & ERR_TXT_STRING) ? " " : "",
135 (err_flags & ERR_TXT_STRING) ? err_data : "",
136 ERR_reason_error_string(err_ssl));
137 continue;
138 }
139
140 DBG("ssl_ctx=%p loaded private key '%s'", ctx, path);
141 }
142 if (private_keys_count && !*cfg.private_keys)
143 {
144 ERR("ssl_ctx=%p none of the required private keys were loaded!", ctx);
145 return EINVAL;
146 }
147
148 x509_store = SSL_CTX_get_cert_store(ctx->ssl_ctx);
149 if (!x509_store)
150 {
151 _efl_net_ssl_ctx_check_errors();
152 ERR("ssl_ctx=%p SSL has no X509 certificate store", ctx);
153 return ENOSYS;
154 }
155 x509_lookup = X509_STORE_add_lookup(x509_store, X509_LOOKUP_file());
156 if (!x509_lookup)
157 {
158 _efl_net_ssl_ctx_check_errors();
159 ERR("ssl_ctx=%p could not add X509 file lookup", ctx);
160 return ENOSYS;
161 }
162
163 EINA_LIST_FOREACH_SAFE(*cfg.certificate_revocation_lists, n, n_next, path)
164 {
165 if ((X509_load_crl_file(x509_lookup, path, X509_FILETYPE_PEM) != 1) &&
166 (X509_load_crl_file(x509_lookup, path, X509_FILETYPE_ASN1) != 1))
167 {
168 err_ssl = ERR_peek_error_line_data(&err_file, &err_line, &err_data, &err_flags);
169 _efl_net_ssl_ctx_check_errors();
170
171 ERR("ssl_ctx=%p could not use certificate revocation lists from %s [%s:%d%s%s '%s']",
172 ctx, path,
173 err_file, err_line,
174 (err_flags & ERR_TXT_STRING) ? " " : "",
175 (err_flags & ERR_TXT_STRING) ? err_data : "",
176 ERR_reason_error_string(err_ssl));
177 eina_stringshare_del(path);
178 *cfg.certificate_revocation_lists = eina_list_remove_list(*cfg.certificate_revocation_lists, n);
179 continue;
180 }
181
182 DBG("ssl_ctx=%p loaded certificate revocation lists '%s'", ctx, path);
183 x509_store_flags |= X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL;
184 }
185 if (certificate_revocation_lists_count && !*cfg.certificate_revocation_lists)
186 {
187 ERR("ssl_ctx=%p none of the required certificate revocation lists were loaded!", ctx);
188 return EINVAL;
189 }
190 X509_STORE_set_flags(x509_store, x509_store_flags);
191
192 EINA_LIST_FOREACH_SAFE(*cfg.certificate_authorities, n, n_next, path)
193 {
194 struct stat st;
195 const char *cafile = NULL, *cadir = NULL;
196
197 if (stat(path, &st) != 0)
198 {
199 ERR("ssl_ctx=%p could not load certificate authorities from '%s': %s", ctx, path, eina_error_msg_get(errno));
200 eina_stringshare_del(path);
201 *cfg.certificate_authorities = eina_list_remove_list(*cfg.certificate_authorities, n);
202 continue;
203 }
204 else if (S_ISDIR(st.st_mode)) cadir = path;
205 else cafile = path;
206
207 if (SSL_CTX_load_verify_locations(ctx->ssl_ctx, cafile, cadir) != 1)
208 {
209 err_ssl = ERR_peek_error_line_data(&err_file, &err_line, &err_data, &err_flags);
210 _efl_net_ssl_ctx_check_errors();
211
212 ERR("ssl_ctx=%p could not use certificate authorities from %s [%s:%d%s%s '%s']",
213 ctx, path,
214 err_file, err_line,
215 (err_flags & ERR_TXT_STRING) ? " " : "",
216 (err_flags & ERR_TXT_STRING) ? err_data : "",
217 ERR_reason_error_string(err_ssl));
218 eina_stringshare_del(path);
219 *cfg.certificate_authorities = eina_list_remove_list(*cfg.certificate_authorities, n);
220 continue;
221 }
222
223 DBG("ssl_ctx=%p loaded certificate authorities '%s'", ctx, path);
224 }
225 if (certificate_authorities_count && !*cfg.certificate_authorities)
226 {
227 ERR("ssl_ctx=%p none of the required certificate authorities were loaded!", ctx);
228 return EINVAL;
229 }
230
231 if (!ctx->did_certificates)
232 {
233 if (!SSL_CTX_set_cipher_list(ctx->ssl_ctx, EFL_NET_SSL_CONTEXT_CIPHERS))
234 {
235 err_ssl = ERR_peek_error_line_data(&err_file, &err_line, &err_data, &err_flags);
236 _efl_net_ssl_ctx_check_errors();
237
238 ERR("ssl_ctx=%p Could not set ciphers '%s' [%s:%d%s%s '%s']",
239 ctx, EFL_NET_SSL_CONTEXT_CIPHERS,
240 err_file, err_line,
241 (err_flags & ERR_TXT_STRING) ? " " : "",
242 (err_flags & ERR_TXT_STRING) ? err_data : "",
243 ERR_reason_error_string(err_ssl));
244 return EINVAL;
245 }
246 }
247
248 return 0;
249 }
250
251 static void *
efl_net_ssl_ctx_connection_new(Efl_Net_Ssl_Ctx * ctx)252 efl_net_ssl_ctx_connection_new(Efl_Net_Ssl_Ctx *ctx)
253 {
254 return SSL_new(ctx->ssl_ctx);
255 }
256
257 static Eina_Error
efl_net_ssl_ctx_setup(Efl_Net_Ssl_Ctx * ctx,Efl_Net_Ssl_Ctx_Config cfg)258 efl_net_ssl_ctx_setup(Efl_Net_Ssl_Ctx *ctx, Efl_Net_Ssl_Ctx_Config cfg)
259 {
260 Eina_Error err;
261 unsigned long options;
262
263 EINA_SAFETY_ON_TRUE_RETURN_VAL(ctx->ssl_ctx != NULL, EALREADY);
264
265 ctx->is_dialer = cfg.is_dialer;
266 if (ctx->is_dialer)
267 {
268 switch (cfg.cipher)
269 {
270 case EFL_NET_SSL_CIPHER_AUTO:
271 ctx->ssl_ctx = SSL_CTX_new(TLS_client_method());
272 break;
273 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
274 case EFL_NET_SSL_CIPHER_TLSV1:
275 ctx->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
276 break;
277 case EFL_NET_SSL_CIPHER_TLSV1_1:
278 ctx->ssl_ctx = SSL_CTX_new(TLSv1_1_client_method());
279 break;
280 case EFL_NET_SSL_CIPHER_TLSV1_2:
281 ctx->ssl_ctx = SSL_CTX_new(TLSv1_2_client_method());
282 break;
283 #else
284 case EFL_NET_SSL_CIPHER_TLSV1:
285 case EFL_NET_SSL_CIPHER_TLSV1_1:
286 case EFL_NET_SSL_CIPHER_TLSV1_2:
287 ctx->ssl_ctx = SSL_CTX_new(TLS_client_method());
288 break;
289 #endif
290 default:
291 ERR("ssl_ctx=%p unsupported cipher %d", ctx, cfg.cipher);
292 return EINVAL;
293 }
294
295 EINA_SAFETY_ON_NULL_RETURN_VAL(ctx->ssl_ctx, ENOSYS);
296 }
297 else
298 {
299 switch (cfg.cipher)
300 {
301 case EFL_NET_SSL_CIPHER_AUTO:
302 ctx->ssl_ctx = SSL_CTX_new(TLS_server_method());
303 break;
304 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
305 case EFL_NET_SSL_CIPHER_TLSV1:
306 ctx->ssl_ctx = SSL_CTX_new(TLSv1_server_method());
307 break;
308 case EFL_NET_SSL_CIPHER_TLSV1_1:
309 ctx->ssl_ctx = SSL_CTX_new(TLSv1_1_server_method());
310 break;
311 case EFL_NET_SSL_CIPHER_TLSV1_2:
312 ctx->ssl_ctx = SSL_CTX_new(TLSv1_2_server_method());
313 break;
314 #else
315 case EFL_NET_SSL_CIPHER_TLSV1:
316 case EFL_NET_SSL_CIPHER_TLSV1_1:
317 case EFL_NET_SSL_CIPHER_TLSV1_2:
318 ctx->ssl_ctx = SSL_CTX_new(TLS_server_method());
319 break;
320 #endif
321 default:
322 ERR("ssl_ctx=%p unsupported cipher %d", ctx, cfg.cipher);
323 return EINVAL;
324 }
325
326 EINA_SAFETY_ON_NULL_RETURN_VAL(ctx->ssl_ctx, ENOSYS);
327 }
328
329 options = SSL_CTX_get_options(ctx->ssl_ctx);
330 options |= SSL_OP_NO_SSLv2;
331 options |= SSL_OP_SINGLE_DH_USE;
332 options |= SSL_OP_NO_SSLv3;
333
334 SSL_CTX_set_options(ctx->ssl_ctx, options);
335
336 err = _efl_net_ssl_ctx_load_lists(ctx, cfg);
337 if (err)
338 {
339 ERR("ssl_ctx=%p failed to load certificate, private keys, CRL or CA", ctx);
340 goto error;
341 }
342
343 return 0;
344
345 error:
346 SSL_CTX_free(ctx->ssl_ctx);
347 ctx->ssl_ctx = NULL;
348 return err;
349 }
350
351 static void
efl_net_ssl_ctx_teardown(Efl_Net_Ssl_Ctx * ctx)352 efl_net_ssl_ctx_teardown(Efl_Net_Ssl_Ctx *ctx)
353 {
354 if (ctx->ssl_ctx)
355 {
356 SSL_CTX_free(ctx->ssl_ctx);
357 ctx->ssl_ctx = NULL;
358 }
359 }
360
361 static Eina_Error
efl_net_ssl_ctx_verify_mode_set(Efl_Net_Ssl_Ctx * ctx,Efl_Net_Ssl_Verify_Mode verify_mode)362 efl_net_ssl_ctx_verify_mode_set(Efl_Net_Ssl_Ctx *ctx, Efl_Net_Ssl_Verify_Mode verify_mode)
363 {
364 int ssl_mode;
365
366 switch (verify_mode)
367 {
368 case EFL_NET_SSL_VERIFY_MODE_NONE:
369 ssl_mode = SSL_VERIFY_NONE;
370 break;
371 case EFL_NET_SSL_VERIFY_MODE_OPTIONAL:
372 ssl_mode = SSL_VERIFY_PEER;
373 break;
374 case EFL_NET_SSL_VERIFY_MODE_REQUIRED:
375 ssl_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
376 break;
377 default:
378 ERR("unknown verify_mode=%d", verify_mode);
379 return EINVAL;
380 }
381
382 SSL_CTX_set_verify(ctx->ssl_ctx, ssl_mode, SSL_CTX_get_verify_callback(ctx->ssl_ctx));
383 return 0;
384 }
385
386 static Eina_Error
efl_net_ssl_ctx_hostname_verify_set(Efl_Net_Ssl_Ctx * ctx EINA_UNUSED,Eina_Bool hostname_verify EINA_UNUSED)387 efl_net_ssl_ctx_hostname_verify_set(Efl_Net_Ssl_Ctx *ctx EINA_UNUSED, Eina_Bool hostname_verify EINA_UNUSED)
388 {
389 return 0;
390 }
391
392 static Eina_Error
efl_net_ssl_ctx_hostname_set(Efl_Net_Ssl_Ctx * ctx EINA_UNUSED,const char * hostname EINA_UNUSED)393 efl_net_ssl_ctx_hostname_set(Efl_Net_Ssl_Ctx *ctx EINA_UNUSED, const char *hostname EINA_UNUSED)
394 {
395 return 0;
396 }
397