2
0

client-ws.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  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. /*
  23. * In-place str to lower case
  24. */
  25. static void
  26. strtolower(char *s)
  27. {
  28. while (*s) {
  29. #ifdef LWS_PLAT_OPTEE
  30. int tolower_optee(int c);
  31. *s = tolower_optee((int)*s);
  32. #else
  33. *s = tolower((int)*s);
  34. #endif
  35. s++;
  36. }
  37. }
  38. int
  39. lws_create_client_ws_object(const struct lws_client_connect_info *i,
  40. struct lws *wsi)
  41. {
  42. int v = SPEC_LATEST_SUPPORTED;
  43. /* allocate the ws struct for the wsi */
  44. wsi->ws = lws_zalloc(sizeof(*wsi->ws), "client ws struct");
  45. if (!wsi->ws) {
  46. lwsl_notice("OOM\n");
  47. return 1;
  48. }
  49. /* -1 means just use latest supported */
  50. if (i->ietf_version_or_minus_one != -1 &&
  51. i->ietf_version_or_minus_one)
  52. v = i->ietf_version_or_minus_one;
  53. wsi->ws->ietf_spec_revision = v;
  54. return 0;
  55. }
  56. #if !defined(LWS_NO_CLIENT)
  57. int
  58. lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len)
  59. {
  60. if ((lwsi_state(wsi) != LRS_WAITING_PROXY_REPLY) &&
  61. (lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE) &&
  62. (lwsi_state(wsi) != LRS_WAITING_SERVER_REPLY) &&
  63. !lwsi_role_client(wsi))
  64. return 0;
  65. // lwsl_notice("%s: hs client gets %d in\n", __func__, (int)len);
  66. while (len) {
  67. /*
  68. * we were accepting input but now we stopped doing so
  69. */
  70. if (lws_is_flowcontrolled(wsi)) {
  71. //lwsl_notice("%s: caching %ld\n", __func__, (long)len);
  72. lws_rxflow_cache(wsi, *buf, 0, (int)len);
  73. *buf += len;
  74. return 0;
  75. }
  76. #if !defined(LWS_WITHOUT_EXTENSIONS)
  77. if (wsi->ws->rx_draining_ext) {
  78. int m;
  79. //lwsl_notice("%s: draining ext\n", __func__);
  80. if (lwsi_role_client(wsi))
  81. m = lws_ws_client_rx_sm(wsi, 0);
  82. else
  83. m = lws_ws_rx_sm(wsi, 0, 0);
  84. if (m < 0)
  85. return -1;
  86. continue;
  87. }
  88. #endif
  89. /* caller will account for buflist usage */
  90. if (lws_ws_client_rx_sm(wsi, *(*buf)++)) {
  91. lwsl_notice("%s: client_rx_sm exited, DROPPING %d\n",
  92. __func__, (int)len);
  93. return -1;
  94. }
  95. len--;
  96. }
  97. // lwsl_notice("%s: finished with %ld\n", __func__, (long)len);
  98. return 0;
  99. }
  100. #endif
  101. char *
  102. lws_generate_client_ws_handshake(struct lws *wsi, char *p, const char *conn1)
  103. {
  104. char buf[128], hash[20], key_b64[40];
  105. int n;
  106. #if !defined(LWS_WITHOUT_EXTENSIONS)
  107. const struct lws_extension *ext;
  108. int ext_count = 0;
  109. #endif
  110. /*
  111. * create the random key
  112. */
  113. n = lws_get_random(wsi->context, hash, 16);
  114. if (n != 16) {
  115. lwsl_err("Unable to read from random dev %s\n",
  116. SYSTEM_RANDOM_FILEPATH);
  117. return NULL;
  118. }
  119. lws_b64_encode_string(hash, 16, key_b64, sizeof(key_b64));
  120. p += sprintf(p, "Upgrade: websocket\x0d\x0a"
  121. "Connection: %sUpgrade\x0d\x0a"
  122. "Sec-WebSocket-Key: ", conn1);
  123. strcpy(p, key_b64);
  124. p += strlen(key_b64);
  125. p += sprintf(p, "\x0d\x0a");
  126. if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS))
  127. p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a",
  128. lws_hdr_simple_ptr(wsi,
  129. _WSI_TOKEN_CLIENT_SENT_PROTOCOLS));
  130. /* tell the server what extensions we could support */
  131. #if !defined(LWS_WITHOUT_EXTENSIONS)
  132. ext = wsi->vhost->ws.extensions;
  133. while (ext && ext->callback) {
  134. n = wsi->vhost->protocols[0].callback(wsi,
  135. LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
  136. wsi->user_space, (char *)ext->name, 0);
  137. /*
  138. * zero return from callback means go ahead and allow
  139. * the extension, it's what we get if the callback is
  140. * unhandled
  141. */
  142. if (n) {
  143. ext++;
  144. continue;
  145. }
  146. /* apply it */
  147. if (ext_count)
  148. *p++ = ',';
  149. else
  150. p += sprintf(p, "Sec-WebSocket-Extensions: ");
  151. p += sprintf(p, "%s", ext->client_offer);
  152. ext_count++;
  153. ext++;
  154. }
  155. if (ext_count)
  156. p += sprintf(p, "\x0d\x0a");
  157. #endif
  158. if (wsi->ws->ietf_spec_revision)
  159. p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a",
  160. wsi->ws->ietf_spec_revision);
  161. /* prepare the expected server accept response */
  162. key_b64[39] = '\0'; /* enforce composed length below buf sizeof */
  163. n = sprintf(buf, "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
  164. key_b64);
  165. lws_SHA1((unsigned char *)buf, n, (unsigned char *)hash);
  166. lws_b64_encode_string(hash, 20,
  167. wsi->http.ah->initial_handshake_hash_base64,
  168. sizeof(wsi->http.ah->initial_handshake_hash_base64));
  169. return p;
  170. }
  171. int
  172. lws_client_ws_upgrade(struct lws *wsi, const char **cce)
  173. {
  174. struct lws_context *context = wsi->context;
  175. struct lws_tokenize ts;
  176. int n, len, okay = 0;
  177. lws_tokenize_elem e;
  178. char *p, buf[64];
  179. const char *pc;
  180. #if !defined(LWS_WITHOUT_EXTENSIONS)
  181. struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
  182. char *sb = (char *)&pt->serv_buf[0];
  183. const struct lws_ext_options *opts;
  184. const struct lws_extension *ext;
  185. char ext_name[128];
  186. const char *c, *a;
  187. int more = 1;
  188. char ignore;
  189. #endif
  190. if (wsi->client_h2_substream) {/* !!! client ws-over-h2 not there yet */
  191. lwsl_warn("%s: client ws-over-h2 upgrade not supported yet\n",
  192. __func__);
  193. *cce = "HS: h2 / ws upgrade unsupported";
  194. goto bail3;
  195. }
  196. if (wsi->http.ah->http_response == 401) {
  197. lwsl_warn(
  198. "lws_client_handshake: got bad HTTP response '%d'\n",
  199. wsi->http.ah->http_response);
  200. *cce = "HS: ws upgrade unauthorized";
  201. goto bail3;
  202. }
  203. if (wsi->http.ah->http_response != 101) {
  204. lwsl_warn(
  205. "lws_client_handshake: got bad HTTP response '%d'\n",
  206. wsi->http.ah->http_response);
  207. *cce = "HS: ws upgrade response not 101";
  208. goto bail3;
  209. }
  210. if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0) {
  211. lwsl_info("no ACCEPT\n");
  212. *cce = "HS: ACCEPT missing";
  213. goto bail3;
  214. }
  215. p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE);
  216. if (!p) {
  217. lwsl_info("no UPGRADE\n");
  218. *cce = "HS: UPGRADE missing";
  219. goto bail3;
  220. }
  221. strtolower(p);
  222. if (strcmp(p, "websocket")) {
  223. lwsl_warn(
  224. "lws_client_handshake: got bad Upgrade header '%s'\n", p);
  225. *cce = "HS: Upgrade to something other than websocket";
  226. goto bail3;
  227. }
  228. /* connection: must have "upgrade" */
  229. lws_tokenize_init(&ts, buf, LWS_TOKENIZE_F_COMMA_SEP_LIST |
  230. LWS_TOKENIZE_F_MINUS_NONTERM);
  231. ts.len = lws_hdr_copy(wsi, buf, sizeof(buf) - 1, WSI_TOKEN_CONNECTION);
  232. if (ts.len <= 0) /* won't fit, or absent */
  233. goto bad_conn_format;
  234. do {
  235. e = lws_tokenize(&ts);
  236. switch (e) {
  237. case LWS_TOKZE_TOKEN:
  238. if (!strcasecmp(ts.token, "upgrade"))
  239. e = LWS_TOKZE_ENDED;
  240. break;
  241. case LWS_TOKZE_DELIMITER:
  242. break;
  243. default: /* includes ENDED */
  244. bad_conn_format:
  245. *cce = "HS: UPGRADE malformed";
  246. goto bail3;
  247. }
  248. } while (e > 0);
  249. pc = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
  250. if (!pc) {
  251. lwsl_parser("lws_client_int_s_hs: no protocol list\n");
  252. } else
  253. lwsl_parser("lws_client_int_s_hs: protocol list '%s'\n", pc);
  254. /*
  255. * confirm the protocol the server wants to talk was in the list
  256. * of protocols we offered
  257. */
  258. len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL);
  259. if (!len) {
  260. lwsl_info("%s: WSI_TOKEN_PROTOCOL is null\n", __func__);
  261. /*
  262. * no protocol name to work from,
  263. * default to first protocol
  264. */
  265. n = 0;
  266. wsi->protocol = &wsi->vhost->protocols[0];
  267. goto check_extensions;
  268. }
  269. p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL);
  270. len = (int)strlen(p);
  271. while (pc && *pc && !okay) {
  272. if (!strncmp(pc, p, len) &&
  273. (pc[len] == ',' || pc[len] == '\0')) {
  274. okay = 1;
  275. continue;
  276. }
  277. while (*pc && *pc++ != ',')
  278. ;
  279. while (*pc == ' ')
  280. pc++;
  281. }
  282. if (!okay) {
  283. lwsl_info("%s: got bad protocol %s\n", __func__, p);
  284. *cce = "HS: PROTOCOL malformed";
  285. goto bail2;
  286. }
  287. /*
  288. * identify the selected protocol struct and set it
  289. */
  290. n = 0;
  291. /* keep client connection pre-bound protocol */
  292. if (!lwsi_role_client(wsi))
  293. wsi->protocol = NULL;
  294. while (wsi->vhost->protocols[n].callback) {
  295. if (!wsi->protocol &&
  296. strcmp(p, wsi->vhost->protocols[n].name) == 0) {
  297. wsi->protocol = &wsi->vhost->protocols[n];
  298. break;
  299. }
  300. n++;
  301. }
  302. if (!wsi->vhost->protocols[n].callback) { /* no match */
  303. /* if server, that's already fatal */
  304. if (!lwsi_role_client(wsi)) {
  305. lwsl_info("%s: fail protocol %s\n", __func__, p);
  306. *cce = "HS: Cannot match protocol";
  307. goto bail2;
  308. }
  309. /* for client, find the index of our pre-bound protocol */
  310. n = 0;
  311. while (wsi->vhost->protocols[n].callback) {
  312. if (wsi->protocol && strcmp(wsi->protocol->name,
  313. wsi->vhost->protocols[n].name) == 0) {
  314. wsi->protocol = &wsi->vhost->protocols[n];
  315. break;
  316. }
  317. n++;
  318. }
  319. if (!wsi->vhost->protocols[n].callback) {
  320. if (wsi->protocol)
  321. lwsl_err("Failed to match protocol %s\n",
  322. wsi->protocol->name);
  323. else
  324. lwsl_err("No protocol on client\n");
  325. goto bail2;
  326. }
  327. }
  328. lwsl_debug("Selected protocol %s\n", wsi->protocol->name);
  329. check_extensions:
  330. /*
  331. * stitch protocol choice into the vh protocol linked list
  332. * We always insert ourselves at the start of the list
  333. *
  334. * X <-> B
  335. * X <-> pAn <-> pB
  336. */
  337. lws_same_vh_protocol_insert(wsi, n);
  338. #if !defined(LWS_WITHOUT_EXTENSIONS)
  339. /* instantiate the accepted extensions */
  340. if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS)) {
  341. lwsl_ext("no client extensions allowed by server\n");
  342. goto check_accept;
  343. }
  344. /*
  345. * break down the list of server accepted extensions
  346. * and go through matching them or identifying bogons
  347. */
  348. if (lws_hdr_copy(wsi, sb, context->pt_serv_buf_size,
  349. WSI_TOKEN_EXTENSIONS) < 0) {
  350. lwsl_warn("ext list from server failed to copy\n");
  351. *cce = "HS: EXT: list too big";
  352. goto bail2;
  353. }
  354. c = sb;
  355. n = 0;
  356. ignore = 0;
  357. a = NULL;
  358. while (more) {
  359. if (*c && (*c != ',' && *c != '\t')) {
  360. if (*c == ';') {
  361. ignore = 1;
  362. if (!a)
  363. a = c + 1;
  364. }
  365. if (ignore || *c == ' ') {
  366. c++;
  367. continue;
  368. }
  369. ext_name[n] = *c++;
  370. if (n < (int)sizeof(ext_name) - 1)
  371. n++;
  372. continue;
  373. }
  374. ext_name[n] = '\0';
  375. ignore = 0;
  376. if (!*c)
  377. more = 0;
  378. else {
  379. c++;
  380. if (!n)
  381. continue;
  382. }
  383. /* check we actually support it */
  384. lwsl_notice("checking client ext %s\n", ext_name);
  385. n = 0;
  386. ext = wsi->vhost->ws.extensions;
  387. while (ext && ext->callback) {
  388. if (strcmp(ext_name, ext->name)) {
  389. ext++;
  390. continue;
  391. }
  392. n = 1;
  393. lwsl_notice("instantiating client ext %s\n", ext_name);
  394. /* instantiate the extension on this conn */
  395. wsi->ws->active_extensions[wsi->ws->count_act_ext] = ext;
  396. /* allow him to construct his ext instance */
  397. if (ext->callback(lws_get_context(wsi), ext, wsi,
  398. LWS_EXT_CB_CLIENT_CONSTRUCT,
  399. (void *)&wsi->ws->act_ext_user[
  400. wsi->ws->count_act_ext],
  401. (void *)&opts, 0)) {
  402. lwsl_info(" ext %s failed construction\n",
  403. ext_name);
  404. ext++;
  405. continue;
  406. }
  407. /*
  408. * allow the user code to override ext defaults if it
  409. * wants to
  410. */
  411. ext_name[0] = '\0';
  412. if (user_callback_handle_rxflow(wsi->protocol->callback,
  413. wsi, LWS_CALLBACK_WS_EXT_DEFAULTS,
  414. (char *)ext->name, ext_name,
  415. sizeof(ext_name))) {
  416. *cce = "HS: EXT: failed setting defaults";
  417. goto bail2;
  418. }
  419. if (ext_name[0] &&
  420. lws_ext_parse_options(ext, wsi,
  421. wsi->ws->act_ext_user[
  422. wsi->ws->count_act_ext],
  423. opts, ext_name,
  424. (int)strlen(ext_name))) {
  425. lwsl_err("%s: unable to parse user defaults '%s'",
  426. __func__, ext_name);
  427. *cce = "HS: EXT: failed parsing defaults";
  428. goto bail2;
  429. }
  430. /*
  431. * give the extension the server options
  432. */
  433. if (a && lws_ext_parse_options(ext, wsi,
  434. wsi->ws->act_ext_user[
  435. wsi->ws->count_act_ext],
  436. opts, a, lws_ptr_diff(c, a))) {
  437. lwsl_err("%s: unable to parse remote def '%s'",
  438. __func__, a);
  439. *cce = "HS: EXT: failed parsing options";
  440. goto bail2;
  441. }
  442. if (ext->callback(lws_get_context(wsi), ext, wsi,
  443. LWS_EXT_CB_OPTION_CONFIRM,
  444. wsi->ws->act_ext_user[wsi->ws->count_act_ext],
  445. NULL, 0)) {
  446. lwsl_err("%s: ext %s rejects server options %s",
  447. __func__, ext->name, a);
  448. *cce = "HS: EXT: Rejects server options";
  449. goto bail2;
  450. }
  451. wsi->ws->count_act_ext++;
  452. ext++;
  453. }
  454. if (n == 0) {
  455. lwsl_warn("Unknown ext '%s'!\n", ext_name);
  456. *cce = "HS: EXT: unknown ext";
  457. goto bail2;
  458. }
  459. a = NULL;
  460. n = 0;
  461. }
  462. check_accept:
  463. #endif
  464. /*
  465. * Confirm his accept token is the one we precomputed
  466. */
  467. p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_ACCEPT);
  468. if (strcmp(p, wsi->http.ah->initial_handshake_hash_base64)) {
  469. lwsl_warn("lws_client_int_s_hs: accept '%s' wrong vs '%s'\n", p,
  470. wsi->http.ah->initial_handshake_hash_base64);
  471. *cce = "HS: Accept hash wrong";
  472. goto bail2;
  473. }
  474. /* allocate the per-connection user memory (if any) */
  475. if (lws_ensure_user_space(wsi)) {
  476. lwsl_err("Problem allocating wsi user mem\n");
  477. *cce = "HS: OOM";
  478. goto bail2;
  479. }
  480. /*
  481. * we seem to be good to go, give client last chance to check
  482. * headers and OK it
  483. */
  484. if (wsi->protocol->callback(wsi,
  485. LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
  486. wsi->user_space, NULL, 0)) {
  487. *cce = "HS: Rejected by filter cb";
  488. goto bail2;
  489. }
  490. /* clear his proxy connection timeout */
  491. lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
  492. /* free up his parsing allocations */
  493. lws_header_table_detach(wsi, 0);
  494. lws_role_transition(wsi, LWSIFR_CLIENT, LRS_ESTABLISHED,
  495. &role_ops_ws);
  496. lws_restart_ws_ping_pong_timer(wsi);
  497. wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
  498. /*
  499. * create the frame buffer for this connection according to the
  500. * size mentioned in the protocol definition. If 0 there, then
  501. * use a big default for compatibility
  502. */
  503. n = (int)wsi->protocol->rx_buffer_size;
  504. if (!n)
  505. n = context->pt_serv_buf_size;
  506. n += LWS_PRE;
  507. wsi->ws->rx_ubuf = lws_malloc(n + 4 /* 0x0000ffff zlib */,
  508. "client frame buffer");
  509. if (!wsi->ws->rx_ubuf) {
  510. lwsl_err("Out of Mem allocating rx buffer %d\n", n);
  511. *cce = "HS: OOM";
  512. goto bail2;
  513. }
  514. wsi->ws->rx_ubuf_alloc = n;
  515. lwsl_info("Allocating client RX buffer %d\n", n);
  516. #if !defined(LWS_WITH_ESP32)
  517. if (setsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_SNDBUF,
  518. (const char *)&n, sizeof n)) {
  519. lwsl_warn("Failed to set SNDBUF to %d", n);
  520. *cce = "HS: SO_SNDBUF failed";
  521. goto bail3;
  522. }
  523. #endif
  524. lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name);
  525. /* call him back to inform him he is up */
  526. if (wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_ESTABLISHED,
  527. wsi->user_space, NULL, 0)) {
  528. *cce = "HS: Rejected at CLIENT_ESTABLISHED";
  529. goto bail3;
  530. }
  531. return 0;
  532. bail3:
  533. return 3;
  534. bail2:
  535. return 2;
  536. }