Coverage Report

Created: 2025-11-11 06:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwebsockets/lib/tls/openssl/openssl-server.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 "private-lib-core.h"
26
#include "private-lib-tls-openssl.h"
27
28
/*
29
 * Care: many openssl apis return 1 for success.  These are translated to the
30
 * lws convention of 0 for success.
31
 */
32
33
extern int openssl_websocket_private_data_index,
34
     openssl_SSL_CTX_private_data_index;
35
36
int lws_openssl_describe_cipher(struct lws *wsi);
37
38
static int
39
OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
40
0
{
41
0
  SSL *ssl;
42
0
  int n;
43
0
  struct lws *wsi;
44
0
  union lws_tls_cert_info_results ir;
45
0
  X509 *topcert = X509_STORE_CTX_get_current_cert(x509_ctx);
46
47
0
  ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
48
0
    SSL_get_ex_data_X509_STORE_CTX_idx());
49
50
  /*
51
   * !!! nasty openssl requires the index to come as a library-scope
52
   * static
53
   */
54
0
  wsi = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
55
0
  if (!wsi)
56
0
    return 0; /* OpenSSL failure */
57
58
0
  n = lws_tls_openssl_cert_info(topcert, LWS_TLS_CERT_INFO_COMMON_NAME,
59
0
              &ir, sizeof(ir.ns.name));
60
0
  if (!n)
61
0
    lwsl_info("%s: client cert CN '%s'\n", __func__, ir.ns.name);
62
0
  else
63
0
    lwsl_info("%s: couldn't get client cert CN\n", __func__);
64
65
0
  n = wsi->a.vhost->protocols[0].callback(wsi,
66
0
      LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
67
0
             x509_ctx, ssl, (unsigned int)preverify_ok);
68
69
  /* convert return code from 0 = OK to 1 = OK */
70
0
  return !n;
71
0
}
72
73
int
74
lws_tls_server_client_cert_verify_config(struct lws_vhost *vh)
75
0
{
76
0
  int verify_options = SSL_VERIFY_PEER;
77
78
  /* as a server, are we requiring clients to identify themselves? */
79
80
0
  if (!lws_check_opt(vh->options,
81
0
        LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT))
82
0
    return 0;
83
84
0
  if (!lws_check_opt(vh->options,
85
0
         LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED))
86
0
    verify_options |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
87
88
0
  SSL_CTX_set_session_id_context(vh->tls.ssl_ctx, (uint8_t *)vh->context,
89
0
               sizeof(void *));
90
91
  /* absolutely require the client cert */
92
0
  SSL_CTX_set_verify(vh->tls.ssl_ctx, verify_options,
93
0
         OpenSSL_verify_callback);
94
95
0
  return 0;
96
0
}
97
98
#if defined(SSL_TLSEXT_ERR_NOACK) && !defined(OPENSSL_NO_TLSEXT)
99
static int
100
lws_ssl_server_name_cb(SSL *ssl, int *ad, void *arg)
101
0
{
102
0
  struct lws_context *context = (struct lws_context *)arg;
103
0
  struct lws_vhost *vhost, *vh;
104
0
  const char *servername;
105
106
0
  if (!ssl)
107
0
    return SSL_TLSEXT_ERR_NOACK;
108
109
  /*
110
   * We can only get ssl accepted connections by using a vhost's ssl_ctx
111
   * find out which listening one took us and only match vhosts on the
112
   * same port.
113
   */
114
0
  vh = context->vhost_list;
115
0
  while (vh) {
116
0
    if (!vh->being_destroyed &&
117
0
        vh->tls.ssl_ctx == SSL_get_SSL_CTX(ssl))
118
0
      break;
119
0
    vh = vh->vhost_next;
120
0
  }
121
122
0
  if (!vh) {
123
0
    assert(vh); /* can't match the incoming vh? */
124
0
    return SSL_TLSEXT_ERR_OK;
125
0
  }
126
127
0
  servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
128
0
  if (!servername) {
129
    /* the client doesn't know what hostname it wants */
130
0
    lwsl_info("SNI: Unknown ServerName\n");
131
132
0
    return SSL_TLSEXT_ERR_OK;
133
0
  }
134
135
0
  vhost = lws_select_vhost(context, vh->listen_port, servername);
136
0
  if (!vhost) {
137
0
    lwsl_info("SNI: none: %s:%d\n", servername, vh->listen_port);
138
139
0
    return SSL_TLSEXT_ERR_OK;
140
0
  }
141
142
0
  lwsl_info("SNI: Found: %s:%d\n", servername, vh->listen_port);
143
144
  /* select the ssl ctx from the selected vhost for this conn */
145
0
  SSL_set_SSL_CTX(ssl, vhost->tls.ssl_ctx);
146
147
0
  return SSL_TLSEXT_ERR_OK;
148
0
}
149
#endif
150
151
/*
152
 * this may now get called after the vhost creation, when certs become
153
 * available.
154
 */
155
int
156
lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi,
157
        const char *cert, const char *private_key,
158
        const char *mem_cert, size_t mem_cert_len,
159
        const char *mem_privkey, size_t mem_privkey_len)
160
0
{
161
0
#if !defined(OPENSSL_NO_EC) && defined(LWS_HAVE_EC_KEY_new_by_curve_name) && \
162
0
    ((OPENSSL_VERSION_NUMBER < 0x30000000l) || \
163
0
     defined(LWS_SUPPRESS_DEPRECATED_API_WARNINGS))
164
0
  const char *ecdh_curve = "prime256v1";
165
0
#if !defined(LWS_WITH_BORINGSSL) && !defined(LWS_WITH_AWSLC) && defined(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS)
166
0
  STACK_OF(X509) *extra_certs = NULL;
167
0
#endif
168
0
  EC_KEY *ecdh, *EC_key = NULL;
169
0
  EVP_PKEY *pkey;
170
0
  X509 *x = NULL;
171
0
  int ecdh_nid;
172
0
  int KeyType;
173
0
#endif
174
0
  unsigned long error;
175
0
  lws_filepos_t flen;
176
0
  uint8_t *p;
177
0
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
178
0
  int ret;
179
0
#endif
180
0
  int n = (int)lws_tls_generic_cert_checks(vhost, cert, private_key), m;
181
182
0
  if (!cert && !private_key)
183
0
    n = LWS_TLS_EXTANT_ALTERNATIVE;
184
185
0
  if (n == LWS_TLS_EXTANT_NO && (!mem_cert || !mem_privkey))
186
0
    return 0;
187
0
  if (n == LWS_TLS_EXTANT_NO)
188
0
    n = LWS_TLS_EXTANT_ALTERNATIVE;
189
190
0
  if (n == LWS_TLS_EXTANT_ALTERNATIVE && (!mem_cert || !mem_privkey))
191
0
    return 1; /* no alternative */
192
193
0
  if (n == LWS_TLS_EXTANT_ALTERNATIVE) {
194
195
0
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
196
197
    /*
198
     * Although we have prepared update certs, we no longer have
199
     * the rights to read our own cert + key we saved.
200
     *
201
     * If we were passed copies in memory buffers, use those
202
     * in favour of the filepaths we normally want.
203
     */
204
0
    cert = NULL;
205
0
    private_key = NULL;
206
0
  }
207
208
  /*
209
   * use the multi-cert interface for backwards compatibility in the
210
   * both simple files case
211
   */
212
213
0
  if (n != LWS_TLS_EXTANT_ALTERNATIVE && cert) {
214
215
    /* set the local certificate from CertFile */
216
0
    m = SSL_CTX_use_certificate_chain_file(vhost->tls.ssl_ctx, cert);
217
0
    if (m != 1) {
218
0
      const char *s;
219
0
      error = ERR_peek_error();
220
0
      s = ERR_error_string(ERR_get_error(), (char *)vhost->context->pt[0].serv_buf);
221
222
0
      lwsl_err("problem getting cert '%s' %lu: %s\n",
223
0
         cert, error, s);
224
225
0
      return 1;
226
0
    }
227
228
0
    if (!private_key) {
229
0
      lwsl_err("ssl private key not set\n");
230
0
      return 1;
231
0
    } else {
232
      /* set the private key from KeyFile */
233
0
      if (SSL_CTX_use_PrivateKey_file(vhost->tls.ssl_ctx, private_key,
234
0
              SSL_FILETYPE_PEM) != 1) {
235
0
        const char *s;
236
0
        error = ERR_peek_error();
237
0
        s = ERR_error_string(ERR_get_error(), (char *)vhost->context->pt[0].serv_buf);
238
0
        lwsl_err("ssl problem getting key '%s' %lu: %s\n",
239
0
           private_key, error, s);
240
0
        return 1;
241
0
      }
242
0
    }
243
244
0
    return 0;
245
0
  }
246
247
  /* otherwise allow for DER or PEM, file or memory image */
248
249
0
  if (lws_tls_alloc_pem_to_der_file(vhost->context, cert, mem_cert,
250
0
            mem_cert_len, &p, &flen)) {
251
0
    lwsl_err("%s: couldn't read cert file\n", __func__);
252
253
0
    return 1;
254
0
  }
255
256
0
#if !defined(USE_WOLFSSL)
257
0
  ret = SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx, SSL_SIZE_CAST(flen), p);
258
#else
259
  ret = wolfSSL_CTX_use_certificate_buffer(vhost->tls.ssl_ctx,
260
             (uint8_t *)p, (int)flen,
261
             WOLFSSL_FILETYPE_ASN1);
262
#endif
263
0
  lws_free_set_NULL(p);
264
0
  if (ret != 1) {
265
0
    lwsl_err("%s: Problem loading cert\n", __func__);
266
267
0
    return 1;
268
0
  }
269
270
0
  if (lws_tls_alloc_pem_to_der_file(vhost->context, private_key,
271
0
            mem_privkey, mem_privkey_len,
272
0
            &p, &flen)) {
273
0
    lwsl_notice("unable to convert memory privkey\n");
274
275
0
    return 1;
276
0
  }
277
278
0
#if !defined(USE_WOLFSSL)
279
0
  ret = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA, vhost->tls.ssl_ctx, p,
280
#if defined(LWS_WITH_BORINGSSL) || defined(LWS_WITH_AWSLC)
281
      (size_t)
282
#else
283
0
            (long)(long long)
284
0
#endif
285
0
            flen);
286
0
  if (ret != 1) {
287
0
    ret = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_EC,
288
0
              vhost->tls.ssl_ctx, p,
289
#if defined(LWS_WITH_BORINGSSL) || defined(LWS_WITH_AWSLC)
290
      (size_t)
291
#else
292
0
            (long)(long long)
293
0
#endif
294
0
              flen);
295
0
  }
296
#else
297
  ret = wolfSSL_CTX_use_PrivateKey_buffer(vhost->tls.ssl_ctx, p, (long) flen,
298
            WOLFSSL_FILETYPE_ASN1);
299
#endif
300
0
  lws_free_set_NULL(p);
301
0
  if (ret != 1)  {
302
0
    lwsl_notice("unable to use memory privkey\n");
303
304
0
    return 1;
305
0
  }
306
307
#else
308
    /*
309
     * Although we have prepared update certs, we no longer have
310
     * the rights to read our own cert + key we saved.
311
     *
312
     * If we were passed copies in memory buffers, use those
313
     * instead.
314
     *
315
     * The passed memory-buffer cert image is in DER, and the
316
     * memory-buffer private key image is PEM.
317
     */
318
    if (lws_tls_alloc_pem_to_der_file(vhost->context, cert, mem_cert,
319
              mem_cert_len, &p, &flen)) {
320
      lwsl_err("%s: couldn't convert pem to der\n", __func__);
321
      return 1;
322
    }
323
#ifndef USE_WOLFSSL
324
    if (SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx,
325
             (int)flen,
326
             (uint8_t *)p) != 1) {
327
#else
328
    if (wolfSSL_CTX_use_certificate_buffer(vhost->tls.ssl_ctx,
329
             (uint8_t *)p,
330
             (int)flen,
331
             WOLFSSL_FILETYPE_ASN1) != 1) {
332
333
#endif
334
      lwsl_err("Problem loading update cert\n");
335
336
      return 1;
337
    }
338
339
    if (lws_tls_alloc_pem_to_der_file(vhost->context, NULL,
340
              mem_privkey, mem_privkey_len,
341
              &p, &flen)) {
342
      lwsl_notice("unable to convert memory privkey\n");
343
344
      return 1;
345
    }
346
#ifndef USE_WOLFSSL
347
    if (SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA,
348
            vhost->tls.ssl_ctx, p,
349
            (long)(long long)flen) != 1) {
350
#else
351
    if (wolfSSL_CTX_use_PrivateKey_buffer(vhost->tls.ssl_ctx, p,
352
              (long)flen, WOLFSSL_FILETYPE_ASN1) != 1) {
353
#endif
354
      lwsl_notice("unable to use memory privkey\n");
355
356
      return 1;
357
    }
358
359
    goto check_key;
360
  }
361
362
  /* set the local certificate from CertFile */
363
  m = SSL_CTX_use_certificate_chain_file(vhost->tls.ssl_ctx, cert);
364
  if (m != 1) {
365
    error = ERR_get_error();
366
    lwsl_err("problem getting cert '%s' %lu: %s\n",
367
       cert, error, ERR_error_string(error,
368
             (char *)vhost->context->pt[0].serv_buf));
369
370
    return 1;
371
  }
372
373
  if (n == LWS_TLS_EXTANT_ALTERNATIVE || !private_key) {
374
    lwsl_err("ssl private key not set\n");
375
    return 1;
376
  } else {
377
    /* set the private key from KeyFile */
378
    if (SSL_CTX_use_PrivateKey_file(vhost->tls.ssl_ctx, private_key,
379
                  SSL_FILETYPE_PEM) != 1) {
380
      error = ERR_get_error();
381
      lwsl_err("ssl problem getting key '%s' %lu: %s\n",
382
         private_key, error,
383
         ERR_error_string(error,
384
              (char *)vhost->context->pt[0].serv_buf));
385
      return 1;
386
    }
387
  }
388
389
check_key:
390
#endif
391
392
  /* verify private key */
393
0
  if (!SSL_CTX_check_private_key(vhost->tls.ssl_ctx)) {
394
0
    lwsl_err("Private SSL key doesn't match cert\n");
395
396
0
    return 1;
397
0
  }
398
399
400
0
#if !defined(OPENSSL_NO_EC) && defined(LWS_HAVE_EC_KEY_new_by_curve_name) && \
401
0
    ((OPENSSL_VERSION_NUMBER < 0x30000000l) || \
402
0
     defined(LWS_SUPPRESS_DEPRECATED_API_WARNINGS))
403
0
  if (vhost->tls.ecdh_curve[0])
404
0
    ecdh_curve = vhost->tls.ecdh_curve;
405
406
0
  ecdh_nid = OBJ_sn2nid(ecdh_curve);
407
0
  if (NID_undef == ecdh_nid) {
408
0
    lwsl_err("SSL: Unknown curve name '%s'", ecdh_curve);
409
0
    return 1;
410
0
  }
411
412
0
  ecdh = EC_KEY_new_by_curve_name(ecdh_nid);
413
0
  if (NULL == ecdh) {
414
0
    lwsl_err("SSL: Unable to create curve '%s'", ecdh_curve);
415
0
    return 1;
416
0
  }
417
0
  SSL_CTX_set_tmp_ecdh(vhost->tls.ssl_ctx, ecdh);
418
0
  EC_KEY_free(ecdh);
419
420
0
  SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_SINGLE_ECDH_USE);
421
422
0
  lwsl_notice(" SSL ECDH curve '%s'\n", ecdh_curve);
423
424
0
  if (lws_check_opt(vhost->context->options, LWS_SERVER_OPTION_SSL_ECDH))
425
0
    lwsl_notice(" Using ECDH certificate support\n");
426
427
  /* Get X509 certificate from ssl context */
428
0
#if !defined(LWS_WITH_BORINGSSL) && !defined(LWS_WITH_AWSLC) && !defined(USE_WOLFSSL)
429
#if !defined(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS)
430
  x = sk_X509_value(vhost->tls.ssl_ctx->extra_certs, 0);
431
#else
432
0
  SSL_CTX_get_extra_chain_certs_only(vhost->tls.ssl_ctx, &extra_certs);
433
0
  if (extra_certs)
434
0
    x = sk_X509_value(extra_certs, 0);
435
0
  else
436
0
    lwsl_info("%s: no extra certs\n", __func__);
437
0
#endif
438
0
  if (!x) {
439
    //lwsl_err("%s: x is NULL\n", __func__);
440
0
    goto post_ecdh;
441
0
  }
442
#else
443
  return 0;
444
#endif /* !boringssl */
445
446
  /* Get the public key from certificate */
447
0
  pkey = X509_get_pubkey(x);
448
0
  if (!pkey) {
449
0
    lwsl_err("%s: pkey is NULL\n", __func__);
450
451
0
    return 1;
452
0
  }
453
  /* Get the key type */
454
0
  KeyType = EVP_PKEY_type(EVP_PKEY_id(pkey));
455
456
0
  if (EVP_PKEY_EC != KeyType) {
457
0
    lwsl_notice("Key type is not EC\n");
458
0
    return 0;
459
0
  }
460
  /* Get the key */
461
0
  EC_key = EVP_PKEY_get1_EC_KEY(pkey);
462
  /* Set ECDH parameter */
463
0
  if (!EC_key) {
464
0
    lwsl_err("%s: ECDH key is NULL \n", __func__);
465
0
    return 1;
466
0
  }
467
0
  SSL_CTX_set_tmp_ecdh(vhost->tls.ssl_ctx, EC_key);
468
469
0
  EC_KEY_free(EC_key);
470
471
0
#if !defined(OPENSSL_NO_EC) && !defined(LWS_WITH_BORINGSSL) && !defined(LWS_WITH_AWSLC) && !defined(USE_WOLFSSL)
472
0
post_ecdh:
473
0
#endif
474
0
  vhost->tls.skipped_certs = 0;
475
#else
476
  lwsl_notice(" OpenSSL doesn't support ECDH\n");
477
#endif
478
479
0
  return 0;
480
0
}
481
482
int
483
lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info,
484
          struct lws_vhost *vhost, struct lws *wsi)
485
0
{
486
0
  unsigned long error;
487
0
  SSL_METHOD *method = (SSL_METHOD *)SSLv23_server_method();
488
489
0
  if (!method) {
490
0
    const char *s;
491
0
    error = ERR_peek_error();
492
0
    s = ERR_error_string(ERR_get_error(), (char *)vhost->context->pt[0].serv_buf);
493
494
0
    lwsl_err("problem creating ssl method %lu: %s\n",
495
0
        error, s);
496
0
    return 1;
497
0
  }
498
0
  vhost->tls.ssl_ctx = SSL_CTX_new(method); /* create context */
499
0
  if (!vhost->tls.ssl_ctx) {
500
0
    const char *s;
501
502
0
    error = ERR_peek_error();
503
0
    s = ERR_error_string(ERR_get_error(), (char *)vhost->context->pt[0].serv_buf);
504
0
    lwsl_err("problem creating ssl context %lu: %s\n",
505
0
        error, s);
506
0
    return 1;
507
0
  }
508
  /* Added for sniffing packets on hub side */
509
0
#if defined(LWS_HAVE_SSL_CTX_set_keylog_callback) && \
510
0
    defined(LWS_WITH_TLS) && (!defined(LWS_WITHOUT_CLIENT) || !defined(LWS_WITHOUT_SERVER))
511
0
  SSL_CTX_set_keylog_callback(vhost->tls.ssl_ctx, lws_klog_dump);
512
0
#endif
513
514
0
  SSL_CTX_set_ex_data(vhost->tls.ssl_ctx,
515
0
          openssl_SSL_CTX_private_data_index,
516
0
          (char *)vhost->context);
517
  /* Disable SSLv2 and SSLv3 */
518
0
  SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_NO_SSLv2 |
519
0
            SSL_OP_NO_SSLv3);
520
0
#ifdef SSL_OP_NO_COMPRESSION
521
0
  SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_NO_COMPRESSION);
522
0
#endif
523
0
  if (lws_check_opt(info->options,
524
0
                    LWS_SERVER_OPTION_OPENSSL_AUTO_DH_PARAMETERS))
525
0
#if defined(LWS_HAVE_SSL_CTX_SET_ECDH_AUTO) || defined(LWS_WITH_BORINGSSL)
526
0
    (void)SSL_CTX_set_ecdh_auto(vhost->tls.ssl_ctx, 1);
527
#else
528
    SSL_CTX_set_dh_auto(vhost->tls.ssl_ctx, 1);
529
#endif
530
531
0
  SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_SINGLE_DH_USE);
532
0
  SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
533
534
0
  if (info->ssl_cipher_list)
535
0
    SSL_CTX_set_cipher_list(vhost->tls.ssl_ctx, info->ssl_cipher_list);
536
537
0
#if defined(LWS_HAVE_SSL_CTX_set_ciphersuites)
538
0
  if (info->tls1_3_plus_cipher_list)
539
0
    SSL_CTX_set_ciphersuites(vhost->tls.ssl_ctx,
540
0
           info->tls1_3_plus_cipher_list);
541
0
#endif
542
543
0
#if !defined(OPENSSL_NO_TLSEXT)
544
0
  SSL_CTX_set_tlsext_servername_callback(vhost->tls.ssl_ctx,
545
0
                 lws_ssl_server_name_cb);
546
0
  SSL_CTX_set_tlsext_servername_arg(vhost->tls.ssl_ctx, vhost->context);
547
0
#endif
548
549
0
  if (info->ssl_ca_filepath &&
550
#if defined(LWS_HAVE_SSL_CTX_load_verify_file)
551
      !SSL_CTX_load_verify_file(vhost->tls.ssl_ctx,
552
              info->ssl_ca_filepath)) {
553
#else
554
0
      !SSL_CTX_load_verify_locations(vhost->tls.ssl_ctx,
555
0
             info->ssl_ca_filepath, NULL)) {
556
0
#endif
557
0
    lwsl_err("%s: SSL_CTX_load_verify_locations unhappy\n",
558
0
       __func__);
559
0
  }
560
561
0
  SSL_OPT_TYPE ssl_options_set_value = (SSL_OPT_TYPE) info->ssl_options_set;
562
563
0
  if (info->ssl_options_set)
564
0
    SSL_CTX_set_options(vhost->tls.ssl_ctx, ssl_options_set_value);
565
566
0
#if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL)
567
568
/* SSL_clear_options introduced in 0.9.8m */
569
0
  SSL_OPT_TYPE ssl_options_clear_value = (SSL_OPT_TYPE) info->ssl_options_clear;
570
571
0
  if (info->ssl_options_clear) {
572
0
    SSL_CTX_clear_options(vhost->tls.ssl_ctx, ssl_options_clear_value);
573
0
  }
574
575
0
  lwsl_info(" SSL options 0x%lX\n",
576
0
      (unsigned long)SSL_CTX_get_options(vhost->tls.ssl_ctx));
577
0
#endif
578
579
0
  if (!vhost->tls.use_ssl ||
580
0
      (!info->ssl_cert_filepath && !info->server_ssl_cert_mem))
581
0
    return 0;
582
583
0
  lws_ssl_bind_passphrase(vhost->tls.ssl_ctx, 0, info);
584
585
0
  return lws_tls_server_certs_load(vhost, wsi, info->ssl_cert_filepath,
586
0
           info->ssl_private_key_filepath,
587
0
           info->server_ssl_cert_mem,
588
0
           info->server_ssl_cert_mem_len,
589
0
           info->server_ssl_private_key_mem,
590
0
           info->server_ssl_private_key_mem_len);
591
0
}
592
593
int
594
lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd)
595
0
{
596
0
#if !defined(USE_WOLFSSL)
597
0
  BIO *bio;
598
0
#endif
599
600
0
  errno = 0;
601
0
  ERR_clear_error();
602
0
  wsi->tls.ssl = SSL_new(wsi->a.vhost->tls.ssl_ctx);
603
0
  if (wsi->tls.ssl == NULL) {
604
0
    lwsl_err("SSL_new failed: %d (errno %d)\n",
605
0
       lws_ssl_get_error(wsi, 0), errno);
606
607
0
    lws_tls_err_describe_clear();
608
0
    return 1;
609
0
  }
610
611
0
  SSL_set_ex_data(wsi->tls.ssl, openssl_websocket_private_data_index, wsi);
612
0
  SSL_set_fd(wsi->tls.ssl, (int)(lws_intptr_t)accept_fd);
613
614
#ifdef USE_WOLFSSL
615
#ifdef USE_OLD_CYASSL
616
  CyaSSL_set_using_nonblock(wsi->tls.ssl, 1);
617
#else
618
  wolfSSL_set_using_nonblock(wsi->tls.ssl, 1);
619
#endif
620
#else
621
622
0
  SSL_set_mode(wsi->tls.ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
623
0
           SSL_MODE_RELEASE_BUFFERS);
624
0
  bio = SSL_get_rbio(wsi->tls.ssl);
625
0
  if (bio)
626
0
    BIO_set_nbio(bio, 1); /* nonblocking */
627
0
  else
628
0
    lwsl_notice("NULL rbio\n");
629
0
  bio = SSL_get_wbio(wsi->tls.ssl);
630
0
  if (bio)
631
0
    BIO_set_nbio(bio, 1); /* nonblocking */
632
0
  else
633
0
    lwsl_notice("NULL rbio\n");
634
0
#endif
635
636
0
#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
637
0
    if (wsi->a.vhost->tls.ssl_info_event_mask)
638
0
      SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback);
639
0
#endif
640
641
0
  return 0;
642
0
}
643
644
enum lws_ssl_capable_status
645
lws_tls_server_abort_connection(struct lws *wsi)
646
0
{
647
0
  if (wsi->tls.use_ssl)
648
0
    SSL_shutdown(wsi->tls.ssl);
649
0
  SSL_free(wsi->tls.ssl);
650
651
0
  return LWS_SSL_CAPABLE_DONE;
652
0
}
653
654
enum lws_ssl_capable_status
655
lws_tls_server_accept(struct lws *wsi)
656
0
{
657
0
  struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
658
0
  union lws_tls_cert_info_results ir;
659
0
  int m, n;
660
661
0
  errno = 0;
662
0
  ERR_clear_error();
663
0
  n = SSL_accept(wsi->tls.ssl);
664
665
0
  wsi->skip_fallback = 1;
666
667
0
  if (n == 1) {
668
0
    n = lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_COMMON_NAME, &ir,
669
0
             sizeof(ir.ns.name));
670
0
    if (!n)
671
0
      lwsl_notice("%s: client cert CN '%s'\n", __func__,
672
0
            ir.ns.name);
673
0
    else
674
0
      lwsl_info("%s: no client cert CN\n", __func__);
675
676
0
    lws_openssl_describe_cipher(wsi);
677
678
0
    if (SSL_pending(wsi->tls.ssl) &&
679
0
        lws_dll2_is_detached(&wsi->tls.dll_pending_tls))
680
0
      lws_dll2_add_head(&wsi->tls.dll_pending_tls,
681
0
            &pt->tls.dll_pending_tls_owner);
682
683
0
    return LWS_SSL_CAPABLE_DONE;
684
0
  }
685
686
0
  m = lws_ssl_get_error(wsi, n);
687
0
  lws_tls_err_describe_clear();
688
689
0
  if (m == SSL_ERROR_SYSCALL || m == SSL_ERROR_SSL)
690
0
    return LWS_SSL_CAPABLE_ERROR;
691
692
0
  if (m == SSL_ERROR_WANT_READ ||
693
0
      (m != SSL_ERROR_ZERO_RETURN && SSL_want_read(wsi->tls.ssl))) {
694
0
    if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
695
0
      lwsl_info("%s: WANT_READ change_pollfd failed\n",
696
0
          __func__);
697
0
      return LWS_SSL_CAPABLE_ERROR;
698
0
    }
699
700
0
    lwsl_info("SSL_ERROR_WANT_READ: m %d\n", m);
701
0
    return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
702
0
  }
703
0
  if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) {
704
0
    lwsl_debug("%s: WANT_WRITE\n", __func__);
705
706
0
    if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) {
707
0
      lwsl_info("%s: WANT_WRITE change_pollfd failed\n",
708
0
          __func__);
709
0
      return LWS_SSL_CAPABLE_ERROR;
710
0
    }
711
0
    return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
712
0
  }
713
714
0
  return LWS_SSL_CAPABLE_ERROR;
715
0
}
716
717
#if defined(LWS_WITH_ACME)
718
static int
719
lws_tls_openssl_rsa_new_key(RSA **rsa, int bits)
720
{
721
  BIGNUM *bn = BN_new();
722
  int n;
723
724
  if (!bn)
725
    return 1;
726
727
  if (BN_set_word(bn, RSA_F4) != 1) {
728
    BN_free(bn);
729
    return 1;
730
  }
731
732
  *rsa = RSA_new();
733
  if (!*rsa) {
734
    BN_free(bn);
735
    return 1;
736
  }
737
738
  n = RSA_generate_key_ex(*rsa, bits, bn, NULL);
739
  BN_free(bn);
740
  if (n == 1)
741
    return 0;
742
743
  RSA_free(*rsa);
744
  *rsa = NULL;
745
746
  return 1;
747
}
748
749
struct lws_tls_ss_pieces {
750
  X509 *x509;
751
  EVP_PKEY *pkey;
752
  RSA *rsa;
753
};
754
755
int
756
lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a,
757
           const char *san_b)
758
{
759
  GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null();
760
  GENERAL_NAME *gen = NULL;
761
  ASN1_IA5STRING *ia5 = NULL;
762
  X509_NAME *name;
763
764
  if (!gens)
765
    return 1;
766
767
  vhost->tls.ss = lws_zalloc(sizeof(*vhost->tls.ss), "sni cert");
768
  if (!vhost->tls.ss) {
769
    GENERAL_NAMES_free(gens);
770
    return 1;
771
  }
772
773
  vhost->tls.ss->x509 = X509_new();
774
  if (!vhost->tls.ss->x509)
775
    goto bail;
776
777
  ASN1_INTEGER_set(X509_get_serialNumber(vhost->tls.ss->x509), 1);
778
  X509_gmtime_adj(X509_get_notBefore(vhost->tls.ss->x509), 0);
779
  X509_gmtime_adj(X509_get_notAfter(vhost->tls.ss->x509), 3600);
780
781
  vhost->tls.ss->pkey = EVP_PKEY_new();
782
  if (!vhost->tls.ss->pkey)
783
    goto bail0;
784
785
  if (lws_tls_openssl_rsa_new_key(&vhost->tls.ss->rsa, 4096))
786
    goto bail1;
787
788
  if (!EVP_PKEY_assign_RSA(vhost->tls.ss->pkey, vhost->tls.ss->rsa))
789
    goto bail2;
790
791
  X509_set_pubkey(vhost->tls.ss->x509, vhost->tls.ss->pkey);
792
793
  name = X509_get_subject_name(vhost->tls.ss->x509);
794
  X509_NAME_add_entry_by_txt(name, "C",  MBSTRING_ASC,
795
           (unsigned char *)"GB",          -1, -1, 0);
796
  X509_NAME_add_entry_by_txt(name, "O",  MBSTRING_ASC,
797
           (unsigned char *)"somecompany", -1, -1, 0);
798
  if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_UTF8,
799
           (unsigned char *)"temp.acme.invalid",
800
                   -1, -1, 0) != 1) {
801
    lwsl_notice("failed to add CN\n");
802
    goto bail2;
803
  }
804
  X509_set_issuer_name(vhost->tls.ss->x509, name);
805
806
  /* add the SAN payloads */
807
808
  gen = GENERAL_NAME_new();
809
  ia5 = ASN1_IA5STRING_new();
810
  if (!ASN1_STRING_set(ia5, san_a, -1)) {
811
    lwsl_notice("failed to set ia5\n");
812
    GENERAL_NAME_free(gen);
813
    goto bail2;
814
  }
815
  GENERAL_NAME_set0_value(gen, GEN_DNS, ia5);
816
  sk_GENERAL_NAME_push(gens, gen);
817
818
  if (X509_add1_ext_i2d(vhost->tls.ss->x509, NID_subject_alt_name,
819
          gens, 0, X509V3_ADD_APPEND) != 1)
820
    goto bail2;
821
822
  GENERAL_NAMES_free(gens);
823
824
  if (san_b && san_b[0]) {
825
    gens = sk_GENERAL_NAME_new_null();
826
    gen = GENERAL_NAME_new();
827
    ia5 = ASN1_IA5STRING_new();
828
    if (!ASN1_STRING_set(ia5, san_a, -1)) {
829
      lwsl_notice("failed to set ia5\n");
830
      GENERAL_NAME_free(gen);
831
      goto bail2;
832
    }
833
    GENERAL_NAME_set0_value(gen, GEN_DNS, ia5);
834
    sk_GENERAL_NAME_push(gens, gen);
835
836
    if (X509_add1_ext_i2d(vhost->tls.ss->x509, NID_subject_alt_name,
837
            gens, 0, X509V3_ADD_APPEND) != 1)
838
      goto bail2;
839
840
    GENERAL_NAMES_free(gens);
841
  }
842
843
  /* sign it with our private key */
844
  if (!X509_sign(vhost->tls.ss->x509, vhost->tls.ss->pkey, EVP_sha256()))
845
    goto bail2;
846
847
#if 0
848
  {/* useful to take a sample of a working cert for mbedtls to crib */
849
    FILE *fp = fopen("/tmp/acme-temp-cert", "w+");
850
851
    i2d_X509_fp(fp, vhost->tls.ss->x509);
852
    fclose(fp);
853
  }
854
#endif
855
856
  /* tell the vhost to use our crafted certificate */
857
  SSL_CTX_use_certificate(vhost->tls.ssl_ctx, vhost->tls.ss->x509);
858
  /* and to use our generated private key */
859
  SSL_CTX_use_PrivateKey(vhost->tls.ssl_ctx, vhost->tls.ss->pkey);
860
861
  return 0;
862
863
bail2:
864
  RSA_free(vhost->tls.ss->rsa);
865
bail1:
866
  EVP_PKEY_free(vhost->tls.ss->pkey);
867
bail0:
868
  X509_free(vhost->tls.ss->x509);
869
bail:
870
  lws_free(vhost->tls.ss);
871
  GENERAL_NAMES_free(gens);
872
873
  return 1;
874
}
875
876
void
877
lws_tls_acme_sni_cert_destroy(struct lws_vhost *vhost)
878
{
879
  if (!vhost->tls.ss)
880
    return;
881
882
  EVP_PKEY_free(vhost->tls.ss->pkey);
883
  X509_free(vhost->tls.ss->x509);
884
  lws_free_set_NULL(vhost->tls.ss);
885
}
886
887
static int
888
lws_tls_openssl_add_nid(X509_NAME *name, int nid, const char *value)
889
{
890
  X509_NAME_ENTRY *e;
891
  int n;
892
893
  if (!value || value[0] == '\0')
894
    value = "none";
895
896
  e = X509_NAME_ENTRY_create_by_NID(NULL, nid, MBSTRING_ASC,
897
            (unsigned char *)value, -1);
898
  if (!e)
899
    return 1;
900
  n = X509_NAME_add_entry(name, e, -1, 0);
901
  X509_NAME_ENTRY_free(e);
902
903
  return n != 1;
904
}
905
906
static int nid_list[] = {
907
  NID_countryName,    /* LWS_TLS_REQ_ELEMENT_COUNTRY */
908
  NID_stateOrProvinceName,  /* LWS_TLS_REQ_ELEMENT_STATE */
909
  NID_localityName,   /* LWS_TLS_REQ_ELEMENT_LOCALITY */
910
  NID_organizationName,   /* LWS_TLS_REQ_ELEMENT_ORGANIZATION */
911
  NID_commonName,     /* LWS_TLS_REQ_ELEMENT_COMMON_NAME */
912
  NID_subject_alt_name,   /* LWS_TLS_REQ_ELEMENT_SUBJECT_ALT_NAME */
913
  NID_pkcs9_emailAddress,   /* LWS_TLS_REQ_ELEMENT_EMAIL */
914
};
915
916
int
917
lws_tls_acme_sni_csr_create(struct lws_context *context, const char *elements[],
918
          uint8_t *csr, size_t csr_len, char **privkey_pem,
919
          size_t *privkey_len)
920
{
921
  uint8_t *csr_in = csr;
922
  RSA *rsakey;
923
  X509_REQ *req;
924
  X509_NAME *subj;
925
  EVP_PKEY *pkey;
926
  char *p, *end;
927
  BIO *bio;
928
  long bio_len;
929
  int n, ret = -1;
930
931
  if (lws_tls_openssl_rsa_new_key(&rsakey, 4096))
932
    return -1;
933
934
  pkey = EVP_PKEY_new();
935
  if (!pkey)
936
    goto bail0;
937
  if (!EVP_PKEY_set1_RSA(pkey, rsakey))
938
    goto bail1;
939
940
  req = X509_REQ_new();
941
  if (!req)
942
          goto bail1;
943
944
  X509_REQ_set_pubkey(req, pkey);
945
946
  subj = X509_NAME_new();
947
  if (!subj)
948
    goto bail2;
949
950
  for (n = 0; n < LWS_TLS_REQ_ELEMENT_COUNT; n++)
951
    if (elements[n] &&
952
      lws_tls_openssl_add_nid(subj, nid_list[n],
953
        elements[n])) {
954
        lwsl_notice("%s: failed to add element %d\n",
955
            __func__, n);
956
      goto bail3;
957
    }
958
959
  if (X509_REQ_set_subject_name(req, subj) != 1)
960
    goto bail3;
961
962
  if (elements[LWS_TLS_REQ_ELEMENT_SUBJECT_ALT_NAME]) {
963
    STACK_OF(X509_EXTENSION) *exts;
964
    X509_EXTENSION *ext;
965
    char san[256];
966
967
    exts = sk_X509_EXTENSION_new_null();
968
    if (!exts)
969
      goto bail3;
970
971
    lws_snprintf(san, sizeof(san), "DNS:%s,DNS:%s",
972
        elements[LWS_TLS_REQ_ELEMENT_COMMON_NAME],
973
        elements[LWS_TLS_REQ_ELEMENT_SUBJECT_ALT_NAME]);
974
975
    ext = X509V3_EXT_conf_nid(NULL, NULL, NID_subject_alt_name,
976
        san);
977
    if (!ext) {
978
      sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
979
      goto bail3;
980
    }
981
    sk_X509_EXTENSION_push(exts, ext);
982
983
    if (!X509_REQ_add_extensions(req, exts)) {
984
      sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
985
      goto bail3;
986
    }
987
    sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
988
  }
989
990
  if (!X509_REQ_sign(req, pkey, EVP_sha256()))
991
    goto bail3;
992
993
  /*
994
   * issue the CSR as PEM to a BIO, and translate to b64urlenc without
995
   * headers, trailers, or whitespace
996
   */
997
998
  bio = BIO_new(BIO_s_mem());
999
  if (!bio)
1000
    goto bail3;
1001
1002
  if (PEM_write_bio_X509_REQ(bio, req) != 1) {
1003
    BIO_free(bio);
1004
    goto bail3;
1005
  }
1006
1007
  bio_len = BIO_get_mem_data(bio, &p);
1008
  end = p + bio_len;
1009
1010
  /* strip the header line */
1011
  while (p < end && *p != '\n')
1012
    p++;
1013
1014
  while (p < end && csr_len) {
1015
    if (*p == '\n') {
1016
      p++;
1017
      continue;
1018
    }
1019
1020
    if (*p == '-')
1021
      break;
1022
1023
    if (*p == '+')
1024
      *csr++ = '-';
1025
    else
1026
      if (*p == '/')
1027
        *csr++ = '_';
1028
      else
1029
        *csr++ = (uint8_t)*p;
1030
    p++;
1031
    csr_len--;
1032
  }
1033
  BIO_free(bio);
1034
  if (!csr_len) {
1035
    lwsl_notice("%s: need %ld for CSR\n", __func__, bio_len);
1036
    goto bail3;
1037
  }
1038
1039
  /*
1040
   * Also return the private key as a PEM in memory
1041
   * (platform may not have a filesystem)
1042
   */
1043
  bio = BIO_new(BIO_s_mem());
1044
  if (!bio)
1045
    goto bail3;
1046
1047
  if (PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, 0, NULL) != 1) {
1048
    BIO_free(bio);
1049
    goto bail3;
1050
  }
1051
  bio_len = BIO_get_mem_data(bio, &p);
1052
  *privkey_pem = malloc((unsigned long)bio_len); /* malloc so user code can own / free */
1053
  *privkey_len = (size_t)bio_len;
1054
  if (!*privkey_pem) {
1055
    lwsl_notice("%s: need %ld for private key\n", __func__,
1056
          bio_len);
1057
    BIO_free(bio);
1058
    goto bail3;
1059
  }
1060
  memcpy(*privkey_pem, p, (unsigned int)(int)(long long)bio_len);
1061
  BIO_free(bio);
1062
1063
  ret = lws_ptr_diff(csr, csr_in);
1064
1065
bail3:
1066
  X509_NAME_free(subj);
1067
bail2:
1068
  X509_REQ_free(req);
1069
bail1:
1070
  EVP_PKEY_free(pkey);
1071
bail0:
1072
  RSA_free(rsakey);
1073
1074
  return ret;
1075
}
1076
#endif