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

windows: openssl: load certificates from certificate store

This commit is contained in:
Curi0 2021-03-12 11:21:30 +05:30 committed by Andy Green
parent a7f7053591
commit dbc89c88ec
7 changed files with 185 additions and 2 deletions

View file

@ -920,6 +920,9 @@ lws_plat_ntpclient_config(struct lws_context *context);
int int
lws_plat_ifname_to_hwaddr(int fd, const char *ifname, uint8_t *hwaddr, int len); lws_plat_ifname_to_hwaddr(int fd, const char *ifname, uint8_t *hwaddr, int len);
int
lws_plat_vhost_tls_client_ctx_init(struct lws_vhost *vhost);
int int
lws_check_byte_utf8(unsigned char state, unsigned char c); lws_check_byte_utf8(unsigned char state, unsigned char c);
int LWS_WARN_UNUSED_RESULT int LWS_WARN_UNUSED_RESULT

View file

@ -324,6 +324,12 @@ lws_plat_ifconfig(int fd, lws_dhcpc_ifstate_t *is)
return -1; return -1;
} }
int
lws_plat_vhost_tls_client_ctx_init(struct lws_vhost *vhost)
{
return 0;
}
#if defined(LWS_WITH_MBEDTLS) #if defined(LWS_WITH_MBEDTLS)
int int
lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len)

View file

@ -262,6 +262,12 @@ lws_plat_set_socket_options_ip(int fd, uint8_t pri, unsigned int lws_flags)
return 0; return 0;
} }
int
lws_plat_vhost_tls_client_ctx_init(struct lws_vhost *vhost)
{
return 0;
}
#if defined(LWS_WITH_MBEDTLS) #if defined(LWS_WITH_MBEDTLS)
int int
lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len)

View file

@ -543,6 +543,12 @@ lws_plat_ifconfig(int fd, lws_dhcpc_ifstate_t *is)
#endif #endif
} }
int
lws_plat_vhost_tls_client_ctx_init(struct lws_vhost *vhost)
{
return 0;
}
#if defined(LWS_WITH_MBEDTLS) #if defined(LWS_WITH_MBEDTLS)
int int
lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len)

View file

@ -68,6 +68,10 @@
#include <afunix.h> #include <afunix.h>
#endif #endif
#if defined(LWS_WITH_TLS)
#include <wincrypt.h>
#endif
#if defined(LWS_HAVE_PTHREAD_H) #if defined(LWS_HAVE_PTHREAD_H)
#define lws_mutex_t pthread_mutex_t #define lws_mutex_t pthread_mutex_t
#define lws_mutex_init(x) pthread_mutex_init(&(x), NULL) #define lws_mutex_init(x) pthread_mutex_init(&(x), NULL)

View file

@ -1,7 +1,7 @@
/* /*
* libwebsockets - small server side websockets and web server implementation * libwebsockets - small server side websockets and web server implementation
* *
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to * of this software and associated documentation files (the "Software"), to
@ -140,7 +140,6 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
lwsl_warn("setsockopt TCP_NODELAY 1 failed with error %d\n", error); lwsl_warn("setsockopt TCP_NODELAY 1 failed with error %d\n", error);
} }
return lws_plat_set_nonblocking(fd); return lws_plat_set_nonblocking(fd);
} }
@ -242,6 +241,163 @@ lws_plat_change_pollfd(struct lws_context *context, struct lws *wsi,
return 0; return 0;
} }
int
lws_plat_vhost_tls_client_ctx_init(struct lws_vhost *vhost)
{
#if !defined(LWS_WITH_MBEDTLS) && defined(LWS_SSL_CLIENT_USE_OS_CA_CERTS)
PCCERT_CONTEXT pcc = NULL;
CERT_ENHKEY_USAGE* ceu = NULL;
DWORD ceu_alloc = 0;
X509_STORE* store;
HCERTSTORE hStore;
int imps = 0;
if (lws_check_opt(vhost->options,
LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS))
return 0;
/*
* Windows Trust Store code adapted from curl (MIT) openssl.c
* https://github.com/warmcat/libwebsockets/pull/2233
*/
store = SSL_CTX_get_cert_store(vhost->tls.ssl_client_ctx);
hStore = CertOpenSystemStore((HCRYPTPROV_LEGACY)NULL, TEXT("ROOT"));
if (!hStore) {
lwsl_notice("%s: no store\n", __func__);
return 1;
}
do {
const unsigned char* ecert;
char cert_name[256];
DWORD req_size = 0;
BYTE key_usage[2];
FILETIME ft;
X509* x509;
pcc = CertEnumCertificatesInStore(hStore, pcc);
if (!pcc)
break;
if (!CertGetNameStringA(pcc, CERT_NAME_SIMPLE_DISPLAY_TYPE,
0, NULL, cert_name, sizeof(cert_name)))
strcpy(cert_name, "Unknown");
lwsl_debug("%s: Checking cert \"%s\"\n", __func__, cert_name);
ecert = (const unsigned char*)pcc->pbCertEncoded;
if (!ecert)
continue;
GetSystemTimeAsFileTime(&ft);
if (CompareFileTime(&pcc->pCertInfo->NotBefore, &ft) > 0 ||
CompareFileTime(&ft, &pcc->pCertInfo->NotAfter) > 0)
continue;
/* If key usage exists check for signing attribute */
if (CertGetIntendedKeyUsage(pcc->dwCertEncodingType,
pcc->pCertInfo,
key_usage, sizeof(key_usage))) {
if (!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
continue;
} else
if (GetLastError())
continue;
/*
* If enhanced key usage exists check for server auth attribute.
*
* Note "In a Microsoft environment, a certificate might also
* have EKU extended properties that specify valid uses for the
* certificate."
* The call below checks both, and behavior varies depending on
* what is found. For more details see CertGetEnhancedKeyUsage
* doc.
*/
if (!CertGetEnhancedKeyUsage(pcc, 0, NULL, &req_size))
continue;
if (req_size && req_size > ceu_alloc) {
void* tmp = lws_realloc(ceu, req_size, __func__);
if (!tmp) {
lwsl_err("%s: OOM", __func__);
break;
}
ceu = (CERT_ENHKEY_USAGE*)tmp;
ceu_alloc = req_size;
}
if (!CertGetEnhancedKeyUsage(pcc, 0, ceu, &req_size))
continue;
if (!ceu || (ceu && !ceu->cUsageIdentifier)) {
/*
* "If GetLastError returns CRYPT_E_NOT_FOUND, the
* certificate is good for all uses. If it returns
* zero, the certificate has no valid uses."
*/
if ((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
continue;
/* ... allow it... */
} else
if (ceu) {
BOOL found = FALSE;
DWORD i;
/*
* If there is a CEU, check that it specifies
* we can use the cert for server validation
*/
for (i = 0; i < ceu->cUsageIdentifier; i++) {
if (strcmp("1.3.6.1.5.5.7.3.1"
/* OID server auth */,
ceu->rgpszUsageIdentifier[i]))
continue;
found = TRUE;
break;
}
if (!found)
/* Don't use cert if no usage match */
continue;
}
x509 = d2i_X509(NULL, &ecert, pcc->cbCertEncoded);
if (!x509)
/* We can't parse it as am X.509, skip it */
continue;
if (X509_STORE_add_cert(store, x509) == 1) {
lwsl_debug("%s: Imported cert \"%s\"\n", __func__,
cert_name);
imps++;
}
/*
* Treat failure as nonfatal, eg, may be dupe
*/
X509_free(x509);
} while (1);
lws_free(ceu);
CertFreeCertificateContext(pcc);
CertCloseStore(hStore, 0);
lwsl_notice("%s: Imported %d certs from plat store\n", __func__, imps);
#endif
return 0;
}
const char * const char *
lws_plat_inet_ntop(int af, const void *src, char *dst, socklen_t cnt) lws_plat_inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
{ {

View file

@ -756,6 +756,8 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh,
return 1; return 1;
} }
lws_plat_vhost_tls_client_ctx_init(vh);
tcr = lws_zalloc(sizeof(*tcr), "client ctx tcr"); tcr = lws_zalloc(sizeof(*tcr), "client ctx tcr");
if (!tcr) { if (!tcr) {
SSL_CTX_free(vh->tls.ssl_client_ctx); SSL_CTX_free(vh->tls.ssl_client_ctx);