Optionally allow non-SSL connections on same port as SSL
[platform/upstream/libwebsockets.git] / lib / server.c
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010-2013 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
23 #include "private-libwebsockets.h"
24
25 #if defined(WIN32) || defined(_WIN32)
26 #include <tchar.h>
27 #include <io.h>
28 #else
29 #ifdef LWS_BUILTIN_GETIFADDRS
30 #include <getifaddrs.h>
31 #else
32 #include <ifaddrs.h>
33 #endif
34 #include <sys/un.h>
35 #include <sys/socket.h>
36 #include <netdb.h>
37 #endif
38
39 #ifdef LWS_OPENSSL_SUPPORT
40
41 static void
42 libwebsockets_decode_ssl_error(void)
43 {
44         char buf[256];
45         u_long err;
46
47         while ((err = ERR_get_error()) != 0) {
48                 ERR_error_string_n(err, buf, sizeof(buf));
49                 lwsl_err("*** %lu %s\n", err, buf);
50         }
51 }
52 #endif
53
54 int
55 interface_to_sa(const char *ifname, struct sockaddr_in *addr, size_t addrlen)
56 {
57         int rc = -1;
58 #if defined(WIN32) || defined(_WIN32)
59         /* TODO */
60 #else
61         struct ifaddrs *ifr;
62         struct ifaddrs *ifc;
63         struct sockaddr_in *sin;
64
65         getifaddrs(&ifr);
66         for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) {
67                 if (ifc->ifa_addr == NULL)
68                         continue;
69                 lwsl_info(" interface %s vs %s\n", ifc->ifa_name, ifname);
70                 if (strcmp(ifc->ifa_name, ifname))
71                         continue;
72                 sin = (struct sockaddr_in *)ifc->ifa_addr;
73                 if (sin->sin_family != AF_INET)
74                         continue;
75                 memcpy(addr, sin, addrlen);
76                 rc = 0;
77         }
78
79         freeifaddrs(ifr);
80 #endif
81         return rc;
82 }
83
84 struct libwebsocket *
85 libwebsocket_create_new_server_wsi(struct libwebsocket_context *context)
86 {
87         struct libwebsocket *new_wsi;
88
89         new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
90         if (new_wsi == NULL) {
91                 lwsl_err("Out of memory for new connection\n");
92                 return NULL;
93         }
94
95         memset(new_wsi, 0, sizeof(struct libwebsocket));
96 #ifndef LWS_NO_EXTENSIONS
97         new_wsi->count_active_extensions = 0;
98 #endif
99         new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
100
101         /* intialize the instance struct */
102
103         new_wsi->state = WSI_STATE_HTTP;
104         new_wsi->mode = LWS_CONNMODE_HTTP_SERVING;
105         new_wsi->hdr_parsing_completed = 0;
106
107         if (lws_allocate_header_table(new_wsi)) {
108                 free(new_wsi);
109                 return NULL;
110         }
111
112         /*
113          * these can only be set once the protocol is known
114          * we set an unestablished connection's protocol pointer
115          * to the start of the supported list, so it can look
116          * for matching ones during the handshake
117          */
118         new_wsi->protocol = context->protocols;
119         new_wsi->user_space = NULL;
120         new_wsi->ietf_spec_revision = 0;
121
122         return new_wsi;
123 }
124
125 int lws_server_socket_service(struct libwebsocket_context *context,
126                         struct libwebsocket *wsi, struct pollfd *pollfd)
127 {
128         struct libwebsocket *new_wsi;
129         int accept_fd;
130         socklen_t clilen;
131         struct sockaddr_in cli_addr;
132         int n;
133         ssize_t len;
134 #ifdef LWS_OPENSSL_SUPPORT
135         int m;
136 #ifndef USE_CYASSL
137         BIO *bio;
138 #endif
139 #endif
140
141         switch (wsi->mode) {
142
143         case LWS_CONNMODE_HTTP_SERVING:
144         case LWS_CONNMODE_HTTP_SERVING_ACCEPTED:
145
146                 /* handle http headers coming in */
147
148                 /* pending truncated sends have uber priority */
149
150                 if (wsi->truncated_send_malloc) {
151                         if (pollfd->revents & POLLOUT)
152                                 lws_issue_raw(wsi, wsi->truncated_send_malloc +
153                                         wsi->truncated_send_offset,
154                                                         wsi->truncated_send_len);
155                         /*
156                          * we can't afford to allow input processing send
157                          * something new, so spin around he event loop until
158                          * he doesn't have any partials
159                          */
160                         break;
161                 }
162
163                 /* any incoming data ready? */
164
165                 if (pollfd->revents & POLLIN) {
166
167         #ifdef LWS_OPENSSL_SUPPORT
168                         if (wsi->ssl)
169                                 len = SSL_read(wsi->ssl,
170                                         context->service_buffer,
171                                                sizeof(context->service_buffer));
172                         else
173         #endif
174                                 len = recv(pollfd->fd,
175                                         context->service_buffer,
176                                         sizeof(context->service_buffer), 0);
177
178                         if (len < 0) {
179                                 lwsl_debug("Socket read returned %d\n", len);
180                                 if (errno != EINTR && errno != EAGAIN)
181                                         libwebsocket_close_and_free_session(
182                                                 context, wsi,
183                                                 LWS_CLOSE_STATUS_NOSTATUS);
184                                 return 0;
185                         }
186                         if (!len) {
187                                 lwsl_info("lws_server_skt_srv: read 0 len\n");
188                                 /* lwsl_info("   state=%d\n", wsi->state); */
189                                 if (!wsi->hdr_parsing_completed)
190                                         free(wsi->u.hdr.ah);
191                                 libwebsocket_close_and_free_session(
192                                        context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
193                                 return 0;
194                         }
195
196                         /* hm this may want to send (via HTTP callback for example) */
197
198                         n = libwebsocket_read(context, wsi,
199                                                 context->service_buffer, len);
200                         if (n < 0)
201                                 /* we closed wsi */
202                                 return 0;
203
204                         /* hum he may have used up the writability above */
205
206                         break;
207                 }
208
209                 /* this handles POLLOUT for http serving fragments */
210
211                 if (!(pollfd->revents & POLLOUT))
212                         break;
213
214                 /* one shot */
215                 pollfd->events &= ~POLLOUT;
216
217                 if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE) {
218                         n = user_callback_handle_rxflow(
219                                         wsi->protocol->callback,
220                                         wsi->protocol->owning_server,
221                                         wsi, LWS_CALLBACK_HTTP_WRITEABLE,
222                                         wsi->user_space,
223                                         NULL,
224                                         0);
225                         if (n < 0)
226                                 libwebsocket_close_and_free_session(
227                                        context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
228                         break;
229                 }
230
231                 /* nonzero for completion or error */
232                 if (libwebsockets_serve_http_file_fragment(context, wsi))
233                         libwebsocket_close_and_free_session(context, wsi,
234                                                LWS_CLOSE_STATUS_NOSTATUS);
235                 break;
236
237         case LWS_CONNMODE_SERVER_LISTENER:
238
239                 /* pollin means a client has connected to us then */
240
241                 if (!(pollfd->revents & POLLIN))
242                         break;
243
244                 /* listen socket got an unencrypted connection... */
245
246                 clilen = sizeof(cli_addr);
247                 lws_latency_pre(context, wsi);
248                 accept_fd  = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
249                                                                        &clilen);
250                 lws_latency(context, wsi,
251                         "unencrypted accept LWS_CONNMODE_SERVER_LISTENER",
252                                                      accept_fd, accept_fd >= 0);
253                 if (accept_fd < 0) {
254                         if (errno == EAGAIN || errno == EWOULDBLOCK) {
255                                 lwsl_debug("accept asks to try again\n");
256                                 break;
257                         }
258                         lwsl_warn("ERROR on accept: %s\n", strerror(errno));
259                         break;
260                 }
261
262                 lws_set_socket_options(context, accept_fd);
263
264                 /*
265                  * look at who we connected to and give user code a chance
266                  * to reject based on client IP.  There's no protocol selected
267                  * yet so we issue this to protocols[0]
268                  */
269
270                 if ((context->protocols[0].callback)(context, wsi,
271                                 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
272                                            NULL, (void *)(long)accept_fd, 0)) {
273                         lwsl_debug("Callback denied network connection\n");
274                         compatible_close(accept_fd);
275                         break;
276                 }
277
278                 new_wsi = libwebsocket_create_new_server_wsi(context);
279                 if (new_wsi == NULL) {
280                         compatible_close(accept_fd);
281                         break;
282                 }
283
284                 new_wsi->sock = accept_fd;
285
286 #ifdef LWS_OPENSSL_SUPPORT
287                 new_wsi->ssl = NULL;
288                 if (!context->use_ssl) {
289 #endif
290
291                         lwsl_debug("accepted new conn  port %u on fd=%d\n",
292                                           ntohs(cli_addr.sin_port), accept_fd);
293
294                         insert_wsi_socket_into_fds(context, new_wsi);
295                         break;
296 #ifdef LWS_OPENSSL_SUPPORT
297                 }
298
299                 new_wsi->ssl = SSL_new(context->ssl_ctx);
300                 if (new_wsi->ssl == NULL) {
301                         lwsl_err("SSL_new failed: %s\n",
302                             ERR_error_string(SSL_get_error(
303                             new_wsi->ssl, 0), NULL));
304                             libwebsockets_decode_ssl_error();
305                         free(new_wsi);
306                         compatible_close(accept_fd);
307                         break;
308                 }
309
310                 SSL_set_ex_data(new_wsi->ssl,
311                         openssl_websocket_private_data_index, context);
312
313                 SSL_set_fd(new_wsi->ssl, accept_fd);
314
315                 #ifdef USE_CYASSL
316                 CyaSSL_set_using_nonblock(new_wsi->ssl, 1);
317                 #else
318                 bio = SSL_get_rbio(new_wsi->ssl);
319                 if (bio)
320                         BIO_set_nbio(bio, 1); /* nonblocking */
321                 else
322                         lwsl_notice("NULL rbio\n");
323                 bio = SSL_get_wbio(new_wsi->ssl);
324                 if (bio)
325                         BIO_set_nbio(bio, 1); /* nonblocking */
326                 else
327                         lwsl_notice("NULL rbio\n");
328                 #endif
329
330                 /*
331                  * we are not accepted yet, but we need to enter ourselves
332                  * as a live connection.  That way we can retry when more
333                  * pieces come if we're not sorted yet
334                  */
335
336                 wsi = new_wsi;
337                 wsi->mode = LWS_CONNMODE_SSL_ACK_PENDING;
338                 insert_wsi_socket_into_fds(context, wsi);
339
340                 libwebsocket_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT,
341                                                         AWAITING_TIMEOUT);
342
343                 lwsl_info("inserted SSL accept into fds, trying SSL_accept\n");
344
345                 /* fallthru */
346
347         case LWS_CONNMODE_SSL_ACK_PENDING:
348
349                 pollfd->events &= ~POLLOUT;
350
351                 /* external POLL support via protocol 0 */
352                 context->protocols[0].callback(context, wsi,
353                         LWS_CALLBACK_CLEAR_MODE_POLL_FD,
354                         wsi->user_space, (void *)(long)wsi->sock, POLLOUT);
355
356                 lws_latency_pre(context, wsi);
357
358                 n = recv(wsi->sock, context->service_buffer,
359                         sizeof(context->service_buffer), MSG_PEEK);
360
361                 /*
362                  * optionally allow non-SSL connect on SSL listening socket
363                  * This is disabled by default, if enabled it goes around any
364                  * SSL-level access control (eg, client-side certs) so leave
365                  * it disabled unless you know it's not a problem for you
366                  */
367
368                 if (context->allow_non_ssl_on_ssl_port && n >= 1 &&
369                                         context->service_buffer[0] >= ' ') {
370                         /*
371                          * TLS content-type for Handshake is 0x16
372                          * TLS content-type for ChangeCipherSpec Record is 0x14
373                          *
374                          * A non-ssl session will start with the HTTP method in
375                          * ASCII.  If we see it's not a legit SSL handshake
376                          * kill the SSL for this connection and try to handle
377                          * as a HTTP connection upgrade directly.
378                          */
379                         wsi->use_ssl = 0;
380                         SSL_shutdown(wsi->ssl);
381                         SSL_free(wsi->ssl);
382                         wsi->ssl = NULL;
383                         goto accepted;
384                 }
385
386                 /* normal SSL connection processing path */
387
388                 n = SSL_accept(wsi->ssl);
389                 lws_latency(context, wsi,
390                         "SSL_accept LWS_CONNMODE_SSL_ACK_PENDING\n", n, n == 1);
391
392                 if (n != 1) {
393                         m = SSL_get_error(wsi->ssl, n);
394                         lwsl_debug("SSL_accept failed %d / %s\n",
395                                                   m, ERR_error_string(m, NULL));
396
397                         if (m == SSL_ERROR_WANT_READ) {
398                                 context->fds[
399                                    wsi->position_in_fds_table].events |= POLLIN;
400
401                                 /* external POLL support via protocol 0 */
402                                 context->protocols[0].callback(context, wsi,
403                                         LWS_CALLBACK_SET_MODE_POLL_FD,
404                                         wsi->user_space,
405                                         (void *)(long)wsi->sock, POLLIN);
406                                 lwsl_info("SSL_ERROR_WANT_READ\n");
407                                 break;
408                         }
409                         if (m == SSL_ERROR_WANT_WRITE) {
410                                 context->fds[
411                                   wsi->position_in_fds_table].events |= POLLOUT;
412                                 /* external POLL support via protocol 0 */
413                                 context->protocols[0].callback(context, wsi,
414                                         LWS_CALLBACK_SET_MODE_POLL_FD,
415                                         wsi->user_space,
416                                         (void *)(long)wsi->sock, POLLOUT);
417                                 break;
418                         }
419                         lwsl_debug("SSL_accept failed skt %u: %s\n",
420                                   pollfd->fd,
421                                   ERR_error_string(m, NULL));
422                         libwebsocket_close_and_free_session(context, wsi,
423                                                  LWS_CLOSE_STATUS_NOSTATUS);
424                         break;
425                 }
426
427 accepted:
428                 /* OK, we are accepted */
429
430                 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
431
432                 wsi->mode = LWS_CONNMODE_HTTP_SERVING;
433
434                 lwsl_debug("accepted new SSL conn\n");
435                 break;
436 #endif
437
438         default:
439                 break;
440         }
441         return 0;
442 }
443
444
445 static const char *err400[] = {
446         "Bad Request",
447         "Unauthorized",
448         "Payment Required",
449         "Forbidden",
450         "Not Found",
451         "Method Not Allowed",
452         "Not Acceptable",
453         "Proxy Auth Required",
454         "Request Timeout",
455         "Conflict",
456         "Gone",
457         "Length Required",
458         "Precondition Failed",
459         "Request Entity Too Large",
460         "Request URI too Long",
461         "Unsupported Media Type",
462         "Requested Range Not Satisfiable",
463         "Expectation Failed"
464 };
465
466 static const char *err500[] = {
467         "Internal Server Error",
468         "Not Implemented",
469         "Bad Gateway",
470         "Service Unavailable",
471         "Gateway Timeout",
472         "HTTP Version Not Supported"
473 };
474
475 /**
476  * libwebsockets_return_http_status() - Return simple http status
477  * @context:            libwebsockets context
478  * @wsi:                Websocket instance (available from user callback)
479  * @code:               Status index, eg, 404
480  * @html_body:          User-readable HTML description, or NULL
481  *
482  *      Helper to report HTTP errors back to the client cleanly and
483  *      consistently
484  */
485 LWS_VISIBLE int libwebsockets_return_http_status(
486                 struct libwebsocket_context *context, struct libwebsocket *wsi,
487                                        unsigned int code, const char *html_body)
488 {
489         int n, m;
490         const char *description = "";
491
492         if (!html_body)
493                 html_body = "";
494
495         if (code >= 400 && code < (400 + ARRAY_SIZE(err400)))
496                 description = err400[code - 400];
497         if (code >= 500 && code < (500 + ARRAY_SIZE(err500)))
498                 description = err500[code - 500];
499
500         n = sprintf((char *)context->service_buffer,
501                 "HTTP/1.0 %u %s\x0d\x0a"
502                 "Server: libwebsockets\x0d\x0a"
503                 "Mime-Type: text/html\x0d\x0a\x0d\x0a"
504                 "<h1>%u %s</h1>%s",
505                 code, description, code, description, html_body);
506
507         lwsl_info((const char *)context->service_buffer);
508
509         m = libwebsocket_write(wsi, context->service_buffer, n, LWS_WRITE_HTTP);
510
511         return m;
512 }
513
514 /**
515  * libwebsockets_serve_http_file() - Send a file back to the client using http
516  * @context:            libwebsockets context
517  * @wsi:                Websocket instance (available from user callback)
518  * @file:               The file to issue over http
519  * @content_type:       The http content type, eg, text/html
520  * @other_headers:      NULL or pointer to \0-terminated other header string
521  *
522  *      This function is intended to be called from the callback in response
523  *      to http requests from the client.  It allows the callback to issue
524  *      local files down the http link in a single step.
525  *
526  *      Returning <0 indicates error and the wsi should be closed.  Returning
527  *      >0 indicates the file was completely sent and the wsi should be closed.
528  *      ==0 indicates the file transfer is started and needs more service later,
529  *      the wsi should be left alone.
530  */
531
532 LWS_VISIBLE int libwebsockets_serve_http_file(
533                 struct libwebsocket_context *context,
534                         struct libwebsocket *wsi, const char *file,
535                            const char *content_type, const char *other_headers)
536 {
537         struct stat stat_buf;
538         unsigned char *p = context->service_buffer;
539         int ret = 0;
540         int n;
541
542         wsi->u.http.fd = open(file, O_RDONLY
543 #ifdef WIN32
544                          | _O_BINARY
545 #endif
546         );
547
548         if (wsi->u.http.fd < 1) {
549                 lwsl_err("Unable to open '%s'\n", file);
550                 libwebsockets_return_http_status(context, wsi,
551                                                 HTTP_STATUS_NOT_FOUND, NULL);
552                 wsi->u.http.fd = -1;
553                 return -1;
554         }
555
556         fstat(wsi->u.http.fd, &stat_buf);
557         wsi->u.http.filelen = stat_buf.st_size;
558         p += sprintf((char *)p,
559 "HTTP/1.0 200 OK\x0d\x0aServer: libwebsockets\x0d\x0a""Content-Type: %s\x0d\x0a",
560                                                                   content_type);
561         if (other_headers) {
562                 n = strlen(other_headers);
563                 memcpy(p, other_headers, n);
564                 p += n;
565         }
566         p += sprintf((char *)p,
567                 "Content-Length: %u\x0d\x0a\x0d\x0a",
568                                         (unsigned int)stat_buf.st_size);
569
570         ret = libwebsocket_write(wsi, context->service_buffer,
571                                    p - context->service_buffer, LWS_WRITE_HTTP);
572         if (ret != (p - context->service_buffer)) {
573                 lwsl_err("_write returned %d from %d\n", ret, (p - context->service_buffer));
574                 return -1;
575         }
576
577         wsi->u.http.filepos = 0;
578         wsi->state = WSI_STATE_HTTP_ISSUING_FILE;
579
580         return libwebsockets_serve_http_file_fragment(context, wsi);
581 }
582