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