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 27#if defined(LWS_WITH_SERVER) 28 29static void 30lws_sul_tls_cb(lws_sorted_usec_list_t *sul) 31{ 32 struct lws_context_per_thread *pt = lws_container_of(sul, 33 struct lws_context_per_thread, sul_tls); 34 35 lws_tls_check_all_cert_lifetimes(pt->context); 36 37 __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], 38 &pt->sul_tls, 39 (lws_usec_t)24 * 3600 * LWS_US_PER_SEC); 40} 41 42int 43lws_context_init_server_ssl(const struct lws_context_creation_info *info, 44 struct lws_vhost *vhost) 45{ 46 struct lws_context *context = vhost->context; 47 lws_fakewsi_def_plwsa(&vhost->context->pt[0]); 48 49 lws_fakewsi_prep_plwsa_ctx(vhost->context); 50 51 if (!lws_check_opt(info->options, 52 LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) { 53 vhost->tls.use_ssl = 0; 54 55 return 0; 56 } 57 58 /* 59 * If he is giving a server cert, take it as a sign he wants to use 60 * it on this vhost. User code can leave the cert filepath NULL and 61 * set the LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX option itself, in 62 * which case he's expected to set up the cert himself at 63 * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, which 64 * provides the vhost SSL_CTX * in the user parameter. 65 */ 66 if (info->ssl_cert_filepath || info->server_ssl_cert_mem) 67 vhost->options |= LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX; 68 69 if (info->port != CONTEXT_PORT_NO_LISTEN) { 70 71 vhost->tls.use_ssl = lws_check_opt(vhost->options, 72 LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX); 73 74 if (vhost->tls.use_ssl && info->ssl_cipher_list) 75 lwsl_notice(" SSL ciphers: '%s'\n", 76 info->ssl_cipher_list); 77 78 lwsl_notice(" Vhost '%s' using %sTLS mode\n", 79 vhost->name, vhost->tls.use_ssl ? "" : "non-"); 80 } 81 82 /* 83 * give him a fake wsi with context + vhost set, so he can use 84 * lws_get_context() in the callback 85 */ 86 plwsa->vhost = vhost; /* not a real bound wsi */ 87 88 /* 89 * as a server, if we are requiring clients to identify themselves 90 * then set the backend up for it 91 */ 92 if (lws_check_opt(info->options, 93 LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT)) 94 /* Normally SSL listener rejects non-ssl, optionally allow */ 95 vhost->tls.allow_non_ssl_on_ssl_port = 1; 96 97 /* 98 * give user code a chance to load certs into the server 99 * allowing it to verify incoming client certs 100 */ 101 if (vhost->tls.use_ssl) { 102 if (lws_tls_server_vhost_backend_init(info, vhost, (struct lws *)plwsa)) 103 return -1; 104 105 lws_tls_server_client_cert_verify_config(vhost); 106 107 if (vhost->protocols[0].callback((struct lws *)plwsa, 108 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, 109 vhost->tls.ssl_ctx, vhost, 0)) 110 return -1; 111 } 112 113 if (vhost->tls.use_ssl) 114 lws_context_init_alpn(vhost); 115 116 /* check certs in a few seconds (after protocol init) and then once a day */ 117 118 context->pt[0].sul_tls.cb = lws_sul_tls_cb; 119 __lws_sul_insert_us(&context->pt[0].pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], 120 &context->pt[0].sul_tls, 121 (lws_usec_t)5 * LWS_US_PER_SEC); 122 123 return 0; 124} 125#endif 126 127int 128lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd, char from_pollin) 129{ 130 struct lws_context *context = wsi->a.context; 131 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; 132 struct lws_vhost *vh; 133 ssize_t s; 134 int n; 135 136 if (!LWS_SSL_ENABLED(wsi->a.vhost)) 137 return 0; 138 139 switch (lwsi_state(wsi)) { 140 case LRS_SSL_INIT: 141 142 if (wsi->tls.ssl) 143 lwsl_err("%s: leaking ssl\n", __func__); 144 if (accept_fd == LWS_SOCK_INVALID) 145 assert(0); 146 147 if (lws_tls_restrict_borrow(wsi)) { 148 lwsl_err("%s: failed on ssl restriction\n", __func__); 149 return 1; 150 } 151 152 if (lws_tls_server_new_nonblocking(wsi, accept_fd)) { 153 lwsl_err("%s: failed on lws_tls_server_new_nonblocking\n", __func__); 154 if (accept_fd != LWS_SOCK_INVALID) 155 compatible_close(accept_fd); 156 lws_tls_restrict_return(wsi); 157 goto fail; 158 } 159 160 /* 161 * we are not accepted yet, but we need to enter ourselves 162 * as a live connection. That way we can retry when more 163 * pieces come if we're not sorted yet 164 */ 165 lwsi_set_state(wsi, LRS_SSL_ACK_PENDING); 166 167 lws_pt_lock(pt, __func__); 168 if (__insert_wsi_socket_into_fds(context, wsi)) { 169 lwsl_err("%s: failed to insert into fds\n", __func__); 170 goto fail; 171 } 172 lws_pt_unlock(pt); 173 174 lws_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT, 175 (int)context->timeout_secs); 176 177 lwsl_debug("inserted SSL accept into fds, trying SSL_accept\n"); 178 179 /* fallthru */ 180 181 case LRS_SSL_ACK_PENDING: 182 183 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) { 184 lwsl_err("%s: lws_change_pollfd failed\n", __func__); 185 goto fail; 186 } 187 188 if (wsi->a.vhost->tls.allow_non_ssl_on_ssl_port && !wsi->skip_fallback) { 189 /* 190 * We came here by POLLIN, so there is supposed to be 191 * something to read... 192 */ 193 194 s = recv(wsi->desc.sockfd, (char *)pt->serv_buf, 195 context->pt_serv_buf_size, MSG_PEEK); 196 /* 197 * We have LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT.. 198 * this just means don't hang up on him because of no 199 * tls hello... what happens next is driven by 200 * additional option flags: 201 * 202 * none: fail the connection 203 * 204 * LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS: 205 * Destroy the TLS, issue a redirect using plaintext 206 * http (this may not be accepted by a client that 207 * has visited the site before and received an STS 208 * header). 209 * 210 * LWS_SERVER_OPTION_ALLOW_HTTP_ON_HTTPS_LISTENER: 211 * Destroy the TLS, continue and serve normally 212 * using http 213 * 214 * LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG: 215 * Destroy the TLS, apply whatever role and protocol 216 * were told in the vhost info struct 217 * .listen_accept_role / .listen_accept_protocol and 218 * continue with that 219 */ 220 221 if (s >= 1 && pt->serv_buf[0] >= ' ') { 222 /* 223 * TLS content-type for Handshake is 0x16, and 224 * for ChangeCipherSpec Record, it's 0x14 225 * 226 * A non-ssl session will start with the HTTP 227 * method in ASCII. If we see it's not a legit 228 * SSL handshake kill the SSL for this 229 * connection and try to handle as a HTTP 230 * connection upgrade directly. 231 */ 232 wsi->tls.use_ssl = 0; 233 234 lws_tls_server_abort_connection(wsi); 235 /* 236 * care... this creates wsi with no ssl when ssl 237 * is enabled and normally mandatory 238 */ 239 wsi->tls.ssl = NULL; 240 241 if (lws_check_opt(wsi->a.vhost->options, 242 LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS)) { 243 lwsl_info("%s: redirecting from http " 244 "to https\n", __func__); 245 wsi->tls.redirect_to_https = 1; 246 goto notls_accepted; 247 } 248 249 if (lws_check_opt(wsi->a.vhost->options, 250 LWS_SERVER_OPTION_ALLOW_HTTP_ON_HTTPS_LISTENER)) { 251 lwsl_info("%s: allowing unencrypted " 252 "http service on tls port\n", 253 __func__); 254 goto notls_accepted; 255 } 256 257 if (lws_check_opt(wsi->a.vhost->options, 258 LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG)) { 259 if (lws_http_to_fallback(wsi, NULL, 0)) 260 goto fail; 261 lwsl_info("%s: allowing non-tls " 262 "fallback\n", __func__); 263 goto notls_accepted; 264 } 265 266 lwsl_notice("%s: client did not send a valid " 267 "tls hello (default vhost %s)\n", 268 __func__, wsi->a.vhost->name); 269 goto fail; 270 } 271 if (!s) { 272 /* 273 * POLLIN but nothing to read is supposed to 274 * mean the connection is gone, we should 275 * fail out... 276 * 277 */ 278 lwsl_debug("%s: PEEKed 0 (from_pollin %d)\n", 279 __func__, from_pollin); 280 if (!from_pollin) 281 /* 282 * If this wasn't actually info from a 283 * pollin let it go around again until 284 * either data came or we still get told 285 * zero length peek AND POLLIN 286 */ 287 goto punt; 288 289 /* 290 * treat as remote closed 291 */ 292 293 goto fail; 294 } 295 if (s < 0 && (LWS_ERRNO == LWS_EAGAIN || 296 LWS_ERRNO == LWS_EWOULDBLOCK)) { 297 298punt: 299 /* 300 * well, we get no way to know ssl or not 301 * so go around again waiting for something 302 * to come and give us a hint, or timeout the 303 * connection. 304 */ 305 if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { 306 lwsl_err("%s: change_pollfd failed\n", 307 __func__); 308 return -1; 309 } 310 311 lwsl_info("SSL_ERROR_WANT_READ\n"); 312 return 0; 313 } 314 } 315 316 /* normal SSL connection processing path */ 317 318 errno = 0; 319 n = lws_tls_server_accept(wsi); 320 lwsl_info("SSL_accept says %d\n", n); 321 switch (n) { 322 case LWS_SSL_CAPABLE_DONE: 323 lws_tls_restrict_return_handshake(wsi); 324 break; 325 case LWS_SSL_CAPABLE_ERROR: 326 lws_tls_restrict_return_handshake(wsi); 327 lwsl_info("%s: SSL_accept failed socket %u: %d\n", 328 __func__, wsi->desc.sockfd, n); 329 wsi->socket_is_permanently_unusable = 1; 330 goto fail; 331 332 default: /* MORE_SERVICE */ 333 return 0; 334 } 335 336 /* adapt our vhost to match the SNI SSL_CTX that was chosen */ 337 vh = context->vhost_list; 338 while (vh) { 339 if (!vh->being_destroyed && wsi->tls.ssl && 340 vh->tls.ssl_ctx == lws_tls_ctx_from_wsi(wsi)) { 341 lwsl_info("setting wsi to vh %s\n", vh->name); 342 lws_vhost_bind_wsi(vh, wsi); 343 break; 344 } 345 vh = vh->vhost_next; 346 } 347 348 /* OK, we are accepted... give him some time to negotiate */ 349 lws_set_timeout(wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER, 350 (int)context->timeout_secs); 351 352 lwsi_set_state(wsi, LRS_ESTABLISHED); 353 if (lws_tls_server_conn_alpn(wsi)) { 354 lwsl_warn("%s: fail on alpn\n", __func__); 355 goto fail; 356 } 357 lwsl_debug("accepted new SSL conn\n"); 358 break; 359 360 default: 361 break; 362 } 363 364 return 0; 365 366notls_accepted: 367 lwsi_set_state(wsi, LRS_ESTABLISHED); 368 369 return 0; 370 371fail: 372 return 1; 373} 374 375