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

tls: lws_system per-connection client certs

Now the generic lws_system blobs can cover client certs + key, let's
add support for applying one of the blob sets to a specific client
connection (rather than doing it via the vhost).
This commit is contained in:
Andy Green 2019-12-08 03:04:03 +00:00
parent c1a3defb88
commit 2eeec91d3d
7 changed files with 126 additions and 3 deletions

View file

@ -145,6 +145,11 @@ struct lws_client_connect_info {
* Currently only the idle parts are applied to the connection.
*/
uint8_t sys_tls_client_cert;
/**< 0 means no client cert. 1+ means apply lws_system client cert 0+
* to the client connection.
*/
/* Add new things just above here ---^
* This is part of the ABI, don't needlessly break compatibility
*

View file

@ -143,6 +143,7 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
wsi->pending_timeout = NO_PENDING_TIMEOUT;
wsi->position_in_fds_table = LWS_NO_FDS_POS;
wsi->ocport = wsi->c_port = i->port;
wsi->sys_tls_client_cert = i->sys_tls_client_cert;
wsi->protocol = &wsi->vhost->protocols[0];
wsi->client_pipeline = !!(i->ssl_connection & LCCSCF_PIPELINE);

View file

@ -778,6 +778,7 @@ struct lws {
#if defined(LWS_WITH_CLIENT)
char chunk_parser; /* enum lws_chunk_parser */
uint8_t addrinfo_idx;
uint8_t sys_tls_client_cert;
#endif
#if defined(LWS_WITH_CGI) || defined(LWS_WITH_CLIENT)
char reason_bf; /* internal writeable callback reason bitfield */

View file

@ -102,7 +102,58 @@ lws_ssl_client_bio_create(struct lws *wsi)
SSL_set_fd(wsi->tls.ssl, wsi->desc.sockfd);
if (wsi->sys_tls_client_cert) {
lws_system_blob_t *b = lws_system_get_blob(wsi->context,
LWS_SYSBLOB_TYPE_CLIENT_CERT_DER,
wsi->sys_tls_client_cert - 1);
const uint8_t *data;
size_t size;
if (!b)
goto no_client_cert;
/*
* Set up the per-connection client cert
*/
size = lws_system_blob_get_size(b);
if (!size)
goto no_client_cert;
if (lws_system_blob_get_single_ptr(b, &data))
goto no_client_cert;
if (SSL_use_certificate_ASN1(wsi->tls.ssl, data, size) != 1)
goto no_client_cert;
b = lws_system_get_blob(wsi->context,
LWS_SYSBLOB_TYPE_CLIENT_KEY_DER,
wsi->sys_tls_client_cert - 1);
if (!b)
goto no_client_cert;
size = lws_system_blob_get_size(b);
if (!size)
goto no_client_cert;
if (lws_system_blob_get_single_ptr(b, &data))
goto no_client_cert;
if (SSL_use_PrivateKey_ASN1(0, wsi->tls.ssl, data, size) != 1)
goto no_client_cert;
/* no wrapper api for check key */
lwsl_notice("%s: set system client cert %u\n", __func__,
wsi->sys_tls_client_cert - 1);
}
return 0;
no_client_cert:
lwsl_err("%s: unable to set up system client cert %d\n", __func__,
wsi->sys_tls_client_cert - 1);
return 1;
}
int ERR_get_error(void)

View file

@ -99,7 +99,8 @@ int SSL_add_client_CA(SSL *ssl, X509 *x);
* 1 : OK
*
*/
int SSL_use_certificate_ASN1(SSL *ssl, int len, const unsigned char *d);
int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
const char *X509_verify_cert_error_string(long n);

View file

@ -286,8 +286,7 @@ failed1:
/**
* @brief load certification into the SSL
*/
int SSL_use_certificate_ASN1(SSL *ssl, int len,
const unsigned char *d)
int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len)
{
int ret;
X509 *x;

View file

@ -279,7 +279,72 @@ lws_ssl_client_bio_create(struct lws *wsi)
SSL_set_ex_data(wsi->tls.ssl, openssl_websocket_private_data_index,
wsi);
if (wsi->sys_tls_client_cert) {
lws_system_blob_t *b = lws_system_get_blob(wsi->context,
LWS_SYSBLOB_TYPE_CLIENT_CERT_DER,
wsi->sys_tls_client_cert - 1);
const uint8_t *data;
size_t size;
if (!b)
goto no_client_cert;
/*
* Set up the per-connection client cert
*/
size = lws_system_blob_get_size(b);
if (!size)
goto no_client_cert;
if (lws_system_blob_get_single_ptr(b, &data))
goto no_client_cert;
if (SSL_use_certificate_ASN1(wsi->tls.ssl, data, size) != 1) {
lwsl_err("%s: use_certificate failed\n", __func__);
lws_tls_err_describe_clear();
goto no_client_cert;
}
b = lws_system_get_blob(wsi->context,
LWS_SYSBLOB_TYPE_CLIENT_KEY_DER,
wsi->sys_tls_client_cert - 1);
if (!b)
goto no_client_cert;
size = lws_system_blob_get_size(b);
if (!size)
goto no_client_cert;
if (lws_system_blob_get_single_ptr(b, &data))
goto no_client_cert;
if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, wsi->tls.ssl,
data, size) != 1 &&
SSL_use_PrivateKey_ASN1(EVP_PKEY_EC, wsi->tls.ssl,
data, size) != 1) {
lwsl_err("%s: use_privkey failed\n", __func__);
lws_tls_err_describe_clear();
goto no_client_cert;
}
if (SSL_check_private_key(wsi->tls.ssl) != 1) {
lwsl_err("Private SSL key doesn't match cert\n");
lws_tls_err_describe_clear();
return 1;
}
lwsl_notice("%s: set system client cert %u\n", __func__,
wsi->sys_tls_client_cert - 1);
}
return 0;
no_client_cert:
lwsl_err("%s: unable to set up system client cert %d\n", __func__,
wsi->sys_tls_client_cert - 1);
return 1;
}
enum lws_ssl_capable_status