• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2019 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 #ifndef _WIN32
28 /* this is needed for Travis CI */
29 #include <dirent.h>
30 #endif
31 
32 #define ESC_INSTALL_DATADIR "_lws_ddir_"
33 
34 static const char * const paths_global[] = {
35 	"global.uid",
36 	"global.gid",
37 	"global.username",
38 	"global.groupname",
39 	"global.count-threads",
40 	"global.init-ssl",
41 	"global.server-string",
42 	"global.plugin-dir",
43 	"global.ws-pingpong-secs", /* deprecated */
44 	"global.timeout-secs",
45 	"global.reject-service-keywords[].*",
46 	"global.reject-service-keywords[]",
47 	"global.default-alpn",
48 	"global.ip-limit-ah",
49 	"global.ip-limit-wsi",
50 	"global.rlimit-nofile",
51 };
52 
53 enum lejp_global_paths {
54 	LEJPGP_UID,
55 	LEJPGP_GID,
56 	LEJPGP_USERNAME,
57 	LEJPGP_GROUPNAME,
58 	LEJPGP_COUNT_THREADS,
59 	LWJPGP_INIT_SSL,
60 	LEJPGP_SERVER_STRING,
61 	LEJPGP_PLUGIN_DIR,
62 	LWJPGP_PINGPONG_SECS,
63 	LWJPGP_TIMEOUT_SECS,
64 	LWJPGP_REJECT_SERVICE_KEYWORDS_NAME,
65 	LWJPGP_REJECT_SERVICE_KEYWORDS,
66 	LWJPGP_DEFAULT_ALPN,
67 	LWJPGP_IP_LIMIT_AH,
68 	LWJPGP_IP_LIMIT_WSI,
69 	LWJPGP_FD_LIMIT_PT,
70 };
71 
72 static const char * const paths_vhosts[] = {
73 	"vhosts[]",
74 	"vhosts[].name",
75 	"vhosts[].port",
76 	"vhosts[].interface",
77 	"vhosts[].unix-socket",
78 	"vhosts[].unix-socket-perms",
79 	"vhosts[].sts",
80 	"vhosts[].host-ssl-key",
81 	"vhosts[].host-ssl-cert",
82 	"vhosts[].host-ssl-ca",
83 	"vhosts[].access-log",
84 	"vhosts[].mounts[].mountpoint",
85 	"vhosts[].mounts[].origin",
86 	"vhosts[].mounts[].protocol",
87 	"vhosts[].mounts[].default",
88 	"vhosts[].mounts[].auth-mask",
89 	"vhosts[].mounts[].cgi-timeout",
90 	"vhosts[].mounts[].cgi-env[].*",
91 	"vhosts[].mounts[].cgi-env[]",
92 	"vhosts[].mounts[].cache-max-age",
93 	"vhosts[].mounts[].cache-reuse",
94 	"vhosts[].mounts[].cache-revalidate",
95 	"vhosts[].mounts[].basic-auth",
96 	"vhosts[].mounts[].cache-intermediaries",
97 	"vhosts[].mounts[].extra-mimetypes.*",
98 	"vhosts[].mounts[].extra-mimetypes",
99 	"vhosts[].mounts[].interpret.*",
100 	"vhosts[].mounts[].interpret",
101 	"vhosts[].mounts[]",
102 	"vhosts[].ws-protocols[].*.*",
103 	"vhosts[].ws-protocols[].*",
104 	"vhosts[].ws-protocols[]",
105 	"vhosts[].keepalive_timeout",
106 	"vhosts[].enable-client-ssl",
107 	"vhosts[].ciphers",
108 	"vhosts[].ecdh-curve",
109 	"vhosts[].noipv6",
110 	"vhosts[].ipv6only",
111 	"vhosts[].ssl-option-set",
112 	"vhosts[].ssl-option-clear",
113 	"vhosts[].mounts[].pmo[].*",
114 	"vhosts[].mounts[].pmo[]",
115 	"vhosts[].headers[].*",
116 	"vhosts[].headers[]",
117 	"vhosts[].client-ssl-key",
118 	"vhosts[].client-ssl-cert",
119 	"vhosts[].client-ssl-ca",
120 	"vhosts[].client-ssl-ciphers",
121 	"vhosts[].onlyraw",
122 	"vhosts[].client-cert-required",
123 	"vhosts[].ignore-missing-cert",
124 	"vhosts[].error-document-404",
125 	"vhosts[].alpn",
126 	"vhosts[].fo-listen-queue",
127 	"vhosts[].ssl-client-option-set",
128 	"vhosts[].ssl-client-option-clear",
129 	"vhosts[].tls13-ciphers",
130 	"vhosts[].client-tls13-ciphers",
131 	"vhosts[].strict-host-check",
132 
133 	"vhosts[].listen-accept-role",
134 	"vhosts[].listen-accept-protocol",
135 	"vhosts[].apply-listen-accept", /* deprecates "onlyraw" */
136 	"vhosts[].fallback-listen-accept",
137 	"vhosts[].allow-non-tls",
138 	"vhosts[].redirect-http",
139 	"vhosts[].allow-http-on-https",
140 
141 	"vhosts[].disable-no-protocol-ws-upgrades",
142 	"vhosts[].h2-half-closed-long-poll",
143 };
144 
145 enum lejp_vhost_paths {
146 	LEJPVP,
147 	LEJPVP_NAME,
148 	LEJPVP_PORT,
149 	LEJPVP_INTERFACE,
150 	LEJPVP_UNIXSKT,
151 	LEJPVP_UNIXSKT_PERMS,
152 	LEJPVP_STS,
153 	LEJPVP_HOST_SSL_KEY,
154 	LEJPVP_HOST_SSL_CERT,
155 	LEJPVP_HOST_SSL_CA,
156 	LEJPVP_ACCESS_LOG,
157 	LEJPVP_MOUNTPOINT,
158 	LEJPVP_ORIGIN,
159 	LEJPVP_MOUNT_PROTOCOL,
160 	LEJPVP_DEFAULT,
161 	LEJPVP_DEFAULT_AUTH_MASK,
162 	LEJPVP_CGI_TIMEOUT,
163 	LEJPVP_CGI_ENV,
164 	LEJPVP_CGI_ENV_base,
165 	LEJPVP_MOUNT_CACHE_MAX_AGE,
166 	LEJPVP_MOUNT_CACHE_REUSE,
167 	LEJPVP_MOUNT_CACHE_REVALIDATE,
168 	LEJPVP_MOUNT_BASIC_AUTH,
169 	LEJPVP_MOUNT_CACHE_INTERMEDIARIES,
170 	LEJPVP_MOUNT_EXTRA_MIMETYPES,
171 	LEJPVP_MOUNT_EXTRA_MIMETYPES_base,
172 	LEJPVP_MOUNT_INTERPRET,
173 	LEJPVP_MOUNT_INTERPRET_base,
174 
175 	LEJPVP_MOUNTS,
176 
177 	LEJPVP_PROTOCOL_NAME_OPT,
178 	LEJPVP_PROTOCOL_NAME,
179 	LEJPVP_PROTOCOL,
180 	LEJPVP_KEEPALIVE_TIMEOUT,
181 	LEJPVP_ENABLE_CLIENT_SSL,
182 	LEJPVP_CIPHERS,
183 	LEJPVP_ECDH_CURVE,
184 	LEJPVP_NOIPV6,
185 	LEJPVP_IPV6ONLY,
186 	LEJPVP_SSL_OPTION_SET,
187 	LEJPVP_SSL_OPTION_CLEAR,
188 	LEJPVP_PMO,
189 	LEJPVP_PM_baseO,
190 	LEJPVP_HEADERS_NAME,
191 	LEJPVP_HEADERS,
192 	LEJPVP_CLIENT_SSL_KEY,
193 	LEJPVP_CLIENT_SSL_CERT,
194 	LEJPVP_CLIENT_SSL_CA,
195 	LEJPVP_CLIENT_CIPHERS,
196 	LEJPVP_FLAG_ONLYRAW,
197 	LEJPVP_FLAG_CLIENT_CERT_REQUIRED,
198 	LEJPVP_IGNORE_MISSING_CERT,
199 	LEJPVP_ERROR_DOCUMENT_404,
200 	LEJPVP_ALPN,
201 	LWJPVP_FO_LISTEN_QUEUE,
202 	LEJPVP_SSL_CLIENT_OPTION_SET,
203 	LEJPVP_SSL_CLIENT_OPTION_CLEAR,
204 	LEJPVP_TLS13_CIPHERS,
205 	LEJPVP_CLIENT_TLS13_CIPHERS,
206 	LEJPVP_FLAG_STRICT_HOST_CHECK,
207 
208 	LEJPVP_LISTEN_ACCEPT_ROLE,
209 	LEJPVP_LISTEN_ACCEPT_PROTOCOL,
210 	LEJPVP_FLAG_APPLY_LISTEN_ACCEPT,
211 	LEJPVP_FLAG_FALLBACK_LISTEN_ACCEPT,
212 	LEJPVP_FLAG_ALLOW_NON_TLS,
213 	LEJPVP_FLAG_REDIRECT_HTTP,
214 	LEJPVP_FLAG_ALLOW_HTTP_ON_HTTPS,
215 
216 	LEJPVP_FLAG_DISABLE_NO_PROTOCOL_WS_UPGRADES,
217 	LEJPVP_FLAG_H2_HALF_CLOSED_LONG_POLL,
218 };
219 
220 #define MAX_PLUGIN_DIRS 10
221 
222 struct jpargs {
223 	struct lws_context_creation_info *info;
224 	struct lws_context *context;
225 	const struct lws_protocols *protocols;
226 	const struct lws_protocols **pprotocols;
227 	const struct lws_extension *extensions;
228 	char *p, *end, valid;
229 	struct lws_http_mount *head, *last;
230 
231 	struct lws_protocol_vhost_options *pvo;
232 	struct lws_protocol_vhost_options *pvo_em;
233 	struct lws_protocol_vhost_options *pvo_int;
234 	struct lws_http_mount m;
235 	const char **plugin_dirs;
236 	int count_plugin_dirs;
237 
238 	unsigned int reject_ws_with_no_protocol:1;
239 	unsigned int enable_client_ssl:1;
240 	unsigned int fresh_mount:1;
241 	unsigned int any_vhosts:1;
242 	unsigned int chunk:1;
243 };
244 
245 static void *
lwsws_align(struct jpargs * a)246 lwsws_align(struct jpargs *a)
247 {
248 	if ((lws_intptr_t)(a->p) & 15)
249 		a->p += 16 - ((lws_intptr_t)(a->p) & 15);
250 
251 	a->chunk = 0;
252 
253 	return a->p;
254 }
255 
256 static int
arg_to_bool(const char * s)257 arg_to_bool(const char *s)
258 {
259 	static const char * const on[] = { "on", "yes", "true" };
260 	int n = atoi(s);
261 
262 	if (n)
263 		return 1;
264 
265 	for (n = 0; n < (int)LWS_ARRAY_SIZE(on); n++)
266 		if (!strcasecmp(s, on[n]))
267 			return 1;
268 
269 	return 0;
270 }
271 
272 static void
set_reset_flag(uint64_t * p,const char * state,uint64_t flag)273 set_reset_flag(uint64_t *p, const char *state, uint64_t flag)
274 {
275 	if (arg_to_bool(state))
276 		*p |= flag;
277 	else
278 		*p &= ~(flag);
279 }
280 
281 static signed char
lejp_globals_cb(struct lejp_ctx * ctx,char reason)282 lejp_globals_cb(struct lejp_ctx *ctx, char reason)
283 {
284 	struct jpargs *a = (struct jpargs *)ctx->user;
285 	struct lws_protocol_vhost_options *rej;
286 	int n;
287 
288 	/* we only match on the prepared path strings */
289 	if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match)
290 		return 0;
291 
292 	/* this catches, eg, vhosts[].headers[].xxx */
293 	if (reason == LEJPCB_VAL_STR_END &&
294 	    ctx->path_match == LWJPGP_REJECT_SERVICE_KEYWORDS_NAME + 1) {
295 		rej = lwsws_align(a);
296 		a->p += sizeof(*rej);
297 
298 		n = lejp_get_wildcard(ctx, 0, a->p, lws_ptr_diff(a->end, a->p));
299 		rej->next = a->info->reject_service_keywords;
300 		a->info->reject_service_keywords = rej;
301 		rej->name = a->p;
302 		 lwsl_notice("  adding rej %s=%s\n", a->p, ctx->buf);
303 		a->p += n - 1;
304 		*(a->p++) = '\0';
305 		rej->value = a->p;
306 		rej->options = NULL;
307 		goto dostring;
308 	}
309 
310 	switch (ctx->path_match - 1) {
311 	case LEJPGP_UID:
312 		a->info->uid = (unsigned int)atoi(ctx->buf);
313 		return 0;
314 	case LEJPGP_GID:
315 		a->info->gid = (unsigned int)atoi(ctx->buf);
316 		return 0;
317 	case LEJPGP_USERNAME:
318 		a->info->username = a->p;
319 		break;
320 	case LEJPGP_GROUPNAME:
321 		a->info->groupname = a->p;
322 		break;
323 	case LEJPGP_COUNT_THREADS:
324 		a->info->count_threads = (unsigned int)atoi(ctx->buf);
325 		return 0;
326 	case LWJPGP_INIT_SSL:
327 		if (arg_to_bool(ctx->buf))
328 			a->info->options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
329 		return 0;
330 	case LEJPGP_SERVER_STRING:
331 #if defined(LWS_WITH_SERVER)
332 		a->info->server_string = a->p;
333 #endif
334 		break;
335 	case LEJPGP_PLUGIN_DIR:
336 		if (a->count_plugin_dirs == MAX_PLUGIN_DIRS - 1) {
337 			lwsl_err("Too many plugin dirs\n");
338 			return -1;
339 		}
340 		a->plugin_dirs[a->count_plugin_dirs++] = a->p;
341 		break;
342 
343 	case LWJPGP_PINGPONG_SECS: /* deprecated */
344 		return 0;
345 
346 	case LWJPGP_TIMEOUT_SECS:
347 		a->info->timeout_secs = (unsigned int)atoi(ctx->buf);
348 		return 0;
349 
350 #if defined(LWS_WITH_TLS)
351 	case LWJPGP_DEFAULT_ALPN:
352 		a->info->alpn = a->p;
353 		break;
354 #endif
355 
356 #if defined(LWS_WITH_PEER_LIMITS)
357 	case LWJPGP_IP_LIMIT_AH:
358 		a->info->ip_limit_ah = (uint16_t)atoi(ctx->buf);
359 		return 0;
360 
361 	case LWJPGP_IP_LIMIT_WSI:
362 		a->info->ip_limit_wsi = (uint16_t)atoi(ctx->buf);
363 		return 0;
364 #endif
365 
366 	case LWJPGP_FD_LIMIT_PT:
367 		a->info->rlimit_nofile = atoi(ctx->buf);
368 		return 0;
369 
370 	default:
371 		return 0;
372 	}
373 
374 dostring:
375 	a->p += lws_snprintf(a->p, lws_ptr_diff_size_t(a->end, a->p), "%s", ctx->buf);
376 	*(a->p)++ = '\0';
377 
378 	return 0;
379 }
380 
381 static signed char
lejp_vhosts_cb(struct lejp_ctx * ctx,char reason)382 lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
383 {
384 	struct jpargs *a = (struct jpargs *)ctx->user;
385 	struct lws_protocol_vhost_options *pvo, *mp_cgienv, *headers;
386 	struct lws_http_mount *m;
387 	char *p, *p1;
388 	int n;
389 
390 #if 0
391 	lwsl_notice(" %d: %s (%d)\n", reason, ctx->path, ctx->path_match);
392 	for (n = 0; n < ctx->wildcount; n++)
393 		lwsl_notice("    %d\n", ctx->wild[n]);
394 #endif
395 
396 	if (reason == LEJPCB_OBJECT_START && ctx->path_match == LEJPVP + 1) {
397 		uint32_t i[4];
398 #if defined(LWS_WITH_SERVER)
399 		const char *ss;
400 #endif
401 
402 		/* set the defaults for this vhost */
403 		a->reject_ws_with_no_protocol = 0;
404 		a->valid = 1;
405 		a->head = NULL;
406 		a->last = NULL;
407 
408 		i[0] = a->info->count_threads;
409 		i[1] = a->info->options & (
410 			LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME |
411 			LWS_SERVER_OPTION_LIBUV |
412 			LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT |
413 			LWS_SERVER_OPTION_EXPLICIT_VHOSTS |
414 			LWS_SERVER_OPTION_UV_NO_SIGSEGV_SIGFPE_SPIN |
415 			LWS_SERVER_OPTION_LIBEVENT |
416 			LWS_SERVER_OPTION_LIBEV
417 				);
418 #if defined(LWS_WITH_SERVER)
419 		ss = a->info->server_string;
420 #endif
421 		i[3] = a->info->timeout_secs;
422 
423 		memset(a->info, 0, sizeof(*a->info));
424 
425 		a->info->count_threads = i[0];
426 		a->info->options = i[1];
427 #if defined(LWS_WITH_SERVER)
428 		a->info->server_string = ss;
429 #endif
430 		a->info->timeout_secs = i[3];
431 
432 		a->info->protocols = a->protocols;
433 		a->info->pprotocols = a->pprotocols;
434 #if defined(LWS_ROLE_WS)
435 		a->info->extensions = a->extensions;
436 #endif
437 #if defined(LWS_WITH_TLS)
438 #if defined(LWS_WITH_CLIENT)
439 		a->info->client_ssl_cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:"
440 			"ECDHE-RSA-AES256-GCM-SHA384:"
441 			"DHE-RSA-AES256-GCM-SHA384:"
442 			"ECDHE-RSA-AES256-SHA384:"
443 			"HIGH:!aNULL:!eNULL:!EXPORT:"
444 			"!DES:!MD5:!PSK:!RC4:!HMAC_SHA1:"
445 			"!SHA1:!DHE-RSA-AES128-GCM-SHA256:"
446 			"!DHE-RSA-AES128-SHA256:"
447 			"!AES128-GCM-SHA256:"
448 			"!AES128-SHA256:"
449 			"!DHE-RSA-AES256-SHA256:"
450 			"!AES256-GCM-SHA384:"
451 			"!AES256-SHA256";
452 #endif
453 #if defined(LWS_WITH_SERVER)
454 		a->info->ssl_cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:"
455 				       "ECDHE-RSA-AES256-GCM-SHA384:"
456 				       "DHE-RSA-AES256-GCM-SHA384:"
457 				       "ECDHE-RSA-AES256-SHA384:"
458 				       "HIGH:!aNULL:!eNULL:!EXPORT:"
459 				       "!DES:!MD5:!PSK:!RC4:!HMAC_SHA1:"
460 				       "!SHA1:!DHE-RSA-AES128-GCM-SHA256:"
461 				       "!DHE-RSA-AES128-SHA256:"
462 				       "!AES128-GCM-SHA256:"
463 				       "!AES128-SHA256:"
464 				       "!DHE-RSA-AES256-SHA256:"
465 				       "!AES256-GCM-SHA384:"
466 				       "!AES256-SHA256";
467 #endif
468 #endif
469 		a->info->keepalive_timeout = 5;
470 	}
471 
472 	if (reason == LEJPCB_OBJECT_START &&
473 	    ctx->path_match == LEJPVP_MOUNTS + 1) {
474 		a->fresh_mount = 1;
475 		memset(&a->m, 0, sizeof(a->m));
476 	}
477 
478 	/* this catches, eg, vhosts[].ws-protocols[].xxx-protocol */
479 	if (reason == LEJPCB_OBJECT_START &&
480 	    ctx->path_match == LEJPVP_PROTOCOL_NAME + 1) {
481 		a->pvo = lwsws_align(a);
482 		a->p += sizeof(*a->pvo);
483 
484 		n = lejp_get_wildcard(ctx, 0, a->p, lws_ptr_diff(a->end, a->p));
485 		/* ie, enable this protocol, no options yet */
486 		a->pvo->next = a->info->pvo;
487 		a->info->pvo = a->pvo;
488 		a->pvo->name = a->p;
489 		lwsl_info("  adding protocol %s\n", a->p);
490 		a->p += n;
491 		a->pvo->value = a->p;
492 		a->pvo->options = NULL;
493 		goto dostring;
494 	}
495 
496 	/* this catches, eg, vhosts[].headers[].xxx */
497 	if ((reason == LEJPCB_VAL_STR_END || reason == LEJPCB_VAL_STR_CHUNK) &&
498 	    ctx->path_match == LEJPVP_HEADERS_NAME + 1) {
499 
500 		if (!a->chunk) {
501 			headers = lwsws_align(a);
502 			a->p += sizeof(*headers);
503 
504 			n = lejp_get_wildcard(ctx, 0, a->p,
505 					lws_ptr_diff(a->end, a->p));
506 			/* ie, add this header */
507 			headers->next = a->info->headers;
508 			a->info->headers = headers;
509 			headers->name = a->p;
510 
511 			lwsl_notice("  adding header %s=%s\n", a->p, ctx->buf);
512 			a->p += n - 1;
513 			*(a->p++) = ':';
514 			if (a->p < a->end)
515 				*(a->p++) = '\0';
516 			else
517 				*(a->p - 1) = '\0';
518 			headers->value = a->p;
519 			headers->options = NULL;
520 		}
521 		a->chunk = reason == LEJPCB_VAL_STR_CHUNK;
522 		goto dostring;
523 	}
524 
525 	if (reason == LEJPCB_OBJECT_END &&
526 	    (ctx->path_match == LEJPVP + 1 || !ctx->path[0]) &&
527 	    a->valid) {
528 
529 		struct lws_vhost *vhost;
530 
531 		//lwsl_notice("%s\n", ctx->path);
532 		if (!a->info->port &&
533 		    !(a->info->options & LWS_SERVER_OPTION_UNIX_SOCK)) {
534 			lwsl_err("Port required (eg, 443)\n");
535 			return 1;
536 		}
537 		a->valid = 0;
538 		a->info->mounts = a->head;
539 
540 		vhost = lws_create_vhost(a->context, a->info);
541 		if (!vhost) {
542 			lwsl_err("Failed to create vhost %s\n",
543 				 a->info->vhost_name);
544 			return 1;
545 		}
546 		a->any_vhosts = 1;
547 
548 		if (a->reject_ws_with_no_protocol) {
549 			a->reject_ws_with_no_protocol = 0;
550 
551 			vhost->default_protocol_index = 255;
552 		}
553 
554 #if defined(LWS_WITH_TLS) && defined(LWS_WITH_CLIENT)
555 		if (a->enable_client_ssl) {
556 			const char *cert_filepath =
557 					a->info->client_ssl_cert_filepath;
558 			const char *private_key_filepath =
559 				       a->info->client_ssl_private_key_filepath;
560 			const char *ca_filepath =
561 					a->info->client_ssl_ca_filepath;
562 			const char *cipher_list =
563 					a->info->client_ssl_cipher_list;
564 
565 			memset(a->info, 0, sizeof(*a->info));
566 			a->info->client_ssl_cert_filepath = cert_filepath;
567 			a->info->client_ssl_private_key_filepath =
568 							private_key_filepath;
569 			a->info->client_ssl_ca_filepath = ca_filepath;
570 			a->info->client_ssl_cipher_list = cipher_list;
571 			a->info->options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
572 			lws_init_vhost_client_ssl(a->info, vhost);
573 		}
574 #endif
575 
576 		return 0;
577 	}
578 
579 	if (reason == LEJPCB_OBJECT_END &&
580 	    ctx->path_match == LEJPVP_MOUNTS + 1) {
581 		static const char * const mount_protocols[] = {
582 			"http://",
583 			"https://",
584 			"file://",
585 			"cgi://",
586 			">http://",
587 			">https://",
588 			"callback://",
589 			"gzip://",
590 		};
591 
592 		if (!a->fresh_mount)
593 			return 0;
594 
595 		if (!a->m.mountpoint || !a->m.origin) {
596 			lwsl_err("mountpoint and origin required\n");
597 			return 1;
598 		}
599 		lwsl_debug("adding mount %s\n", a->m.mountpoint);
600 		m = lwsws_align(a);
601 		memcpy(m, &a->m, sizeof(*m));
602 		if (a->last)
603 			a->last->mount_next = m;
604 
605 		for (n = 0; n < (int)LWS_ARRAY_SIZE(mount_protocols); n++)
606 			if (!strncmp(a->m.origin, mount_protocols[n],
607 			     strlen(mount_protocols[n]))) {
608 				lwsl_info("----%s\n", a->m.origin);
609 				m->origin_protocol = (uint8_t)(unsigned int)n;
610 				m->origin = a->m.origin +
611 					    strlen(mount_protocols[n]);
612 				break;
613 			}
614 
615 		if (n == (int)LWS_ARRAY_SIZE(mount_protocols)) {
616 			lwsl_err("unsupported protocol:// %s\n", a->m.origin);
617 			return 1;
618 		}
619 
620 		a->p += sizeof(*m);
621 		if (!a->head)
622 			a->head = m;
623 
624 		a->last = m;
625 		a->fresh_mount = 0;
626 	}
627 
628 	/* we only match on the prepared path strings */
629 	if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match)
630 		return 0;
631 
632 	switch (ctx->path_match - 1) {
633 	case LEJPVP_NAME:
634 		a->info->vhost_name = a->p;
635 		break;
636 	case LEJPVP_PORT:
637 		a->info->port = atoi(ctx->buf);
638 		return 0;
639 	case LEJPVP_INTERFACE:
640 		a->info->iface = a->p;
641 		break;
642 	case LEJPVP_UNIXSKT:
643 		if (arg_to_bool(ctx->buf))
644 			a->info->options |= (uint64_t)LWS_SERVER_OPTION_UNIX_SOCK;
645 		else
646 			a->info->options &= (uint64_t)~(LWS_SERVER_OPTION_UNIX_SOCK);
647 		return 0;
648 	case LEJPVP_UNIXSKT_PERMS:
649 		a->info->unix_socket_perms = a->p;
650 		break;
651 	case LEJPVP_STS:
652 		if (arg_to_bool(ctx->buf))
653 			a->info->options |= (uint64_t)LWS_SERVER_OPTION_STS;
654 		else
655 			a->info->options &= (uint64_t)~(LWS_SERVER_OPTION_STS);
656 		return 0;
657 #if defined(LWS_WITH_TLS)
658 	case LEJPVP_HOST_SSL_KEY:
659 		a->info->ssl_private_key_filepath = a->p;
660 		break;
661 	case LEJPVP_HOST_SSL_CERT:
662 		a->info->ssl_cert_filepath = a->p;
663 		break;
664 	case LEJPVP_HOST_SSL_CA:
665 		a->info->ssl_ca_filepath = a->p;
666 		break;
667 #endif
668 	case LEJPVP_ACCESS_LOG:
669 		a->info->log_filepath = a->p;
670 		break;
671 	case LEJPVP_MOUNTPOINT:
672 		a->m.mountpoint = a->p;
673 		a->m.mountpoint_len = (unsigned char)strlen(ctx->buf);
674 		break;
675 	case LEJPVP_ORIGIN:
676 		if (!strncmp(ctx->buf, "callback://", 11))
677 			a->m.protocol = a->p + 11;
678 
679 		if (!a->m.origin)
680 			a->m.origin = a->p;
681 		break;
682 	case LEJPVP_DEFAULT:
683 		a->m.def = a->p;
684 		break;
685 	case LEJPVP_DEFAULT_AUTH_MASK:
686 		a->m.auth_mask = (unsigned int)atoi(ctx->buf);
687 		return 0;
688 	case LEJPVP_MOUNT_CACHE_MAX_AGE:
689 		a->m.cache_max_age = atoi(ctx->buf);
690 		return 0;
691 	case LEJPVP_MOUNT_CACHE_REUSE:
692 		a->m.cache_reusable = !!arg_to_bool(ctx->buf);
693 		return 0;
694 	case LEJPVP_MOUNT_CACHE_REVALIDATE:
695 		a->m.cache_revalidate = !!arg_to_bool(ctx->buf);
696 		return 0;
697 	case LEJPVP_MOUNT_CACHE_INTERMEDIARIES:
698 		a->m.cache_intermediaries = !!arg_to_bool(ctx->buf);;
699 		return 0;
700 	case LEJPVP_MOUNT_BASIC_AUTH:
701 #if defined(LWS_WITH_HTTP_BASIC_AUTH)
702 		a->m.basic_auth_login_file = a->p;
703 #endif
704 		break;
705 	case LEJPVP_CGI_TIMEOUT:
706 		a->m.cgi_timeout = atoi(ctx->buf);
707 		return 0;
708 	case LWJPVP_FO_LISTEN_QUEUE:
709 		a->info->fo_listen_queue = atoi(ctx->buf);
710 		return 0;
711 	case LEJPVP_KEEPALIVE_TIMEOUT:
712 		a->info->keepalive_timeout = atoi(ctx->buf);
713 		return 0;
714 #if defined(LWS_WITH_TLS)
715 #if defined(LWS_WITH_CLIENT)
716 	case LEJPVP_CLIENT_CIPHERS:
717 		a->info->client_ssl_cipher_list = a->p;
718 		break;
719 	case LEJPVP_CLIENT_TLS13_CIPHERS:
720 		a->info->client_tls_1_3_plus_cipher_list = a->p;
721 		break;
722 #endif
723 
724 	case LEJPVP_CIPHERS:
725 		a->info->ssl_cipher_list = a->p;
726 		break;
727 	case LEJPVP_TLS13_CIPHERS:
728 		a->info->tls1_3_plus_cipher_list = a->p;
729 		break;
730 	case LEJPVP_ECDH_CURVE:
731 		a->info->ecdh_curve = a->p;
732 		break;
733 #endif
734 	case LEJPVP_PMO:
735 	case LEJPVP_CGI_ENV:
736 		mp_cgienv = lwsws_align(a);
737 		a->p += sizeof(*a->m.cgienv);
738 
739 		mp_cgienv->next = a->m.cgienv;
740 		a->m.cgienv = mp_cgienv;
741 
742 		n = lejp_get_wildcard(ctx, 0, a->p, lws_ptr_diff(a->end, a->p));
743 		mp_cgienv->name = a->p;
744 		a->p += n;
745 		mp_cgienv->value = a->p;
746 		mp_cgienv->options = NULL;
747 		//lwsl_notice("    adding pmo / cgi-env '%s' = '%s'\n",
748 		//		mp_cgienv->name, mp_cgienv->value);
749 		goto dostring;
750 
751 	case LEJPVP_PROTOCOL_NAME_OPT:
752 		/* this catches, eg,
753 		 * vhosts[].ws-protocols[].xxx-protocol.yyy-option
754 		 * ie, these are options attached to a protocol with { }
755 		 */
756 		pvo = lwsws_align(a);
757 		a->p += sizeof(*a->pvo);
758 
759 		n = lejp_get_wildcard(ctx, 1, a->p, lws_ptr_diff(a->end, a->p));
760 		/* ie, enable this protocol, no options yet */
761 		pvo->next = a->pvo->options;
762 		a->pvo->options = pvo;
763 		pvo->name = a->p;
764 		a->p += n;
765 		pvo->value = a->p;
766 		pvo->options = NULL;
767 		break;
768 
769 	case LEJPVP_MOUNT_EXTRA_MIMETYPES:
770 		a->pvo_em = lwsws_align(a);
771 		a->p += sizeof(*a->pvo_em);
772 
773 		n = lejp_get_wildcard(ctx, 0, a->p, lws_ptr_diff(a->end, a->p));
774 		/* ie, enable this protocol, no options yet */
775 		a->pvo_em->next = a->m.extra_mimetypes;
776 		a->m.extra_mimetypes = a->pvo_em;
777 		a->pvo_em->name = a->p;
778 		lwsl_notice("  + extra-mimetypes %s -> %s\n", a->p, ctx->buf);
779 		a->p += n;
780 		a->pvo_em->value = a->p;
781 		a->pvo_em->options = NULL;
782 		break;
783 
784 	case LEJPVP_MOUNT_INTERPRET:
785 		a->pvo_int = lwsws_align(a);
786 		a->p += sizeof(*a->pvo_int);
787 
788 		n = lejp_get_wildcard(ctx, 0, a->p, lws_ptr_diff(a->end, a->p));
789 		/* ie, enable this protocol, no options yet */
790 		a->pvo_int->next = a->m.interpret;
791 		a->m.interpret = a->pvo_int;
792 		a->pvo_int->name = a->p;
793 		lwsl_notice("  adding interpret %s -> %s\n", a->p,
794 			    ctx->buf);
795 		a->p += n;
796 		a->pvo_int->value = a->p;
797 		a->pvo_int->options = NULL;
798 		break;
799 
800 	case LEJPVP_ENABLE_CLIENT_SSL:
801 		a->enable_client_ssl = !!arg_to_bool(ctx->buf);
802 		return 0;
803 #if defined(LWS_WITH_TLS) && defined(LWS_WITH_CLIENT)
804 	case LEJPVP_CLIENT_SSL_KEY:
805 		a->info->client_ssl_private_key_filepath = a->p;
806 		break;
807 	case LEJPVP_CLIENT_SSL_CERT:
808 		a->info->client_ssl_cert_filepath = a->p;
809 		break;
810 	case LEJPVP_CLIENT_SSL_CA:
811 		a->info->client_ssl_ca_filepath = a->p;
812 		break;
813 #endif
814 
815 	case LEJPVP_NOIPV6:
816 		set_reset_flag(&a->info->options, ctx->buf,
817 			       LWS_SERVER_OPTION_DISABLE_IPV6);
818 		return 0;
819 
820 	case LEJPVP_FLAG_ONLYRAW:
821 		set_reset_flag(&a->info->options, ctx->buf,
822 			    LWS_SERVER_OPTION_ADOPT_APPLY_LISTEN_ACCEPT_CONFIG);
823 		return 0;
824 
825 	case LEJPVP_IPV6ONLY:
826 		a->info->options |= LWS_SERVER_OPTION_IPV6_V6ONLY_MODIFY;
827 		set_reset_flag(&a->info->options, ctx->buf,
828 			       LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE);
829 		return 0;
830 
831 	case LEJPVP_FLAG_CLIENT_CERT_REQUIRED:
832 		if (arg_to_bool(ctx->buf))
833 			a->info->options |=
834 			    LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;
835 		return 0;
836 
837 	case LEJPVP_IGNORE_MISSING_CERT:
838 		set_reset_flag(&a->info->options, ctx->buf,
839 				LWS_SERVER_OPTION_IGNORE_MISSING_CERT);
840 		return 0;
841 
842 	case LEJPVP_FLAG_STRICT_HOST_CHECK:
843 		set_reset_flag(&a->info->options, ctx->buf,
844 			LWS_SERVER_OPTION_VHOST_UPG_STRICT_HOST_CHECK);
845 		return 0;
846 
847 	case LEJPVP_ERROR_DOCUMENT_404:
848 		a->info->error_document_404 = a->p;
849 		break;
850 
851 #if defined(LWS_WITH_TLS)
852 	case LEJPVP_SSL_OPTION_SET:
853 		a->info->ssl_options_set |= atol(ctx->buf);
854 		return 0;
855 	case LEJPVP_SSL_OPTION_CLEAR:
856 		a->info->ssl_options_clear |= atol(ctx->buf);
857 		return 0;
858 
859 #if defined(LWS_WITH_CLIENT)
860 	case LEJPVP_SSL_CLIENT_OPTION_SET:
861 		a->info->ssl_client_options_set |= atol(ctx->buf);
862 		return 0;
863 	case LEJPVP_SSL_CLIENT_OPTION_CLEAR:
864 		a->info->ssl_client_options_clear |= atol(ctx->buf);
865 		return 0;
866 #endif
867 
868 	case LEJPVP_ALPN:
869 		a->info->alpn = a->p;
870 		break;
871 #endif
872 
873 	case LEJPVP_LISTEN_ACCEPT_ROLE:
874 		a->info->listen_accept_role = a->p;
875 		break;
876 	case LEJPVP_LISTEN_ACCEPT_PROTOCOL:
877 		a->info->listen_accept_protocol = a->p;
878 		break;
879 
880 	case LEJPVP_FLAG_APPLY_LISTEN_ACCEPT:
881 		set_reset_flag(&a->info->options, ctx->buf,
882 			LWS_SERVER_OPTION_ADOPT_APPLY_LISTEN_ACCEPT_CONFIG);
883 		return 0;
884 	case LEJPVP_FLAG_FALLBACK_LISTEN_ACCEPT:
885 		lwsl_notice("vh %s: LEJPVP_FLAG_FALLBACK_LISTEN_ACCEPT: %s\n",
886 			    a->info->vhost_name, ctx->buf);
887 		set_reset_flag(&a->info->options, ctx->buf,
888 		      LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG);
889 		return 0;
890 	case LEJPVP_FLAG_ALLOW_NON_TLS:
891 		set_reset_flag(&a->info->options, ctx->buf,
892 			       LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT);
893 		return 0;
894 	case LEJPVP_FLAG_REDIRECT_HTTP:
895 		set_reset_flag(&a->info->options, ctx->buf,
896 			       LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS);
897 		return 0;
898 	case LEJPVP_FLAG_ALLOW_HTTP_ON_HTTPS:
899 		set_reset_flag(&a->info->options, ctx->buf,
900 			       LWS_SERVER_OPTION_ALLOW_HTTP_ON_HTTPS_LISTENER);
901 		return 0;
902 
903 	case LEJPVP_FLAG_DISABLE_NO_PROTOCOL_WS_UPGRADES:
904 		a->reject_ws_with_no_protocol = 1;
905 		return 0;
906 
907 	case LEJPVP_FLAG_H2_HALF_CLOSED_LONG_POLL:
908 		set_reset_flag(&a->info->options, ctx->buf,
909 				LWS_SERVER_OPTION_VH_H2_HALF_CLOSED_LONG_POLL);
910 		return 0;
911 
912 	default:
913 		return 0;
914 	}
915 
916 dostring:
917 	p = ctx->buf;
918 	p[LEJP_STRING_CHUNK] = '\0';
919 	p1 = strstr(p, ESC_INSTALL_DATADIR);
920 	if (p1) {
921 		n = lws_ptr_diff(p1, p);
922 		if (n > a->end - a->p)
923 			n = lws_ptr_diff(a->end, a->p);
924 		lws_strncpy(a->p, p, (unsigned int)n + 1u);
925 		a->p += n;
926 		a->p += lws_snprintf(a->p, lws_ptr_diff_size_t(a->end, a->p), "%s",
927 				     LWS_INSTALL_DATADIR);
928 		p += n + (int)strlen(ESC_INSTALL_DATADIR);
929 	}
930 
931 	a->p += lws_snprintf(a->p, lws_ptr_diff_size_t(a->end, a->p), "%s", p);
932 	if (reason == LEJPCB_VAL_STR_END)
933 		*(a->p)++ = '\0';
934 
935 	return 0;
936 }
937 
938 /*
939  * returns 0 = OK, 1 = can't open, 2 = parsing error
940  */
941 
942 static int
lwsws_get_config(void * user,const char * f,const char * const * paths,int count_paths,lejp_callback cb)943 lwsws_get_config(void *user, const char *f, const char * const *paths,
944 		 int count_paths, lejp_callback cb)
945 {
946 	unsigned char buf[128];
947 	struct lejp_ctx ctx;
948 	int n, m = 0, fd;
949 
950 	memset(&ctx, 0, sizeof(ctx));
951 
952 	fd = lws_open(f, O_RDONLY);
953 	if (fd < 0) {
954 		lwsl_err("Cannot open %s\n", f);
955 		return 2;
956 	}
957 	lwsl_info("%s: %s\n", __func__, f);
958 	lejp_construct(&ctx, cb, user, paths, (uint8_t)(unsigned int)count_paths);
959 
960 	do {
961 		n = (int)read(fd, buf, sizeof(buf));
962 		if (!n)
963 			break;
964 
965 		m = lejp_parse(&ctx, buf, n);
966 	} while (m == LEJP_CONTINUE);
967 
968 	close(fd);
969 	n = (int32_t)ctx.line;
970 	lejp_destruct(&ctx);
971 
972 	if (m < 0) {
973 		lwsl_err("%s(%u): parsing error %d: %s\n", f, n, m,
974 			 lejp_error_to_string(m));
975 		return 2;
976 	}
977 
978 	return 0;
979 }
980 
981 struct lws_dir_args {
982 	void *user;
983 	const char * const *paths;
984 	int count_paths;
985 	lejp_callback cb;
986 };
987 
988 static int
lwsws_get_config_d_cb(const char * dirpath,void * user,struct lws_dir_entry * lde)989 lwsws_get_config_d_cb(const char *dirpath, void *user,
990 		      struct lws_dir_entry *lde)
991 {
992 	struct lws_dir_args *da = (struct lws_dir_args *)user;
993 	char path[256];
994 
995 	if (lde->type != LDOT_FILE && lde->type != LDOT_UNKNOWN /* ZFS */)
996 		return 0;
997 
998 	lws_snprintf(path, sizeof(path) - 1, "%s/%s", dirpath, lde->name);
999 
1000 	return lwsws_get_config(da->user, path, da->paths,
1001 				da->count_paths, da->cb);
1002 }
1003 
1004 int
lwsws_get_config_globals(struct lws_context_creation_info * info,const char * d,char ** cs,int * len)1005 lwsws_get_config_globals(struct lws_context_creation_info *info, const char *d,
1006 			 char **cs, int *len)
1007 {
1008 	struct lws_dir_args da;
1009 	struct jpargs a;
1010 #if defined(LWS_WITH_PLUGINS)
1011 	const char * const *old = info->plugin_dirs;
1012 #endif
1013 	char dd[128];
1014 
1015 	memset(&a, 0, sizeof(a));
1016 
1017 	a.info = info;
1018 	a.p = *cs;
1019 	a.end = (a.p + *len) - 1;
1020 	a.valid = 0;
1021 
1022 	lwsws_align(&a);
1023 #if defined(LWS_WITH_PLUGINS)
1024 	info->plugin_dirs = (void *)a.p;
1025 #endif
1026 	a.plugin_dirs = (void *)a.p; /* writeable version */
1027 	a.p += MAX_PLUGIN_DIRS * sizeof(void *);
1028 
1029 #if defined(LWS_WITH_PLUGINS)
1030 	/* copy any default paths */
1031 
1032 	while (old && *old) {
1033 		a.plugin_dirs[a.count_plugin_dirs++] = *old;
1034 		old++;
1035 	}
1036 #endif
1037 
1038 	lws_snprintf(dd, sizeof(dd) - 1, "%s/conf", d);
1039 	if (lwsws_get_config(&a, dd, paths_global,
1040 			     LWS_ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
1041 		return 1;
1042 	lws_snprintf(dd, sizeof(dd) - 1, "%s/conf.d", d);
1043 
1044 	da.user = &a;
1045 	da.paths = paths_global;
1046 	da.count_paths = LWS_ARRAY_SIZE(paths_global),
1047 	da.cb = lejp_globals_cb;
1048 
1049 	if (lws_dir(dd, &da, lwsws_get_config_d_cb) > 1)
1050 		return 1;
1051 
1052 	a.plugin_dirs[a.count_plugin_dirs] = NULL;
1053 
1054 	*cs = a.p;
1055 	*len = lws_ptr_diff(a.end, a.p);
1056 
1057 	return 0;
1058 }
1059 
1060 int
lwsws_get_config_vhosts(struct lws_context * context,struct lws_context_creation_info * info,const char * d,char ** cs,int * len)1061 lwsws_get_config_vhosts(struct lws_context *context,
1062 			struct lws_context_creation_info *info, const char *d,
1063 			char **cs, int *len)
1064 {
1065 	struct lws_dir_args da;
1066 	struct jpargs a;
1067 	char dd[128];
1068 
1069 	memset(&a, 0, sizeof(a));
1070 
1071 	a.info = info;
1072 	a.p = *cs;
1073 	a.end = a.p + *len;
1074 	a.valid = 0;
1075 	a.context = context;
1076 	a.protocols = info->protocols;
1077 	a.pprotocols = info->pprotocols;
1078 #if defined(LWS_ROLE_WS)
1079 	a.extensions = info->extensions;
1080 #endif
1081 
1082 	lws_snprintf(dd, sizeof(dd) - 1, "%s/conf", d);
1083 	if (lwsws_get_config(&a, dd, paths_vhosts,
1084 			     LWS_ARRAY_SIZE(paths_vhosts), lejp_vhosts_cb) > 1)
1085 		return 1;
1086 	lws_snprintf(dd, sizeof(dd) - 1, "%s/conf.d", d);
1087 
1088 	da.user = &a;
1089 	da.paths = paths_vhosts;
1090 	da.count_paths = LWS_ARRAY_SIZE(paths_vhosts),
1091 	da.cb = lejp_vhosts_cb;
1092 
1093 	if (lws_dir(dd, &da, lwsws_get_config_d_cb) > 1)
1094 		return 1;
1095 
1096 	*cs = a.p;
1097 	*len = lws_ptr_diff(a.end, a.p);
1098 
1099 	if (!a.any_vhosts) {
1100 		lwsl_err("Need at least one vhost\n");
1101 		return 1;
1102 	}
1103 
1104 //	lws_finalize_startup(context);
1105 
1106 	return 0;
1107 }
1108