1/*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2020 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
27static const uint8_t hnames[] = {
28	_WSI_TOKEN_CLIENT_PEER_ADDRESS,
29	_WSI_TOKEN_CLIENT_URI,
30	_WSI_TOKEN_CLIENT_HOST,
31	_WSI_TOKEN_CLIENT_ORIGIN,
32	_WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
33	_WSI_TOKEN_CLIENT_METHOD,
34	_WSI_TOKEN_CLIENT_IFACE,
35	_WSI_TOKEN_CLIENT_ALPN
36};
37
38struct lws *
39lws_http_client_connect_via_info2(struct lws *wsi)
40{
41	struct client_info_stash *stash = wsi->stash;
42	int n;
43
44	lwsl_wsi_debug(wsi, "stash %p", stash);
45
46	if (!stash)
47		return wsi;
48
49	wsi->a.opaque_user_data = wsi->stash->opaque_user_data;
50
51	if (stash->cis[CIS_METHOD] && (!strcmp(stash->cis[CIS_METHOD], "RAW") ||
52				      !strcmp(stash->cis[CIS_METHOD], "MQTT")))
53		goto no_ah;
54
55	/*
56	 * we're not necessarily in a position to action these right away,
57	 * stash them... we only need during connect phase so into a temp
58	 * allocated stash
59	 */
60	for (n = 0; n < (int)LWS_ARRAY_SIZE(hnames); n++)
61		if (hnames[n] && stash->cis[n] &&
62		    lws_hdr_simple_create(wsi, hnames[n], stash->cis[n]))
63			goto bail;
64
65#if defined(LWS_WITH_SOCKS5)
66	if (!wsi->a.vhost->socks_proxy_port)
67		lws_free_set_NULL(wsi->stash);
68#endif
69
70no_ah:
71	return lws_client_connect_2_dnsreq(wsi);
72
73bail:
74#if defined(LWS_WITH_SOCKS5)
75	if (!wsi->a.vhost->socks_proxy_port)
76		lws_free_set_NULL(wsi->stash);
77#endif
78
79	lws_free_set_NULL(wsi->stash);
80
81	return NULL;
82}
83
84int
85lws_client_stash_create(struct lws *wsi, const char **cisin)
86{
87	size_t size;
88	char *pc;
89	int n;
90
91	size = sizeof(*wsi->stash) + 1;
92
93	/*
94	 * Let's overallocate the stash object with space for all the args
95	 * in one hit.
96	 */
97	for (n = 0; n < CIS_COUNT; n++)
98		if (cisin[n])
99			size += strlen(cisin[n]) + 1;
100
101	if (wsi->stash)
102		lws_free_set_NULL(wsi->stash);
103
104	wsi->stash = lws_malloc(size, "client stash");
105	if (!wsi->stash)
106		return 1;
107
108	/* all the pointers default to NULL, but no need to zero the args */
109	memset(wsi->stash, 0, sizeof(*wsi->stash));
110
111	pc = (char *)&wsi->stash[1];
112
113	for (n = 0; n < CIS_COUNT; n++)
114		if (cisin[n]) {
115			size_t mm;
116			wsi->stash->cis[n] = pc;
117			if (n == CIS_PATH && cisin[n][0] != '/')
118				*pc++ = '/';
119			mm = strlen(cisin[n]) + 1;
120			memcpy(pc, cisin[n], mm);
121			pc += mm;
122		}
123
124	return 0;
125}
126
127struct lws *
128lws_client_connect_via_info(const struct lws_client_connect_info *i)
129{
130	const char *local = i->protocol;
131	struct lws *wsi, *safe = NULL;
132	const struct lws_protocols *p;
133	const char *cisin[CIS_COUNT];
134	struct lws_vhost *vh;
135	int tsi;
136
137	if (i->context->requested_stop_internal_loops)
138		return NULL;
139
140	if (!i->context->protocol_init_done)
141		if (lws_protocol_init(i->context))
142			return NULL;
143
144	/*
145	 * If we have .local_protocol_name, use it to select the local protocol
146	 * handler to bind to.  Otherwise use .protocol if http[s].
147	 */
148	if (i->local_protocol_name)
149		local = i->local_protocol_name;
150
151	lws_context_lock(i->context, __func__);
152	/*
153	 * PHASE 1: if SMP, find out the tsi related to current service thread
154	 */
155
156	tsi = lws_pthread_self_to_tsi(i->context);
157	assert(tsi >= 0);
158
159	/* PHASE 2: create a bare wsi */
160
161	wsi = __lws_wsi_create_with_role(i->context, tsi, NULL, i->log_cx);
162	lws_context_unlock(i->context);
163	if (wsi == NULL)
164		return NULL;
165
166	vh = i->vhost;
167	if (!vh) {
168#if defined(LWS_WITH_TLS_JIT_TRUST)
169		if (lws_tls_jit_trust_vhost_bind(i->context, i->address, &vh))
170#endif
171		{
172			vh = lws_get_vhost_by_name(i->context, "default");
173			if (!vh) {
174
175				vh = i->context->vhost_list;
176
177				if (!vh) { /* coverity */
178					lwsl_cx_err(i->context, "no vhost");
179					goto bail;
180				}
181				if (!strcmp(vh->name, "system"))
182					vh = vh->vhost_next;
183			}
184		}
185	}
186
187#if defined(LWS_WITH_SECURE_STREAMS)
188	/* any of these imply we are a client wsi bound to an SS, which
189	 * implies our opaque user ptr is the ss (or sspc if PROXY_LINK) handle
190	 */
191	wsi->for_ss = !!(i->ssl_connection & (LCCSCF_SECSTREAM_CLIENT | LCCSCF_SECSTREAM_PROXY_LINK | LCCSCF_SECSTREAM_PROXY_ONWARD));
192	wsi->client_bound_sspc = !!(i->ssl_connection & LCCSCF_SECSTREAM_PROXY_LINK); /* so wsi close understands need to remove sspc ptr to wsi */
193	wsi->client_proxy_onward = !!(i->ssl_connection & LCCSCF_SECSTREAM_PROXY_ONWARD);
194#endif
195
196#if defined(LWS_WITH_SYS_FAULT_INJECTION)
197	wsi->fic.name = "wsi";
198	if (i->fic.fi_owner.count)
199		/*
200		 * This moves all the lws_fi_t from i->fi to the vhost fi,
201		 * leaving it empty
202		 */
203		lws_fi_import(&wsi->fic, &i->fic);
204
205	lws_fi_inherit_copy(&wsi->fic, &i->context->fic, "wsi", i->fi_wsi_name);
206
207	if (lws_fi(&wsi->fic, "createfail"))
208		goto bail;
209
210#if defined(LWS_WITH_SECURE_STREAMS)
211#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
212	if (wsi->client_bound_sspc) {
213		lws_sspc_handle_t *fih = (lws_sspc_handle_t *)i->opaque_user_data;
214		lws_fi_inherit_copy(&wsi->fic, &fih->fic, "wsi", NULL);
215	}
216#endif
217	if (wsi->for_ss) {
218		lws_ss_handle_t *fih = (lws_ss_handle_t *)i->opaque_user_data;
219		lws_fi_inherit_copy(&wsi->fic, &fih->fic, "wsi", NULL);
220	}
221#endif
222#endif
223
224	lws_wsi_fault_timedclose(wsi);
225
226	/*
227	 * Until we exit, we can report connection failure directly to the
228	 * caller without needing to call through to protocol CONNECTION_ERROR.
229	 */
230	wsi->client_suppress_CONNECTION_ERROR = 1;
231
232	if (i->keep_warm_secs)
233		wsi->keep_warm_secs = i->keep_warm_secs;
234	else
235		wsi->keep_warm_secs = 5;
236
237	wsi->seq = i->seq;
238	wsi->flags = i->ssl_connection;
239
240	wsi->c_pri = i->priority;
241
242	if (i->retry_and_idle_policy)
243		wsi->retry_policy = i->retry_and_idle_policy;
244	else
245		wsi->retry_policy = &i->context->default_retry;
246
247	if (i->ssl_connection & LCCSCF_WAKE_SUSPEND__VALIDITY)
248		wsi->conn_validity_wakesuspend = 1;
249
250	lws_vhost_bind_wsi(vh, wsi);
251
252#if defined(LWS_WITH_SYS_FAULT_INJECTION)
253	/* additionally inerit from vhost we bound to */
254	lws_fi_inherit_copy(&wsi->fic, &vh->fic, "wsi", i->fi_wsi_name);
255#endif
256
257	if (!wsi->a.vhost) {
258		lwsl_wsi_err(wsi, "No vhost in the context");
259
260		goto bail;
261	}
262
263	/*
264	 * PHASE 3: Choose an initial role for the wsi and do role-specific init
265	 *
266	 * Note the initial role may not reflect the final role, eg,
267	 * we may want ws, but first we have to go through h1 to get that
268	 */
269
270	if (lws_role_call_client_bind(wsi, i) < 0) {
271		lwsl_wsi_err(wsi, "unable to bind to role");
272
273		goto bail;
274	}
275	lwsl_wsi_info(wsi, "role binding to %s", wsi->role_ops->name);
276
277	/*
278	 * PHASE 4: fill up the wsi with stuff from the connect_info as far as
279	 * it can go.  It's uncertain because not only is our connection
280	 * going to complete asynchronously, we might have bound to h1 and not
281	 * even be able to get ahold of an ah immediately.
282	 */
283
284	wsi->user_space = NULL;
285	wsi->pending_timeout = NO_PENDING_TIMEOUT;
286	wsi->position_in_fds_table = LWS_NO_FDS_POS;
287	wsi->ocport = wsi->c_port = (uint16_t)(unsigned int)i->port;
288	wsi->sys_tls_client_cert = i->sys_tls_client_cert;
289
290#if defined(LWS_ROLE_H2)
291	wsi->txc.manual_initial_tx_credit =
292			(int32_t)i->manual_initial_tx_credit;
293#endif
294
295	wsi->a.protocol = &wsi->a.vhost->protocols[0];
296	wsi->client_pipeline = !!(i->ssl_connection & LCCSCF_PIPELINE);
297	wsi->client_no_follow_redirect = !!(i->ssl_connection &
298					    LCCSCF_HTTP_NO_FOLLOW_REDIRECT);
299
300	/*
301	 * PHASE 5: handle external user_space now, generic alloc is done in
302	 * role finalization
303	 */
304
305	if (i->userdata) {
306		wsi->user_space_externally_allocated = 1;
307		wsi->user_space = i->userdata;
308	}
309
310	if (local) {
311		lwsl_wsi_info(wsi, "vh %s protocol binding to %s\n",
312				wsi->a.vhost->name, local);
313		p = lws_vhost_name_to_protocol(wsi->a.vhost, local);
314		if (p)
315			lws_bind_protocol(wsi, p, __func__);
316		else
317			lwsl_wsi_info(wsi, "unknown protocol %s", local);
318
319		lwsl_wsi_info(wsi, "%s: %s %s entry",
320			    lws_wsi_tag(wsi), wsi->role_ops->name,
321			    wsi->a.protocol ? wsi->a.protocol->name : "none");
322	}
323
324	/*
325	 * PHASE 5: handle external user_space now, generic alloc is done in
326	 * role finalization
327	 */
328
329	if (!wsi->user_space && i->userdata) {
330		wsi->user_space_externally_allocated = 1;
331		wsi->user_space = i->userdata;
332	}
333
334#if defined(LWS_WITH_TLS)
335	wsi->tls.use_ssl = (unsigned int)i->ssl_connection;
336#else
337	if (i->ssl_connection & LCCSCF_USE_SSL) {
338		lwsl_wsi_err(wsi, "lws not configured for tls");
339		goto bail;
340	}
341#endif
342
343	/*
344	 * PHASE 6: stash the things from connect_info that we can't process
345	 * right now, eg, if http binding, without an ah.  If h1 and no ah, we
346	 * will go on the ah waiting list and process those things later (after
347	 * the connect_info and maybe the things pointed to have gone out of
348	 * scope)
349	 *
350	 * However these things are stashed in a generic way at this point,
351	 * with no relationship to http or ah
352	 */
353
354	cisin[CIS_ADDRESS]	= i->address;
355	cisin[CIS_PATH]		= i->path;
356	cisin[CIS_HOST]		= i->host;
357	cisin[CIS_ORIGIN]	= i->origin;
358	cisin[CIS_PROTOCOL]	= i->protocol;
359	cisin[CIS_METHOD]	= i->method;
360	cisin[CIS_IFACE]	= i->iface;
361	cisin[CIS_ALPN]		= i->alpn;
362
363	if (lws_client_stash_create(wsi, cisin))
364		goto bail;
365
366#if defined(LWS_WITH_TLS)
367	if (i->alpn)
368		lws_strncpy(wsi->alpn, i->alpn, sizeof(wsi->alpn));
369#endif
370
371	wsi->a.opaque_user_data = wsi->stash->opaque_user_data =
372		i->opaque_user_data;
373
374#if defined(LWS_WITH_SECURE_STREAMS)
375
376	if (wsi->for_ss) {
377		/* it's related to ss... the options are
378		 *
379		 * LCCSCF_SECSTREAM_PROXY_LINK  : client SSPC link to proxy
380		 * LCCSCF_SECSTREAM_PROXY_ONWARD: proxy's onward connection
381		 */
382		__lws_lc_tag(i->context, &i->context->lcg[
383#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
384		         i->ssl_connection & LCCSCF_SECSTREAM_PROXY_LINK ? LWSLCG_WSI_SSP_CLIENT :
385#if defined(LWS_WITH_SERVER)
386		         (i->ssl_connection & LCCSCF_SECSTREAM_PROXY_ONWARD ? LWSLCG_WSI_SSP_ONWARD :
387#endif
388			  LWSLCG_WSI_CLIENT
389#if defined(LWS_WITH_SERVER)
390			  )
391#endif
392		],
393#else
394				LWSLCG_WSI_CLIENT],
395#endif
396			&wsi->lc, "%s/%s/%s/(%s)", i->method ? i->method : "WS",
397			wsi->role_ops->name, i->address,
398#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
399			wsi->client_bound_sspc ?
400				lws_sspc_tag((lws_sspc_handle_t *)i->opaque_user_data) :
401#endif
402			lws_ss_tag(((lws_ss_handle_t *)i->opaque_user_data)));
403	} else
404#endif
405		__lws_lc_tag(i->context, &i->context->lcg[LWSLCG_WSI_CLIENT], &wsi->lc,
406			     "%s/%s/%s/%s", i->method ? i->method : "WS",
407			     wsi->role_ops->name ? wsi->role_ops->name : "novh", vh->name, i->address);
408
409	lws_metrics_tag_wsi_add(wsi, "vh", wsi->a.vhost->name);
410
411	/*
412	 * at this point user callbacks like
413	 * LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER will be interested to
414	 * know the parent... eg for proxying we can grab extra headers from
415	 * the parent's incoming ah and add them to the child client handshake
416	 */
417
418	if (i->parent_wsi) {
419		lwsl_wsi_info(wsi, "created as child %s",
420			      lws_wsi_tag(i->parent_wsi));
421		wsi->parent = i->parent_wsi;
422		safe = wsi->sibling_list = i->parent_wsi->child_list;
423		i->parent_wsi->child_list = wsi;
424	}
425
426	/*
427	 * PHASE 7: Do any role-specific finalization processing.  We can still
428	 * see important info things via wsi->stash
429	 */
430
431	if (lws_rops_fidx(wsi->role_ops, LWS_ROPS_client_bind)) {
432
433		int n = lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_client_bind).
434							client_bind(wsi, NULL);
435
436		if (n && i->parent_wsi)
437			/* unpick from parent */
438			i->parent_wsi->child_list = safe;
439
440		if (n < 0)
441			/* we didn't survive, wsi is freed */
442			goto bail2;
443
444		if (n)
445			/* something else failed, wsi needs freeing */
446			goto bail;
447	}
448
449	/* let the caller's optional wsi storage have the wsi we created */
450
451	if (i->pwsi)
452		*i->pwsi = wsi;
453
454	if (!wsi->a.protocol)
455		/* we must have one protocol or another bound by this point */
456		goto bail;
457
458	/* PHASE 8: notify protocol with role-specific connected callback */
459
460	/* raw socket per se doesn't want this... raw socket proxy wants it... */
461
462	if (wsi->role_ops != &role_ops_raw_skt ||
463	    (i->local_protocol_name &&
464	     !strcmp(i->local_protocol_name, "raw-proxy"))) {
465		lwsl_wsi_debug(wsi, "adoption cb %d to %s %s",
466			   wsi->role_ops->adoption_cb[0],
467			   wsi->role_ops->name, wsi->a.protocol->name);
468
469		wsi->a.protocol->callback(wsi, wsi->role_ops->adoption_cb[0],
470				wsi->user_space, NULL, 0);
471	}
472
473#if defined(LWS_WITH_HUBBUB)
474	if (i->uri_replace_to)
475		wsi->http.rw = lws_rewrite_create(wsi, html_parser_cb,
476					     i->uri_replace_from,
477					     i->uri_replace_to);
478#endif
479
480	if (i->method && (!strcmp(i->method, "RAW") // ||
481//			  !strcmp(i->method, "MQTT")
482	)) {
483
484		/*
485		 * Not for MQTT here, since we don't know if we will
486		 * pipeline it or not...
487		 */
488
489#if defined(LWS_WITH_TLS)
490
491		wsi->tls.ssl = NULL;
492
493		if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
494			const char *cce = NULL;
495
496			switch (
497#if !defined(LWS_WITH_SYS_ASYNC_DNS)
498			lws_client_create_tls(wsi, &cce, 1)
499#else
500			lws_client_create_tls(wsi, &cce, 0)
501#endif
502			) {
503			case 1:
504				return wsi;
505			case 0:
506				break;
507			default:
508				goto bail3;
509			}
510		}
511#endif
512
513
514		/* fallthru */
515
516		wsi = lws_http_client_connect_via_info2(wsi);
517	}
518
519	if (wsi)
520		/*
521		 * If it subsequently fails, report CONNECTION_ERROR,
522		 * because we're going to return a non-error return now.
523		 */
524		wsi->client_suppress_CONNECTION_ERROR = 0;
525
526	return wsi;
527
528#if defined(LWS_WITH_TLS)
529bail3:
530	lwsl_wsi_info(wsi, "tls start fail");
531	lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "tls start fail");
532
533	if (i->pwsi)
534		*i->pwsi = NULL;
535
536	return NULL;
537#endif
538
539bail:
540#if defined(LWS_WITH_TLS)
541	if (wsi->tls.ssl)
542		lws_tls_restrict_return(wsi);
543#endif
544
545	lws_free_set_NULL(wsi->stash);
546	lws_fi_destroy(&wsi->fic);
547	lws_free(wsi);
548#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
549bail2:
550#endif
551
552	if (i->pwsi)
553		*i->pwsi = NULL;
554
555	return NULL;
556}
557