Coverage Report

Created: 2025-08-03 06:52

/src/libwebsockets/lib/tls/openssl/openssl-server.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 "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
  SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_SINGLE_DH_USE);
524
0
  SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
525
526
0
  if (info->ssl_cipher_list)
527
0
    SSL_CTX_set_cipher_list(vhost->tls.ssl_ctx, info->ssl_cipher_list);
528
529
0
#if defined(LWS_HAVE_SSL_CTX_set_ciphersuites)
530
0
  if (info->tls1_3_plus_cipher_list)
531
0
    SSL_CTX_set_ciphersuites(vhost->tls.ssl_ctx,
532
0
           info->tls1_3_plus_cipher_list);
533
0
#endif
534
535
0
#if !defined(OPENSSL_NO_TLSEXT)
536
0
  SSL_CTX_set_tlsext_servername_callback(vhost->tls.ssl_ctx,
537
0
                 lws_ssl_server_name_cb);
538
0
  SSL_CTX_set_tlsext_servername_arg(vhost->tls.ssl_ctx, vhost->context);
539
0
#endif
540
541
0
  if (info->ssl_ca_filepath &&
542
#if defined(LWS_HAVE_SSL_CTX_load_verify_file)
543
      !SSL_CTX_load_verify_file(vhost->tls.ssl_ctx,
544
              info->ssl_ca_filepath)) {
545
#else
546
0
      !SSL_CTX_load_verify_locations(vhost->tls.ssl_ctx,
547
0
             info->ssl_ca_filepath, NULL)) {
548
0
#endif
549
0
    lwsl_err("%s: SSL_CTX_load_verify_locations unhappy\n",
550
0
       __func__);
551
0
  }
552
553
0
  SSL_OPT_TYPE ssl_options_set_value = (SSL_OPT_TYPE) info->ssl_options_set;
554
555
0
  if (info->ssl_options_set)
556
0
    SSL_CTX_set_options(vhost->tls.ssl_ctx, ssl_options_set_value);
557
558
0
#if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL)
559
560
/* SSL_clear_options introduced in 0.9.8m */
561
0
  SSL_OPT_TYPE ssl_options_clear_value = (SSL_OPT_TYPE) info->ssl_options_clear;
562
563
0
  if (info->ssl_options_clear) {
564
0
    SSL_CTX_clear_options(vhost->tls.ssl_ctx, ssl_options_clear_value);
565
0
  }
566
567
0
  lwsl_info(" SSL options 0x%lX\n",
568
0
      (unsigned long)SSL_CTX_get_options(vhost->tls.ssl_ctx));
569
0
#endif
570
571
0
  if (!vhost->tls.use_ssl ||
572
0
      (!info->ssl_cert_filepath && !info->server_ssl_cert_mem))
573
0
    return 0;
574
575
0
  lws_ssl_bind_passphrase(vhost->tls.ssl_ctx, 0, info);
576
577
0
  return lws_tls_server_certs_load(vhost, wsi, info->ssl_cert_filepath,
578
0
           info->ssl_private_key_filepath,
579
0
           info->server_ssl_cert_mem,
580
0
           info->server_ssl_cert_mem_len,
581
0
           info->server_ssl_private_key_mem,
582
0
           info->server_ssl_private_key_mem_len);
583
0
}
584
585
int
586
lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd)
587
0
{
588
0
#if !defined(USE_WOLFSSL)
589
0
  BIO *bio;
590
0
#endif
591
592
0
  errno = 0;
593
0
  ERR_clear_error();
594
0
  wsi->tls.ssl = SSL_new(wsi->a.vhost->tls.ssl_ctx);
595
0
  if (wsi->tls.ssl == NULL) {
596
0
    lwsl_err("SSL_new failed: %d (errno %d)\n",
597
0
       lws_ssl_get_error(wsi, 0), errno);
598
599
0
    lws_tls_err_describe_clear();
600
0
    return 1;
601
0
  }
602
603
0
  SSL_set_ex_data(wsi->tls.ssl, openssl_websocket_private_data_index, wsi);
604
0
  SSL_set_fd(wsi->tls.ssl, (int)(lws_intptr_t)accept_fd);
605
606
#ifdef USE_WOLFSSL
607
#ifdef USE_OLD_CYASSL
608
  CyaSSL_set_using_nonblock(wsi->tls.ssl, 1);
609
#else
610
  wolfSSL_set_using_nonblock(wsi->tls.ssl, 1);
611
#endif
612
#else
613
614
0
  SSL_set_mode(wsi->tls.ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
615
0
           SSL_MODE_RELEASE_BUFFERS);
616
0
  bio = SSL_get_rbio(wsi->tls.ssl);
617
0
  if (bio)
618
0
    BIO_set_nbio(bio, 1); /* nonblocking */
619
0
  else
620
0
    lwsl_notice("NULL rbio\n");
621
0
  bio = SSL_get_wbio(wsi->tls.ssl);
622
0
  if (bio)
623
0
    BIO_set_nbio(bio, 1); /* nonblocking */
624
0
  else
625
0
    lwsl_notice("NULL rbio\n");
626
0
#endif
627
628
0
#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
629
0
    if (wsi->a.vhost->tls.ssl_info_event_mask)
630
0
      SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback);
631
0
#endif
632
633
0
  return 0;
634
0
}
635
636
enum lws_ssl_capable_status
637
lws_tls_server_abort_connection(struct lws *wsi)
638
0
{
639
0
  if (wsi->tls.use_ssl)
640
0
    SSL_shutdown(wsi->tls.ssl);
641
0
  SSL_free(wsi->tls.ssl);
642
643
0
  return LWS_SSL_CAPABLE_DONE;
644
0
}
645
646
enum lws_ssl_capable_status
647
lws_tls_server_accept(struct lws *wsi)
648
0
{
649
0
  struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
650
0
  union lws_tls_cert_info_results ir;
651
0
  int m, n;
652
653
0
  errno = 0;
654
0
  ERR_clear_error();
655
0
  n = SSL_accept(wsi->tls.ssl);
656
657
0
  wsi->skip_fallback = 1;
658
659
0
  if (n == 1) {
660
0
    n = lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_COMMON_NAME, &ir,
661
0
             sizeof(ir.ns.name));
662
0
    if (!n)
663
0
      lwsl_notice("%s: client cert CN '%s'\n", __func__,
664
0
            ir.ns.name);
665
0
    else
666
0
      lwsl_info("%s: no client cert CN\n", __func__);
667
668
0
    lws_openssl_describe_cipher(wsi);
669
670
0
    if (SSL_pending(wsi->tls.ssl) &&
671
0
        lws_dll2_is_detached(&wsi->tls.dll_pending_tls))
672
0
      lws_dll2_add_head(&wsi->tls.dll_pending_tls,
673
0
            &pt->tls.dll_pending_tls_owner);
674
675
0
    return LWS_SSL_CAPABLE_DONE;
676
0
  }
677
678
0
  m = lws_ssl_get_error(wsi, n);
679
0
  lws_tls_err_describe_clear();
680
681
0
  if (m == SSL_ERROR_SYSCALL || m == SSL_ERROR_SSL)
682
0
    return LWS_SSL_CAPABLE_ERROR;
683
684
0
  if (m == SSL_ERROR_WANT_READ ||
685
0
      (m != SSL_ERROR_ZERO_RETURN && SSL_want_read(wsi->tls.ssl))) {
686
0
    if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
687
0
      lwsl_info("%s: WANT_READ change_pollfd failed\n",
688
0
          __func__);
689
0
      return LWS_SSL_CAPABLE_ERROR;
690
0
    }
691
692
0
    lwsl_info("SSL_ERROR_WANT_READ: m %d\n", m);
693
0
    return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
694
0
  }
695
0
  if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) {
696
0
    lwsl_debug("%s: WANT_WRITE\n", __func__);
697
698
0
    if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) {
699
0
      lwsl_info("%s: WANT_WRITE change_pollfd failed\n",
700
0
          __func__);
701
0
      return LWS_SSL_CAPABLE_ERROR;
702
0
    }
703
0
    return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
704
0
  }
705
706
0
  return LWS_SSL_CAPABLE_ERROR;
707
0
}
708
709
#if defined(LWS_WITH_ACME)
710
static int
711
lws_tls_openssl_rsa_new_key(RSA **rsa, int bits)
712
{
713
  BIGNUM *bn = BN_new();
714
  int n;
715
716
  if (!bn)
717
    return 1;
718
719
  if (BN_set_word(bn, RSA_F4) != 1) {
720
    BN_free(bn);
721
    return 1;
722
  }
723
724
  *rsa = RSA_new();
725
  if (!*rsa) {
726
    BN_free(bn);
727
    return 1;
728
  }
729
730
  n = RSA_generate_key_ex(*rsa, bits, bn, NULL);
731
  BN_free(bn);
732
  if (n == 1)
733
    return 0;
734
735
  RSA_free(*rsa);
736
  *rsa = NULL;
737
738
  return 1;
739
}
740
741
struct lws_tls_ss_pieces {
742
  X509 *x509;
743
  EVP_PKEY *pkey;
744
  RSA *rsa;
745
};
746
747
int
748
lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a,
749
           const char *san_b)
750
{
751
  GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null();
752
  GENERAL_NAME *gen = NULL;
753
  ASN1_IA5STRING *ia5 = NULL;
754
  X509_NAME *name;
755
756
  if (!gens)
757
    return 1;
758
759
  vhost->tls.ss = lws_zalloc(sizeof(*vhost->tls.ss), "sni cert");
760
  if (!vhost->tls.ss) {
761
    GENERAL_NAMES_free(gens);
762
    return 1;
763
  }
764
765
  vhost->tls.ss->x509 = X509_new();
766
  if (!vhost->tls.ss->x509)
767
    goto bail;
768
769
  ASN1_INTEGER_set(X509_get_serialNumber(vhost->tls.ss->x509), 1);
770
  X509_gmtime_adj(X509_get_notBefore(vhost->tls.ss->x509), 0);
771
  X509_gmtime_adj(X509_get_notAfter(vhost->tls.ss->x509), 3600);
772
773
  vhost->tls.ss->pkey = EVP_PKEY_new();
774
  if (!vhost->tls.ss->pkey)
775
    goto bail0;
776
777
  if (lws_tls_openssl_rsa_new_key(&vhost->tls.ss->rsa, 4096))
778
    goto bail1;
779
780
  if (!EVP_PKEY_assign_RSA(vhost->tls.ss->pkey, vhost->tls.ss->rsa))
781
    goto bail2;
782
783
  X509_set_pubkey(vhost->tls.ss->x509, vhost->tls.ss->pkey);
784
785
  name = X509_get_subject_name(vhost->tls.ss->x509);
786
  X509_NAME_add_entry_by_txt(name, "C",  MBSTRING_ASC,
787
           (unsigned char *)"GB",          -1, -1, 0);
788
  X509_NAME_add_entry_by_txt(name, "O",  MBSTRING_ASC,
789
           (unsigned char *)"somecompany", -1, -1, 0);
790
  if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_UTF8,
791
           (unsigned char *)"temp.acme.invalid",
792
                   -1, -1, 0) != 1) {
793
    lwsl_notice("failed to add CN\n");
794
    goto bail2;
795
  }
796
  X509_set_issuer_name(vhost->tls.ss->x509, name);
797
798
  /* add the SAN payloads */
799
800
  gen = GENERAL_NAME_new();
801
  ia5 = ASN1_IA5STRING_new();
802
  if (!ASN1_STRING_set(ia5, san_a, -1)) {
803
    lwsl_notice("failed to set ia5\n");
804
    GENERAL_NAME_free(gen);
805
    goto bail2;
806
  }
807
  GENERAL_NAME_set0_value(gen, GEN_DNS, ia5);
808
  sk_GENERAL_NAME_push(gens, gen);
809
810
  if (X509_add1_ext_i2d(vhost->tls.ss->x509, NID_subject_alt_name,
811
          gens, 0, X509V3_ADD_APPEND) != 1)
812
    goto bail2;
813
814
  GENERAL_NAMES_free(gens);
815
816
  if (san_b && san_b[0]) {
817
    gens = sk_GENERAL_NAME_new_null();
818
    gen = GENERAL_NAME_new();
819
    ia5 = ASN1_IA5STRING_new();
820
    if (!ASN1_STRING_set(ia5, san_a, -1)) {
821
      lwsl_notice("failed to set ia5\n");
822
      GENERAL_NAME_free(gen);
823
      goto bail2;
824
    }
825
    GENERAL_NAME_set0_value(gen, GEN_DNS, ia5);
826
    sk_GENERAL_NAME_push(gens, gen);
827
828
    if (X509_add1_ext_i2d(vhost->tls.ss->x509, NID_subject_alt_name,
829
            gens, 0, X509V3_ADD_APPEND) != 1)
830
      goto bail2;
831
832
    GENERAL_NAMES_free(gens);
833
  }
834
835
  /* sign it with our private key */
836
  if (!X509_sign(vhost->tls.ss->x509, vhost->tls.ss->pkey, EVP_sha256()))
837
    goto bail2;
838
839
#if 0
840
  {/* useful to take a sample of a working cert for mbedtls to crib */
841
    FILE *fp = fopen("/tmp/acme-temp-cert", "w+");
842
843
    i2d_X509_fp(fp, vhost->tls.ss->x509);
844
    fclose(fp);
845
  }
846
#endif
847
848
  /* tell the vhost to use our crafted certificate */
849
  SSL_CTX_use_certificate(vhost->tls.ssl_ctx, vhost->tls.ss->x509);
850
  /* and to use our generated private key */
851
  SSL_CTX_use_PrivateKey(vhost->tls.ssl_ctx, vhost->tls.ss->pkey);
852
853
  return 0;
854
855
bail2:
856
  RSA_free(vhost->tls.ss->rsa);
857
bail1:
858
  EVP_PKEY_free(vhost->tls.ss->pkey);
859
bail0:
860
  X509_free(vhost->tls.ss->x509);
861
bail:
862
  lws_free(vhost->tls.ss);
863
  GENERAL_NAMES_free(gens);
864
865
  return 1;
866
}
867
868
void
869
lws_tls_acme_sni_cert_destroy(struct lws_vhost *vhost)
870
{
871
  if (!vhost->tls.ss)
872
    return;
873
874
  EVP_PKEY_free(vhost->tls.ss->pkey);
875
  X509_free(vhost->tls.ss->x509);
876
  lws_free_set_NULL(vhost->tls.ss);
877
}
878
879
static int
880
lws_tls_openssl_add_nid(X509_NAME *name, int nid, const char *value)
881
{
882
  X509_NAME_ENTRY *e;
883
  int n;
884
885
  if (!value || value[0] == '\0')
886
    value = "none";
887
888
  e = X509_NAME_ENTRY_create_by_NID(NULL, nid, MBSTRING_ASC,
889
            (unsigned char *)value, -1);
890
  if (!e)
891
    return 1;
892
  n = X509_NAME_add_entry(name, e, -1, 0);
893
  X509_NAME_ENTRY_free(e);
894
895
  return n != 1;
896
}
897
898
static int nid_list[] = {
899
  NID_countryName,    /* LWS_TLS_REQ_ELEMENT_COUNTRY */
900
  NID_stateOrProvinceName,  /* LWS_TLS_REQ_ELEMENT_STATE */
901
  NID_localityName,   /* LWS_TLS_REQ_ELEMENT_LOCALITY */
902
  NID_organizationName,   /* LWS_TLS_REQ_ELEMENT_ORGANIZATION */
903
  NID_commonName,     /* LWS_TLS_REQ_ELEMENT_COMMON_NAME */
904
  NID_subject_alt_name,   /* LWS_TLS_REQ_ELEMENT_SUBJECT_ALT_NAME */
905
  NID_pkcs9_emailAddress,   /* LWS_TLS_REQ_ELEMENT_EMAIL */
906
};
907
908
int
909
lws_tls_acme_sni_csr_create(struct lws_context *context, const char *elements[],
910
          uint8_t *csr, size_t csr_len, char **privkey_pem,
911
          size_t *privkey_len)
912
{
913
  uint8_t *csr_in = csr;
914
  RSA *rsakey;
915
  X509_REQ *req;
916
  X509_NAME *subj;
917
  EVP_PKEY *pkey;
918
  char *p, *end;
919
  BIO *bio;
920
  long bio_len;
921
  int n, ret = -1;
922
923
  if (lws_tls_openssl_rsa_new_key(&rsakey, 4096))
924
    return -1;
925
926
  pkey = EVP_PKEY_new();
927
  if (!pkey)
928
    goto bail0;
929
  if (!EVP_PKEY_set1_RSA(pkey, rsakey))
930
    goto bail1;
931
932
  req = X509_REQ_new();
933
  if (!req)
934
          goto bail1;
935
936
  X509_REQ_set_pubkey(req, pkey);
937
938
  subj = X509_NAME_new();
939
  if (!subj)
940
    goto bail2;
941
942
  for (n = 0; n < LWS_TLS_REQ_ELEMENT_COUNT; n++)
943
    if (elements[n] &&
944
      lws_tls_openssl_add_nid(subj, nid_list[n],
945
        elements[n])) {
946
        lwsl_notice("%s: failed to add element %d\n",
947
            __func__, n);
948
      goto bail3;
949
    }
950
951
  if (X509_REQ_set_subject_name(req, subj) != 1)
952
    goto bail3;
953
954
  if (elements[LWS_TLS_REQ_ELEMENT_SUBJECT_ALT_NAME]) {
955
    STACK_OF(X509_EXTENSION) *exts;
956
    X509_EXTENSION *ext;
957
    char san[256];
958
959
    exts = sk_X509_EXTENSION_new_null();
960
    if (!exts)
961
      goto bail3;
962
963
    lws_snprintf(san, sizeof(san), "DNS:%s,DNS:%s",
964
        elements[LWS_TLS_REQ_ELEMENT_COMMON_NAME],
965
        elements[LWS_TLS_REQ_ELEMENT_SUBJECT_ALT_NAME]);
966
967
    ext = X509V3_EXT_conf_nid(NULL, NULL, NID_subject_alt_name,
968
        san);
969
    if (!ext) {
970
      sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
971
      goto bail3;
972
    }
973
    sk_X509_EXTENSION_push(exts, ext);
974
975
    if (!X509_REQ_add_extensions(req, exts)) {
976
      sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
977
      goto bail3;
978
    }
979
    sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
980
  }
981
982
  if (!X509_REQ_sign(req, pkey, EVP_sha256()))
983
    goto bail3;
984
985
  /*
986
   * issue the CSR as PEM to a BIO, and translate to b64urlenc without
987
   * headers, trailers, or whitespace
988
   */
989
990
  bio = BIO_new(BIO_s_mem());
991
  if (!bio)
992
    goto bail3;
993
994
  if (PEM_write_bio_X509_REQ(bio, req) != 1) {
995
    BIO_free(bio);
996
    goto bail3;
997
  }
998
999
  bio_len = BIO_get_mem_data(bio, &p);
1000
  end = p + bio_len;
1001
1002
  /* strip the header line */
1003
  while (p < end && *p != '\n')
1004
    p++;
1005
1006
  while (p < end && csr_len) {
1007
    if (*p == '\n') {
1008
      p++;
1009
      continue;
1010
    }
1011
1012
    if (*p == '-')
1013
      break;
1014
1015
    if (*p == '+')
1016
      *csr++ = '-';
1017
    else
1018
      if (*p == '/')
1019
        *csr++ = '_';
1020
      else
1021
        *csr++ = (uint8_t)*p;
1022
    p++;
1023
    csr_len--;
1024
  }
1025
  BIO_free(bio);
1026
  if (!csr_len) {
1027
    lwsl_notice("%s: need %ld for CSR\n", __func__, bio_len);
1028
    goto bail3;
1029
  }
1030
1031
  /*
1032
   * Also return the private key as a PEM in memory
1033
   * (platform may not have a filesystem)
1034
   */
1035
  bio = BIO_new(BIO_s_mem());
1036
  if (!bio)
1037
    goto bail3;
1038
1039
  if (PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, 0, NULL) != 1) {
1040
    BIO_free(bio);
1041
    goto bail3;
1042
  }
1043
  bio_len = BIO_get_mem_data(bio, &p);
1044
  *privkey_pem = malloc((unsigned long)bio_len); /* malloc so user code can own / free */
1045
  *privkey_len = (size_t)bio_len;
1046
  if (!*privkey_pem) {
1047
    lwsl_notice("%s: need %ld for private key\n", __func__,
1048
          bio_len);
1049
    BIO_free(bio);
1050
    goto bail3;
1051
  }
1052
  memcpy(*privkey_pem, p, (unsigned int)(int)(long long)bio_len);
1053
  BIO_free(bio);
1054
1055
  ret = lws_ptr_diff(csr, csr_in);
1056
1057
bail3:
1058
  X509_NAME_free(subj);
1059
bail2:
1060
  X509_REQ_free(req);
1061
bail1:
1062
  EVP_PKEY_free(pkey);
1063
bail0:
1064
  RSA_free(rsakey);
1065
1066
  return ret;
1067
}
1068
#endif