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