1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

mbedtls: improve SNI for client certs

This commit is contained in:
Andy Green 2017-11-06 06:28:55 +08:00
parent ad07d95026
commit b06665b851
7 changed files with 89 additions and 17 deletions

View file

@ -2469,8 +2469,7 @@ lws_ssl_get_error_string(int status, int ret, char *buf, size_t len);
*/
LWS_EXTERN int
lws_tls_server_client_cert_verify_config(struct lws_context_creation_info *info,
struct lws_vhost *vh);
lws_tls_server_client_cert_verify_config(struct lws_vhost *vh);
LWS_EXTERN int
lws_tls_server_vhost_backend_init(struct lws_context_creation_info *info,
struct lws_vhost *vhost, struct lws *wsi);

View file

@ -86,7 +86,7 @@ lws_context_init_server_ssl(struct lws_context_creation_info *info,
if (lws_tls_server_vhost_backend_init(info, vhost, &wsi))
return -1;
lws_tls_server_client_cert_verify_config(info, vhost);
lws_tls_server_client_cert_verify_config(vhost);
vhost->protocols[0].callback(&wsi,
LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,

View file

@ -23,20 +23,31 @@
#include <mbedtls/x509_csr.h>
int
lws_tls_server_client_cert_verify_config(struct lws_context_creation_info *info,
struct lws_vhost *vh)
lws_tls_server_client_cert_verify_config(struct lws_vhost *vh)
{
int verify_options = SSL_VERIFY_PEER;
/* as a server, are we requiring clients to identify themselves? */
if (!lws_check_opt(info->options,
LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT))
if (!lws_check_opt(vh->options,
LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT)) {
lwsl_notice("no client cert required\n");
return 0;
}
if (lws_check_opt(info->options, LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED))
/*
* The wrapper has this messed-up mapping:
*
* else if (ctx->verify_mode == SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
* mode = MBEDTLS_SSL_VERIFY_OPTIONAL;
*
* ie the meaning is inverted. So where we should test for ! we don't
*/
if (lws_check_opt(vh->options, LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED))
verify_options = SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
lwsl_notice("%s: vh %s requires client cert %d\n", __func__, vh->name,
verify_options);
SSL_CTX_set_verify(vh->ssl_ctx, verify_options, NULL);
return 0;
@ -78,7 +89,8 @@ lws_mbedtls_sni_cb(void *arg, mbedtls_ssl_context *mbedtls_ctx,
return 0;
}
lwsl_info("SNI: Found: %s:%d\n", servername, vh->listen_port);
lwsl_info("SNI: Found: %s:%d at vhost '%s'\n", servername,
vh->listen_port, vhost->name);
/* select the ssl ctx from the selected vhost for this conn */
SSL_set_SSL_CTX(ssl, vhost->ssl_ctx);
@ -192,6 +204,8 @@ lws_tls_server_vhost_backend_init(struct lws_context_creation_info *info,
struct lws_vhost *vhost, struct lws *wsi)
{
const SSL_METHOD *method = TLS_server_method();
uint8_t *p;
lws_filepos_t flen;
vhost->ssl_ctx = SSL_CTX_new(method); /* create context */
if (!vhost->ssl_ctx) {
@ -202,6 +216,26 @@ lws_tls_server_vhost_backend_init(struct lws_context_creation_info *info,
if (!vhost->use_ssl || !info->ssl_cert_filepath)
return 0;
if (info->ssl_ca_filepath) {
lwsl_notice("%s: vh %s: loading CA filepath %s\n", __func__,
vhost->name, info->ssl_ca_filepath);
if (lws_tls_alloc_pem_to_der_file(vhost->context,
info->ssl_ca_filepath, NULL, 0, &p, &flen)) {
lwsl_err("couldn't find client CA file %s\n",
info->ssl_ca_filepath);
return 1;
}
if (SSL_CTX_add_client_CA_ASN1(vhost->ssl_ctx, (int)flen, p) != 1) {
lwsl_err("%s: SSL_CTX_add_client_CA_ASN1 unhappy\n",
__func__);
free(p);
return 1;
}
free(p);
}
return lws_tls_server_certs_load(vhost, wsi,
info->ssl_cert_filepath,
info->ssl_private_key_filepath,

View file

@ -46,6 +46,9 @@
void SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx);
int SSL_CTX_add_client_CA_ASN1(SSL_CTX *ssl, int len,
const unsigned char *d);
SSL *SSL_SSL_from_mbedtls_ssl_context(mbedtls_ssl_context *msc);
/**

View file

@ -166,6 +166,28 @@ int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x)
return 1;
}
/**
* @brief add CA client certification into the SSL
*/
int SSL_CTX_add_client_CA_ASN1(SSL_CTX *ctx, int len,
const unsigned char *d)
{
X509 *x;
x = d2i_X509(NULL, d, len);
if (!x) {
SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_X509() return NULL");
return 0;
}
SSL_ASSERT1(ctx);
X509_free(ctx->client_CA);
ctx->client_CA = x;
return 1;
}
/**
* @brief add CA client certification into the SSL
*/

View file

@ -823,17 +823,32 @@ void SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx)
{
struct ssl_pm *ssl_pm = ssl->ssl_pm;
struct x509_pm *x509_pm = (struct x509_pm *)ctx->cert->x509->x509_pm;
struct x509_pm *x509_pm_ca = (struct x509_pm *)ctx->client_CA->x509_pm;
struct pkey_pm *pkey_pm = (struct pkey_pm *)ctx->cert->pkey->pkey_pm;
int mode;
if (ssl->cert)
ssl_cert_free(ssl->cert);
ssl->ctx = ctx;
ssl->cert = __ssl_cert_new(ctx->cert);
if (ctx->verify_mode == SSL_VERIFY_PEER)
mode = MBEDTLS_SSL_VERIFY_REQUIRED;
else if (ctx->verify_mode == SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
mode = MBEDTLS_SSL_VERIFY_OPTIONAL;
else if (ctx->verify_mode == SSL_VERIFY_CLIENT_ONCE)
mode = MBEDTLS_SSL_VERIFY_UNSET;
else
mode = MBEDTLS_SSL_VERIFY_NONE;
// printf("ssl: %p, client ca x509_crt %p, mbedtls mode %d\n", ssl, x509_pm_ca->x509_crt, mode);
/* apply new ctx cert to ssl */
mbedtls_ssl_set_hs_own_cert(&ssl_pm->ssl, x509_pm->x509_crt, pkey_pm->pkey);
mbedtls_ssl_set_hs_authmode(&ssl_pm->ssl, MBEDTLS_SSL_VERIFY_NONE);
mbedtls_ssl_set_hs_ca_chain(&ssl_pm->ssl, x509_pm->x509_crt, NULL);
ssl->verify_mode = ctx->verify_mode;
mbedtls_ssl_set_hs_ca_chain(&ssl_pm->ssl, x509_pm_ca->x509_crt, NULL);
mbedtls_ssl_set_hs_own_cert(&ssl_pm->ssl, x509_pm->x509_crt, pkey_pm->pkey);
mbedtls_ssl_set_hs_authmode(&ssl_pm->ssl, mode);
}

View file

@ -58,18 +58,17 @@ OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
}
int
lws_tls_server_client_cert_verify_config(struct lws_context_creation_info *info,
struct lws_vhost *vh)
lws_tls_server_client_cert_verify_config(struct lws_vhost *vh)
{
int verify_options = SSL_VERIFY_PEER;
/* as a server, are we requiring clients to identify themselves? */
if (!lws_check_opt(info->options,
if (!lws_check_opt(vh->options,
LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT))
return 0;
if (!lws_check_opt(info->options,
if (!lws_check_opt(vh->options,
LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED))
verify_options |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;