1/*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25#include "private-lib-core.h"
26
27struct lws *
28lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback,
29				 ssize_t plen)
30{
31#if defined(LWS_CLIENT_HTTP_PROXYING)
32	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
33#endif
34	const char *meth;
35	struct lws_pollfd pfd;
36	const char *cce = "";
37	int n, m, rawish = 0;
38
39	meth = lws_wsi_client_stash_item(wsi, CIS_METHOD,
40					 _WSI_TOKEN_CLIENT_METHOD);
41
42	if (meth && (!strcmp(meth, "RAW")
43#if defined(LWS_ROLE_MQTT)
44		     || !strcmp(meth, "MQTT")
45#endif
46	))
47		rawish = 1;
48
49	if (wsi_piggyback)
50		goto send_hs;
51
52#if defined(LWS_CLIENT_HTTP_PROXYING)
53#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
54	/* we are connected to server, or proxy */
55
56	/* http proxy */
57	if (wsi->a.vhost->http.http_proxy_port) {
58		const char *cpa;
59
60		cpa = lws_wsi_client_stash_item(wsi, CIS_ADDRESS,
61						_WSI_TOKEN_CLIENT_PEER_ADDRESS);
62		if (!cpa)
63			goto failed;
64
65		lwsl_wsi_info(wsi, "going via proxy");
66
67		plen = lws_snprintf((char *)pt->serv_buf, 256,
68			"CONNECT %s:%u HTTP/1.1\x0d\x0a"
69			"Host: %s:%u\x0d\x0a"
70			"User-agent: lws\x0d\x0a", cpa, wsi->ocport,
71						   cpa, wsi->ocport);
72
73#if defined(LWS_WITH_HTTP_BASIC_AUTH)
74		if (wsi->a.vhost->proxy_basic_auth_token[0])
75			plen += lws_snprintf((char *)pt->serv_buf + plen, 256,
76					"Proxy-authorization: basic %s\x0d\x0a",
77					wsi->a.vhost->proxy_basic_auth_token);
78#endif
79
80		plen += lws_snprintf((char *)pt->serv_buf + plen, 5,
81					"\x0d\x0a");
82
83		/* lwsl_hexdump_notice(pt->serv_buf, plen); */
84
85		/*
86		 * OK from now on we talk via the proxy, so connect to that
87		 */
88		if (wsi->stash)
89			wsi->stash->cis[CIS_ADDRESS] =
90				wsi->a.vhost->http.http_proxy_address;
91		else
92			if (lws_hdr_simple_create(wsi,
93					_WSI_TOKEN_CLIENT_PEER_ADDRESS,
94					wsi->a.vhost->http.http_proxy_address))
95			goto failed;
96		wsi->c_port = (uint16_t)wsi->a.vhost->http.http_proxy_port;
97
98		n = (int)send(wsi->desc.sockfd, (char *)pt->serv_buf,
99			      (unsigned int)plen,
100			 MSG_NOSIGNAL);
101		if (n < 0) {
102			lwsl_wsi_debug(wsi, "ERROR writing to proxy socket");
103			cce = "proxy write failed";
104			goto failed;
105		}
106
107		lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
108				(int)wsi->a.context->timeout_secs);
109
110		wsi->conn_port = wsi->c_port;
111		lwsi_set_state(wsi, LRS_WAITING_PROXY_REPLY);
112
113		return wsi;
114	}
115#endif
116#endif
117
118	/* coverity */
119	if (!wsi->a.protocol)
120		return NULL;
121
122#if defined(LWS_WITH_SOCKS5)
123	if (lwsi_state(wsi) != 	LRS_ESTABLISHED)
124		switch (lws_socks5c_greet(wsi, &cce)) {
125		case -1:
126			goto failed;
127		case 1:
128			return wsi;
129		default:
130			break;
131		}
132#endif
133
134#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
135send_hs:
136
137	if (wsi_piggyback &&
138	    !lws_dll2_is_detached(&wsi->dll2_cli_txn_queue)) {
139		/*
140		 * We are pipelining on an already-established connection...
141		 * we can skip tls establishment.
142		 *
143		 * Set these queued guys to a state where they won't actually
144		 * send their headers until we decide later.
145		 */
146
147		lwsi_set_state(wsi, LRS_H2_WAITING_TO_SEND_HEADERS);
148
149		/*
150		 * we can't send our headers directly, because they have to
151		 * be sent when the parent is writeable.  The parent will check
152		 * for anybody on his client transaction queue that is in
153		 * LRS_H1C_ISSUE_HANDSHAKE2, and let them write.
154		 *
155		 * If we are trying to do this too early, before the network
156		 * connection has written his own headers, then it will just
157		 * wait in the queue until it's possible to send them.
158		 */
159		lws_callback_on_writable(wsi_piggyback);
160
161		lwsl_wsi_info(wsi, "waiting to send hdrs (par state 0x%x)",
162			      lwsi_state(wsi_piggyback));
163	} else {
164		lwsl_wsi_info(wsi, "%s %s client created own conn "
165			  "(raw %d) vh %s st 0x%x",
166			  wsi->role_ops->name, wsi->a.protocol->name, rawish,
167			  wsi->a.vhost->name, lwsi_state(wsi));
168
169		/* we are making our own connection */
170
171		if (!rawish
172#if defined(LWS_WITH_TLS)
173		    // && (!(wsi->tls.use_ssl & LCCSCF_USE_SSL) || wsi->tls.ssl)
174#endif
175		    ) {
176
177			if (lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2)
178				lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE);
179		} else {
180			/* for a method = "RAW" connection, this makes us
181			 * established */
182
183#if defined(LWS_WITH_TLS)// && !defined(LWS_WITH_MBEDTLS)
184
185			/* we have connected if we got here */
186
187			if (lwsi_state(wsi) == LRS_WAITING_CONNECT &&
188			    (wsi->tls.use_ssl & LCCSCF_USE_SSL)) {
189				int result;
190
191				//lwsi_set_state(wsi, LRS_WAITING_SSL);
192
193				/*
194				 * We can retry this... just cook the SSL BIO
195				 * the first time
196				 */
197
198				result = lws_client_create_tls(wsi, &cce, 1);
199				switch (result) {
200				case CCTLS_RETURN_DONE:
201					break;
202				case CCTLS_RETURN_RETRY:
203					lwsl_wsi_debug(wsi, "create_tls RETRY");
204					return wsi;
205				default:
206					lwsl_wsi_debug(wsi, "create_tls FAIL");
207					goto failed;
208				}
209
210				/*
211				 * We succeeded to negotiate a new client tls
212				 * tunnel.  If it's h2 alpn, we have arranged
213				 * to send the h2 prefix and set our state to
214				 * LRS_H2_WAITING_TO_SEND_HEADERS already.
215				 */
216
217				lwsl_wsi_notice(wsi, "tls established st 0x%x, "
218					    "client_h2_alpn %d", lwsi_state(wsi),
219					    wsi->client_h2_alpn);
220
221				if (lwsi_state(wsi) !=
222						LRS_H2_WAITING_TO_SEND_HEADERS)
223					lwsi_set_state(wsi,
224						LRS_H1C_ISSUE_HANDSHAKE2);
225				lws_set_timeout(wsi,
226					PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
227					(int)wsi->a.context->timeout_secs);
228#if 0
229				/* ensure pollin enabled */
230				if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
231					lwsl_wsi_notice(wsi,
232							"unable to set POLLIN");
233#endif
234
235				goto provoke_service;
236			}
237#endif
238
239			/* clear his established timeout */
240			lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
241
242			m = wsi->role_ops->adoption_cb[0];
243			if (m) {
244				n = user_callback_handle_rxflow(
245						wsi->a.protocol->callback, wsi,
246						(enum lws_callback_reasons)m,
247						wsi->user_space, NULL, 0);
248				if (n < 0) {
249					lwsl_wsi_info(wsi, "RAW_PROXY_CLI_ADOPT err");
250					goto failed;
251				}
252			}
253
254			/* service.c pollout processing wants this */
255			wsi->hdr_parsing_completed = 1;
256#if defined(LWS_ROLE_MQTT)
257			if (meth && !strcmp(meth, "MQTT")) {
258#if defined(LWS_WITH_TLS)
259				if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
260					lwsi_set_state(wsi, LRS_WAITING_SSL);
261					return wsi;
262				}
263#endif
264				lwsl_wsi_info(wsi, "settings LRS_MQTTC_IDLE");
265				lwsi_set_state(wsi, LRS_MQTTC_IDLE);
266
267				/*
268				 * provoke service to issue the CONNECT
269				 * directly.
270				 */
271				lws_set_timeout(wsi,
272					PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE,
273						(int)wsi->a.context->timeout_secs);
274
275				assert(lws_socket_is_valid(wsi->desc.sockfd));
276
277				pfd.fd = wsi->desc.sockfd;
278				pfd.events = LWS_POLLIN;
279				pfd.revents = LWS_POLLOUT;
280
281				lwsl_wsi_info(wsi, "going to service fd");
282				n = lws_service_fd(wsi->a.context, &pfd);
283				if (n < 0) {
284					cce = "first service failed";
285					goto failed;
286				}
287				if (n)
288					/* returns 1 on fail after close wsi */
289					return NULL;
290				return wsi;
291			}
292#endif
293			lwsl_wsi_info(wsi, "setting ESTABLISHED");
294			lwsi_set_state(wsi, LRS_ESTABLISHED);
295
296			return wsi;
297		}
298
299		/*
300		 * provoke service to issue the handshake directly.
301		 *
302		 * we need to do it this way because in the proxy case, this is
303		 * the next state and executed only if and when we get a good
304		 * proxy response inside the state machine... but notice in
305		 * SSL case this may not have sent anything yet with 0 return,
306		 * and won't until many retries from main loop.  To stop that
307		 * becoming endless, cover with a timeout.
308		 */
309#if defined(LWS_WITH_TLS) //&& !defined(LWS_WITH_MBEDTLS)
310provoke_service:
311#endif
312		lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE,
313				(int)wsi->a.context->timeout_secs);
314
315		assert(lws_socket_is_valid(wsi->desc.sockfd));
316
317		pfd.fd = wsi->desc.sockfd;
318		pfd.events = LWS_POLLIN;
319		pfd.revents = LWS_POLLIN;
320
321		n = lws_service_fd(wsi->a.context, &pfd);
322		if (n < 0) {
323			cce = "first service failed";
324			goto failed;
325		}
326		if (n) /* returns 1 on failure after closing wsi */
327			return NULL;
328	}
329#endif
330	return wsi;
331
332failed:
333	lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
334
335	lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect4");
336
337	return NULL;
338}
339