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:
parent
c1a3defb88
commit
2eeec91d3d
7 changed files with 126 additions and 3 deletions
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue