lejp-conf.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993
  1. /*
  2. * libwebsockets web server application
  3. *
  4. * Copyright (C) 2010-2017 Andy Green <[email protected]>
  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. #include "core/private.h"
  22. #ifndef _WIN32
  23. /* this is needed for Travis CI */
  24. #include <dirent.h>
  25. #endif
  26. #define ESC_INSTALL_DATADIR "_lws_ddir_"
  27. static const char * const paths_global[] = {
  28. "global.uid",
  29. "global.gid",
  30. "global.count-threads",
  31. "global.init-ssl",
  32. "global.server-string",
  33. "global.plugin-dir",
  34. "global.ws-pingpong-secs",
  35. "global.timeout-secs",
  36. "global.reject-service-keywords[].*",
  37. "global.reject-service-keywords[]",
  38. "global.default-alpn",
  39. };
  40. enum lejp_global_paths {
  41. LEJPGP_UID,
  42. LEJPGP_GID,
  43. LEJPGP_COUNT_THREADS,
  44. LWJPGP_INIT_SSL,
  45. LEJPGP_SERVER_STRING,
  46. LEJPGP_PLUGIN_DIR,
  47. LWJPGP_PINGPONG_SECS,
  48. LWJPGP_TIMEOUT_SECS,
  49. LWJPGP_REJECT_SERVICE_KEYWORDS_NAME,
  50. LWJPGP_REJECT_SERVICE_KEYWORDS,
  51. LWJPGP_DEFAULT_ALPN,
  52. };
  53. static const char * const paths_vhosts[] = {
  54. "vhosts[]",
  55. "vhosts[].mounts[]",
  56. "vhosts[].name",
  57. "vhosts[].port",
  58. "vhosts[].interface",
  59. "vhosts[].unix-socket",
  60. "vhosts[].sts",
  61. "vhosts[].host-ssl-key",
  62. "vhosts[].host-ssl-cert",
  63. "vhosts[].host-ssl-ca",
  64. "vhosts[].access-log",
  65. "vhosts[].mounts[].mountpoint",
  66. "vhosts[].mounts[].origin",
  67. "vhosts[].mounts[].protocol",
  68. "vhosts[].mounts[].default",
  69. "vhosts[].mounts[].auth-mask",
  70. "vhosts[].mounts[].cgi-timeout",
  71. "vhosts[].mounts[].cgi-env[].*",
  72. "vhosts[].mounts[].cache-max-age",
  73. "vhosts[].mounts[].cache-reuse",
  74. "vhosts[].mounts[].cache-revalidate",
  75. "vhosts[].mounts[].basic-auth",
  76. "vhosts[].mounts[].cache-intermediaries",
  77. "vhosts[].mounts[].extra-mimetypes.*",
  78. "vhosts[].mounts[].interpret.*",
  79. "vhosts[].ws-protocols[].*.*",
  80. "vhosts[].ws-protocols[].*",
  81. "vhosts[].ws-protocols[]",
  82. "vhosts[].keepalive_timeout",
  83. "vhosts[].enable-client-ssl",
  84. "vhosts[].ciphers",
  85. "vhosts[].ecdh-curve",
  86. "vhosts[].noipv6",
  87. "vhosts[].ipv6only",
  88. "vhosts[].ssl-option-set",
  89. "vhosts[].ssl-option-clear",
  90. "vhosts[].mounts[].pmo[].*",
  91. "vhosts[].headers[].*",
  92. "vhosts[].headers[]",
  93. "vhosts[].client-ssl-key",
  94. "vhosts[].client-ssl-cert",
  95. "vhosts[].client-ssl-ca",
  96. "vhosts[].client-ssl-ciphers",
  97. "vhosts[].onlyraw",
  98. "vhosts[].client-cert-required",
  99. "vhosts[].ignore-missing-cert",
  100. "vhosts[].error-document-404",
  101. "vhosts[].alpn",
  102. };
  103. enum lejp_vhost_paths {
  104. LEJPVP,
  105. LEJPVP_MOUNTS,
  106. LEJPVP_NAME,
  107. LEJPVP_PORT,
  108. LEJPVP_INTERFACE,
  109. LEJPVP_UNIXSKT,
  110. LEJPVP_STS,
  111. LEJPVP_HOST_SSL_KEY,
  112. LEJPVP_HOST_SSL_CERT,
  113. LEJPVP_HOST_SSL_CA,
  114. LEJPVP_ACCESS_LOG,
  115. LEJPVP_MOUNTPOINT,
  116. LEJPVP_ORIGIN,
  117. LEJPVP_MOUNT_PROTOCOL,
  118. LEJPVP_DEFAULT,
  119. LEJPVP_DEFAULT_AUTH_MASK,
  120. LEJPVP_CGI_TIMEOUT,
  121. LEJPVP_CGI_ENV,
  122. LEJPVP_MOUNT_CACHE_MAX_AGE,
  123. LEJPVP_MOUNT_CACHE_REUSE,
  124. LEJPVP_MOUNT_CACHE_REVALIDATE,
  125. LEJPVP_MOUNT_BASIC_AUTH,
  126. LEJPVP_MOUNT_CACHE_INTERMEDIARIES,
  127. LEJPVP_MOUNT_EXTRA_MIMETYPES,
  128. LEJPVP_MOUNT_INTERPRET,
  129. LEJPVP_PROTOCOL_NAME_OPT,
  130. LEJPVP_PROTOCOL_NAME,
  131. LEJPVP_PROTOCOL,
  132. LEJPVP_KEEPALIVE_TIMEOUT,
  133. LEJPVP_ENABLE_CLIENT_SSL,
  134. LEJPVP_CIPHERS,
  135. LEJPVP_ECDH_CURVE,
  136. LEJPVP_NOIPV6,
  137. LEJPVP_IPV6ONLY,
  138. LEJPVP_SSL_OPTION_SET,
  139. LEJPVP_SSL_OPTION_CLEAR,
  140. LEJPVP_PMO,
  141. LEJPVP_HEADERS_NAME,
  142. LEJPVP_HEADERS,
  143. LEJPVP_CLIENT_SSL_KEY,
  144. LEJPVP_CLIENT_SSL_CERT,
  145. LEJPVP_CLIENT_SSL_CA,
  146. LEJPVP_CLIENT_CIPHERS,
  147. LEJPVP_FLAG_ONLYRAW,
  148. LEJPVP_FLAG_CLIENT_CERT_REQUIRED,
  149. LEJPVP_IGNORE_MISSING_CERT,
  150. LEJPVP_ERROR_DOCUMENT_404,
  151. LEJPVP_ALPN,
  152. };
  153. static const char * const parser_errs[] = {
  154. "",
  155. "",
  156. "No opening '{'",
  157. "Expected closing '}'",
  158. "Expected '\"'",
  159. "String underrun",
  160. "Illegal unescaped control char",
  161. "Illegal escape format",
  162. "Illegal hex number",
  163. "Expected ':'",
  164. "Illegal value start",
  165. "Digit required after decimal point",
  166. "Bad number format",
  167. "Bad exponent format",
  168. "Unknown token",
  169. "Too many ']'",
  170. "Mismatched ']'",
  171. "Expected ']'",
  172. "JSON nesting limit exceeded",
  173. "Nesting tracking used up",
  174. "Number too long",
  175. "Comma or block end expected",
  176. "Unknown",
  177. "Parser callback errored (see earlier error)",
  178. };
  179. #define MAX_PLUGIN_DIRS 10
  180. struct jpargs {
  181. struct lws_context_creation_info *info;
  182. struct lws_context *context;
  183. const struct lws_protocols *protocols;
  184. const struct lws_extension *extensions;
  185. char *p, *end, valid;
  186. struct lws_http_mount *head, *last;
  187. struct lws_protocol_vhost_options *pvo;
  188. struct lws_protocol_vhost_options *pvo_em;
  189. struct lws_protocol_vhost_options *pvo_int;
  190. struct lws_http_mount m;
  191. const char **plugin_dirs;
  192. int count_plugin_dirs;
  193. unsigned int enable_client_ssl:1;
  194. unsigned int fresh_mount:1;
  195. unsigned int any_vhosts:1;
  196. unsigned int chunk:1;
  197. };
  198. static void *
  199. lwsws_align(struct jpargs *a)
  200. {
  201. if ((lws_intptr_t)(a->p) & 15)
  202. a->p += 16 - ((lws_intptr_t)(a->p) & 15);
  203. a->chunk = 0;
  204. return a->p;
  205. }
  206. static int
  207. arg_to_bool(const char *s)
  208. {
  209. static const char * const on[] = { "on", "yes", "true" };
  210. int n = atoi(s);
  211. if (n)
  212. return 1;
  213. for (n = 0; n < (int)LWS_ARRAY_SIZE(on); n++)
  214. if (!strcasecmp(s, on[n]))
  215. return 1;
  216. return 0;
  217. }
  218. static signed char
  219. lejp_globals_cb(struct lejp_ctx *ctx, char reason)
  220. {
  221. struct jpargs *a = (struct jpargs *)ctx->user;
  222. struct lws_protocol_vhost_options *rej;
  223. int n;
  224. /* we only match on the prepared path strings */
  225. if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match)
  226. return 0;
  227. /* this catches, eg, vhosts[].headers[].xxx */
  228. if (reason == LEJPCB_VAL_STR_END &&
  229. ctx->path_match == LWJPGP_REJECT_SERVICE_KEYWORDS_NAME + 1) {
  230. rej = lwsws_align(a);
  231. a->p += sizeof(*rej);
  232. n = lejp_get_wildcard(ctx, 0, a->p, a->end - a->p);
  233. rej->next = a->info->reject_service_keywords;
  234. a->info->reject_service_keywords = rej;
  235. rej->name = a->p;
  236. lwsl_notice(" adding rej %s=%s\n", a->p, ctx->buf);
  237. a->p += n - 1;
  238. *(a->p++) = '\0';
  239. rej->value = a->p;
  240. rej->options = NULL;
  241. goto dostring;
  242. }
  243. switch (ctx->path_match - 1) {
  244. case LEJPGP_UID:
  245. a->info->uid = atoi(ctx->buf);
  246. return 0;
  247. case LEJPGP_GID:
  248. a->info->gid = atoi(ctx->buf);
  249. return 0;
  250. case LEJPGP_COUNT_THREADS:
  251. a->info->count_threads = atoi(ctx->buf);
  252. return 0;
  253. case LWJPGP_INIT_SSL:
  254. if (arg_to_bool(ctx->buf))
  255. a->info->options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
  256. return 0;
  257. case LEJPGP_SERVER_STRING:
  258. a->info->server_string = a->p;
  259. break;
  260. case LEJPGP_PLUGIN_DIR:
  261. if (a->count_plugin_dirs == MAX_PLUGIN_DIRS - 1) {
  262. lwsl_err("Too many plugin dirs\n");
  263. return -1;
  264. }
  265. a->plugin_dirs[a->count_plugin_dirs++] = a->p;
  266. break;
  267. case LWJPGP_PINGPONG_SECS:
  268. a->info->ws_ping_pong_interval = atoi(ctx->buf);
  269. return 0;
  270. case LWJPGP_TIMEOUT_SECS:
  271. a->info->timeout_secs = atoi(ctx->buf);
  272. return 0;
  273. case LWJPGP_DEFAULT_ALPN:
  274. a->info->alpn = a->p;
  275. break;
  276. default:
  277. return 0;
  278. }
  279. dostring:
  280. a->p += lws_snprintf(a->p, a->end - a->p, "%s", ctx->buf);
  281. *(a->p)++ = '\0';
  282. return 0;
  283. }
  284. static signed char
  285. lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
  286. {
  287. struct jpargs *a = (struct jpargs *)ctx->user;
  288. struct lws_protocol_vhost_options *pvo, *mp_cgienv, *headers;
  289. struct lws_http_mount *m;
  290. char *p, *p1;
  291. int n;
  292. #if 0
  293. lwsl_notice(" %d: %s (%d)\n", reason, ctx->path, ctx->path_match);
  294. for (n = 0; n < ctx->wildcount; n++)
  295. lwsl_notice(" %d\n", ctx->wild[n]);
  296. #endif
  297. if (reason == LEJPCB_OBJECT_START && ctx->path_match == LEJPVP + 1) {
  298. uint32_t i[4];
  299. const char *ss;
  300. /* set the defaults for this vhost */
  301. a->valid = 1;
  302. a->head = NULL;
  303. a->last = NULL;
  304. i[0] = a->info->count_threads;
  305. i[1] = a->info->options & (
  306. LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME |
  307. LWS_SERVER_OPTION_LIBUV |
  308. LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT |
  309. LWS_SERVER_OPTION_EXPLICIT_VHOSTS |
  310. LWS_SERVER_OPTION_UV_NO_SIGSEGV_SIGFPE_SPIN |
  311. LWS_SERVER_OPTION_LIBEVENT |
  312. LWS_SERVER_OPTION_LIBEV
  313. );
  314. ss = a->info->server_string;
  315. i[2] = a->info->ws_ping_pong_interval;
  316. i[3] = a->info->timeout_secs;
  317. memset(a->info, 0, sizeof(*a->info));
  318. a->info->count_threads = i[0];
  319. a->info->options = i[1];
  320. a->info->server_string = ss;
  321. a->info->ws_ping_pong_interval = i[2];
  322. a->info->timeout_secs = i[3];
  323. a->info->protocols = a->protocols;
  324. a->info->extensions = a->extensions;
  325. #if defined(LWS_WITH_TLS)
  326. a->info->client_ssl_cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:"
  327. "ECDHE-RSA-AES256-GCM-SHA384:"
  328. "DHE-RSA-AES256-GCM-SHA384:"
  329. "ECDHE-RSA-AES256-SHA384:"
  330. "HIGH:!aNULL:!eNULL:!EXPORT:"
  331. "!DES:!MD5:!PSK:!RC4:!HMAC_SHA1:"
  332. "!SHA1:!DHE-RSA-AES128-GCM-SHA256:"
  333. "!DHE-RSA-AES128-SHA256:"
  334. "!AES128-GCM-SHA256:"
  335. "!AES128-SHA256:"
  336. "!DHE-RSA-AES256-SHA256:"
  337. "!AES256-GCM-SHA384:"
  338. "!AES256-SHA256";
  339. #endif
  340. a->info->ssl_cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:"
  341. "ECDHE-RSA-AES256-GCM-SHA384:"
  342. "DHE-RSA-AES256-GCM-SHA384:"
  343. "ECDHE-RSA-AES256-SHA384:"
  344. "HIGH:!aNULL:!eNULL:!EXPORT:"
  345. "!DES:!MD5:!PSK:!RC4:!HMAC_SHA1:"
  346. "!SHA1:!DHE-RSA-AES128-GCM-SHA256:"
  347. "!DHE-RSA-AES128-SHA256:"
  348. "!AES128-GCM-SHA256:"
  349. "!AES128-SHA256:"
  350. "!DHE-RSA-AES256-SHA256:"
  351. "!AES256-GCM-SHA384:"
  352. "!AES256-SHA256";
  353. a->info->keepalive_timeout = 5;
  354. }
  355. if (reason == LEJPCB_OBJECT_START &&
  356. ctx->path_match == LEJPVP_MOUNTS + 1) {
  357. a->fresh_mount = 1;
  358. memset(&a->m, 0, sizeof(a->m));
  359. }
  360. /* this catches, eg, vhosts[].ws-protocols[].xxx-protocol */
  361. if (reason == LEJPCB_OBJECT_START &&
  362. ctx->path_match == LEJPVP_PROTOCOL_NAME + 1) {
  363. a->pvo = lwsws_align(a);
  364. a->p += sizeof(*a->pvo);
  365. n = lejp_get_wildcard(ctx, 0, a->p, a->end - a->p);
  366. /* ie, enable this protocol, no options yet */
  367. a->pvo->next = a->info->pvo;
  368. a->info->pvo = a->pvo;
  369. a->pvo->name = a->p;
  370. lwsl_info(" adding protocol %s\n", a->p);
  371. a->p += n;
  372. a->pvo->value = a->p;
  373. a->pvo->options = NULL;
  374. goto dostring;
  375. }
  376. /* this catches, eg, vhosts[].headers[].xxx */
  377. if ((reason == LEJPCB_VAL_STR_END || reason == LEJPCB_VAL_STR_CHUNK) &&
  378. ctx->path_match == LEJPVP_HEADERS_NAME + 1) {
  379. if (!a->chunk) {
  380. headers = lwsws_align(a);
  381. a->p += sizeof(*headers);
  382. n = lejp_get_wildcard(ctx, 0, a->p,
  383. lws_ptr_diff(a->end, a->p));
  384. /* ie, add this header */
  385. headers->next = a->info->headers;
  386. a->info->headers = headers;
  387. headers->name = a->p;
  388. lwsl_notice(" adding header %s=%s\n", a->p, ctx->buf);
  389. a->p += n - 1;
  390. *(a->p++) = ':';
  391. if (a->p < a->end)
  392. *(a->p++) = '\0';
  393. else
  394. *(a->p - 1) = '\0';
  395. headers->value = a->p;
  396. headers->options = NULL;
  397. }
  398. a->chunk = reason == LEJPCB_VAL_STR_CHUNK;
  399. goto dostring;
  400. }
  401. if (reason == LEJPCB_OBJECT_END &&
  402. (ctx->path_match == LEJPVP + 1 || !ctx->path[0]) &&
  403. a->valid) {
  404. struct lws_vhost *vhost;
  405. //lwsl_notice("%s\n", ctx->path);
  406. if (!a->info->port) {
  407. lwsl_err("Port required (eg, 443)");
  408. return 1;
  409. }
  410. a->valid = 0;
  411. a->info->mounts = a->head;
  412. vhost = lws_create_vhost(a->context, a->info);
  413. if (!vhost) {
  414. lwsl_err("Failed to create vhost %s\n",
  415. a->info->vhost_name);
  416. return 1;
  417. }
  418. a->any_vhosts = 1;
  419. #if defined(LWS_WITH_TLS)
  420. if (a->enable_client_ssl) {
  421. const char *cert_filepath = a->info->client_ssl_cert_filepath;
  422. const char *private_key_filepath = a->info->client_ssl_private_key_filepath;
  423. const char *ca_filepath = a->info->client_ssl_ca_filepath;
  424. const char *cipher_list = a->info->client_ssl_cipher_list;
  425. memset(a->info, 0, sizeof(*a->info));
  426. a->info->client_ssl_cert_filepath = cert_filepath;
  427. a->info->client_ssl_private_key_filepath = private_key_filepath;
  428. a->info->client_ssl_ca_filepath = ca_filepath;
  429. a->info->client_ssl_cipher_list = cipher_list;
  430. a->info->options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
  431. lws_init_vhost_client_ssl(a->info, vhost);
  432. }
  433. #endif
  434. return 0;
  435. }
  436. if (reason == LEJPCB_OBJECT_END &&
  437. ctx->path_match == LEJPVP_MOUNTS + 1) {
  438. static const char * const mount_protocols[] = {
  439. "http://",
  440. "https://",
  441. "file://",
  442. "cgi://",
  443. ">http://",
  444. ">https://",
  445. "callback://",
  446. "gzip://",
  447. };
  448. if (!a->fresh_mount)
  449. return 0;
  450. if (!a->m.mountpoint || !a->m.origin) {
  451. lwsl_err("mountpoint and origin required\n");
  452. return 1;
  453. }
  454. lwsl_debug("adding mount %s\n", a->m.mountpoint);
  455. m = lwsws_align(a);
  456. memcpy(m, &a->m, sizeof(*m));
  457. if (a->last)
  458. a->last->mount_next = m;
  459. for (n = 0; n < (int)LWS_ARRAY_SIZE(mount_protocols); n++)
  460. if (!strncmp(a->m.origin, mount_protocols[n],
  461. strlen(mount_protocols[n]))) {
  462. lwsl_info("----%s\n", a->m.origin);
  463. m->origin_protocol = n;
  464. m->origin = a->m.origin +
  465. strlen(mount_protocols[n]);
  466. break;
  467. }
  468. if (n == (int)LWS_ARRAY_SIZE(mount_protocols)) {
  469. lwsl_err("unsupported protocol:// %s\n", a->m.origin);
  470. return 1;
  471. }
  472. a->p += sizeof(*m);
  473. if (!a->head)
  474. a->head = m;
  475. a->last = m;
  476. a->fresh_mount = 0;
  477. }
  478. /* we only match on the prepared path strings */
  479. if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match)
  480. return 0;
  481. switch (ctx->path_match - 1) {
  482. case LEJPVP_NAME:
  483. a->info->vhost_name = a->p;
  484. break;
  485. case LEJPVP_PORT:
  486. a->info->port = atoi(ctx->buf);
  487. return 0;
  488. case LEJPVP_INTERFACE:
  489. a->info->iface = a->p;
  490. break;
  491. case LEJPVP_UNIXSKT:
  492. if (arg_to_bool(ctx->buf))
  493. a->info->options |= LWS_SERVER_OPTION_UNIX_SOCK;
  494. else
  495. a->info->options &= ~(LWS_SERVER_OPTION_UNIX_SOCK);
  496. return 0;
  497. case LEJPVP_STS:
  498. if (arg_to_bool(ctx->buf))
  499. a->info->options |= LWS_SERVER_OPTION_STS;
  500. else
  501. a->info->options &= ~(LWS_SERVER_OPTION_STS);
  502. return 0;
  503. case LEJPVP_HOST_SSL_KEY:
  504. a->info->ssl_private_key_filepath = a->p;
  505. break;
  506. case LEJPVP_HOST_SSL_CERT:
  507. a->info->ssl_cert_filepath = a->p;
  508. break;
  509. case LEJPVP_HOST_SSL_CA:
  510. a->info->ssl_ca_filepath = a->p;
  511. break;
  512. case LEJPVP_ACCESS_LOG:
  513. a->info->log_filepath = a->p;
  514. break;
  515. case LEJPVP_MOUNTPOINT:
  516. a->m.mountpoint = a->p;
  517. a->m.mountpoint_len = (unsigned char)strlen(ctx->buf);
  518. break;
  519. case LEJPVP_ORIGIN:
  520. if (!strncmp(ctx->buf, "callback://", 11))
  521. a->m.protocol = a->p + 11;
  522. if (!a->m.origin)
  523. a->m.origin = a->p;
  524. break;
  525. case LEJPVP_DEFAULT:
  526. a->m.def = a->p;
  527. break;
  528. case LEJPVP_DEFAULT_AUTH_MASK:
  529. a->m.auth_mask = atoi(ctx->buf);
  530. return 0;
  531. case LEJPVP_MOUNT_CACHE_MAX_AGE:
  532. a->m.cache_max_age = atoi(ctx->buf);
  533. return 0;
  534. case LEJPVP_MOUNT_CACHE_REUSE:
  535. a->m.cache_reusable = arg_to_bool(ctx->buf);
  536. return 0;
  537. case LEJPVP_MOUNT_CACHE_REVALIDATE:
  538. a->m.cache_revalidate = arg_to_bool(ctx->buf);
  539. return 0;
  540. case LEJPVP_MOUNT_CACHE_INTERMEDIARIES:
  541. a->m.cache_intermediaries = arg_to_bool(ctx->buf);;
  542. return 0;
  543. case LEJPVP_MOUNT_BASIC_AUTH:
  544. a->m.basic_auth_login_file = a->p;
  545. break;
  546. case LEJPVP_CGI_TIMEOUT:
  547. a->m.cgi_timeout = atoi(ctx->buf);
  548. return 0;
  549. case LEJPVP_KEEPALIVE_TIMEOUT:
  550. a->info->keepalive_timeout = atoi(ctx->buf);
  551. return 0;
  552. #if defined(LWS_WITH_TLS)
  553. case LEJPVP_CLIENT_CIPHERS:
  554. a->info->client_ssl_cipher_list = a->p;
  555. break;
  556. #endif
  557. case LEJPVP_CIPHERS:
  558. a->info->ssl_cipher_list = a->p;
  559. break;
  560. case LEJPVP_ECDH_CURVE:
  561. a->info->ecdh_curve = a->p;
  562. break;
  563. case LEJPVP_PMO:
  564. case LEJPVP_CGI_ENV:
  565. mp_cgienv = lwsws_align(a);
  566. a->p += sizeof(*a->m.cgienv);
  567. mp_cgienv->next = a->m.cgienv;
  568. a->m.cgienv = mp_cgienv;
  569. n = lejp_get_wildcard(ctx, 0, a->p, a->end - a->p);
  570. mp_cgienv->name = a->p;
  571. a->p += n;
  572. mp_cgienv->value = a->p;
  573. mp_cgienv->options = NULL;
  574. //lwsl_notice(" adding pmo / cgi-env '%s' = '%s'\n", mp_cgienv->name,
  575. // mp_cgienv->value);
  576. goto dostring;
  577. case LEJPVP_PROTOCOL_NAME_OPT:
  578. /* this catches, eg,
  579. * vhosts[].ws-protocols[].xxx-protocol.yyy-option
  580. * ie, these are options attached to a protocol with { }
  581. */
  582. pvo = lwsws_align(a);
  583. a->p += sizeof(*a->pvo);
  584. n = lejp_get_wildcard(ctx, 1, a->p, a->end - a->p);
  585. /* ie, enable this protocol, no options yet */
  586. pvo->next = a->pvo->options;
  587. a->pvo->options = pvo;
  588. pvo->name = a->p;
  589. a->p += n;
  590. pvo->value = a->p;
  591. pvo->options = NULL;
  592. break;
  593. case LEJPVP_MOUNT_EXTRA_MIMETYPES:
  594. a->pvo_em = lwsws_align(a);
  595. a->p += sizeof(*a->pvo_em);
  596. n = lejp_get_wildcard(ctx, 0, a->p, a->end - a->p);
  597. /* ie, enable this protocol, no options yet */
  598. a->pvo_em->next = a->m.extra_mimetypes;
  599. a->m.extra_mimetypes = a->pvo_em;
  600. a->pvo_em->name = a->p;
  601. lwsl_notice(" adding extra-mimetypes %s -> %s\n", a->p, ctx->buf);
  602. a->p += n;
  603. a->pvo_em->value = a->p;
  604. a->pvo_em->options = NULL;
  605. break;
  606. case LEJPVP_MOUNT_INTERPRET:
  607. a->pvo_int = lwsws_align(a);
  608. a->p += sizeof(*a->pvo_int);
  609. n = lejp_get_wildcard(ctx, 0, a->p, a->end - a->p);
  610. /* ie, enable this protocol, no options yet */
  611. a->pvo_int->next = a->m.interpret;
  612. a->m.interpret = a->pvo_int;
  613. a->pvo_int->name = a->p;
  614. lwsl_notice(" adding interpret %s -> %s\n", a->p,
  615. ctx->buf);
  616. a->p += n;
  617. a->pvo_int->value = a->p;
  618. a->pvo_int->options = NULL;
  619. break;
  620. case LEJPVP_ENABLE_CLIENT_SSL:
  621. a->enable_client_ssl = arg_to_bool(ctx->buf);
  622. return 0;
  623. #if defined(LWS_WITH_TLS)
  624. case LEJPVP_CLIENT_SSL_KEY:
  625. a->info->client_ssl_private_key_filepath = a->p;
  626. break;
  627. case LEJPVP_CLIENT_SSL_CERT:
  628. a->info->client_ssl_cert_filepath = a->p;
  629. break;
  630. case LEJPVP_CLIENT_SSL_CA:
  631. a->info->client_ssl_ca_filepath = a->p;
  632. break;
  633. #endif
  634. case LEJPVP_NOIPV6:
  635. if (arg_to_bool(ctx->buf))
  636. a->info->options |= LWS_SERVER_OPTION_DISABLE_IPV6;
  637. else
  638. a->info->options &= ~(LWS_SERVER_OPTION_DISABLE_IPV6);
  639. return 0;
  640. case LEJPVP_FLAG_ONLYRAW:
  641. if (arg_to_bool(ctx->buf))
  642. a->info->options |= LWS_SERVER_OPTION_ONLY_RAW;
  643. else
  644. a->info->options &= ~(LWS_SERVER_OPTION_ONLY_RAW);
  645. return 0;
  646. case LEJPVP_IPV6ONLY:
  647. a->info->options |= LWS_SERVER_OPTION_IPV6_V6ONLY_MODIFY;
  648. if (arg_to_bool(ctx->buf))
  649. a->info->options |= LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE;
  650. else
  651. a->info->options &= ~(LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE);
  652. return 0;
  653. case LEJPVP_FLAG_CLIENT_CERT_REQUIRED:
  654. if (arg_to_bool(ctx->buf))
  655. a->info->options |=
  656. LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;
  657. return 0;
  658. case LEJPVP_IGNORE_MISSING_CERT:
  659. if (arg_to_bool(ctx->buf))
  660. a->info->options |= LWS_SERVER_OPTION_IGNORE_MISSING_CERT;
  661. else
  662. a->info->options &= ~(LWS_SERVER_OPTION_IGNORE_MISSING_CERT);
  663. return 0;
  664. case LEJPVP_ERROR_DOCUMENT_404:
  665. a->info->error_document_404 = a->p;
  666. break;
  667. case LEJPVP_SSL_OPTION_SET:
  668. a->info->ssl_options_set |= atol(ctx->buf);
  669. return 0;
  670. case LEJPVP_SSL_OPTION_CLEAR:
  671. a->info->ssl_options_clear |= atol(ctx->buf);
  672. return 0;
  673. case LEJPVP_ALPN:
  674. a->info->alpn = a->p;
  675. break;
  676. default:
  677. return 0;
  678. }
  679. dostring:
  680. p = ctx->buf;
  681. p[LEJP_STRING_CHUNK] = '\0';
  682. p1 = strstr(p, ESC_INSTALL_DATADIR);
  683. if (p1) {
  684. n = p1 - p;
  685. if (n > a->end - a->p)
  686. n = a->end - a->p;
  687. lws_strncpy(a->p, p, n + 1);
  688. a->p += n;
  689. a->p += lws_snprintf(a->p, a->end - a->p, "%s", LWS_INSTALL_DATADIR);
  690. p += n + strlen(ESC_INSTALL_DATADIR);
  691. }
  692. a->p += lws_snprintf(a->p, a->end - a->p, "%s", p);
  693. if (reason == LEJPCB_VAL_STR_END)
  694. *(a->p)++ = '\0';
  695. return 0;
  696. }
  697. /*
  698. * returns 0 = OK, 1 = can't open, 2 = parsing error
  699. */
  700. static int
  701. lwsws_get_config(void *user, const char *f, const char * const *paths,
  702. int count_paths, lejp_callback cb)
  703. {
  704. unsigned char buf[128];
  705. struct lejp_ctx ctx;
  706. int n, m, fd;
  707. fd = lws_open(f, O_RDONLY);
  708. if (fd < 0) {
  709. lwsl_err("Cannot open %s\n", f);
  710. return 2;
  711. }
  712. lwsl_info("%s: %s\n", __func__, f);
  713. lejp_construct(&ctx, cb, user, paths, count_paths);
  714. do {
  715. n = read(fd, buf, sizeof(buf));
  716. if (!n)
  717. break;
  718. m = (int)(signed char)lejp_parse(&ctx, buf, n);
  719. } while (m == LEJP_CONTINUE);
  720. close(fd);
  721. n = ctx.line;
  722. lejp_destruct(&ctx);
  723. if (m < 0) {
  724. lwsl_err("%s(%u): parsing error %d: %s\n", f, n, m,
  725. parser_errs[-m]);
  726. return 2;
  727. }
  728. return 0;
  729. }
  730. #if defined(LWS_WITH_LIBUV) && UV_VERSION_MAJOR > 0
  731. static int
  732. lwsws_get_config_d(void *user, const char *d, const char * const *paths,
  733. int count_paths, lejp_callback cb)
  734. {
  735. uv_dirent_t dent;
  736. uv_fs_t req;
  737. char path[256];
  738. int ret = 0, ir;
  739. uv_loop_t loop;
  740. ir = uv_loop_init(&loop);
  741. if (ir) {
  742. lwsl_err("%s: loop init failed %d\n", __func__, ir);
  743. }
  744. if (!uv_fs_scandir(&loop, &req, d, 0, NULL)) {
  745. lwsl_err("Scandir on %s failed\n", d);
  746. return 2;
  747. }
  748. while (uv_fs_scandir_next(&req, &dent) != UV_EOF) {
  749. lws_snprintf(path, sizeof(path) - 1, "%s/%s", d, dent.name);
  750. ret = lwsws_get_config(user, path, paths, count_paths, cb);
  751. if (ret)
  752. goto bail;
  753. }
  754. bail:
  755. uv_fs_req_cleanup(&req);
  756. while (uv_loop_close(&loop))
  757. ;
  758. return ret;
  759. }
  760. #else
  761. #ifndef _WIN32
  762. static int filter(const struct dirent *ent)
  763. {
  764. if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
  765. return 0;
  766. return 1;
  767. }
  768. #endif
  769. static int
  770. lwsws_get_config_d(void *user, const char *d, const char * const *paths,
  771. int count_paths, lejp_callback cb)
  772. {
  773. #ifndef _WIN32
  774. struct dirent **namelist;
  775. char path[256];
  776. int n, i, ret = 0;
  777. n = scandir(d, &namelist, filter, alphasort);
  778. if (n < 0) {
  779. lwsl_err("Scandir on %s failed\n", d);
  780. return 1;
  781. }
  782. for (i = 0; i < n; i++) {
  783. if (strchr(namelist[i]->d_name, '~'))
  784. goto skip;
  785. lws_snprintf(path, sizeof(path) - 1, "%s/%s", d,
  786. namelist[i]->d_name);
  787. ret = lwsws_get_config(user, path, paths, count_paths, cb);
  788. if (ret) {
  789. while (i++ < n)
  790. free(namelist[i]);
  791. goto bail;
  792. }
  793. skip:
  794. free(namelist[i]);
  795. }
  796. bail:
  797. free(namelist);
  798. return ret;
  799. #else
  800. return 0;
  801. #endif
  802. }
  803. #endif
  804. int
  805. lwsws_get_config_globals(struct lws_context_creation_info *info, const char *d,
  806. char **cs, int *len)
  807. {
  808. struct jpargs a;
  809. const char * const *old = info->plugin_dirs;
  810. char dd[128];
  811. memset(&a, 0, sizeof(a));
  812. a.info = info;
  813. a.p = *cs;
  814. a.end = (a.p + *len) - 1;
  815. a.valid = 0;
  816. lwsws_align(&a);
  817. info->plugin_dirs = (void *)a.p;
  818. a.plugin_dirs = (void *)a.p; /* writeable version */
  819. a.p += MAX_PLUGIN_DIRS * sizeof(void *);
  820. /* copy any default paths */
  821. while (old && *old) {
  822. a.plugin_dirs[a.count_plugin_dirs++] = *old;
  823. old++;
  824. }
  825. lws_snprintf(dd, sizeof(dd) - 1, "%s/conf", d);
  826. if (lwsws_get_config(&a, dd, paths_global,
  827. LWS_ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
  828. return 1;
  829. lws_snprintf(dd, sizeof(dd) - 1, "%s/conf.d", d);
  830. if (lwsws_get_config_d(&a, dd, paths_global,
  831. LWS_ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
  832. return 1;
  833. a.plugin_dirs[a.count_plugin_dirs] = NULL;
  834. *cs = a.p;
  835. *len = a.end - a.p;
  836. return 0;
  837. }
  838. int
  839. lwsws_get_config_vhosts(struct lws_context *context,
  840. struct lws_context_creation_info *info, const char *d,
  841. char **cs, int *len)
  842. {
  843. struct jpargs a;
  844. char dd[128];
  845. memset(&a, 0, sizeof(a));
  846. a.info = info;
  847. a.p = *cs;
  848. a.end = a.p + *len;
  849. a.valid = 0;
  850. a.context = context;
  851. a.protocols = info->protocols;
  852. a.extensions = info->extensions;
  853. lws_snprintf(dd, sizeof(dd) - 1, "%s/conf", d);
  854. if (lwsws_get_config(&a, dd, paths_vhosts,
  855. LWS_ARRAY_SIZE(paths_vhosts), lejp_vhosts_cb) > 1)
  856. return 1;
  857. lws_snprintf(dd, sizeof(dd) - 1, "%s/conf.d", d);
  858. if (lwsws_get_config_d(&a, dd, paths_vhosts,
  859. LWS_ARRAY_SIZE(paths_vhosts), lejp_vhosts_cb) > 1)
  860. return 1;
  861. *cs = a.p;
  862. *len = a.end - a.p;
  863. if (!a.any_vhosts) {
  864. lwsl_err("Need at least one vhost\n");
  865. return 1;
  866. }
  867. // lws_finalize_startup(context);
  868. return 0;
  869. }