policy-json.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896
  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 JSON-provided policy, it's not built
  25. * if LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY enabled.
  26. */
  27. #include <private-lib-core.h>
  28. static const char * const lejp_tokens_policy[] = {
  29. "release",
  30. "product",
  31. "schema-version",
  32. "via-socks5",
  33. "retry[].*.backoff",
  34. "retry[].*.conceal",
  35. "retry[].*.jitterpc",
  36. "retry[].*.svalidping",
  37. "retry[].*.svalidhup",
  38. "retry[].*",
  39. "certs[].*",
  40. "trust_stores[].name",
  41. "trust_stores[].stack",
  42. "s[].*.endpoint",
  43. "s[].*.via-socks5",
  44. "s[].*.protocol",
  45. "s[].*.port",
  46. "s[].*.plugins",
  47. "s[].*.tls",
  48. "s[].*.client_cert",
  49. "s[].*.opportunistic",
  50. "s[].*.nailed_up",
  51. "s[].*.allow_redirects",
  52. "s[].*.urgent_tx",
  53. "s[].*.urgent_rx",
  54. "s[].*.long_poll",
  55. "s[].*.retry",
  56. "s[].*.timeout_ms",
  57. "s[].*.tls_trust_store",
  58. "s[].*.metadata",
  59. "s[].*.metadata[].*",
  60. "s[].*.http_auth_header",
  61. "s[].*.http_dsn_header",
  62. "s[].*.http_fwv_header",
  63. "s[].*.http_devtype_header",
  64. "s[].*.http_auth_preamble",
  65. "s[].*.http_no_content_length",
  66. "s[].*.rideshare", /* streamtype name this rides shotgun with */
  67. "s[].*.payload_fmt",
  68. "s[].*.http_method",
  69. "s[].*.http_url",
  70. "s[].*.nghttp2_quirk_end_stream",
  71. "s[].*.h2q_oflow_txcr",
  72. "s[].*.http_multipart_name",
  73. "s[].*.http_multipart_filename",
  74. "s[].*.http_mime_content_type",
  75. "s[].*.http_www_form_urlencoded",
  76. "s[].*.http_expect",
  77. "s[].*.http_fail_redirect",
  78. "s[].*.http_multipart_ss_in",
  79. "s[].*.ws_subprotocol",
  80. "s[].*.ws_binary",
  81. "s[].*.local_sink",
  82. "s[].*.server",
  83. "s[].*.server_cert",
  84. "s[].*.server_key",
  85. "s[].*.mqtt_topic",
  86. "s[].*.mqtt_subscribe",
  87. "s[].*.mqtt_qos",
  88. "s[].*.mqtt_keep_alive",
  89. "s[].*.mqtt_clean_start",
  90. "s[].*.mqtt_will_topic",
  91. "s[].*.mqtt_will_message",
  92. "s[].*.mqtt_will_qos",
  93. "s[].*.mqtt_will_retain",
  94. "s[].*.swake_validity",
  95. "s[].*",
  96. };
  97. typedef enum {
  98. LSSPPT_RELEASE,
  99. LSSPPT_PRODUCT,
  100. LSSPPT_SCHEMA_VERSION,
  101. LSSPPT_VIA_SOCKS5,
  102. LSSPPT_BACKOFF,
  103. LSSPPT_CONCEAL,
  104. LSSPPT_JITTERPC,
  105. LSSPPT_VALIDPING_S,
  106. LSSPPT_VALIDHUP_S,
  107. LSSPPT_RETRY,
  108. LSSPPT_CERTS,
  109. LSSPPT_TRUST_STORES_NAME,
  110. LSSPPT_TRUST_STORES_STACK,
  111. LSSPPT_ENDPOINT,
  112. LSSPPT_VH_VIA_SOCKS5,
  113. LSSPPT_PROTOCOL,
  114. LSSPPT_PORT,
  115. LSSPPT_PLUGINS,
  116. LSSPPT_TLS,
  117. LSSPPT_TLS_CLIENT_CERT,
  118. LSSPPT_OPPORTUNISTIC,
  119. LSSPPT_NAILED_UP,
  120. LSSPPT_ALLOW_REDIRECTS,
  121. LSSPPT_URGENT_TX,
  122. LSSPPT_URGENT_RX,
  123. LSSPPT_LONG_POLL,
  124. LSSPPT_RETRYPTR,
  125. LSSPPT_DEFAULT_TIMEOUT_MS,
  126. LSSPPT_TRUST,
  127. LSSPPT_METADATA,
  128. LSSPPT_METADATA_ITEM,
  129. LSSPPT_HTTP_AUTH_HEADER,
  130. LSSPPT_HTTP_DSN_HEADER,
  131. LSSPPT_HTTP_FWV_HEADER,
  132. LSSPPT_HTTP_TYPE_HEADER,
  133. LSSPPT_HTTP_AUTH_PREAMBLE,
  134. LSSPPT_HTTP_NO_CONTENT_LENGTH,
  135. LSSPPT_RIDESHARE,
  136. LSSPPT_PAYLOAD_FORMAT,
  137. LSSPPT_HTTP_METHOD,
  138. LSSPPT_HTTP_URL,
  139. LSSPPT_NGHTTP2_QUIRK_END_STREAM,
  140. LSSPPT_H2_QUIRK_OVERFLOWS_TXCR,
  141. LSSPPT_HTTP_MULTIPART_NAME,
  142. LSSPPT_HTTP_MULTIPART_FILENAME,
  143. LSSPPT_HTTP_MULTIPART_CONTENT_TYPE,
  144. LSSPPT_HTTP_WWW_FORM_URLENCODED,
  145. LSSPPT_HTTP_EXPECT,
  146. LSSPPT_HTTP_FAIL_REDIRECT,
  147. LSSPPT_HTTP_MULTIPART_SS_IN,
  148. LSSPPT_WS_SUBPROTOCOL,
  149. LSSPPT_WS_BINARY,
  150. LSSPPT_LOCAL_SINK,
  151. LSSPPT_SERVER,
  152. LSSPPT_SERVER_CERT,
  153. LSSPPT_SERVER_KEY,
  154. LSSPPT_MQTT_TOPIC,
  155. LSSPPT_MQTT_SUBSCRIBE,
  156. LSSPPT_MQTT_QOS,
  157. LSSPPT_MQTT_KEEPALIVE,
  158. LSSPPT_MQTT_CLEAN_START,
  159. LSSPPT_MQTT_WILL_TOPIC,
  160. LSSPPT_MQTT_WILL_MESSAGE,
  161. LSSPPT_MQTT_WILL_QOS,
  162. LSSPPT_MQTT_WILL_RETAIN,
  163. LSSPPT_SWAKE_VALIDITY,
  164. LSSPPT_STREAMTYPES,
  165. } policy_token_t;
  166. #define POL_AC_INITIAL 2048
  167. #define POL_AC_GRAIN 800
  168. #define MAX_CERT_TEMP 3072 /* used to discover actual cert size for realloc */
  169. static uint8_t sizes[] = {
  170. sizeof(backoff_t),
  171. sizeof(lws_ss_x509_t),
  172. sizeof(lws_ss_trust_store_t),
  173. sizeof(lws_ss_policy_t),
  174. };
  175. static const char *protonames[] = {
  176. "h1", /* LWSSSP_H1 */
  177. "h2", /* LWSSSP_H2 */
  178. "ws", /* LWSSSP_WS */
  179. "mqtt", /* LWSSSP_MQTT */
  180. "raw", /* LWSSSP_RAW */
  181. };
  182. static signed char
  183. lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason)
  184. {
  185. struct policy_cb_args *a = (struct policy_cb_args *)ctx->user;
  186. #if defined(LWS_WITH_SSPLUGINS)
  187. const lws_ss_plugin_t **pin;
  188. #endif
  189. char **pp, dotstar[32], *q;
  190. lws_ss_trust_store_t *ts;
  191. lws_ss_metadata_t *pmd;
  192. lws_ss_x509_t *x, **py;
  193. lws_ss_policy_t *p2;
  194. lws_retry_bo_t *b;
  195. size_t inl, outl;
  196. uint8_t *extant;
  197. backoff_t *bot;
  198. int n = -1;
  199. lwsl_debug("%s: %d %d %s\n", __func__, reason, ctx->path_match - 1,
  200. ctx->path);
  201. switch (ctx->path_match - 1) {
  202. case LSSPPT_RETRY:
  203. n = LTY_BACKOFF;
  204. break;
  205. case LSSPPT_CERTS:
  206. n = LTY_X509;
  207. break;
  208. case LSSPPT_TRUST_STORES_NAME:
  209. case LSSPPT_TRUST_STORES_STACK:
  210. n = LTY_TRUSTSTORE;
  211. break;
  212. case LSSPPT_STREAMTYPES:
  213. n = LTY_POLICY;
  214. break;
  215. }
  216. if (reason == LEJPCB_ARRAY_START &&
  217. (ctx->path_match - 1 == LSSPPT_PLUGINS ||
  218. ctx->path_match - 1 == LSSPPT_METADATA))
  219. a->count = 0;
  220. if (reason == LEJPCB_ARRAY_END &&
  221. ctx->path_match - 1 == LSSPPT_TRUST_STORES_STACK && !a->count) {
  222. lwsl_err("%s: at least one cert required in trust store\n",
  223. __func__);
  224. goto oom;
  225. }
  226. if (reason == LEJPCB_OBJECT_END && a->p) {
  227. /*
  228. * Allocate a just-the-right-size buf for the cert DER now
  229. * we decoded it into the a->p temp buffer and know the exact
  230. * size.
  231. *
  232. * The struct *x is in the lwsac... the ca_der it points to
  233. * is individually allocated from the heap
  234. */
  235. a->curr[LTY_X509].x->ca_der = lws_malloc(a->count, "ssx509");
  236. if (!a->curr[LTY_X509].x->ca_der)
  237. goto oom;
  238. memcpy((uint8_t *)a->curr[LTY_X509].x->ca_der, a->p, a->count);
  239. a->curr[LTY_X509].x->ca_der_len = a->count;
  240. /*
  241. * ... and then we can free the temp buffer
  242. */
  243. lws_free_set_NULL(a->p);
  244. return 0;
  245. }
  246. if (reason == LEJPCB_PAIR_NAME && n != -1 && n != LTY_TRUSTSTORE) {
  247. p2 = NULL;
  248. if (n == LTY_POLICY) {
  249. /*
  250. * We want to allow for the possibility of overlays...
  251. * eg, we come later with a JSON snippet that overrides
  252. * select streamtype members of a streamtype that was
  253. * already defined
  254. */
  255. p2 = (lws_ss_policy_t *)a->context->pss_policies;
  256. while (p2) {
  257. if (!strncmp(p2->streamtype,
  258. ctx->path + ctx->st[ctx->sp].p,
  259. ctx->path_match_len -
  260. ctx->st[ctx->sp].p)) {
  261. lwsl_info("%s: overriding s[] %s\n",
  262. __func__, p2->streamtype);
  263. break;
  264. }
  265. p2 = p2->next;
  266. }
  267. }
  268. /*
  269. * We do the pointers always as .b union member, all of the
  270. * participating structs begin with .next and .name the same
  271. */
  272. if (p2) /* we may be overriding existing streamtype... */
  273. a->curr[n].b = (backoff_t *)p2;
  274. else
  275. a->curr[n].b = lwsac_use_zero(&a->ac, sizes[n], POL_AC_GRAIN);
  276. if (!a->curr[n].b)
  277. goto oom;
  278. if (n == LTY_X509) {
  279. a->p = lws_malloc(MAX_CERT_TEMP, "cert temp");
  280. if (!a->p)
  281. goto oom;
  282. memset(&a->b64, 0, sizeof(a->b64));
  283. }
  284. a->count = 0;
  285. if (!p2) {
  286. a->curr[n].b->next = a->heads[n].b;
  287. a->heads[n].b = a->curr[n].b;
  288. pp = (char **)&a->curr[n].b->name;
  289. goto string1;
  290. }
  291. return 0; /* overriding */
  292. }
  293. if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match)
  294. return 0;
  295. switch (ctx->path_match - 1) {
  296. /* strings */
  297. case LSSPPT_RELEASE:
  298. break;
  299. case LSSPPT_PRODUCT:
  300. break;
  301. case LSSPPT_SCHEMA_VERSION:
  302. break;
  303. case LSSPPT_VIA_SOCKS5:
  304. /* the global / default proxy */
  305. pp = (char **)&a->socks5_proxy;
  306. goto string2;
  307. case LSSPPT_BACKOFF:
  308. b = &a->curr[LTY_BACKOFF].b->r;
  309. if (b->retry_ms_table_count == 8) {
  310. lwsl_err("%s: > 8 backoff levels\n", __func__);
  311. return 1;
  312. }
  313. if (!b->retry_ms_table_count) {
  314. b->retry_ms_table = (uint32_t *)lwsac_use_zero(&a->ac,
  315. sizeof(uint32_t) * 8, POL_AC_GRAIN);
  316. if (!b->retry_ms_table)
  317. goto oom;
  318. }
  319. ((uint32_t *)b->retry_ms_table)
  320. [b->retry_ms_table_count++] = atoi(ctx->buf);
  321. break;
  322. case LSSPPT_CONCEAL:
  323. a->curr[LTY_BACKOFF].b->r.conceal_count = atoi(ctx->buf);
  324. break;
  325. case LSSPPT_JITTERPC:
  326. a->curr[LTY_BACKOFF].b->r.jitter_percent = atoi(ctx->buf);
  327. break;
  328. case LSSPPT_VALIDPING_S:
  329. a->curr[LTY_BACKOFF].b->r.secs_since_valid_ping = atoi(ctx->buf);
  330. break;
  331. case LSSPPT_VALIDHUP_S:
  332. a->curr[LTY_BACKOFF].b->r.secs_since_valid_hangup = atoi(ctx->buf);
  333. break;
  334. case LSSPPT_CERTS:
  335. if (a->count + ctx->npos >= MAX_CERT_TEMP) {
  336. lwsl_err("%s: cert too big\n", __func__);
  337. goto oom;
  338. }
  339. inl = ctx->npos;
  340. outl = MAX_CERT_TEMP - a->count;
  341. lws_b64_decode_stateful(&a->b64, ctx->buf, &inl,
  342. a->p + a->count, &outl,
  343. reason == LEJPCB_VAL_STR_END);
  344. a->count += (int)outl;
  345. if (inl != ctx->npos) {
  346. lwsl_err("%s: b64 decode fail\n", __func__);
  347. goto oom;
  348. }
  349. break;
  350. case LSSPPT_TRUST_STORES_NAME:
  351. /*
  352. * We do the pointers always as .b, all of the participating
  353. * structs begin with .next and .name
  354. */
  355. a->curr[LTY_TRUSTSTORE].b = lwsac_use_zero(&a->ac,
  356. sizes[LTY_TRUSTSTORE], POL_AC_GRAIN);
  357. if (!a->curr[LTY_TRUSTSTORE].b)
  358. goto oom;
  359. a->count = 0;
  360. a->curr[LTY_TRUSTSTORE].b->next = a->heads[LTY_TRUSTSTORE].b;
  361. a->heads[LTY_TRUSTSTORE].b = a->curr[LTY_TRUSTSTORE].b;
  362. pp = (char **)&a->curr[LTY_TRUSTSTORE].b->name;
  363. goto string2;
  364. case LSSPPT_TRUST_STORES_STACK:
  365. if (a->count >= (int)LWS_ARRAY_SIZE(
  366. a->curr[LTY_TRUSTSTORE].t->ssx509)) {
  367. lwsl_err("%s: trust store too big\n", __func__);
  368. goto oom;
  369. }
  370. lwsl_debug("%s: trust stores stack %.*s\n", __func__,
  371. ctx->npos, ctx->buf);
  372. x = a->heads[LTY_X509].x;
  373. while (x) {
  374. if (!strncmp(x->vhost_name, ctx->buf, ctx->npos)) {
  375. a->curr[LTY_TRUSTSTORE].t->ssx509[a->count++] = x;
  376. a->curr[LTY_TRUSTSTORE].t->count++;
  377. return 0;
  378. }
  379. x = x->next;
  380. }
  381. lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar));
  382. lwsl_err("%s: unknown trust store entry %s\n", __func__,
  383. dotstar);
  384. goto oom;
  385. case LSSPPT_SERVER_CERT:
  386. case LSSPPT_SERVER_KEY:
  387. /* iterate through the certs */
  388. py = &a->heads[LTY_X509].x;
  389. x = a->heads[LTY_X509].x;
  390. while (x) {
  391. if (!strncmp(x->vhost_name, ctx->buf, ctx->npos) &&
  392. !x->vhost_name[ctx->npos]) {
  393. if ((ctx->path_match - 1) == LSSPPT_SERVER_CERT)
  394. a->curr[LTY_POLICY].p->trust.server.cert = x;
  395. else
  396. a->curr[LTY_POLICY].p->trust.server.key = x;
  397. /*
  398. * Certs that are for servers need to stick
  399. * around in DER form, so the vhost can be
  400. * instantiated when the server is brought up
  401. */
  402. x->keep = 1;
  403. lwsl_notice("%s: server '%s' keep %d %p\n",
  404. __func__, x->vhost_name,
  405. ctx->path_match - 1, x);
  406. /*
  407. * Server DER we need to move it to another
  408. * list just for destroying it when the context
  409. * is destroyed... snip us out of the live
  410. * X.509 list
  411. */
  412. *py = x->next;
  413. /*
  414. * ... and instead put us on the list of things
  415. * to keep hold of for context destruction
  416. */
  417. x->next = a->context->server_der_list;
  418. a->context->server_der_list = x;
  419. return 0;
  420. }
  421. py = &x->next;
  422. x = x->next;
  423. }
  424. lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar));
  425. lwsl_err("%s: unknown cert / key %s\n", __func__, dotstar);
  426. goto oom;
  427. case LSSPPT_ENDPOINT:
  428. pp = (char **)&a->curr[LTY_POLICY].p->endpoint;
  429. goto string2;
  430. case LSSPPT_VH_VIA_SOCKS5:
  431. pp = (char **)&a->curr[LTY_POLICY].p->socks5_proxy;
  432. goto string2;
  433. case LSSPPT_PORT:
  434. a->curr[LTY_POLICY].p->port = atoi(ctx->buf);
  435. break;
  436. case LSSPPT_HTTP_METHOD:
  437. pp = (char **)&a->curr[LTY_POLICY].p->u.http.method;
  438. goto string2;
  439. case LSSPPT_HTTP_URL:
  440. pp = (char **)&a->curr[LTY_POLICY].p->u.http.url;
  441. goto string2;
  442. case LSSPPT_RIDESHARE:
  443. pp = (char **)&a->curr[LTY_POLICY].p->rideshare_streamtype;
  444. goto string2;
  445. case LSSPPT_PAYLOAD_FORMAT:
  446. pp = (char **)&a->curr[LTY_POLICY].p->payload_fmt;
  447. goto string2;
  448. case LSSPPT_PLUGINS:
  449. #if defined(LWS_WITH_SSPLUGINS)
  450. pin = a->context->pss_plugins;
  451. if (a->count ==
  452. (int)LWS_ARRAY_SIZE(a->curr[LTY_POLICY].p->plugins)) {
  453. lwsl_err("%s: too many plugins\n", __func__);
  454. goto oom;
  455. }
  456. if (!pin)
  457. break;
  458. while (*pin) {
  459. if (!strncmp((*pin)->name, ctx->buf, ctx->npos)) {
  460. a->curr[LTY_POLICY].p->plugins[a->count++] = *pin;
  461. return 0;
  462. }
  463. pin++;
  464. }
  465. lwsl_err("%s: unknown plugin\n", __func__);
  466. goto oom;
  467. #else
  468. break;
  469. #endif
  470. case LSSPPT_TLS:
  471. if (reason == LEJPCB_VAL_TRUE)
  472. a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_TLS;
  473. break;
  474. case LSSPPT_TLS_CLIENT_CERT:
  475. a->curr[LTY_POLICY].p->client_cert = atoi(ctx->buf) + 1;
  476. break;
  477. case LSSPPT_HTTP_EXPECT:
  478. a->curr[LTY_POLICY].p->u.http.resp_expect = atoi(ctx->buf);
  479. break;
  480. case LSSPPT_DEFAULT_TIMEOUT_MS:
  481. a->curr[LTY_POLICY].p->timeout_ms = atoi(ctx->buf);
  482. break;
  483. case LSSPPT_OPPORTUNISTIC:
  484. if (reason == LEJPCB_VAL_TRUE)
  485. a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_OPPORTUNISTIC;
  486. break;
  487. case LSSPPT_NAILED_UP:
  488. if (reason == LEJPCB_VAL_TRUE)
  489. a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_NAILED_UP;
  490. break;
  491. case LSSPPT_URGENT_TX:
  492. if (reason == LEJPCB_VAL_TRUE)
  493. a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_URGENT_TX;
  494. break;
  495. case LSSPPT_URGENT_RX:
  496. if (reason == LEJPCB_VAL_TRUE)
  497. a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_URGENT_RX;
  498. break;
  499. case LSSPPT_LONG_POLL:
  500. if (reason == LEJPCB_VAL_TRUE)
  501. a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_LONG_POLL;
  502. break;
  503. case LSSPPT_HTTP_WWW_FORM_URLENCODED:
  504. if (reason == LEJPCB_VAL_TRUE)
  505. a->curr[LTY_POLICY].p->flags |=
  506. LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED;
  507. break;
  508. case LSSPPT_SWAKE_VALIDITY:
  509. if (reason == LEJPCB_VAL_TRUE)
  510. a->curr[LTY_POLICY].p->flags |=
  511. LWSSSPOLF_WAKE_SUSPEND__VALIDITY;
  512. break;
  513. case LSSPPT_ALLOW_REDIRECTS:
  514. if (reason == LEJPCB_VAL_TRUE)
  515. a->curr[LTY_POLICY].p->flags |=
  516. LWSSSPOLF_ALLOW_REDIRECTS;
  517. break;
  518. case LSSPPT_HTTP_MULTIPART_SS_IN:
  519. if (reason == LEJPCB_VAL_TRUE)
  520. a->curr[LTY_POLICY].p->flags |=
  521. LWSSSPOLF_HTTP_MULTIPART_IN;
  522. return 0;
  523. case LSSPPT_RETRYPTR:
  524. bot = a->heads[LTY_BACKOFF].b;
  525. while (bot) {
  526. if (!strncmp(ctx->buf, bot->name, ctx->npos)) {
  527. a->curr[LTY_POLICY].p->retry_bo = &bot->r;
  528. return 0;
  529. }
  530. bot = bot->next;
  531. }
  532. lwsl_err("%s: unknown backoff scheme\n", __func__);
  533. return -1;
  534. case LSSPPT_TRUST:
  535. ts = a->heads[LTY_TRUSTSTORE].t;
  536. while (ts) {
  537. if (!strncmp(ctx->buf, ts->name, ctx->npos)) {
  538. a->curr[LTY_POLICY].p->trust.store = ts;
  539. return 0;
  540. }
  541. ts = ts->next;
  542. }
  543. lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar));
  544. lwsl_err("%s: unknown trust store name %s\n", __func__,
  545. dotstar);
  546. return -1;
  547. case LSSPPT_METADATA:
  548. break;
  549. case LSSPPT_METADATA_ITEM:
  550. pmd = a->curr[LTY_POLICY].p->metadata;
  551. a->curr[LTY_POLICY].p->metadata = lwsac_use_zero(&a->ac,
  552. sizeof(lws_ss_metadata_t) + ctx->npos +
  553. (ctx->path_match_len - ctx->st[ctx->sp - 2].p + 1) + 2,
  554. POL_AC_GRAIN);
  555. a->curr[LTY_POLICY].p->metadata->next = pmd;
  556. q = (char *)a->curr[LTY_POLICY].p->metadata +
  557. sizeof(lws_ss_metadata_t);
  558. a->curr[LTY_POLICY].p->metadata->name = q;
  559. memcpy(q, ctx->path + ctx->st[ctx->sp - 2].p + 1,
  560. ctx->path_match_len - ctx->st[ctx->sp - 2].p);
  561. q += ctx->path_match_len - ctx->st[ctx->sp - 2].p;
  562. a->curr[LTY_POLICY].p->metadata->value = q;
  563. memcpy(q, ctx->buf, ctx->npos);
  564. a->curr[LTY_POLICY].p->metadata->length = /* the index in handle->metadata */
  565. a->curr[LTY_POLICY].p->metadata_count++;
  566. break;
  567. #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
  568. case LSSPPT_HTTP_AUTH_HEADER:
  569. case LSSPPT_HTTP_DSN_HEADER:
  570. case LSSPPT_HTTP_FWV_HEADER:
  571. case LSSPPT_HTTP_TYPE_HEADER:
  572. pp = (char **)&a->curr[LTY_POLICY].p->u.http.blob_header[
  573. (ctx->path_match - 1) - LSSPPT_HTTP_AUTH_HEADER];
  574. goto string2;
  575. case LSSPPT_HTTP_AUTH_PREAMBLE:
  576. pp = (char **)&a->curr[LTY_POLICY].p->u.http.auth_preamble;
  577. goto string2;
  578. case LSSPPT_HTTP_NO_CONTENT_LENGTH:
  579. if (reason == LEJPCB_VAL_TRUE)
  580. a->curr[LTY_POLICY].p->flags |=
  581. LWSSSPOLF_HTTP_NO_CONTENT_LENGTH;
  582. break;
  583. case LSSPPT_NGHTTP2_QUIRK_END_STREAM:
  584. if (reason == LEJPCB_VAL_TRUE)
  585. a->curr[LTY_POLICY].p->flags |=
  586. LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM;
  587. break;
  588. case LSSPPT_H2_QUIRK_OVERFLOWS_TXCR:
  589. if (reason == LEJPCB_VAL_TRUE)
  590. a->curr[LTY_POLICY].p->flags |=
  591. LWSSSPOLF_H2_QUIRK_OVERFLOWS_TXCR;
  592. break;
  593. case LSSPPT_HTTP_MULTIPART_NAME:
  594. a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_MULTIPART;
  595. pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_name;
  596. goto string2;
  597. case LSSPPT_HTTP_MULTIPART_FILENAME:
  598. a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_MULTIPART;
  599. pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_filename;
  600. goto string2;
  601. case LSSPPT_HTTP_MULTIPART_CONTENT_TYPE:
  602. a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_MULTIPART;
  603. pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_content_type;
  604. goto string2;
  605. case LSSPPT_HTTP_FAIL_REDIRECT:
  606. a->curr[LTY_POLICY].p->u.http.fail_redirect =
  607. reason == LEJPCB_VAL_TRUE;
  608. break;
  609. #endif
  610. #if defined(LWS_ROLE_WS)
  611. case LSSPPT_WS_SUBPROTOCOL:
  612. pp = (char **)&a->curr[LTY_POLICY].p->u.http.u.ws.subprotocol;
  613. goto string2;
  614. case LSSPPT_WS_BINARY:
  615. a->curr[LTY_POLICY].p->u.http.u.ws.binary =
  616. reason == LEJPCB_VAL_TRUE;
  617. break;
  618. #endif
  619. case LSSPPT_LOCAL_SINK:
  620. if (reason == LEJPCB_VAL_TRUE)
  621. a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_LOCAL_SINK;
  622. break;
  623. case LSSPPT_SERVER:
  624. if (reason == LEJPCB_VAL_TRUE)
  625. a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_SERVER;
  626. break;
  627. #if defined(LWS_ROLE_MQTT)
  628. case LSSPPT_MQTT_TOPIC:
  629. pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.topic;
  630. goto string2;
  631. case LSSPPT_MQTT_SUBSCRIBE:
  632. pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.subscribe;
  633. goto string2;
  634. case LSSPPT_MQTT_QOS:
  635. a->curr[LTY_POLICY].p->u.mqtt.qos = atoi(ctx->buf);
  636. break;
  637. case LSSPPT_MQTT_KEEPALIVE:
  638. a->curr[LTY_POLICY].p->u.mqtt.keep_alive = atoi(ctx->buf);
  639. break;
  640. case LSSPPT_MQTT_CLEAN_START:
  641. a->curr[LTY_POLICY].p->u.mqtt.clean_start =
  642. reason == LEJPCB_VAL_TRUE;
  643. break;
  644. case LSSPPT_MQTT_WILL_TOPIC:
  645. pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.will_topic;
  646. goto string2;
  647. case LSSPPT_MQTT_WILL_MESSAGE:
  648. pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.will_message;
  649. goto string2;
  650. case LSSPPT_MQTT_WILL_QOS:
  651. a->curr[LTY_POLICY].p->u.mqtt.will_qos = atoi(ctx->buf);
  652. break;
  653. case LSSPPT_MQTT_WILL_RETAIN:
  654. a->curr[LTY_POLICY].p->u.mqtt.will_retain =
  655. reason == LEJPCB_VAL_TRUE;
  656. break;
  657. #endif
  658. case LSSPPT_PROTOCOL:
  659. a->curr[LTY_POLICY].p->protocol = 0xff;
  660. for (n = 0; n < (int)LWS_ARRAY_SIZE(protonames); n++)
  661. if (strlen(protonames[n]) == ctx->npos &&
  662. !strncmp(ctx->buf, protonames[n], ctx->npos))
  663. a->curr[LTY_POLICY].p->protocol = (uint8_t)n;
  664. if (a->curr[LTY_POLICY].p->protocol != 0xff)
  665. break;
  666. lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar));
  667. lwsl_err("%s: unknown protocol name %s\n", __func__, dotstar);
  668. return -1;
  669. default:
  670. break;
  671. }
  672. return 0;
  673. string2:
  674. /*
  675. * If we can do const string folding, reuse the existing string rather
  676. * than make a new entry
  677. */
  678. extant = lwsac_scan_extant(a->ac, (uint8_t *)ctx->buf, ctx->npos, 1);
  679. if (extant) {
  680. *pp = (char *)extant;
  681. return 0;
  682. }
  683. *pp = lwsac_use_backfill(&a->ac, ctx->npos + 1, POL_AC_GRAIN);
  684. if (!*pp)
  685. goto oom;
  686. memcpy(*pp, ctx->buf, ctx->npos);
  687. (*pp)[ctx->npos] = '\0';
  688. return 0;
  689. string1:
  690. n = ctx->st[ctx->sp].p;
  691. *pp = lwsac_use_backfill(&a->ac, ctx->path_match_len + 1 - n,
  692. POL_AC_GRAIN);
  693. if (!*pp)
  694. goto oom;
  695. memcpy(*pp, ctx->path + n, ctx->path_match_len - n);
  696. (*pp)[ctx->path_match_len - n] = '\0';
  697. return 0;
  698. oom:
  699. lwsl_err("%s: OOM\n", __func__);
  700. lws_free_set_NULL(a->p);
  701. lwsac_free(&a->ac);
  702. return -1;
  703. }
  704. int
  705. lws_ss_policy_parse_begin(struct lws_context *context, int overlay)
  706. {
  707. struct policy_cb_args *args;
  708. char *p;
  709. args = lws_zalloc(sizeof(struct policy_cb_args), __func__);
  710. if (!args) {
  711. lwsl_err("%s: OOM\n", __func__);
  712. return 1;
  713. }
  714. if (overlay)
  715. /* continue to use the existing lwsac */
  716. args->ac = context->ac_policy;
  717. else
  718. /* we don't want to see any old policy */
  719. context->pss_policies = NULL;
  720. context->pol_args = args;
  721. args->context = context;
  722. p = lwsac_use(&args->ac, 1, POL_AC_INITIAL);
  723. if (!p) {
  724. lwsl_err("%s: OOM\n", __func__);
  725. lws_free_set_NULL(context->pol_args);
  726. return -1;
  727. }
  728. *p = 0;
  729. lejp_construct(&args->jctx, lws_ss_policy_parser_cb, args,
  730. lejp_tokens_policy, LWS_ARRAY_SIZE(lejp_tokens_policy));
  731. return 0;
  732. }
  733. int
  734. lws_ss_policy_parse_abandon(struct lws_context *context)
  735. {
  736. struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args;
  737. lejp_destruct(&args->jctx);
  738. lwsac_free(&args->ac);
  739. lws_free_set_NULL(context->pol_args);
  740. return 0;
  741. }
  742. int
  743. lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len)
  744. {
  745. struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args;
  746. int m;
  747. m = lejp_parse(&args->jctx, buf, (int)len);
  748. if (m == LEJP_CONTINUE || m >= 0)
  749. return m;
  750. lwsl_err("%s: parse failed line %u: %d: %s\n", __func__,
  751. args->jctx.line, m, lejp_error_to_string(m));
  752. lws_ss_policy_parse_abandon(context);
  753. assert(0);
  754. return m;
  755. }
  756. int
  757. lws_ss_policy_overlay(struct lws_context *context, const char *overlay)
  758. {
  759. lws_ss_policy_parse_begin(context, 1);
  760. return lws_ss_policy_parse(context, (const uint8_t *)overlay,
  761. strlen(overlay));
  762. }
  763. const lws_ss_policy_t *
  764. lws_ss_policy_get(struct lws_context *context)
  765. {
  766. struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args;
  767. if (!args)
  768. return NULL;
  769. return args->heads[LTY_POLICY].p;
  770. }