Coverage Report

Created: 2026-08-15 07:08

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