9c1a5b98ac5752c95def7a45ea8cdd14b8215f7d
[platform/upstream/libwebsockets.git] / lib / ssl-client.c
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010-2016 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 extern int openssl_websocket_private_data_index,
25     openssl_SSL_CTX_private_data_index;
26
27 extern void
28 lws_ssl_bind_passphrase(SSL_CTX *ssl_ctx, struct lws_context_creation_info *info);
29
30 extern int lws_ssl_get_error(struct lws *wsi, int n);
31
32 #if defined(LWS_USE_POLARSSL)
33 #else
34 #if defined(LWS_USE_MBEDTLS)
35 #else
36 #ifdef USE_WOLFSSL
37 #else
38
39 static int
40 OpenSSL_client_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
41 {
42         SSL *ssl;
43         int n;
44         struct lws *wsi;
45
46         /* keep old behaviour accepting self-signed server certs */
47         if (!preverify_ok) {
48                 int err = X509_STORE_CTX_get_error(x509_ctx);
49
50                 if (err != X509_V_OK) {
51                         ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
52                         wsi = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
53
54                         if ((err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
55                                         err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) &&
56                                         wsi->use_ssl & LCCSCF_ALLOW_SELFSIGNED) {
57                                 lwsl_notice("accepting self-signed certificate (verify_callback)\n");
58                                 X509_STORE_CTX_set_error(x509_ctx, X509_V_OK);
59                                 return 1;       // ok
60                         } else if ((err == X509_V_ERR_CERT_NOT_YET_VALID ||
61                                         err == X509_V_ERR_CERT_HAS_EXPIRED) &&
62                                         wsi->use_ssl & LCCSCF_ALLOW_EXPIRED) {
63                                 if (err == X509_V_ERR_CERT_NOT_YET_VALID)
64                                         lwsl_notice("accepting not yet valid certificate (verify_callback)\n");
65                                 else if (err == X509_V_ERR_CERT_HAS_EXPIRED)
66                                         lwsl_notice("accepting expired certificate (verify_callback)\n");
67                                 X509_STORE_CTX_set_error(x509_ctx, X509_V_OK);
68                                 return 1;       // ok
69                         }
70                 }
71         }
72
73         ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
74         wsi = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
75
76         n = lws_get_context_protocol(wsi->context, 0).callback(wsi, LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION, x509_ctx, ssl, preverify_ok);
77
78         /* keep old behaviour if something wrong with server certs */
79         /* if ssl error is overruled in callback and cert is ok,
80          * X509_STORE_CTX_set_error(x509_ctx, X509_V_OK); must be set and
81          * return value is 0 from callback */
82         if (!preverify_ok) {
83                 int err = X509_STORE_CTX_get_error(x509_ctx);
84
85                 if (err != X509_V_OK) { /* cert validation error was not handled in callback */
86                         int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
87                         const char* msg = X509_verify_cert_error_string(err);
88                         lwsl_err("SSL error: %s (preverify_ok=%d;err=%d;depth=%d)\n", msg, preverify_ok, err, depth);
89                         return preverify_ok;    // not ok
90                 }
91         }
92         /* convert callback return code from 0 = OK to verify callback return value 1 = OK */
93         return !n;
94 }
95 #endif
96 #endif
97 #endif
98
99 int
100 lws_ssl_client_bio_create(struct lws *wsi)
101 {
102 #if defined(LWS_USE_POLARSSL)
103         return 0;
104 #else
105 #if defined(LWS_USE_MBEDTLS)
106 #else
107         char hostname[128], *p;
108
109         if (lws_hdr_copy(wsi, hostname, sizeof(hostname),
110                          _WSI_TOKEN_CLIENT_HOST) <= 0) {
111                 lwsl_err("%s: Unable to get hostname\n", __func__);
112
113                 return -1;
114         }
115
116         /*
117          * remove any :port part on the hostname... necessary for network
118          * connection but typical certificates do not contain it
119          */
120         p = hostname;
121         while (*p) {
122                 if (*p == ':') {
123                         *p = '\0';
124                         break;
125                 }
126                 p++;
127         }
128
129         wsi->ssl = SSL_new(wsi->vhost->ssl_client_ctx);
130         if (!wsi->ssl) {
131                 lwsl_err("SSL_new failed: %s\n",
132                          ERR_error_string(lws_ssl_get_error(wsi, 0), NULL));
133                 lws_decode_ssl_error();
134                 return -1;
135         }
136
137 #if defined LWS_HAVE_X509_VERIFY_PARAM_set1_host
138         X509_VERIFY_PARAM *param;
139         (void)param;
140
141         if (!(wsi->use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) {
142                 param = SSL_get0_param(wsi->ssl);
143                 /* Enable automatic hostname checks */
144                 X509_VERIFY_PARAM_set_hostflags(param,
145                                                 X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
146                 X509_VERIFY_PARAM_set1_host(param, hostname, 0);
147         }
148
149 #endif
150
151 #ifndef USE_WOLFSSL
152 #ifndef USE_OLD_CYASSL
153         /* OpenSSL_client_verify_callback will be called @ SSL_connect() */
154         SSL_set_verify(wsi->ssl, SSL_VERIFY_PEER, OpenSSL_client_verify_callback);
155 #endif
156 #endif
157
158 #ifndef USE_WOLFSSL
159         SSL_set_mode(wsi->ssl,  SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
160 #endif
161         /*
162          * use server name indication (SNI), if supported,
163          * when establishing connection
164          */
165 #ifdef USE_WOLFSSL
166 #ifdef USE_OLD_CYASSL
167 #ifdef CYASSL_SNI_HOST_NAME
168         CyaSSL_UseSNI(wsi->ssl, CYASSL_SNI_HOST_NAME, hostname, strlen(hostname));
169 #endif
170 #else
171 #ifdef WOLFSSL_SNI_HOST_NAME
172         wolfSSL_UseSNI(wsi->ssl, WOLFSSL_SNI_HOST_NAME, hostname, strlen(hostname));
173 #endif
174 #endif
175 #else
176 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
177         SSL_set_tlsext_host_name(wsi->ssl, hostname);
178 #endif
179 #endif
180
181 #ifdef USE_WOLFSSL
182         /*
183          * wolfSSL/CyaSSL does certificate verification differently
184          * from OpenSSL.
185          * If we should ignore the certificate, we need to set
186          * this before SSL_new and SSL_connect is called.
187          * Otherwise the connect will simply fail with error code -155
188          */
189 #ifdef USE_OLD_CYASSL
190         if (wsi->use_ssl == 2)
191                 CyaSSL_set_verify(wsi->ssl, SSL_VERIFY_NONE, NULL);
192 #else
193         if (wsi->use_ssl == 2)
194                 wolfSSL_set_verify(wsi->ssl, SSL_VERIFY_NONE, NULL);
195 #endif
196 #endif /* USE_WOLFSSL */
197
198         wsi->client_bio = BIO_new_socket(wsi->sock, BIO_NOCLOSE);
199         SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
200
201 #ifdef USE_WOLFSSL
202 #ifdef USE_OLD_CYASSL
203         CyaSSL_set_using_nonblock(wsi->ssl, 1);
204 #else
205         wolfSSL_set_using_nonblock(wsi->ssl, 1);
206 #endif
207 #else
208         BIO_set_nbio(wsi->client_bio, 1); /* nonblocking */
209 #endif
210
211         SSL_set_ex_data(wsi->ssl, openssl_websocket_private_data_index,
212                         wsi);
213
214         return 0;
215 #endif
216 #endif
217 }
218
219 int
220 lws_ssl_client_connect1(struct lws *wsi)
221 {
222         struct lws_context *context = wsi->context;
223         int n = 0;
224
225         lws_latency_pre(context, wsi);
226 #if defined(LWS_USE_POLARSSL)
227 #else
228 #if defined(LWS_USE_MBEDTLS)
229 #else
230         n = SSL_connect(wsi->ssl);
231 #endif
232 #endif
233
234         lws_latency(context, wsi,
235           "SSL_connect LWSCM_WSCL_ISSUE_HANDSHAKE", n, n > 0);
236
237         if (n < 0) {
238                 n = lws_ssl_get_error(wsi, n);
239
240                 if (n == SSL_ERROR_WANT_READ)
241                         goto some_wait;
242
243                 if (n == SSL_ERROR_WANT_WRITE) {
244                         /*
245                          * wants us to retry connect due to
246                          * state of the underlying ssl layer...
247                          * but since it may be stalled on
248                          * blocked write, no incoming data may
249                          * arrive to trigger the retry.
250                          * Force (possibly many times if the SSL
251                          * state persists in returning the
252                          * condition code, but other sockets
253                          * are getting serviced inbetweentimes)
254                          * us to get called back when writable.
255                          */
256                         lwsl_info("%s: WANT_WRITE... retrying\n", __func__);
257                         lws_callback_on_writable(wsi);
258 some_wait:
259                         wsi->mode = LWSCM_WSCL_WAITING_SSL;
260
261                         return 0; /* no error */
262                 }
263
264                 {
265                         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
266                         char *p = (char *)&pt->serv_buf[0];
267                         char *sb = p;
268
269                         lwsl_err("ssl hs1 error, X509_V_ERR = %d: %s\n",
270                                  n, ERR_error_string(n, sb));
271                         lws_ssl_elaborate_error();
272                 }
273
274                 n = -1;
275         }
276
277         if (n <= 0) {
278                 /*
279                  * retry if new data comes until we
280                  * run into the connection timeout or win
281                  */
282 #if defined(LWS_USE_POLARSSL)
283 #else
284 #if defined(LWS_USE_MBEDTLS)
285 #else
286                 unsigned long error = ERR_get_error();
287
288                 if (error != SSL_ERROR_NONE) {
289                         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
290                         char *p = (char *)&pt->serv_buf[0];
291                         char *sb = p;
292                         lwsl_err("SSL connect error %lu: %s\n",
293                                 error, ERR_error_string(error, sb));
294                         return -1;
295                 }
296 #endif
297 #endif
298         }
299
300         return 1;
301 }
302
303 int
304 lws_ssl_client_connect2(struct lws *wsi)
305 {
306         struct lws_context *context = wsi->context;
307 #if defined(LWS_USE_POLARSSL)
308 #else
309 #if defined(LWS_USE_MBEDTLS)
310 #else
311         struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
312         char *p = (char *)&pt->serv_buf[0];
313         char *sb = p;
314 #endif
315 #endif
316         int n = 0;
317
318         if (wsi->mode == LWSCM_WSCL_WAITING_SSL) {
319                 lws_latency_pre(context, wsi);
320 #if defined(LWS_USE_POLARSSL)
321 #else
322 #if defined(LWS_USE_MBEDTLS)
323 #else
324                 n = SSL_connect(wsi->ssl);
325 #endif
326 #endif
327                 lwsl_notice("%s: SSL_connect says %d\n", __func__, n);
328
329                 lws_latency(context, wsi,
330                             "SSL_connect LWSCM_WSCL_WAITING_SSL", n, n > 0);
331
332                 if (n < 0) {
333                         n = lws_ssl_get_error(wsi, n);
334
335                         if (n == SSL_ERROR_WANT_READ) {
336                                 lwsl_info("SSL_connect WANT_READ... retrying\n");
337
338                                 wsi->mode = LWSCM_WSCL_WAITING_SSL;
339
340                                 return 0; /* no error */
341                         }
342
343                         if (n == SSL_ERROR_WANT_WRITE) {
344                                 /*
345                                  * wants us to retry connect due to
346                                  * state of the underlying ssl layer...
347                                  * but since it may be stalled on
348                                  * blocked write, no incoming data may
349                                  * arrive to trigger the retry.
350                                  * Force (possibly many times if the SSL
351                                  * state persists in returning the
352                                  * condition code, but other sockets
353                                  * are getting serviced inbetweentimes)
354                                  * us to get called back when writable.
355                                  */
356                                 lwsl_info("SSL_connect WANT_WRITE... retrying\n");
357                                 lws_callback_on_writable(wsi);
358
359                                 wsi->mode = LWSCM_WSCL_WAITING_SSL;
360
361                                 return 0; /* no error */
362                         }
363
364                         n = -1;
365                 }
366
367                 if (n <= 0) {
368                         /*
369                          * retry if new data comes until we
370                          * run into the connection timeout or win
371                          */
372 #if defined(LWS_USE_POLARSSL)
373 #else
374 #if defined(LWS_USE_MBEDTLS)
375 #else
376                         unsigned long error = ERR_get_error();
377                         if (error != SSL_ERROR_NONE) {
378                                 lwsl_err("SSL connect error %lu: %s\n",
379                                          error, ERR_error_string(error, sb));
380                                 return -1;
381                         }
382 #endif
383 #endif
384                 }
385         }
386
387 #if defined(LWS_USE_POLARSSL)
388 #else
389 #if defined(LWS_USE_MBEDTLS)
390 #else
391 #ifndef USE_WOLFSSL
392         /*
393          * See comment above about wolfSSL certificate
394          * verification
395          */
396         lws_latency_pre(context, wsi);
397         n = SSL_get_verify_result(wsi->ssl);
398         lws_latency(context, wsi,
399                 "SSL_get_verify_result LWS_CONNMODE..HANDSHAKE", n, n > 0);
400
401         if (n != X509_V_OK) {
402                 if ((n == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
403                      n == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) &&
404                      (wsi->use_ssl & LCCSCF_ALLOW_SELFSIGNED)) {
405                         lwsl_notice("accepting self-signed certificate\n");
406                 } else if ((n == X509_V_ERR_CERT_NOT_YET_VALID ||
407                             n == X509_V_ERR_CERT_HAS_EXPIRED) &&
408                      (wsi->use_ssl & LCCSCF_ALLOW_EXPIRED)) {
409                         lwsl_notice("accepting expired certificate\n");
410                 } else if (n == X509_V_ERR_CERT_NOT_YET_VALID) {
411                         lwsl_notice("Cert is from the future... "
412                                     "probably our clock... accepting...\n");
413                 } else {
414                         lwsl_err("server's cert didn't look good, X509_V_ERR = %d: %s\n",
415                                  n, ERR_error_string(n, sb));
416                         lws_ssl_elaborate_error();
417                         return -1;
418                 }
419         }
420
421 #endif /* USE_WOLFSSL */
422 #endif
423 #endif
424
425         return 1;
426 }
427
428
429 int lws_context_init_client_ssl(struct lws_context_creation_info *info,
430                                 struct lws_vhost *vhost)
431 {
432 #if defined(LWS_USE_POLARSSL)
433         return 0;
434 #else
435 #if defined(LWS_USE_MBEDTLS)
436 #else
437         SSL_METHOD *method;
438         struct lws wsi;
439         unsigned long error;
440         int n;
441
442         if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
443                 return 0;
444
445         if (info->provided_client_ssl_ctx) {
446                 /* use the provided OpenSSL context if given one */
447                 vhost->ssl_client_ctx = info->provided_client_ssl_ctx;
448                 /* nothing for lib to delete */
449                 vhost->user_supplied_ssl_ctx = 1;
450
451                 return 0;
452         }
453
454         if (info->port != CONTEXT_PORT_NO_LISTEN)
455                 return 0;
456
457         /* basic openssl init already happened in context init */
458
459         method = (SSL_METHOD *)SSLv23_client_method();
460         if (!method) {
461                 error = ERR_get_error();
462                 lwsl_err("problem creating ssl method %lu: %s\n",
463                         error, ERR_error_string(error,
464                                       (char *)vhost->context->pt[0].serv_buf));
465                 return 1;
466         }
467         /* create context */
468         vhost->ssl_client_ctx = SSL_CTX_new(method);
469         if (!vhost->ssl_client_ctx) {
470                 error = ERR_get_error();
471                 lwsl_err("problem creating ssl context %lu: %s\n",
472                         error, ERR_error_string(error,
473                                       (char *)vhost->context->pt[0].serv_buf));
474                 return 1;
475         }
476
477 #ifdef SSL_OP_NO_COMPRESSION
478         SSL_CTX_set_options(vhost->ssl_client_ctx, SSL_OP_NO_COMPRESSION);
479 #endif
480         SSL_CTX_set_options(vhost->ssl_client_ctx,
481                             SSL_OP_CIPHER_SERVER_PREFERENCE);
482         if (info->ssl_cipher_list)
483                 SSL_CTX_set_cipher_list(vhost->ssl_client_ctx,
484                                                 info->ssl_cipher_list);
485
486 #ifdef LWS_SSL_CLIENT_USE_OS_CA_CERTS
487         if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS))
488                 /* loads OS default CA certs */
489                 SSL_CTX_set_default_verify_paths(vhost->ssl_client_ctx);
490 #endif
491
492         /* openssl init for cert verification (for client sockets) */
493         if (!info->ssl_ca_filepath) {
494                 if (!SSL_CTX_load_verify_locations(
495                         vhost->ssl_client_ctx, NULL,
496                                              LWS_OPENSSL_CLIENT_CERTS))
497                         lwsl_err(
498                             "Unable to load SSL Client certs from %s "
499                             "(set by --with-client-cert-dir= "
500                             "in configure) --  client ssl isn't "
501                             "going to work", LWS_OPENSSL_CLIENT_CERTS);
502         } else
503                 if (!SSL_CTX_load_verify_locations(
504                         vhost->ssl_client_ctx, info->ssl_ca_filepath,
505                                                           NULL)) {
506                         lwsl_err(
507                                 "Unable to load SSL Client certs "
508                                 "file from %s -- client ssl isn't "
509                                 "going to work", info->ssl_ca_filepath);
510                         lws_ssl_elaborate_error();
511                 }
512                 else
513                         lwsl_info("loaded ssl_ca_filepath\n");
514
515         /*
516          * callback allowing user code to load extra verification certs
517          * helping the client to verify server identity
518          */
519
520         /* support for client-side certificate authentication */
521         if (info->ssl_cert_filepath) {
522         lwsl_notice("%s: doing cert filepath\n", __func__);
523                 n = SSL_CTX_use_certificate_chain_file(vhost->ssl_client_ctx,
524                                                        info->ssl_cert_filepath);
525                 if (n < 1) {
526                         lwsl_err("problem %d getting cert '%s'\n", n,
527                                 info->ssl_cert_filepath);
528                         lws_ssl_elaborate_error();
529                         return 1;
530                 }
531                 lwsl_notice("Loaded client cert %s\n", info->ssl_cert_filepath);
532         }
533
534         if (info->ssl_private_key_filepath) {
535                 lwsl_notice("%s: doing private key filepath\n", __func__);
536                 lws_ssl_bind_passphrase(vhost->ssl_client_ctx, info);
537                 /* set the private key from KeyFile */
538                 if (SSL_CTX_use_PrivateKey_file(vhost->ssl_client_ctx,
539                     info->ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) {
540                         lwsl_err("use_PrivateKey_file '%s'\n",
541                                 info->ssl_private_key_filepath);
542                         lws_ssl_elaborate_error();
543                         return 1;
544                 }
545                 lwsl_notice("Loaded client cert private key %s\n",
546                             info->ssl_private_key_filepath);
547
548                 /* verify private key */
549                 if (!SSL_CTX_check_private_key(vhost->ssl_client_ctx)) {
550                         lwsl_err("Private SSL key doesn't match cert\n");
551                         return 1;
552                 }
553         }
554
555         /*
556          * give him a fake wsi with context set, so he can use
557          * lws_get_context() in the callback
558          */
559         memset(&wsi, 0, sizeof(wsi));
560         wsi.vhost = vhost;
561         wsi.context = vhost->context;
562
563         vhost->protocols[0].callback(&wsi,
564                         LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
565                                        vhost->ssl_client_ctx, NULL, 0);
566
567         return 0;
568 #endif
569 #endif
570 }