ssl: improve client error message on server cert probs
[platform/upstream/libwebsockets.git] / lib / client.c
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010-2014 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
22 #include "private-libwebsockets.h"
23
24 int lws_handshake_client(struct libwebsocket *wsi, unsigned char **buf, size_t len)
25 {
26         int n;
27
28         switch (wsi->mode) {
29         case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:
30         case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
31         case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
32         case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
33         case LWS_CONNMODE_WS_CLIENT:
34                 for (n = 0; n < len; n++)
35                         if (libwebsocket_client_rx_sm(wsi, *(*buf)++)) {
36                                 lwsl_debug("client_rx_sm failed\n");
37                                 return 1;
38                         }
39                 return 0;
40         default:
41                 break;
42         }
43         return 0;
44 }
45
46 int lws_client_socket_service(struct libwebsocket_context *context,
47                 struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd)
48 {
49         int n;
50         char *p = (char *)&context->service_buffer[0];
51         int len;
52         unsigned char c;
53
54         switch (wsi->mode) {
55
56         case LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT:
57
58                 /*
59                  * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
60                  * timeout protection set in client-handshake.c
61                  */
62
63                if (libwebsocket_client_connect_2(context, wsi) == NULL) {
64                         /* closed */
65                         lwsl_client("closed\n");
66                         return -1;
67                 }
68
69                 /* either still pending connection, or changed mode */
70                 return 0;
71
72         case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:
73
74                 /* handle proxy hung up on us */
75
76                 if (pollfd->revents & LWS_POLLHUP) {
77
78                         lwsl_warn("Proxy connection %p (fd=%d) dead\n",
79                                 (void *)wsi, pollfd->fd);
80
81                         libwebsocket_close_and_free_session(context, wsi,
82                                                      LWS_CLOSE_STATUS_NOSTATUS);
83                         return 0;
84                 }
85
86                 n = recv(wsi->sock, context->service_buffer,
87                                         sizeof(context->service_buffer), 0);
88                 if (n < 0) {
89                         
90                         if (LWS_ERRNO == LWS_EAGAIN) {
91                                 lwsl_debug(
92                                                    "Proxy read returned EAGAIN... retrying\n");
93                                 return 0;
94                         }
95                         
96                         libwebsocket_close_and_free_session(context, wsi,
97                                                      LWS_CLOSE_STATUS_NOSTATUS);
98                         lwsl_err("ERROR reading from proxy socket\n");
99                         return 0;
100                 }
101
102                 context->service_buffer[13] = '\0';
103                 if (strcmp((char *)context->service_buffer, "HTTP/1.0 200 ")) {
104                         libwebsocket_close_and_free_session(context, wsi,
105                                                      LWS_CLOSE_STATUS_NOSTATUS);
106                         lwsl_err("ERROR proxy: %s\n", context->service_buffer);
107                         return 0;
108                 }
109
110                 /* clear his proxy connection timeout */
111
112                 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
113
114                 /* fallthru */
115
116         case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
117
118                 /*
119                  * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
120                  * timeout protection set in client-handshake.c
121                  */
122
123                 /*
124                  * take care of our libwebsocket_callback_on_writable
125                  * happening at a time when there's no real connection yet
126                  */
127                 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
128                         return -1;
129
130 #ifdef LWS_OPENSSL_SUPPORT
131                 /* we can retry this... just cook the SSL BIO the first time */
132
133                 if (wsi->use_ssl && !wsi->ssl) {
134 #if defined(CYASSL_SNI_HOST_NAME) || defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
135                         const char *hostname = lws_hdr_simple_ptr(wsi,
136                                                 _WSI_TOKEN_CLIENT_PEER_ADDRESS);
137 #endif
138
139                         wsi->ssl = SSL_new(context->ssl_client_ctx);
140 #ifndef USE_CYASSL
141                         SSL_set_mode(wsi->ssl,
142                                         SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
143 #endif
144                         /*
145                          * use server name indication (SNI), if supported,
146                          * when establishing connection
147                          */
148 #ifdef USE_CYASSL
149 #ifdef CYASSL_SNI_HOST_NAME
150                         CyaSSL_UseSNI(wsi->ssl, CYASSL_SNI_HOST_NAME,
151                                 hostname, strlen(hostname));
152 #endif
153 #else
154 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
155                         SSL_set_tlsext_host_name(wsi->ssl, hostname);
156 #endif
157 #endif
158
159 #ifdef USE_CYASSL
160                         /*
161                          * CyaSSL does certificate verification differently
162                          * from OpenSSL.
163                          * If we should ignore the certificate, we need to set
164                          * this before SSL_new and SSL_connect is called.
165                          * Otherwise the connect will simply fail with error
166                          * code -155
167                          */
168                         if (wsi->use_ssl == 2)
169                                 CyaSSL_set_verify(wsi->ssl,
170                                                         SSL_VERIFY_NONE, NULL);
171 #endif /* USE_CYASSL */
172
173                         wsi->client_bio =
174                                 BIO_new_socket(wsi->sock, BIO_NOCLOSE);
175                         SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
176
177 #ifdef USE_CYASSL
178                         CyaSSL_set_using_nonblock(wsi->ssl, 1);
179 #else
180                         BIO_set_nbio(wsi->client_bio, 1); /* nonblocking */
181 #endif
182
183                         SSL_set_ex_data(wsi->ssl,
184                                         openssl_websocket_private_data_index,
185                                                                        context);
186                 }
187
188                 if (wsi->use_ssl) {
189                         lws_latency_pre(context, wsi);
190                         n = SSL_connect(wsi->ssl);
191                         lws_latency(context, wsi,
192                           "SSL_connect LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE",
193                                                                       n, n > 0);
194
195                         if (n < 0) {
196                                 n = SSL_get_error(wsi->ssl, n);
197
198                                 if (n == SSL_ERROR_WANT_READ ||
199                                         n == SSL_ERROR_WANT_WRITE) {
200                                         /*
201                                          * wants us to retry connect due to
202                                          * state of the underlying ssl layer...
203                                          * but since it may be stalled on
204                                          * blocked write, no incoming data may
205                                          * arrive to trigger the retry.
206                                          * Force (possibly many times if the SSL
207                                          * state persists in returning the
208                                          * condition code, but other sockets
209                                          * are getting serviced inbetweentimes)
210                                          * us to get called back when writable.
211                                          */
212
213                                         lwsl_info(
214                                              "SSL_connect WANT_... retrying\n");
215                                         libwebsocket_callback_on_writable(
216                                                                   context, wsi);
217                                         
218                                         wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SSL;
219                                         
220                                         return 0; /* no error */
221                                 }
222                                 n = -1;
223                         }
224
225                         if (n <= 0) {
226                                 /*
227                                  * retry if new data comes until we
228                                  * run into the connection timeout or win
229                                  */
230                                 
231                                 n = ERR_get_error();
232                                 if (n != SSL_ERROR_NONE) {
233                                         lwsl_err("SSL connect error %lu: %s\n",
234                                                 n,
235                                                 ERR_error_string(n,
236                                                           (char *)context->service_buffer));
237                                         return 0;
238                                 }
239                         }
240                 } else
241                         wsi->ssl = NULL;
242
243                 /* fallthru */
244                         
245         case LWS_CONNMODE_WS_CLIENT_WAITING_SSL:
246                         
247                 if (wsi->use_ssl) {
248                                 
249                         if (wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_SSL) {
250                                 lws_latency_pre(context, wsi);
251                                 n = SSL_connect(wsi->ssl);
252                                 lws_latency(context, wsi,
253                                                         "SSL_connect LWS_CONNMODE_WS_CLIENT_WAITING_SSL",
254                                                         n, n > 0);
255                                 
256                                 if (n < 0) {
257                                         n = SSL_get_error(wsi->ssl, n);
258                                         
259                                         if (n == SSL_ERROR_WANT_READ ||
260                                                 n == SSL_ERROR_WANT_WRITE) {
261                                                 /*
262                                                  * wants us to retry connect due to
263                                                  * state of the underlying ssl layer...
264                                                  * but since it may be stalled on
265                                                  * blocked write, no incoming data may
266                                                  * arrive to trigger the retry.
267                                                  * Force (possibly many times if the SSL
268                                                  * state persists in returning the
269                                                  * condition code, but other sockets
270                                                  * are getting serviced inbetweentimes)
271                                                  * us to get called back when writable.
272                                                  */
273                                                 
274                                                 lwsl_info(
275                                                                   "SSL_connect WANT_... retrying\n");
276                                                 libwebsocket_callback_on_writable(
277                                                                                                                   context, wsi);
278                                                 
279                                                 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SSL;
280                                                 
281                                                 return 0; /* no error */
282                                         }
283                                         n = -1;
284                                 }
285                                 
286                                 if (n <= 0) {
287                                         /*
288                                          * retry if new data comes until we
289                                          * run into the connection timeout or win
290                                          */
291                                         n = ERR_get_error();
292                                         if (n != SSL_ERROR_NONE) {
293                                                 lwsl_err("SSL connect error %lu: %s\n",
294                                                                  n,
295                                                                  ERR_error_string(n,
296                                                                                                   (char *)context->service_buffer));
297                                                 return 0;
298                                         }
299                                 }
300                         }
301                         
302                         #ifndef USE_CYASSL
303                         /*
304                          * See comment above about CyaSSL certificate
305                          * verification
306                          */
307                         lws_latency_pre(context, wsi);
308                         n = SSL_get_verify_result(wsi->ssl);
309                         lws_latency(context, wsi,
310                                 "SSL_get_verify_result LWS_CONNMODE..HANDSHAKE",
311                                                                       n, n > 0);
312
313                         if (n != X509_V_OK) {
314                                 if ((n == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
315                                      n == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) && wsi->use_ssl == 2) {
316                                         lwsl_notice("accepting self-signed certificate\n");
317                                 } else {
318                                         lwsl_err("server's cert didn't look good, X509_V_ERR = %d: %s\n",
319                                                  n, ERR_error_string(n, (char *)context->service_buffer));
320                                         libwebsocket_close_and_free_session(context,
321                                                         wsi, LWS_CLOSE_STATUS_NOSTATUS);
322                                         return 0;
323                                 }
324                         }
325 #endif /* USE_CYASSL */
326                 } else
327                         wsi->ssl = NULL;
328 #endif
329                 
330                 wsi->mode = LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE2;
331                 libwebsocket_set_timeout(wsi,
332                                 PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
333                                                               AWAITING_TIMEOUT);
334
335                 /* fallthru */
336
337         case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE2:
338                 p = libwebsockets_generate_client_handshake(context, wsi, p);
339                 if (p == NULL) {
340                         lwsl_err("Failed to generate handshake for client\n");
341                         libwebsocket_close_and_free_session(context, wsi,
342                                                      LWS_CLOSE_STATUS_NOSTATUS);
343                         return 0;
344                 }
345
346                 /* send our request to the server */
347
348                 lws_latency_pre(context, wsi);
349
350                 n = lws_ssl_capable_write(wsi, context->service_buffer, p - (char *)context->service_buffer);
351                 lws_latency(context, wsi, "send lws_issue_raw", n, n == p - (char *)context->service_buffer);
352                 switch (n) {
353                 case LWS_SSL_CAPABLE_ERROR:
354                         lwsl_debug("ERROR writing to client socket\n");
355                         libwebsocket_close_and_free_session(context, wsi,
356                                                      LWS_CLOSE_STATUS_NOSTATUS);
357                         return 0;
358                 case LWS_SSL_CAPABLE_MORE_SERVICE:
359                         libwebsocket_callback_on_writable(context, wsi);
360                         break;
361                 }
362
363                 wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
364                 wsi->u.hdr.lextable_pos = 0;
365                 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY;
366                 libwebsocket_set_timeout(wsi,
367                                 PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
368                                                               AWAITING_TIMEOUT);
369                 break;
370
371         case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
372
373                 /* handle server hung up on us */
374
375                 if (pollfd->revents & LWS_POLLHUP) {
376
377                         lwsl_debug("Server connection %p (fd=%d) dead\n",
378                                 (void *)wsi, pollfd->fd);
379
380                         goto bail3;
381                 }
382
383                 if (!(pollfd->revents & LWS_POLLIN))
384                         break;
385
386                 /* interpret the server response */
387
388                 /*
389                  *  HTTP/1.1 101 Switching Protocols
390                  *  Upgrade: websocket
391                  *  Connection: Upgrade
392                  *  Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
393                  *  Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
394                  *  Sec-WebSocket-Protocol: chat
395                  */
396
397                 /*
398                  * we have to take some care here to only take from the
399                  * socket bytewise.  The browser may (and has been seen to
400                  * in the case that onopen() performs websocket traffic)
401                  * coalesce both handshake response and websocket traffic
402                  * in one packet, since at that point the connection is
403                  * definitively ready from browser pov.
404                  */
405                 len = 1;
406                 while (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE &&
407                                                                       len > 0) {
408                         n = lws_ssl_capable_read(context, wsi, &c, 1);
409                         lws_latency(context, wsi, "send lws_issue_raw", n, n == 1);
410                         switch (n) {
411                         case LWS_SSL_CAPABLE_ERROR:
412                                 goto bail3;
413                         case LWS_SSL_CAPABLE_MORE_SERVICE:
414                                 return 0;
415                         }
416
417                         if (libwebsocket_parse(context, wsi, c)) {
418                                 lwsl_warn("problems parsing header\n");
419                                 goto bail3;
420                         }
421                 }
422
423                 /*
424                  * hs may also be coming in multiple packets, there is a 5-sec
425                  * libwebsocket timeout still active here too, so if parsing did
426                  * not complete just wait for next packet coming in this state
427                  */
428
429                 if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
430                         break;
431
432                 /*
433                  * otherwise deal with the handshake.  If there's any
434                  * packet traffic already arrived we'll trigger poll() again
435                  * right away and deal with it that way
436                  */
437
438                 return lws_client_interpret_server_handshake(context, wsi);
439
440 bail3:
441                 lwsl_info(
442                         "closing connection at LWS_CONNMODE...SERVER_REPLY\n");
443                 libwebsocket_close_and_free_session(context, wsi,
444                                                     LWS_CLOSE_STATUS_NOSTATUS);
445                 return -1;
446
447         case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
448                 lwsl_ext("LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT\n");
449                 break;
450
451         case LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD:
452                 lwsl_ext("LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD\n");
453                 break;
454         default:
455                 break;
456         }
457
458         return 0;
459 }
460
461
462 /*
463  * In-place str to lower case
464  */
465
466 static void
467 strtolower(char *s)
468 {
469         while (*s) {
470                 *s = tolower((int)*s);
471                 s++;
472         }
473 }
474
475 int
476 lws_client_interpret_server_handshake(struct libwebsocket_context *context,
477                 struct libwebsocket *wsi)
478 {
479         const char *pc;
480         int okay = 0;
481         char *p;
482         int len;
483 #ifndef LWS_NO_EXTENSIONS
484         char ext_name[128];
485         struct libwebsocket_extension *ext;
486         void *v;
487         int more = 1;
488         const char *c;
489 #endif
490         int n;
491         int close_reason = LWS_CLOSE_STATUS_PROTOCOL_ERR;
492
493         /*
494          * well, what the server sent looked reasonable for syntax.
495          * Now let's confirm it sent all the necessary headers
496          */
497
498         if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0) {
499                 lwsl_info("no ACCEPT\n");
500                 goto bail3;
501         }
502
503         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP);
504         if (!p) {
505                 lwsl_info("no URI\n");
506                 goto bail3;
507         }
508         if (p && strncmp(p, "101", 3)) {
509                 lwsl_warn(
510                        "lws_client_handshake: got bad HTTP response '%s'\n", p);
511                 goto bail3;
512         }
513
514         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE);
515         if (!p) {
516                 lwsl_info("no UPGRADE\n");
517                 goto bail3;
518         }
519         strtolower(p);
520         if (strcmp(p, "websocket")) {
521                 lwsl_warn(
522                       "lws_client_handshake: got bad Upgrade header '%s'\n", p);
523                 goto bail3;
524         }
525
526         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_CONNECTION);
527         if (!p) {
528                 lwsl_info("no Connection hdr\n");
529                 goto bail3;
530         }
531         strtolower(p);
532         if (strcmp(p, "upgrade")) {
533                 lwsl_warn("lws_client_int_s_hs: bad header %s\n", p);
534                 goto bail3;
535         }
536
537         pc = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
538         if (pc == NULL)
539                 lwsl_parser("lws_client_int_s_hs: no protocol list\n");
540         else
541                 lwsl_parser("lws_client_int_s_hs: protocol list '%s'\n", pc);
542
543         /*
544          * confirm the protocol the server wants to talk was in the list
545          * of protocols we offered
546          */
547
548         len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL);
549         if (!len) {
550
551                 lwsl_info("lws_client_int_s_hs: WSI_TOKEN_PROTOCOL is null\n");
552                 /*
553                  * no protocol name to work from,
554                  * default to first protocol
555                  */
556                 wsi->protocol = &context->protocols[0];
557                 goto check_extensions;
558         }
559
560         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL);
561         len = strlen(p);
562
563         while (*pc && !okay) {
564                 if (!strncmp(pc, p, len) &&
565                                           (pc[len] == ',' || pc[len] == '\0')) {
566                         okay = 1;
567                         continue;
568                 }
569                 while (*pc && *pc != ',')
570                         pc++;
571                 while (*pc && *pc == ' ')
572                         pc++;
573         }
574
575         if (!okay) {
576                 lwsl_err("lws_client_int_s_hs: got bad protocol '%s'\n", p);
577                 goto bail2;
578         }
579
580         /*
581          * identify the selected protocol struct and set it
582          */
583         n = 0;
584         wsi->protocol = NULL;
585         while (context->protocols[n].callback && !wsi->protocol) {
586                 if (strcmp(p, context->protocols[n].name) == 0) {
587                         wsi->protocol = &context->protocols[n];
588                         break;
589                 }
590                 n++;
591         }
592
593         if (wsi->protocol == NULL) {
594                 lwsl_err("lws_client_int_s_hs: fail protocol '%s'\n", p);
595                 goto bail2;
596         }
597
598
599 check_extensions:
600 #ifndef LWS_NO_EXTENSIONS
601         /* instantiate the accepted extensions */
602
603         if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS)) {
604                 lwsl_ext("no client extenstions allowed by server\n");
605                 goto check_accept;
606         }
607
608         /*
609          * break down the list of server accepted extensions
610          * and go through matching them or identifying bogons
611          */
612
613         if (lws_hdr_copy(wsi, (char *)context->service_buffer,
614                    sizeof(context->service_buffer), WSI_TOKEN_EXTENSIONS) < 0) {
615                 lwsl_warn("ext list from server failed to copy\n");
616                 goto bail2;
617         }
618
619         c = (char *)context->service_buffer;
620         n = 0;
621         while (more) {
622
623                 if (*c && (*c != ',' && *c != ' ' && *c != '\t')) {
624                         ext_name[n] = *c++;
625                         if (n < sizeof(ext_name) - 1)
626                                 n++;
627                         continue;
628                 }
629                 ext_name[n] = '\0';
630                 if (!*c)
631                         more = 0;
632                 else {
633                         c++;
634                         if (!n)
635                                 continue;
636                 }
637
638                 /* check we actually support it */
639
640                 lwsl_ext("checking client ext %s\n", ext_name);
641
642                 n = 0;
643                 ext = wsi->protocol->owning_server->extensions;
644                 while (ext && ext->callback) {
645
646                         if (strcmp(ext_name, ext->name)) {
647                                 ext++;
648                                 continue;
649                         }
650
651                         n = 1;
652
653                         lwsl_ext("instantiating client ext %s\n", ext_name);
654
655                         /* instantiate the extension on this conn */
656
657                         wsi->active_extensions_user[
658                                 wsi->count_active_extensions] =
659                                          malloc(ext->per_session_data_size);
660                         if (wsi->active_extensions_user[
661                                 wsi->count_active_extensions] == NULL) {
662                                 lwsl_err("Out of mem\n");
663                                 goto bail2;
664                         }
665                         memset(wsi->active_extensions_user[
666                                 wsi->count_active_extensions], 0,
667                                                     ext->per_session_data_size);
668                         wsi->active_extensions[
669                                   wsi->count_active_extensions] = ext;
670
671                         /* allow him to construct his context */
672
673                         ext->callback(wsi->protocol->owning_server,
674                                 ext, wsi,
675                                    LWS_EXT_CALLBACK_CLIENT_CONSTRUCT,
676                                         wsi->active_extensions_user[
677                                          wsi->count_active_extensions],
678                                                                    NULL, 0);
679
680                         wsi->count_active_extensions++;
681
682                         ext++;
683                 }
684
685                 if (n == 0) {
686                         lwsl_warn("Unknown ext '%s'!\n", ext_name);
687                         goto bail2;
688                 }
689
690                 n = 0;
691         }
692
693 check_accept:
694 #endif
695
696         /*
697          * Confirm his accept token is the one we precomputed
698          */
699
700         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_ACCEPT);
701         if (strcmp(p, wsi->u.hdr.ah->initial_handshake_hash_base64)) {
702                 lwsl_warn("lws_client_int_s_hs: accept %s wrong vs %s\n", p,
703                                   wsi->u.hdr.ah->initial_handshake_hash_base64);
704                 goto bail2;
705         }
706
707         /* allocate the per-connection user memory (if any) */
708         if (libwebsocket_ensure_user_space(wsi)) {
709                 lwsl_err("Problem allocating wsi user mem\n");
710                 goto bail2;
711         }
712
713         /*
714          * we seem to be good to go, give client last chance to check
715          * headers and OK it
716          */
717
718         wsi->protocol->callback(context, wsi,
719                                 LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
720                                                      wsi->user_space, NULL, 0);
721
722         /* clear his proxy connection timeout */
723
724         libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
725
726         /* free up his parsing allocations */
727
728         if (wsi->u.hdr.ah)
729                 free(wsi->u.hdr.ah);
730
731         lws_union_transition(wsi, LWS_CONNMODE_WS_CLIENT);
732         wsi->state = WSI_STATE_ESTABLISHED;
733
734         wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
735
736         /*
737          * create the frame buffer for this connection according to the
738          * size mentioned in the protocol definition.  If 0 there, then
739          * use a big default for compatibility
740          */
741
742         n = wsi->protocol->rx_buffer_size;
743         if (!n)
744                 n = LWS_MAX_SOCKET_IO_BUF;
745         n += LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING;
746         wsi->u.ws.rx_user_buffer = malloc(n);
747         if (!wsi->u.ws.rx_user_buffer) {
748                 lwsl_err("Out of Mem allocating rx buffer %d\n", n);
749                 goto bail2;
750         }
751         lwsl_info("Allocating client RX buffer %d\n", n);
752
753         if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof n)) {
754                 lwsl_warn("Failed to set SNDBUF to %d", n);
755                 goto bail3;
756         }
757
758         lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name);
759
760         /* call him back to inform him he is up */
761
762         wsi->protocol->callback(context, wsi,
763                                 LWS_CALLBACK_CLIENT_ESTABLISHED,
764                                                      wsi->user_space, NULL, 0);
765 #ifndef LWS_NO_EXTENSIONS
766         /*
767          * inform all extensions, not just active ones since they
768          * already know
769          */
770
771         ext = context->extensions;
772
773         while (ext && ext->callback) {
774                 v = NULL;
775                 for (n = 0; n < wsi->count_active_extensions; n++)
776                         if (wsi->active_extensions[n] == ext)
777                                 v = wsi->active_extensions_user[n];
778
779                 ext->callback(context, ext, wsi,
780                           LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED, v, NULL, 0);
781                 ext++;
782         }
783 #endif
784
785         return 0;
786
787 bail3:
788         free(wsi->u.ws.rx_user_buffer);
789         wsi->u.ws.rx_user_buffer = NULL;
790         close_reason = LWS_CLOSE_STATUS_NOSTATUS;
791
792 bail2:
793         if (wsi->protocol)
794                 wsi->protocol->callback(context, wsi,
795                         LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
796                                                       wsi->user_space, NULL, 0);
797
798         lwsl_info("closing connection due to bail2 connection error\n");
799
800         /* free up his parsing allocations */
801
802         if (wsi->u.hdr.ah)
803                 free(wsi->u.hdr.ah);
804
805         libwebsocket_close_and_free_session(context, wsi, close_reason);
806
807         return 1;
808 }
809
810
811 char *
812 libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
813                 struct libwebsocket *wsi, char *pkt)
814 {
815         char buf[128];
816         char hash[20];
817         char key_b64[40];
818         char *p = pkt;
819         int n;
820 #ifndef LWS_NO_EXTENSIONS
821         struct libwebsocket_extension *ext;
822         int ext_count = 0;
823 #endif
824
825         /*
826          * create the random key
827          */
828
829         n = libwebsockets_get_random(context, hash, 16);
830         if (n != 16) {
831                 lwsl_err("Unable to read from random dev %s\n",
832                                                 SYSTEM_RANDOM_FILEPATH);
833                 libwebsocket_close_and_free_session(context, wsi,
834                                              LWS_CLOSE_STATUS_NOSTATUS);
835                 return NULL;
836         }
837
838         lws_b64_encode_string(hash, 16, key_b64, sizeof(key_b64));
839
840         /*
841          * 00 example client handshake
842          *
843          * GET /socket.io/websocket HTTP/1.1
844          * Upgrade: WebSocket
845          * Connection: Upgrade
846          * Host: 127.0.0.1:9999
847          * Origin: http://127.0.0.1
848          * Sec-WebSocket-Key1: 1 0 2#0W 9 89 7  92 ^
849          * Sec-WebSocket-Key2: 7 7Y 4328 B2v[8(z1
850          * Cookie: socketio=websocket
851          *
852          * (Á®Ä0¶†≥
853          *
854          * 04 example client handshake
855          *
856          * GET /chat HTTP/1.1
857          * Host: server.example.com
858          * Upgrade: websocket
859          * Connection: Upgrade
860          * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
861          * Sec-WebSocket-Origin: http://example.com
862          * Sec-WebSocket-Protocol: chat, superchat
863          * Sec-WebSocket-Version: 4
864          */
865
866         p += sprintf(p, "GET %s HTTP/1.1\x0d\x0a",
867                                 lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI));
868
869         p += sprintf(p,
870                 "Pragma: no-cache\x0d\x0a""Cache-Control: no-cache\x0d\x0a");
871
872         p += sprintf(p, "Host: %s\x0d\x0a",
873                                lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST));
874         p += sprintf(p,
875 "Upgrade: websocket\x0d\x0a""Connection: Upgrade\x0d\x0a""Sec-WebSocket-Key: ");
876         strcpy(p, key_b64);
877         p += strlen(key_b64);
878         p += sprintf(p, "\x0d\x0a");
879         if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN))
880                 p += sprintf(p, "Origin: http://%s\x0d\x0a",
881                              lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN));
882
883         if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS))
884                 p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a",
885                      lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS));
886
887         /* tell the server what extensions we could support */
888
889         p += sprintf(p, "Sec-WebSocket-Extensions: ");
890 #ifndef LWS_NO_EXTENSIONS
891         ext = context->extensions;
892         while (ext && ext->callback) {
893
894                 n = lws_ext_callback_for_each_extension_type(context, wsi,
895                            LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION,
896                                                           (char *)ext->name, 0);
897                 if (n) { /* an extension vetos us */
898                         lwsl_ext("ext %s vetoed\n", (char *)ext->name);
899                         ext++;
900                         continue;
901                 }
902
903                 n = context->protocols[0].callback(context, wsi,
904                         LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
905                                 wsi->user_space, (char *)ext->name, 0);
906
907                 /*
908                  * zero return from callback means
909                  * go ahead and allow the extension,
910                  * it's what we get if the callback is
911                  * unhandled
912                  */
913
914                 if (n) {
915                         ext++;
916                         continue;
917                 }
918
919                 /* apply it */
920
921                 if (ext_count)
922                         *p++ = ',';
923                 p += sprintf(p, "%s", ext->name);
924                 ext_count++;
925
926                 ext++;
927         }
928 #endif
929         p += sprintf(p, "\x0d\x0a");
930
931         if (wsi->ietf_spec_revision)
932                 p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a",
933                                                wsi->ietf_spec_revision);
934
935         /* give userland a chance to append, eg, cookies */
936
937         context->protocols[0].callback(context, wsi,
938                 LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
939                 NULL, &p, (pkt + sizeof(context->service_buffer)) - p - 12);
940
941         p += sprintf(p, "\x0d\x0a");
942
943         /* prepare the expected server accept response */
944
945         key_b64[39] = '\0'; /* enforce composed length below buf sizeof */
946         n = sprintf(buf, "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", key_b64);
947
948         libwebsockets_SHA1((unsigned char *)buf, n, (unsigned char *)hash);
949
950         lws_b64_encode_string(hash, 20,
951                         wsi->u.hdr.ah->initial_handshake_hash_base64,
952                           sizeof(wsi->u.hdr.ah->initial_handshake_hash_base64));
953
954         return p;
955 }
956