/src/libwebsockets/lib/tls/openssl/openssl-ssl.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * libwebsockets - small server side websockets and web server implementation |
3 | | * |
4 | | * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> |
5 | | * |
6 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | | * of this software and associated documentation files (the "Software"), to |
8 | | * deal in the Software without restriction, including without limitation the |
9 | | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
10 | | * sell copies of the Software, and to permit persons to whom the Software is |
11 | | * furnished to do so, subject to the following conditions: |
12 | | * |
13 | | * The above copyright notice and this permission notice shall be included in |
14 | | * all copies or substantial portions of the Software. |
15 | | * |
16 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
19 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
20 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
21 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
22 | | * IN THE SOFTWARE. |
23 | | */ |
24 | | |
25 | | #include "private-lib-core.h" |
26 | | #include "private-lib-tls-openssl.h" |
27 | | |
28 | | int openssl_websocket_private_data_index, |
29 | | openssl_SSL_CTX_private_data_index; |
30 | | |
31 | | /* |
32 | | * Care: many openssl apis return 1 for success. These are translated to the |
33 | | * lws convention of 0 for success. |
34 | | */ |
35 | | |
36 | | int lws_openssl_describe_cipher(struct lws *wsi) |
37 | 0 | { |
38 | 0 | #if !defined(LWS_WITH_NO_LOGS) && !defined(USE_WOLFSSL) |
39 | 0 | int np = -1; |
40 | 0 | SSL *s = wsi->tls.ssl; |
41 | |
|
42 | 0 | SSL_get_cipher_bits(s, &np); |
43 | 0 | lwsl_info("%s: %s: %s, %s, %d bits, %s\n", __func__, lws_wsi_tag(wsi), |
44 | 0 | SSL_get_cipher_name(s), SSL_get_cipher(s), np, |
45 | 0 | SSL_get_cipher_version(s)); |
46 | 0 | #endif |
47 | |
|
48 | 0 | return 0; |
49 | 0 | } |
50 | | |
51 | | int lws_ssl_get_error(struct lws *wsi, int n) |
52 | 0 | { |
53 | 0 | int m; |
54 | 0 | unsigned long l; |
55 | 0 | char buf[160]; |
56 | |
|
57 | 0 | if (!wsi->tls.ssl) |
58 | 0 | return 99; |
59 | | |
60 | 0 | m = SSL_get_error(wsi->tls.ssl, n); |
61 | 0 | lwsl_debug("%s: %p %d -> %d (errno %d)\n", __func__, wsi->tls.ssl, n, m, LWS_ERRNO); |
62 | 0 | if (m == SSL_ERROR_SSL) { |
63 | 0 | if (!wsi->tls.err_helper[0]) { |
64 | | /* Append first error for clarity */ |
65 | 0 | l = ERR_get_error(); |
66 | 0 | if (l) { |
67 | 0 | ERR_error_string_n( |
68 | | #if defined(LWS_WITH_BORINGSSL) || defined(LWS_WITH_AWSLC) |
69 | | (uint32_t) |
70 | | #endif |
71 | 0 | l, buf, sizeof(buf) - 1); |
72 | 0 | buf[sizeof(buf) - 1] = '\0'; |
73 | 0 | lws_strncpy(wsi->tls.err_helper, buf, |
74 | 0 | sizeof(wsi->tls.err_helper)); |
75 | 0 | } |
76 | 0 | } |
77 | | |
78 | | // Describe other errors |
79 | 0 | lws_tls_err_describe_clear(); |
80 | 0 | } |
81 | | |
82 | | // assert (LWS_ERRNO != 9); |
83 | |
|
84 | 0 | return m; |
85 | 0 | } |
86 | | |
87 | | #if defined(LWS_WITH_SERVER) |
88 | | static int |
89 | | lws_context_init_ssl_pem_passwd_cb(char *buf, int size, int rwflag, |
90 | | void *userdata) |
91 | 0 | { |
92 | 0 | struct lws_context_creation_info * info = |
93 | 0 | (struct lws_context_creation_info *)userdata; |
94 | |
|
95 | 0 | strncpy(buf, info->ssl_private_key_password, (unsigned int)size); |
96 | 0 | buf[size - 1] = '\0'; |
97 | |
|
98 | 0 | return (int)strlen(buf); |
99 | 0 | } |
100 | | #endif |
101 | | |
102 | | #if defined(LWS_WITH_CLIENT) |
103 | | static int |
104 | | lws_context_init_ssl_pem_passwd_client_cb(char *buf, int size, int rwflag, |
105 | | void *userdata) |
106 | 0 | { |
107 | 0 | struct lws_context_creation_info * info = |
108 | 0 | (struct lws_context_creation_info *)userdata; |
109 | 0 | const char *p = info->ssl_private_key_password; |
110 | |
|
111 | 0 | if (info->client_ssl_private_key_password) |
112 | 0 | p = info->client_ssl_private_key_password; |
113 | |
|
114 | 0 | strncpy(buf, p, (unsigned int)size); |
115 | 0 | buf[size - 1] = '\0'; |
116 | |
|
117 | 0 | return (int)strlen(buf); |
118 | 0 | } |
119 | | #endif |
120 | | |
121 | | void |
122 | | lws_ssl_bind_passphrase(SSL_CTX *ssl_ctx, int is_client, |
123 | | const struct lws_context_creation_info *info) |
124 | 0 | { |
125 | 0 | if ( |
126 | 0 | #if defined(LWS_WITH_SERVER) |
127 | 0 | !info->ssl_private_key_password |
128 | 0 | #endif |
129 | 0 | #if defined(LWS_WITH_SERVER) && defined(LWS_WITH_CLIENT) |
130 | 0 | && |
131 | 0 | #endif |
132 | 0 | #if defined(LWS_WITH_CLIENT) |
133 | 0 | !info->client_ssl_private_key_password |
134 | 0 | #endif |
135 | 0 | ) |
136 | 0 | return; |
137 | | /* |
138 | | * password provided, set ssl callback and user data |
139 | | * for checking password which will be trigered during |
140 | | * SSL_CTX_use_PrivateKey_file function |
141 | | */ |
142 | 0 | SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, (void *)info); |
143 | 0 | SSL_CTX_set_default_passwd_cb(ssl_ctx, is_client ? |
144 | 0 | #if defined(LWS_WITH_CLIENT) |
145 | 0 | lws_context_init_ssl_pem_passwd_client_cb: |
146 | | #else |
147 | | NULL: |
148 | | #endif |
149 | 0 | #if defined(LWS_WITH_SERVER) |
150 | 0 | lws_context_init_ssl_pem_passwd_cb |
151 | | #else |
152 | | NULL |
153 | | #endif |
154 | 0 | ); |
155 | 0 | } |
156 | | |
157 | | #if defined(LWS_WITH_CLIENT) |
158 | | static void |
159 | | lws_ssl_destroy_client_ctx(struct lws_vhost *vhost) |
160 | 0 | { |
161 | 0 | if (vhost->tls.user_supplied_ssl_ctx || !vhost->tls.ssl_client_ctx) |
162 | 0 | return; |
163 | | |
164 | 0 | if (vhost->tls.tcr && --vhost->tls.tcr->refcount) |
165 | 0 | return; |
166 | | |
167 | 0 | SSL_CTX_free(vhost->tls.ssl_client_ctx); |
168 | 0 | vhost->tls.ssl_client_ctx = NULL; |
169 | |
|
170 | 0 | vhost->context->tls.count_client_contexts--; |
171 | |
|
172 | 0 | if (vhost->tls.tcr) { |
173 | 0 | lws_dll2_remove(&vhost->tls.tcr->cc_list); |
174 | 0 | lws_free(vhost->tls.tcr); |
175 | 0 | vhost->tls.tcr = NULL; |
176 | 0 | } |
177 | 0 | } |
178 | | #endif |
179 | | void |
180 | | lws_ssl_destroy(struct lws_vhost *vhost) |
181 | 0 | { |
182 | 0 | if (!lws_check_opt(vhost->context->options, |
183 | 0 | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) |
184 | 0 | return; |
185 | | |
186 | 0 | if (vhost->tls.ssl_ctx) |
187 | 0 | SSL_CTX_free(vhost->tls.ssl_ctx); |
188 | 0 | #if defined(LWS_WITH_CLIENT) |
189 | 0 | lws_ssl_destroy_client_ctx(vhost); |
190 | 0 | #endif |
191 | | |
192 | | // after 1.1.0 no need |
193 | | #if (OPENSSL_VERSION_NUMBER < 0x10100000) |
194 | | // <= 1.0.1f = old api, 1.0.1g+ = new api |
195 | | #if (OPENSSL_VERSION_NUMBER <= 0x1000106f) || defined(USE_WOLFSSL) |
196 | | ERR_remove_state(0); |
197 | | #else |
198 | | #if OPENSSL_VERSION_NUMBER >= 0x1010005f && \ |
199 | | !defined(LIBRESSL_VERSION_NUMBER) && \ |
200 | | !defined(OPENSSL_IS_BORINGSSL) && \ |
201 | | !defined(OPENSSL_IS_AWSLC) |
202 | | ERR_remove_thread_state(); |
203 | | #else |
204 | | ERR_remove_thread_state(NULL); |
205 | | #endif |
206 | | #endif |
207 | | /* not needed after 1.1.0 */ |
208 | | #if (OPENSSL_VERSION_NUMBER >= 0x10002000) && \ |
209 | | (OPENSSL_VERSION_NUMBER <= 0x10100000) |
210 | | SSL_COMP_free_compression_methods(); |
211 | | #endif |
212 | | ERR_free_strings(); |
213 | | EVP_cleanup(); |
214 | | CRYPTO_cleanup_all_ex_data(); |
215 | | #endif |
216 | 0 | } |
217 | | |
218 | | int |
219 | | lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, size_t len) |
220 | 0 | { |
221 | 0 | struct lws_context *context = wsi->a.context; |
222 | 0 | struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; |
223 | 0 | int n = 0, m; |
224 | |
|
225 | 0 | if (!wsi->tls.ssl) |
226 | 0 | return lws_ssl_capable_read_no_ssl(wsi, buf, len); |
227 | | |
228 | 0 | #ifndef WIN32 |
229 | 0 | errno = 0; |
230 | | #else |
231 | | WSASetLastError(0); |
232 | | #endif |
233 | 0 | ERR_clear_error(); |
234 | 0 | n = SSL_read(wsi->tls.ssl, buf, (int)(ssize_t)len); |
235 | | #if defined(LWS_PLAT_FREERTOS) |
236 | | if (!n && errno == LWS_ENOTCONN) { |
237 | | lwsl_debug("%s: SSL_read ENOTCONN\n", lws_wsi_tag(wsi)); |
238 | | return LWS_SSL_CAPABLE_ERROR; |
239 | | } |
240 | | #endif |
241 | |
|
242 | 0 | lwsl_debug("%s: SSL_read says %d\n", lws_wsi_tag(wsi), n); |
243 | | /* manpage: returning 0 means connection shut down |
244 | | * |
245 | | * 2018-09-10: https://github.com/openssl/openssl/issues/1903 |
246 | | * |
247 | | * So, in summary, if you get a 0 or -1 return from SSL_read() / |
248 | | * SSL_write(), you should call SSL_get_error(): |
249 | | * |
250 | | * - If you get back SSL_ERROR_RETURN_ZERO then you know the connection |
251 | | * has been cleanly shutdown by the peer. To fully close the |
252 | | * connection you may choose to call SSL_shutdown() to send a |
253 | | * close_notify back. |
254 | | * |
255 | | * - If you get back SSL_ERROR_SSL then some kind of internal or |
256 | | * protocol error has occurred. More details will be on the SSL error |
257 | | * queue. You can also call SSL_get_shutdown(). If this indicates a |
258 | | * state of SSL_RECEIVED_SHUTDOWN then you know a fatal alert has |
259 | | * been received from the peer (if it had been a close_notify then |
260 | | * SSL_get_error() would have returned SSL_ERROR_RETURN_ZERO). |
261 | | * SSL_ERROR_SSL is considered fatal - you should not call |
262 | | * SSL_shutdown() in this case. |
263 | | * |
264 | | * - If you get back SSL_ERROR_SYSCALL then some kind of fatal (i.e. |
265 | | * non-retryable) error has occurred in a system call. |
266 | | */ |
267 | 0 | if (n <= 0) { |
268 | 0 | m = lws_ssl_get_error(wsi, n); |
269 | 0 | lwsl_debug("%s: ssl err %d errno %d\n", lws_wsi_tag(wsi), m, LWS_ERRNO); |
270 | 0 | if (m == SSL_ERROR_ZERO_RETURN) /* cleanly shut down */ |
271 | 0 | goto do_err; |
272 | | |
273 | 0 | if (m == SSL_ERROR_SSL) |
274 | 0 | lws_tls_err_describe_clear(); |
275 | | |
276 | | /* hm not retryable.. could be 0 size pkt or error */ |
277 | |
|
278 | 0 | if (m == SSL_ERROR_SSL || m == SSL_ERROR_SYSCALL || |
279 | 0 | LWS_ERRNO == LWS_ENOTCONN) { |
280 | | |
281 | | /* unclean, eg closed conn */ |
282 | |
|
283 | 0 | wsi->socket_is_permanently_unusable = 1; |
284 | 0 | do_err: |
285 | | #if defined(LWS_WITH_SYS_METRICS) |
286 | | if (wsi->a.vhost) |
287 | | lws_metric_event(wsi->a.vhost->mt_traffic_rx, |
288 | | METRES_NOGO, 0); |
289 | | #endif |
290 | 0 | return LWS_SSL_CAPABLE_ERROR; |
291 | 0 | } |
292 | | |
293 | | /* retryable? */ |
294 | | |
295 | 0 | if (SSL_want_read(wsi->tls.ssl)) { |
296 | 0 | lwsl_debug("%s: WANT_READ\n", __func__); |
297 | 0 | lwsl_debug("%s: LWS_SSL_CAPABLE_MORE_SERVICE\n", lws_wsi_tag(wsi)); |
298 | 0 | return LWS_SSL_CAPABLE_MORE_SERVICE; |
299 | 0 | } |
300 | 0 | if (SSL_want_write(wsi->tls.ssl)) { |
301 | 0 | lwsl_info("%s: WANT_WRITE\n", __func__); |
302 | 0 | lwsl_debug("%s: LWS_SSL_CAPABLE_MORE_SERVICE\n", lws_wsi_tag(wsi)); |
303 | 0 | wsi->tls_read_wanted_write = 1; |
304 | 0 | lws_callback_on_writable(wsi); |
305 | 0 | return LWS_SSL_CAPABLE_MORE_SERVICE; |
306 | 0 | } |
307 | | |
308 | | /* keep on trucking it seems */ |
309 | 0 | } |
310 | | |
311 | | #if defined(LWS_TLS_LOG_PLAINTEXT_RX) |
312 | | /* |
313 | | * If using openssl type tls library, this is the earliest point for all |
314 | | * paths to dump what was received as decrypted data from the tls tunnel |
315 | | */ |
316 | | lwsl_notice("%s: len %d\n", __func__, n); |
317 | | lwsl_hexdump_notice(buf, (unsigned int)n); |
318 | | #endif |
319 | | |
320 | | #if defined(LWS_WITH_SYS_METRICS) |
321 | | if (wsi->a.vhost) |
322 | | lws_metric_event(wsi->a.vhost->mt_traffic_rx, METRES_GO, (u_mt_t)n); |
323 | | #endif |
324 | | |
325 | | /* |
326 | | * if it was our buffer that limited what we read, |
327 | | * check if SSL has additional data pending inside SSL buffers. |
328 | | * |
329 | | * Because these won't signal at the network layer with POLLIN |
330 | | * and if we don't realize, this data will sit there forever |
331 | | */ |
332 | 0 | if (n != (int)(ssize_t)len) |
333 | 0 | goto bail; |
334 | 0 | if (!wsi->tls.ssl) |
335 | 0 | goto bail; |
336 | | |
337 | 0 | if (SSL_pending(wsi->tls.ssl)) { |
338 | 0 | if (lws_dll2_is_detached(&wsi->tls.dll_pending_tls)) |
339 | 0 | lws_dll2_add_head(&wsi->tls.dll_pending_tls, |
340 | 0 | &pt->tls.dll_pending_tls_owner); |
341 | 0 | } else |
342 | 0 | __lws_ssl_remove_wsi_from_buffered_list(wsi); |
343 | |
|
344 | 0 | return n; |
345 | 0 | bail: |
346 | 0 | lws_ssl_remove_wsi_from_buffered_list(wsi); |
347 | |
|
348 | 0 | return n; |
349 | 0 | } |
350 | | |
351 | | int |
352 | | lws_ssl_pending(struct lws *wsi) |
353 | 0 | { |
354 | 0 | if (!wsi->tls.ssl) |
355 | 0 | return 0; |
356 | | |
357 | 0 | return SSL_pending(wsi->tls.ssl); |
358 | 0 | } |
359 | | |
360 | | int |
361 | | lws_ssl_capable_write(struct lws *wsi, unsigned char *buf, size_t len) |
362 | 0 | { |
363 | 0 | int n, m; |
364 | | |
365 | |
|
366 | | #if defined(LWS_TLS_LOG_PLAINTEXT_TX) |
367 | | /* |
368 | | * If using OpenSSL type tls library, this is the last point for all |
369 | | * paths before sending data into the tls tunnel, where you can dump it |
370 | | * and see what is being sent. |
371 | | */ |
372 | | lwsl_notice("%s: len %u\n", __func__, (unsigned int)len); |
373 | | lwsl_hexdump_notice(buf, len); |
374 | | #endif |
375 | |
|
376 | 0 | if (!wsi->tls.ssl) |
377 | 0 | return lws_ssl_capable_write_no_ssl(wsi, buf, len); |
378 | | |
379 | 0 | errno = 0; |
380 | 0 | ERR_clear_error(); |
381 | 0 | n = SSL_write(wsi->tls.ssl, buf, (int)(ssize_t)len); |
382 | 0 | if (n > 0) { |
383 | | #if defined(LWS_WITH_SYS_METRICS) |
384 | | if (wsi->a.vhost) |
385 | | lws_metric_event(wsi->a.vhost->mt_traffic_tx, |
386 | | METRES_GO, (u_mt_t)n); |
387 | | #endif |
388 | 0 | return n; |
389 | 0 | } |
390 | | |
391 | 0 | m = lws_ssl_get_error(wsi, n); |
392 | 0 | if (m != SSL_ERROR_SYSCALL) { |
393 | 0 | if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) { |
394 | 0 | lwsl_notice("%s: want read\n", __func__); |
395 | |
|
396 | 0 | return LWS_SSL_CAPABLE_MORE_SERVICE; |
397 | 0 | } |
398 | | |
399 | 0 | if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) { |
400 | 0 | lws_set_blocking_send(wsi); |
401 | |
|
402 | 0 | lwsl_debug("%s: want write\n", __func__); |
403 | |
|
404 | 0 | return LWS_SSL_CAPABLE_MORE_SERVICE; |
405 | 0 | } |
406 | 0 | } |
407 | | |
408 | 0 | lwsl_debug("%s failed: %s\n",__func__, ERR_error_string((unsigned int)m, NULL)); |
409 | 0 | lws_tls_err_describe_clear(); |
410 | |
|
411 | 0 | wsi->socket_is_permanently_unusable = 1; |
412 | |
|
413 | | #if defined(LWS_WITH_SYS_METRICS) |
414 | | if (wsi->a.vhost) |
415 | | lws_metric_event(wsi->a.vhost->mt_traffic_tx, |
416 | | METRES_NOGO, 0); |
417 | | #endif |
418 | |
|
419 | 0 | return LWS_SSL_CAPABLE_ERROR; |
420 | 0 | } |
421 | | |
422 | | void |
423 | | lws_ssl_info_callback(const SSL *ssl, int where, int ret) |
424 | 0 | { |
425 | 0 | struct lws *wsi; |
426 | 0 | struct lws_context *context; |
427 | 0 | struct lws_ssl_info si; |
428 | 0 | int fd; |
429 | |
|
430 | 0 | #ifndef USE_WOLFSSL |
431 | 0 | context = (struct lws_context *)SSL_CTX_get_ex_data( |
432 | 0 | SSL_get_SSL_CTX(ssl), |
433 | 0 | openssl_SSL_CTX_private_data_index); |
434 | | #else |
435 | | context = (struct lws_context *)SSL_CTX_get_ex_data( |
436 | | SSL_get_SSL_CTX((SSL*) ssl), |
437 | | openssl_SSL_CTX_private_data_index); |
438 | | #endif |
439 | 0 | if (!context) |
440 | 0 | return; |
441 | | |
442 | 0 | fd = SSL_get_fd(ssl); |
443 | 0 | if (fd < 0 || (fd - lws_plat_socket_offset()) < 0) |
444 | 0 | return; |
445 | | |
446 | 0 | wsi = wsi_from_fd(context, fd); |
447 | 0 | if (!wsi) |
448 | 0 | return; |
449 | | |
450 | 0 | if (!(where & wsi->a.vhost->tls.ssl_info_event_mask)) |
451 | 0 | return; |
452 | | |
453 | 0 | si.where = where; |
454 | 0 | si.ret = ret; |
455 | |
|
456 | 0 | if (user_callback_handle_rxflow(wsi->a.protocol->callback, |
457 | 0 | wsi, LWS_CALLBACK_SSL_INFO, |
458 | 0 | wsi->user_space, &si, 0)) |
459 | 0 | lws_set_timeout(wsi, PENDING_TIMEOUT_KILLED_BY_SSL_INFO, -1); |
460 | 0 | } |
461 | | |
462 | | |
463 | | int |
464 | | lws_ssl_close(struct lws *wsi) |
465 | 0 | { |
466 | 0 | lws_sockfd_type n; |
467 | |
|
468 | 0 | if (!wsi->tls.ssl) |
469 | 0 | return 0; /* not handled */ |
470 | | |
471 | 0 | #if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK) |
472 | | /* kill ssl callbacks, because we will remove the fd from the |
473 | | * table linking it to the wsi |
474 | | */ |
475 | 0 | if (wsi->a.vhost->tls.ssl_info_event_mask) |
476 | 0 | SSL_set_info_callback(wsi->tls.ssl, NULL); |
477 | 0 | #endif |
478 | |
|
479 | | #if defined(LWS_TLS_SYNTHESIZE_CB) |
480 | | lws_sul_cancel(&wsi->tls.sul_cb_synth); |
481 | | /* |
482 | | * ... check the session in case it did not live long enough to get |
483 | | * the scheduled callback to sample it |
484 | | */ |
485 | | lws_sess_cache_synth_cb(&wsi->tls.sul_cb_synth); |
486 | | #endif |
487 | |
|
488 | 0 | n = SSL_get_fd(wsi->tls.ssl); |
489 | 0 | if (!wsi->socket_is_permanently_unusable) |
490 | 0 | SSL_shutdown(wsi->tls.ssl); |
491 | 0 | compatible_close(n); |
492 | 0 | SSL_free(wsi->tls.ssl); |
493 | 0 | wsi->tls.ssl = NULL; |
494 | |
|
495 | 0 | lws_tls_restrict_return(wsi); |
496 | | |
497 | | // lwsl_notice("%s: ssl restr %d, simul %d\n", __func__, |
498 | | // wsi->a.context->simultaneous_ssl_restriction, |
499 | | // wsi->a.context->simultaneous_ssl); |
500 | |
|
501 | 0 | return 1; /* handled */ |
502 | 0 | } |
503 | | |
504 | | void |
505 | | lws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost) |
506 | 0 | { |
507 | 0 | if (vhost->tls.ssl_ctx) |
508 | 0 | SSL_CTX_free(vhost->tls.ssl_ctx); |
509 | |
|
510 | 0 | #if defined(LWS_WITH_CLIENT) |
511 | 0 | lws_ssl_destroy_client_ctx(vhost); |
512 | 0 | #endif |
513 | |
|
514 | | #if defined(LWS_WITH_ACME) |
515 | | lws_tls_acme_sni_cert_destroy(vhost); |
516 | | #endif |
517 | 0 | } |
518 | | |
519 | | void |
520 | | lws_ssl_context_destroy(struct lws_context *context) |
521 | 0 | { |
522 | | // after 1.1.0 no need |
523 | | #if (OPENSSL_VERSION_NUMBER < 0x10100000) |
524 | | // <= 1.0.1f = old api, 1.0.1g+ = new api |
525 | | #if (OPENSSL_VERSION_NUMBER <= 0x1000106f) || defined(USE_WOLFSSL) |
526 | | ERR_remove_state(0); |
527 | | #else |
528 | | #if OPENSSL_VERSION_NUMBER >= 0x1010005f && \ |
529 | | !defined(LIBRESSL_VERSION_NUMBER) && \ |
530 | | !defined(OPENSSL_IS_BORINGSSL) && \ |
531 | | !defined(OPENSSL_IS_AWSLC) |
532 | | ERR_remove_thread_state(); |
533 | | #else |
534 | | ERR_remove_thread_state(NULL); |
535 | | #endif |
536 | | #endif |
537 | | // after 1.1.0 no need |
538 | | #if (OPENSSL_VERSION_NUMBER >= 0x10002000) && (OPENSSL_VERSION_NUMBER <= 0x10100000) |
539 | | SSL_COMP_free_compression_methods(); |
540 | | #endif |
541 | | ERR_free_strings(); |
542 | | EVP_cleanup(); |
543 | | CRYPTO_cleanup_all_ex_data(); |
544 | | #endif |
545 | 0 | } |
546 | | |
547 | | lws_tls_ctx * |
548 | | lws_tls_ctx_from_wsi(struct lws *wsi) |
549 | 0 | { |
550 | 0 | if (!wsi->tls.ssl) |
551 | 0 | return NULL; |
552 | | |
553 | 0 | return SSL_get_SSL_CTX(wsi->tls.ssl); |
554 | 0 | } |
555 | | |
556 | | enum lws_ssl_capable_status |
557 | | __lws_tls_shutdown(struct lws *wsi) |
558 | 0 | { |
559 | 0 | int n; |
560 | |
|
561 | 0 | #ifndef WIN32 |
562 | 0 | errno = 0; |
563 | | #else |
564 | | WSASetLastError(0); |
565 | | #endif |
566 | 0 | ERR_clear_error(); |
567 | 0 | n = SSL_shutdown(wsi->tls.ssl); |
568 | 0 | lwsl_debug("SSL_shutdown=%d for fd %d\n", n, wsi->desc.sockfd); |
569 | 0 | switch (n) { |
570 | 0 | case 1: /* successful completion */ |
571 | 0 | n = shutdown(wsi->desc.sockfd, SHUT_WR); |
572 | 0 | return LWS_SSL_CAPABLE_DONE; |
573 | | |
574 | 0 | case 0: /* needs a retry */ |
575 | 0 | __lws_change_pollfd(wsi, 0, LWS_POLLIN); |
576 | 0 | return LWS_SSL_CAPABLE_MORE_SERVICE; |
577 | | |
578 | 0 | default: /* fatal error, or WANT */ |
579 | 0 | n = SSL_get_error(wsi->tls.ssl, n); |
580 | 0 | if (n != SSL_ERROR_SYSCALL && n != SSL_ERROR_SSL) { |
581 | 0 | if (SSL_want_read(wsi->tls.ssl)) { |
582 | 0 | lwsl_debug("(wants read)\n"); |
583 | 0 | __lws_change_pollfd(wsi, 0, LWS_POLLIN); |
584 | 0 | return LWS_SSL_CAPABLE_MORE_SERVICE_READ; |
585 | 0 | } |
586 | 0 | if (SSL_want_write(wsi->tls.ssl)) { |
587 | 0 | lwsl_debug("(wants write)\n"); |
588 | 0 | __lws_change_pollfd(wsi, 0, LWS_POLLOUT); |
589 | 0 | return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE; |
590 | 0 | } |
591 | 0 | } |
592 | 0 | return LWS_SSL_CAPABLE_ERROR; |
593 | 0 | } |
594 | 0 | } |
595 | | |
596 | | |
597 | | static int |
598 | | tops_fake_POLLIN_for_buffered_openssl(struct lws_context_per_thread *pt) |
599 | 0 | { |
600 | 0 | return lws_tls_fake_POLLIN_for_buffered(pt); |
601 | 0 | } |
602 | | |
603 | | const struct lws_tls_ops tls_ops_openssl = { |
604 | | /* fake_POLLIN_for_buffered */ tops_fake_POLLIN_for_buffered_openssl, |
605 | | }; |