lejp-conf.c 19 KB

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