lejp-conf.c 22 KB

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