• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2019 - 2020 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 
25 #include <private-lib-core.h>
26 
27 typedef struct backoffs {
28 	struct backoffs *next;
29 	const char *name;
30 	lws_retry_bo_t r;
31 } backoff_t;
32 
33 static const char * const lejp_tokens_policy[] = {
34 	"release",
35 	"product",
36 	"schema-version",
37 	"via-socks5",
38 	"retry[].*.backoff",
39 	"retry[].*.conceal",
40 	"retry[].*.jitterpc",
41 	"retry[].*.svalidping",
42 	"retry[].*.svalidhup",
43 	"retry[].*",
44 	"certs[].*",
45 	"trust_stores[].name",
46 	"trust_stores[].stack",
47 	"s[].*.endpoint",
48 	"s[].*.via-socks5",
49 	"s[].*.protocol",
50 	"s[].*.port",
51 	"s[].*.plugins",
52 	"s[].*.tls",
53 	"s[].*.client_cert",
54 	"s[].*.opportunistic",
55 	"s[].*.nailed_up",
56 	"s[].*.urgent_tx",
57 	"s[].*.urgent_rx",
58 	"s[].*.long_poll",
59 	"s[].*.retry",
60 	"s[].*.tls_trust_store",
61 	"s[].*.metadata",
62 	"s[].*.metadata[].*",
63 
64 	"s[].*.http_auth_header",
65 	"s[].*.http_dsn_header",
66 	"s[].*.http_fwv_header",
67 	"s[].*.http_devtype_header",
68 
69 	"s[].*.http_auth_preamble",
70 
71 	"s[].*.http_no_content_length",
72 	"s[].*.rideshare",	/* streamtype name this rides shotgun with */
73 	"s[].*.payload_fmt",
74 	"s[].*.http_method",
75 	"s[].*.http_url",
76 	"s[].*.nghttp2_quirk_end_stream",
77 	"s[].*.h2q_oflow_txcr",
78 	"s[].*.http_multipart_name",
79 	"s[].*.http_multipart_filename",
80 	"s[].*.http_mime_content_type",
81 	"s[].*.http_www_form_urlencoded",
82 	"s[].*.ws_subprotocol",
83 	"s[].*.ws_binary",
84 	"s[].*.local_sink",
85 	"s[].*.mqtt_topic",
86 	"s[].*.mqtt_subscribe",
87 	"s[].*.mqtt_qos",
88 	"s[].*.mqtt_keep_alive",
89 	"s[].*.mqtt_clean_start",
90 	"s[].*.mqtt_will_topic",
91 	"s[].*.mqtt_will_message",
92 	"s[].*.mqtt_will_qos",
93 	"s[].*.mqtt_will_retain",
94 	"s[].*",
95 };
96 
97 typedef enum {
98 	LSSPPT_RELEASE,
99 	LSSPPT_PRODUCT,
100 	LSSPPT_SCHEMA_VERSION,
101 	LSSPPT_VIA_SOCKS5,
102 	LSSPPT_BACKOFF,
103 	LSSPPT_CONCEAL,
104 	LSSPPT_JITTERPC,
105 	LSSPPT_VALIDPING_S,
106 	LSSPPT_VALIDHUP_S,
107 	LSSPPT_RETRY,
108 	LSSPPT_CERTS,
109 	LSSPPT_TRUST_STORES_NAME,
110 	LSSPPT_TRUST_STORES_STACK,
111 	LSSPPT_ENDPOINT,
112 	LSSPPT_VH_VIA_SOCKS5,
113 	LSSPPT_PROTOCOL,
114 	LSSPPT_PORT,
115 	LSSPPT_PLUGINS,
116 	LSSPPT_TLS,
117 	LSSPPT_TLS_CLIENT_CERT,
118 	LSSPPT_OPPORTUNISTIC,
119 	LSSPPT_NAILED_UP,
120 	LSSPPT_URGENT_TX,
121 	LSSPPT_URGENT_RX,
122 	LSSPPT_LONG_POLL,
123 	LSSPPT_RETRYPTR,
124 	LSSPPT_TRUST,
125 	LSSPPT_METADATA,
126 	LSSPPT_METADATA_ITEM,
127 
128 	LSSPPT_HTTP_AUTH_HEADER,
129 	LSSPPT_HTTP_DSN_HEADER,
130 	LSSPPT_HTTP_FWV_HEADER,
131 	LSSPPT_HTTP_TYPE_HEADER,
132 
133 	LSSPPT_HTTP_AUTH_PREAMBLE,
134 	LSSPPT_HTTP_NO_CONTENT_LENGTH,
135 	LSSPPT_RIDESHARE,
136 	LSSPPT_PAYLOAD_FORMAT,
137 	LSSPPT_HTTP_METHOD,
138 	LSSPPT_HTTP_URL,
139 	LSSPPT_NGHTTP2_QUIRK_END_STREAM,
140 	LSSPPT_H2_QUIRK_OVERFLOWS_TXCR,
141 	LSSPPT_HTTP_MULTIPART_NAME,
142 	LSSPPT_HTTP_MULTIPART_FILENAME,
143 	LSSPPT_HTTP_MULTIPART_CONTENT_TYPE,
144 	LSSPPT_HTTP_WWW_FORM_URLENCODED,
145 	LSSPPT_WS_SUBPROTOCOL,
146 	LSSPPT_WS_BINARY,
147 	LSSPPT_LOCAL_SINK,
148 	LSSPPT_MQTT_TOPIC,
149 	LSSPPT_MQTT_SUBSCRIBE,
150 	LSSPPT_MQTT_QOS,
151 	LSSPPT_MQTT_KEEPALIVE,
152 	LSSPPT_MQTT_CLEAN_START,
153 	LSSPPT_MQTT_WILL_TOPIC,
154 	LSSPPT_MQTT_WILL_MESSAGE,
155 	LSSPPT_MQTT_WILL_QOS,
156 	LSSPPT_MQTT_WILL_RETAIN,
157 	LSSPPT_STREAMTYPES
158 } policy_token_t;
159 
160 union u {
161 	backoff_t *b;
162 	lws_ss_x509_t *x;
163 	lws_ss_trust_store_t *t;
164 	lws_ss_policy_t *p;
165 };
166 
167 enum {
168 	LTY_BACKOFF,
169 	LTY_X509,
170 	LTY_TRUSTSTORE,
171 	LTY_POLICY,
172 
173 	_LTY_COUNT /* always last */
174 };
175 
176 struct policy_cb_args {
177 	struct lejp_ctx jctx;
178 	struct lws_context *context;
179 	struct lwsac *ac;
180 
181 	const char *socks5_proxy;
182 
183 	struct lws_b64state b64;
184 
185 	union u heads[_LTY_COUNT];
186 	union u curr[_LTY_COUNT];
187 
188 	uint8_t *p;
189 
190 	int count;
191 };
192 
193 #define POL_AC_INITIAL	2048
194 #define POL_AC_GRAIN	800
195 #define MAX_CERT_TEMP	2048 /* used to discover actual cert size for realloc */
196 
197 static uint8_t sizes[] = {
198 	sizeof(backoff_t),
199 	sizeof(lws_ss_x509_t),
200 	sizeof(lws_ss_trust_store_t),
201 	sizeof(lws_ss_policy_t),
202 };
203 
204 static const char *protonames[] = {
205 	"h1",		/* LWSSSP_H1 */
206 	"h2",		/* LWSSSP_H2 */
207 	"ws",		/* LWSSSP_WS */
208 	"mqtt",		/* LWSSSP_MQTT */
209 };
210 
211 lws_ss_metadata_t *
lws_ss_policy_metadata(const lws_ss_policy_t * p,const char * name)212 lws_ss_policy_metadata(const lws_ss_policy_t *p, const char *name)
213 {
214 	lws_ss_metadata_t *pmd = p->metadata;
215 
216 	while (pmd) {
217 		if (pmd->name && !strcmp(name, pmd->name))
218 			return pmd;
219 		pmd = pmd->next;
220 	}
221 
222 	return NULL;
223 }
224 
225 lws_ss_metadata_t *
lws_ss_policy_metadata_index(const lws_ss_policy_t * p,size_t index)226 lws_ss_policy_metadata_index(const lws_ss_policy_t *p, size_t index)
227 {
228 	lws_ss_metadata_t *pmd = p->metadata;
229 
230 	while (pmd) {
231 		if (pmd->length == index)
232 			return pmd;
233 		pmd = pmd->next;
234 	}
235 
236 	return NULL;
237 }
238 
239 int
lws_ss_set_metadata(struct lws_ss_handle * h,const char * name,void * value,size_t len)240 lws_ss_set_metadata(struct lws_ss_handle *h, const char *name,
241 		    void *value, size_t len)
242 {
243 	lws_ss_metadata_t *omd = lws_ss_policy_metadata(h->policy, name);
244 
245 	if (!omd) {
246 		lwsl_err("%s: unknown metadata %s\n", __func__, name);
247 		return 1;
248 	}
249 
250 	h->metadata[omd->length].name = name;
251 	h->metadata[omd->length].value = value;
252 	h->metadata[omd->length].length = len;
253 
254 	return 0;
255 }
256 
257 lws_ss_metadata_t *
lws_ss_get_handle_metadata(struct lws_ss_handle * h,const char * name)258 lws_ss_get_handle_metadata(struct lws_ss_handle *h, const char *name)
259 {
260 	lws_ss_metadata_t *omd = lws_ss_policy_metadata(h->policy, name);
261 
262 	if (!omd)
263 		return NULL;
264 
265 	return &h->metadata[omd->length];
266 }
267 
268 static signed char
lws_ss_policy_parser_cb(struct lejp_ctx * ctx,char reason)269 lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason)
270 {
271 	struct policy_cb_args *a = (struct policy_cb_args *)ctx->user;
272 	const lws_ss_plugin_t **pin;
273 	char **pp, dotstar[32], *q;
274 	lws_ss_trust_store_t *ts;
275 	lws_ss_metadata_t *pmd;
276 	lws_retry_bo_t *b;
277 	size_t inl, outl;
278 	lws_ss_x509_t *x;
279 	uint8_t *extant;
280 	backoff_t *bot;
281 	int n = -1;
282 
283 	lwsl_debug("%s: %d %d %s\n", __func__, reason, ctx->path_match - 1,
284 		   ctx->path);
285 
286 	switch (ctx->path_match - 1) {
287 	case LSSPPT_RETRY:
288 		n = LTY_BACKOFF;
289 		break;
290 	case LSSPPT_CERTS:
291 		n = LTY_X509;
292 		break;
293 	case LSSPPT_TRUST_STORES_NAME:
294 	case LSSPPT_TRUST_STORES_STACK:
295 		n = LTY_TRUSTSTORE;
296 		break;
297 	case LSSPPT_STREAMTYPES:
298 		n = LTY_POLICY;
299 		break;
300 	}
301 
302 	if (reason == LEJPCB_ARRAY_START &&
303 	    (ctx->path_match - 1 == LSSPPT_PLUGINS ||
304 	     ctx->path_match - 1 == LSSPPT_METADATA))
305 		a->count = 0;
306 
307 	if (reason == LEJPCB_ARRAY_END &&
308 	    ctx->path_match - 1 == LSSPPT_TRUST_STORES_STACK && !a->count) {
309 		lwsl_err("%s: at least one cert required in trust store\n",
310 				__func__);
311 		goto oom;
312 	}
313 
314 	if (reason == LEJPCB_OBJECT_END && a->p) {
315 		/*
316 		 * Allocate a just-the-right-size buf for the cert DER now
317 		 * we decoded it into the a->p temp buffer and know the exact
318 		 * size
319 		 */
320 		a->curr[LTY_X509].x->ca_der = lws_malloc(a->count, "ssx509");
321 		if (!a->curr[LTY_X509].x->ca_der)
322 			goto oom;
323 		memcpy((uint8_t *)a->curr[LTY_X509].x->ca_der, a->p, a->count);
324 		a->curr[LTY_X509].x->ca_der_len = a->count;
325 
326 		/*
327 		 * ... and then we can free the temp buffer
328 		 */
329 		lws_free_set_NULL(a->p);
330 
331 		return 0;
332 	}
333 
334 	if (reason == LEJPCB_PAIR_NAME && n != -1 && n != LTY_TRUSTSTORE) {
335 		/*
336 		 * We do the pointers always as .b, all of the participating
337 		 * structs begin with .next and .name
338 		 */
339 		a->curr[n].b = lwsac_use_zero(&a->ac, sizes[n], POL_AC_GRAIN);
340 		if (!a->curr[n].b)
341 			goto oom;
342 
343 		if (n == LTY_X509) {
344 			a->p = lws_malloc(MAX_CERT_TEMP, "cert temp");
345 			if (!a->p)
346 				goto oom;
347 			memset(&a->b64, 0, sizeof(a->b64));
348 		}
349 
350 		a->count = 0;
351 		a->curr[n].b->next = a->heads[n].b;
352 		a->heads[n].b = a->curr[n].b;
353 		pp = (char **)&a->curr[n].b->name;
354 
355 		goto string1;
356 	}
357 
358 	if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match)
359 		return 0;
360 
361 	switch (ctx->path_match - 1) {
362 
363 	/* strings */
364 
365 	case LSSPPT_RELEASE:
366 		break;
367 
368 	case LSSPPT_PRODUCT:
369 		break;
370 
371 	case LSSPPT_SCHEMA_VERSION:
372 		break;
373 
374 	case LSSPPT_VIA_SOCKS5:
375 		/* the global / default proxy */
376 		pp = (char **)&a->socks5_proxy;
377 		goto string2;
378 
379 	case LSSPPT_BACKOFF:
380 		b = &a->curr[LTY_BACKOFF].b->r;
381 		if (b->retry_ms_table_count == 8) {
382 			lwsl_err("%s: > 8 backoff levels\n", __func__);
383 			return 1;
384 		}
385 		if (!b->retry_ms_table_count) {
386 			b->retry_ms_table = (uint32_t *)lwsac_use_zero(&a->ac,
387 					   sizeof(uint32_t) * 8, POL_AC_GRAIN);
388 			if (!b->retry_ms_table)
389 				goto oom;
390 		}
391 
392 		((uint32_t *)b->retry_ms_table)
393 				[b->retry_ms_table_count++] = atoi(ctx->buf);
394 		break;
395 
396 	case LSSPPT_CONCEAL:
397 		a->curr[LTY_BACKOFF].b->r.conceal_count = atoi(ctx->buf);
398 		break;
399 
400 	case LSSPPT_JITTERPC:
401 		a->curr[LTY_BACKOFF].b->r.jitter_percent = atoi(ctx->buf);
402 		break;
403 
404 	case LSSPPT_VALIDPING_S:
405 		a->curr[LTY_BACKOFF].b->r.secs_since_valid_ping = atoi(ctx->buf);
406 		break;
407 
408 	case LSSPPT_VALIDHUP_S:
409 		a->curr[LTY_BACKOFF].b->r.secs_since_valid_hangup = atoi(ctx->buf);
410 		break;
411 
412 	case LSSPPT_CERTS:
413 		if (a->count + ctx->npos >= MAX_CERT_TEMP) {
414 			lwsl_err("%s: cert too big\n", __func__);
415 			goto oom;
416 		}
417 		inl = ctx->npos;
418 		outl = MAX_CERT_TEMP - a->count;
419 
420 		lws_b64_decode_stateful(&a->b64, ctx->buf, &inl,
421 					a->p + a->count, &outl,
422 					reason == LEJPCB_VAL_STR_END);
423 		a->count += outl;
424 		if (inl != ctx->npos) {
425 			lwsl_err("%s: b64 decode fail\n", __func__);
426 			goto oom;
427 		}
428 		break;
429 
430 	case LSSPPT_TRUST_STORES_NAME:
431 		/*
432 		 * We do the pointers always as .b, all of the participating
433 		 * structs begin with .next and .name
434 		 */
435 		a->curr[LTY_TRUSTSTORE].b = lwsac_use_zero(&a->ac,
436 					sizes[LTY_TRUSTSTORE], POL_AC_GRAIN);
437 		if (!a->curr[LTY_TRUSTSTORE].b)
438 			goto oom;
439 
440 		a->count = 0;
441 		a->curr[LTY_TRUSTSTORE].b->next = a->heads[LTY_TRUSTSTORE].b;
442 		a->heads[LTY_TRUSTSTORE].b = a->curr[LTY_TRUSTSTORE].b;
443 		pp = (char **)&a->curr[LTY_TRUSTSTORE].b->name;
444 
445 		goto string2;
446 
447 	case LSSPPT_TRUST_STORES_STACK:
448 		if (a->count >= (int)LWS_ARRAY_SIZE(
449 					a->curr[LTY_TRUSTSTORE].t->ssx509)) {
450 			lwsl_err("%s: trust store too big\n", __func__);
451 			goto oom;
452 		}
453 		lwsl_debug("%s: trust stores stack %.*s\n", __func__,
454 			   ctx->npos, ctx->buf);
455 		x = a->heads[LTY_X509].x;
456 		while (x) {
457 			if (!strncmp(x->vhost_name, ctx->buf, ctx->npos)) {
458 				a->curr[LTY_TRUSTSTORE].t->ssx509[a->count++] = x;
459 				a->curr[LTY_TRUSTSTORE].t->count++;
460 
461 				return 0;
462 			}
463 			x = x->next;
464 		}
465 		lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar));
466 		lwsl_err("%s: unknown trust store entry %s\n", __func__,
467 			 dotstar);
468 		goto oom;
469 
470 	case LSSPPT_ENDPOINT:
471 		pp = (char **)&a->curr[LTY_POLICY].p->endpoint;
472 		goto string2;
473 
474 	case LSSPPT_VH_VIA_SOCKS5:
475 		pp = (char **)&a->curr[LTY_POLICY].p->socks5_proxy;
476 		goto string2;
477 
478 	case LSSPPT_PORT:
479 		a->curr[LTY_POLICY].p->port = atoi(ctx->buf);
480 		break;
481 
482 	case LSSPPT_HTTP_METHOD:
483 		pp = (char **)&a->curr[LTY_POLICY].p->u.http.method;
484 		goto string2;
485 
486 	case LSSPPT_HTTP_URL:
487 		pp = (char **)&a->curr[LTY_POLICY].p->u.http.url;
488 		goto string2;
489 
490 	case LSSPPT_RIDESHARE:
491 		pp = (char **)&a->curr[LTY_POLICY].p->rideshare_streamtype;
492 		goto string2;
493 
494 	case LSSPPT_PAYLOAD_FORMAT:
495 		pp = (char **)&a->curr[LTY_POLICY].p->payload_fmt;
496 		goto string2;
497 
498 	case LSSPPT_PLUGINS:
499 		pin = a->context->pss_plugins;
500 		if (a->count ==
501 			  (int)LWS_ARRAY_SIZE(a->curr[LTY_POLICY].p->plugins)) {
502 			lwsl_err("%s: too many plugins\n", __func__);
503 
504 			goto oom;
505 		}
506 		if (!pin)
507 			break;
508 		while (*pin) {
509 			if (!strncmp((*pin)->name, ctx->buf, ctx->npos)) {
510 				a->curr[LTY_POLICY].p->plugins[a->count++] = *pin;
511 				return 0;
512 			}
513 			pin++;
514 		}
515 		lwsl_err("%s: unknown plugin\n", __func__);
516 		goto oom;
517 
518 	case LSSPPT_TLS:
519 		if (reason == LEJPCB_VAL_TRUE)
520 			a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_TLS;
521 		break;
522 
523 	case LSSPPT_TLS_CLIENT_CERT:
524 		a->curr[LTY_POLICY].p->client_cert = atoi(ctx->buf) + 1;
525 		break;
526 
527 	case LSSPPT_OPPORTUNISTIC:
528 		if (reason == LEJPCB_VAL_TRUE)
529 			a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_OPPORTUNISTIC;
530 		break;
531 	case LSSPPT_NAILED_UP:
532 		if (reason == LEJPCB_VAL_TRUE)
533 			a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_NAILED_UP;
534 		break;
535 	case LSSPPT_URGENT_TX:
536 		if (reason == LEJPCB_VAL_TRUE)
537 			a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_URGENT_TX;
538 		break;
539 	case LSSPPT_URGENT_RX:
540 		if (reason == LEJPCB_VAL_TRUE)
541 			a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_URGENT_RX;
542 		break;
543 	case LSSPPT_LONG_POLL:
544 		if (reason == LEJPCB_VAL_TRUE)
545 			a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_LONG_POLL;
546 		break;
547 	case LSSPPT_HTTP_WWW_FORM_URLENCODED:
548 		if (reason == LEJPCB_VAL_TRUE)
549 			a->curr[LTY_POLICY].p->flags |=
550 					LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED;
551 		break;
552 
553 	case LSSPPT_RETRYPTR:
554 		bot = a->heads[LTY_BACKOFF].b;
555 		while (bot) {
556 			if (!strncmp(ctx->buf, bot->name, ctx->npos)) {
557 				a->curr[LTY_POLICY].p->retry_bo = &bot->r;
558 
559 				return 0;
560 			}
561 			bot = bot->next;
562 		}
563 		lwsl_err("%s: unknown backoff scheme\n", __func__);
564 
565 		return -1;
566 
567 	case LSSPPT_TRUST:
568 		ts = a->heads[LTY_TRUSTSTORE].t;
569 		while (ts) {
570 			if (!strncmp(ctx->buf, ts->name, ctx->npos)) {
571 				a->curr[LTY_POLICY].p->trust_store = ts;
572 				return 0;
573 			}
574 			ts = ts->next;
575 		}
576 		lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar));
577 		lwsl_err("%s: unknown trust store name %s\n", __func__,
578 			 dotstar);
579 
580 		return -1;
581 
582 	case LSSPPT_METADATA:
583 		break;
584 
585 	case LSSPPT_METADATA_ITEM:
586 		pmd = a->curr[LTY_POLICY].p->metadata;
587 		a->curr[LTY_POLICY].p->metadata = lwsac_use_zero(&a->ac,
588 			sizeof(lws_ss_metadata_t) + ctx->npos +
589 			(ctx->path_match_len - ctx->st[ctx->sp - 2].p + 1) + 2,
590 			POL_AC_GRAIN);
591 		a->curr[LTY_POLICY].p->metadata->next = pmd;
592 
593 		q = (char *)a->curr[LTY_POLICY].p->metadata +
594 				sizeof(lws_ss_metadata_t);
595 		a->curr[LTY_POLICY].p->metadata->name = q;
596 		memcpy(q, ctx->path + ctx->st[ctx->sp - 2].p + 1,
597 		       ctx->path_match_len - ctx->st[ctx->sp - 2].p);
598 
599 		q += ctx->path_match_len - ctx->st[ctx->sp - 2].p;
600 		a->curr[LTY_POLICY].p->metadata->value = q;
601 		memcpy(q, ctx->buf, ctx->npos);
602 
603 		a->curr[LTY_POLICY].p->metadata->length = /* the index in handle->metadata */
604 				a->curr[LTY_POLICY].p->metadata_count++;
605 		break;
606 
607 	case LSSPPT_HTTP_AUTH_HEADER:
608 	case LSSPPT_HTTP_DSN_HEADER:
609 	case LSSPPT_HTTP_FWV_HEADER:
610 	case LSSPPT_HTTP_TYPE_HEADER:
611 		pp = (char **)&a->curr[LTY_POLICY].p->u.http.blob_header[
612 		               (ctx->path_match - 1) - LSSPPT_HTTP_AUTH_HEADER];
613 		goto string2;
614 
615 	case LSSPPT_HTTP_AUTH_PREAMBLE:
616 		pp = (char **)&a->curr[LTY_POLICY].p->u.http.auth_preamble;
617 		goto string2;
618 
619 	case LSSPPT_HTTP_NO_CONTENT_LENGTH:
620 		if (reason == LEJPCB_VAL_TRUE)
621 			a->curr[LTY_POLICY].p->flags |=
622 					LWSSSPOLF_HTTP_NO_CONTENT_LENGTH;
623 		break;
624 
625 	case LSSPPT_NGHTTP2_QUIRK_END_STREAM:
626 		if (reason == LEJPCB_VAL_TRUE)
627 			a->curr[LTY_POLICY].p->flags |=
628 					LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM;
629 		break;
630 	case LSSPPT_H2_QUIRK_OVERFLOWS_TXCR:
631 		if (reason == LEJPCB_VAL_TRUE)
632 			a->curr[LTY_POLICY].p->flags |=
633 					LWSSSPOLF_H2_QUIRK_OVERFLOWS_TXCR;
634 		break;
635 	case LSSPPT_HTTP_MULTIPART_NAME:
636 		a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_MULTIPART;
637 		pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_name;
638 		goto string2;
639 	case LSSPPT_HTTP_MULTIPART_FILENAME:
640 		a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_MULTIPART;
641 		pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_filename;
642 		goto string2;
643 	case LSSPPT_HTTP_MULTIPART_CONTENT_TYPE:
644 		a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_MULTIPART;
645 		pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_content_type;
646 		goto string2;
647 	case LSSPPT_WS_SUBPROTOCOL:
648 		pp = (char **)&a->curr[LTY_POLICY].p->u.http.u.ws.subprotocol;
649 		goto string2;
650 
651 	case LSSPPT_WS_BINARY:
652 		a->curr[LTY_POLICY].p->u.http.u.ws.binary =
653 						reason == LEJPCB_VAL_TRUE;
654 		break;
655 	case LSSPPT_LOCAL_SINK:
656 		if (reason == LEJPCB_VAL_TRUE)
657 			a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_LOCAL_SINK;
658 		break;
659 
660 	case LSSPPT_MQTT_TOPIC:
661 		pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.topic;
662 		goto string2;
663 
664 	case LSSPPT_MQTT_SUBSCRIBE:
665 		pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.subscribe;
666 		goto string2;
667 
668 	case LSSPPT_MQTT_QOS:
669 		a->curr[LTY_POLICY].p->u.mqtt.qos = atoi(ctx->buf);
670 		break;
671 
672 	case LSSPPT_MQTT_KEEPALIVE:
673 		a->curr[LTY_POLICY].p->u.mqtt.keep_alive = atoi(ctx->buf);
674 		break;
675 
676 	case LSSPPT_MQTT_CLEAN_START:
677 		a->curr[LTY_POLICY].p->u.mqtt.clean_start =
678 						reason == LEJPCB_VAL_TRUE;
679 		break;
680 	case LSSPPT_MQTT_WILL_TOPIC:
681 		pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.will_topic;
682 		goto string2;
683 
684 	case LSSPPT_MQTT_WILL_MESSAGE:
685 		pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.will_message;
686 		goto string2;
687 
688 	case LSSPPT_MQTT_WILL_QOS:
689 		a->curr[LTY_POLICY].p->u.mqtt.will_qos = atoi(ctx->buf);
690 		break;
691 	case LSSPPT_MQTT_WILL_RETAIN:
692 		a->curr[LTY_POLICY].p->u.mqtt.will_retain =
693 						reason == LEJPCB_VAL_TRUE;
694 		break;
695 
696 	case LSSPPT_PROTOCOL:
697 		a->curr[LTY_POLICY].p->protocol = 0xff;
698 		for (n = 0; n < (int)LWS_ARRAY_SIZE(protonames); n++)
699 			if (strlen(protonames[n]) == ctx->npos &&
700 			    !strncmp(ctx->buf, protonames[n], ctx->npos))
701 				a->curr[LTY_POLICY].p->protocol = (uint8_t)n;
702 
703 		if (a->curr[LTY_POLICY].p->protocol != 0xff)
704 			break;
705 		lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar));
706 		lwsl_err("%s: unknown protocol name %s\n", __func__, dotstar);
707 		return -1;
708 	}
709 
710 	return 0;
711 
712 string2:
713 	/*
714 	 * If we can do const string folding, reuse the existing string rather
715 	 * than make a new entry
716 	 */
717 	extant = lwsac_scan_extant(a->ac, (uint8_t *)ctx->buf, ctx->npos, 1);
718 	if (extant) {
719 		*pp = (char *)extant;
720 
721 		return 0;
722 	}
723 	*pp = lwsac_use_backfill(&a->ac, ctx->npos + 1, POL_AC_GRAIN);
724 	if (!*pp)
725 		goto oom;
726 	memcpy(*pp, ctx->buf, ctx->npos);
727 	(*pp)[ctx->npos] = '\0';
728 
729 	return 0;
730 
731 string1:
732 	n = ctx->st[ctx->sp].p;
733 	*pp = lwsac_use_backfill(&a->ac, ctx->path_match_len + 1 - n,
734 				 POL_AC_GRAIN);
735 	if (!*pp)
736 		goto oom;
737 	memcpy(*pp, ctx->path + n, ctx->path_match_len - n);
738 	(*pp)[ctx->path_match_len - n] = '\0';
739 
740 	return 0;
741 
742 oom:
743 	lwsl_err("%s: OOM\n", __func__);
744 	lws_free_set_NULL(a->p);
745 	lwsac_free(&a->ac);
746 
747 	return -1;
748 }
749 
750 int
lws_ss_policy_parse_begin(struct lws_context * context)751 lws_ss_policy_parse_begin(struct lws_context *context)
752 {
753 	struct policy_cb_args *args;
754 	char *p;
755 
756 	args = lws_zalloc(sizeof(struct policy_cb_args), __func__);
757 	if (!args) {
758 		lwsl_err("%s: OOM\n", __func__);
759 
760 		return 1;
761 	}
762 
763 	context->pol_args = args;
764 	args->context = context;
765 	p = lwsac_use(&args->ac, 1, POL_AC_INITIAL);
766 	if (!p) {
767 		lwsl_err("%s: OOM\n", __func__);
768 		lws_free_set_NULL(context->pol_args);
769 
770 		return -1;
771 	}
772 	*p = 0;
773 	lejp_construct(&args->jctx, lws_ss_policy_parser_cb, args,
774 		       lejp_tokens_policy, LWS_ARRAY_SIZE(lejp_tokens_policy));
775 
776 	return 0;
777 }
778 
779 int
lws_ss_policy_parse_abandon(struct lws_context * context)780 lws_ss_policy_parse_abandon(struct lws_context *context)
781 {
782 	struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args;
783 
784 	lejp_destruct(&args->jctx);
785 	lws_free_set_NULL(context->pol_args);
786 
787 	return 0;
788 }
789 
790 int
lws_ss_policy_parse(struct lws_context * context,const uint8_t * buf,size_t len)791 lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len)
792 {
793 	struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args;
794 	int m;
795 
796 	m = (int)(signed char)lejp_parse(&args->jctx, buf, len);
797 	if (m == LEJP_CONTINUE || m >= 0)
798 		return m;
799 
800 	lwsl_err("%s: parse failed: %d: %s\n", __func__, m,
801 		 lejp_error_to_string(m));
802 	lws_ss_policy_parse_abandon(context);
803 
804 	return m;
805 }
806 
807 int
lws_ss_policy_set(struct lws_context * context,const char * name)808 lws_ss_policy_set(struct lws_context *context, const char *name)
809 {
810 	struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args;
811 	lws_ss_trust_store_t *ts;
812 	struct lws_vhost *v;
813 	lws_ss_x509_t *x;
814 	char buf[16];
815 	int m, ret = 0;
816 
817 	/*
818 	 * Parsing seems to have succeeded, and we're going to use the new
819 	 * policy that's laid out in args->ac
820 	 */
821 
822 	lejp_destruct(&args->jctx);
823 
824 	if (context->ac_policy) {
825 
826 		/*
827 		 * So this is a bit fun-filled, we already had a policy in
828 		 * force, perhaps it was the default policy that's just good for
829 		 * fetching the real policy, and we're doing that now.
830 		 *
831 		 * We can destroy all the policy-related direct allocations
832 		 * easily because they're cleanly in a single lwsac...
833 		 */
834 		lwsac_free(&context->ac_policy);
835 
836 		/*
837 		 * ...but when we did the trust stores, we created vhosts for
838 		 * each.  We need to destroy those now too, and recreate new
839 		 * ones from the new policy, perhaps with different X.509s.
840 		 */
841 
842 		v = context->vhost_list;
843 		while (v) {
844 			if (v->from_ss_policy) {
845 				struct lws_vhost *vh = v->vhost_next;
846 				lwsl_debug("%s: destroying vh %p\n", __func__, v);
847 				lws_vhost_destroy(v);
848 				v = vh;
849 				continue;
850 			}
851 			v = v->vhost_next;
852 		}
853 
854 		lws_check_deferred_free(context, 0, 1);
855 	}
856 
857 	context->pss_policies = args->heads[LTY_POLICY].p;
858 	context->ac_policy = args->ac;
859 
860 	lws_humanize(buf, sizeof(buf), lwsac_total_alloc(args->ac),
861 			humanize_schema_si_bytes);
862 	if (lwsac_total_alloc(args->ac))
863 		m = (int)((lwsac_total_overhead(args->ac) * 100) /
864 				lwsac_total_alloc(args->ac));
865 	else
866 		m = 0;
867 
868 	lwsl_notice("%s: %s, pad %d%c: %s\n", __func__, buf, m, '%', name);
869 
870 	/* Create vhosts for each type of trust store */
871 
872 	ts = args->heads[LTY_TRUSTSTORE].t;
873 	while (ts) {
874 		struct lws_context_creation_info i;
875 
876 		memset(&i, 0, sizeof(i));
877 
878 		/*
879 		 * We get called from context creation... instantiates
880 		 * vhosts with client tls contexts set up for each unique CA.
881 		 *
882 		 * Create the vhost with the first (mandatory) entry in the
883 		 * trust store...
884 		 */
885 
886 		v = lws_get_vhost_by_name(context, ts->name);
887 		if (!v) {
888 			int n;
889 
890 			i.options = context->options;
891 			i.vhost_name = ts->name;
892 			lwsl_debug("%s: %s\n", __func__, i.vhost_name);
893 			i.client_ssl_ca_mem = ts->ssx509[0]->ca_der;
894 			i.client_ssl_ca_mem_len = ts->ssx509[0]->ca_der_len;
895 			i.port = CONTEXT_PORT_NO_LISTEN;
896 			lwsl_info("%s: %s trust store initial '%s'\n", __func__,
897 				  ts->name, ts->ssx509[0]->vhost_name);
898 
899 			v = lws_create_vhost(context, &i);
900 			if (!v) {
901 				lwsl_err("%s: failed to create vhost %s\n",
902 					 __func__, ts->name);
903 				ret = 1;
904 			} else
905 				v->from_ss_policy = 1;
906 
907 			for (n = 1; v && n < ts->count; n++) {
908 				lwsl_info("%s: add '%s' to trust store\n",
909 					  __func__, ts->ssx509[n]->vhost_name);
910 				if (lws_tls_client_vhost_extra_cert_mem(v,
911 						ts->ssx509[n]->ca_der,
912 						ts->ssx509[n]->ca_der_len)) {
913 					lwsl_err("%s: add extra cert failed\n",
914 							__func__);
915 					ret = 1;
916 				}
917 			}
918 		}
919 
920 		ts = ts->next;
921 	}
922 
923 #if defined(LWS_WITH_SOCKS5)
924 
925 	/*
926 	 * ... we need to go through every vhost updating its understanding of
927 	 * which socks5 proxy to use...
928 	 */
929 
930 	v = context->vhost_list;
931 	while (v) {
932 		lws_set_socks(v, args->socks5_proxy);
933 		v = v->vhost_next;
934 	}
935 	if (context->vhost_system)
936 		lws_set_socks(context->vhost_system, args->socks5_proxy);
937 
938 	if (args->socks5_proxy)
939 		lwsl_notice("%s: global socks5 proxy: %s\n", __func__,
940 			    args->socks5_proxy);
941 #endif
942 
943 	/* now we processed the x.509 CAs, we can free all of our originals */
944 
945 	x = args->heads[LTY_X509].x;
946 	while (x) {
947 		/*
948 		 * Free all the DER buffers now they have been parsed into
949 		 * tls library X.509 objects
950 		 */
951 		lws_free((void *)x->ca_der);
952 		x->ca_der = NULL;
953 		x = x->next;
954 	}
955 
956 	/* and we can discard the parsing args object now, invalidating args */
957 
958 	lws_free_set_NULL(context->pol_args);
959 
960 	return ret;
961 }
962 
963 const lws_ss_policy_t *
lws_ss_policy_lookup(const struct lws_context * context,const char * streamtype)964 lws_ss_policy_lookup(const struct lws_context *context, const char *streamtype)
965 {
966 	const lws_ss_policy_t *p = context->pss_policies;
967 
968 	if (!streamtype)
969 		return NULL;
970 
971 	while (p) {
972 		if (!strcmp(p->streamtype, streamtype))
973 			return p;
974 		p = p->next;
975 	}
976 
977 	return NULL;
978 }
979