tls-network.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
  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. #include "private-lib-core.h"
  25. /*
  26. * fakes POLLIN on all tls guys with buffered rx
  27. *
  28. * returns nonzero if any tls guys had POLLIN faked
  29. */
  30. int
  31. lws_tls_fake_POLLIN_for_buffered(struct lws_context_per_thread *pt)
  32. {
  33. int ret = 0;
  34. lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
  35. lws_dll2_get_head(&pt->tls.dll_pending_tls_owner)) {
  36. struct lws *wsi = lws_container_of(p, struct lws,
  37. tls.dll_pending_tls);
  38. if (wsi->position_in_fds_table >= 0) {
  39. pt->fds[wsi->position_in_fds_table].revents |=
  40. pt->fds[wsi->position_in_fds_table].events & LWS_POLLIN;
  41. ret |= pt->fds[wsi->position_in_fds_table].revents & LWS_POLLIN;
  42. }
  43. } lws_end_foreach_dll_safe(p, p1);
  44. return !!ret;
  45. }
  46. void
  47. __lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi)
  48. {
  49. lws_dll2_remove(&wsi->tls.dll_pending_tls);
  50. }
  51. void
  52. lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi)
  53. {
  54. struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
  55. lws_pt_lock(pt, __func__);
  56. __lws_ssl_remove_wsi_from_buffered_list(wsi);
  57. lws_pt_unlock(pt);
  58. }
  59. #if defined(LWS_WITH_SERVER)
  60. int
  61. lws_tls_check_cert_lifetime(struct lws_vhost *v)
  62. {
  63. time_t now = (time_t)lws_now_secs(), life = 0;
  64. struct lws_acme_cert_aging_args caa;
  65. union lws_tls_cert_info_results ir;
  66. int n;
  67. if (v->tls.ssl_ctx && !v->tls.skipped_certs) {
  68. if (now < 1542933698) /* Nov 23 2018 00:42 UTC */
  69. /* our clock is wrong and we can't judge the certs */
  70. return -1;
  71. n = lws_tls_vhost_cert_info(v, LWS_TLS_CERT_INFO_VALIDITY_TO,
  72. &ir, 0);
  73. if (n)
  74. return 1;
  75. life = (ir.time - now) / (24 * 3600);
  76. lwsl_notice(" vhost %s: cert expiry: %dd\n", v->name,
  77. (int)life);
  78. } else
  79. lwsl_info(" vhost %s: no cert\n", v->name);
  80. memset(&caa, 0, sizeof(caa));
  81. caa.vh = v;
  82. lws_broadcast(&v->context->pt[0], LWS_CALLBACK_VHOST_CERT_AGING, (void *)&caa,
  83. (size_t)(ssize_t)life);
  84. return 0;
  85. }
  86. int
  87. lws_tls_check_all_cert_lifetimes(struct lws_context *context)
  88. {
  89. struct lws_vhost *v = context->vhost_list;
  90. while (v) {
  91. if (lws_tls_check_cert_lifetime(v) < 0)
  92. return -1;
  93. v = v->vhost_next;
  94. }
  95. return 0;
  96. }
  97. /*
  98. * LWS_TLS_EXTANT_NO : skip adding the cert
  99. * LWS_TLS_EXTANT_YES : use the cert and private key paths normally
  100. * LWS_TLS_EXTANT_ALTERNATIVE: normal paths not usable, try alternate if poss
  101. */
  102. enum lws_tls_extant
  103. lws_tls_generic_cert_checks(struct lws_vhost *vhost, const char *cert,
  104. const char *private_key)
  105. {
  106. int n, m;
  107. /*
  108. * The user code can choose to either pass the cert and
  109. * key filepaths using the info members like this, or it can
  110. * leave them NULL; force the vhost SSL_CTX init using the info
  111. * options flag LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX; and
  112. * set up the cert himself using the user callback
  113. * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, which
  114. * happened just above and has the vhost SSL_CTX * in the user
  115. * parameter.
  116. */
  117. if (!cert || !private_key)
  118. return LWS_TLS_EXTANT_NO;
  119. n = lws_tls_use_any_upgrade_check_extant(cert);
  120. if (n == LWS_TLS_EXTANT_ALTERNATIVE)
  121. return LWS_TLS_EXTANT_ALTERNATIVE;
  122. m = lws_tls_use_any_upgrade_check_extant(private_key);
  123. if (m == LWS_TLS_EXTANT_ALTERNATIVE)
  124. return LWS_TLS_EXTANT_ALTERNATIVE;
  125. if ((n == LWS_TLS_EXTANT_NO || m == LWS_TLS_EXTANT_NO) &&
  126. (vhost->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT)) {
  127. lwsl_notice("Ignoring missing %s or %s\n", cert, private_key);
  128. vhost->tls.skipped_certs = 1;
  129. return LWS_TLS_EXTANT_NO;
  130. }
  131. /*
  132. * the cert + key exist
  133. */
  134. return LWS_TLS_EXTANT_YES;
  135. }
  136. /*
  137. * update the cert for every vhost using the given path
  138. */
  139. int
  140. lws_tls_cert_updated(struct lws_context *context, const char *certpath,
  141. const char *keypath,
  142. const char *mem_cert, size_t len_mem_cert,
  143. const char *mem_privkey, size_t len_mem_privkey)
  144. {
  145. struct lws wsi;
  146. wsi.a.context = context;
  147. lws_start_foreach_ll(struct lws_vhost *, v, context->vhost_list) {
  148. wsi.a.vhost = v; /* not a real bound wsi */
  149. if (v->tls.alloc_cert_path && v->tls.key_path &&
  150. !strcmp(v->tls.alloc_cert_path, certpath) &&
  151. !strcmp(v->tls.key_path, keypath)) {
  152. lws_tls_server_certs_load(v, &wsi, certpath, keypath,
  153. mem_cert, len_mem_cert,
  154. mem_privkey, len_mem_privkey);
  155. if (v->tls.skipped_certs)
  156. lwsl_notice("%s: vhost %s: cert unset\n",
  157. __func__, v->name);
  158. }
  159. } lws_end_foreach_ll(v, vhost_next);
  160. return 0;
  161. }
  162. #endif
  163. int
  164. lws_gate_accepts(struct lws_context *context, int on)
  165. {
  166. struct lws_vhost *v = context->vhost_list;
  167. lwsl_notice("%s: on = %d\n", __func__, on);
  168. #if defined(LWS_WITH_STATS)
  169. context->updated = 1;
  170. #endif
  171. while (v) {
  172. if (v->tls.use_ssl && v->lserv_wsi &&
  173. lws_change_pollfd(v->lserv_wsi, (LWS_POLLIN) * !on,
  174. (LWS_POLLIN) * on))
  175. lwsl_notice("Unable to set accept POLLIN %d\n", on);
  176. v = v->vhost_next;
  177. }
  178. return 0;
  179. }
  180. /* comma-separated alpn list, like "h2,http/1.1" to openssl alpn format */
  181. int
  182. lws_alpn_comma_to_openssl(const char *comma, uint8_t *os, int len)
  183. {
  184. uint8_t *oos = os, *plen = NULL;
  185. if (!comma)
  186. return 0;
  187. while (*comma && len > 2) {
  188. if (!plen && *comma == ' ') {
  189. comma++;
  190. continue;
  191. }
  192. if (!plen) {
  193. plen = os++;
  194. len--;
  195. }
  196. if (*comma == ',') {
  197. *plen = lws_ptr_diff(os, plen + 1);
  198. plen = NULL;
  199. comma++;
  200. } else {
  201. *os++ = *comma++;
  202. len--;
  203. }
  204. }
  205. if (plen)
  206. *plen = lws_ptr_diff(os, plen + 1);
  207. *os = 0;
  208. return lws_ptr_diff(os, oos);
  209. }