Coverage Report

Created: 2024-09-08 06:10

/src/libwebsockets/lib/tls/openssl/openssl-client.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * libwebsockets - small server side websockets and web server implementation
3
 *
4
 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to
8
 * deal in the Software without restriction, including without limitation the
9
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10
 * sell copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
 * IN THE SOFTWARE.
23
 */
24
25
#include "lws_config.h"
26
#ifdef LWS_HAVE_X509_VERIFY_PARAM_set1_host
27
/* Before glibc 2.10, strnlen required _GNU_SOURCE */
28
#if !defined(_GNU_SOURCE)
29
#define _GNU_SOURCE
30
#endif
31
#endif
32
#include <string.h>
33
34
#include "private-lib-core.h"
35
#include "private-lib-tls-openssl.h"
36
37
/*
38
 * Care: many openssl apis return 1 for success.  These are translated to the
39
 * lws convention of 0 for success.
40
 */
41
42
int lws_openssl_describe_cipher(struct lws *wsi);
43
44
extern int openssl_websocket_private_data_index,
45
    openssl_SSL_CTX_private_data_index;
46
47
#if !defined(USE_WOLFSSL)
48
49
#if 0
50
#if defined(LWS_WITH_TLS_JIT_TRUST)
51
52
/*
53
 * Completion of sync or async JIT trust lookup
54
 */
55
56
int
57
lws_tls_jit_trust_got_cert_cb(void *got_opaque, const uint8_t *der,
58
            size_t der_len)
59
{
60
  X509 *x = d2i_X509(NULL, &der, (long)der_len);
61
  /** !!! this is not safe for async atm */
62
  struct lws *wsi = (struct lws *)got_opaque;
63
  X509_STORE *xs;
64
  int ret = 0;
65
66
  if (!x) {
67
    lwsl_err("%s: failed\n", __func__);
68
    return 1;
69
  }
70
71
  xs = SSL_CTX_get_cert_store(SSL_get_SSL_CTX(wsi->tls.ssl));
72
  if (xs) {
73
    if (X509_STORE_add_cert(xs, x) != 1) {
74
      lwsl_warn("%s: unable to set trusted CA\n", __func__);
75
      ret = 1;
76
    } else
77
      lwsl_notice("%s: added trusted CA to CTX for next time\n",
78
          __func__);
79
  } else
80
    lwsl_warn("%s: couldn't get cert store\n", __func__);
81
82
  X509_free(x);
83
84
  return ret;
85
}
86
#endif
87
#endif
88
89
static int
90
OpenSSL_client_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
91
0
{
92
0
  SSL *ssl;
93
0
  int n, err = 0;
94
0
  struct lws *wsi;
95
96
  /* keep old behaviour accepting self-signed server certs */
97
0
  if (!preverify_ok) {
98
0
    err = X509_STORE_CTX_get_error(x509_ctx);
99
100
0
    if (err != X509_V_OK) {
101
0
      ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
102
0
          SSL_get_ex_data_X509_STORE_CTX_idx());
103
0
      wsi = SSL_get_ex_data(ssl,
104
0
          openssl_websocket_private_data_index);
105
0
      if (!wsi) {
106
0
        lwsl_err("%s: can't get wsi from ssl privdata\n",
107
0
           __func__);
108
109
0
        return 0;
110
0
      }
111
112
0
      if ((err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
113
0
           err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) &&
114
0
           wsi->tls.use_ssl & LCCSCF_ALLOW_SELFSIGNED) {
115
0
        lwsl_notice("accepting self-signed "
116
0
              "certificate (verify_callback)\n");
117
0
        X509_STORE_CTX_set_error(x509_ctx, X509_V_OK);
118
0
        return 1; // ok
119
0
    } else if ((err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY ||
120
0
          err == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE) &&
121
0
          wsi->tls.use_ssl & LCCSCF_ALLOW_INSECURE) {
122
0
        lwsl_notice("accepting non-trusted certificate\n");
123
0
        X509_STORE_CTX_set_error(x509_ctx, X509_V_OK);
124
0
        return 1;  /* ok */
125
0
      } else if ((err == X509_V_ERR_CERT_NOT_YET_VALID ||
126
0
            err == X509_V_ERR_CERT_HAS_EXPIRED) &&
127
0
            wsi->tls.use_ssl & LCCSCF_ALLOW_EXPIRED) {
128
0
        if (err == X509_V_ERR_CERT_NOT_YET_VALID)
129
0
          lwsl_notice("accepting not yet valid "
130
0
                "certificate (verify_"
131
0
                "callback)\n");
132
0
        else if (err == X509_V_ERR_CERT_HAS_EXPIRED)
133
0
          lwsl_notice("accepting expired "
134
0
                "certificate (verify_"
135
0
                "callback)\n");
136
0
        X509_STORE_CTX_set_error(x509_ctx, X509_V_OK);
137
0
        return 1; // ok
138
0
      }
139
0
    }
140
0
  }
141
142
0
  ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
143
0
           SSL_get_ex_data_X509_STORE_CTX_idx());
144
0
  wsi = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
145
0
  if (!wsi) {
146
0
    lwsl_err("%s: can't get wsi from ssl privdata\n",  __func__);
147
148
0
    return 0;
149
0
  }
150
151
#if defined(LWS_WITH_TLS_JIT_TRUST)
152
  if (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) {
153
    union lws_tls_cert_info_results ci;
154
    STACK_OF(X509) *x509_stack;
155
156
    x509_stack = X509_STORE_CTX_get1_chain(x509_ctx);
157
    if (x509_stack) {
158
159
      for (n = 0; n < OPENSSL_sk_num((const OPENSSL_STACK *)x509_stack) &&
160
            wsi->tls.kid_chain.count !=
161
             LWS_ARRAY_SIZE(wsi->tls.kid_chain.akid); n++) {
162
        X509 *x509 = OPENSSL_sk_value((const OPENSSL_STACK *)x509_stack, n);
163
164
        if (!lws_tls_openssl_cert_info(x509,
165
              LWS_TLS_CERT_INFO_SUBJECT_KEY_ID,
166
              &ci, 0))
167
          lws_tls_kid_copy(&ci,
168
            &wsi->tls.kid_chain.skid[
169
                 wsi->tls.kid_chain.count]);
170
171
        if (!lws_tls_openssl_cert_info(x509,
172
               LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID,
173
               &ci, 0))
174
          lws_tls_kid_copy(&ci,
175
             &wsi->tls.kid_chain.akid[
176
                 wsi->tls.kid_chain.count]);
177
178
        wsi->tls.kid_chain.count++;
179
      }
180
181
      sk_X509_pop_free(x509_stack, X509_free);
182
    }
183
184
    lws_tls_jit_trust_sort_kids(wsi, &wsi->tls.kid_chain);
185
  }
186
#endif
187
188
0
  n = lws_get_context_protocol(wsi->a.context, 0).callback(wsi,
189
0
      LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION,
190
0
      x509_ctx, ssl, (unsigned int)preverify_ok);
191
192
  /* keep old behaviour if something wrong with server certs */
193
  /* if ssl error is overruled in callback and cert is ok,
194
   * X509_STORE_CTX_set_error(x509_ctx, X509_V_OK); must be set and
195
   * return value is 0 from callback */
196
0
  if (!preverify_ok) {
197
0
    int err = X509_STORE_CTX_get_error(x509_ctx);
198
199
0
    if (err != X509_V_OK) {
200
      /* cert validation error was not handled in callback */
201
0
      int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
202
0
      const char *msg = X509_verify_cert_error_string(err);
203
204
0
      lws_strncpy(wsi->tls.err_helper, msg,
205
0
            sizeof(wsi->tls.err_helper));
206
207
0
      lwsl_err("SSL error: %s (preverify_ok=%d;err=%d;"
208
0
         "depth=%d)\n", msg, preverify_ok, err, depth);
209
210
#if defined(LWS_WITH_SYS_METRICS)
211
      {
212
        char buckname[64];
213
214
        lws_snprintf(buckname, sizeof(buckname),
215
               "tls=\"%s\"", msg);
216
        lws_metrics_hist_bump_describe_wsi(wsi,
217
          lws_metrics_priv_to_pub(wsi->a.context->mth_conn_failures),
218
          buckname);
219
      }
220
#endif
221
222
0
      return preverify_ok;  // not ok
223
0
    }
224
0
  }
225
  /*
226
   * convert callback return code from 0 = OK to verify callback
227
   * return value 1 = OK
228
   */
229
0
  return !n;
230
0
}
231
#endif
232
233
int
234
lws_ssl_client_bio_create(struct lws *wsi)
235
0
{
236
0
  char hostname[128], *p;
237
0
#if defined(LWS_HAVE_SSL_set_alpn_protos) && \
238
0
    defined(LWS_HAVE_SSL_get0_alpn_selected)
239
0
  uint8_t openssl_alpn[40];
240
0
  const char *alpn_comma = wsi->a.context->tls.alpn_default;
241
0
  int n;
242
0
#endif
243
244
0
  if (wsi->stash) {
245
0
    lws_strncpy(hostname, wsi->stash->cis[CIS_HOST], sizeof(hostname));
246
0
#if defined(LWS_HAVE_SSL_set_alpn_protos) && \
247
0
    defined(LWS_HAVE_SSL_get0_alpn_selected)
248
0
    alpn_comma = wsi->stash->cis[CIS_ALPN];
249
0
#endif
250
0
  } else {
251
0
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
252
0
    if (lws_hdr_copy(wsi, hostname, sizeof(hostname),
253
0
         _WSI_TOKEN_CLIENT_HOST) <= 0)
254
0
#endif
255
0
    {
256
0
      lwsl_err("%s: Unable to get hostname\n", __func__);
257
258
0
      return -1;
259
0
    }
260
0
  }
261
262
  /*
263
   * remove any :port part on the hostname... necessary for network
264
   * connection but typical certificates do not contain it
265
   */
266
0
  p = hostname;
267
0
  while (*p) {
268
0
    if (*p == ':') {
269
0
      *p = '\0';
270
0
      break;
271
0
    }
272
0
    p++;
273
0
  }
274
275
0
  wsi->tls.ssl = SSL_new(wsi->a.vhost->tls.ssl_client_ctx);
276
0
  if (!wsi->tls.ssl) {
277
0
    const char *es = ERR_error_string(
278
#if defined(LWS_WITH_BORINGSSL)
279
  (uint32_t)
280
#else
281
0
  (unsigned long)
282
0
#endif
283
0
  lws_ssl_get_error(wsi, 0), NULL);
284
0
    lwsl_err("SSL_new failed: %s\n", es);
285
0
    lws_tls_err_describe_clear();
286
0
    return -1;
287
0
  }
288
289
0
#if defined(LWS_WITH_TLS_SESSIONS)
290
0
  if (!(wsi->a.vhost->options & LWS_SERVER_OPTION_DISABLE_TLS_SESSION_CACHE))
291
0
    lws_tls_reuse_session(wsi);
292
0
#endif
293
294
0
#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
295
0
  if (wsi->a.vhost->tls.ssl_info_event_mask)
296
0
    SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback);
297
0
#endif
298
299
0
#if defined(LWS_HAVE_X509_VERIFY_PARAM_set1_host)
300
0
  if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) {
301
0
#if !defined(USE_WOLFSSL)
302
303
0
    X509_VERIFY_PARAM *param = SSL_get0_param(wsi->tls.ssl);
304
305
    /* Enable automatic hostname checks */
306
0
    X509_VERIFY_PARAM_set_hostflags(param,
307
0
          X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
308
    /* Handle the case where the hostname is an IP address */
309
0
    if (!X509_VERIFY_PARAM_set1_ip_asc(param, hostname))
310
0
      X509_VERIFY_PARAM_set1_host(param, hostname,
311
0
          strnlen(hostname, sizeof(hostname)));
312
0
#endif
313
314
0
  }
315
#else
316
  if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) {
317
    lwsl_err("%s: your tls lib is too old to have "
318
       "X509_VERIFY_PARAM_set1_host, failing all client tls\n",
319
       __func__);
320
    return -1;
321
  }
322
#endif
323
324
0
#if !defined(USE_WOLFSSL)
325
0
#ifndef USE_OLD_CYASSL
326
  /* OpenSSL_client_verify_callback will be called @ SSL_connect() */
327
0
  SSL_set_verify(wsi->tls.ssl, SSL_VERIFY_PEER,
328
0
           OpenSSL_client_verify_callback);
329
0
#endif
330
0
#endif
331
332
0
#if !defined(USE_WOLFSSL)
333
0
  SSL_set_mode(wsi->tls.ssl,  SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
334
0
#endif
335
  /*
336
   * use server name indication (SNI), if supported,
337
   * when establishing connection
338
   */
339
#ifdef USE_WOLFSSL
340
#ifdef USE_OLD_CYASSL
341
#ifdef CYASSL_SNI_HOST_NAME
342
  CyaSSL_UseSNI(wsi->tls.ssl, CYASSL_SNI_HOST_NAME, hostname,
343
          strlen(hostname));
344
#endif
345
#else
346
#if defined(WOLFSSL_SNI_HOST_NAME) || defined(HAVE_SNI)
347
  wolfSSL_UseSNI(wsi->tls.ssl, WOLFSSL_SNI_HOST_NAME, hostname,
348
           (unsigned short)strlen(hostname));
349
#endif
350
#endif
351
#else
352
0
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
353
0
  SSL_set_tlsext_host_name(wsi->tls.ssl, hostname);
354
0
#endif
355
0
#endif
356
357
#ifdef USE_WOLFSSL
358
  /*
359
   * wolfSSL/CyaSSL does certificate verification differently
360
   * from OpenSSL.
361
   * If we should ignore the certificate, we need to set
362
   * this before SSL_new and SSL_connect is called.
363
   * Otherwise the connect will simply fail with error code -155
364
   */
365
#ifdef USE_OLD_CYASSL
366
  if (wsi->tls.use_ssl & LCCSCF_ALLOW_SELFSIGNED)
367
    CyaSSL_set_verify(wsi->tls.ssl, SSL_VERIFY_NONE, NULL);
368
#else
369
  if (wsi->tls.use_ssl & LCCSCF_ALLOW_SELFSIGNED)
370
    wolfSSL_set_verify(wsi->tls.ssl, SSL_VERIFY_NONE, NULL);
371
#endif
372
#endif /* USE_WOLFSSL */
373
374
0
  wsi->tls.client_bio = BIO_new_socket((int)(lws_intptr_t)wsi->desc.sockfd,
375
0
               BIO_NOCLOSE);
376
0
  SSL_set_bio(wsi->tls.ssl, wsi->tls.client_bio, wsi->tls.client_bio);
377
378
#ifdef USE_WOLFSSL
379
#ifdef USE_OLD_CYASSL
380
  CyaSSL_set_using_nonblock(wsi->tls.ssl, 1);
381
#else
382
  wolfSSL_set_using_nonblock(wsi->tls.ssl, 1);
383
#endif
384
#else
385
0
  BIO_set_nbio(wsi->tls.client_bio, 1); /* nonblocking */
386
0
#endif
387
388
0
#if defined(LWS_HAVE_SSL_set_alpn_protos) && \
389
0
    defined(LWS_HAVE_SSL_get0_alpn_selected)
390
0
  if (wsi->a.vhost->tls.alpn)
391
0
    alpn_comma = wsi->a.vhost->tls.alpn;
392
0
  if (wsi->stash) {
393
0
    alpn_comma = wsi->stash->cis[CIS_ALPN];
394
0
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
395
0
  } else {
396
0
    if (lws_hdr_copy(wsi, hostname, sizeof(hostname),
397
0
         _WSI_TOKEN_CLIENT_ALPN) > 0)
398
0
      alpn_comma = hostname;
399
0
#endif
400
0
  }
401
402
0
  lwsl_info("%s client conn using alpn list '%s'\n", wsi->role_ops->name, alpn_comma);
403
404
0
  n = lws_alpn_comma_to_openssl(alpn_comma, openssl_alpn,
405
0
              sizeof(openssl_alpn) - 1);
406
407
0
  SSL_set_alpn_protos(wsi->tls.ssl, openssl_alpn, (unsigned int)n);
408
0
#endif
409
410
0
  SSL_set_ex_data(wsi->tls.ssl, openssl_websocket_private_data_index,
411
0
      wsi);
412
413
0
  if (wsi->sys_tls_client_cert) {
414
0
    lws_system_blob_t *b = lws_system_get_blob(wsi->a.context,
415
0
          LWS_SYSBLOB_TYPE_CLIENT_CERT_DER,
416
0
          wsi->sys_tls_client_cert - 1);
417
0
    const uint8_t *data;
418
0
    size_t size;
419
420
0
    if (!b)
421
0
      goto no_client_cert;
422
423
    /*
424
     * Set up the per-connection client cert
425
     */
426
427
0
    size = lws_system_blob_get_size(b);
428
0
    if (!size)
429
0
      goto no_client_cert;
430
431
0
    if (lws_system_blob_get_single_ptr(b, &data))
432
0
      goto no_client_cert;
433
434
0
    if (SSL_use_certificate_ASN1(wsi->tls.ssl,
435
#if defined(USE_WOLFSSL)
436
      (unsigned char *)
437
#endif
438
0
          data,
439
#if defined(LWS_WITH_BORINGSSL)
440
          (size_t)
441
#else
442
0
          (int)
443
0
#endif
444
0
          size) != 1) {
445
0
      lwsl_err("%s: use_certificate failed\n", __func__);
446
0
      lws_tls_err_describe_clear();
447
0
      goto no_client_cert;
448
0
    }
449
450
0
    b = lws_system_get_blob(wsi->a.context,
451
0
          LWS_SYSBLOB_TYPE_CLIENT_KEY_DER,
452
0
          wsi->sys_tls_client_cert - 1);
453
0
    if (!b)
454
0
      goto no_client_cert;
455
456
0
    size = lws_system_blob_get_size(b);
457
0
    if (!size)
458
0
      goto no_client_cert;
459
460
0
    if (lws_system_blob_get_single_ptr(b, &data))
461
0
      goto no_client_cert;
462
463
0
    if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, wsi->tls.ssl,
464
#if defined(USE_WOLFSSL)
465
      (unsigned char *)
466
#endif
467
468
0
              data,
469
#if defined(LWS_WITH_BORINGSSL)
470
          (size_t)
471
#else
472
0
          (int)
473
0
#endif
474
0
              size) != 1 &&
475
0
        SSL_use_PrivateKey_ASN1(EVP_PKEY_EC, wsi->tls.ssl,
476
#if defined(USE_WOLFSSL)
477
      (unsigned char *)
478
#endif
479
0
              data,
480
#if defined(LWS_WITH_BORINGSSL)
481
          (size_t)
482
#else
483
0
          (int)
484
0
#endif
485
0
              size) != 1) {
486
0
      lwsl_err("%s: use_privkey failed\n", __func__);
487
0
      lws_tls_err_describe_clear();
488
0
      goto no_client_cert;
489
0
    }
490
491
0
    if (SSL_check_private_key(wsi->tls.ssl) != 1) {
492
0
      lwsl_err("Private SSL key doesn't match cert\n");
493
0
      lws_tls_err_describe_clear();
494
0
      return 1;
495
0
    }
496
497
0
    lwsl_notice("%s: set system client cert %u\n", __func__,
498
0
        wsi->sys_tls_client_cert - 1);
499
0
  }
500
501
0
  return 0;
502
503
0
no_client_cert:
504
0
  lwsl_err("%s: unable to set up system client cert %d\n", __func__,
505
0
      wsi->sys_tls_client_cert - 1);
506
507
0
  return 1;
508
0
}
509
510
enum lws_ssl_capable_status
511
lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen)
512
0
{
513
0
#if defined(LWS_HAVE_SSL_set_alpn_protos) && \
514
0
    defined(LWS_HAVE_SSL_get0_alpn_selected)
515
0
  const unsigned char *prot;
516
0
  char a[32];
517
0
  unsigned int len;
518
0
#endif
519
0
  int m, n, en;
520
0
  unsigned long l;
521
0
#if defined(LWS_WITH_TLS_SESSIONS) && defined(LWS_HAVE_SSL_SESSION_set_time)
522
0
  SSL_SESSION *sess;
523
0
#endif
524
0
  errno = 0;
525
0
  ERR_clear_error();
526
0
  wsi->tls.err_helper[0] = '\0';
527
0
  n = SSL_connect(wsi->tls.ssl);
528
0
  en = errno;
529
530
0
  m = lws_ssl_get_error(wsi, n);
531
532
0
  if (m == SSL_ERROR_SYSCALL
533
#if defined(WIN32)
534
      && en
535
#endif
536
0
  ) {
537
0
#if defined(WIN32) || (_LWS_ENABLED_LOGS & LLL_INFO)
538
0
    lwsl_info("%s: n %d, m %d, errno %d\n", __func__, n, m, en);
539
0
#endif
540
0
    lws_snprintf(errbuf, elen, "connect SYSCALL %d", en);
541
0
    return LWS_SSL_CAPABLE_ERROR;
542
0
  }
543
544
0
  if (m == SSL_ERROR_SSL) {
545
0
    l = ERR_get_error();
546
0
    n = lws_snprintf(errbuf, elen, "tls: %s", wsi->tls.err_helper);
547
0
    if (!wsi->tls.err_helper[0])
548
0
      ERR_error_string_n((unsigned int)l, errbuf + n, (elen - (unsigned int)n));
549
0
    return LWS_SSL_CAPABLE_ERROR;
550
0
  }
551
552
0
#if defined(LWS_WITH_TLS_SESSIONS)
553
0
  if (SSL_session_reused(wsi->tls.ssl)) {
554
0
#if defined(LWS_HAVE_SSL_SESSION_set_time)
555
0
    sess = SSL_get_session(wsi->tls.ssl);
556
0
    if (sess) /* should always be true */
557
#if defined(OPENSSL_IS_BORINGSSL)
558
      SSL_SESSION_set_time(sess, (uint64_t)time(NULL)); /* extend session lifetime */
559
#else
560
0
      SSL_SESSION_set_time(sess, (long)time(NULL)); /* extend session lifetime */
561
0
#endif
562
0
#endif
563
0
  }
564
0
#endif
565
566
0
  if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl))
567
0
    return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
568
569
0
  if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl))
570
0
    return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
571
572
0
  if (n == 1 || m == SSL_ERROR_SYSCALL) {
573
0
#if defined(LWS_HAVE_SSL_set_alpn_protos) && \
574
0
    defined(LWS_HAVE_SSL_get0_alpn_selected)
575
0
    SSL_get0_alpn_selected(wsi->tls.ssl, &prot, &len);
576
577
0
    if (len >= sizeof(a))
578
0
      len = sizeof(a) - 1;
579
0
    memcpy(a, (const char *)prot, len);
580
0
    a[len] = '\0';
581
582
0
    lws_role_call_alpn_negotiated(wsi, (const char *)a);
583
0
#endif
584
#if defined(LWS_TLS_SYNTHESIZE_CB)
585
    lws_sul_schedule(wsi->a.context, wsi->tsi,
586
         &wsi->tls.sul_cb_synth,
587
         lws_sess_cache_synth_cb, 500 * LWS_US_PER_MS);
588
#endif
589
590
0
    lwsl_info("client connect OK\n");
591
0
    lws_openssl_describe_cipher(wsi);
592
0
    return LWS_SSL_CAPABLE_DONE;
593
0
  }
594
595
0
  if (!n) /* we don't know what he wants, but he says to retry */
596
0
    return LWS_SSL_CAPABLE_MORE_SERVICE;
597
598
0
  lws_snprintf(errbuf, elen, "connect unk %d", m);
599
600
0
  return LWS_SSL_CAPABLE_ERROR;
601
0
}
602
603
int
604
lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, size_t ebuf_len)
605
0
{
606
0
#if !defined(USE_WOLFSSL)
607
0
  struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
608
0
  char *p = (char *)&pt->serv_buf[0];
609
0
  const char *es, *type = "";
610
0
  unsigned int avoid = 0;
611
0
  char *sb = p;
612
0
  long n;
613
614
0
  errno = 0;
615
0
  ERR_clear_error();
616
0
  n = SSL_get_verify_result(wsi->tls.ssl);
617
618
0
  switch (n) {
619
0
  case X509_V_OK:
620
0
    return 0;
621
622
0
  case X509_V_ERR_HOSTNAME_MISMATCH:
623
0
    type = "tls=hostname";
624
0
    avoid = LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;
625
0
    break;
626
627
0
  case X509_V_ERR_INVALID_CA:
628
0
  case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
629
0
  case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
630
0
    type = "tls=invalidca";
631
0
    avoid = LCCSCF_ALLOW_SELFSIGNED;
632
0
    break;
633
634
0
  case X509_V_ERR_CERT_NOT_YET_VALID:
635
0
    type = "tls=notyetvalid";
636
0
    avoid = LCCSCF_ALLOW_EXPIRED;
637
0
    break;
638
639
0
  case X509_V_ERR_CERT_HAS_EXPIRED:
640
0
    type = "tls=expired";
641
0
    avoid = LCCSCF_ALLOW_EXPIRED;
642
0
    break;
643
0
  }
644
645
0
  lwsl_info("%s: cert problem: %s\n", __func__, type);
646
647
#if defined(LWS_WITH_SYS_METRICS)
648
  lws_metrics_hist_bump_describe_wsi(wsi,
649
      lws_metrics_priv_to_pub(wsi->a.context->mth_conn_failures), type);
650
#endif
651
652
0
  if (wsi->tls.use_ssl & avoid) {
653
0
    lwsl_info("%s: allowing anyway\n", __func__);
654
655
0
    return 0;
656
0
  }
657
658
0
  es = ERR_error_string(
659
  #if defined(LWS_WITH_BORINGSSL)
660
           (uint32_t)
661
  #else
662
0
           (unsigned long)
663
0
  #endif
664
0
           n, sb);
665
0
  lws_snprintf(ebuf, ebuf_len,
666
0
    "server's cert didn't look good, %s X509_V_ERR = %ld: %s\n",
667
0
     type, n, es);
668
0
  lwsl_info("%s\n", ebuf);
669
0
  lws_tls_err_describe_clear();
670
671
0
  return -1;
672
673
#else /* USE_WOLFSSL */
674
  return 0;
675
#endif
676
0
}
677
678
int
679
lws_tls_client_vhost_extra_cert_mem(struct lws_vhost *vh,
680
                const uint8_t *der, size_t der_len)
681
0
{
682
0
  X509_STORE *st;
683
#if defined(USE_WOLFSSL)
684
  X509 *x  = d2i_X509(NULL, &der, (int)der_len);
685
#else
686
0
  X509 *x  = d2i_X509(NULL, &der, (long)der_len);
687
0
#endif
688
0
  int n;
689
690
0
  if (!x) {
691
0
    lwsl_err("%s: Failed to load DER\n", __func__);
692
0
    lws_tls_err_describe_clear();
693
0
    return 1;
694
0
  }
695
696
0
  st = SSL_CTX_get_cert_store(vh->tls.ssl_client_ctx);
697
0
  if (!st) {
698
0
    lwsl_err("%s: failed to get cert store\n", __func__);
699
0
    X509_free(x);
700
0
    return 1;
701
0
  }
702
703
0
  n = X509_STORE_add_cert(st, x);
704
0
  if (n != 1)
705
0
    lwsl_err("%s: failed to add cert\n", __func__);
706
707
0
  X509_free(x);
708
709
0
  return n != 1;
710
0
}
711
712
#if defined(LWS_HAVE_SSL_CTX_set_keylog_callback) && \
713
  defined(LWS_WITH_TLS) && defined(LWS_WITH_CLIENT)
714
void
715
lws_klog_dump(const SSL *ssl, const char *line)
716
0
{
717
0
  struct lws *wsi = SSL_get_ex_data(ssl,
718
0
            openssl_websocket_private_data_index);
719
0
  char path[128], hdr[128], ts[64];
720
0
  size_t w = 0, wx = 0;
721
0
  int fd, t;
722
723
0
  if (!wsi || !wsi->a.context->keylog_file[0] || !wsi->a.vhost)
724
0
    return;
725
726
0
  lws_snprintf(path, sizeof(path), "%s.%s", wsi->a.context->keylog_file,
727
0
      wsi->a.vhost->name);
728
729
0
  fd = open(path, O_CREAT | O_RDWR | O_APPEND, 0600);
730
0
  if (fd == -1) {
731
0
    lwsl_vhost_warn(wsi->a.vhost, "Failed to append %s", path);
732
0
    return;
733
0
  }
734
735
  /* the first item in the chunk */
736
0
  if (!strncmp(line, "SERVER_HANDSHAKE_TRAFFIC_SECRET", 31)) {
737
0
    w += (size_t)write(fd, "\n# ", 3);
738
0
    wx += 3;
739
0
    t = lwsl_timestamp(LLL_WARN, ts, sizeof(ts));
740
0
    wx += (size_t)t;
741
0
    w += (size_t)write(fd, ts, (size_t)t);
742
743
0
    t = lws_snprintf(hdr, sizeof(hdr), "%s\n", wsi->lc.gutag);
744
0
    w += (size_t)write(fd, hdr, (size_t)t);
745
0
    wx += (size_t)t;
746
747
0
    lwsl_vhost_warn(wsi->a.vhost, "appended ssl keylog: %s", path);
748
0
  }
749
750
0
  wx += strlen(line) + 1;
751
0
  w += (size_t)write(fd, line, 
752
#if defined(WIN32)
753
      (unsigned int)
754
#endif
755
0
      strlen(line));
756
0
  w += (size_t)write(fd, "\n", 1);
757
0
  close(fd);
758
759
0
  if (w != wx) {
760
0
    lwsl_vhost_warn(wsi->a.vhost, "Failed to write %s", path);
761
0
    return;
762
0
  }
763
0
}
764
#endif
765
766
int
767
lws_tls_client_create_vhost_context(struct lws_vhost *vh,
768
            const struct lws_context_creation_info *info,
769
            const char *cipher_list,
770
            const char *ca_filepath,
771
            const void *ca_mem,
772
            unsigned int ca_mem_len,
773
            const char *cert_filepath,
774
            const void *cert_mem,
775
            unsigned int cert_mem_len,
776
            const char *private_key_filepath,
777
          const void *key_mem,
778
            unsigned int key_mem_len
779
          )
780
0
{
781
0
  struct lws_tls_client_reuse *tcr;
782
0
  X509_STORE *x509_store;
783
0
  unsigned long error;
784
0
  SSL_METHOD *method;
785
0
  EVP_MD_CTX *mdctx;
786
0
  unsigned int len;
787
0
  uint8_t hash[32];
788
0
  X509 *client_CA;
789
0
  char c;
790
0
  int n;
791
792
  /* basic openssl init already happened in context init */
793
794
  /* choose the most recent spin of the api */
795
0
#if defined(LWS_HAVE_TLS_CLIENT_METHOD)
796
0
  method = (SSL_METHOD *)TLS_client_method();
797
#elif defined(LWS_HAVE_TLSV1_2_CLIENT_METHOD)
798
  method = (SSL_METHOD *)TLSv1_2_client_method();
799
#else
800
  method = (SSL_METHOD *)SSLv23_client_method();
801
#endif
802
803
0
  if (!method) {
804
0
    const char *es;
805
806
0
    error = ERR_get_error();
807
0
    es = ERR_error_string(
808
    #if defined(LWS_WITH_BORINGSSL)
809
      (uint32_t)
810
    #else
811
0
      (unsigned long)
812
0
    #endif
813
0
       error, (char *)vh->context->pt[0].serv_buf);
814
0
    lwsl_err("problem creating ssl method %lu: %s\n",
815
0
      error, es);
816
0
    return 1;
817
0
  }
818
819
  /*
820
   * OpenSSL client contexts are quite expensive, because they bring in
821
   * the system certificate bundle for each one.  So if you have multiple
822
   * vhosts, each with a client context, it can add up to several
823
   * megabytes of heap.  In the case the client contexts are configured
824
   * identically, they could perfectly well have shared just the one.
825
   *
826
   * For that reason, use a hash to fingerprint the context configuration
827
   * and prefer to reuse an existing one with the same fingerprint if
828
   * possible.
829
   */
830
831
0
   mdctx = EVP_MD_CTX_create();
832
0
   if (!mdctx)
833
0
     return 1;
834
835
0
  if (EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL) != 1) {
836
0
    EVP_MD_CTX_destroy(mdctx);
837
838
0
    return 1;
839
0
  }
840
841
0
  if (info->ssl_client_options_set)
842
0
    EVP_DigestUpdate(mdctx, &info->ssl_client_options_set,
843
0
         sizeof(info->ssl_client_options_set));
844
845
0
#if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL)
846
0
  if (info->ssl_client_options_clear)
847
0
    EVP_DigestUpdate(mdctx, &info->ssl_client_options_clear,
848
0
         sizeof(info->ssl_client_options_clear));
849
0
#endif
850
851
0
  if (cipher_list)
852
0
    EVP_DigestUpdate(mdctx, cipher_list, strlen(cipher_list));
853
854
#if defined(LWS_HAVE_SSL_CTX_set_ciphersuites)
855
  if (info->client_tls_1_3_plus_cipher_list)
856
    EVP_DigestUpdate(mdctx, info->client_tls_1_3_plus_cipher_list,
857
         strlen(info->client_tls_1_3_plus_cipher_list));
858
#endif
859
860
0
  if (!lws_check_opt(vh->options, LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS)) {
861
0
    c = 1;
862
0
    EVP_DigestUpdate(mdctx, &c, 1);
863
0
  }
864
865
0
  if (ca_filepath)
866
0
    EVP_DigestUpdate(mdctx, ca_filepath, strlen(ca_filepath));
867
868
0
  if (cert_filepath)
869
0
    EVP_DigestUpdate(mdctx, cert_filepath, strlen(cert_filepath));
870
871
0
  if (private_key_filepath)
872
0
    EVP_DigestUpdate(mdctx, private_key_filepath,
873
0
         strlen(private_key_filepath));
874
0
  if (ca_mem && ca_mem_len)
875
0
    EVP_DigestUpdate(mdctx, ca_mem, ca_mem_len);
876
877
0
  if (cert_mem && cert_mem_len)
878
0
    EVP_DigestUpdate(mdctx, cert_mem, cert_mem_len);
879
880
0
  len = sizeof(hash);
881
0
  EVP_DigestFinal_ex(mdctx, hash, &len);
882
0
  EVP_MD_CTX_destroy(mdctx);
883
884
  /* look for existing client context with same config already */
885
886
0
  lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp,
887
0
       lws_dll2_get_head(&vh->context->tls.cc_owner)) {
888
0
    tcr = lws_container_of(p, struct lws_tls_client_reuse, cc_list);
889
890
0
    if (!memcmp(hash, tcr->hash, len)) {
891
892
      /* it's a match */
893
894
0
      tcr->refcount++;
895
0
      vh->tls.ssl_client_ctx = tcr->ssl_client_ctx;
896
0
      vh->tls.tcr = tcr;
897
898
0
      lwsl_info("%s: vh %s: reusing client ctx %d: use %d\n",
899
0
           __func__, vh->name, tcr->index,
900
0
           tcr->refcount);
901
902
0
      return 0;
903
0
    }
904
0
  } lws_end_foreach_dll_safe(p, tp);
905
906
  /* no existing one the same... create new client SSL_CTX */
907
908
0
  errno = 0;
909
0
  ERR_clear_error();
910
0
  vh->tls.ssl_client_ctx = SSL_CTX_new(method);
911
0
  if (!vh->tls.ssl_client_ctx) {
912
0
    const char *es;
913
914
0
    error = ERR_get_error();
915
0
    es = ERR_error_string(
916
    #if defined(LWS_WITH_BORINGSSL)
917
      (uint32_t)
918
    #else
919
0
      (unsigned long)
920
0
    #endif
921
0
       error, (char *)vh->context->pt[0].serv_buf);
922
0
    lwsl_err("problem creating ssl context %lu: %s\n",
923
0
      error, es);
924
0
    return 1;
925
0
  }
926
927
0
  SSL_CTX_set_ex_data(vh->tls.ssl_client_ctx,
928
0
        openssl_SSL_CTX_private_data_index,
929
0
        (char *)vh->context);
930
931
0
  lws_plat_vhost_tls_client_ctx_init(vh);
932
933
0
  tcr = lws_zalloc(sizeof(*tcr), "client ctx tcr");
934
0
  if (!tcr) {
935
0
    SSL_CTX_free(vh->tls.ssl_client_ctx);
936
0
    return 1;
937
0
  }
938
939
0
  tcr->ssl_client_ctx = vh->tls.ssl_client_ctx;
940
0
  tcr->refcount = 1;
941
0
  memcpy(tcr->hash, hash, len);
942
0
  tcr->index = vh->context->tls.count_client_contexts++;
943
0
  lws_dll2_add_head(&tcr->cc_list, &vh->context->tls.cc_owner);
944
945
0
  lwsl_info("%s: vh %s: created new client ctx %d\n", __func__,
946
0
      vh->name, tcr->index);
947
948
  /* bind the tcr to the client context */
949
950
0
  vh->tls.tcr = tcr;
951
952
0
#if defined(LWS_HAVE_SSL_CTX_set_keylog_callback) && \
953
0
    defined(LWS_WITH_TLS) && defined(LWS_WITH_CLIENT)
954
0
  if (vh->context->keylog_file[0])
955
0
    SSL_CTX_set_keylog_callback(vh->tls.ssl_client_ctx, lws_klog_dump);
956
0
#endif
957
958
0
#if defined(LWS_WITH_TLS_SESSIONS)
959
0
  vh->tls_session_cache_max = info->tls_session_cache_max ?
960
0
            info->tls_session_cache_max : 10;
961
0
  lws_tls_session_cache(vh, info->tls_session_timeout);
962
0
#endif
963
964
0
#ifdef SSL_OP_NO_COMPRESSION
965
0
  SSL_CTX_set_options(vh->tls.ssl_client_ctx, SSL_OP_NO_COMPRESSION);
966
0
#endif
967
968
0
  SSL_CTX_set_options(vh->tls.ssl_client_ctx,
969
0
          SSL_OP_CIPHER_SERVER_PREFERENCE);
970
971
0
  SSL_CTX_set_mode(vh->tls.ssl_client_ctx,
972
0
       SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
973
0
       SSL_MODE_RELEASE_BUFFERS);
974
975
0
#if !defined(USE_WOLFSSL)
976
#if defined(LWS_WITH_BORINGSSL)
977
        uint32_t
978
#else
979
0
#if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && \
980
0
  !defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */
981
0
    unsigned long
982
#else
983
    long
984
#endif
985
0
#endif
986
#else
987
    long
988
#endif
989
0
      ssl_client_options_set_value =
990
0
#if !defined(USE_WOLFSSL)
991
#if defined(LWS_WITH_BORINGSSL)
992
        (uint32_t)
993
#else
994
0
#if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && \
995
0
  !defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */
996
0
        (unsigned long)
997
#else
998
        (long)
999
#endif
1000
0
#endif
1001
0
#endif
1002
0
      info->ssl_client_options_set;
1003
1004
0
  if (info->ssl_client_options_set)
1005
0
    SSL_CTX_set_options(vh->tls.ssl_client_ctx, ssl_client_options_set_value);
1006
1007
0
#if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL)
1008
1009
  /* SSL_clear_options introduced in 0.9.8m */
1010
#if defined(LWS_WITH_BORINGSSL)
1011
                uint32_t
1012
#else
1013
0
#if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && \
1014
0
  !defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */
1015
0
    unsigned long
1016
#else
1017
    long
1018
#endif
1019
0
#endif
1020
1021
0
      ssl_client_options_clear_value =
1022
#if defined(LWS_WITH_BORINGSSL)
1023
        (uint32_t)
1024
#else
1025
0
#if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && \
1026
0
  !defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */
1027
0
        (unsigned long)
1028
#else
1029
        (long)
1030
#endif
1031
0
#endif
1032
0
      info->ssl_client_options_clear;
1033
1034
0
  if (info->ssl_client_options_clear)
1035
0
    SSL_CTX_clear_options(vh->tls.ssl_client_ctx, ssl_client_options_clear_value);
1036
0
#endif
1037
1038
0
  if (cipher_list)
1039
0
    SSL_CTX_set_cipher_list(vh->tls.ssl_client_ctx, cipher_list);
1040
1041
#if defined(LWS_HAVE_SSL_CTX_set_ciphersuites)
1042
  if (info->client_tls_1_3_plus_cipher_list)
1043
    SSL_CTX_set_ciphersuites(vh->tls.ssl_client_ctx,
1044
           info->client_tls_1_3_plus_cipher_list);
1045
#endif
1046
1047
0
#ifdef LWS_SSL_CLIENT_USE_OS_CA_CERTS
1048
0
  if (!lws_check_opt(vh->options, LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS))
1049
    /* loads OS default CA certs */
1050
0
    SSL_CTX_set_default_verify_paths(vh->tls.ssl_client_ctx);
1051
0
#endif
1052
1053
  /* openssl init for cert verification (for client sockets) */
1054
0
  if (!ca_filepath && (!ca_mem || !ca_mem_len)) {
1055
#if defined(LWS_HAVE_SSL_CTX_load_verify_dir)
1056
    if (!SSL_CTX_load_verify_dir(
1057
      vh->tls.ssl_client_ctx, LWS_OPENSSL_CLIENT_CERTS))
1058
#else
1059
0
    if (!SSL_CTX_load_verify_locations(
1060
0
      vh->tls.ssl_client_ctx, NULL, LWS_OPENSSL_CLIENT_CERTS))
1061
0
#endif
1062
0
      lwsl_err("Unable to load SSL Client certs from %s "
1063
0
          "(set by LWS_OPENSSL_CLIENT_CERTS) -- "
1064
0
          "client ssl isn't going to work\n",
1065
0
          LWS_OPENSSL_CLIENT_CERTS);
1066
0
  } else if (ca_filepath) {
1067
#if defined(LWS_HAVE_SSL_CTX_load_verify_file)
1068
    if (!SSL_CTX_load_verify_file(
1069
      vh->tls.ssl_client_ctx, ca_filepath)) {
1070
#else
1071
0
    if (!SSL_CTX_load_verify_locations(
1072
0
      vh->tls.ssl_client_ctx, ca_filepath, NULL)) {
1073
0
#endif
1074
0
      lwsl_err(
1075
0
        "Unable to load SSL Client certs "
1076
0
        "file from %s -- client ssl isn't "
1077
0
        "going to work\n", ca_filepath);
1078
0
      lws_tls_err_describe_clear();
1079
0
    }
1080
0
    else
1081
0
      lwsl_info("loaded ssl_ca_filepath\n");
1082
0
  } else {
1083
1084
0
    lws_filepos_t amount = 0;
1085
0
    const uint8_t *up;
1086
0
    uint8_t *up1;
1087
1088
0
    if (lws_tls_alloc_pem_to_der_file(vh->context, NULL, ca_mem,
1089
0
              ca_mem_len, &up1, &amount)) {
1090
0
      lwsl_err("%s: Unable to decode x.509 mem\n", __func__);
1091
0
      lwsl_hexdump_notice(ca_mem, ca_mem_len);
1092
0
      return 1;
1093
0
    }
1094
1095
0
    up = up1;
1096
#if defined(USE_WOLFSSL)
1097
    client_CA = d2i_X509(NULL, &up, (int)amount);
1098
#else
1099
0
    client_CA = d2i_X509(NULL, &up, (long)amount);
1100
0
#endif
1101
0
    if (!client_CA) {
1102
0
      lwsl_err("%s: d2i_X509 failed\n", __func__);
1103
0
      lwsl_hexdump_notice(up1, (size_t)amount);
1104
0
      lws_tls_err_describe_clear();
1105
0
    } else {
1106
0
      x509_store = X509_STORE_new();
1107
0
      if (!X509_STORE_add_cert(x509_store, client_CA)) {
1108
0
        X509_STORE_free(x509_store);
1109
0
        lwsl_err("Unable to load SSL Client certs from "
1110
0
           "ssl_ca_mem -- client ssl isn't going to "
1111
0
           "work\n");
1112
0
        lws_tls_err_describe_clear();
1113
0
      } else {
1114
        /* it doesn't increment x509_store ref counter */
1115
0
        SSL_CTX_set_cert_store(vh->tls.ssl_client_ctx,
1116
0
                   x509_store);
1117
0
        lwsl_info("loaded ssl_ca_mem\n");
1118
0
      }
1119
0
    }
1120
0
    if (client_CA)
1121
0
      X509_free(client_CA);
1122
0
    lws_free(up1);
1123
  //  lws_tls_client_vhost_extra_cert_mem(vh, ca_mem, ca_mem_len);
1124
0
  }
1125
1126
  /*
1127
   * callback allowing user code to load extra verification certs
1128
   * helping the client to verify server identity
1129
   */
1130
1131
  /* support for client-side certificate authentication */
1132
1133
0
  if (cert_filepath) {
1134
0
    if (lws_tls_use_any_upgrade_check_extant(cert_filepath) !=
1135
0
        LWS_TLS_EXTANT_YES &&
1136
0
        (info->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT))
1137
0
      return 0;
1138
1139
0
    lwsl_notice("%s: doing cert filepath %s\n", __func__,
1140
0
        cert_filepath);
1141
0
    n = SSL_CTX_use_certificate_chain_file(vh->tls.ssl_client_ctx,
1142
0
                   cert_filepath);
1143
0
    if (n < 1) {
1144
0
      lwsl_err("problem %d getting cert '%s'\n", n,
1145
0
         cert_filepath);
1146
0
      lws_tls_err_describe_clear();
1147
0
      return 1;
1148
0
    }
1149
0
    lwsl_info("Loaded client cert %s\n", cert_filepath);
1150
1151
0
  } else if (cert_mem && cert_mem_len) {
1152
0
    lws_filepos_t flen;
1153
0
    uint8_t *p;
1154
1155
0
    if (lws_tls_alloc_pem_to_der_file(vh->context, NULL, cert_mem,
1156
0
              cert_mem_len, &p, &flen)) {
1157
0
      lwsl_err("%s: couldn't read cert file\n", __func__);
1158
1159
0
      return 1;
1160
0
    }
1161
1162
0
    n = SSL_CTX_use_certificate_ASN1(vh->tls.ssl_client_ctx,
1163
#if defined(LWS_WITH_BORINGSSL)
1164
        (size_t)
1165
#else
1166
0
        (int)
1167
0
#endif
1168
0
        flen, p);
1169
1170
0
    if (n < 1) {
1171
0
      lwsl_err("%s: problem interpreting client cert\n",  __func__);
1172
0
      lws_tls_err_describe_clear();
1173
0
    }
1174
1175
0
    lws_free_set_NULL(p);
1176
1177
0
    if (n != 1)
1178
0
      return 1;
1179
1180
0
  }
1181
0
  if (private_key_filepath) {
1182
0
    lwsl_info("%s: using private key filepath\n", __func__);
1183
0
    lws_ssl_bind_passphrase(vh->tls.ssl_client_ctx, 1, info);
1184
    /* set the private key from KeyFile */
1185
0
    if (SSL_CTX_use_PrivateKey_file(vh->tls.ssl_client_ctx,
1186
0
        private_key_filepath, SSL_FILETYPE_PEM) != 1) {
1187
0
      lwsl_err("use_PrivateKey_file '%s'\n",
1188
0
         private_key_filepath);
1189
0
      lws_tls_err_describe_clear();
1190
0
      return 1;
1191
0
    }
1192
0
    lwsl_info("Loaded client cert private key %s\n",
1193
0
          private_key_filepath);
1194
1195
    /* verify private key */
1196
0
    if (!SSL_CTX_check_private_key(vh->tls.ssl_client_ctx)) {
1197
0
      lwsl_err("Private SSL key doesn't match cert\n");
1198
0
      return 1;
1199
0
    }
1200
0
  }
1201
0
  else if (key_mem && key_mem_len) {
1202
1203
0
    lws_filepos_t flen;
1204
0
    uint8_t *p;
1205
1206
0
    if (lws_tls_alloc_pem_to_der_file(vh->context, NULL, key_mem,
1207
0
              key_mem_len, &p, &flen)) {
1208
0
      lwsl_err("%s: couldn't use mem cert\n", __func__);
1209
1210
0
      return 1;
1211
0
    }
1212
1213
0
    n = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA, vh->tls.ssl_client_ctx, p,
1214
#if defined(LWS_WITH_BORINGSSL)
1215
        (size_t)
1216
#else
1217
0
        (long)(lws_intptr_t)
1218
0
#endif
1219
0
            flen);
1220
0
    if (n != 1)
1221
0
      n = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_EC,
1222
0
              vh->tls.ssl_client_ctx, p,
1223
#if defined(LWS_WITH_BORINGSSL)
1224
        (size_t)
1225
#else
1226
0
        (long)(lws_intptr_t)
1227
0
#endif
1228
0
            flen);
1229
1230
0
    lws_free_set_NULL(p);
1231
1232
0
    if (n != 1)  {
1233
0
      lwsl_err("%s: unable to use key_mem\n", __func__);
1234
1235
0
      return 1;
1236
0
    }
1237
0
  }
1238
1239
0
  return 0;
1240
0
}
1241
1242