parsers.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010-2018 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. static const unsigned char lextable[] = {
  23. #include "../lextable.h"
  24. };
  25. #define FAIL_CHAR 0x08
  26. static struct allocated_headers *
  27. _lws_create_ah(struct lws_context_per_thread *pt, ah_data_idx_t data_size)
  28. {
  29. struct allocated_headers *ah = lws_zalloc(sizeof(*ah), "ah struct");
  30. if (!ah)
  31. return NULL;
  32. ah->data = lws_malloc(data_size, "ah data");
  33. if (!ah->data) {
  34. lws_free(ah);
  35. return NULL;
  36. }
  37. ah->next = pt->http.ah_list;
  38. pt->http.ah_list = ah;
  39. ah->data_length = data_size;
  40. pt->http.ah_pool_length++;
  41. lwsl_info("%s: created ah %p (size %d): pool length %d\n", __func__,
  42. ah, (int)data_size, pt->http.ah_pool_length);
  43. return ah;
  44. }
  45. int
  46. _lws_destroy_ah(struct lws_context_per_thread *pt, struct allocated_headers *ah)
  47. {
  48. lws_start_foreach_llp(struct allocated_headers **, a, pt->http.ah_list) {
  49. if ((*a) == ah) {
  50. *a = ah->next;
  51. pt->http.ah_pool_length--;
  52. lwsl_info("%s: freed ah %p : pool length %d\n",
  53. __func__, ah, pt->http.ah_pool_length);
  54. if (ah->data)
  55. lws_free(ah->data);
  56. lws_free(ah);
  57. return 0;
  58. }
  59. } lws_end_foreach_llp(a, next);
  60. return 1;
  61. }
  62. void
  63. _lws_header_table_reset(struct allocated_headers *ah)
  64. {
  65. /* init the ah to reflect no headers or data have appeared yet */
  66. memset(ah->frag_index, 0, sizeof(ah->frag_index));
  67. memset(ah->frags, 0, sizeof(ah->frags));
  68. ah->nfrag = 0;
  69. ah->pos = 0;
  70. ah->http_response = 0;
  71. ah->parser_state = WSI_TOKEN_NAME_PART;
  72. ah->lextable_pos = 0;
  73. }
  74. // doesn't scrub the ah rxbuffer by default, parent must do if needed
  75. void
  76. __lws_header_table_reset(struct lws *wsi, int autoservice)
  77. {
  78. struct allocated_headers *ah = wsi->http.ah;
  79. struct lws_context_per_thread *pt;
  80. struct lws_pollfd *pfd;
  81. /* if we have the idea we're resetting 'our' ah, must be bound to one */
  82. assert(ah);
  83. /* ah also concurs with ownership */
  84. assert(ah->wsi == wsi);
  85. _lws_header_table_reset(ah);
  86. /* since we will restart the ah, our new headers are not completed */
  87. wsi->hdr_parsing_completed = 0;
  88. /* while we hold the ah, keep a timeout on the wsi */
  89. __lws_set_timeout(wsi, PENDING_TIMEOUT_HOLDING_AH,
  90. wsi->vhost->timeout_secs_ah_idle);
  91. time(&ah->assigned);
  92. if (wsi->position_in_fds_table != LWS_NO_FDS_POS &&
  93. lws_buflist_next_segment_len(&wsi->buflist, NULL) &&
  94. autoservice) {
  95. lwsl_debug("%s: service on readbuf ah\n", __func__);
  96. pt = &wsi->context->pt[(int)wsi->tsi];
  97. /*
  98. * Unlike a normal connect, we have the headers already
  99. * (or the first part of them anyway)
  100. */
  101. pfd = &pt->fds[wsi->position_in_fds_table];
  102. pfd->revents |= LWS_POLLIN;
  103. lwsl_err("%s: calling service\n", __func__);
  104. lws_service_fd_tsi(wsi->context, pfd, wsi->tsi);
  105. }
  106. }
  107. void
  108. lws_header_table_reset(struct lws *wsi, int autoservice)
  109. {
  110. struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
  111. lws_pt_lock(pt, __func__);
  112. __lws_header_table_reset(wsi, autoservice);
  113. lws_pt_unlock(pt);
  114. }
  115. static void
  116. _lws_header_ensure_we_are_on_waiting_list(struct lws *wsi)
  117. {
  118. struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
  119. struct lws_pollargs pa;
  120. struct lws **pwsi = &pt->http.ah_wait_list;
  121. while (*pwsi) {
  122. if (*pwsi == wsi)
  123. return;
  124. pwsi = &(*pwsi)->http.ah_wait_list;
  125. }
  126. lwsl_info("%s: wsi: %p\n", __func__, wsi);
  127. wsi->http.ah_wait_list = pt->http.ah_wait_list;
  128. pt->http.ah_wait_list = wsi;
  129. pt->http.ah_wait_list_length++;
  130. /* we cannot accept input then */
  131. _lws_change_pollfd(wsi, LWS_POLLIN, 0, &pa);
  132. }
  133. static int
  134. __lws_remove_from_ah_waiting_list(struct lws *wsi)
  135. {
  136. struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
  137. struct lws **pwsi =&pt->http.ah_wait_list;
  138. while (*pwsi) {
  139. if (*pwsi == wsi) {
  140. lwsl_info("%s: wsi %p\n", __func__, wsi);
  141. /* point prev guy to our next */
  142. *pwsi = wsi->http.ah_wait_list;
  143. /* we shouldn't point anywhere now */
  144. wsi->http.ah_wait_list = NULL;
  145. pt->http.ah_wait_list_length--;
  146. return 1;
  147. }
  148. pwsi = &(*pwsi)->http.ah_wait_list;
  149. }
  150. return 0;
  151. }
  152. int LWS_WARN_UNUSED_RESULT
  153. lws_header_table_attach(struct lws *wsi, int autoservice)
  154. {
  155. struct lws_context *context = wsi->context;
  156. struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
  157. struct lws_pollargs pa;
  158. int n;
  159. lwsl_info("%s: wsi %p: ah %p (tsi %d, count = %d) in\n", __func__,
  160. (void *)wsi, (void *)wsi->http.ah, wsi->tsi,
  161. pt->http.ah_count_in_use);
  162. lws_pt_lock(pt, __func__);
  163. /* if we are already bound to one, just clear it down */
  164. if (wsi->http.ah) {
  165. lwsl_info("%s: cleardown\n", __func__);
  166. goto reset;
  167. }
  168. n = pt->http.ah_count_in_use == context->max_http_header_pool;
  169. #if defined(LWS_WITH_PEER_LIMITS)
  170. if (!n) {
  171. n = lws_peer_confirm_ah_attach_ok(context, wsi->peer);
  172. if (n)
  173. lws_stats_atomic_bump(wsi->context, pt,
  174. LWSSTATS_C_PEER_LIMIT_AH_DENIED, 1);
  175. }
  176. #endif
  177. if (n) {
  178. /*
  179. * Pool is either all busy, or we don't want to give this
  180. * particular guy an ah right now...
  181. *
  182. * Make sure we are on the waiting list, and return that we
  183. * weren't able to provide the ah
  184. */
  185. _lws_header_ensure_we_are_on_waiting_list(wsi);
  186. goto bail;
  187. }
  188. __lws_remove_from_ah_waiting_list(wsi);
  189. wsi->http.ah = _lws_create_ah(pt, context->max_http_header_data);
  190. if (!wsi->http.ah) { /* we could not create an ah */
  191. _lws_header_ensure_we_are_on_waiting_list(wsi);
  192. goto bail;
  193. }
  194. wsi->http.ah->in_use = 1;
  195. wsi->http.ah->wsi = wsi; /* mark our owner */
  196. pt->http.ah_count_in_use++;
  197. #if defined(LWS_WITH_PEER_LIMITS) && (defined(LWS_ROLE_H1) || \
  198. defined(LWS_ROLE_H2))
  199. lws_context_lock(context, "ah attach"); /* <========================= */
  200. if (wsi->peer)
  201. wsi->peer->http.count_ah++;
  202. lws_context_unlock(context); /* ====================================> */
  203. #endif
  204. _lws_change_pollfd(wsi, 0, LWS_POLLIN, &pa);
  205. lwsl_info("%s: did attach wsi %p: ah %p: count %d (on exit)\n", __func__,
  206. (void *)wsi, (void *)wsi->http.ah, pt->http.ah_count_in_use);
  207. reset:
  208. __lws_header_table_reset(wsi, autoservice);
  209. lws_pt_unlock(pt);
  210. #ifndef LWS_NO_CLIENT
  211. if (lwsi_role_client(wsi) && lwsi_state(wsi) == LRS_UNCONNECTED)
  212. if (!lws_http_client_connect_via_info2(wsi))
  213. /* our client connect has failed, the wsi
  214. * has been closed
  215. */
  216. return -1;
  217. #endif
  218. return 0;
  219. bail:
  220. lws_pt_unlock(pt);
  221. return 1;
  222. }
  223. int __lws_header_table_detach(struct lws *wsi, int autoservice)
  224. {
  225. struct lws_context *context = wsi->context;
  226. struct allocated_headers *ah = wsi->http.ah;
  227. struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
  228. struct lws_pollargs pa;
  229. struct lws **pwsi, **pwsi_eligible;
  230. time_t now;
  231. __lws_remove_from_ah_waiting_list(wsi);
  232. if (!ah)
  233. return 0;
  234. lwsl_info("%s: wsi %p: ah %p (tsi=%d, count = %d)\n", __func__,
  235. (void *)wsi, (void *)ah, wsi->tsi,
  236. pt->http.ah_count_in_use);
  237. /* we did have an ah attached */
  238. time(&now);
  239. if (ah->assigned && now - ah->assigned > 3) {
  240. /*
  241. * we're detaching the ah, but it was held an
  242. * unreasonably long time
  243. */
  244. lwsl_debug("%s: wsi %p: ah held %ds, role/state 0x%x 0x%x,"
  245. "\n", __func__, wsi, (int)(now - ah->assigned),
  246. lwsi_role(wsi), lwsi_state(wsi));
  247. }
  248. ah->assigned = 0;
  249. /* if we think we're detaching one, there should be one in use */
  250. assert(pt->http.ah_count_in_use > 0);
  251. /* and this specific one should have been in use */
  252. assert(ah->in_use);
  253. memset(&wsi->http.ah, 0, sizeof(wsi->http.ah));
  254. #if defined(LWS_WITH_PEER_LIMITS)
  255. if (ah->wsi)
  256. lws_peer_track_ah_detach(context, wsi->peer);
  257. #endif
  258. ah->wsi = NULL; /* no owner */
  259. pwsi = &pt->http.ah_wait_list;
  260. /* oh there is nobody on the waiting list... leave the ah unattached */
  261. if (!*pwsi)
  262. goto nobody_usable_waiting;
  263. /*
  264. * at least one wsi on the same tsi is waiting, give it to oldest guy
  265. * who is allowed to take it (if any)
  266. */
  267. lwsl_info("pt wait list %p\n", *pwsi);
  268. wsi = NULL;
  269. pwsi_eligible = NULL;
  270. while (*pwsi) {
  271. #if defined(LWS_WITH_PEER_LIMITS)
  272. /* are we willing to give this guy an ah? */
  273. if (!lws_peer_confirm_ah_attach_ok(context, (*pwsi)->peer))
  274. #endif
  275. {
  276. wsi = *pwsi;
  277. pwsi_eligible = pwsi;
  278. }
  279. #if defined(LWS_WITH_PEER_LIMITS)
  280. else
  281. if (!(*pwsi)->http.ah_wait_list)
  282. lws_stats_atomic_bump(context, pt,
  283. LWSSTATS_C_PEER_LIMIT_AH_DENIED, 1);
  284. #endif
  285. pwsi = &(*pwsi)->http.ah_wait_list;
  286. }
  287. if (!wsi) /* everybody waiting already has too many ah... */
  288. goto nobody_usable_waiting;
  289. lwsl_info("%s: transferring ah to last eligible wsi in wait list "
  290. "%p (wsistate 0x%x)\n", __func__, wsi, wsi->wsistate);
  291. wsi->http.ah = ah;
  292. ah->wsi = wsi; /* new owner */
  293. __lws_header_table_reset(wsi, autoservice);
  294. #if defined(LWS_WITH_PEER_LIMITS) && (defined(LWS_ROLE_H1) || \
  295. defined(LWS_ROLE_H2))
  296. lws_context_lock(context, "ah detach"); /* <========================= */
  297. if (wsi->peer)
  298. wsi->peer->http.count_ah++;
  299. lws_context_unlock(context); /* ====================================> */
  300. #endif
  301. /* clients acquire the ah and then insert themselves in fds table... */
  302. if (wsi->position_in_fds_table != LWS_NO_FDS_POS) {
  303. lwsl_info("%s: Enabling %p POLLIN\n", __func__, wsi);
  304. /* he has been stuck waiting for an ah, but now his wait is
  305. * over, let him progress */
  306. _lws_change_pollfd(wsi, 0, LWS_POLLIN, &pa);
  307. }
  308. /* point prev guy to next guy in list instead */
  309. *pwsi_eligible = wsi->http.ah_wait_list;
  310. /* the guy who got one is out of the list */
  311. wsi->http.ah_wait_list = NULL;
  312. pt->http.ah_wait_list_length--;
  313. #ifndef LWS_NO_CLIENT
  314. if (lwsi_role_client(wsi) && lwsi_state(wsi) == LRS_UNCONNECTED) {
  315. lws_pt_unlock(pt);
  316. if (!lws_http_client_connect_via_info2(wsi)) {
  317. /* our client connect has failed, the wsi
  318. * has been closed
  319. */
  320. return -1;
  321. }
  322. return 0;
  323. }
  324. #endif
  325. assert(!!pt->http.ah_wait_list_length ==
  326. !!(lws_intptr_t)pt->http.ah_wait_list);
  327. bail:
  328. lwsl_info("%s: wsi %p: ah %p (tsi=%d, count = %d)\n", __func__,
  329. (void *)wsi, (void *)ah, pt->tid, pt->http.ah_count_in_use);
  330. return 0;
  331. nobody_usable_waiting:
  332. lwsl_info("%s: nobody usable waiting\n", __func__);
  333. _lws_destroy_ah(pt, ah);
  334. pt->http.ah_count_in_use--;
  335. goto bail;
  336. }
  337. int lws_header_table_detach(struct lws *wsi, int autoservice)
  338. {
  339. struct lws_context *context = wsi->context;
  340. struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
  341. int n;
  342. lws_pt_lock(pt, __func__);
  343. n = __lws_header_table_detach(wsi, autoservice);
  344. lws_pt_unlock(pt);
  345. return n;
  346. }
  347. LWS_VISIBLE int
  348. lws_hdr_fragment_length(struct lws *wsi, enum lws_token_indexes h, int frag_idx)
  349. {
  350. int n;
  351. if (!wsi->http.ah)
  352. return 0;
  353. n = wsi->http.ah->frag_index[h];
  354. if (!n)
  355. return 0;
  356. do {
  357. if (!frag_idx)
  358. return wsi->http.ah->frags[n].len;
  359. n = wsi->http.ah->frags[n].nfrag;
  360. } while (frag_idx-- && n);
  361. return 0;
  362. }
  363. LWS_VISIBLE int lws_hdr_total_length(struct lws *wsi, enum lws_token_indexes h)
  364. {
  365. int n;
  366. int len = 0;
  367. if (!wsi->http.ah)
  368. return 0;
  369. n = wsi->http.ah->frag_index[h];
  370. if (!n)
  371. return 0;
  372. do {
  373. len += wsi->http.ah->frags[n].len;
  374. n = wsi->http.ah->frags[n].nfrag;
  375. if (n && h != WSI_TOKEN_HTTP_COOKIE)
  376. ++len;
  377. } while (n);
  378. return len;
  379. }
  380. LWS_VISIBLE int lws_hdr_copy_fragment(struct lws *wsi, char *dst, int len,
  381. enum lws_token_indexes h, int frag_idx)
  382. {
  383. int n = 0;
  384. int f;
  385. if (!wsi->http.ah)
  386. return -1;
  387. f = wsi->http.ah->frag_index[h];
  388. if (!f)
  389. return -1;
  390. while (n < frag_idx) {
  391. f = wsi->http.ah->frags[f].nfrag;
  392. if (!f)
  393. return -1;
  394. n++;
  395. }
  396. if (wsi->http.ah->frags[f].len >= len)
  397. return -1;
  398. memcpy(dst, wsi->http.ah->data + wsi->http.ah->frags[f].offset,
  399. wsi->http.ah->frags[f].len);
  400. dst[wsi->http.ah->frags[f].len] = '\0';
  401. return wsi->http.ah->frags[f].len;
  402. }
  403. LWS_VISIBLE int lws_hdr_copy(struct lws *wsi, char *dst, int len,
  404. enum lws_token_indexes h)
  405. {
  406. int toklen = lws_hdr_total_length(wsi, h);
  407. int n;
  408. int comma;
  409. *dst = '\0';
  410. if (!toklen)
  411. return 0;
  412. if (toklen >= len)
  413. return -1;
  414. if (!wsi->http.ah)
  415. return -1;
  416. n = wsi->http.ah->frag_index[h];
  417. if (!n)
  418. return 0;
  419. do {
  420. comma = (wsi->http.ah->frags[n].nfrag &&
  421. h != WSI_TOKEN_HTTP_COOKIE) ? 1 : 0;
  422. if (wsi->http.ah->frags[n].len + comma >= len)
  423. return -1;
  424. strncpy(dst, &wsi->http.ah->data[wsi->http.ah->frags[n].offset],
  425. wsi->http.ah->frags[n].len);
  426. dst += wsi->http.ah->frags[n].len;
  427. len -= wsi->http.ah->frags[n].len;
  428. n = wsi->http.ah->frags[n].nfrag;
  429. if (comma)
  430. *dst++ = ',';
  431. } while (n);
  432. *dst = '\0';
  433. return toklen;
  434. }
  435. char *lws_hdr_simple_ptr(struct lws *wsi, enum lws_token_indexes h)
  436. {
  437. int n;
  438. if (!wsi->http.ah)
  439. return NULL;
  440. n = wsi->http.ah->frag_index[h];
  441. if (!n)
  442. return NULL;
  443. return wsi->http.ah->data + wsi->http.ah->frags[n].offset;
  444. }
  445. static int LWS_WARN_UNUSED_RESULT
  446. lws_pos_in_bounds(struct lws *wsi)
  447. {
  448. if (!wsi->http.ah)
  449. return -1;
  450. if (wsi->http.ah->pos <
  451. (unsigned int)wsi->context->max_http_header_data)
  452. return 0;
  453. if ((int)wsi->http.ah->pos == wsi->context->max_http_header_data) {
  454. lwsl_err("Ran out of header data space\n");
  455. return 1;
  456. }
  457. /*
  458. * with these tests everywhere, it should never be able to exceed
  459. * the limit, only meet it
  460. */
  461. lwsl_err("%s: pos %d, limit %d\n", __func__, wsi->http.ah->pos,
  462. wsi->context->max_http_header_data);
  463. assert(0);
  464. return 1;
  465. }
  466. int LWS_WARN_UNUSED_RESULT
  467. lws_hdr_simple_create(struct lws *wsi, enum lws_token_indexes h, const char *s)
  468. {
  469. wsi->http.ah->nfrag++;
  470. if (wsi->http.ah->nfrag == LWS_ARRAY_SIZE(wsi->http.ah->frags)) {
  471. lwsl_warn("More hdr frags than we can deal with, dropping\n");
  472. return -1;
  473. }
  474. wsi->http.ah->frag_index[h] = wsi->http.ah->nfrag;
  475. wsi->http.ah->frags[wsi->http.ah->nfrag].offset = wsi->http.ah->pos;
  476. wsi->http.ah->frags[wsi->http.ah->nfrag].len = 0;
  477. wsi->http.ah->frags[wsi->http.ah->nfrag].nfrag = 0;
  478. do {
  479. if (lws_pos_in_bounds(wsi))
  480. return -1;
  481. wsi->http.ah->data[wsi->http.ah->pos++] = *s;
  482. if (*s)
  483. wsi->http.ah->frags[wsi->http.ah->nfrag].len++;
  484. } while (*s++);
  485. return 0;
  486. }
  487. static int LWS_WARN_UNUSED_RESULT
  488. issue_char(struct lws *wsi, unsigned char c)
  489. {
  490. unsigned short frag_len;
  491. if (lws_pos_in_bounds(wsi))
  492. return -1;
  493. frag_len = wsi->http.ah->frags[wsi->http.ah->nfrag].len;
  494. /*
  495. * If we haven't hit the token limit, just copy the character into
  496. * the header
  497. */
  498. if (!wsi->http.ah->current_token_limit ||
  499. frag_len < wsi->http.ah->current_token_limit) {
  500. wsi->http.ah->data[wsi->http.ah->pos++] = c;
  501. if (c)
  502. wsi->http.ah->frags[wsi->http.ah->nfrag].len++;
  503. return 0;
  504. }
  505. /* Insert a null character when we *hit* the limit: */
  506. if (frag_len == wsi->http.ah->current_token_limit) {
  507. if (lws_pos_in_bounds(wsi))
  508. return -1;
  509. wsi->http.ah->data[wsi->http.ah->pos++] = '\0';
  510. lwsl_warn("header %i exceeds limit %d\n",
  511. wsi->http.ah->parser_state,
  512. wsi->http.ah->current_token_limit);
  513. }
  514. return 1;
  515. }
  516. int
  517. lws_parse_urldecode(struct lws *wsi, uint8_t *_c)
  518. {
  519. struct allocated_headers *ah = wsi->http.ah;
  520. unsigned int enc = 0;
  521. uint8_t c = *_c;
  522. // lwsl_notice("ah->ups %d\n", ah->ups);
  523. /*
  524. * PRIORITY 1
  525. * special URI processing... convert %xx
  526. */
  527. switch (ah->ues) {
  528. case URIES_IDLE:
  529. if (c == '%') {
  530. ah->ues = URIES_SEEN_PERCENT;
  531. goto swallow;
  532. }
  533. break;
  534. case URIES_SEEN_PERCENT:
  535. if (char_to_hex(c) < 0)
  536. /* illegal post-% char */
  537. goto forbid;
  538. ah->esc_stash = c;
  539. ah->ues = URIES_SEEN_PERCENT_H1;
  540. goto swallow;
  541. case URIES_SEEN_PERCENT_H1:
  542. if (char_to_hex(c) < 0)
  543. /* illegal post-% char */
  544. goto forbid;
  545. *_c = (char_to_hex(ah->esc_stash) << 4) |
  546. char_to_hex(c);
  547. c = *_c;
  548. enc = 1;
  549. ah->ues = URIES_IDLE;
  550. break;
  551. }
  552. /*
  553. * PRIORITY 2
  554. * special URI processing...
  555. * convert /.. or /... or /../ etc to /
  556. * convert /./ to /
  557. * convert // or /// etc to /
  558. * leave /.dir or whatever alone
  559. */
  560. switch (ah->ups) {
  561. case URIPS_IDLE:
  562. if (!c)
  563. return -1;
  564. /* genuine delimiter */
  565. if ((c == '&' || c == ';') && !enc) {
  566. if (issue_char(wsi, '\0') < 0)
  567. return -1;
  568. /* link to next fragment */
  569. ah->frags[ah->nfrag].nfrag = ah->nfrag + 1;
  570. ah->nfrag++;
  571. if (ah->nfrag >= LWS_ARRAY_SIZE(ah->frags))
  572. goto excessive;
  573. /* start next fragment after the & */
  574. ah->post_literal_equal = 0;
  575. ah->frags[ah->nfrag].offset = ++ah->pos;
  576. ah->frags[ah->nfrag].len = 0;
  577. ah->frags[ah->nfrag].nfrag = 0;
  578. goto swallow;
  579. }
  580. /* uriencoded = in the name part, disallow */
  581. if (c == '=' && enc &&
  582. ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] &&
  583. !ah->post_literal_equal) {
  584. c = '_';
  585. *_c =c;
  586. }
  587. /* after the real =, we don't care how many = */
  588. if (c == '=' && !enc)
  589. ah->post_literal_equal = 1;
  590. /* + to space */
  591. if (c == '+' && !enc) {
  592. c = ' ';
  593. *_c = c;
  594. }
  595. /* issue the first / always */
  596. if (c == '/' && !ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS])
  597. ah->ups = URIPS_SEEN_SLASH;
  598. break;
  599. case URIPS_SEEN_SLASH:
  600. /* swallow subsequent slashes */
  601. if (c == '/')
  602. goto swallow;
  603. /* track and swallow the first . after / */
  604. if (c == '.') {
  605. ah->ups = URIPS_SEEN_SLASH_DOT;
  606. goto swallow;
  607. }
  608. ah->ups = URIPS_IDLE;
  609. break;
  610. case URIPS_SEEN_SLASH_DOT:
  611. /* swallow second . */
  612. if (c == '.') {
  613. ah->ups = URIPS_SEEN_SLASH_DOT_DOT;
  614. goto swallow;
  615. }
  616. /* change /./ to / */
  617. if (c == '/') {
  618. ah->ups = URIPS_SEEN_SLASH;
  619. goto swallow;
  620. }
  621. /* it was like /.dir ... regurgitate the . */
  622. ah->ups = URIPS_IDLE;
  623. if (issue_char(wsi, '.') < 0)
  624. return -1;
  625. break;
  626. case URIPS_SEEN_SLASH_DOT_DOT:
  627. /* /../ or /..[End of URI] --> backup to last / */
  628. if (c == '/' || c == '?') {
  629. /*
  630. * back up one dir level if possible
  631. * safe against header fragmentation because
  632. * the method URI can only be in 1 fragment
  633. */
  634. if (ah->frags[ah->nfrag].len > 2) {
  635. ah->pos--;
  636. ah->frags[ah->nfrag].len--;
  637. do {
  638. ah->pos--;
  639. ah->frags[ah->nfrag].len--;
  640. } while (ah->frags[ah->nfrag].len > 1 &&
  641. ah->data[ah->pos] != '/');
  642. }
  643. ah->ups = URIPS_SEEN_SLASH;
  644. if (ah->frags[ah->nfrag].len > 1)
  645. break;
  646. goto swallow;
  647. }
  648. /* /..[^/] ... regurgitate and allow */
  649. if (issue_char(wsi, '.') < 0)
  650. return -1;
  651. if (issue_char(wsi, '.') < 0)
  652. return -1;
  653. ah->ups = URIPS_IDLE;
  654. break;
  655. }
  656. if (c == '?' && !enc &&
  657. !ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS]) { /* start of URI args */
  658. if (ah->ues != URIES_IDLE)
  659. goto forbid;
  660. /* seal off uri header */
  661. if (issue_char(wsi, '\0') < 0)
  662. return -1;
  663. /* move to using WSI_TOKEN_HTTP_URI_ARGS */
  664. ah->nfrag++;
  665. if (ah->nfrag >= LWS_ARRAY_SIZE(ah->frags))
  666. goto excessive;
  667. ah->frags[ah->nfrag].offset = ++ah->pos;
  668. ah->frags[ah->nfrag].len = 0;
  669. ah->frags[ah->nfrag].nfrag = 0;
  670. ah->post_literal_equal = 0;
  671. ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] = ah->nfrag;
  672. ah->ups = URIPS_IDLE;
  673. goto swallow;
  674. }
  675. return LPUR_CONTINUE;
  676. swallow:
  677. return LPUR_SWALLOW;
  678. forbid:
  679. return LPUR_FORBID;
  680. excessive:
  681. return LPUR_EXCESSIVE;
  682. }
  683. static const unsigned char methods[] = {
  684. WSI_TOKEN_GET_URI,
  685. WSI_TOKEN_POST_URI,
  686. WSI_TOKEN_OPTIONS_URI,
  687. WSI_TOKEN_PUT_URI,
  688. WSI_TOKEN_PATCH_URI,
  689. WSI_TOKEN_DELETE_URI,
  690. WSI_TOKEN_CONNECT,
  691. WSI_TOKEN_HEAD_URI,
  692. };
  693. /*
  694. * possible returns:, -1 fail, 0 ok or 2, transition to raw
  695. */
  696. int LWS_WARN_UNUSED_RESULT
  697. lws_parse(struct lws *wsi, unsigned char *buf, int *len)
  698. {
  699. struct allocated_headers *ah = wsi->http.ah;
  700. struct lws_context *context = wsi->context;
  701. unsigned int n, m;
  702. unsigned char c;
  703. int r, pos;
  704. assert(wsi->http.ah);
  705. do {
  706. (*len)--;
  707. c = *buf++;
  708. switch (ah->parser_state) {
  709. default:
  710. lwsl_parser("WSI_TOK_(%d) '%c'\n", ah->parser_state, c);
  711. /* collect into malloc'd buffers */
  712. /* optional initial space swallow */
  713. if (!ah->frags[ah->frag_index[ah->parser_state]].len &&
  714. c == ' ')
  715. break;
  716. for (m = 0; m < LWS_ARRAY_SIZE(methods); m++)
  717. if (ah->parser_state == methods[m])
  718. break;
  719. if (m == LWS_ARRAY_SIZE(methods))
  720. /* it was not any of the methods */
  721. goto check_eol;
  722. /* special URI processing... end at space */
  723. if (c == ' ') {
  724. /* enforce starting with / */
  725. if (!ah->frags[ah->nfrag].len)
  726. if (issue_char(wsi, '/') < 0)
  727. return -1;
  728. if (ah->ups == URIPS_SEEN_SLASH_DOT_DOT) {
  729. /*
  730. * back up one dir level if possible
  731. * safe against header fragmentation
  732. * because the method URI can only be
  733. * in 1 fragment
  734. */
  735. if (ah->frags[ah->nfrag].len > 2) {
  736. ah->pos--;
  737. ah->frags[ah->nfrag].len--;
  738. do {
  739. ah->pos--;
  740. ah->frags[ah->nfrag].len--;
  741. } while (ah->frags[ah->nfrag].len > 1 &&
  742. ah->data[ah->pos] != '/');
  743. }
  744. }
  745. /* begin parsing HTTP version: */
  746. if (issue_char(wsi, '\0') < 0)
  747. return -1;
  748. ah->parser_state = WSI_TOKEN_HTTP;
  749. goto start_fragment;
  750. }
  751. r = lws_parse_urldecode(wsi, &c);
  752. switch (r) {
  753. case LPUR_CONTINUE:
  754. break;
  755. case LPUR_SWALLOW:
  756. goto swallow;
  757. case LPUR_FORBID:
  758. goto forbid;
  759. case LPUR_EXCESSIVE:
  760. goto excessive;
  761. default:
  762. return -1;
  763. }
  764. check_eol:
  765. /* bail at EOL */
  766. if (ah->parser_state != WSI_TOKEN_CHALLENGE &&
  767. c == '\x0d') {
  768. if (ah->ues != URIES_IDLE)
  769. goto forbid;
  770. c = '\0';
  771. ah->parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
  772. lwsl_parser("*\n");
  773. }
  774. n = issue_char(wsi, c);
  775. if ((int)n < 0)
  776. return -1;
  777. if (n > 0)
  778. ah->parser_state = WSI_TOKEN_SKIPPING;
  779. swallow:
  780. /* per-protocol end of headers management */
  781. if (ah->parser_state == WSI_TOKEN_CHALLENGE)
  782. goto set_parsing_complete;
  783. break;
  784. /* collecting and checking a name part */
  785. case WSI_TOKEN_NAME_PART:
  786. lwsl_parser("WSI_TOKEN_NAME_PART '%c' 0x%02X (role=0x%x) "
  787. "wsi->lextable_pos=%d\n", c, c, lwsi_role(wsi),
  788. ah->lextable_pos);
  789. if (c >= 'A' && c <= 'Z')
  790. c += 'a' - 'A';
  791. pos = ah->lextable_pos;
  792. while (1) {
  793. if (lextable[pos] & (1 << 7)) {
  794. /* 1-byte, fail on mismatch */
  795. if ((lextable[pos] & 0x7f) != c) {
  796. nope:
  797. ah->lextable_pos = -1;
  798. break;
  799. }
  800. /* fall thru */
  801. pos++;
  802. if (lextable[pos] == FAIL_CHAR)
  803. goto nope;
  804. ah->lextable_pos = pos;
  805. break;
  806. }
  807. if (lextable[pos] == FAIL_CHAR)
  808. goto nope;
  809. /* b7 = 0, end or 3-byte */
  810. if (lextable[pos] < FAIL_CHAR) { /* term mark */
  811. ah->lextable_pos = pos;
  812. break;
  813. }
  814. if (lextable[pos] == c) { /* goto */
  815. ah->lextable_pos = pos +
  816. (lextable[pos + 1]) +
  817. (lextable[pos + 2] << 8);
  818. break;
  819. }
  820. /* fall thru goto */
  821. pos += 3;
  822. /* continue */
  823. }
  824. /*
  825. * If it's h1, server needs to look out for unknown
  826. * methods...
  827. */
  828. if (ah->lextable_pos < 0 && lwsi_role_h1(wsi) &&
  829. lwsi_role_server(wsi)) {
  830. /* this is not a header we know about */
  831. for (m = 0; m < LWS_ARRAY_SIZE(methods); m++)
  832. if (ah->frag_index[methods[m]]) {
  833. /*
  834. * already had the method, no idea what
  835. * this crap from the client is, ignore
  836. */
  837. ah->parser_state = WSI_TOKEN_SKIPPING;
  838. break;
  839. }
  840. /*
  841. * hm it's an unknown http method from a client in fact,
  842. * it cannot be valid http
  843. */
  844. if (m == LWS_ARRAY_SIZE(methods)) {
  845. /*
  846. * are we set up to accept raw in these cases?
  847. */
  848. if (lws_check_opt(wsi->vhost->options,
  849. LWS_SERVER_OPTION_FALLBACK_TO_RAW))
  850. return 2; /* transition to raw */
  851. lwsl_info("Unknown method - dropping\n");
  852. goto forbid;
  853. }
  854. break;
  855. }
  856. /*
  857. * ...otherwise for a client, let him ignore unknown headers
  858. * coming from the server
  859. */
  860. if (ah->lextable_pos < 0) {
  861. ah->parser_state = WSI_TOKEN_SKIPPING;
  862. break;
  863. }
  864. if (lextable[ah->lextable_pos] < FAIL_CHAR) {
  865. /* terminal state */
  866. n = ((unsigned int)lextable[ah->lextable_pos] << 8) |
  867. lextable[ah->lextable_pos + 1];
  868. lwsl_parser("known hdr %d\n", n);
  869. for (m = 0; m < LWS_ARRAY_SIZE(methods); m++)
  870. if (n == methods[m] &&
  871. ah->frag_index[methods[m]]) {
  872. lwsl_warn("Duplicated method\n");
  873. return -1;
  874. }
  875. /*
  876. * WSORIGIN is protocol equiv to ORIGIN,
  877. * JWebSocket likes to send it, map to ORIGIN
  878. */
  879. if (n == WSI_TOKEN_SWORIGIN)
  880. n = WSI_TOKEN_ORIGIN;
  881. ah->parser_state = (enum lws_token_indexes)
  882. (WSI_TOKEN_GET_URI + n);
  883. ah->ups = URIPS_IDLE;
  884. if (context->token_limits)
  885. ah->current_token_limit = context->
  886. token_limits->token_limit[
  887. ah->parser_state];
  888. else
  889. ah->current_token_limit =
  890. wsi->context->max_http_header_data;
  891. if (ah->parser_state == WSI_TOKEN_CHALLENGE)
  892. goto set_parsing_complete;
  893. goto start_fragment;
  894. }
  895. break;
  896. start_fragment:
  897. ah->nfrag++;
  898. excessive:
  899. if (ah->nfrag == LWS_ARRAY_SIZE(ah->frags)) {
  900. lwsl_warn("More hdr frags than we can deal with\n");
  901. return -1;
  902. }
  903. ah->frags[ah->nfrag].offset = ah->pos;
  904. ah->frags[ah->nfrag].len = 0;
  905. ah->frags[ah->nfrag].nfrag = 0;
  906. ah->frags[ah->nfrag].flags = 2;
  907. n = ah->frag_index[ah->parser_state];
  908. if (!n) { /* first fragment */
  909. ah->frag_index[ah->parser_state] = ah->nfrag;
  910. ah->hdr_token_idx = ah->parser_state;
  911. break;
  912. }
  913. /* continuation */
  914. while (ah->frags[n].nfrag)
  915. n = ah->frags[n].nfrag;
  916. ah->frags[n].nfrag = ah->nfrag;
  917. if (issue_char(wsi, ' ') < 0)
  918. return -1;
  919. break;
  920. /* skipping arg part of a name we didn't recognize */
  921. case WSI_TOKEN_SKIPPING:
  922. lwsl_parser("WSI_TOKEN_SKIPPING '%c'\n", c);
  923. if (c == '\x0d')
  924. ah->parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
  925. break;
  926. case WSI_TOKEN_SKIPPING_SAW_CR:
  927. lwsl_parser("WSI_TOKEN_SKIPPING_SAW_CR '%c'\n", c);
  928. if (ah->ues != URIES_IDLE)
  929. goto forbid;
  930. if (c == '\x0a') {
  931. ah->parser_state = WSI_TOKEN_NAME_PART;
  932. ah->lextable_pos = 0;
  933. } else
  934. ah->parser_state = WSI_TOKEN_SKIPPING;
  935. break;
  936. /* we're done, ignore anything else */
  937. case WSI_PARSING_COMPLETE:
  938. lwsl_parser("WSI_PARSING_COMPLETE '%c'\n", c);
  939. break;
  940. }
  941. } while (*len);
  942. return 0;
  943. set_parsing_complete:
  944. if (ah->ues != URIES_IDLE)
  945. goto forbid;
  946. if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) {
  947. if (lws_hdr_total_length(wsi, WSI_TOKEN_VERSION))
  948. wsi->rx_frame_type = /* temp for ws version index */
  949. atoi(lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION));
  950. lwsl_parser("v%02d hdrs done\n", wsi->rx_frame_type);
  951. }
  952. ah->parser_state = WSI_PARSING_COMPLETE;
  953. wsi->hdr_parsing_completed = 1;
  954. return 0;
  955. forbid:
  956. lwsl_notice(" forbidding on uri sanitation\n");
  957. lws_return_http_status(wsi, HTTP_STATUS_FORBIDDEN, NULL);
  958. return -1;
  959. }