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