ssl optimize poll when buffered ssl read data
[platform/upstream/libwebsockets.git] / lib / ssl.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 openssl_websocket_private_data_index;
25
26 #ifndef LWS_NO_SERVER
27 static int
28 OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
29 {
30         SSL *ssl;
31         int n;
32         struct libwebsocket_context *context;
33
34         ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
35                 SSL_get_ex_data_X509_STORE_CTX_idx());
36
37         /*
38          * !!! nasty openssl requires the index to come as a library-scope
39          * static
40          */
41         context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
42
43         n = context->protocols[0].callback(NULL, NULL,
44                 LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
45                                                    x509_ctx, ssl, preverify_ok);
46
47         /* convert return code from 0 = OK to 1 = OK */
48         return !n;
49 }
50
51 LWS_VISIBLE int
52 lws_context_init_server_ssl(struct lws_context_creation_info *info,
53                      struct libwebsocket_context *context)
54 {
55         SSL_METHOD *method;
56         int error;
57         int n;
58
59         if (info->port != CONTEXT_PORT_NO_LISTEN) {
60
61                 context->use_ssl = info->ssl_cert_filepath != NULL &&
62                                          info->ssl_private_key_filepath != NULL;
63 #ifdef USE_CYASSL
64                 lwsl_notice(" Compiled with CYASSL support\n");
65 #else
66                 lwsl_notice(" Compiled with OpenSSL support\n");
67 #endif
68                 
69                 if (info->ssl_cipher_list)
70                         lwsl_notice(" SSL ciphers: '%s'\n", info->ssl_cipher_list);
71
72                 if (context->use_ssl)
73                         lwsl_notice(" Using SSL mode\n");
74                 else
75                         lwsl_notice(" Using non-SSL mode\n");
76         }
77
78         /* basic openssl init */
79
80         SSL_library_init();
81
82         OpenSSL_add_all_algorithms();
83         SSL_load_error_strings();
84
85         openssl_websocket_private_data_index =
86                 SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
87
88         /*
89          * Firefox insists on SSLv23 not SSLv3
90          * Konq disables SSLv2 by default now, SSLv23 works
91          */
92
93         method = (SSL_METHOD *)SSLv23_server_method();
94         if (!method) {
95                 error = ERR_get_error();
96                 lwsl_err("problem creating ssl method %lu: %s\n", 
97                         error, ERR_error_string(error,
98                                               (char *)context->service_buffer));
99                 return 1;
100         }
101         context->ssl_ctx = SSL_CTX_new(method); /* create context */
102         if (!context->ssl_ctx) {
103                 error = ERR_get_error();
104                 lwsl_err("problem creating ssl context %lu: %s\n",
105                         error, ERR_error_string(error,
106                                               (char *)context->service_buffer));
107                 return 1;
108         }
109
110 #ifdef SSL_OP_NO_COMPRESSION
111         SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
112 #endif
113         SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
114         if (info->ssl_cipher_list)
115                 SSL_CTX_set_cipher_list(context->ssl_ctx,
116                                                 info->ssl_cipher_list);
117
118         /* as a server, are we requiring clients to identify themselves? */
119
120         if (info->options &
121                         LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
122
123                 /* absolutely require the client cert */
124
125                 SSL_CTX_set_verify(context->ssl_ctx,
126                        SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
127                                                        OpenSSL_verify_callback);
128
129                 /*
130                  * give user code a chance to load certs into the server
131                  * allowing it to verify incoming client certs
132                  */
133
134                 context->protocols[0].callback(context, NULL,
135                         LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
136                                                      context->ssl_ctx, NULL, 0);
137         }
138
139         if (info->options & LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT) {
140                 /* Normally SSL listener rejects non-ssl, optionally allow */
141                 context->allow_non_ssl_on_ssl_port = 1;
142         }
143
144         if (context->use_ssl) {
145
146                 /* openssl init for server sockets */
147
148                 /* set the local certificate from CertFile */
149                 n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx,
150                                         info->ssl_cert_filepath);
151                 if (n != 1) {
152                         error = ERR_get_error();
153                         lwsl_err("problem getting cert '%s' %lu: %s\n",
154                                 info->ssl_cert_filepath,
155                                 error,
156                                 ERR_error_string(error,
157                                               (char *)context->service_buffer));
158                         return 1;
159                 }
160                 /* set the private key from KeyFile */
161                 if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
162                              info->ssl_private_key_filepath,
163                                                        SSL_FILETYPE_PEM) != 1) {
164                         error = ERR_get_error();
165                         lwsl_err("ssl problem getting key '%s' %lu: %s\n",
166                                 info->ssl_private_key_filepath,
167                                         error,
168                                         ERR_error_string(error,
169                                               (char *)context->service_buffer));
170                         return 1;
171                 }
172                 /* verify private key */
173                 if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
174                         lwsl_err("Private SSL key doesn't match cert\n");
175                         return 1;
176                 }
177
178                 /*
179                  * SSL is happy and has a cert it's content with
180                  * If we're supporting HTTP2, initialize that
181                  */
182                 
183                 lws_context_init_http2_ssl(context);
184         }
185         
186         return 0;
187 }
188 #endif
189
190 LWS_VISIBLE void
191 lws_ssl_destroy(struct libwebsocket_context *context)
192 {
193         if (context->ssl_ctx)
194                 SSL_CTX_free(context->ssl_ctx);
195         if (context->ssl_client_ctx)
196                 SSL_CTX_free(context->ssl_client_ctx);
197
198         ERR_remove_state(0);
199         ERR_free_strings();
200         EVP_cleanup();
201         CRYPTO_cleanup_all_ex_data();
202 }
203
204 LWS_VISIBLE void
205 libwebsockets_decode_ssl_error(void)
206 {
207         char buf[256];
208         u_long err;
209
210         while ((err = ERR_get_error()) != 0) {
211                 ERR_error_string_n(err, buf, sizeof(buf));
212                 lwsl_err("*** %lu %s\n", err, buf);
213         }
214 }
215
216 #ifndef LWS_NO_CLIENT
217 static int lws_context_init_client_ssl_pem_passwd_cb(char * buf, int size, int rwflag, void * userdata)
218 {
219         struct lws_context_creation_info * info = (struct lws_context_creation_info *)userdata;
220    
221         const int passLen = (int)strlen(info->ssl_private_key_password);
222         const int minimumLen = passLen < size ? passLen : size;
223         strncpy(buf, info->ssl_private_key_password, minimumLen);
224    
225         if (minimumLen < size)
226         {
227                 buf[minimumLen] = '\0';
228        return minimumLen;
229    }
230    
231     return minimumLen;
232 }
233
234 int lws_context_init_client_ssl(struct lws_context_creation_info *info,
235                             struct libwebsocket_context *context)
236 {
237         int error;
238         int n;
239         SSL_METHOD *method;
240
241         if (info->port != CONTEXT_PORT_NO_LISTEN)
242                 return 0;
243
244         method = (SSL_METHOD *)SSLv23_client_method();
245         if (!method) {
246                 error = ERR_get_error();
247                 lwsl_err("problem creating ssl method %lu: %s\n",
248                         error, ERR_error_string(error,
249                                       (char *)context->service_buffer));
250                 return 1;
251         }
252         /* create context */
253         context->ssl_client_ctx = SSL_CTX_new(method);
254         if (!context->ssl_client_ctx) {
255                 error = ERR_get_error();
256                 lwsl_err("problem creating ssl context %lu: %s\n",
257                         error, ERR_error_string(error,
258                                       (char *)context->service_buffer));
259                 return 1;
260         }
261
262 #ifdef SSL_OP_NO_COMPRESSION
263         SSL_CTX_set_options(context->ssl_client_ctx,
264                                                  SSL_OP_NO_COMPRESSION);
265 #endif
266         SSL_CTX_set_options(context->ssl_client_ctx,
267                                        SSL_OP_CIPHER_SERVER_PREFERENCE);
268         if (info->ssl_cipher_list)
269                 SSL_CTX_set_cipher_list(context->ssl_client_ctx,
270                                                 info->ssl_cipher_list);
271
272 #ifdef LWS_SSL_CLIENT_USE_OS_CA_CERTS
273         if (!(info->options & LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS))
274                 /* loads OS default CA certs */
275                 SSL_CTX_set_default_verify_paths(context->ssl_client_ctx);
276 #endif
277
278         /* openssl init for cert verification (for client sockets) */
279         if (!info->ssl_ca_filepath) {
280                 if (!SSL_CTX_load_verify_locations(
281                         context->ssl_client_ctx, NULL,
282                                              LWS_OPENSSL_CLIENT_CERTS))
283                         lwsl_err(
284                             "Unable to load SSL Client certs from %s "
285                             "(set by --with-client-cert-dir= "
286                             "in configure) --  client ssl isn't "
287                             "going to work", LWS_OPENSSL_CLIENT_CERTS);
288         } else
289                 if (!SSL_CTX_load_verify_locations(
290                         context->ssl_client_ctx, info->ssl_ca_filepath,
291                                                           NULL))
292                         lwsl_err(
293                                 "Unable to load SSL Client certs "
294                                 "file from %s -- client ssl isn't "
295                                 "going to work", info->ssl_ca_filepath);
296
297         /*
298          * callback allowing user code to load extra verification certs
299          * helping the client to verify server identity
300          */
301
302         /* support for client-side certificate authentication */
303         if (info->ssl_cert_filepath) {
304                 n = SSL_CTX_use_certificate_chain_file(
305                         context->ssl_client_ctx,
306                                         info->ssl_cert_filepath);
307                 if (n != 1) {
308                         lwsl_err("problem getting cert '%s' %lu: %s\n",
309                                 info->ssl_cert_filepath,
310                                 ERR_get_error(),
311                                 ERR_error_string(ERR_get_error(),
312                                 (char *)context->service_buffer));
313                         return 1;
314                 }
315         } 
316         if (info->ssl_private_key_filepath) {
317                 /* check for provided by user password to private key */
318                 if (info->ssl_private_key_password) {
319                 /* 
320                  * password provided, set ssl callback and user data
321                  * for checking password which will be trigered during
322                  * SSL_CTX_use_PrivateKey_file function
323                  */
324                         SSL_CTX_set_default_passwd_cb_userdata(
325                                         context->ssl_client_ctx,
326                                                   (void *)info);
327                         SSL_CTX_set_default_passwd_cb(context->ssl_client_ctx,
328                                 lws_context_init_client_ssl_pem_passwd_cb);
329                 }
330                 /* set the private key from KeyFile */
331                 if (SSL_CTX_use_PrivateKey_file(context->ssl_client_ctx,
332                     info->ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) {
333                         lwsl_err("use_PrivateKey_file '%s' %lu: %s\n",
334                                 info->ssl_private_key_filepath,
335                                 ERR_get_error(),
336                                 ERR_error_string(ERR_get_error(),
337                                       (char *)context->service_buffer));
338                         return 1;
339                 }
340
341                 /* verify private key */
342                 if (!SSL_CTX_check_private_key(
343                                         context->ssl_client_ctx)) {
344                         lwsl_err("Private SSL key doesn't match cert\n");
345                         return 1;
346                 }
347         } 
348
349         context->protocols[0].callback(context, NULL,
350                 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
351                 context->ssl_client_ctx, NULL, 0);
352         
353         return 0;
354 }
355 #endif
356
357 LWS_VISIBLE int
358 lws_ssl_capable_read(struct libwebsocket_context *context,
359                      struct libwebsocket *wsi, unsigned char *buf, int len)
360 {
361         int n;
362
363         if (!wsi->ssl)
364                 return lws_ssl_capable_read_no_ssl(context, wsi, buf, len);
365         
366         wsi->buffered_reads_pending = 0;
367
368         n = SSL_read(wsi->ssl, buf, len);
369         if (n >= 0) {
370                 /* 
371                  * if it was our buffer that limited what we read,
372                  * check if SSL has additional data pending inside SSL buffers.
373                  * 
374                  * Because these won't signal at the network layer with POLLIN
375                  * and if we don't realize, this data will sit there forever
376                  */
377                 if (n == len && wsi->ssl && SSL_pending(wsi->ssl)) {
378                         context->ssl_flag_buffered_reads = 1;
379                         wsi->buffered_reads_pending = 1;
380                 }
381                 
382                 return n;
383         }
384         n = SSL_get_error(wsi->ssl, n);
385         if (n ==  SSL_ERROR_WANT_READ || n ==  SSL_ERROR_WANT_WRITE)
386                 return LWS_SSL_CAPABLE_MORE_SERVICE;
387
388         return LWS_SSL_CAPABLE_ERROR; 
389 }
390
391 LWS_VISIBLE int
392 lws_ssl_capable_write(struct libwebsocket *wsi, unsigned char *buf, int len)
393 {
394         int n;
395
396         if (!wsi->ssl)
397                 return lws_ssl_capable_write_no_ssl(wsi, buf, len);
398         
399         n = SSL_write(wsi->ssl, buf, len);
400         if (n >= 0)
401                 return n;
402
403         n = SSL_get_error(wsi->ssl, n);
404         if (n == SSL_ERROR_WANT_READ || n == SSL_ERROR_WANT_WRITE) {
405                 if (n == SSL_ERROR_WANT_WRITE)
406                         lws_set_blocking_send(wsi);
407                 return LWS_SSL_CAPABLE_MORE_SERVICE;
408         }
409
410         return LWS_SSL_CAPABLE_ERROR;
411 }
412
413 LWS_VISIBLE int
414 lws_ssl_close(struct libwebsocket *wsi)
415 {
416         int n;
417
418         if (!wsi->ssl)
419                 return 0; /* not handled */
420
421         n = SSL_get_fd(wsi->ssl);
422         SSL_shutdown(wsi->ssl);
423         compatible_close(n);
424         SSL_free(wsi->ssl);
425
426         return 1; /* handled */
427 }
428
429 LWS_VISIBLE int
430 lws_server_socket_service_ssl(struct libwebsocket_context *context,
431                 struct libwebsocket **pwsi, struct libwebsocket *new_wsi,
432                         int accept_fd, struct libwebsocket_pollfd *pollfd)
433 {
434         int n, m;
435         struct libwebsocket *wsi = *pwsi;
436 #ifndef USE_CYASSL
437         BIO *bio;
438 #endif
439
440         if (!LWS_SSL_ENABLED(context))
441                 return 0;
442
443         switch (wsi->mode) {
444         case LWS_CONNMODE_SERVER_LISTENER:
445
446                 if (!new_wsi) {
447                         lwsl_err("no new_wsi\n");
448                         return 0;
449                 }
450
451                 new_wsi->ssl = SSL_new(context->ssl_ctx);
452                 if (new_wsi->ssl == NULL) {
453                         lwsl_err("SSL_new failed: %s\n",
454                             ERR_error_string(SSL_get_error(
455                             new_wsi->ssl, 0), NULL));
456                             libwebsockets_decode_ssl_error();
457                         free(new_wsi);
458                         compatible_close(accept_fd);
459                         break;
460                 }
461
462                 SSL_set_ex_data(new_wsi->ssl,
463                         openssl_websocket_private_data_index, context);
464
465                 SSL_set_fd(new_wsi->ssl, accept_fd);
466
467 #ifdef USE_CYASSL
468                 CyaSSL_set_using_nonblock(new_wsi->ssl, 1);
469 #else
470                 SSL_set_mode(new_wsi->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
471                 bio = SSL_get_rbio(new_wsi->ssl);
472                 if (bio)
473                         BIO_set_nbio(bio, 1); /* nonblocking */
474                 else
475                         lwsl_notice("NULL rbio\n");
476                 bio = SSL_get_wbio(new_wsi->ssl);
477                 if (bio)
478                         BIO_set_nbio(bio, 1); /* nonblocking */
479                 else
480                         lwsl_notice("NULL rbio\n");
481 #endif
482
483                 /*
484                  * we are not accepted yet, but we need to enter ourselves
485                  * as a live connection.  That way we can retry when more
486                  * pieces come if we're not sorted yet
487                  */
488
489                 *pwsi = new_wsi;
490                 wsi = *pwsi;
491                 wsi->mode = LWS_CONNMODE_SSL_ACK_PENDING;
492                 insert_wsi_socket_into_fds(context, wsi);
493
494                 libwebsocket_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT,
495                                                         AWAITING_TIMEOUT);
496
497                 lwsl_info("inserted SSL accept into fds, trying SSL_accept\n");
498
499                 /* fallthru */
500
501         case LWS_CONNMODE_SSL_ACK_PENDING:
502
503                 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
504                         goto fail;
505
506                 lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);
507
508                 lws_latency_pre(context, wsi);
509
510                 n = recv(wsi->sock, context->service_buffer,
511                         sizeof(context->service_buffer), MSG_PEEK);
512
513                 /*
514                  * optionally allow non-SSL connect on SSL listening socket
515                  * This is disabled by default, if enabled it goes around any
516                  * SSL-level access control (eg, client-side certs) so leave
517                  * it disabled unless you know it's not a problem for you
518                  */
519
520                 if (context->allow_non_ssl_on_ssl_port && n >= 1 &&
521                                         context->service_buffer[0] >= ' ') {
522                         /*
523                          * TLS content-type for Handshake is 0x16
524                          * TLS content-type for ChangeCipherSpec Record is 0x14
525                          *
526                          * A non-ssl session will start with the HTTP method in
527                          * ASCII.  If we see it's not a legit SSL handshake
528                          * kill the SSL for this connection and try to handle
529                          * as a HTTP connection upgrade directly.
530                          */
531                         wsi->use_ssl = 0;
532                         SSL_shutdown(wsi->ssl);
533                         SSL_free(wsi->ssl);
534                         wsi->ssl = NULL;
535                         goto accepted;
536                 }
537
538                 /* normal SSL connection processing path */
539
540                 n = SSL_accept(wsi->ssl);
541                 lws_latency(context, wsi,
542                         "SSL_accept LWS_CONNMODE_SSL_ACK_PENDING\n", n, n == 1);
543
544                 if (n == 1)
545                         goto accepted;
546
547                 m = SSL_get_error(wsi->ssl, n);
548                 lwsl_debug("SSL_accept failed %d / %s\n",
549                                                   m, ERR_error_string(m, NULL));
550
551                 if (m == SSL_ERROR_WANT_READ) {
552                         if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
553                                 goto fail;
554
555                         lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_READ);
556
557                         lwsl_info("SSL_ERROR_WANT_READ\n");
558                         break;
559                 }
560                 if (m == SSL_ERROR_WANT_WRITE) {
561                         if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
562                                 goto fail;
563
564                         lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_WRITE);
565                         break;
566                 }
567                 lwsl_debug("SSL_accept failed skt %u: %s\n",
568                                          pollfd->fd, ERR_error_string(m, NULL));
569                 libwebsocket_close_and_free_session(context, wsi,
570                                                      LWS_CLOSE_STATUS_NOSTATUS);
571                 break;
572
573 accepted:
574                 /* OK, we are accepted... give him some time to negotiate */
575                 libwebsocket_set_timeout(wsi,
576                         PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
577                                                         AWAITING_TIMEOUT);
578
579                 wsi->mode = LWS_CONNMODE_HTTP_SERVING;
580
581                 lwsl_debug("accepted new SSL conn\n");
582                 break;
583         }
584
585         return 0;
586         
587 fail:
588         return 1;
589 }
590
591 LWS_VISIBLE void
592 lws_ssl_context_destroy(struct libwebsocket_context *context)
593 {
594         if (context->ssl_ctx)
595                 SSL_CTX_free(context->ssl_ctx);
596         if (context->ssl_client_ctx)
597                 SSL_CTX_free(context->ssl_client_ctx);
598
599         ERR_remove_state(0);
600         ERR_free_strings();
601         EVP_cleanup();
602         CRYPTO_cleanup_all_ex_data();
603 }