1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to 8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the 9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions: 12d4afb5ceSopenharmony_ci * 13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22d4afb5ceSopenharmony_ci * IN THE SOFTWARE. 23d4afb5ceSopenharmony_ci */ 24d4afb5ceSopenharmony_ci 25d4afb5ceSopenharmony_ci#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS 26d4afb5ceSopenharmony_ci#define _WINSOCK_DEPRECATED_NO_WARNINGS 27d4afb5ceSopenharmony_ci#endif 28d4afb5ceSopenharmony_ci#define MBEDTLS_ALLOW_PRIVATE_ACCESS 29d4afb5ceSopenharmony_ci#include "private-lib-core.h" 30d4afb5ceSopenharmony_ci 31d4afb5ceSopenharmony_ci#if defined(LWS_WITH_MBEDTLS) 32d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_MBEDTLS_NET_SOCKETS) 33d4afb5ceSopenharmony_ci#include "mbedtls/net_sockets.h" 34d4afb5ceSopenharmony_ci#else 35d4afb5ceSopenharmony_ci#include "mbedtls/net.h" 36d4afb5ceSopenharmony_ci#endif 37d4afb5ceSopenharmony_ci#endif 38d4afb5ceSopenharmony_ci 39d4afb5ceSopenharmony_ciint 40d4afb5ceSopenharmony_cilws_send_pipe_choked(struct lws *wsi) 41d4afb5ceSopenharmony_ci{ struct lws *wsi_eff; 42d4afb5ceSopenharmony_ci 43d4afb5ceSopenharmony_ci#if defined(LWS_WITH_HTTP2) 44d4afb5ceSopenharmony_ci wsi_eff = lws_get_network_wsi(wsi); 45d4afb5ceSopenharmony_ci#else 46d4afb5ceSopenharmony_ci wsi_eff = wsi; 47d4afb5ceSopenharmony_ci#endif 48d4afb5ceSopenharmony_ci /* the fact we checked implies we avoided back-to-back writes */ 49d4afb5ceSopenharmony_ci wsi_eff->could_have_pending = 0; 50d4afb5ceSopenharmony_ci 51d4afb5ceSopenharmony_ci /* treat the fact we got a truncated send pending as if we're choked */ 52d4afb5ceSopenharmony_ci if (lws_has_buffered_out(wsi_eff) 53d4afb5ceSopenharmony_ci#if defined(LWS_WITH_HTTP_STREAM_COMPRESSION) 54d4afb5ceSopenharmony_ci ||wsi->http.comp_ctx.buflist_comp || 55d4afb5ceSopenharmony_ci wsi->http.comp_ctx.may_have_more 56d4afb5ceSopenharmony_ci#endif 57d4afb5ceSopenharmony_ci ) 58d4afb5ceSopenharmony_ci return 1; 59d4afb5ceSopenharmony_ci 60d4afb5ceSopenharmony_ci return (int)wsi_eff->sock_send_blocking; 61d4afb5ceSopenharmony_ci} 62d4afb5ceSopenharmony_ci 63d4afb5ceSopenharmony_ciint 64d4afb5ceSopenharmony_cilws_poll_listen_fd(struct lws_pollfd *fd) 65d4afb5ceSopenharmony_ci{ 66d4afb5ceSopenharmony_ci fd_set readfds; 67d4afb5ceSopenharmony_ci struct timeval tv = { 0, 0 }; 68d4afb5ceSopenharmony_ci 69d4afb5ceSopenharmony_ci assert((fd->events & LWS_POLLIN) == LWS_POLLIN); 70d4afb5ceSopenharmony_ci 71d4afb5ceSopenharmony_ci FD_ZERO(&readfds); 72d4afb5ceSopenharmony_ci FD_SET(fd->fd, &readfds); 73d4afb5ceSopenharmony_ci 74d4afb5ceSopenharmony_ci return select(((int)fd->fd) + 1, &readfds, NULL, NULL, &tv); 75d4afb5ceSopenharmony_ci} 76d4afb5ceSopenharmony_ci 77d4afb5ceSopenharmony_ciint 78d4afb5ceSopenharmony_cilws_plat_set_nonblocking(lws_sockfd_type fd) 79d4afb5ceSopenharmony_ci{ 80d4afb5ceSopenharmony_ci u_long optl = 1; 81d4afb5ceSopenharmony_ci int result = !!ioctlsocket(fd, FIONBIO, &optl); 82d4afb5ceSopenharmony_ci#if (_LWS_ENABLED_LOGS & LLL_ERR) 83d4afb5ceSopenharmony_ci if (result) 84d4afb5ceSopenharmony_ci { 85d4afb5ceSopenharmony_ci int error = LWS_ERRNO; 86d4afb5ceSopenharmony_ci lwsl_err("ioctlsocket FIONBIO 1 failed with error %d\n", error); 87d4afb5ceSopenharmony_ci } 88d4afb5ceSopenharmony_ci#endif 89d4afb5ceSopenharmony_ci return result; 90d4afb5ceSopenharmony_ci} 91d4afb5ceSopenharmony_ci 92d4afb5ceSopenharmony_ciint 93d4afb5ceSopenharmony_cilws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd, 94d4afb5ceSopenharmony_ci int unix_skt) 95d4afb5ceSopenharmony_ci{ 96d4afb5ceSopenharmony_ci int optval = 1; 97d4afb5ceSopenharmony_ci int optlen = sizeof(optval); 98d4afb5ceSopenharmony_ci DWORD dwBytesRet; 99d4afb5ceSopenharmony_ci struct tcp_keepalive alive; 100d4afb5ceSopenharmony_ci int protonbr; 101d4afb5ceSopenharmony_ci#ifndef _WIN32_WCE 102d4afb5ceSopenharmony_ci struct protoent *tcp_proto; 103d4afb5ceSopenharmony_ci#endif 104d4afb5ceSopenharmony_ci 105d4afb5ceSopenharmony_ci if (vhost->ka_time) { 106d4afb5ceSopenharmony_ci /* enable keepalive on this socket */ 107d4afb5ceSopenharmony_ci optval = 1; 108d4afb5ceSopenharmony_ci if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, 109d4afb5ceSopenharmony_ci (const char *)&optval, optlen) < 0) { 110d4afb5ceSopenharmony_ci#if (_LWS_ENABLED_LOGS & LLL_ERR) 111d4afb5ceSopenharmony_ci int error = LWS_ERRNO; 112d4afb5ceSopenharmony_ci lwsl_err("setsockopt SO_KEEPALIVE 1 failed with error %d\n", error); 113d4afb5ceSopenharmony_ci#endif 114d4afb5ceSopenharmony_ci return 1; 115d4afb5ceSopenharmony_ci } 116d4afb5ceSopenharmony_ci 117d4afb5ceSopenharmony_ci alive.onoff = TRUE; 118d4afb5ceSopenharmony_ci alive.keepalivetime = vhost->ka_time * 1000; 119d4afb5ceSopenharmony_ci alive.keepaliveinterval = vhost->ka_interval * 1000; 120d4afb5ceSopenharmony_ci 121d4afb5ceSopenharmony_ci if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive), 122d4afb5ceSopenharmony_ci NULL, 0, &dwBytesRet, NULL, NULL)) { 123d4afb5ceSopenharmony_ci#if (_LWS_ENABLED_LOGS & LLL_ERR) 124d4afb5ceSopenharmony_ci int error = LWS_ERRNO; 125d4afb5ceSopenharmony_ci lwsl_err("WSAIoctl SIO_KEEPALIVE_VALS 1 %lu %lu failed with error %d\n", alive.keepalivetime, alive.keepaliveinterval, error); 126d4afb5ceSopenharmony_ci#endif 127d4afb5ceSopenharmony_ci return 1; 128d4afb5ceSopenharmony_ci } 129d4afb5ceSopenharmony_ci } 130d4afb5ceSopenharmony_ci 131d4afb5ceSopenharmony_ci /* Disable Nagle */ 132d4afb5ceSopenharmony_ci optval = 1; 133d4afb5ceSopenharmony_ci#ifndef _WIN32_WCE 134d4afb5ceSopenharmony_ci tcp_proto = getprotobyname("TCP"); 135d4afb5ceSopenharmony_ci if (!tcp_proto) { 136d4afb5ceSopenharmony_ci#if (_LWS_ENABLED_LOGS & LLL_WARN) 137d4afb5ceSopenharmony_ci int error = LWS_ERRNO; 138d4afb5ceSopenharmony_ci lwsl_warn("getprotobyname(\"TCP\") failed with error, falling back to 6 %d\n", error); 139d4afb5ceSopenharmony_ci#endif 140d4afb5ceSopenharmony_ci protonbr = 6; /* IPPROTO_TCP */ 141d4afb5ceSopenharmony_ci } else 142d4afb5ceSopenharmony_ci protonbr = tcp_proto->p_proto; 143d4afb5ceSopenharmony_ci#else 144d4afb5ceSopenharmony_ci protonbr = 6; 145d4afb5ceSopenharmony_ci#endif 146d4afb5ceSopenharmony_ci 147d4afb5ceSopenharmony_ci if (setsockopt(fd, protonbr, TCP_NODELAY, (const char *)&optval, optlen) ) { 148d4afb5ceSopenharmony_ci#if (_LWS_ENABLED_LOGS & LLL_WARN) 149d4afb5ceSopenharmony_ci int error = LWS_ERRNO; 150d4afb5ceSopenharmony_ci lwsl_warn("setsockopt TCP_NODELAY 1 failed with error %d\n", error); 151d4afb5ceSopenharmony_ci#endif 152d4afb5ceSopenharmony_ci } 153d4afb5ceSopenharmony_ci 154d4afb5ceSopenharmony_ci return lws_plat_set_nonblocking(fd); 155d4afb5ceSopenharmony_ci} 156d4afb5ceSopenharmony_ci 157d4afb5ceSopenharmony_ciint 158d4afb5ceSopenharmony_cilws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags) 159d4afb5ceSopenharmony_ci{ 160d4afb5ceSopenharmony_ci /* 161d4afb5ceSopenharmony_ci * Seems to require "differeniated services" but no docs 162d4afb5ceSopenharmony_ci * 163d4afb5ceSopenharmony_ci * https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options 164d4afb5ceSopenharmony_ci * https://docs.microsoft.com/en-us/previous-versions/windows/desktop/qos/differentiated-services 165d4afb5ceSopenharmony_ci */ 166d4afb5ceSopenharmony_ci lwsl_warn("%s: not implemented on windows platform\n", __func__); 167d4afb5ceSopenharmony_ci 168d4afb5ceSopenharmony_ci return 0; 169d4afb5ceSopenharmony_ci} 170d4afb5ceSopenharmony_ci 171d4afb5ceSopenharmony_ciint 172d4afb5ceSopenharmony_cilws_interface_to_sa(int ipv6, 173d4afb5ceSopenharmony_ci const char *ifname, struct sockaddr_in *addr, size_t addrlen) 174d4afb5ceSopenharmony_ci{ 175d4afb5ceSopenharmony_ci long long address; 176d4afb5ceSopenharmony_ci#ifdef LWS_WITH_IPV6 177d4afb5ceSopenharmony_ci struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; 178d4afb5ceSopenharmony_ci 179d4afb5ceSopenharmony_ci if (ipv6) { 180d4afb5ceSopenharmony_ci if (lws_plat_inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1) { 181d4afb5ceSopenharmony_ci return LWS_ITOSA_USABLE; 182d4afb5ceSopenharmony_ci } 183d4afb5ceSopenharmony_ci } 184d4afb5ceSopenharmony_ci#endif 185d4afb5ceSopenharmony_ci 186d4afb5ceSopenharmony_ci address = inet_addr(ifname); 187d4afb5ceSopenharmony_ci 188d4afb5ceSopenharmony_ci if (address == INADDR_NONE) { 189d4afb5ceSopenharmony_ci struct hostent *entry = gethostbyname(ifname); 190d4afb5ceSopenharmony_ci if (entry) 191d4afb5ceSopenharmony_ci address = ((struct in_addr *)entry->h_addr_list[0])->s_addr; 192d4afb5ceSopenharmony_ci } 193d4afb5ceSopenharmony_ci 194d4afb5ceSopenharmony_ci if (address == INADDR_NONE) 195d4afb5ceSopenharmony_ci return LWS_ITOSA_NOT_EXIST; 196d4afb5ceSopenharmony_ci 197d4afb5ceSopenharmony_ci addr->sin_addr.s_addr = (unsigned long)(lws_intptr_t)address; 198d4afb5ceSopenharmony_ci 199d4afb5ceSopenharmony_ci return LWS_ITOSA_USABLE; 200d4afb5ceSopenharmony_ci} 201d4afb5ceSopenharmony_ci 202d4afb5ceSopenharmony_civoid 203d4afb5ceSopenharmony_cilws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi) 204d4afb5ceSopenharmony_ci{ 205d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; 206d4afb5ceSopenharmony_ci 207d4afb5ceSopenharmony_ci#if defined(LWS_WITH_UDP) 208d4afb5ceSopenharmony_ci if (wsi->udp) { 209d4afb5ceSopenharmony_ci lwsl_info("%s: UDP\n", __func__); 210d4afb5ceSopenharmony_ci pt->fds[pt->fds_count].events |= LWS_POLLIN; 211d4afb5ceSopenharmony_ci } 212d4afb5ceSopenharmony_ci#endif 213d4afb5ceSopenharmony_ci 214d4afb5ceSopenharmony_ci if (context->event_loop_ops->io) 215d4afb5ceSopenharmony_ci context->event_loop_ops->io(wsi, LWS_EV_START | LWS_EV_READ); 216d4afb5ceSopenharmony_ci 217d4afb5ceSopenharmony_ci pt->fds[pt->fds_count++].revents = 0; 218d4afb5ceSopenharmony_ci 219d4afb5ceSopenharmony_ci lws_plat_change_pollfd(context, wsi, &pt->fds[pt->fds_count - 1]); 220d4afb5ceSopenharmony_ci} 221d4afb5ceSopenharmony_ci 222d4afb5ceSopenharmony_civoid 223d4afb5ceSopenharmony_cilws_plat_delete_socket_from_fds(struct lws_context *context, 224d4afb5ceSopenharmony_ci struct lws *wsi, int m) 225d4afb5ceSopenharmony_ci{ 226d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; 227d4afb5ceSopenharmony_ci 228d4afb5ceSopenharmony_ci pt->fds_count--; 229d4afb5ceSopenharmony_ci} 230d4afb5ceSopenharmony_ci 231d4afb5ceSopenharmony_ci 232d4afb5ceSopenharmony_ciint 233d4afb5ceSopenharmony_cilws_plat_check_connection_error(struct lws *wsi) 234d4afb5ceSopenharmony_ci{ 235d4afb5ceSopenharmony_ci int optVal; 236d4afb5ceSopenharmony_ci int optLen = sizeof(int); 237d4afb5ceSopenharmony_ci 238d4afb5ceSopenharmony_ci if (getsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_ERROR, 239d4afb5ceSopenharmony_ci (char*)&optVal, &optLen) != SOCKET_ERROR && optVal && 240d4afb5ceSopenharmony_ci optVal != LWS_EALREADY && optVal != LWS_EINPROGRESS && 241d4afb5ceSopenharmony_ci optVal != LWS_EWOULDBLOCK && optVal != WSAEINVAL) { 242d4afb5ceSopenharmony_ci lwsl_debug("Connect failed SO_ERROR=%d\n", optVal); 243d4afb5ceSopenharmony_ci return 1; 244d4afb5ceSopenharmony_ci } 245d4afb5ceSopenharmony_ci 246d4afb5ceSopenharmony_ci return 0; 247d4afb5ceSopenharmony_ci} 248d4afb5ceSopenharmony_ci 249d4afb5ceSopenharmony_ciint 250d4afb5ceSopenharmony_cilws_plat_change_pollfd(struct lws_context *context, struct lws *wsi, 251d4afb5ceSopenharmony_ci struct lws_pollfd *pfd) 252d4afb5ceSopenharmony_ci{ 253d4afb5ceSopenharmony_ci //struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; 254d4afb5ceSopenharmony_ci 255d4afb5ceSopenharmony_ci return 0; 256d4afb5ceSopenharmony_ci} 257d4afb5ceSopenharmony_ci 258d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS) 259d4afb5ceSopenharmony_ci 260d4afb5ceSopenharmony_ciint 261d4afb5ceSopenharmony_cilws_plat_vhost_tls_client_ctx_init(struct lws_vhost *vhost) 262d4afb5ceSopenharmony_ci{ 263d4afb5ceSopenharmony_ci#if !defined(LWS_WITH_MBEDTLS) && defined(LWS_SSL_CLIENT_USE_OS_CA_CERTS) 264d4afb5ceSopenharmony_ci PCCERT_CONTEXT pcc = NULL; 265d4afb5ceSopenharmony_ci CERT_ENHKEY_USAGE* ceu = NULL; 266d4afb5ceSopenharmony_ci DWORD ceu_alloc = 0; 267d4afb5ceSopenharmony_ci X509_STORE* store; 268d4afb5ceSopenharmony_ci HCERTSTORE hStore; 269d4afb5ceSopenharmony_ci int imps = 0; 270d4afb5ceSopenharmony_ci 271d4afb5ceSopenharmony_ci if (lws_check_opt(vhost->options, 272d4afb5ceSopenharmony_ci LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS)) 273d4afb5ceSopenharmony_ci return 0; 274d4afb5ceSopenharmony_ci 275d4afb5ceSopenharmony_ci /* 276d4afb5ceSopenharmony_ci * Windows Trust Store code adapted from curl (MIT) openssl.c 277d4afb5ceSopenharmony_ci * https://github.com/warmcat/libwebsockets/pull/2233 278d4afb5ceSopenharmony_ci */ 279d4afb5ceSopenharmony_ci 280d4afb5ceSopenharmony_ci store = SSL_CTX_get_cert_store(vhost->tls.ssl_client_ctx); 281d4afb5ceSopenharmony_ci hStore = CertOpenSystemStore((HCRYPTPROV_LEGACY)NULL, TEXT("ROOT")); 282d4afb5ceSopenharmony_ci 283d4afb5ceSopenharmony_ci if (!hStore) { 284d4afb5ceSopenharmony_ci lwsl_notice("%s: no store\n", __func__); 285d4afb5ceSopenharmony_ci return 1; 286d4afb5ceSopenharmony_ci } 287d4afb5ceSopenharmony_ci 288d4afb5ceSopenharmony_ci do { 289d4afb5ceSopenharmony_ci const unsigned char* ecert; 290d4afb5ceSopenharmony_ci char cert_name[256]; 291d4afb5ceSopenharmony_ci DWORD req_size = 0; 292d4afb5ceSopenharmony_ci BYTE key_usage[2]; 293d4afb5ceSopenharmony_ci FILETIME ft; 294d4afb5ceSopenharmony_ci X509* x509; 295d4afb5ceSopenharmony_ci 296d4afb5ceSopenharmony_ci pcc = CertEnumCertificatesInStore(hStore, pcc); 297d4afb5ceSopenharmony_ci if (!pcc) 298d4afb5ceSopenharmony_ci break; 299d4afb5ceSopenharmony_ci 300d4afb5ceSopenharmony_ci if (!CertGetNameStringA(pcc, CERT_NAME_SIMPLE_DISPLAY_TYPE, 301d4afb5ceSopenharmony_ci 0, NULL, cert_name, sizeof(cert_name))) 302d4afb5ceSopenharmony_ci strcpy(cert_name, "Unknown"); 303d4afb5ceSopenharmony_ci 304d4afb5ceSopenharmony_ci lwsl_debug("%s: Checking cert \"%s\"\n", __func__, cert_name); 305d4afb5ceSopenharmony_ci 306d4afb5ceSopenharmony_ci ecert = (const unsigned char*)pcc->pbCertEncoded; 307d4afb5ceSopenharmony_ci if (!ecert) 308d4afb5ceSopenharmony_ci continue; 309d4afb5ceSopenharmony_ci 310d4afb5ceSopenharmony_ci GetSystemTimeAsFileTime(&ft); 311d4afb5ceSopenharmony_ci if (CompareFileTime(&pcc->pCertInfo->NotBefore, &ft) > 0 || 312d4afb5ceSopenharmony_ci CompareFileTime(&ft, &pcc->pCertInfo->NotAfter) > 0) 313d4afb5ceSopenharmony_ci continue; 314d4afb5ceSopenharmony_ci 315d4afb5ceSopenharmony_ci /* If key usage exists check for signing attribute */ 316d4afb5ceSopenharmony_ci if (CertGetIntendedKeyUsage(pcc->dwCertEncodingType, 317d4afb5ceSopenharmony_ci pcc->pCertInfo, 318d4afb5ceSopenharmony_ci key_usage, sizeof(key_usage))) { 319d4afb5ceSopenharmony_ci if (!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE)) 320d4afb5ceSopenharmony_ci continue; 321d4afb5ceSopenharmony_ci } else 322d4afb5ceSopenharmony_ci if (GetLastError()) 323d4afb5ceSopenharmony_ci continue; 324d4afb5ceSopenharmony_ci 325d4afb5ceSopenharmony_ci /* 326d4afb5ceSopenharmony_ci * If enhanced key usage exists check for server auth attribute. 327d4afb5ceSopenharmony_ci * 328d4afb5ceSopenharmony_ci * Note "In a Microsoft environment, a certificate might also 329d4afb5ceSopenharmony_ci * have EKU extended properties that specify valid uses for the 330d4afb5ceSopenharmony_ci * certificate." 331d4afb5ceSopenharmony_ci * The call below checks both, and behavior varies depending on 332d4afb5ceSopenharmony_ci * what is found. For more details see CertGetEnhancedKeyUsage 333d4afb5ceSopenharmony_ci * doc. 334d4afb5ceSopenharmony_ci */ 335d4afb5ceSopenharmony_ci if (!CertGetEnhancedKeyUsage(pcc, 0, NULL, &req_size)) 336d4afb5ceSopenharmony_ci continue; 337d4afb5ceSopenharmony_ci 338d4afb5ceSopenharmony_ci if (req_size && req_size > ceu_alloc) { 339d4afb5ceSopenharmony_ci void* tmp = lws_realloc(ceu, req_size, __func__); 340d4afb5ceSopenharmony_ci 341d4afb5ceSopenharmony_ci if (!tmp) { 342d4afb5ceSopenharmony_ci lwsl_err("%s: OOM", __func__); 343d4afb5ceSopenharmony_ci break; 344d4afb5ceSopenharmony_ci } 345d4afb5ceSopenharmony_ci 346d4afb5ceSopenharmony_ci ceu = (CERT_ENHKEY_USAGE*)tmp; 347d4afb5ceSopenharmony_ci ceu_alloc = req_size; 348d4afb5ceSopenharmony_ci } 349d4afb5ceSopenharmony_ci 350d4afb5ceSopenharmony_ci if (!CertGetEnhancedKeyUsage(pcc, 0, ceu, &req_size)) 351d4afb5ceSopenharmony_ci continue; 352d4afb5ceSopenharmony_ci 353d4afb5ceSopenharmony_ci if (!ceu || (ceu && !ceu->cUsageIdentifier)) { 354d4afb5ceSopenharmony_ci /* 355d4afb5ceSopenharmony_ci * "If GetLastError returns CRYPT_E_NOT_FOUND, the 356d4afb5ceSopenharmony_ci * certificate is good for all uses. If it returns 357d4afb5ceSopenharmony_ci * zero, the certificate has no valid uses." 358d4afb5ceSopenharmony_ci */ 359d4afb5ceSopenharmony_ci if ((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND) 360d4afb5ceSopenharmony_ci continue; 361d4afb5ceSopenharmony_ci 362d4afb5ceSopenharmony_ci /* ... allow it... */ 363d4afb5ceSopenharmony_ci 364d4afb5ceSopenharmony_ci } else 365d4afb5ceSopenharmony_ci if (ceu) { 366d4afb5ceSopenharmony_ci BOOL found = FALSE; 367d4afb5ceSopenharmony_ci DWORD i; 368d4afb5ceSopenharmony_ci 369d4afb5ceSopenharmony_ci /* 370d4afb5ceSopenharmony_ci * If there is a CEU, check that it specifies 371d4afb5ceSopenharmony_ci * we can use the cert for server validation 372d4afb5ceSopenharmony_ci */ 373d4afb5ceSopenharmony_ci 374d4afb5ceSopenharmony_ci for (i = 0; i < ceu->cUsageIdentifier; i++) { 375d4afb5ceSopenharmony_ci if (strcmp("1.3.6.1.5.5.7.3.1" 376d4afb5ceSopenharmony_ci /* OID server auth */, 377d4afb5ceSopenharmony_ci ceu->rgpszUsageIdentifier[i])) 378d4afb5ceSopenharmony_ci continue; 379d4afb5ceSopenharmony_ci 380d4afb5ceSopenharmony_ci found = TRUE; 381d4afb5ceSopenharmony_ci break; 382d4afb5ceSopenharmony_ci } 383d4afb5ceSopenharmony_ci 384d4afb5ceSopenharmony_ci if (!found) 385d4afb5ceSopenharmony_ci /* Don't use cert if no usage match */ 386d4afb5ceSopenharmony_ci continue; 387d4afb5ceSopenharmony_ci } 388d4afb5ceSopenharmony_ci 389d4afb5ceSopenharmony_ci x509 = d2i_X509(NULL, &ecert, pcc->cbCertEncoded); 390d4afb5ceSopenharmony_ci if (!x509) 391d4afb5ceSopenharmony_ci /* We can't parse it as am X.509, skip it */ 392d4afb5ceSopenharmony_ci continue; 393d4afb5ceSopenharmony_ci 394d4afb5ceSopenharmony_ci if (X509_STORE_add_cert(store, x509) == 1) { 395d4afb5ceSopenharmony_ci lwsl_debug("%s: Imported cert \"%s\"\n", __func__, 396d4afb5ceSopenharmony_ci cert_name); 397d4afb5ceSopenharmony_ci imps++; 398d4afb5ceSopenharmony_ci } 399d4afb5ceSopenharmony_ci 400d4afb5ceSopenharmony_ci /* 401d4afb5ceSopenharmony_ci * Treat failure as nonfatal, eg, may be dupe 402d4afb5ceSopenharmony_ci */ 403d4afb5ceSopenharmony_ci 404d4afb5ceSopenharmony_ci X509_free(x509); 405d4afb5ceSopenharmony_ci } while (1); 406d4afb5ceSopenharmony_ci 407d4afb5ceSopenharmony_ci lws_free(ceu); 408d4afb5ceSopenharmony_ci CertFreeCertificateContext(pcc); 409d4afb5ceSopenharmony_ci CertCloseStore(hStore, 0); 410d4afb5ceSopenharmony_ci 411d4afb5ceSopenharmony_ci lwsl_notice("%s: Imported %d certs from plat store\n", __func__, imps); 412d4afb5ceSopenharmony_ci#endif 413d4afb5ceSopenharmony_ci 414d4afb5ceSopenharmony_ci return 0; 415d4afb5ceSopenharmony_ci} 416d4afb5ceSopenharmony_ci 417d4afb5ceSopenharmony_ci#endif 418d4afb5ceSopenharmony_ci 419d4afb5ceSopenharmony_ciconst char * 420d4afb5ceSopenharmony_cilws_plat_inet_ntop(int af, const void *src, char *dst, socklen_t cnt) 421d4afb5ceSopenharmony_ci{ 422d4afb5ceSopenharmony_ci WCHAR *buffer; 423d4afb5ceSopenharmony_ci size_t bufferlen = (size_t)cnt; 424d4afb5ceSopenharmony_ci BOOL ok = FALSE; 425d4afb5ceSopenharmony_ci 426d4afb5ceSopenharmony_ci buffer = lws_malloc(bufferlen * 2, "inet_ntop"); 427d4afb5ceSopenharmony_ci if (!buffer) { 428d4afb5ceSopenharmony_ci lwsl_err("Out of memory\n"); 429d4afb5ceSopenharmony_ci return NULL; 430d4afb5ceSopenharmony_ci } 431d4afb5ceSopenharmony_ci 432d4afb5ceSopenharmony_ci if (af == AF_INET) { 433d4afb5ceSopenharmony_ci struct sockaddr_in srcaddr; 434d4afb5ceSopenharmony_ci memset(&srcaddr, 0, sizeof(srcaddr)); 435d4afb5ceSopenharmony_ci srcaddr.sin_family = AF_INET; 436d4afb5ceSopenharmony_ci memcpy(&(srcaddr.sin_addr), src, sizeof(srcaddr.sin_addr)); 437d4afb5ceSopenharmony_ci 438d4afb5ceSopenharmony_ci if (!WSAAddressToStringW((struct sockaddr*)&srcaddr, 439d4afb5ceSopenharmony_ci sizeof(srcaddr), 0, buffer, 440d4afb5ceSopenharmony_ci (LPDWORD)&bufferlen)) 441d4afb5ceSopenharmony_ci ok = TRUE; 442d4afb5ceSopenharmony_ci#ifdef LWS_WITH_IPV6 443d4afb5ceSopenharmony_ci } else if (af == AF_INET6) { 444d4afb5ceSopenharmony_ci struct sockaddr_in6 srcaddr; 445d4afb5ceSopenharmony_ci memset(&srcaddr, 0, sizeof(srcaddr)); 446d4afb5ceSopenharmony_ci srcaddr.sin6_family = AF_INET6; 447d4afb5ceSopenharmony_ci memcpy(&(srcaddr.sin6_addr), src, sizeof(srcaddr.sin6_addr)); 448d4afb5ceSopenharmony_ci 449d4afb5ceSopenharmony_ci if (!WSAAddressToStringW((struct sockaddr*)&srcaddr, 450d4afb5ceSopenharmony_ci sizeof(srcaddr), 0, buffer, 451d4afb5ceSopenharmony_ci (LPDWORD)&bufferlen)) 452d4afb5ceSopenharmony_ci ok = TRUE; 453d4afb5ceSopenharmony_ci#endif 454d4afb5ceSopenharmony_ci } else 455d4afb5ceSopenharmony_ci lwsl_err("Unsupported type\n"); 456d4afb5ceSopenharmony_ci 457d4afb5ceSopenharmony_ci if (!ok) { 458d4afb5ceSopenharmony_ci int rv = WSAGetLastError(); 459d4afb5ceSopenharmony_ci lwsl_err("WSAAddressToString() : %d\n", rv); 460d4afb5ceSopenharmony_ci } else { 461d4afb5ceSopenharmony_ci if (WideCharToMultiByte(CP_ACP, 0, buffer, (int)bufferlen, dst, 462d4afb5ceSopenharmony_ci cnt, 0, NULL) <= 0) 463d4afb5ceSopenharmony_ci ok = FALSE; 464d4afb5ceSopenharmony_ci } 465d4afb5ceSopenharmony_ci 466d4afb5ceSopenharmony_ci lws_free(buffer); 467d4afb5ceSopenharmony_ci return ok ? dst : NULL; 468d4afb5ceSopenharmony_ci} 469d4afb5ceSopenharmony_ci 470d4afb5ceSopenharmony_ciint 471d4afb5ceSopenharmony_cilws_plat_inet_pton(int af, const char *src, void *dst) 472d4afb5ceSopenharmony_ci{ 473d4afb5ceSopenharmony_ci WCHAR *buffer; 474d4afb5ceSopenharmony_ci size_t bufferlen = strlen(src) + 1; 475d4afb5ceSopenharmony_ci BOOL ok = FALSE; 476d4afb5ceSopenharmony_ci 477d4afb5ceSopenharmony_ci buffer = lws_malloc(bufferlen * 2, "inet_pton"); 478d4afb5ceSopenharmony_ci if (!buffer) { 479d4afb5ceSopenharmony_ci lwsl_err("Out of memory\n"); 480d4afb5ceSopenharmony_ci return -1; 481d4afb5ceSopenharmony_ci } 482d4afb5ceSopenharmony_ci 483d4afb5ceSopenharmony_ci if (MultiByteToWideChar(CP_ACP, 0, src, (int)bufferlen, buffer, 484d4afb5ceSopenharmony_ci (int)bufferlen) <= 0) { 485d4afb5ceSopenharmony_ci lwsl_err("Failed to convert multi byte to wide char\n"); 486d4afb5ceSopenharmony_ci lws_free(buffer); 487d4afb5ceSopenharmony_ci return -1; 488d4afb5ceSopenharmony_ci } 489d4afb5ceSopenharmony_ci 490d4afb5ceSopenharmony_ci if (af == AF_INET) { 491d4afb5ceSopenharmony_ci struct sockaddr_in dstaddr; 492d4afb5ceSopenharmony_ci int dstaddrlen = sizeof(dstaddr); 493d4afb5ceSopenharmony_ci 494d4afb5ceSopenharmony_ci memset(&dstaddr, 0, sizeof(dstaddr)); 495d4afb5ceSopenharmony_ci dstaddr.sin_family = AF_INET; 496d4afb5ceSopenharmony_ci 497d4afb5ceSopenharmony_ci if (!WSAStringToAddressW(buffer, af, 0, (struct sockaddr *) &dstaddr, &dstaddrlen)) { 498d4afb5ceSopenharmony_ci ok = TRUE; 499d4afb5ceSopenharmony_ci memcpy(dst, &dstaddr.sin_addr, sizeof(dstaddr.sin_addr)); 500d4afb5ceSopenharmony_ci } 501d4afb5ceSopenharmony_ci#ifdef LWS_WITH_IPV6 502d4afb5ceSopenharmony_ci } else if (af == AF_INET6) { 503d4afb5ceSopenharmony_ci struct sockaddr_in6 dstaddr; 504d4afb5ceSopenharmony_ci int dstaddrlen = sizeof(dstaddr); 505d4afb5ceSopenharmony_ci 506d4afb5ceSopenharmony_ci memset(&dstaddr, 0, sizeof(dstaddr)); 507d4afb5ceSopenharmony_ci dstaddr.sin6_family = AF_INET6; 508d4afb5ceSopenharmony_ci 509d4afb5ceSopenharmony_ci if (!WSAStringToAddressW(buffer, af, 0, (struct sockaddr *) &dstaddr, &dstaddrlen)) { 510d4afb5ceSopenharmony_ci ok = TRUE; 511d4afb5ceSopenharmony_ci memcpy(dst, &dstaddr.sin6_addr, sizeof(dstaddr.sin6_addr)); 512d4afb5ceSopenharmony_ci } 513d4afb5ceSopenharmony_ci#endif 514d4afb5ceSopenharmony_ci } else 515d4afb5ceSopenharmony_ci lwsl_err("Unsupported type\n"); 516d4afb5ceSopenharmony_ci 517d4afb5ceSopenharmony_ci if (!ok) { 518d4afb5ceSopenharmony_ci int rv = WSAGetLastError(); 519d4afb5ceSopenharmony_ci lwsl_err("WSAAddressToString() : %d\n", rv); 520d4afb5ceSopenharmony_ci } 521d4afb5ceSopenharmony_ci 522d4afb5ceSopenharmony_ci lws_free(buffer); 523d4afb5ceSopenharmony_ci return ok ? 1 : -1; 524d4afb5ceSopenharmony_ci} 525d4afb5ceSopenharmony_ci 526d4afb5ceSopenharmony_ciint 527d4afb5ceSopenharmony_cilws_plat_ifname_to_hwaddr(int fd, const char *ifname, uint8_t *hwaddr, int len) 528d4afb5ceSopenharmony_ci{ 529d4afb5ceSopenharmony_ci lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__); 530d4afb5ceSopenharmony_ci 531d4afb5ceSopenharmony_ci return -1; 532d4afb5ceSopenharmony_ci} 533d4afb5ceSopenharmony_ci 534d4afb5ceSopenharmony_ciint 535d4afb5ceSopenharmony_cilws_plat_rawudp_broadcast(uint8_t *p, const uint8_t *canned, size_t canned_len, 536d4afb5ceSopenharmony_ci size_t n, int fd, const char *iface) 537d4afb5ceSopenharmony_ci{ 538d4afb5ceSopenharmony_ci lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__); 539d4afb5ceSopenharmony_ci 540d4afb5ceSopenharmony_ci return -1; 541d4afb5ceSopenharmony_ci} 542d4afb5ceSopenharmony_ci 543d4afb5ceSopenharmony_ciint 544d4afb5ceSopenharmony_cilws_plat_if_up(const char *ifname, int fd, int up) 545d4afb5ceSopenharmony_ci{ 546d4afb5ceSopenharmony_ci lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__); 547d4afb5ceSopenharmony_ci 548d4afb5ceSopenharmony_ci return -1; 549d4afb5ceSopenharmony_ci} 550d4afb5ceSopenharmony_ci 551d4afb5ceSopenharmony_ciint 552d4afb5ceSopenharmony_cilws_plat_BINDTODEVICE(lws_sockfd_type fd, const char *ifname) 553d4afb5ceSopenharmony_ci{ 554d4afb5ceSopenharmony_ci lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__); 555d4afb5ceSopenharmony_ci 556d4afb5ceSopenharmony_ci return -1; 557d4afb5ceSopenharmony_ci} 558d4afb5ceSopenharmony_ci 559d4afb5ceSopenharmony_ciint 560d4afb5ceSopenharmony_cilws_plat_ifconfig(int fd, uint8_t *ip, lws_dhcpc_ifstate_t *is) 561d4afb5ceSopenharmony_ci{ 562d4afb5ceSopenharmony_ci lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__); 563d4afb5ceSopenharmony_ci 564d4afb5ceSopenharmony_ci return -1; 565d4afb5ceSopenharmony_ci} 566d4afb5ceSopenharmony_ci 567d4afb5ceSopenharmony_ci#if defined(LWS_WITH_MBEDTLS) 568d4afb5ceSopenharmony_ciint 569d4afb5ceSopenharmony_cilws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) 570d4afb5ceSopenharmony_ci{ 571d4afb5ceSopenharmony_ci int fd = ((mbedtls_net_context *) ctx)->fd; 572d4afb5ceSopenharmony_ci int ret, en; 573d4afb5ceSopenharmony_ci 574d4afb5ceSopenharmony_ci if (fd < 0) 575d4afb5ceSopenharmony_ci return MBEDTLS_ERR_NET_INVALID_CONTEXT; 576d4afb5ceSopenharmony_ci 577d4afb5ceSopenharmony_ci ret = send(fd, (const char *)buf, (unsigned int)len, 0); 578d4afb5ceSopenharmony_ci if (ret >= 0) 579d4afb5ceSopenharmony_ci return ret; 580d4afb5ceSopenharmony_ci 581d4afb5ceSopenharmony_ci en = LWS_ERRNO; 582d4afb5ceSopenharmony_ci if (en == EAGAIN || en == EWOULDBLOCK || en == WSAEWOULDBLOCK) 583d4afb5ceSopenharmony_ci return MBEDTLS_ERR_SSL_WANT_WRITE; 584d4afb5ceSopenharmony_ci 585d4afb5ceSopenharmony_ci ret = WSAGetLastError(); 586d4afb5ceSopenharmony_ci lwsl_notice("%s: errno %d, GLE %d\n", __func__, en, ret); 587d4afb5ceSopenharmony_ci if (ret == WSAECONNRESET ) 588d4afb5ceSopenharmony_ci return( MBEDTLS_ERR_NET_CONN_RESET ); 589d4afb5ceSopenharmony_ci 590d4afb5ceSopenharmony_ci return MBEDTLS_ERR_NET_SEND_FAILED; 591d4afb5ceSopenharmony_ci} 592d4afb5ceSopenharmony_ci 593d4afb5ceSopenharmony_ciint 594d4afb5ceSopenharmony_cilws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) 595d4afb5ceSopenharmony_ci{ 596d4afb5ceSopenharmony_ci int fd = ((mbedtls_net_context *) ctx)->fd; 597d4afb5ceSopenharmony_ci int ret, en; 598d4afb5ceSopenharmony_ci 599d4afb5ceSopenharmony_ci if (fd < 0) 600d4afb5ceSopenharmony_ci return MBEDTLS_ERR_NET_INVALID_CONTEXT; 601d4afb5ceSopenharmony_ci 602d4afb5ceSopenharmony_ci ret = (int)recv(fd, (char *)buf, (unsigned int)len, 0); 603d4afb5ceSopenharmony_ci if (ret >= 0) 604d4afb5ceSopenharmony_ci return ret; 605d4afb5ceSopenharmony_ci 606d4afb5ceSopenharmony_ci en = LWS_ERRNO; 607d4afb5ceSopenharmony_ci if (en == EAGAIN || en == EWOULDBLOCK || en == WSAEWOULDBLOCK) 608d4afb5ceSopenharmony_ci return MBEDTLS_ERR_SSL_WANT_READ; 609d4afb5ceSopenharmony_ci 610d4afb5ceSopenharmony_ci ret = WSAGetLastError(); 611d4afb5ceSopenharmony_ci lwsl_notice("%s: errno %d, GLE %d\n", __func__, en, ret); 612d4afb5ceSopenharmony_ci 613d4afb5ceSopenharmony_ci if (ret == WSAECONNRESET) 614d4afb5ceSopenharmony_ci return MBEDTLS_ERR_NET_CONN_RESET; 615d4afb5ceSopenharmony_ci 616d4afb5ceSopenharmony_ci return MBEDTLS_ERR_NET_RECV_FAILED; 617d4afb5ceSopenharmony_ci} 618d4afb5ceSopenharmony_ci#endif 619d4afb5ceSopenharmony_ci 620