policy-common.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2019 - 2020 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. * This file contains the stuff related to secure streams policy, it's always
  25. * built if LWS_WITH_SECURE_STREAMS enabled.
  26. */
  27. #include <private-lib-core.h>
  28. #if defined(LWS_WITH_SYS_SMD)
  29. const lws_ss_policy_t pol_smd = {
  30. .flags = 0, /* have to set something for windows */
  31. };
  32. #endif
  33. const lws_ss_policy_t *
  34. lws_ss_policy_lookup(const struct lws_context *context, const char *streamtype)
  35. {
  36. const lws_ss_policy_t *p = context->pss_policies;
  37. if (!streamtype)
  38. return NULL;
  39. #if defined(LWS_WITH_SYS_SMD)
  40. if (!strcmp(streamtype, LWS_SMD_STREAMTYPENAME))
  41. return &pol_smd;
  42. #endif
  43. while (p) {
  44. if (!strcmp(p->streamtype, streamtype))
  45. return p;
  46. p = p->next;
  47. }
  48. return NULL;
  49. }
  50. int
  51. lws_ss_set_metadata(struct lws_ss_handle *h, const char *name,
  52. const void *value, size_t len)
  53. {
  54. lws_ss_metadata_t *omd = lws_ss_policy_metadata(h->policy, name);
  55. if (!omd) {
  56. lwsl_info("%s: unknown metadata %s\n", __func__, name);
  57. return 1;
  58. }
  59. h->metadata[omd->length].name = name;
  60. h->metadata[omd->length].value = (void *)value;
  61. h->metadata[omd->length].length = len;
  62. return 0;
  63. }
  64. lws_ss_metadata_t *
  65. lws_ss_get_handle_metadata(struct lws_ss_handle *h, const char *name)
  66. {
  67. lws_ss_metadata_t *omd = lws_ss_policy_metadata(h->policy, name);
  68. if (!omd)
  69. return NULL;
  70. return &h->metadata[omd->length];
  71. }
  72. lws_ss_metadata_t *
  73. lws_ss_policy_metadata(const lws_ss_policy_t *p, const char *name)
  74. {
  75. lws_ss_metadata_t *pmd = p->metadata;
  76. while (pmd) {
  77. if (pmd->name && !strcmp(name, pmd->name))
  78. return pmd;
  79. pmd = pmd->next;
  80. }
  81. return NULL;
  82. }
  83. lws_ss_metadata_t *
  84. lws_ss_policy_metadata_index(const lws_ss_policy_t *p, size_t index)
  85. {
  86. lws_ss_metadata_t *pmd = p->metadata;
  87. while (pmd) {
  88. if (pmd->length == index)
  89. return pmd;
  90. pmd = pmd->next;
  91. }
  92. return NULL;
  93. }
  94. #if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
  95. static int
  96. fe_lws_ss_destroy(struct lws_dll2 *d, void *user)
  97. {
  98. lws_ss_handle_t *h = lws_container_of(d, lws_ss_handle_t, list);
  99. lws_ss_destroy(&h);
  100. return 0;
  101. }
  102. #endif
  103. /*
  104. * Dynamic policy: we want to one-time create the vhost for the policy and the
  105. * trust store behind it.
  106. *
  107. * Static policy: We want to make use of a trust store / vhost from the policy and add to its
  108. * ss-refcount.
  109. */
  110. struct lws_vhost *
  111. lws_ss_policy_ref_trust_store(struct lws_context *context,
  112. const lws_ss_policy_t *pol, char doref)
  113. {
  114. struct lws_context_creation_info i;
  115. struct lws_vhost *v;
  116. int n;
  117. memset(&i, 0, sizeof(i));
  118. if (!pol->trust.store) {
  119. v = lws_get_vhost_by_name(context, "_ss_default");
  120. if (!v) {
  121. /* corner case... there's no trust store used */
  122. i.options = context->options;
  123. i.vhost_name = "_ss_default";
  124. i.port = CONTEXT_PORT_NO_LISTEN;
  125. v = lws_create_vhost(context, &i);
  126. if (!v) {
  127. lwsl_err("%s: failed to create vhost %s\n",
  128. __func__, i.vhost_name);
  129. return NULL;
  130. }
  131. }
  132. goto accepted;
  133. }
  134. v = lws_get_vhost_by_name(context, pol->trust.store->name);
  135. if (v) {
  136. lwsl_debug("%s: vh already exists\n", __func__);
  137. goto accepted;
  138. }
  139. i.options = context->options;
  140. i.vhost_name = pol->trust.store->name;
  141. lwsl_debug("%s: %s\n", __func__, i.vhost_name);
  142. #if defined(LWS_WITH_TLS) && defined(LWS_WITH_CLIENT)
  143. i.client_ssl_ca_mem = pol->trust.store->ssx509[0]->ca_der;
  144. i.client_ssl_ca_mem_len = (unsigned int)
  145. pol->trust.store->ssx509[0]->ca_der_len;
  146. #endif
  147. i.port = CONTEXT_PORT_NO_LISTEN;
  148. lwsl_info("%s: %s trust store initial '%s'\n", __func__,
  149. i.vhost_name, pol->trust.store->ssx509[0]->vhost_name);
  150. v = lws_create_vhost(context, &i);
  151. if (!v) {
  152. lwsl_err("%s: failed to create vhost %s\n",
  153. __func__, i.vhost_name);
  154. return NULL;
  155. } else
  156. v->from_ss_policy = 1;
  157. for (n = 1; v && n < pol->trust.store->count; n++) {
  158. lwsl_info("%s: add '%s' to trust store\n", __func__,
  159. pol->trust.store->ssx509[n]->vhost_name);
  160. #if defined(LWS_WITH_TLS)
  161. if (lws_tls_client_vhost_extra_cert_mem(v,
  162. pol->trust.store->ssx509[n]->ca_der,
  163. pol->trust.store->ssx509[n]->ca_der_len)) {
  164. lwsl_err("%s: add extra cert failed\n",
  165. __func__);
  166. return NULL;
  167. }
  168. #endif
  169. }
  170. accepted:
  171. #if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
  172. if (doref)
  173. v->ss_refcount++;
  174. #endif
  175. return v;
  176. }
  177. #if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
  178. int
  179. lws_ss_policy_unref_trust_store(struct lws_context *context,
  180. const lws_ss_policy_t *pol)
  181. {
  182. struct lws_vhost *v;
  183. const char *name = "_ss_default";
  184. if (pol->trust.store)
  185. name = pol->trust.store->name;
  186. v = lws_get_vhost_by_name(context, name);
  187. if (!v || !v->from_ss_policy)
  188. return 0;
  189. assert(v->ss_refcount);
  190. v->ss_refcount--;
  191. if (!v->ss_refcount) {
  192. lwsl_notice("%s: destroying vh %s\n", __func__, name);
  193. lws_vhost_destroy(v);
  194. }
  195. return 1;
  196. }
  197. #endif
  198. int
  199. lws_ss_policy_set(struct lws_context *context, const char *name)
  200. {
  201. int ret = 0;
  202. #if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
  203. struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args;
  204. const lws_ss_policy_t *pol;
  205. struct lws_vhost *v;
  206. lws_ss_x509_t *x;
  207. char buf[16];
  208. int m;
  209. /*
  210. * Parsing seems to have succeeded, and we're going to use the new
  211. * policy that's laid out in args->ac
  212. */
  213. lejp_destruct(&args->jctx);
  214. if (context->ac_policy) {
  215. int n;
  216. /*
  217. * any existing ss created with the old policy have to go away
  218. * now, since they point to the shortly-to-be-destroyed old
  219. * policy
  220. */
  221. for (n = 0; n < context->count_threads; n++) {
  222. struct lws_context_per_thread *pt = &context->pt[n];
  223. lws_dll2_foreach_safe(&pt->ss_owner, NULL, fe_lws_ss_destroy);
  224. }
  225. /*
  226. * So this is a bit fun-filled, we already had a policy in
  227. * force, perhaps it was the default policy that's just good for
  228. * fetching the real policy, and we're doing that now.
  229. *
  230. * We can destroy all the policy-related direct allocations
  231. * easily because they're cleanly in a single lwsac...
  232. */
  233. lwsac_free(&context->ac_policy);
  234. /*
  235. * ...but when we did the trust stores, we created vhosts for
  236. * each. We need to destroy those now too, and recreate new
  237. * ones from the new policy, perhaps with different X.509s.
  238. */
  239. v = context->vhost_list;
  240. while (v) {
  241. if (v->from_ss_policy) {
  242. struct lws_vhost *vh = v->vhost_next;
  243. lwsl_debug("%s: destroying vh %p\n", __func__, v);
  244. lws_vhost_destroy(v);
  245. v = vh;
  246. continue;
  247. }
  248. v = v->vhost_next;
  249. }
  250. lws_check_deferred_free(context, 0, 1);
  251. }
  252. context->pss_policies = args->heads[LTY_POLICY].p;
  253. context->ac_policy = args->ac;
  254. lws_humanize(buf, sizeof(buf), lwsac_total_alloc(args->ac),
  255. humanize_schema_si_bytes);
  256. if (lwsac_total_alloc(args->ac))
  257. m = (int)((lwsac_total_overhead(args->ac) * 100) /
  258. lwsac_total_alloc(args->ac));
  259. else
  260. m = 0;
  261. (void)m;
  262. lwsl_info("%s: %s, pad %d%c: %s\n", __func__, buf, m, '%', name);
  263. /* Create vhosts for each type of trust store */
  264. /*
  265. * We get called from context creation... instantiates
  266. * vhosts with client tls contexts set up for each unique CA.
  267. *
  268. * We create the vhosts by walking streamtype list and create vhosts
  269. * using trust store name if it's a client connection that doesn't
  270. * already exist.
  271. */
  272. pol = context->pss_policies;
  273. while (pol) {
  274. if (!(pol->flags & LWSSSPOLF_SERVER)) {
  275. v = lws_ss_policy_ref_trust_store(context, pol,
  276. 0 /* no refcount inc */);
  277. if (!v)
  278. ret = 1;
  279. }
  280. pol = pol->next;
  281. }
  282. #if defined(LWS_WITH_SOCKS5)
  283. /*
  284. * ... we need to go through every vhost updating its understanding of
  285. * which socks5 proxy to use...
  286. */
  287. v = context->vhost_list;
  288. while (v) {
  289. lws_set_socks(v, args->socks5_proxy);
  290. v = v->vhost_next;
  291. }
  292. if (context->vhost_system)
  293. lws_set_socks(context->vhost_system, args->socks5_proxy);
  294. if (args->socks5_proxy)
  295. lwsl_notice("%s: global socks5 proxy: %s\n", __func__,
  296. args->socks5_proxy);
  297. #endif
  298. /*
  299. * For dynamic policy case, now we processed the x.509 CAs, we can free
  300. * all of our originals. For static policy, they're in .rodata, nothing
  301. * to free.
  302. */
  303. x = args->heads[LTY_X509].x;
  304. while (x) {
  305. /*
  306. * Free all the client DER buffers now they have been parsed
  307. * into tls library X.509 objects
  308. */
  309. if (!x->keep) { /* used for server */
  310. lws_free((void *)x->ca_der);
  311. x->ca_der = NULL;
  312. }
  313. x = x->next;
  314. }
  315. /* and we can discard the parsing args object now, invalidating args */
  316. lws_free_set_NULL(context->pol_args);
  317. #endif
  318. return ret;
  319. }