| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- /*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
- #include "private-lib-core.h"
- /*
- * fakes POLLIN on all tls guys with buffered rx
- *
- * returns nonzero if any tls guys had POLLIN faked
- */
- int
- lws_tls_fake_POLLIN_for_buffered(struct lws_context_per_thread *pt)
- {
- int ret = 0;
- lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
- lws_dll2_get_head(&pt->tls.dll_pending_tls_owner)) {
- struct lws *wsi = lws_container_of(p, struct lws,
- tls.dll_pending_tls);
- if (wsi->position_in_fds_table >= 0) {
- pt->fds[wsi->position_in_fds_table].revents |=
- pt->fds[wsi->position_in_fds_table].events & LWS_POLLIN;
- ret |= pt->fds[wsi->position_in_fds_table].revents & LWS_POLLIN;
- }
- } lws_end_foreach_dll_safe(p, p1);
- return !!ret;
- }
- void
- __lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi)
- {
- lws_dll2_remove(&wsi->tls.dll_pending_tls);
- }
- void
- lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi)
- {
- struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
- lws_pt_lock(pt, __func__);
- __lws_ssl_remove_wsi_from_buffered_list(wsi);
- lws_pt_unlock(pt);
- }
- #if defined(LWS_WITH_SERVER)
- int
- lws_tls_check_cert_lifetime(struct lws_vhost *v)
- {
- time_t now = (time_t)lws_now_secs(), life = 0;
- struct lws_acme_cert_aging_args caa;
- union lws_tls_cert_info_results ir;
- int n;
- if (v->tls.ssl_ctx && !v->tls.skipped_certs) {
- if (now < 1542933698) /* Nov 23 2018 00:42 UTC */
- /* our clock is wrong and we can't judge the certs */
- return -1;
- n = lws_tls_vhost_cert_info(v, LWS_TLS_CERT_INFO_VALIDITY_TO,
- &ir, 0);
- if (n)
- return 1;
- life = (ir.time - now) / (24 * 3600);
- lwsl_notice(" vhost %s: cert expiry: %dd\n", v->name,
- (int)life);
- } else
- lwsl_info(" vhost %s: no cert\n", v->name);
- memset(&caa, 0, sizeof(caa));
- caa.vh = v;
- lws_broadcast(&v->context->pt[0], LWS_CALLBACK_VHOST_CERT_AGING, (void *)&caa,
- (size_t)(ssize_t)life);
- return 0;
- }
- int
- lws_tls_check_all_cert_lifetimes(struct lws_context *context)
- {
- struct lws_vhost *v = context->vhost_list;
- while (v) {
- if (lws_tls_check_cert_lifetime(v) < 0)
- return -1;
- v = v->vhost_next;
- }
- return 0;
- }
- /*
- * LWS_TLS_EXTANT_NO : skip adding the cert
- * LWS_TLS_EXTANT_YES : use the cert and private key paths normally
- * LWS_TLS_EXTANT_ALTERNATIVE: normal paths not usable, try alternate if poss
- */
- enum lws_tls_extant
- lws_tls_generic_cert_checks(struct lws_vhost *vhost, const char *cert,
- const char *private_key)
- {
- int n, m;
- /*
- * The user code can choose to either pass the cert and
- * key filepaths using the info members like this, or it can
- * leave them NULL; force the vhost SSL_CTX init using the info
- * options flag LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX; and
- * set up the cert himself using the user callback
- * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, which
- * happened just above and has the vhost SSL_CTX * in the user
- * parameter.
- */
- if (!cert || !private_key)
- return LWS_TLS_EXTANT_NO;
- n = lws_tls_use_any_upgrade_check_extant(cert);
- if (n == LWS_TLS_EXTANT_ALTERNATIVE)
- return LWS_TLS_EXTANT_ALTERNATIVE;
- m = lws_tls_use_any_upgrade_check_extant(private_key);
- if (m == LWS_TLS_EXTANT_ALTERNATIVE)
- return LWS_TLS_EXTANT_ALTERNATIVE;
- if ((n == LWS_TLS_EXTANT_NO || m == LWS_TLS_EXTANT_NO) &&
- (vhost->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT)) {
- lwsl_notice("Ignoring missing %s or %s\n", cert, private_key);
- vhost->tls.skipped_certs = 1;
- return LWS_TLS_EXTANT_NO;
- }
- /*
- * the cert + key exist
- */
- return LWS_TLS_EXTANT_YES;
- }
- /*
- * update the cert for every vhost using the given path
- */
- int
- lws_tls_cert_updated(struct lws_context *context, const char *certpath,
- const char *keypath,
- const char *mem_cert, size_t len_mem_cert,
- const char *mem_privkey, size_t len_mem_privkey)
- {
- struct lws wsi;
- wsi.a.context = context;
- lws_start_foreach_ll(struct lws_vhost *, v, context->vhost_list) {
- wsi.a.vhost = v; /* not a real bound wsi */
- if (v->tls.alloc_cert_path && v->tls.key_path &&
- !strcmp(v->tls.alloc_cert_path, certpath) &&
- !strcmp(v->tls.key_path, keypath)) {
- lws_tls_server_certs_load(v, &wsi, certpath, keypath,
- mem_cert, len_mem_cert,
- mem_privkey, len_mem_privkey);
- if (v->tls.skipped_certs)
- lwsl_notice("%s: vhost %s: cert unset\n",
- __func__, v->name);
- }
- } lws_end_foreach_ll(v, vhost_next);
- return 0;
- }
- #endif
- int
- lws_gate_accepts(struct lws_context *context, int on)
- {
- struct lws_vhost *v = context->vhost_list;
- lwsl_notice("%s: on = %d\n", __func__, on);
- #if defined(LWS_WITH_STATS)
- context->updated = 1;
- #endif
- while (v) {
- if (v->tls.use_ssl && v->lserv_wsi &&
- lws_change_pollfd(v->lserv_wsi, (LWS_POLLIN) * !on,
- (LWS_POLLIN) * on))
- lwsl_notice("Unable to set accept POLLIN %d\n", on);
- v = v->vhost_next;
- }
- return 0;
- }
- /* comma-separated alpn list, like "h2,http/1.1" to openssl alpn format */
- int
- lws_alpn_comma_to_openssl(const char *comma, uint8_t *os, int len)
- {
- uint8_t *oos = os, *plen = NULL;
- if (!comma)
- return 0;
- while (*comma && len > 2) {
- if (!plen && *comma == ' ') {
- comma++;
- continue;
- }
- if (!plen) {
- plen = os++;
- len--;
- }
- if (*comma == ',') {
- *plen = lws_ptr_diff(os, plen + 1);
- plen = NULL;
- comma++;
- } else {
- *os++ = *comma++;
- len--;
- }
- }
- if (plen)
- *plen = lws_ptr_diff(os, plen + 1);
- *os = 0;
- return lws_ptr_diff(os, oos);
- }
|