Coverage Report

Created: 2023-11-19 06:49

/src/libwebsockets/lib/roles/ws/server-ws.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * libwebsockets - small server side websockets and web server implementation
3
 *
4
 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to
8
 * deal in the Software without restriction, including without limitation the
9
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10
 * sell copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
 * IN THE SOFTWARE.
23
 */
24
25
#include <private-lib-core.h>
26
27
0
#define LWS_CPYAPP(ptr, str) { strcpy(ptr, str); ptr += strlen(str); }
28
29
#if !defined(LWS_WITHOUT_EXTENSIONS)
30
static int
31
lws_extension_server_handshake(struct lws *wsi, char **p, int budget)
32
{
33
  struct lws_context *context = wsi->a.context;
34
  struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
35
  char ext_name[64], *args, *end = (*p) + budget - 1;
36
  const struct lws_ext_options *opts, *po;
37
  const struct lws_extension *ext;
38
  struct lws_ext_option_arg oa;
39
  int n, m, more = 1;
40
  int ext_count = 0;
41
  char ignore;
42
  char *c;
43
44
  /*
45
   * Figure out which extensions the client has that we want to
46
   * enable on this connection, and give him back the list
47
   */
48
  if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS))
49
    return 0;
50
51
  /*
52
   * break down the list of client extensions
53
   * and go through them
54
   */
55
56
  if (lws_hdr_copy(wsi, (char *)pt->serv_buf, (int)context->pt_serv_buf_size,
57
       WSI_TOKEN_EXTENSIONS) < 0)
58
    return 1;
59
60
  c = (char *)pt->serv_buf;
61
  lwsl_parser("WSI_TOKEN_EXTENSIONS = '%s'\n", c);
62
  wsi->ws->count_act_ext = 0;
63
  ignore = 0;
64
  n = 0;
65
  args = NULL;
66
67
  /*
68
   * We may get a simple request
69
   *
70
   * Sec-WebSocket-Extensions: permessage-deflate
71
   *
72
   * or an elaborated one with requested options
73
   *
74
   * Sec-WebSocket-Extensions: permessage-deflate; \
75
   *           server_no_context_takeover; \
76
   *           client_no_context_takeover
77
   */
78
79
  while (more) {
80
81
    if (c >= (char *)pt->serv_buf + 255)
82
      return -1;
83
84
    if (*c && (*c != ',' && *c != '\t')) {
85
      if (*c == ';') {
86
        ignore = 1;
87
        if (!args)
88
          args = c + 1;
89
      }
90
      if (ignore || *c == ' ') {
91
        c++;
92
        continue;
93
      }
94
      ext_name[n] = *c++;
95
      if (n < (int)sizeof(ext_name) - 1)
96
        n++;
97
      continue;
98
    }
99
    ext_name[n] = '\0';
100
101
    ignore = 0;
102
    if (!*c)
103
      more = 0;
104
    else {
105
      c++;
106
      if (!n)
107
        continue;
108
    }
109
110
    while (args && *args == ' ')
111
      args++;
112
113
    /* check a client's extension against our support */
114
115
    ext = wsi->a.vhost->ws.extensions;
116
117
    while (ext && ext->callback) {
118
119
      if (strcmp(ext_name, ext->name)) {
120
        ext++;
121
        continue;
122
      }
123
124
      /*
125
       * oh, we do support this one he asked for... but let's
126
       * confirm he only gave it once
127
       */
128
      for (m = 0; m < wsi->ws->count_act_ext; m++)
129
        if (wsi->ws->active_extensions[m] == ext) {
130
          lwsl_info("ext mentioned twice\n");
131
          return 1; /* shenanigans */
132
        }
133
134
      /*
135
       * ask user code if it's OK to apply it on this
136
       * particular connection + protocol
137
       */
138
      m = (wsi->a.protocol->callback)(wsi,
139
        LWS_CALLBACK_CONFIRM_EXTENSION_OKAY,
140
        wsi->user_space, ext_name, 0);
141
142
      /*
143
       * zero return from callback means go ahead and allow
144
       * the extension, it's what we get if the callback is
145
       * unhandled
146
       */
147
      if (m) {
148
        ext++;
149
        continue;
150
      }
151
152
      /* apply it */
153
154
      ext_count++;
155
156
      /* instantiate the extension on this conn */
157
158
      wsi->ws->active_extensions[wsi->ws->count_act_ext] = ext;
159
160
      /* allow him to construct his context */
161
162
      if (ext->callback(lws_get_context(wsi), ext, wsi,
163
            LWS_EXT_CB_CONSTRUCT,
164
            (void *)&wsi->ws->act_ext_user[
165
                          wsi->ws->count_act_ext],
166
            (void *)&opts, 0)) {
167
        lwsl_info("ext %s failed construction\n",
168
              ext_name);
169
        ext_count--;
170
        ext++;
171
172
        continue;
173
      }
174
175
      if (ext_count > 1)
176
        *(*p)++ = ',';
177
      else
178
        LWS_CPYAPP(*p,
179
            "\x0d\x0aSec-WebSocket-Extensions: ");
180
      *p += lws_snprintf(*p, lws_ptr_diff_size_t(end, *p), "%s", ext_name);
181
182
      /*
183
       * The client may send a bunch of different option
184
       * sets for the same extension, we are supposed to
185
       * pick one we like the look of.  The option sets are
186
       * separated by comma.
187
       *
188
       * Actually we just either accept the first one or
189
       * nothing.
190
       *
191
       * Go through the options trying to apply the
192
       * recognized ones
193
       */
194
195
      lwsl_info("ext args %s\n", args);
196
197
      while (args && *args && *args != ',') {
198
        while (*args == ' ')
199
          args++;
200
        po = opts;
201
        while (po->name) {
202
          /* only support arg-less options... */
203
          if (po->type != EXTARG_NONE ||
204
              strncmp(args, po->name,
205
                strlen(po->name))) {
206
            po++;
207
            continue;
208
          }
209
          oa.option_name = NULL;
210
          oa.option_index = (int)(po - opts);
211
          oa.start = NULL;
212
          oa.len = 0;
213
          lwsl_info("setting '%s'\n", po->name);
214
          if (!ext->callback(lws_get_context(wsi),
215
                 ext, wsi,
216
            LWS_EXT_CB_OPTION_SET,
217
            wsi->ws->act_ext_user[
218
              wsi->ws->count_act_ext],
219
                &oa, lws_ptr_diff_size_t(end, *p))) {
220
221
            *p += lws_snprintf(*p,
222
                   lws_ptr_diff_size_t(end, *p),
223
                    "; %s", po->name);
224
            lwsl_debug("adding option %s\n",
225
                 po->name);
226
          }
227
          po++;
228
        }
229
        while (*args && *args != ',' && *args != ';')
230
          args++;
231
232
        if (*args == ';')
233
          args++;
234
      }
235
236
      wsi->ws->count_act_ext++;
237
      lwsl_parser("cnt_act_ext <- %d\n",
238
            wsi->ws->count_act_ext);
239
240
      if (args && *args == ',')
241
        more = 0;
242
243
      ext++;
244
    }
245
246
    n = 0;
247
    args = NULL;
248
  }
249
250
  return 0;
251
}
252
#endif
253
254
int
255
lws_process_ws_upgrade2(struct lws *wsi)
256
0
{
257
0
  struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
258
0
#if defined(LWS_WITH_HTTP_BASIC_AUTH)
259
0
  const struct lws_protocol_vhost_options *pvos = NULL;
260
0
  const char *ws_prot_basic_auth = NULL;
261
262
263
  /*
264
   * Allow basic auth a look-in now we bound the wsi to the protocol.
265
   *
266
   * For vhost ws basic auth, it is "basic-auth": "path" as usual but
267
   * applied to the protocol's entry in the vhost's "ws-protocols":
268
   * section, as a pvo.
269
   */
270
271
0
  pvos = lws_vhost_protocol_options(wsi->a.vhost, wsi->a.protocol->name);
272
0
  if (pvos && pvos->options &&
273
0
      !lws_pvo_get_str((void *)pvos->options, "basic-auth",
274
0
           &ws_prot_basic_auth)) {
275
0
    lwsl_info("%s: ws upgrade requires basic auth\n", __func__);
276
0
    switch (lws_check_basic_auth(wsi, ws_prot_basic_auth, LWSAUTHM_DEFAULT
277
0
            /* no callback based auth here */)) {
278
0
    case LCBA_CONTINUE:
279
0
      break;
280
0
    case LCBA_FAILED_AUTH:
281
0
      return lws_unauthorised_basic_auth(wsi);
282
0
    case LCBA_END_TRANSACTION:
283
0
      lws_return_http_status(wsi, HTTP_STATUS_FORBIDDEN, NULL);
284
0
      return lws_http_transaction_completed(wsi);
285
0
    }
286
0
  }
287
0
#endif
288
289
  /*
290
   * We are upgrading to ws, so http/1.1 + h2 and keepalive + pipelined
291
   * header considerations about keeping the ah around no longer apply.
292
   *
293
   * However it's common for the first ws protocol data to have been
294
   * coalesced with the browser upgrade request and to already be in the
295
   * ah rx buffer.
296
   */
297
298
0
  lws_pt_lock(pt, __func__);
299
300
  /*
301
   * Switch roles if we're upgrading away from http
302
   */
303
304
0
  if (!wsi->h2_stream_carries_ws) {
305
0
    lws_role_transition(wsi, LWSIFR_SERVER, LRS_ESTABLISHED,
306
0
            &role_ops_ws);
307
308
0
#if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SERVER)
309
310
    /*
311
     * If we're a SS server object, we have to switch to ss-ws
312
     * protocol handler too
313
     */
314
0
    if (wsi->a.vhost->ss_handle) {
315
0
      lwsl_info("%s: %s switching to ws protocol\n",
316
0
          __func__, lws_ss_tag(wsi->a.vhost->ss_handle));
317
0
      wsi->a.protocol = &protocol_secstream_ws;
318
319
      /*
320
       * inform the SS user code that this has done a one-way
321
       * upgrade to some other protocol... it will likely
322
       * want to treat subsequent payloads differently
323
       */
324
325
0
      (void)lws_ss_event_helper(wsi->a.vhost->ss_handle,
326
0
            LWSSSCS_SERVER_UPGRADE);
327
0
    }
328
0
#endif
329
0
  }
330
331
0
  lws_pt_unlock(pt);
332
333
  /* allocate the ws struct for the wsi */
334
335
0
  wsi->ws = lws_zalloc(sizeof(*wsi->ws), "ws struct");
336
0
  if (!wsi->ws) {
337
0
    lwsl_notice("OOM\n");
338
0
    return 1;
339
0
  }
340
341
0
  if (lws_hdr_total_length(wsi, WSI_TOKEN_VERSION))
342
0
    wsi->ws->ietf_spec_revision = (uint8_t)
343
0
             atoi(lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION));
344
345
  /* allocate wsi->user storage */
346
0
  if (lws_ensure_user_space(wsi)) {
347
0
    lwsl_notice("problem with user space\n");
348
0
    return 1;
349
0
  }
350
351
  /*
352
   * Give the user code a chance to study the request and
353
   * have the opportunity to deny it
354
   */
355
0
  if ((wsi->a.protocol->callback)(wsi,
356
0
      LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
357
0
      wsi->user_space,
358
0
          lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL), 0)) {
359
0
    lwsl_warn("User code denied connection\n");
360
0
    return 1;
361
0
  }
362
363
  /*
364
   * Perform the handshake according to the protocol version the
365
   * client announced
366
   */
367
368
0
  switch (wsi->ws->ietf_spec_revision) {
369
0
  default:
370
0
    lwsl_notice("Unknown client spec version %d\n",
371
0
        wsi->ws->ietf_spec_revision);
372
0
    wsi->ws->ietf_spec_revision = 13;
373
    //return 1;
374
    /* fallthru */
375
0
  case 13:
376
0
#if defined(LWS_WITH_HTTP2)
377
0
    if (wsi->h2_stream_carries_ws) {
378
0
      if (lws_h2_ws_handshake(wsi)) {
379
0
        lwsl_notice("h2 ws handshake failed\n");
380
0
        return 1;
381
0
      }
382
0
      lws_role_transition(wsi,
383
0
              LWSIFR_SERVER | LWSIFR_P_ENCAP_H2,
384
0
              LRS_ESTABLISHED, &role_ops_ws);
385
386
      /*
387
       * There should be no validity checking since we
388
       * are encapsulated in something else with its own
389
       * validity checking
390
       */
391
392
0
      lws_sul_cancel(&wsi->sul_validity);
393
0
    } else
394
0
#endif
395
0
    {
396
0
      lwsl_parser("lws_parse calling handshake_04\n");
397
0
      if (handshake_0405(wsi->a.context, wsi)) {
398
0
        lwsl_notice("hs0405 has failed the connection\n");
399
0
        return 1;
400
0
      }
401
0
    }
402
0
    break;
403
0
  }
404
405
0
  if (lws_server_init_wsi_for_ws(wsi)) {
406
0
    lwsl_notice("%s: user ESTABLISHED failed connection\n", __func__);
407
0
    return 1;
408
0
  }
409
0
  lwsl_parser("accepted v%02d connection\n", wsi->ws->ietf_spec_revision);
410
411
#if defined(LWS_WITH_ACCESS_LOG)
412
  {
413
    char *uptr = "unknown method", combo[128], dotstar[64];
414
    int l = 14, meth = lws_http_get_uri_and_method(wsi, &uptr, &l);
415
416
    if (wsi->h2_stream_carries_ws)
417
      wsi->http.request_version = HTTP_VERSION_2;
418
419
    wsi->http.access_log.response = 101;
420
421
    lws_strnncpy(dotstar, uptr, l, sizeof(dotstar));
422
    l = lws_snprintf(combo, sizeof(combo), "%s (%s)", dotstar,
423
         wsi->a.protocol->name);
424
425
    if (meth < 0)
426
      meth = 0;
427
    lws_prepare_access_log_info(wsi, combo, l, meth);
428
    lws_access_log(wsi);
429
  }
430
#endif
431
432
0
  lwsl_info("%s: %s: dropping ah on ws upgrade\n", __func__, lws_wsi_tag(wsi));
433
0
  lws_header_table_detach(wsi, 1);
434
435
0
  return 0;
436
0
}
437
438
int
439
lws_process_ws_upgrade(struct lws *wsi)
440
0
{
441
0
  const struct lws_protocols *pcol = NULL;
442
0
  char buf[128], name[64];
443
0
  struct lws_tokenize ts;
444
0
  lws_tokenize_elem e;
445
0
  int n;
446
447
0
  if (!wsi->a.protocol)
448
0
    lwsl_err("NULL protocol at lws_read\n");
449
450
  /*
451
   * It's either websocket or h2->websocket
452
   *
453
   * If we are on h1, confirm we got the required "connection: upgrade"
454
   * header.  h2 / ws-over-h2 does not have this.
455
   */
456
457
0
#if defined(LWS_WITH_HTTP2)
458
0
  if (!wsi->mux_substream) {
459
0
#endif
460
461
0
    lws_tokenize_init(&ts, buf, LWS_TOKENIZE_F_COMMA_SEP_LIST |
462
0
              LWS_TOKENIZE_F_DOT_NONTERM |
463
0
              LWS_TOKENIZE_F_RFC7230_DELIMS |
464
0
              LWS_TOKENIZE_F_MINUS_NONTERM);
465
0
    n = lws_hdr_copy(wsi, buf, sizeof(buf) - 1, WSI_TOKEN_CONNECTION);
466
0
    if (n <= 0)
467
0
      goto bad_conn_format;
468
0
    ts.len = (unsigned int)n;
469
470
0
    do {
471
0
      e = lws_tokenize(&ts);
472
0
      switch (e) {
473
0
      case LWS_TOKZE_TOKEN:
474
0
        if (!strncasecmp(ts.token, "upgrade", ts.token_len))
475
0
          e = LWS_TOKZE_ENDED;
476
0
        break;
477
478
0
      case LWS_TOKZE_DELIMITER:
479
0
        break;
480
481
0
      default: /* includes ENDED */
482
0
  bad_conn_format:
483
0
        lwsl_err("%s: malformed or absent conn hdr\n",
484
0
           __func__);
485
486
0
        return 1;
487
0
      }
488
0
    } while (e > 0);
489
490
0
#if defined(LWS_WITH_HTTP2)
491
0
  }
492
0
#endif
493
494
#if defined(LWS_WITH_HTTP_PROXY)
495
  {
496
    const struct lws_http_mount *hit;
497
    int uri_len = 0, meth;
498
    char *uri_ptr;
499
500
    meth = lws_http_get_uri_and_method(wsi, &uri_ptr, &uri_len);
501
    hit = lws_find_mount(wsi, uri_ptr, uri_len);
502
503
    if (hit && (meth == LWSHUMETH_GET ||
504
          meth == LWSHUMETH_CONNECT ||
505
          meth == LWSHUMETH_COLON_PATH) &&
506
        (hit->origin_protocol == LWSMPRO_HTTPS ||
507
         hit->origin_protocol == LWSMPRO_HTTP))
508
      /*
509
       * We are an h1 ws upgrade on a urlpath that corresponds
510
       * to a proxying mount.  Don't try to deal with it
511
       * locally, eg, we won't even have the right protocol
512
       * handler since we're not the guy handling it, just a
513
       * conduit.
514
       *
515
       * Instead open the related ongoing h1 connection
516
       * according to the mount configuration and proxy
517
       * whatever that has to say from now on.
518
       */
519
      return lws_http_proxy_start(wsi, hit, uri_ptr, 1);
520
  }
521
#endif
522
523
  /*
524
   * Select the first protocol we support from the list
525
   * the client sent us.
526
   */
527
528
0
  lws_tokenize_init(&ts, buf, LWS_TOKENIZE_F_COMMA_SEP_LIST |
529
0
            LWS_TOKENIZE_F_MINUS_NONTERM |
530
0
            LWS_TOKENIZE_F_DOT_NONTERM |
531
0
            LWS_TOKENIZE_F_RFC7230_DELIMS);
532
0
  n = lws_hdr_copy(wsi, buf, sizeof(buf) - 1, WSI_TOKEN_PROTOCOL);
533
0
  if (n < 0) {
534
0
    lwsl_err("%s: protocol list too long\n", __func__);
535
0
    return 1;
536
0
  }
537
0
  ts.len = (unsigned int)n;
538
0
  if (!ts.len) {
539
0
    int n = wsi->a.vhost->default_protocol_index;
540
    /*
541
     * Some clients only have one protocol and do not send the
542
     * protocol list header... allow it and match to the vhost's
543
     * default protocol (which itself defaults to zero).
544
     *
545
     * Setting the vhost default protocol index to -1 or anything
546
     * more than the actual number of protocols on the vhost causes
547
     * these "no protocol" ws connections to be rejected.
548
     */
549
550
0
    if (n >= wsi->a.vhost->count_protocols) {
551
0
      lwsl_notice("%s: rejecting ws upg with no protocol\n",
552
0
            __func__);
553
554
0
      return 1;
555
0
    }
556
557
0
    lwsl_info("%s: defaulting to prot handler %d\n", __func__, n);
558
559
0
    lws_bind_protocol(wsi, &wsi->a.vhost->protocols[n],
560
0
          "ws upgrade default pcol");
561
562
0
    goto alloc_ws;
563
0
  }
564
565
0
#if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SERVER)
566
0
  if (wsi->a.vhost->ss_handle) {
567
0
    lws_ss_handle_t *sssh = wsi->a.vhost->ss_handle;
568
569
    /*
570
     * At the moment, once we see it's a ss ws server, whatever
571
     * he asked for we bind him to the ss-ws protocol handler.
572
     *
573
     * In the response subprotocol header, we need to name
574
     *
575
     * sssh->policy->u.http.u.ws.subprotocol
576
     *
577
     * though...
578
     */
579
580
0
    if (sssh->policy->u.http.u.ws.subprotocol) {
581
0
      pcol = lws_vhost_name_to_protocol(wsi->a.vhost,
582
0
                "lws-secstream-ws");
583
0
      if (pcol) {
584
0
        lws_bind_protocol(wsi, pcol, "ss ws upg pcol");
585
586
0
        goto alloc_ws;
587
0
      }
588
0
    }
589
0
  }
590
0
#endif
591
592
  /* otherwise go through the user-provided protocol list */
593
594
0
  do {
595
0
    e = lws_tokenize(&ts);
596
0
    switch (e) {
597
0
    case LWS_TOKZE_TOKEN:
598
599
0
      if (lws_tokenize_cstr(&ts, name, sizeof(name))) {
600
0
        lwsl_err("%s: pcol name too long\n", __func__);
601
602
0
        return 1;
603
0
      }
604
0
      lwsl_debug("checking %s\n", name);
605
0
      pcol = lws_vhost_name_to_protocol(wsi->a.vhost, name);
606
0
      if (pcol) {
607
        /* if we know it, bind to it and stop looking */
608
0
        lws_bind_protocol(wsi, pcol, "ws upg pcol");
609
0
        e = LWS_TOKZE_ENDED;
610
0
      }
611
0
      break;
612
613
0
    case LWS_TOKZE_DELIMITER:
614
0
    case LWS_TOKZE_ENDED:
615
0
      break;
616
617
0
    default:
618
0
      lwsl_err("%s: malformatted protocol list", __func__);
619
620
0
      return 1;
621
0
    }
622
0
  } while (e > 0);
623
624
  /* we didn't find a protocol he wanted? */
625
626
0
  if (!pcol) {
627
0
    lwsl_notice("No supported protocol \"%s\"\n", buf);
628
629
0
    return 1;
630
0
  }
631
632
0
alloc_ws:
633
634
0
  return lws_process_ws_upgrade2(wsi);
635
0
}
636
637
int
638
handshake_0405(struct lws_context *context, struct lws *wsi)
639
0
{
640
0
  struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
641
0
  struct lws_process_html_args args;
642
0
  unsigned char hash[20];
643
0
  int n, accept_len;
644
0
  char *response;
645
0
  char *p;
646
647
0
  if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST) ||
648
0
      !lws_hdr_total_length(wsi, WSI_TOKEN_KEY)) {
649
0
    lwsl_info("handshake_04 missing pieces\n");
650
    /* completed header processing, but missing some bits */
651
0
    goto bail;
652
0
  }
653
654
0
  if (lws_hdr_total_length(wsi, WSI_TOKEN_KEY) >=
655
0
      MAX_WEBSOCKET_04_KEY_LEN) {
656
0
    lwsl_warn("Client key too long %d\n", MAX_WEBSOCKET_04_KEY_LEN);
657
0
    goto bail;
658
0
  }
659
660
  /*
661
   * since key length is restricted above (currently 128), cannot
662
   * overflow
663
   */
664
0
  n = sprintf((char *)pt->serv_buf,
665
0
        "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
666
0
        lws_hdr_simple_ptr(wsi, WSI_TOKEN_KEY));
667
668
0
  lws_SHA1(pt->serv_buf, (unsigned int)n, hash);
669
670
0
  accept_len = lws_b64_encode_string((char *)hash, 20,
671
0
      (char *)pt->serv_buf, (int)context->pt_serv_buf_size);
672
0
  if (accept_len < 0) {
673
0
    lwsl_warn("Base64 encoded hash too long\n");
674
0
    goto bail;
675
0
  }
676
677
  /* allocate the per-connection user memory (if any) */
678
0
  if (lws_ensure_user_space(wsi))
679
0
    goto bail;
680
681
  /* create the response packet */
682
683
  /* make a buffer big enough for everything */
684
685
0
  response = (char *)pt->serv_buf + MAX_WEBSOCKET_04_KEY_LEN +
686
0
       256 + LWS_PRE;
687
0
  p = response;
688
0
  LWS_CPYAPP(p, "HTTP/1.1 101 Switching Protocols\x0d\x0a"
689
0
          "Upgrade: WebSocket\x0d\x0a"
690
0
          "Connection: Upgrade\x0d\x0a"
691
0
          "Sec-WebSocket-Accept: ");
692
0
  strcpy(p, (char *)pt->serv_buf);
693
0
  p += accept_len;
694
695
  /* we can only return the protocol header if:
696
   *  - one came in, and ... */
697
0
  if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL) &&
698
      /*  - it is not an empty string */
699
0
      wsi->a.protocol->name &&
700
0
      wsi->a.protocol->name[0]) {
701
0
    const char *prot = wsi->a.protocol->name;
702
703
#if defined(LWS_WITH_HTTP_PROXY)
704
    if (wsi->proxied_ws_parent && wsi->child_list)
705
      prot = wsi->child_list->ws->actual_protocol;
706
#endif
707
708
0
#if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SERVER)
709
0
    {
710
0
      lws_ss_handle_t *sssh = wsi->a.vhost->ss_handle;
711
712
      /*
713
       * At the moment, once we see it's a ss ws server, whatever
714
       * he asked for we bind him to the ss-ws protocol handler.
715
       *
716
       * In the response subprotocol header, we need to name
717
       *
718
       * sssh->policy->u.http.u.ws.subprotocol
719
       *
720
       * though...
721
       */
722
723
0
      if (sssh && sssh->policy &&
724
0
          sssh->policy->u.http.u.ws.subprotocol)
725
0
        prot = sssh->policy->u.http.u.ws.subprotocol;
726
0
    }
727
0
#endif
728
729
0
    LWS_CPYAPP(p, "\x0d\x0aSec-WebSocket-Protocol: ");
730
0
    p += lws_snprintf(p, 128, "%s", prot);
731
0
  }
732
733
#if !defined(LWS_WITHOUT_EXTENSIONS)
734
  /*
735
   * Figure out which extensions the client has that we want to
736
   * enable on this connection, and give him back the list.
737
   *
738
   * Give him a limited write bugdet
739
   */
740
  if (lws_extension_server_handshake(wsi, &p, 192))
741
    goto bail;
742
#endif
743
0
  LWS_CPYAPP(p, "\x0d\x0a");
744
745
0
  args.p = p;
746
0
  args.max_len = lws_ptr_diff((char *)pt->serv_buf +
747
0
            context->pt_serv_buf_size, p);
748
0
  if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi,
749
0
          LWS_CALLBACK_ADD_HEADERS,
750
0
          wsi->user_space, &args, 0))
751
0
    goto bail;
752
753
0
  p = args.p;
754
755
  /* end of response packet */
756
757
0
  LWS_CPYAPP(p, "\x0d\x0a");
758
759
  /* okay send the handshake response accepting the connection */
760
761
0
  lwsl_parser("issuing resp pkt %d len\n",
762
0
        lws_ptr_diff(p, response));
763
#if defined(DEBUG)
764
  fwrite(response, 1,  p - response, stderr);
765
#endif
766
0
  n = lws_write(wsi, (unsigned char *)response, lws_ptr_diff_size_t(p, response),
767
0
          LWS_WRITE_HTTP_HEADERS);
768
0
  if (n != lws_ptr_diff(p, response)) {
769
0
    lwsl_info("%s: ERROR writing to socket %d\n", __func__, n);
770
0
    goto bail;
771
0
  }
772
773
  /* alright clean up and set ourselves into established state */
774
775
0
  lwsi_set_state(wsi, LRS_ESTABLISHED);
776
0
  wsi->lws_rx_parse_state = LWS_RXPS_NEW;
777
778
0
  {
779
0
    const char * uri_ptr =
780
0
      lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI);
781
0
    int uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI);
782
0
    const struct lws_http_mount *hit =
783
0
      lws_find_mount(wsi, uri_ptr, uri_len);
784
0
    if (hit && hit->cgienv &&
785
0
        wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP_PMO,
786
0
      wsi->user_space, (void *)hit->cgienv, 0))
787
0
      return 1;
788
0
  }
789
790
0
  return 0;
791
792
0
bail:
793
  /* caller will free up his parsing allocations */
794
0
  return -1;
795
0
}
796
797
798
799
/*
800
 * Once we reach LWS_RXPS_WS_FRAME_PAYLOAD, we know how much
801
 * to expect in that state and can deal with it in bulk more efficiently.
802
 */
803
804
static int
805
lws_ws_frame_rest_is_payload(struct lws *wsi, uint8_t **buf, size_t len)
806
0
{
807
0
  struct lws_ext_pm_deflate_rx_ebufs pmdrx;
808
0
  unsigned int avail = (unsigned int)len;
809
0
  uint8_t *buffer = *buf, mask[4];
810
#if !defined(LWS_WITHOUT_EXTENSIONS)
811
  unsigned int old_packet_length = (unsigned int)wsi->ws->rx_packet_length;
812
#endif
813
0
  int n = 0;
814
815
  /*
816
   * With zlib, we can give it as much input as we like.  The pmd
817
   * extension will draw it down in chunks (default 1024).
818
   *
819
   * If we try to restrict how much we give it, because we must go
820
   * back to the event loop each time, we will drop the remainder...
821
   */
822
823
#if !defined(LWS_WITHOUT_EXTENSIONS)
824
  if (!wsi->ws->count_act_ext)
825
#endif
826
0
  {
827
0
    if (wsi->a.protocol->rx_buffer_size)
828
0
      avail = (unsigned int)wsi->a.protocol->rx_buffer_size;
829
0
    else
830
0
      avail = wsi->a.context->pt_serv_buf_size;
831
0
  }
832
833
  /* do not consume more than we should */
834
0
  if (avail > wsi->ws->rx_packet_length)
835
0
    avail = (unsigned int)wsi->ws->rx_packet_length;
836
837
  /* do not consume more than what is in the buffer */
838
0
  if (avail > len)
839
0
    avail = (unsigned int)len;
840
841
0
  if (!avail)
842
0
    return 0;
843
844
0
  pmdrx.eb_in.token = buffer;
845
0
  pmdrx.eb_in.len = (int)avail;
846
0
  pmdrx.eb_out.token = buffer;
847
0
  pmdrx.eb_out.len = (int)avail;
848
849
0
  if (!wsi->ws->all_zero_nonce) {
850
851
0
    for (n = 0; n < 4; n++)
852
0
      mask[n] = wsi->ws->mask[(wsi->ws->mask_idx + n) & 3];
853
854
    /* deal with 4-byte chunks using unwrapped loop */
855
0
    n = (int)(avail >> 2);
856
0
    while (n--) {
857
0
      *(buffer) = *(buffer) ^ mask[0];
858
0
      buffer++;
859
0
      *(buffer) = *(buffer) ^ mask[1];
860
0
      buffer++;
861
0
      *(buffer) = *(buffer) ^ mask[2];
862
0
      buffer++;
863
0
      *(buffer) = *(buffer) ^ mask[3];
864
0
      buffer++;
865
0
    }
866
    /* and the remaining bytes bytewise */
867
0
    for (n = 0; n < (int)(avail & 3); n++) {
868
0
      *(buffer) = *(buffer) ^ mask[n];
869
0
      buffer++;
870
0
    }
871
872
0
    wsi->ws->mask_idx = (wsi->ws->mask_idx + avail) & 3;
873
0
  }
874
875
0
  lwsl_info("%s: using %d of raw input (total %d on offer)\n", __func__,
876
0
        avail, (int)len);
877
878
0
  (*buf) += avail;
879
0
  len -= avail;
880
0
  wsi->ws->rx_packet_length -= avail;
881
882
#if !defined(LWS_WITHOUT_EXTENSIONS)
883
  n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &pmdrx, 0);
884
  lwsl_info("%s: ext says %d / ebuf_out.len %d\n", __func__,  n,
885
      pmdrx.eb_out.len);
886
887
  /*
888
   * ebuf may be pointing somewhere completely different now,
889
   * it's the output
890
   */
891
892
  if (n < 0) {
893
    /*
894
     * we may rely on this to get RX, just drop connection
895
     */
896
    lwsl_notice("%s: LWS_EXT_CB_PAYLOAD_RX blew out\n", __func__);
897
    wsi->socket_is_permanently_unusable = 1;
898
899
    return -1;
900
  }
901
902
  /*
903
   * if we had an rx fragment right at the last compressed byte of the
904
   * message, we can get a zero length inflated output, where no prior
905
   * rx inflated output marked themselves with FIN, since there was
906
   * raw ws payload still to drain at that time.
907
   *
908
   * Then we need to generate a zero length ws rx that can be understood
909
   * as the message completion.
910
   */
911
912
  if (!pmdrx.eb_out.len &&        /* zero-length inflation output */
913
      n == PMDR_EMPTY_FINAL &&    /* nothing to drain from the inflator */
914
      old_packet_length &&      /* we gave the inflator new input */
915
      !wsi->ws->rx_packet_length &&   /* raw ws packet payload all gone */
916
      wsi->ws->final &&       /* the raw ws packet is a FIN guy */
917
      wsi->a.protocol->callback &&
918
      !wsi->wsistate_pre_close) {
919
920
    lwsl_ext("%s: issuing zero length FIN pkt\n", __func__);
921
922
    if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi,
923
            LWS_CALLBACK_RECEIVE,
924
            wsi->user_space, NULL, 0))
925
      return -1;
926
927
    return (int)avail;
928
  }
929
930
  /*
931
   * If doing permessage-deflate, above was the only way to get a zero
932
   * length receive.  Otherwise we're more willing.
933
   */
934
  if (wsi->ws->count_act_ext && !pmdrx.eb_out.len)
935
    return (int)avail;
936
937
  if (n == PMDR_HAS_PENDING)
938
    /* extension had more... main loop will come back */
939
    lws_add_wsi_to_draining_ext_list(wsi);
940
  else
941
    lws_remove_wsi_from_draining_ext_list(wsi);
942
#endif
943
944
0
  if (pmdrx.eb_out.len &&
945
0
      wsi->ws->check_utf8 && !wsi->ws->defeat_check_utf8) {
946
0
    if (lws_check_utf8(&wsi->ws->utf8,
947
0
           pmdrx.eb_out.token,
948
0
           (unsigned int)pmdrx.eb_out.len)) {
949
0
      lws_close_reason(wsi, LWS_CLOSE_STATUS_INVALID_PAYLOAD,
950
0
           (uint8_t *)"bad utf8", 8);
951
0
      goto utf8_fail;
952
0
    }
953
954
    /* we are ending partway through utf-8 character? */
955
0
    if (!wsi->ws->rx_packet_length && wsi->ws->final &&
956
0
        wsi->ws->utf8 && !n) {
957
0
      lwsl_info("FINAL utf8 error\n");
958
0
      lws_close_reason(wsi, LWS_CLOSE_STATUS_INVALID_PAYLOAD,
959
0
           (uint8_t *)"partial utf8", 12);
960
961
0
utf8_fail:
962
0
      lwsl_info("utf8 error\n");
963
0
      lwsl_hexdump_info(pmdrx.eb_out.token, (size_t)pmdrx.eb_out.len);
964
965
0
      return -1;
966
0
    }
967
0
  }
968
969
0
  if (wsi->a.protocol->callback && !wsi->wsistate_pre_close)
970
0
    if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi,
971
0
            LWS_CALLBACK_RECEIVE,
972
0
            wsi->user_space,
973
0
            pmdrx.eb_out.token,
974
0
            (unsigned int)pmdrx.eb_out.len))
975
0
      return -1;
976
977
0
  wsi->ws->first_fragment = 0;
978
979
#if !defined(LWS_WITHOUT_EXTENSIONS)
980
  lwsl_info("%s: input used %d, output %d, rem len %d, rx_draining_ext %d\n",
981
      __func__, avail, pmdrx.eb_out.len, (int)len,
982
      wsi->ws->rx_draining_ext);
983
#endif
984
985
0
  return (int)avail; /* how much we used from the input */
986
0
}
987
988
989
int
990
lws_parse_ws(struct lws *wsi, unsigned char **buf, size_t len)
991
0
{
992
0
  unsigned char *bufin = *buf;
993
0
  int m, bulk = 0;
994
995
0
  lwsl_debug("%s: received %d byte packet\n", __func__, (int)len);
996
997
  //lwsl_hexdump_notice(*buf, len);
998
999
  /* let the rx protocol state machine have as much as it needs */
1000
1001
0
  while (len) {
1002
    /*
1003
     * we were accepting input but now we stopped doing so
1004
     */
1005
0
    if (wsi->rxflow_bitmap) {
1006
0
      lwsl_info("%s: doing rxflow, caching %d\n", __func__,
1007
0
        (int)len);
1008
      /*
1009
       * Since we cached the remaining available input, we
1010
       * can say we "consumed" it.
1011
       *
1012
       * But what about the case where the available input
1013
       * came out of the rxflow cache already?  If we are
1014
       * effectively "putting it back in the cache", we have
1015
       * leave it where it is, already pointed to by the head.
1016
       */
1017
0
      if (lws_rxflow_cache(wsi, *buf, 0, len) ==
1018
0
              LWSRXFC_TRIMMED) {
1019
        /*
1020
         * We dealt with it by trimming the existing
1021
         * rxflow cache HEAD to account for what we used.
1022
         *
1023
         * so he doesn't do any consumed processing
1024
         */
1025
0
        lwsl_info("%s: trimming inside rxflow cache\n",
1026
0
            __func__);
1027
0
        *buf = bufin;
1028
0
      } else
1029
0
        *buf += len;
1030
1031
0
      return 1;
1032
0
    }
1033
#if !defined(LWS_WITHOUT_EXTENSIONS)
1034
    if (wsi->ws->rx_draining_ext) {
1035
      lwsl_debug("%s: draining rx ext\n", __func__);
1036
      m = lws_ws_rx_sm(wsi, ALREADY_PROCESSED_IGNORE_CHAR, 0);
1037
      if (m < 0)
1038
        return -1;
1039
      continue;
1040
    }
1041
#endif
1042
1043
    /* consume payload bytes efficiently */
1044
0
    while (wsi->lws_rx_parse_state == LWS_RXPS_WS_FRAME_PAYLOAD &&
1045
0
        (wsi->ws->opcode == LWSWSOPC_TEXT_FRAME ||
1046
0
         wsi->ws->opcode == LWSWSOPC_BINARY_FRAME ||
1047
0
         wsi->ws->opcode == LWSWSOPC_CONTINUATION) &&
1048
0
           len) {
1049
0
      uint8_t *bin = *buf;
1050
1051
0
      bulk = 1;
1052
0
      m = lws_ws_frame_rest_is_payload(wsi, buf, len);
1053
0
      assert((int)lws_ptr_diff(*buf, bin) <= (int)len);
1054
0
      len -= lws_ptr_diff_size_t(*buf, bin);
1055
1056
0
      if (!m) {
1057
1058
0
        break;
1059
0
      }
1060
0
      if (m < 0) {
1061
0
        lwsl_info("%s: rest_is_payload bailed\n",
1062
0
            __func__);
1063
0
        return -1;
1064
0
      }
1065
0
    }
1066
1067
0
    if (!bulk) {
1068
      /* process the byte */
1069
0
      m = lws_ws_rx_sm(wsi, 0, *(*buf)++);
1070
0
      len--;
1071
0
    } else {
1072
      /*
1073
       * We already handled this byte in bulk, just deal
1074
       * with the ramifications
1075
       */
1076
#if !defined(LWS_WITHOUT_EXTENSIONS)
1077
      lwsl_debug("%s: coming out of bulk with len %d, "
1078
           "wsi->ws->rx_draining_ext %d\n",
1079
           __func__, (int)len,
1080
           wsi->ws->rx_draining_ext);
1081
#endif
1082
0
      m = lws_ws_rx_sm(wsi, ALREADY_PROCESSED_IGNORE_CHAR |
1083
0
                ALREADY_PROCESSED_NO_CB, 0);
1084
0
    }
1085
1086
0
    if (m < 0) {
1087
0
      lwsl_info("%s: lws_ws_rx_sm bailed %d\n", __func__,
1088
0
          bulk);
1089
1090
0
      return -1;
1091
0
    }
1092
1093
0
    bulk = 0;
1094
0
  }
1095
1096
0
  lwsl_debug("%s: exit with %d unused\n", __func__, (int)len);
1097
1098
0
  return 0;
1099
0
}