Coverage Report

Created: 2025-07-11 06:34

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