/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 | } |