Coverage Report

Created: 2026-09-14 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwebsockets/lib/tls/openssl/openssl-client.c
Line
Count
Source
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
0
  const struct lws_protocols *lp;
96
97
  /* keep old behaviour accepting self-signed server certs */
98
0
  if (!preverify_ok) {
99
0
    err = X509_STORE_CTX_get_error(x509_ctx);
100
101
0
    if (err != X509_V_OK) {
102
0
      ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
103
0
          SSL_get_ex_data_X509_STORE_CTX_idx());
104
0
      wsi = SSL_get_ex_data(ssl,
105
0
          openssl_websocket_private_data_index);
106
0
      if (!wsi) {
107
0
        lwsl_err("%s: can't get wsi from ssl privdata\n",
108
0
           __func__);
109
110
0
        return 0;
111
0
      }
112
113
0
      if ((err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
114
0
           err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) &&
115
0
           wsi->tls.use_ssl & LCCSCF_ALLOW_SELFSIGNED) {
116
0
        lwsl_notice("accepting self-signed "
117
0
              "certificate (verify_callback)\n");
118
0
        X509_STORE_CTX_set_error(x509_ctx, X509_V_OK);
119
0
        return 1; // ok
120
0
    } else if ((err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY ||
121
0
          err == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE) &&
122
0
          wsi->tls.use_ssl & LCCSCF_ALLOW_INSECURE) {
123
0
        lwsl_notice("accepting non-trusted certificate\n");
124
0
        X509_STORE_CTX_set_error(x509_ctx, X509_V_OK);
125
0
        return 1;  /* ok */
126
0
      } else if ((err == X509_V_ERR_CERT_NOT_YET_VALID ||
127
0
            err == X509_V_ERR_CERT_HAS_EXPIRED) &&
128
0
            wsi->tls.use_ssl & LCCSCF_ALLOW_EXPIRED) {
129
0
        if (err == X509_V_ERR_CERT_NOT_YET_VALID)
130
0
          lwsl_notice("accepting not yet valid "
131
0
                "certificate (verify_"
132
0
                "callback)\n");
133
0
        else if (err == X509_V_ERR_CERT_HAS_EXPIRED)
134
0
          lwsl_notice("accepting expired "
135
0
                "certificate (verify_"
136
0
                "callback)\n");
137
0
        X509_STORE_CTX_set_error(x509_ctx, X509_V_OK);
138
0
        return 1; // ok
139
0
      }
140
0
    }
141
0
  }
142
143
0
  ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
144
0
           SSL_get_ex_data_X509_STORE_CTX_idx());
145
0
  wsi = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
146
0
  if (!wsi) {
147
0
    lwsl_err("%s: can't get wsi from ssl privdata\n",  __func__);
148
149
0
    return 0;
150
0
  }
151
152
#if defined(LWS_WITH_TLS_JIT_TRUST)
153
  if (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) {
154
    union lws_tls_cert_info_results ci;
155
    STACK_OF(X509) *x509_stack;
156
157
    x509_stack = X509_STORE_CTX_get1_chain(x509_ctx);
158
    if (x509_stack) {
159
160
      for (n = 0; n < OPENSSL_sk_num((const OPENSSL_STACK *)x509_stack) &&
161
            wsi->tls.kid_chain.count !=
162
             LWS_ARRAY_SIZE(wsi->tls.kid_chain.akid); n++) {
163
        X509 *x509 = OPENSSL_sk_value((const OPENSSL_STACK *)x509_stack, n);
164
165
        /* the len is the buffer size, 0 meant "never fits" */
166
        if (!lws_tls_openssl_cert_info(x509,
167
              LWS_TLS_CERT_INFO_SUBJECT_KEY_ID,
168
              &ci, sizeof(ci.ns.name)))
169
          lws_tls_kid_copy(&ci,
170
            &wsi->tls.kid_chain.skid[
171
                 wsi->tls.kid_chain.count]);
172
173
        if (!lws_tls_openssl_cert_info(x509,
174
               LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID,
175
               &ci, sizeof(ci.ns.name)))
176
          lws_tls_kid_copy(&ci,
177
             &wsi->tls.kid_chain.akid[
178
                 wsi->tls.kid_chain.count]);
179
180
        wsi->tls.kid_chain.count++;
181
      }
182
183
      sk_X509_pop_free(x509_stack, X509_free);
184
    }
185
186
    lws_tls_jit_trust_sort_kids(wsi, &wsi->tls.kid_chain);
187
  }
188
#endif
189
0
  lp = &(lws_get_context_protocol(wsi->a.context, 0));
190
0
  if (wsi->a.protocol)
191
0
    lp = wsi->a.protocol;
192
193
0
  n = lp->callback(wsi,
194
0
      LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION,
195
0
      x509_ctx, ssl, (unsigned int)preverify_ok);
196
197
  /* keep old behaviour if something wrong with server certs */
198
  /* if ssl error is overruled in callback and cert is ok,
199
   * X509_STORE_CTX_set_error(x509_ctx, X509_V_OK); must be set and
200
   * return value is 0 from callback */
201
0
  if (!preverify_ok) {
202
0
    int err = X509_STORE_CTX_get_error(x509_ctx);
203
204
0
    if (err != X509_V_OK) {
205
      /* cert validation error was not handled in callback */
206
0
      int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
207
0
      const char *msg = X509_verify_cert_error_string(err);
208
209
0
      lws_strncpy(wsi->tls.err_helper, msg,
210
0
            sizeof(wsi->tls.err_helper));
211
212
0
      lwsl_err("SSL error: %s (preverify_ok=%d;err=%d;"
213
0
         "depth=%d)\n", msg, preverify_ok, err, depth);
214
215
0
      if (err == X509_V_ERR_HOSTNAME_MISMATCH) {
216
0
        const char *expected = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
217
0
        char cert_cn[256] = "unknown";
218
0
        X509 *cert = X509_STORE_CTX_get_current_cert(x509_ctx);
219
0
        if (cert) {
220
0
          const X509_NAME *subject = X509_get_subject_name(cert);
221
0
          if (subject)
222
0
            X509_NAME_get_text_by_NID(subject, NID_commonName, cert_cn, sizeof(cert_cn));
223
0
        }
224
0
        lwsl_err("Hostname mismatch details: Expected='%s', Cert CN='%s'\n",
225
0
          expected ? expected : "unknown", cert_cn);
226
0
      }
227
228
#if defined(LWS_WITH_SYS_METRICS)
229
      {
230
        char buckname[64];
231
232
        lws_snprintf(buckname, sizeof(buckname),
233
               "tls=\"%s\"", msg);
234
        lws_metrics_hist_bump_describe_wsi(wsi,
235
          lws_metrics_priv_to_pub(wsi->a.context->mth_conn_failures),
236
          buckname);
237
      }
238
#endif
239
240
0
      return preverify_ok;  // not ok
241
0
    }
242
0
  }
243
  /*
244
   * convert callback return code from 0 = OK to verify callback
245
   * return value 1 = OK
246
   */
247
0
  return !n;
248
0
}
249
#endif
250
251
int
252
lws_ssl_client_bio_create(struct lws *wsi)
253
0
{
254
0
  char hostname[128];
255
0
#if (defined(LWS_HAVE_SSL_set_alpn_protos) || defined(OPENSSL_IS_AWSLC)) && \
256
0
    (defined(LWS_HAVE_SSL_get0_alpn_selected) || defined(OPENSSL_IS_AWSLC))
257
0
  uint8_t openssl_alpn[40];
258
0
  const char *alpn_comma = wsi->a.context->tls.alpn_default;
259
0
  int n;
260
0
#endif
261
262
0
  if (wsi->stash) {
263
0
    lws_strncpy(hostname, wsi->stash->cis[CIS_HOST], sizeof(hostname));
264
0
#if (defined(LWS_HAVE_SSL_set_alpn_protos) || defined(OPENSSL_IS_AWSLC)) && \
265
0
    (defined(LWS_HAVE_SSL_get0_alpn_selected) || defined(OPENSSL_IS_AWSLC))
266
0
    alpn_comma = wsi->stash->cis[CIS_ALPN];
267
0
#endif
268
0
  } else {
269
0
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
270
0
    if (lws_hdr_copy(wsi, hostname, sizeof(hostname),
271
0
         _WSI_TOKEN_CLIENT_HOST) <= 0)
272
0
#endif
273
0
    {
274
0
      lwsl_err("%s: Unable to get hostname\n", __func__);
275
276
0
      return -1;
277
0
    }
278
0
  }
279
280
  /*
281
   * remove any :port part on the hostname... necessary for network
282
   * connection but typical certificates do not contain it
283
   */
284
0
  if (lws_tls_client_strip_port(hostname) &&
285
0
      !(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) {
286
    /*
287
     * There is no name left to check the peer cert against, and we
288
     * were not told to skip that check.  Fail closed: continuing
289
     * would ask openssl to verify the chain and nothing else
290
     */
291
0
    lwsl_err("%s: no usable hostname for peer cert check\n",
292
0
       __func__);
293
294
0
    return -1;
295
0
  }
296
297
0
  wsi->tls.ssl = SSL_new(wsi->a.vhost->tls.ssl_client_ctx);
298
0
  if (!wsi->tls.ssl) {
299
0
    unsigned long err = ERR_get_error();
300
0
    const char *es = ERR_error_string(LWS_TLS_ERR_CAST(err), NULL);
301
0
    lwsl_err("SSL_new failed: %s (real error %lu)\n", es, err);
302
0
    lws_tls_err_describe_clear();
303
0
    return -1;
304
0
  }
305
306
0
#if defined(LWS_WITH_TLS_SESSIONS)
307
0
  if (!(wsi->a.vhost->options & LWS_SERVER_OPTION_DISABLE_TLS_SESSION_CACHE))
308
0
    lws_tls_reuse_session(wsi);
309
0
#endif
310
311
0
#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
312
0
  if (wsi->a.vhost->tls.ssl_info_event_mask)
313
0
    SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback);
314
0
#endif
315
316
0
#if defined(LWS_HAVE_X509_VERIFY_PARAM_set1_host)
317
0
  if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) {
318
0
#if !defined(USE_WOLFSSL)
319
320
0
    X509_VERIFY_PARAM *param = SSL_get0_param(wsi->tls.ssl);
321
322
    /* Enable automatic hostname checks */
323
0
    X509_VERIFY_PARAM_set_hostflags(param,
324
0
          X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
325
    /*
326
     * Handle the case where the hostname is an IP address.
327
     *
328
     * This is the only peer name check there is... nothing
329
     * downstream re-checks it, lws_tls_client_confirm_peer_cert()
330
     * only reads SSL_get_verify_result().  So if setting the name
331
     * we want checked did not work, we must not continue: with no
332
     * name in the verify param, openssl validates the chain alone
333
     * and reports X509_V_OK for a cert naming anything at all
334
     */
335
0
    if (!X509_VERIFY_PARAM_set1_ip_asc(param, hostname) &&
336
0
        !X509_VERIFY_PARAM_set1_host(param, hostname,
337
0
          strnlen(hostname, sizeof(hostname)))) {
338
0
      lwsl_err("%s: unable to bind peer cert check to '%s'\n",
339
0
         __func__, hostname);
340
341
0
      return -1;
342
0
    }
343
0
#endif
344
345
0
  }
346
#else
347
  if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) {
348
    lwsl_err("%s: your tls lib is too old to have "
349
       "X509_VERIFY_PARAM_set1_host, failing all client tls\n",
350
       __func__);
351
    return -1;
352
  }
353
#endif
354
355
0
#if !defined(USE_WOLFSSL)
356
0
#ifndef USE_OLD_CYASSL
357
  /* OpenSSL_client_verify_callback will be called @ SSL_connect() */
358
0
  SSL_set_verify(wsi->tls.ssl, SSL_VERIFY_PEER,
359
0
           OpenSSL_client_verify_callback);
360
0
#endif
361
0
#endif
362
363
0
#if !defined(USE_WOLFSSL)
364
0
  SSL_set_mode(wsi->tls.ssl,  SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
365
0
#endif
366
  /*
367
   * use server name indication (SNI), if supported,
368
   * when establishing connection... but RFC 6066 3 says literal IPv4
369
   * and IPv6 addresses are not permitted in there
370
   */
371
0
  if (!lws_tls_client_host_is_literal(hostname)) {
372
#ifdef USE_WOLFSSL
373
#ifdef USE_OLD_CYASSL
374
#ifdef CYASSL_SNI_HOST_NAME
375
  CyaSSL_UseSNI(wsi->tls.ssl, CYASSL_SNI_HOST_NAME, hostname,
376
          strlen(hostname));
377
#endif
378
#else
379
#if defined(WOLFSSL_SNI_HOST_NAME) || defined(HAVE_SNI)
380
  wolfSSL_UseSNI(wsi->tls.ssl, WOLFSSL_SNI_HOST_NAME, hostname,
381
           (unsigned short)strlen(hostname));
382
#endif
383
#endif
384
#else
385
0
#if defined(SSL_CTRL_SET_TLSEXT_HOSTNAME) || defined(LWS_HAVE_SSL_set_tlsext_host_name)
386
0
  SSL_set_tlsext_host_name(wsi->tls.ssl, hostname);
387
0
#endif
388
0
#endif
389
0
  }
390
391
#ifdef USE_WOLFSSL
392
  /*
393
   * wolfSSL has no X509_VERIFY_PARAM_set1_host(): its equivalent is
394
   * wolfSSL_check_domain_name(), which has to be armed before the
395
   * handshake.  Without it nothing on this backend ever compared the
396
   * peer certificate against the name we asked for, ie, any certificate
397
   * from any trusted CA was accepted for any host... the same hazard
398
   * C-337 fixed on gnutls and C-408 on openssl.
399
   */
400
  if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) {
401
#ifdef USE_OLD_CYASSL
402
    if (CyaSSL_check_domain_name(wsi->tls.ssl, hostname) !=
403
                SSL_SUCCESS)
404
#else
405
    if (wolfSSL_check_domain_name(wsi->tls.ssl, hostname) !=
406
                SSL_SUCCESS)
407
#endif
408
    {
409
      lwsl_err("%s: unable to bind peer cert check to '%s'\n",
410
         __func__, hostname);
411
412
      return -1;
413
    }
414
  }
415
416
  /*
417
   * wolfSSL/CyaSSL does certificate verification differently
418
   * from OpenSSL.
419
   * If we should ignore the certificate, we need to set
420
   * this before SSL_new and SSL_connect is called.
421
   * Otherwise the connect will simply fail with error code -155
422
   */
423
#ifdef USE_OLD_CYASSL
424
  if (wsi->tls.use_ssl & LCCSCF_ALLOW_SELFSIGNED)
425
    CyaSSL_set_verify(wsi->tls.ssl, SSL_VERIFY_NONE, NULL);
426
#else
427
  if (wsi->tls.use_ssl & LCCSCF_ALLOW_SELFSIGNED)
428
    wolfSSL_set_verify(wsi->tls.ssl, SSL_VERIFY_NONE, NULL);
429
#endif
430
#endif /* USE_WOLFSSL */
431
432
0
  wsi->tls.client_bio = BIO_new_socket((int)(lws_intptr_t)wsi->desc.sockfd,
433
0
               BIO_NOCLOSE);
434
0
  SSL_set_bio(wsi->tls.ssl, wsi->tls.client_bio, wsi->tls.client_bio);
435
436
#ifdef USE_WOLFSSL
437
#ifdef USE_OLD_CYASSL
438
  CyaSSL_set_using_nonblock(wsi->tls.ssl, 1);
439
#else
440
  wolfSSL_set_using_nonblock(wsi->tls.ssl, 1);
441
#endif
442
#else
443
0
  BIO_set_nbio(wsi->tls.client_bio, 1); /* nonblocking */
444
0
#endif
445
446
0
#if (defined(LWS_HAVE_SSL_set_alpn_protos) || defined(OPENSSL_IS_AWSLC)) && \
447
0
    (defined(LWS_HAVE_SSL_get0_alpn_selected) || defined(OPENSSL_IS_AWSLC))
448
0
  if (wsi->a.vhost->tls.alpn)
449
0
    alpn_comma = wsi->a.vhost->tls.alpn;
450
0
  if (wsi->role_ops && !strcmp(wsi->role_ops->name, "quic")) {
451
    /*
452
     * QUIC only carries QUIC-mapped ALPNs (h3 family).  The
453
     * stash / vhost lists are the TCP ALPNs (eg, "h2,http/1.1"):
454
     * offering those on QUIC can get "h2" negotiated on top of
455
     * the UDP transport, where the h2 role can never make
456
     * progress.  For the alt-svc QUIC race, connect2 puts the
457
     * h3-only list in wsi->alpn (the TCP fallback restores the
458
     * original from there); native h3 streams also carry their
459
     * ALPN in wsi->alpn.
460
     */
461
0
    alpn_comma = wsi->alpn[0] ? wsi->alpn : "h3";
462
0
  } else
463
0
  if (wsi->stash) {
464
0
    alpn_comma = wsi->stash->cis[CIS_ALPN];
465
0
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
466
0
  } else {
467
0
    if (lws_hdr_copy(wsi, hostname, sizeof(hostname),
468
0
         _WSI_TOKEN_CLIENT_ALPN) > 0)
469
0
      alpn_comma = hostname;
470
0
#endif
471
0
  }
472
473
0
  lwsl_info("%s client conn using alpn list '%s'\n", wsi->role_ops->name, alpn_comma);
474
475
0
  n = lws_alpn_comma_to_openssl(alpn_comma, openssl_alpn,
476
0
              sizeof(openssl_alpn) - 1);
477
478
0
  SSL_set_alpn_protos(wsi->tls.ssl, openssl_alpn, (unsigned int)n);
479
0
#endif
480
481
0
  SSL_set_ex_data(wsi->tls.ssl, openssl_websocket_private_data_index,
482
0
      wsi);
483
484
0
  if (wsi->sys_tls_client_cert) {
485
0
    lws_system_blob_t *b = lws_system_get_blob(wsi->a.context,
486
0
          LWS_SYSBLOB_TYPE_CLIENT_CERT_DER,
487
0
          wsi->sys_tls_client_cert - 1);
488
0
    const uint8_t *data;
489
0
    size_t size;
490
491
0
    if (!b)
492
0
      goto no_client_cert;
493
494
    /*
495
     * Set up the per-connection client cert
496
     */
497
498
0
    size = lws_system_blob_get_size(b);
499
0
    if (!size)
500
0
      goto no_client_cert;
501
502
0
    if (lws_system_blob_get_single_ptr(b, &data))
503
0
      goto no_client_cert;
504
505
0
    if (SSL_use_certificate_ASN1(wsi->tls.ssl, SSL_DATA_CAST(data),
506
0
      SSL_SIZE_T_CAST(size)) != 1) {
507
0
      lwsl_err("%s: use_certificate failed\n", __func__);
508
0
      lws_tls_err_describe_clear();
509
0
      goto no_client_cert;
510
0
    }
511
512
0
    b = lws_system_get_blob(wsi->a.context,
513
0
          LWS_SYSBLOB_TYPE_CLIENT_KEY_DER,
514
0
          wsi->sys_tls_client_cert - 1);
515
0
    if (!b)
516
0
      goto no_client_cert;
517
518
0
    size = lws_system_blob_get_size(b);
519
0
    if (!size)
520
0
      goto no_client_cert;
521
522
0
    if (lws_system_blob_get_single_ptr(b, &data))
523
0
      goto no_client_cert;
524
525
0
    if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, wsi->tls.ssl, SSL_DATA_CAST(data),
526
0
      SSL_SIZE_T_CAST(size)) != 1 &&
527
0
        SSL_use_PrivateKey_ASN1(EVP_PKEY_EC, wsi->tls.ssl, SSL_DATA_CAST(data),
528
0
      SSL_SIZE_T_CAST(size)) != 1) {
529
530
0
      lwsl_err("%s: use_privkey failed\n", __func__);
531
0
      lws_tls_err_describe_clear();
532
0
      goto no_client_cert;
533
0
    }
534
535
0
    if (SSL_check_private_key(wsi->tls.ssl) != 1) {
536
0
      lwsl_err("Private SSL key doesn't match cert\n");
537
0
      lws_tls_err_describe_clear();
538
0
      return 1;
539
0
    }
540
541
0
    lwsl_notice("%s: set system client cert %u\n", __func__,
542
0
        wsi->sys_tls_client_cert - 1);
543
0
  }
544
545
0
  return 0;
546
547
0
no_client_cert:
548
0
  lwsl_err("%s: unable to set up system client cert %d\n", __func__,
549
0
      wsi->sys_tls_client_cert - 1);
550
551
0
  return 1;
552
0
}
553
554
#if defined(LWS_WITH_TCP_TLS)
555
enum lws_ssl_capable_status
556
lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen)
557
0
{
558
0
  int m, n, en;
559
0
  unsigned long l;
560
0
#if defined(LWS_WITH_TLS_SESSIONS) && defined(LWS_HAVE_SSL_SESSION_set_time)
561
0
  SSL_SESSION *sess;
562
0
#endif
563
0
  errno = 0;
564
0
  ERR_clear_error();
565
0
  wsi->tls.err_helper[0] = '\0';
566
0
  n = SSL_connect(wsi->tls.ssl);
567
0
  en = errno;
568
569
0
  m = lws_ssl_get_error(wsi, n);
570
571
  /*
572
   * SSL_ERROR_SYSCALL means the transport failed under us, ie, the
573
   * handshake did not complete.  On windows the socket error appears in
574
   * WSAGetLastError() (which LWS_ERRNO reflects) and the CRT errno is
575
   * typically 0, so gating the bail on errno used to let a truncated
576
   * handshake fall through to the "connect OK" test below and be
577
   * reported upstairs as an established, cert-verified connection
578
   */
579
580
0
  if (m == SSL_ERROR_SYSCALL) {
581
0
    if (!en)
582
0
      en = LWS_ERRNO;
583
0
#if defined(WIN32) || (_LWS_ENABLED_LOGS & LLL_INFO)
584
0
    lwsl_info("%s: n %d, m %d, errno %d\n", __func__, n, m, en);
585
0
#endif
586
0
    lws_snprintf(errbuf, elen, "connect SYSCALL %d", en);
587
0
    return LWS_SSL_CAPABLE_ERROR;
588
0
  }
589
590
0
  if (m == SSL_ERROR_SSL) {
591
0
    l = ERR_get_error();
592
0
    n = lws_snprintf(errbuf, elen, "tls: %s", wsi->tls.err_helper);
593
0
    if (!wsi->tls.err_helper[0])
594
0
      ERR_error_string_n(LWS_TLS_ERR_CAST(l), errbuf + n, (elen - (unsigned int)n));
595
0
    return LWS_SSL_CAPABLE_ERROR;
596
0
  }
597
598
0
#if defined(LWS_WITH_TLS_SESSIONS)
599
0
  if (SSL_session_reused(wsi->tls.ssl)) {
600
0
#if defined(LWS_HAVE_SSL_SESSION_set_time)
601
0
    sess = SSL_get_session(wsi->tls.ssl);
602
0
    if (sess) /* should always be true */
603
#if defined(OPENSSL_IS_BORINGSSL) || defined(LWS_WITH_AWSLC)
604
      SSL_SESSION_set_time(sess, (uint64_t)time(NULL)); /* extend session lifetime */
605
#else
606
0
      SSL_SESSION_set_time(sess, (long)time(NULL)); /* extend session lifetime */
607
0
#endif
608
0
#endif
609
0
  }
610
0
#endif
611
612
0
  if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl))
613
0
    return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
614
615
0
  if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl))
616
0
    return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
617
618
0
  if (n == 1) {
619
    /*
620
     * Handle the negotiated ALPN the same way at handshake
621
     * completion as the gnutls backend does: this also records
622
     * the negotiated ALPN in the client alpn cache, so later
623
     * connections to the same origin can take the stored
624
     * knowledge into account
625
     */
626
0
    lws_tls_server_conn_alpn(wsi);
627
#if defined(LWS_TLS_SYNTHESIZE_CB)
628
    lws_sul_schedule(wsi->a.context, wsi->tsi,
629
         &wsi->tls.sul_cb_synth,
630
         lws_sess_cache_synth_cb, 500 * LWS_US_PER_MS);
631
#endif
632
633
0
    lwsl_info("client connect OK\n");
634
0
    lws_openssl_describe_cipher(wsi);
635
0
    return LWS_SSL_CAPABLE_DONE;
636
0
  }
637
638
0
  if (!n) /* we don't know what he wants, but he says to retry */
639
0
    return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
640
641
0
  lws_snprintf(errbuf, elen, "connect unk %d", m);
642
643
0
  return LWS_SSL_CAPABLE_ERROR;
644
0
}
645
646
int
647
lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, size_t ebuf_len)
648
0
{
649
0
#if !defined(USE_WOLFSSL)
650
0
  char buf[256];
651
0
  const char *es, *type = "";
652
0
  unsigned int avoid = 0;
653
0
  long n;
654
655
0
  errno = 0;
656
0
  ERR_clear_error();
657
0
  n = SSL_get_verify_result(wsi->tls.ssl);
658
659
0
  switch (n) {
660
0
  case X509_V_OK:
661
0
    return 0;
662
663
0
  case X509_V_ERR_HOSTNAME_MISMATCH:
664
0
    type = "tls=hostname";
665
0
    avoid = LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;
666
0
    break;
667
668
0
  case X509_V_ERR_INVALID_CA:
669
0
  case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
670
0
  case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
671
0
    type = "tls=invalidca";
672
0
    avoid = LCCSCF_ALLOW_SELFSIGNED;
673
0
    break;
674
675
0
  case X509_V_ERR_CERT_NOT_YET_VALID:
676
0
    type = "tls=notyetvalid";
677
0
    avoid = LCCSCF_ALLOW_EXPIRED;
678
0
    break;
679
680
0
  case X509_V_ERR_CERT_HAS_EXPIRED:
681
0
    type = "tls=expired";
682
0
    avoid = LCCSCF_ALLOW_EXPIRED;
683
0
    break;
684
0
  }
685
686
0
  lwsl_info("%s: cert problem: %s\n", __func__, type);
687
688
#if defined(LWS_WITH_SYS_METRICS)
689
  lws_metrics_hist_bump_describe_wsi(wsi,
690
      lws_metrics_priv_to_pub(wsi->a.context->mth_conn_failures), type);
691
#endif
692
693
0
  if (wsi->tls.use_ssl & avoid) {
694
0
    lwsl_info("%s: allowing anyway\n", __func__);
695
696
0
    return 0;
697
0
  }
698
699
0
  es = ERR_error_string(LWS_TLS_ERR_CAST(n), buf);
700
0
  lws_snprintf(ebuf, ebuf_len,
701
0
    "server's cert didn't look good, %s X509_V_ERR = %ld: %s\n",
702
0
     type, n, es);
703
0
  lwsl_info("%s\n", ebuf);
704
0
  lws_tls_err_describe_clear();
705
706
0
  return -1;
707
708
#else /* USE_WOLFSSL */
709
710
  /*
711
   * This used to return 0 unconditionally, ie, a wolfSSL-built client
712
   * accepted any server certificate at all: the chain result was never
713
   * looked at on the one path that is supposed to look at it.
714
   *
715
   * wolfSSL's compat layer does not carry the whole X509_V_ERR_ set the
716
   * openssl arm above maps onto individual LCCSCF_ relaxations, and the
717
   * ones it does carry do not have stable values across versions, so we
718
   * cannot say which relaxation would cover a particular failure here.
719
   * What we can do is fail closed on anything that is not X509_V_OK, and
720
   * honour the blanket relaxation.  LCCSCF_ALLOW_SELFSIGNED is already
721
   * handled on this backend by the wolfSSL_set_verify(SSL_VERIFY_NONE)
722
   * in lws_ssl_client_bio_create(), which leaves the result X509_V_OK.
723
   */
724
725
  long n = SSL_get_verify_result(wsi->tls.ssl);
726
727
  if (n == X509_V_OK)
728
    return 0;
729
730
  if (wsi->tls.use_ssl & LCCSCF_ALLOW_INSECURE) {
731
    lwsl_info("%s: allowing anyway (LCCSCF_ALLOW_INSECURE)\n",
732
        __func__);
733
734
    return 0;
735
  }
736
737
  lws_snprintf(ebuf, ebuf_len, "server's cert didn't look good, "
738
         "X509_V_ERR = %ld", n);
739
  lwsl_info("%s\n", ebuf);
740
741
  return -1;
742
#endif
743
0
}
744
#endif
745
746
int
747
lws_tls_client_vhost_extra_cert_mem(struct lws_vhost *vh,
748
                const uint8_t *der, size_t der_len)
749
0
{
750
0
  X509_STORE *st;
751
#if defined(USE_WOLFSSL)
752
  X509 *x  = d2i_X509(NULL, &der, (int)der_len);
753
#else
754
0
  X509 *x  = d2i_X509(NULL, &der, (long)der_len);
755
0
#endif
756
0
  int n;
757
758
0
  if (!x) {
759
0
    lwsl_err("%s: Failed to load DER\n", __func__);
760
0
    lws_tls_err_describe_clear();
761
0
    return 1;
762
0
  }
763
764
0
  st = SSL_CTX_get_cert_store(vh->tls.ssl_client_ctx);
765
0
  if (!st) {
766
0
    st = X509_STORE_new();
767
0
    if (!st) {
768
0
      lwsl_err("%s: failed to create cert store\n", __func__);
769
0
      X509_free(x);
770
0
      return 1;
771
0
    }
772
0
    SSL_CTX_set_cert_store(vh->tls.ssl_client_ctx, st);
773
0
  }
774
775
0
  n = X509_STORE_add_cert(st, x);
776
0
  if (n != 1)
777
0
    lwsl_err("%s: failed to add cert\n", __func__);
778
779
0
  X509_free(x);
780
781
0
  return n != 1;
782
0
}
783
784
int
785
lws_tls_client_create_vhost_context(struct lws_vhost *vh,
786
            const struct lws_context_creation_info *info,
787
            const char *cipher_list,
788
            const char *ca_filepath,
789
            const void *ca_mem,
790
            unsigned int ca_mem_len,
791
            const char *cert_filepath,
792
            const void *cert_mem,
793
            unsigned int cert_mem_len,
794
            const char *private_key_filepath,
795
          const void *key_mem,
796
            unsigned int key_mem_len
797
          )
798
0
{
799
0
#if defined(LWS_HAVE_SSL_CTX_set1_groups_list)
800
  /*
801
   * the client-specific group list if given, else the generic
802
   * .ecdh_curve one
803
   */
804
0
  const char *group_list = vh->tls.cfg_client_ecdh_curve ?
805
0
         vh->tls.cfg_client_ecdh_curve :
806
0
         vh->tls.cfg_ecdh_curve;
807
0
#endif
808
0
  struct lws_tls_client_reuse *tcr;
809
0
  unsigned long error;
810
0
  SSL_METHOD *method;
811
0
  EVP_MD_CTX *mdctx;
812
0
  unsigned int len;
813
0
  uint8_t hash[32];
814
0
  char c;
815
0
  int n;
816
817
  /* basic openssl init already happened in context init */
818
819
  /* choose the most recent spin of the api */
820
0
#if defined(LWS_HAVE_TLS_CLIENT_METHOD)
821
0
  method = (SSL_METHOD *)TLS_client_method();
822
#elif defined(LWS_HAVE_TLSV1_2_CLIENT_METHOD)
823
  method = (SSL_METHOD *)TLSv1_2_client_method();
824
#else
825
  method = (SSL_METHOD *)SSLv23_client_method();
826
#endif
827
828
0
  if (!method) {
829
0
    const char *es;
830
0
    char buf[256];
831
832
0
    error = ERR_peek_error();
833
0
    es = ERR_error_string(LWS_TLS_ERR_CAST(ERR_get_error()), buf);
834
0
    lwsl_err("problem creating ssl method %lu: %s\n",
835
0
      error, es);
836
0
    return 1;
837
0
  }
838
839
  /*
840
   * OpenSSL client contexts are quite expensive, because they bring in
841
   * the system certificate bundle for each one.  So if you have multiple
842
   * vhosts, each with a client context, it can add up to several
843
   * megabytes of heap.  In the case the client contexts are configured
844
   * identically, they could perfectly well have shared just the one.
845
   *
846
   * For that reason, use a hash to fingerprint the context configuration
847
   * and prefer to reuse an existing one with the same fingerprint if
848
   * possible.
849
   */
850
851
0
   mdctx = EVP_MD_CTX_create();
852
0
   if (!mdctx)
853
0
     return 1;
854
855
0
  if (EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL) != 1) {
856
0
    EVP_MD_CTX_destroy(mdctx);
857
858
0
    return 1;
859
0
  }
860
861
0
  if (info->ssl_client_options_set)
862
0
    EVP_DigestUpdate(mdctx, &info->ssl_client_options_set,
863
0
         sizeof(info->ssl_client_options_set));
864
865
0
#if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL)
866
0
  if (info->ssl_client_options_clear)
867
0
    EVP_DigestUpdate(mdctx, &info->ssl_client_options_clear,
868
0
         sizeof(info->ssl_client_options_clear));
869
0
#endif
870
871
0
  if (info->client_tls_ciphers_iana)
872
0
    EVP_DigestUpdate(mdctx, info->client_tls_ciphers_iana,
873
0
         strlen(info->client_tls_ciphers_iana));
874
0
  else {
875
0
    if (cipher_list)
876
0
      EVP_DigestUpdate(mdctx, cipher_list, strlen(cipher_list));
877
878
0
#if defined(LWS_HAVE_SSL_CTX_set_ciphersuites)
879
0
    if (info->client_tls_1_3_plus_cipher_list)
880
0
      EVP_DigestUpdate(mdctx, info->client_tls_1_3_plus_cipher_list,
881
0
           strlen(info->client_tls_1_3_plus_cipher_list));
882
0
#endif
883
0
  }
884
885
0
#if defined(LWS_HAVE_SSL_CTX_set1_groups_list)
886
  /* the group list also affects the identity of the client context */
887
0
  if (group_list)
888
0
    EVP_DigestUpdate(mdctx, group_list, strlen(group_list));
889
0
#endif
890
891
0
  if (!lws_check_opt(vh->options, LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS)) {
892
0
    c = 1;
893
0
    EVP_DigestUpdate(mdctx, &c, 1);
894
0
  }
895
896
  /*
897
   * protocols[0] is part of the context's identity, because it is what
898
   * receives LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS, and
899
   * whatever it adds there lands in the ctx's X509_STORE.  If two vhosts
900
   * with different protocols[0] shared a ctx, a private CA one of them
901
   * pins would silently become trusted by the other, which may have been
902
   * given nothing but the OS trust store on purpose.  The digest cannot
903
   * see inside the callback, but it can at least keep vhosts with
904
   * different handlers apart.
905
   */
906
907
0
  if (vh->protocols)
908
0
    EVP_DigestUpdate(mdctx, &vh->protocols[0].callback,
909
0
         sizeof(vh->protocols[0].callback));
910
911
0
  if (ca_filepath)
912
0
    EVP_DigestUpdate(mdctx, ca_filepath, strlen(ca_filepath));
913
914
0
  if (cert_filepath)
915
0
    EVP_DigestUpdate(mdctx, cert_filepath, strlen(cert_filepath));
916
917
0
  if (private_key_filepath)
918
0
    EVP_DigestUpdate(mdctx, private_key_filepath,
919
0
         strlen(private_key_filepath));
920
0
  if (ca_mem && ca_mem_len)
921
0
    EVP_DigestUpdate(mdctx, ca_mem, ca_mem_len);
922
923
0
  if (cert_mem && cert_mem_len)
924
0
    EVP_DigestUpdate(mdctx, cert_mem, cert_mem_len);
925
926
  /*
927
   * The in-memory client key is part of the identity the context will
928
   * present: without it in the fingerprint, two vhosts with the same
929
   * client cert but different keys share one SSL_CTX, and the second
930
   * silently gets the first one's key
931
   */
932
933
0
  if (key_mem && key_mem_len)
934
0
    EVP_DigestUpdate(mdctx, key_mem, key_mem_len);
935
936
0
  if (info->client_ssl_private_key_password)
937
0
    EVP_DigestUpdate(mdctx, info->client_ssl_private_key_password,
938
0
         strlen(info->client_ssl_private_key_password));
939
940
0
  len = sizeof(hash);
941
0
  EVP_DigestFinal_ex(mdctx, hash, &len);
942
0
  EVP_MD_CTX_destroy(mdctx);
943
944
  /* look for existing client context with same config already */
945
946
0
  lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp,
947
0
       lws_dll2_get_head(&vh->context->tls.cc_owner)) {
948
0
    tcr = lws_container_of(p, struct lws_tls_client_reuse, cc_list);
949
950
0
    if (!memcmp(hash, tcr->hash, len)) {
951
952
      /* it's a match */
953
954
0
      tcr->refcount++;
955
0
      vh->tls.ssl_client_ctx = tcr->ssl_client_ctx;
956
0
      vh->tls.tcr = tcr;
957
958
0
      lwsl_info("%s: vh %s: reusing client ctx %d: use %d\n",
959
0
           __func__, vh->name, tcr->index,
960
0
           tcr->refcount);
961
962
0
      return 0;
963
0
    }
964
0
  } lws_end_foreach_dll_safe(p, tp);
965
966
  /* no existing one the same... create new client SSL_CTX */
967
968
0
  errno = 0;
969
0
  ERR_clear_error();
970
0
  vh->tls.ssl_client_ctx = SSL_CTX_new(method);
971
0
  if (!vh->tls.ssl_client_ctx) {
972
0
    const char *es;
973
0
    char buf[256];
974
975
0
    error = ERR_peek_error();
976
0
    es = ERR_error_string(LWS_TLS_ERR_CAST(ERR_get_error()), buf);
977
0
    lwsl_err("problem creating ssl context %lu: %s\n",
978
0
      error, es);
979
0
    return 1;
980
0
  }
981
982
0
  SSL_CTX_set_ex_data(vh->tls.ssl_client_ctx,
983
0
        openssl_SSL_CTX_private_data_index,
984
0
        (char *)vh->context);
985
986
0
  lws_plat_vhost_tls_client_ctx_init(vh);
987
988
0
  tcr = lws_zalloc(sizeof(*tcr), "client ctx tcr");
989
0
  if (!tcr) {
990
0
    SSL_CTX_free(vh->tls.ssl_client_ctx);
991
0
    return 1;
992
0
  }
993
994
0
  tcr->ssl_client_ctx = vh->tls.ssl_client_ctx;
995
0
  tcr->refcount = 1;
996
0
  memcpy(tcr->hash, hash, len);
997
0
  tcr->index = vh->context->tls.count_client_contexts++;
998
0
  lws_dll2_add_head(&tcr->cc_list, &vh->context->tls.cc_owner);
999
1000
0
  lwsl_info("%s: vh %s: created new client ctx %d\n", __func__,
1001
0
      vh->name, tcr->index);
1002
1003
  /* bind the tcr to the client context */
1004
1005
0
  vh->tls.tcr = tcr;
1006
1007
0
#if defined(LWS_WITH_TLS_KEYLOG) && \
1008
0
    defined(LWS_WITH_TLS) && defined(LWS_WITH_CLIENT)
1009
0
  if (vh->context->keylog_file[0])
1010
0
    SSL_CTX_set_keylog_callback(vh->tls.ssl_client_ctx, lws_klog_dump);
1011
0
#endif
1012
1013
0
#if defined(LWS_WITH_TLS_SESSIONS)
1014
0
  vh->tls_session_cache_max = info->tls_session_cache_max ?
1015
0
            info->tls_session_cache_max : 10;
1016
0
  lws_tls_session_cache(vh, info->tls_session_timeout);
1017
0
#endif
1018
1019
0
#ifdef SSL_OP_NO_COMPRESSION
1020
0
  SSL_CTX_set_options(vh->tls.ssl_client_ctx, SSL_OP_NO_COMPRESSION);
1021
0
#endif
1022
1023
  /*
1024
   * Same floor as the server ctx: SSLv2 / SSLv3 off and TLS 1.2 the
1025
   * minimum (RFC 8996).  Expressed as options so that the existing
1026
   * .ssl_client_options_clear info member, applied below, is still the
1027
   * way an app that must reach a legacy peer lowers it.
1028
   */
1029
0
  SSL_CTX_set_options(vh->tls.ssl_client_ctx, SSL_OP_NO_SSLv2 |
1030
0
                SSL_OP_NO_SSLv3
1031
0
#if defined(SSL_OP_NO_TLSv1)
1032
0
                | SSL_OP_NO_TLSv1
1033
0
#endif
1034
0
#if defined(SSL_OP_NO_TLSv1_1)
1035
0
                | SSL_OP_NO_TLSv1_1
1036
0
#endif
1037
0
         );
1038
1039
  /*
1040
   * A server that can force renegotiation can present a different
1041
   * certificate after we have already latched the peer identity check,
1042
   * and it costs us a key exchange per HelloRequest.  Refuse it.
1043
   */
1044
0
#if defined(SSL_OP_NO_RENEGOTIATION)
1045
0
  SSL_CTX_set_options(vh->tls.ssl_client_ctx, SSL_OP_NO_RENEGOTIATION);
1046
0
#endif
1047
1048
0
  SSL_CTX_set_options(vh->tls.ssl_client_ctx,
1049
0
          SSL_OP_CIPHER_SERVER_PREFERENCE);
1050
1051
0
  SSL_CTX_set_mode(vh->tls.ssl_client_ctx,
1052
0
       SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
1053
0
       SSL_MODE_RELEASE_BUFFERS);
1054
1055
0
  SSL_OPT_TYPE ssl_client_options_set_value = (SSL_OPT_TYPE) info->ssl_client_options_set;
1056
1057
0
  if (info->ssl_client_options_set)
1058
0
    SSL_CTX_set_options(vh->tls.ssl_client_ctx, ssl_client_options_set_value);
1059
1060
0
#if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL)
1061
  /* SSL_clear_options introduced in 0.9.8m */
1062
0
  SSL_OPT_TYPE ssl_client_options_clear_value = (SSL_OPT_TYPE) info->ssl_client_options_clear;
1063
1064
0
  if (info->ssl_client_options_clear)
1065
0
    SSL_CTX_clear_options(vh->tls.ssl_client_ctx, ssl_client_options_clear_value);
1066
#else
1067
  /*
1068
   * There is no SSL_CTX_clear_options() to apply here, so
1069
   * .ssl_client_options_clear is inoperative on this build... which also
1070
   * means the TLS 1.2 floor and the renegotiation refusal set above
1071
   * (C-406) cannot be lowered.  Say so rather than let an operator
1072
   * believe his override took effect.
1073
   */
1074
  if (info->ssl_client_options_clear)
1075
    lwsl_err("%s: vh %s: this TLS build has no "
1076
       "SSL_CTX_clear_options(), ssl_client_options_clear "
1077
       "0x%lX IGNORED\n", __func__, vh->name,
1078
       (unsigned long)info->ssl_client_options_clear);
1079
#endif
1080
1081
0
  if (info->client_tls_ciphers_iana) {
1082
0
    char *p = lws_strdup(info->client_tls_ciphers_iana);
1083
0
    if (p) {
1084
0
      char *q = p;
1085
0
      while (*q) {
1086
0
        if (*q == ',')
1087
0
          *q = ':';
1088
0
        q++;
1089
0
      }
1090
0
      SSL_CTX_set_cipher_list(vh->tls.ssl_client_ctx, p);
1091
0
#if defined(LWS_HAVE_SSL_CTX_set_ciphersuites)
1092
0
      SSL_CTX_set_ciphersuites(vh->tls.ssl_client_ctx, p);
1093
0
#endif
1094
0
      lws_free(p);
1095
0
    }
1096
0
  } else {
1097
0
    if (cipher_list)
1098
0
      SSL_CTX_set_cipher_list(vh->tls.ssl_client_ctx, cipher_list);
1099
1100
0
#if defined(LWS_HAVE_SSL_CTX_set_ciphersuites)
1101
0
    if (info->client_tls_1_3_plus_cipher_list)
1102
0
      SSL_CTX_set_ciphersuites(vh->tls.ssl_client_ctx,
1103
0
             info->client_tls_1_3_plus_cipher_list);
1104
0
#endif
1105
0
  }
1106
1107
0
#if defined(LWS_HAVE_SSL_CTX_set1_groups_list)
1108
  /* restrict the groups offered to the peer, if asked to */
1109
0
  if (group_list) {
1110
0
    if (!SSL_CTX_set1_groups_list(vh->tls.ssl_client_ctx,
1111
0
                group_list)) {
1112
0
      lwsl_err("%s: SSL_CTX_set1_groups_list '%s' failed\n",
1113
0
         __func__, group_list);
1114
0
      lws_tls_err_describe_clear();
1115
1116
0
      return 1;
1117
0
    }
1118
0
    lwsl_notice("%s: vh %s: client groups list '%s'\n", __func__,
1119
0
          vh->name, group_list);
1120
0
  }
1121
0
#endif
1122
1123
0
#ifdef LWS_SSL_CLIENT_USE_OS_CA_CERTS
1124
0
  if (!lws_check_opt(vh->options, LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS))
1125
    /* loads OS default CA certs */
1126
0
    SSL_CTX_set_default_verify_paths(vh->tls.ssl_client_ctx);
1127
0
#endif
1128
1129
  /* openssl init for cert verification (for client sockets) */
1130
0
  if (!ca_filepath && (!ca_mem || !ca_mem_len)) {
1131
#if defined(LWS_HAVE_SSL_CTX_load_verify_dir)
1132
    if (!SSL_CTX_load_verify_dir(
1133
      vh->tls.ssl_client_ctx, LWS_OPENSSL_CLIENT_CERTS))
1134
#else
1135
0
    if (!SSL_CTX_load_verify_locations(
1136
0
      vh->tls.ssl_client_ctx, NULL, LWS_OPENSSL_CLIENT_CERTS))
1137
0
#endif
1138
0
      lwsl_err("Unable to load SSL Client certs from %s "
1139
0
          "(set by LWS_OPENSSL_CLIENT_CERTS) -- "
1140
0
          "client ssl isn't going to work\n",
1141
0
          LWS_OPENSSL_CLIENT_CERTS);
1142
0
  } else if (ca_filepath) {
1143
#if defined(LWS_HAVE_SSL_CTX_load_verify_file)
1144
    if (!SSL_CTX_load_verify_file(
1145
      vh->tls.ssl_client_ctx, ca_filepath)) {
1146
#else
1147
0
    if (!SSL_CTX_load_verify_locations(
1148
0
      vh->tls.ssl_client_ctx, ca_filepath, NULL)) {
1149
0
#endif
1150
0
      lwsl_err(
1151
0
        "Unable to load SSL Client certs "
1152
0
        "file from %s -- client ssl isn't "
1153
0
        "going to work\n", ca_filepath);
1154
0
      lws_tls_err_describe_clear();
1155
0
    }
1156
0
    else
1157
0
      lwsl_info("loaded ssl_ca_filepath\n");
1158
0
  } else {
1159
1160
0
    if (lws_tls_client_vhost_ca_mem_parse(vh, ca_mem, ca_mem_len)) {
1161
0
      lwsl_err("%s: Unable to load x.509 ca_mem\n", __func__);
1162
0
      return 1;
1163
0
    }
1164
0
  }
1165
1166
  /*
1167
   * callback allowing user code to load extra verification certs
1168
   * helping the client to verify server identity
1169
   */
1170
1171
  /* support for client-side certificate authentication */
1172
1173
0
  if (cert_filepath) {
1174
0
    if (lws_tls_use_any_upgrade_check_extant(cert_filepath) !=
1175
0
        LWS_TLS_EXTANT_YES &&
1176
0
        (info->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT))
1177
0
      return 0;
1178
1179
0
    lwsl_notice("%s: doing cert filepath %s\n", __func__,
1180
0
        cert_filepath);
1181
0
    n = SSL_CTX_use_certificate_chain_file(vh->tls.ssl_client_ctx,
1182
0
                   cert_filepath);
1183
0
    if (n < 1) {
1184
0
      lwsl_err("problem %d getting cert '%s'\n", n,
1185
0
         cert_filepath);
1186
0
      lws_tls_err_describe_clear();
1187
0
      return 1;
1188
0
    }
1189
0
    lwsl_info("Loaded client cert %s\n", cert_filepath);
1190
1191
0
  } else if (cert_mem && cert_mem_len) {
1192
0
    lws_filepos_t flen;
1193
0
    uint8_t *p;
1194
1195
0
    if (lws_tls_alloc_pem_to_der_file(vh->context, NULL, cert_mem,
1196
0
              cert_mem_len, &p, &flen)) {
1197
0
      lwsl_err("%s: couldn't read cert file\n", __func__);
1198
1199
0
      return 1;
1200
0
    }
1201
1202
0
    n = SSL_CTX_use_certificate_ASN1(vh->tls.ssl_client_ctx, SSL_SIZE_T_CAST(flen), p);
1203
1204
0
    if (n < 1) {
1205
0
      lwsl_err("%s: problem interpreting client cert\n",  __func__);
1206
0
      lws_tls_err_describe_clear();
1207
0
    }
1208
1209
0
    lws_free_set_NULL(p);
1210
1211
0
    if (n != 1)
1212
0
      return 1;
1213
1214
0
  }
1215
0
  if (private_key_filepath) {
1216
0
    lwsl_info("%s: using private key filepath\n", __func__);
1217
0
    lws_ssl_bind_passphrase(vh->tls.ssl_client_ctx, 1, info);
1218
    /* set the private key from KeyFile */
1219
0
    if (SSL_CTX_use_PrivateKey_file(vh->tls.ssl_client_ctx,
1220
0
        private_key_filepath, SSL_FILETYPE_PEM) != 1) {
1221
0
      lwsl_err("use_PrivateKey_file '%s'\n",
1222
0
         private_key_filepath);
1223
0
      lws_tls_err_describe_clear();
1224
0
      return 1;
1225
0
    }
1226
0
    lwsl_info("Loaded client cert private key %s\n",
1227
0
          private_key_filepath);
1228
1229
    /* verify private key */
1230
0
    if (!SSL_CTX_check_private_key(vh->tls.ssl_client_ctx)) {
1231
0
      lwsl_err("Private SSL key doesn't match cert\n");
1232
0
      return 1;
1233
0
    }
1234
0
  }
1235
0
  else if (key_mem && key_mem_len) {
1236
1237
0
    lws_filepos_t flen;
1238
0
    uint8_t *p;
1239
1240
0
    if (lws_tls_alloc_pem_to_der_file(vh->context, NULL, key_mem,
1241
0
              key_mem_len, &p, &flen)) {
1242
0
      lwsl_err("%s: couldn't use mem cert\n", __func__);
1243
1244
0
      return 1;
1245
0
    }
1246
1247
0
    n = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA, vh->tls.ssl_client_ctx, p,
1248
#if defined(LWS_WITH_BORINGSSL) || defined(LWS_WITH_AWSLC)
1249
        (size_t)
1250
#else
1251
0
        (long)(lws_intptr_t)
1252
0
#endif
1253
0
            flen);
1254
0
    if (n != 1)
1255
0
      n = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_EC,
1256
0
              vh->tls.ssl_client_ctx, p,
1257
#if defined(LWS_WITH_BORINGSSL) || defined(LWS_WITH_AWSLC)
1258
        (size_t)
1259
#else
1260
0
        (long)(lws_intptr_t)
1261
0
#endif
1262
0
            flen);
1263
1264
0
    lws_free_set_NULL(p);
1265
1266
0
    if (n != 1)  {
1267
0
      lwsl_err("%s: unable to use key_mem\n", __func__);
1268
1269
0
      return 1;
1270
0
    }
1271
0
  }
1272
1273
#if defined(LWS_ROLE_QUIC) && !defined(LWS_WITH_MBEDTLS) && !defined(LWS_WITH_WOLFSSL) && !defined(LWS_WITH_SCHANNEL) && !defined(LWS_WITH_GNUTLS) && !defined(LWS_WITH_BEARSSL)
1274
  lws_tls_quic_vhost_init(vh->tls.ssl_client_ctx);
1275
#endif
1276
1277
0
  return 0;
1278
0
}
1279
1280