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