1/* 2 * libwebsockets - small server side websockets and web server implementation 3 * 4 * Copyright (C) 2019 - 2021 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 * 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 28#include <private-lib-core.h> 29 30static const char * const lejp_tokens_policy[] = { 31 "release", 32 "product", 33 "schema-version", 34 "via-socks5", 35 "retry[].*.backoff", 36 "retry[].*.conceal", 37 "retry[].*.jitterpc", 38 "retry[].*.svalidping", 39 "retry[].*.svalidhup", 40 "retry[].*", 41 "certs[].*", 42 "trust_stores[].name", 43 "trust_stores[].stack", 44 "metrics[].name", 45 "metrics[].us_schedule", 46 "metrics[].us_halflife", 47 "metrics[].min_outlier", 48 "metrics[].report", 49 "s[].*.endpoint", 50 "s[].*.via-socks5", 51 "s[].*.protocol", 52 "s[].*.port", 53 "s[].*.plugins", 54 "s[].*.tls", 55 "s[].*.client_cert", 56 "s[].*.opportunistic", 57 "s[].*.nailed_up", 58 "s[].*.allow_redirects", 59 "s[].*.urgent_tx", 60 "s[].*.urgent_rx", 61 "s[].*.attr_priority", 62 "s[].*.attr_low_latency", 63 "s[].*.attr_high_throughput", 64 "s[].*.attr_high_reliability", 65 "s[].*.attr_low_cost", 66 "s[].*.long_poll", 67 "s[].*.ws_prioritize_reads", 68 "s[].*.retry", 69 "s[].*.timeout_ms", 70 "s[].*.perf", 71 "s[].*.tls_trust_store", 72 "s[].*.proxy_buflen", 73 "s[].*.proxy_buflen_rxflow_on_above", 74 "s[].*.proxy_buflen_rxflow_off_below", 75 "s[].*.client_buflen", 76 "s[].*.client_buflen_rxflow_on_above", 77 "s[].*.client_buflen_rxflow_off_below", 78 "s[].*.metadata", 79 "s[].*.metadata[].*", 80 "s[].*.http_resp_map", 81 "s[].*.http_resp_map[].*", 82 83 "s[].*.http_auth_header", 84 "s[].*.http_dsn_header", 85 "s[].*.http_fwv_header", 86 "s[].*.http_devtype_header", 87 88 "s[].*.http_auth_preamble", 89 90 "s[].*.http_no_content_length", 91 "s[].*.rideshare", /* streamtype name this rides shotgun with */ 92 "s[].*.payload_fmt", 93 "s[].*.http_method", 94 "s[].*.http_url", 95 "s[].*.nghttp2_quirk_end_stream", 96 "s[].*.h2q_oflow_txcr", 97 "s[].*.http_multipart_name", 98 "s[].*.http_multipart_filename", 99 "s[].*.http_mime_content_type", 100 "s[].*.http_www_form_urlencoded", 101 "s[].*.http_expect", 102 "s[].*.http_cookies", 103 "s[].*.http_fail_redirect", 104 "s[].*.http_multipart_ss_in", 105 "s[].*.ws_subprotocol", 106 "s[].*.ws_binary", 107 "s[].*.local_sink", 108 "s[].*.server", 109 "s[].*.server_cert", 110 "s[].*.server_key", 111 "s[].*.mqtt_topic", 112 "s[].*.mqtt_subscribe", 113 "s[].*.mqtt_qos", 114 "s[].*.mqtt_retain", 115 "s[].*.mqtt_keep_alive", 116 "s[].*.mqtt_clean_start", 117 "s[].*.mqtt_will_topic", 118 "s[].*.mqtt_will_message", 119 "s[].*.mqtt_will_qos", 120 "s[].*.mqtt_will_retain", 121 "s[].*.mqtt_birth_topic", 122 "s[].*.mqtt_birth_message", 123 "s[].*.mqtt_birth_qos", 124 "s[].*.mqtt_birth_retain", 125 "s[].*.aws_iot", 126 "s[].*.swake_validity", 127 "s[].*.use_auth", 128 "s[].*.aws_region", 129 "s[].*.aws_service", 130 "s[].*.direct_proto_str", 131 "s[].*", 132 "auth[].name", 133 "auth[].type", 134 "auth[].streamtype", 135 "auth[].blob", 136 "auth[]", 137}; 138 139typedef enum { 140 LSSPPT_RELEASE, 141 LSSPPT_PRODUCT, 142 LSSPPT_SCHEMA_VERSION, 143 LSSPPT_VIA_SOCKS5, 144 LSSPPT_BACKOFF, 145 LSSPPT_CONCEAL, 146 LSSPPT_JITTERPC, 147 LSSPPT_VALIDPING_S, 148 LSSPPT_VALIDHUP_S, 149 LSSPPT_RETRY, 150 LSSPPT_CERTS, 151 LSSPPT_TRUST_STORES_NAME, 152 LSSPPT_TRUST_STORES_STACK, 153 LSSPPT_METRICS_NAME, 154 LSSPPT_METRICS_US_SCHEDULE, 155 LSSPPT_METRICS_US_HALFLIFE, 156 LSSPPT_METRICS_MIN_OUTLIER, 157 LSSPPT_METRICS_REPORT, 158 LSSPPT_ENDPOINT, 159 LSSPPT_VH_VIA_SOCKS5, 160 LSSPPT_PROTOCOL, 161 LSSPPT_PORT, 162 LSSPPT_PLUGINS, 163 LSSPPT_TLS, 164 LSSPPT_TLS_CLIENT_CERT, 165 LSSPPT_OPPORTUNISTIC, 166 LSSPPT_NAILED_UP, 167 LSSPPT_ALLOW_REDIRECTS, 168 LSSPPT_URGENT_TX, 169 LSSPPT_URGENT_RX, 170 LSSPPT_ATTR_PRIORITY, 171 LSSPPT_ATTR_LOW_LATENCY, 172 LSSPPT_ATTR_HIGH_THROUGHPUT, 173 LSSPPT_ATTR_HIGH_RELIABILITY, 174 LSSPPT_ATTR_LOW_COST, 175 LSSPPT_LONG_POLL, 176 LSSPPT_PRIORITIZE_READS, 177 LSSPPT_RETRYPTR, 178 LSSPPT_DEFAULT_TIMEOUT_MS, 179 LSSPPT_PERF, 180 LSSPPT_TRUST, 181 LSSPPT_PROXY_BUFLEN, 182 LSSPPT_PROXY_BUFLEN_RXFLOW_ON_ABOVE, 183 LSSPPT_PROXY_BUFLEN_RXFLOW_OFF_BELOW, 184 LSSPPT_CLIENT_BUFLEN, 185 LSSPPT_CLIENT_BUFLEN_RXFLOW_ON_ABOVE, 186 LSSPPT_CLIENT_BUFLEN_RXFLOW_OFF_BELOW, 187 LSSPPT_METADATA, 188 LSSPPT_METADATA_ITEM, 189 LSSPPT_HTTPRESPMAP, 190 LSSPPT_HTTPRESPMAP_ITEM, 191 192 LSSPPT_HTTP_AUTH_HEADER, 193 LSSPPT_HTTP_DSN_HEADER, 194 LSSPPT_HTTP_FWV_HEADER, 195 LSSPPT_HTTP_TYPE_HEADER, 196 197 LSSPPT_HTTP_AUTH_PREAMBLE, 198 LSSPPT_HTTP_NO_CONTENT_LENGTH, 199 LSSPPT_RIDESHARE, 200 LSSPPT_PAYLOAD_FORMAT, 201 LSSPPT_HTTP_METHOD, 202 LSSPPT_HTTP_URL, 203 LSSPPT_NGHTTP2_QUIRK_END_STREAM, 204 LSSPPT_H2_QUIRK_OVERFLOWS_TXCR, 205 LSSPPT_HTTP_MULTIPART_NAME, 206 LSSPPT_HTTP_MULTIPART_FILENAME, 207 LSSPPT_HTTP_MULTIPART_CONTENT_TYPE, 208 LSSPPT_HTTP_WWW_FORM_URLENCODED, 209 LSSPPT_HTTP_EXPECT, 210 LSSPPT_HTTP_COOKIES, 211 LSSPPT_HTTP_FAIL_REDIRECT, 212 LSSPPT_HTTP_MULTIPART_SS_IN, 213 LSSPPT_WS_SUBPROTOCOL, 214 LSSPPT_WS_BINARY, 215 LSSPPT_LOCAL_SINK, 216 LSSPPT_SERVER, 217 LSSPPT_SERVER_CERT, 218 LSSPPT_SERVER_KEY, 219 LSSPPT_MQTT_TOPIC, 220 LSSPPT_MQTT_SUBSCRIBE, 221 LSSPPT_MQTT_QOS, 222 LSSPPT_MQTT_RETAIN, 223 LSSPPT_MQTT_KEEPALIVE, 224 LSSPPT_MQTT_CLEAN_START, 225 LSSPPT_MQTT_WILL_TOPIC, 226 LSSPPT_MQTT_WILL_MESSAGE, 227 LSSPPT_MQTT_WILL_QOS, 228 LSSPPT_MQTT_WILL_RETAIN, 229 LSSPPT_MQTT_BIRTH_TOPIC, 230 LSSPPT_MQTT_BIRTH_MESSAGE, 231 LSSPPT_MQTT_BIRTH_QOS, 232 LSSPPT_MQTT_BIRTH_RETAIN, 233 LSSPPT_MQTT_AWS_IOT, 234 LSSPPT_SWAKE_VALIDITY, 235 LSSPPT_USE_AUTH, 236 LSSPPT_AWS_REGION, 237 LSSPPT_AWS_SERVICE, 238 LSSPPT_DIRECT_PROTO_STR, 239 LSSPPT_STREAMTYPES, 240 LSSPPT_AUTH_NAME, 241 LSSPPT_AUTH_TYPE, 242 LSSPPT_AUTH_STREAMTYPE, 243 LSSPPT_AUTH_BLOB, 244 LSSPPT_AUTH, 245 246} policy_token_t; 247 248#define POL_AC_INITIAL 2048 249#define POL_AC_GRAIN 800 250#define MAX_CERT_TEMP 3072 /* used to discover actual cert size for realloc */ 251 252static uint16_t sizes[] = { 253 sizeof(backoff_t), 254 sizeof(lws_ss_x509_t), 255 sizeof(lws_ss_trust_store_t), 256 sizeof(lws_ss_policy_t), 257 sizeof(lws_ss_auth_t), 258 sizeof(lws_metric_policy_t), 259}; 260 261static const char * const protonames[] = { 262 "h1", /* LWSSSP_H1 */ 263 "h2", /* LWSSSP_H2 */ 264 "ws", /* LWSSSP_WS */ 265 "mqtt", /* LWSSSP_MQTT */ 266 "raw", /* LWSSSP_RAW */ 267}; 268 269static const lws_ss_auth_t * 270lws_ss_policy_find_auth_by_name(struct policy_cb_args *a, 271 const char *name, size_t len) 272{ 273 const lws_ss_auth_t *auth = a->heads[LTY_AUTH].a; 274 275 while (auth) { 276 if (auth->name && 277 len == strlen(auth->name) && 278 !strncmp(auth->name, name, len)) 279 return auth; 280 281 auth = auth->next; 282 } 283 284 return NULL; 285} 286 287static int 288lws_ss_policy_alloc_helper(struct policy_cb_args *a, int type) 289{ 290 /* 291 * We do the pointers always as .b union member, all of the 292 * participating structs begin with .next and .name the same 293 */ 294 295 a->curr[type].b = lwsac_use_zero(&a->ac, 296 sizes[type], POL_AC_GRAIN); 297 if (!a->curr[type].b) 298 return 1; 299 300 a->curr[type].b->next = a->heads[type].b; 301 a->heads[type].b = a->curr[type].b; 302 303 return 0; 304} 305 306static signed char 307lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) 308{ 309 struct policy_cb_args *a = (struct policy_cb_args *)ctx->user; 310#if defined(LWS_WITH_SSPLUGINS) 311 const lws_ss_plugin_t **pin; 312#endif 313 char **pp, dotstar[32], *q; 314 lws_ss_trust_store_t *ts; 315 lws_ss_metadata_t *pmd; 316 lws_ss_x509_t *x, **py; 317 lws_ss_policy_t *p2; 318 lws_retry_bo_t *b; 319 size_t inl, outl; 320 uint8_t *extant; 321 backoff_t *bot; 322 int n = -1; 323 324// lwsl_debug("%s: %d %d %s\n", __func__, reason, ctx->path_match - 1, 325// ctx->path); 326 327 switch (ctx->path_match - 1) { 328 case LSSPPT_RETRY: 329 n = LTY_BACKOFF; 330 break; 331 case LSSPPT_CERTS: 332 n = LTY_X509; 333 break; 334 case LSSPPT_TRUST_STORES_NAME: 335 case LSSPPT_TRUST_STORES_STACK: 336 n = LTY_TRUSTSTORE; 337 break; 338 case LSSPPT_STREAMTYPES: 339 n = LTY_POLICY; 340 break; 341 case LSSPPT_AUTH: 342 n = LTY_AUTH; 343 break; 344 case LSSPPT_METRICS_NAME: 345 case LSSPPT_METRICS_US_SCHEDULE: 346 case LSSPPT_METRICS_US_HALFLIFE: 347 case LSSPPT_METRICS_MIN_OUTLIER: 348 case LSSPPT_METRICS_REPORT: 349 n = LTY_METRICS; 350 break; 351 } 352 353 if (reason == LEJPCB_ARRAY_START && 354 (ctx->path_match - 1 == LSSPPT_PLUGINS || 355 ctx->path_match - 1 == LSSPPT_METADATA || 356 ctx->path_match - 1 == LSSPPT_HTTPRESPMAP)) 357 a->count = 0; 358 359 if (reason == LEJPCB_OBJECT_START && n == LTY_AUTH) { 360 if (lws_ss_policy_alloc_helper(a, LTY_AUTH)) 361 goto oom; 362 return 0; 363 } 364 365 if (reason == LEJPCB_ARRAY_END && 366 ctx->path_match - 1 == LSSPPT_TRUST_STORES_STACK && !a->count) { 367 lwsl_err("%s: at least one cert required in trust store\n", 368 __func__); 369 goto oom; 370 } 371 372 if (reason == LEJPCB_ARRAY_END && a->count && a->pending_respmap) { 373 374 // lwsl_notice("%s: allocating respmap %d\n", __func__, a->count); 375 376 a->curr[LTY_POLICY].p->u.http.respmap = lwsac_use_zero(&a->ac, 377 sizeof(lws_ss_http_respmap_t) * (unsigned int)a->count, POL_AC_GRAIN); 378 379 if (!a->curr[LTY_POLICY].p->u.http.respmap) 380 goto oom; 381 382 memcpy((void *)a->curr[LTY_POLICY].p->u.http.respmap, 383 a->respmap, sizeof(lws_ss_http_respmap_t) * (unsigned int)a->count); 384 a->curr[LTY_POLICY].p->u.http.count_respmap = (uint8_t)a->count; 385 a->count = 0; 386 a->pending_respmap = 0; 387 388 return 0; 389 } 390 391 if (reason == LEJPCB_OBJECT_END && a->p) { 392 /* 393 * Allocate a just-the-right-size buf for the cert DER now 394 * we decoded it into the a->p temp buffer and know the exact 395 * size. 396 * 397 * The struct *x is in the lwsac... the ca_der it points to 398 * is individually allocated from the heap 399 */ 400 a->curr[LTY_X509].x->ca_der = lws_malloc((unsigned int)a->count, "ssx509"); 401 if (!a->curr[LTY_X509].x->ca_der) 402 goto oom; 403 memcpy((uint8_t *)a->curr[LTY_X509].x->ca_der, a->p, (unsigned int)a->count); 404 a->curr[LTY_X509].x->ca_der_len = (unsigned int)a->count; 405 406 /* 407 * ... and then we can free the temp buffer 408 */ 409 lws_free_set_NULL(a->p); 410 411 return 0; 412 } 413 414 if (reason == LEJPCB_PAIR_NAME && n != -1 && 415 (n != LTY_TRUSTSTORE && n != LTY_AUTH && n != LTY_METRICS)) { 416 417 p2 = NULL; 418 if (n == LTY_POLICY) { 419 /* 420 * We want to allow for the possibility of overlays... 421 * eg, we come later with a JSON snippet that overrides 422 * select streamtype members of a streamtype that was 423 * already defined 424 */ 425 p2 = (lws_ss_policy_t *)a->context->pss_policies; 426 427 while (p2) { 428 if (!strncmp(p2->streamtype, 429 ctx->path + ctx->st[ctx->sp].p, 430 (unsigned int)(ctx->path_match_len - 431 ctx->st[ctx->sp].p))) { 432 lwsl_info("%s: overriding s[] %s\n", 433 __func__, p2->streamtype); 434 break; 435 } 436 437 p2 = p2->next; 438 } 439 } 440 441 /* 442 * We do the pointers always as .b union member, all of the 443 * participating structs begin with .next and .name the same 444 */ 445 if (p2) /* we may be overriding existing streamtype... */ 446 a->curr[n].b = (backoff_t *)p2; 447 else 448 a->curr[n].b = lwsac_use_zero(&a->ac, sizes[n], 449 POL_AC_GRAIN); 450 if (!a->curr[n].b) 451 goto oom; 452 453 if (n == LTY_X509) { 454 a->p = lws_malloc(MAX_CERT_TEMP, "cert temp"); 455 if (!a->p) 456 goto oom; 457 memset(&a->b64, 0, sizeof(a->b64)); 458 } 459 460 a->count = 0; 461 if (!p2) { 462 a->curr[n].b->next = a->heads[n].b; 463 a->heads[n].b = a->curr[n].b; 464 pp = (char **)&a->curr[n].b->name; 465 466 goto string1; 467 } 468 469 return 0; /* overriding */ 470 } 471 472 if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match) 473 return 0; 474 475 switch (ctx->path_match - 1) { 476 477 /* strings */ 478 479 case LSSPPT_RELEASE: 480 break; 481 482 case LSSPPT_PRODUCT: 483 break; 484 485 case LSSPPT_SCHEMA_VERSION: 486 break; 487 488 case LSSPPT_VIA_SOCKS5: 489 /* the global / default proxy */ 490 pp = (char **)&a->socks5_proxy; 491 goto string2; 492 493 case LSSPPT_BACKOFF: 494 b = &a->curr[LTY_BACKOFF].b->r; 495 if (b->retry_ms_table_count == 8) { 496 lwsl_err("%s: > 8 backoff levels\n", __func__); 497 return 1; 498 } 499 if (!b->retry_ms_table_count) { 500 b->retry_ms_table = (uint32_t *)lwsac_use_zero(&a->ac, 501 sizeof(uint32_t) * 8, POL_AC_GRAIN); 502 if (!b->retry_ms_table) 503 goto oom; 504 } 505 506 ((uint32_t *)b->retry_ms_table) 507 [b->retry_ms_table_count++] = (uint32_t)atoi(ctx->buf); 508 break; 509 510 case LSSPPT_CONCEAL: 511 a->curr[LTY_BACKOFF].b->r.conceal_count = (uint16_t)atoi(ctx->buf); 512 break; 513 514 case LSSPPT_JITTERPC: 515 a->curr[LTY_BACKOFF].b->r.jitter_percent = (uint8_t)atoi(ctx->buf); 516 break; 517 518 case LSSPPT_VALIDPING_S: 519 a->curr[LTY_BACKOFF].b->r.secs_since_valid_ping = (uint16_t)atoi(ctx->buf); 520 break; 521 522 case LSSPPT_VALIDHUP_S: 523 a->curr[LTY_BACKOFF].b->r.secs_since_valid_hangup = (uint16_t)atoi(ctx->buf); 524 break; 525 526 case LSSPPT_CERTS: 527 if (a->count + ctx->npos >= MAX_CERT_TEMP) { 528 lwsl_err("%s: cert too big\n", __func__); 529 goto oom; 530 } 531 inl = ctx->npos; 532 outl = MAX_CERT_TEMP - (unsigned int)a->count; 533 534 lws_b64_decode_stateful(&a->b64, ctx->buf, &inl, 535 a->p + a->count, &outl, 536 reason == LEJPCB_VAL_STR_END); 537 a->count += (int)outl; 538 if (inl != ctx->npos) { 539 lwsl_err("%s: b64 decode fail\n", __func__); 540 goto oom; 541 } 542 break; 543 544 case LSSPPT_TRUST_STORES_NAME: 545 if (lws_ss_policy_alloc_helper(a, LTY_TRUSTSTORE)) 546 goto oom; 547 548 a->count = 0; 549 pp = (char **)&a->curr[LTY_TRUSTSTORE].b->name; 550 551 goto string2; 552 553 case LSSPPT_TRUST_STORES_STACK: 554 if (a->count >= (int)LWS_ARRAY_SIZE( 555 a->curr[LTY_TRUSTSTORE].t->ssx509)) { 556 lwsl_err("%s: trust store too big\n", __func__); 557 goto oom; 558 } 559 lwsl_debug("%s: trust stores stack %.*s\n", __func__, 560 ctx->npos, ctx->buf); 561 x = a->heads[LTY_X509].x; 562 while (x) { 563 if (!strncmp(x->vhost_name, ctx->buf, ctx->npos)) { 564 a->curr[LTY_TRUSTSTORE].t->ssx509[a->count++] = x; 565 a->curr[LTY_TRUSTSTORE].t->count++; 566 567 return 0; 568 } 569 x = x->next; 570 } 571 lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar)); 572 lwsl_err("%s: unknown trust store entry %s\n", __func__, 573 dotstar); 574 goto oom; 575#if defined(LWS_WITH_SYS_METRICS) 576 case LSSPPT_METRICS_NAME: 577 if (lws_ss_policy_alloc_helper(a, LTY_METRICS)) 578 goto oom; 579 580 pp = (char **)&a->curr[LTY_METRICS].b->name; 581 582 goto string2; 583 584 case LSSPPT_METRICS_US_SCHEDULE: 585 a->curr[LTY_METRICS].m->us_schedule = (uint64_t)atoll(ctx->buf); 586 break; 587 588 case LSSPPT_METRICS_US_HALFLIFE: 589 a->curr[LTY_METRICS].m->us_decay_unit = (uint32_t)atol(ctx->buf); 590 break; 591 592 case LSSPPT_METRICS_MIN_OUTLIER: 593 a->curr[LTY_METRICS].m->min_contributors = (uint8_t)atoi(ctx->buf); 594 break; 595 596 case LSSPPT_METRICS_REPORT: 597 pp = (char **)&a->curr[LTY_METRICS].m->report; 598 goto string2; 599#endif 600 601 case LSSPPT_SERVER_CERT: 602 case LSSPPT_SERVER_KEY: 603 604 /* iterate through the certs */ 605 606 py = &a->heads[LTY_X509].x; 607 x = a->heads[LTY_X509].x; 608 while (x) { 609 if (!strncmp(x->vhost_name, ctx->buf, ctx->npos) && 610 !x->vhost_name[ctx->npos]) { 611 if ((ctx->path_match - 1) == LSSPPT_SERVER_CERT) 612 a->curr[LTY_POLICY].p->trust.server.cert = x; 613 else 614 a->curr[LTY_POLICY].p->trust.server.key = x; 615 /* 616 * Certs that are for servers need to stick 617 * around in DER form, so the vhost can be 618 * instantiated when the server is brought up 619 */ 620 x->keep = 1; 621 lwsl_notice("%s: server '%s' keep %d %p\n", 622 __func__, x->vhost_name, 623 ctx->path_match - 1, x); 624 625 /* 626 * Server DER we need to move it to another 627 * list just for destroying it when the context 628 * is destroyed... snip us out of the live 629 * X.509 list 630 */ 631 632 *py = x->next; 633 634 /* 635 * ... and instead put us on the list of things 636 * to keep hold of for context destruction 637 */ 638 639 x->next = a->context->server_der_list; 640 a->context->server_der_list = x; 641 642 return 0; 643 } 644 py = &x->next; 645 x = x->next; 646 } 647 lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar)); 648 lwsl_err("%s: unknown cert / key %s\n", __func__, dotstar); 649 goto oom; 650 651 case LSSPPT_ENDPOINT: 652 pp = (char **)&a->curr[LTY_POLICY].p->endpoint; 653 goto string2; 654 655 case LSSPPT_VH_VIA_SOCKS5: 656 pp = (char **)&a->curr[LTY_POLICY].p->socks5_proxy; 657 goto string2; 658 659 case LSSPPT_PORT: 660 a->curr[LTY_POLICY].p->port = (uint16_t)atoi(ctx->buf); 661 break; 662 663 case LSSPPT_PROXY_BUFLEN: 664 a->curr[LTY_POLICY].p->proxy_buflen = (uint32_t)atol(ctx->buf); 665 break; 666 667 case LSSPPT_PROXY_BUFLEN_RXFLOW_ON_ABOVE: 668 a->curr[LTY_POLICY].p->proxy_buflen_rxflow_on_above = 669 (uint32_t)atol(ctx->buf); 670 break; 671 case LSSPPT_PROXY_BUFLEN_RXFLOW_OFF_BELOW: 672 a->curr[LTY_POLICY].p->proxy_buflen_rxflow_off_below = 673 (uint32_t)atol(ctx->buf); 674 break; 675 676 case LSSPPT_CLIENT_BUFLEN: 677 a->curr[LTY_POLICY].p->client_buflen = (uint32_t)atol(ctx->buf); 678 break; 679 680 case LSSPPT_CLIENT_BUFLEN_RXFLOW_ON_ABOVE: 681 a->curr[LTY_POLICY].p->client_buflen_rxflow_on_above = 682 (uint32_t)atol(ctx->buf); 683 break; 684 case LSSPPT_CLIENT_BUFLEN_RXFLOW_OFF_BELOW: 685 a->curr[LTY_POLICY].p->client_buflen_rxflow_off_below = 686 (uint32_t)atol(ctx->buf); 687 break; 688 689 case LSSPPT_HTTP_METHOD: 690 pp = (char **)&a->curr[LTY_POLICY].p->u.http.method; 691 goto string2; 692 693 case LSSPPT_HTTP_URL: 694 pp = (char **)&a->curr[LTY_POLICY].p->u.http.url; 695 goto string2; 696 697 case LSSPPT_RIDESHARE: 698 pp = (char **)&a->curr[LTY_POLICY].p->rideshare_streamtype; 699 goto string2; 700 701 case LSSPPT_PAYLOAD_FORMAT: 702 pp = (char **)&a->curr[LTY_POLICY].p->payload_fmt; 703 goto string2; 704 705 case LSSPPT_PLUGINS: 706#if defined(LWS_WITH_SSPLUGINS) 707 pin = a->context->pss_plugins; 708 if (a->count == 709 (int)LWS_ARRAY_SIZE(a->curr[LTY_POLICY].p->plugins)) { 710 lwsl_err("%s: too many plugins\n", __func__); 711 712 goto oom; 713 } 714 if (!pin) 715 break; 716 while (*pin) { 717 if (!strncmp((*pin)->name, ctx->buf, ctx->npos)) { 718 a->curr[LTY_POLICY].p->plugins[a->count++] = *pin; 719 return 0; 720 } 721 pin++; 722 } 723 lwsl_err("%s: unknown plugin\n", __func__); 724 goto oom; 725#else 726 break; 727#endif 728 729 case LSSPPT_TLS: 730 if (reason == LEJPCB_VAL_TRUE) 731 a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_TLS; 732 break; 733 734 case LSSPPT_TLS_CLIENT_CERT: 735 a->curr[LTY_POLICY].p->client_cert = (uint8_t)(atoi(ctx->buf) + 1); 736 break; 737 738 case LSSPPT_AUTH_BLOB: 739 a->curr[LTY_AUTH].a->blob_index = (uint8_t)atoi(ctx->buf); 740 break; 741 case LSSPPT_HTTP_EXPECT: 742 a->curr[LTY_POLICY].p->u.http.resp_expect = (uint16_t)atoi(ctx->buf); 743 break; 744 745 case LSSPPT_DEFAULT_TIMEOUT_MS: 746 a->curr[LTY_POLICY].p->timeout_ms = (uint32_t)atoi(ctx->buf); 747 break; 748 749 case LSSPPT_ATTR_PRIORITY: 750 a->curr[LTY_POLICY].p->priority = (uint8_t)atoi(ctx->buf); 751 break; 752 753 case LSSPPT_OPPORTUNISTIC: 754 if (reason == LEJPCB_VAL_TRUE) 755 a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_OPPORTUNISTIC; 756 break; 757 case LSSPPT_NAILED_UP: 758 if (reason == LEJPCB_VAL_TRUE) 759 a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_NAILED_UP; 760 break; 761 case LSSPPT_URGENT_TX: 762 if (reason == LEJPCB_VAL_TRUE) 763 a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_URGENT_TX; 764 break; 765 case LSSPPT_URGENT_RX: 766 if (reason == LEJPCB_VAL_TRUE) 767 a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_URGENT_RX; 768 break; 769 case LSSPPT_LONG_POLL: 770 if (reason == LEJPCB_VAL_TRUE) 771 a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_LONG_POLL; 772 break; 773 case LSSPPT_PRIORITIZE_READS: 774 if (reason == LEJPCB_VAL_TRUE) 775 a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_PRIORITIZE_READS; 776 break; 777 778 case LSSPPT_HTTP_WWW_FORM_URLENCODED: 779 if (reason == LEJPCB_VAL_TRUE) 780 a->curr[LTY_POLICY].p->flags |= 781 LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED; 782 break; 783 case LSSPPT_SWAKE_VALIDITY: 784 if (reason == LEJPCB_VAL_TRUE) 785 a->curr[LTY_POLICY].p->flags |= 786 LWSSSPOLF_WAKE_SUSPEND__VALIDITY; 787 break; 788 case LSSPPT_ALLOW_REDIRECTS: 789 if (reason == LEJPCB_VAL_TRUE) 790 a->curr[LTY_POLICY].p->flags |= 791 LWSSSPOLF_ALLOW_REDIRECTS; 792 break; 793 case LSSPPT_HTTP_COOKIES: 794 if (reason == LEJPCB_VAL_TRUE) 795 a->curr[LTY_POLICY].p->flags |= 796 LWSSSPOLF_HTTP_CACHE_COOKIES; 797 break; 798 case LSSPPT_HTTP_MULTIPART_SS_IN: 799 if (reason == LEJPCB_VAL_TRUE) 800 a->curr[LTY_POLICY].p->flags |= 801 LWSSSPOLF_HTTP_MULTIPART_IN; 802 return 0; 803 804 case LSSPPT_ATTR_LOW_LATENCY: 805 if (reason == LEJPCB_VAL_TRUE) 806 a->curr[LTY_POLICY].p->flags |= 807 LWSSSPOLF_ATTR_LOW_LATENCY; 808 return 0; 809 810 case LSSPPT_ATTR_HIGH_THROUGHPUT: 811 if (reason == LEJPCB_VAL_TRUE) 812 a->curr[LTY_POLICY].p->flags |= 813 LWSSSPOLF_ATTR_HIGH_THROUGHPUT; 814 return 0; 815 816 case LSSPPT_ATTR_HIGH_RELIABILITY: 817 if (reason == LEJPCB_VAL_TRUE) 818 a->curr[LTY_POLICY].p->flags |= 819 LWSSSPOLF_ATTR_HIGH_RELIABILITY; 820 return 0; 821 822 case LSSPPT_ATTR_LOW_COST: 823 if (reason == LEJPCB_VAL_TRUE) 824 a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_ATTR_LOW_COST; 825 return 0; 826 827 case LSSPPT_PERF: 828 if (reason == LEJPCB_VAL_TRUE) 829 a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_PERF; 830 return 0; 831 832 case LSSPPT_RETRYPTR: 833 bot = a->heads[LTY_BACKOFF].b; 834 while (bot) { 835 if (!strncmp(ctx->buf, bot->name, ctx->npos)) { 836 a->curr[LTY_POLICY].p->retry_bo = &bot->r; 837 838 return 0; 839 } 840 bot = bot->next; 841 } 842 lwsl_err("%s: unknown backoff scheme\n", __func__); 843 844 return -1; 845 846 case LSSPPT_TRUST: 847 ts = a->heads[LTY_TRUSTSTORE].t; 848 while (ts) { 849 if (!strncmp(ctx->buf, ts->name, ctx->npos)) { 850 a->curr[LTY_POLICY].p->trust.store = ts; 851 return 0; 852 } 853 ts = ts->next; 854 } 855 lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar)); 856 lwsl_err("%s: unknown trust store name %s\n", __func__, 857 dotstar); 858 859 return -1; 860 861 case LSSPPT_METADATA: 862 break; 863 864 case LSSPPT_USE_AUTH: 865 a->curr[LTY_POLICY].p->auth = 866 lws_ss_policy_find_auth_by_name(a, ctx->buf, ctx->npos); 867 if (!a->curr[LTY_POLICY].p->auth) { 868 lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar)); 869 lwsl_err("%s: unknown auth '%s'\n", __func__, dotstar); 870 return -1; 871 } 872 break; 873 874 875 case LSSPPT_METADATA_ITEM: 876 pmd = a->curr[LTY_POLICY].p->metadata; 877 a->curr[LTY_POLICY].p->metadata = lwsac_use_zero(&a->ac, 878 sizeof(lws_ss_metadata_t) + ctx->npos + 879 (unsigned int)(ctx->path_match_len - ctx->st[ctx->sp - 2].p + 1) + 2, 880 POL_AC_GRAIN); 881 a->curr[LTY_POLICY].p->metadata->next = pmd; 882 883 q = (char *)a->curr[LTY_POLICY].p->metadata + 884 sizeof(lws_ss_metadata_t); 885 a->curr[LTY_POLICY].p->metadata->name = q; 886 memcpy(q, ctx->path + ctx->st[ctx->sp - 2].p + 1, 887 (unsigned int)(ctx->path_match_len - ctx->st[ctx->sp - 2].p)); 888 889 q += ctx->path_match_len - ctx->st[ctx->sp - 2].p; 890 a->curr[LTY_POLICY].p->metadata->value__may_own_heap = q; 891 memcpy(q, ctx->buf, ctx->npos); 892 893#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) 894 /* 895 * Check the metadata value part to see if it's a well-known 896 * http header... if so, LWS_HTTP_NO_KNOWN_HEADER (0xff) means 897 * no header string match else it's the well-known header index 898 */ 899 a->curr[LTY_POLICY].p->metadata->value_is_http_token = (uint8_t) 900 lws_http_string_to_known_header(ctx->buf, ctx->npos); 901#endif 902 903 a->curr[LTY_POLICY].p->metadata->length = /* the index in handle->metadata */ 904 a->curr[LTY_POLICY].p->metadata_count++; 905 906 a->curr[LTY_POLICY].p->metadata->value_length = ctx->npos; 907 break; 908 909#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) 910 911 case LSSPPT_HTTPRESPMAP_ITEM: 912 if (a->count >= (int)LWS_ARRAY_SIZE(a->respmap)) { 913 lwsl_err("%s: respmap too big\n", __func__); 914 return -1; 915 } 916 a->respmap[a->count].resp = (uint16_t) 917 atoi(ctx->path + ctx->st[ctx->sp - 2].p + 1); 918 a->respmap[a->count].state = (uint16_t)atoi(ctx->buf); 919 a->pending_respmap = 1; 920 a->count++; 921 break; 922 923 case LSSPPT_HTTP_AUTH_HEADER: 924 case LSSPPT_HTTP_DSN_HEADER: 925 case LSSPPT_HTTP_FWV_HEADER: 926 case LSSPPT_HTTP_TYPE_HEADER: 927 pp = (char **)&a->curr[LTY_POLICY].p->u.http.blob_header[ 928 (ctx->path_match - 1) - LSSPPT_HTTP_AUTH_HEADER]; 929 goto string2; 930 931 case LSSPPT_HTTP_AUTH_PREAMBLE: 932 pp = (char **)&a->curr[LTY_POLICY].p->u.http.auth_preamble; 933 goto string2; 934 935 case LSSPPT_HTTP_NO_CONTENT_LENGTH: 936 if (reason == LEJPCB_VAL_TRUE) 937 a->curr[LTY_POLICY].p->flags |= 938 LWSSSPOLF_HTTP_NO_CONTENT_LENGTH; 939 break; 940 941 case LSSPPT_NGHTTP2_QUIRK_END_STREAM: 942 if (reason == LEJPCB_VAL_TRUE) 943 a->curr[LTY_POLICY].p->flags |= 944 LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM; 945 break; 946 case LSSPPT_H2_QUIRK_OVERFLOWS_TXCR: 947 if (reason == LEJPCB_VAL_TRUE) 948 a->curr[LTY_POLICY].p->flags |= 949 LWSSSPOLF_H2_QUIRK_OVERFLOWS_TXCR; 950 break; 951 case LSSPPT_HTTP_MULTIPART_NAME: 952 a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_MULTIPART; 953 pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_name; 954 goto string2; 955 case LSSPPT_HTTP_MULTIPART_FILENAME: 956 a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_MULTIPART; 957 pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_filename; 958 goto string2; 959 case LSSPPT_HTTP_MULTIPART_CONTENT_TYPE: 960 a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_MULTIPART; 961 pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_content_type; 962 goto string2; 963 964 case LSSPPT_AUTH_NAME: 965 pp = (char **)&a->curr[LTY_AUTH].a->name; 966 goto string2; 967 968 case LSSPPT_AUTH_STREAMTYPE: 969 pp = (char **)&a->curr[LTY_AUTH].a->streamtype; 970 goto string2; 971 case LSSPPT_AUTH_TYPE: 972 pp = (char **)&a->curr[LTY_AUTH].a->type; 973 goto string2; 974 case LSSPPT_HTTP_FAIL_REDIRECT: 975 a->curr[LTY_POLICY].p->u.http.fail_redirect = 976 reason == LEJPCB_VAL_TRUE; 977 break; 978#if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4) 979 case LSSPPT_AWS_REGION: 980 pp = (char **)&a->curr[LTY_POLICY].p->aws_region; 981 goto string2; 982 983 case LSSPPT_AWS_SERVICE: 984 pp = (char **)&a->curr[LTY_POLICY].p->aws_service; 985 goto string2; 986#endif 987 988#endif 989 990#if defined(LWS_ROLE_WS) 991 992 case LSSPPT_WS_SUBPROTOCOL: 993 pp = (char **)&a->curr[LTY_POLICY].p->u.http.u.ws.subprotocol; 994 goto string2; 995 996 case LSSPPT_WS_BINARY: 997 a->curr[LTY_POLICY].p->u.http.u.ws.binary = 998 reason == LEJPCB_VAL_TRUE; 999 break; 1000#endif 1001 1002 case LSSPPT_LOCAL_SINK: 1003 if (reason == LEJPCB_VAL_TRUE) 1004 a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_LOCAL_SINK; 1005 break; 1006 1007 case LSSPPT_SERVER: 1008 if (reason == LEJPCB_VAL_TRUE) 1009 a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_SERVER; 1010 break; 1011 1012#if defined(LWS_ROLE_MQTT) 1013 case LSSPPT_MQTT_TOPIC: 1014 pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.topic; 1015 goto string2; 1016 1017 case LSSPPT_MQTT_SUBSCRIBE: 1018 pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.subscribe; 1019 goto string2; 1020 1021 case LSSPPT_MQTT_QOS: 1022 a->curr[LTY_POLICY].p->u.mqtt.qos = (uint8_t)atoi(ctx->buf); 1023 break; 1024 1025 case LSSPPT_MQTT_RETAIN: 1026 a->curr[LTY_POLICY].p->u.mqtt.retain = 1027 reason == LEJPCB_VAL_TRUE; 1028 break; 1029 1030 case LSSPPT_MQTT_KEEPALIVE: 1031 a->curr[LTY_POLICY].p->u.mqtt.keep_alive = (uint16_t)atoi(ctx->buf); 1032 break; 1033 1034 case LSSPPT_MQTT_CLEAN_START: 1035 a->curr[LTY_POLICY].p->u.mqtt.clean_start = 1036 reason == LEJPCB_VAL_TRUE; 1037 break; 1038 case LSSPPT_MQTT_WILL_TOPIC: 1039 pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.will_topic; 1040 goto string2; 1041 1042 case LSSPPT_MQTT_WILL_MESSAGE: 1043 pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.will_message; 1044 goto string2; 1045 1046 case LSSPPT_MQTT_WILL_QOS: 1047 a->curr[LTY_POLICY].p->u.mqtt.will_qos = (uint8_t)atoi(ctx->buf); 1048 break; 1049 case LSSPPT_MQTT_WILL_RETAIN: 1050 a->curr[LTY_POLICY].p->u.mqtt.will_retain = 1051 reason == LEJPCB_VAL_TRUE; 1052 break; 1053 case LSSPPT_MQTT_BIRTH_TOPIC: 1054 pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.birth_topic; 1055 goto string2; 1056 1057 case LSSPPT_MQTT_BIRTH_MESSAGE: 1058 pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.birth_message; 1059 goto string2; 1060 1061 case LSSPPT_MQTT_BIRTH_QOS: 1062 a->curr[LTY_POLICY].p->u.mqtt.birth_qos = (uint8_t)atoi(ctx->buf); 1063 break; 1064 case LSSPPT_MQTT_BIRTH_RETAIN: 1065 a->curr[LTY_POLICY].p->u.mqtt.birth_retain = 1066 reason == LEJPCB_VAL_TRUE; 1067 break; 1068 case LSSPPT_MQTT_AWS_IOT: 1069 if (reason == LEJPCB_VAL_TRUE) 1070 a->curr[LTY_POLICY].p->u.mqtt.aws_iot = 1071 reason == LEJPCB_VAL_TRUE; 1072 break; 1073#endif 1074 case LSSPPT_DIRECT_PROTO_STR: 1075 if (reason == LEJPCB_VAL_TRUE) 1076 a->curr[LTY_POLICY].p->flags |= 1077 LWSSSPOLF_DIRECT_PROTO_STR; 1078 break; 1079 1080 1081 case LSSPPT_PROTOCOL: 1082 a->curr[LTY_POLICY].p->protocol = 0xff; 1083 for (n = 0; n < (int)LWS_ARRAY_SIZE(protonames); n++) 1084 if (strlen(protonames[n]) == ctx->npos && 1085 !strncmp(ctx->buf, protonames[n], ctx->npos)) 1086 a->curr[LTY_POLICY].p->protocol = (uint8_t)n; 1087 1088 if (a->curr[LTY_POLICY].p->protocol != 0xff) 1089 break; 1090 lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar)); 1091 lwsl_err("%s: unknown protocol name %s\n", __func__, dotstar); 1092 return -1; 1093 1094 default: 1095 break; 1096 } 1097 1098 return 0; 1099 1100string2: 1101 /* 1102 * If we can do const string folding, reuse the existing string rather 1103 * than make a new entry 1104 */ 1105 extant = lwsac_scan_extant(a->ac, (uint8_t *)ctx->buf, (size_t)ctx->npos, 1); 1106 if (extant) { 1107 *pp = (char *)extant; 1108 1109 return 0; 1110 } 1111 *pp = lwsac_use_backfill(&a->ac, (size_t)(ctx->npos + 1), POL_AC_GRAIN); 1112 if (!*pp) 1113 goto oom; 1114 memcpy(*pp, ctx->buf, ctx->npos); 1115 (*pp)[ctx->npos] = '\0'; 1116 1117 return 0; 1118 1119string1: 1120 n = ctx->st[ctx->sp].p; 1121 *pp = lwsac_use_backfill(&a->ac, (size_t)ctx->path_match_len + (size_t)1 - (size_t)n, 1122 POL_AC_GRAIN); 1123 if (!*pp) 1124 goto oom; 1125 memcpy(*pp, ctx->path + n, ctx->path_match_len - (unsigned int)n); 1126 (*pp)[ctx->path_match_len - n] = '\0'; 1127 1128 return 0; 1129 1130oom: 1131 lwsl_err("%s: OOM\n", __func__); 1132 lws_free_set_NULL(a->p); 1133 lwsac_free(&a->ac); 1134 1135 return -1; 1136} 1137 1138int 1139lws_ss_policy_parse_begin(struct lws_context *context, int overlay) 1140{ 1141 struct policy_cb_args *args; 1142 char *p; 1143 1144 args = lws_zalloc(sizeof(struct policy_cb_args), __func__); 1145 if (!args) { 1146 lwsl_err("%s: OOM\n", __func__); 1147 1148 return 1; 1149 } 1150 if (overlay) 1151 /* continue to use the existing lwsac */ 1152 args->ac = context->ac_policy; 1153 else 1154 /* we don't want to see any old policy */ 1155 context->pss_policies = NULL; 1156 1157 context->pol_args = args; 1158 args->context = context; 1159 p = lwsac_use(&args->ac, 1, POL_AC_INITIAL); 1160 if (!p) { 1161 lwsl_err("%s: OOM\n", __func__); 1162 lws_free_set_NULL(context->pol_args); 1163 1164 return -1; 1165 } 1166 *p = 0; 1167 lejp_construct(&args->jctx, lws_ss_policy_parser_cb, args, 1168 lejp_tokens_policy, LWS_ARRAY_SIZE(lejp_tokens_policy)); 1169 1170 return 0; 1171} 1172 1173int 1174lws_ss_policy_parse_abandon(struct lws_context *context) 1175{ 1176 struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; 1177 lws_ss_x509_t *x; 1178 1179 x = args->heads[LTY_X509].x; 1180 while (x) { 1181 /* 1182 * Free all the client DER buffers now they have been parsed 1183 * into tls library X.509 objects 1184 */ 1185 lws_free((void *)x->ca_der); 1186 x->ca_der = NULL; 1187 1188 x = x->next; 1189 } 1190 1191 x = context->server_der_list; 1192 while (x) { 1193 lws_free((void *)x->ca_der); 1194 x->ca_der = NULL; 1195 1196 x = x->next; 1197 } 1198 1199 lejp_destruct(&args->jctx); 1200 lwsac_free(&args->ac); 1201 lws_free_set_NULL(context->pol_args); 1202 1203 context->server_der_list = NULL; 1204 1205 return 0; 1206} 1207 1208#if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) 1209int 1210lws_ss_policy_parse_file(struct lws_context *cx, const char *filepath) 1211{ 1212 struct policy_cb_args *args = (struct policy_cb_args *)cx->pol_args; 1213 uint8_t buf[512]; 1214 int n, m, fd = lws_open(filepath, LWS_O_RDONLY); 1215 1216 if (fd < 0) 1217 return LEJP_REJECT_UNKNOWN; 1218 1219 do { 1220 n = (int)read(fd, buf, sizeof(buf)); 1221 if (n < 0) { 1222 m = -1; 1223 goto bail; 1224 } 1225 1226 m = lejp_parse(&args->jctx, buf, n); 1227 if (m != LEJP_CONTINUE && m < 0) { 1228 lwsl_err("%s: parse failed line %u: %d: %s\n", __func__, 1229 (unsigned int)args->jctx.line, m, 1230 lejp_error_to_string(m)); 1231 lws_ss_policy_parse_abandon(cx); 1232 1233 m = -1; 1234 goto bail; 1235 } 1236 1237 if (m != LEJP_CONTINUE) 1238 break; 1239 } while (n); 1240 1241 m = 0; 1242bail: 1243 close(fd); 1244 1245 return m; 1246} 1247#endif 1248 1249int 1250lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len) 1251{ 1252 struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; 1253 int m; 1254 1255#if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) 1256 if (args->jctx.line < 2 && buf[0] != '{' && !args->parse_data) 1257 return lws_ss_policy_parse_file(context, (const char *)buf); 1258#endif 1259 1260 args->parse_data = 1; 1261 m = lejp_parse(&args->jctx, buf, (int)len); 1262 if (m == LEJP_CONTINUE || m >= 0) 1263 return m; 1264 1265 lwsl_err("%s: parse failed line %u: %d: %s\n", __func__, 1266 (unsigned int)args->jctx.line, m, lejp_error_to_string(m)); 1267 lws_ss_policy_parse_abandon(context); 1268 assert(0); 1269 1270 return m; 1271} 1272 1273int 1274lws_ss_policy_overlay(struct lws_context *context, const char *overlay) 1275{ 1276 lws_ss_policy_parse_begin(context, 1); 1277 return lws_ss_policy_parse(context, (const uint8_t *)overlay, 1278 strlen(overlay)); 1279} 1280 1281const lws_ss_policy_t * 1282lws_ss_policy_get(struct lws_context *context) 1283{ 1284 struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; 1285 1286 if (!args) 1287 return NULL; 1288 1289 return args->heads[LTY_POLICY].p; 1290} 1291 1292const lws_ss_auth_t * 1293lws_ss_auth_get(struct lws_context *context) 1294{ 1295 struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; 1296 1297 if (!args) 1298 return NULL; 1299 1300 return args->heads[LTY_AUTH].a; 1301} 1302