1/*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2019 - 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/* current SS Serialization protocol version */
26#define LWS_SSS_CLIENT_PROTOCOL_VERSION 1
27
28/*
29 * Secure Stream state
30 */
31
32typedef enum {
33	SSSEQ_IDLE,
34	SSSEQ_TRY_CONNECT,
35	SSSEQ_TRY_CONNECT_NAUTH,
36	SSSEQ_TRY_CONNECT_SAUTH,
37	SSSEQ_RECONNECT_WAIT,
38	SSSEQ_DO_RETRY,
39	SSSEQ_CONNECTED,
40} lws_ss_seq_state_t;
41
42struct conn;
43
44/**
45 * lws_ss_handle_t: publicly-opaque secure stream object implementation
46 */
47
48typedef struct lws_ss_handle {
49	lws_ss_info_t		info;	  /**< copy of stream creation info */
50
51	lws_lifecycle_t		lc;
52
53#if defined(LWS_WITH_SYS_METRICS)
54	lws_metrics_caliper_compose(cal_txn)
55#endif
56
57	struct lws_dll2		list;	  /**< pt lists active ss */
58	struct lws_dll2		to_list;  /**< pt lists ss with pending to-s */
59#if defined(LWS_WITH_SERVER)
60	struct lws_dll2		cli_list;  /**< same server clients list */
61#endif
62#if defined(LWS_WITH_SYS_FAULT_INJECTION)
63	lws_fi_ctx_t		fic;	/**< Fault Injection context */
64#endif
65
66	struct lws_dll2_owner	src_list; /**< sink's list of bound sources */
67
68	struct lws_context      *context; /**< lws context we are created on */
69	const lws_ss_policy_t	*policy;  /**< system policy for stream */
70
71	struct lws_sequencer	*seq;	  /**< owning sequencer if any */
72	struct lws		*wsi;	  /**< the stream wsi if any */
73
74	struct conn		*conn_if_sspc_onw;
75
76#if defined(LWS_WITH_SSPLUGINS)
77	void			*nauthi;  /**< the nauth plugin instance data */
78	void			*sauthi;  /**< the sauth plugin instance data */
79#endif
80
81	lws_ss_metadata_t	*metadata;
82#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR)
83	lws_ss_metadata_t	*instant_metadata; /**< for set instant metadata */
84	struct lwsac            *imd_ac;           /**< for get custom header */
85#endif
86	const lws_ss_policy_t	*rideshare;
87	struct lws_ss_handle	*h_in_svc;
88
89#if defined(LWS_WITH_CONMON)
90	char			*conmon_json;
91#endif
92
93	//struct lws_ss_handle	*h_sink;  /**< sink we are bound to, or NULL */
94	//void 			*sink_obj;/**< sink's private object representing us */
95
96	lws_sorted_usec_list_t	sul_timeout;
97	lws_sorted_usec_list_t	sul;
98	lws_ss_tx_ordinal_t	txord;
99
100	/* protocol-specific connection helpers */
101
102	union {
103
104		/* ...for http-related protocols... */
105
106		struct {
107
108			/* common to all http-related protocols */
109
110			/* incoming multipart parsing */
111
112			char boundary[24];	/* --boundary from headers */
113			uint8_t boundary_len;	/* length of --boundary */
114			uint8_t boundary_seq;	/* current match amount */
115			uint8_t boundary_dashes; /* check for -- after */
116			uint8_t boundary_post; /* swallow post CRLF */
117
118			uint8_t som:1;	/* SOM has been sent */
119			uint8_t eom:1;  /* EOM has been sent */
120			uint8_t any:1;	/* any content has been sent */
121
122
123			uint8_t good_respcode:1; /* 200 type response code */
124
125			union {
126				struct { /* LWSSSP_H1 */
127#if defined(WIN32)
128					uint8_t dummy;
129#endif
130				} h1;
131				struct { /* LWSSSP_H2 */
132#if defined(WIN32)
133					uint8_t dummy;
134#endif
135				} h2;
136				struct { /* LWSSSP_WS */
137#if defined(WIN32)
138					uint8_t dummy;
139#endif
140				} ws;
141			} u;
142		} http;
143
144		/* details for non-http related protocols... */
145#if defined(LWS_ROLE_MQTT)
146		struct {
147			lws_mqtt_topic_elem_t		topic_qos;
148			lws_mqtt_topic_elem_t		sub_top;
149			lws_mqtt_subscribe_param_t 	sub_info;
150			lws_mqtt_subscribe_param_t 	shadow_sub;
151			/* allocation that must be destroyed with conn */
152			void				*heap_baggage;
153			const char			*subscribe_to;
154			size_t				subscribe_to_len;
155			struct lws_buflist		*buflist_unacked;
156			uint32_t			unacked_size;
157			uint8_t				retry_count;
158			uint8_t				send_unacked:1;
159		} mqtt;
160#endif
161#if defined(LWS_WITH_SYS_SMD)
162		struct {
163			struct lws_smd_peer		*smd_peer;
164			lws_sorted_usec_list_t		sul_write;
165		} smd;
166#endif
167	} u;
168
169	unsigned long		writeable_len;
170
171	lws_ss_constate_t	connstate;/**< public connection state */
172	lws_ss_seq_state_t	seqstate; /**< private connection state */
173	lws_ss_state_return_t	pending_ret; /**< holds desired disposition
174						* for ss during CCE */
175
176#if defined(LWS_WITH_SERVER)
177	int			txn_resp;
178#endif
179
180	uint16_t		retry;	  /**< retry / backoff tracking */
181#if defined(LWS_WITH_CONMON)
182	uint16_t		conmon_len;
183#endif
184	int16_t			temp16;
185
186	uint8_t			tsi;	  /**< service thread idx, usually 0 */
187	uint8_t			subseq;	  /**< emulate SOM tracking */
188	uint8_t			txn_ok;	  /**< 1 = transaction was OK */
189	uint8_t			prev_ss_state;
190
191	uint8_t			txn_resp_set:1; /**< user code set one */
192	uint8_t			txn_resp_pending:1; /**< we have yet to send */
193	uint8_t			hanging_som:1;
194	uint8_t			inside_msg:1;
195	uint8_t			being_serialized:1; /* we are not the consumer */
196	uint8_t			destroying:1;
197	uint8_t			ss_dangling_connected:1;
198	uint8_t			proxy_onward:1; /* opaque is conn */
199	uint8_t			inside_connect:1; /* set if we are currently
200						   * creating the onward
201						   * connect */
202} lws_ss_handle_t;
203
204/* connection helper that doesn't need to hang around after connection starts */
205
206union lws_ss_contemp {
207#if defined(LWS_ROLE_MQTT)
208	lws_mqtt_client_connect_param_t ccp;
209#else
210#if defined(WIN32)
211	uint8_t	dummy;
212#endif
213#endif
214};
215
216/*
217 * When allocating the opaque handle, we overallocate for:
218 *
219 *  1) policy->nauth_plugin->alloc (.nauthi) if any
220 *  2) policy->sauth_plugin->alloc (.sauthi) if any
221 *  3) copy of creation info stream type pointed to by info.streamtype... this
222 *     may be arbitrarily long and since it may be coming from socket ipc and be
223 *     temporary at creation time, we need a place for the copy to stay in scope
224 *  4) copy of info->streamtype contents
225 */
226
227
228/* the user object allocation is immediately after the ss object allocation */
229#define ss_to_userobj(ss) ((void *)&(ss)[1])
230
231/*
232 * serialization parser state
233 */
234
235enum {
236	KIND_C_TO_P,
237	KIND_SS_TO_P,
238};
239
240struct lws_ss_serialization_parser {
241	char			streamtype[32];
242	char			rideshare[32];
243	char			metadata_name[32];
244
245	uint64_t		ust_pwait;
246
247	lws_ss_metadata_t	*ssmd;
248	uint8_t			*rxmetaval;
249
250	int			ps;
251	int			ctr;
252
253	uint32_t		usd_phandling;
254	uint32_t		flags;
255	uint32_t		client_pid;
256	int32_t			temp32;
257
258	int32_t			txcr_out;
259	int32_t			txcr_in;
260	uint16_t		rem;
261
262	uint8_t			type;
263	uint8_t			frag1;
264	uint8_t			slen;
265	uint8_t			rsl_pos;
266	uint8_t			rsl_idx;
267	uint8_t			protocol_version;
268};
269
270/*
271 * Unlike locally-fulfilled SS, SSS doesn't have to hold metadata on client side
272 * but pass it through to the proxy.  The client side doesn't know the real
273 * metadata names that are available in the policy (since it's hardcoded in code
274 * no point passing them back to the client from the policy).  Because of that,
275 * it doesn't know how many to allocate when we create the sspc_handle either.
276 *
277 * So we use a linked-list of changed-but-not-yet-proxied metadata allocated
278 * on the heap and items removed as they are proxied out.  Anything on the list
279 * is sent to the proxy before any requested tx is handled.
280 *
281 * This is also used to queue tx credit changes
282 */
283
284typedef struct lws_sspc_metadata {
285	lws_dll2_t	list;
286	char		name[32];  /* empty string, then actually TCXR */
287	size_t		len;
288	int		tx_cr_adjust;
289
290	/* the value of length .len is overallocated after this */
291} lws_sspc_metadata_t;
292
293/* state of the upstream proxy onward connection */
294
295enum {
296	LWSSSPC_ONW_NONE,
297	LWSSSPC_ONW_REQ,
298	LWSSSPC_ONW_ONGOING,
299	LWSSSPC_ONW_CONN,
300};
301
302typedef struct lws_sspc_handle {
303	char			rideshare_list[128];
304
305	lws_lifecycle_t		lc;
306
307	lws_ss_info_t		ssi;
308	lws_sorted_usec_list_t	sul_retry;
309
310	struct lws_ss_serialization_parser parser;
311
312#if defined(LWS_WITH_SYS_FAULT_INJECTION)
313	lws_fi_ctx_t		fic;	/**< Fault Injection context */
314#endif
315
316	lws_dll2_owner_t	metadata_owner;
317	lws_dll2_owner_t	metadata_owner_rx;
318
319	struct lws_dll2		client_list;
320	struct lws_tx_credit	txc;
321
322#if defined(LWS_WITH_SYS_METRICS)
323	lws_metrics_caliper_compose(cal_txn)
324#endif
325
326	struct lws		*cwsi;
327
328	struct lws_dsh		*dsh;
329	struct lws_context	*context;
330
331	struct lws_sspc_handle	*h_in_svc;
332	/*
333	 * Used to detect illegal lws_sspc_destroy() calls while still
334	 * being serviced
335	 */
336
337	lws_usec_t		us_earliest_write_req;
338	lws_usec_t		us_start_upstream;
339
340	unsigned long		writeable_len;
341
342	lws_ss_conn_states_t	state;
343
344	uint32_t		timeout_ms;
345	uint32_t		ord;
346
347	int16_t			temp16;
348
349	uint8_t			rideshare_ofs[4];
350	uint8_t			rsidx;
351
352	uint8_t			prev_ss_state;
353
354	uint8_t			conn_req_state:2;
355	uint8_t			destroying:1;
356	uint8_t			non_wsi:1;
357	uint8_t			ignore_txc:1;
358	uint8_t			pending_timeout_update:1;
359	uint8_t			pending_writeable_len:1;
360	uint8_t			creating_cb_done:1;
361	uint8_t			ss_dangling_connected:1;
362} lws_sspc_handle_t;
363
364typedef struct backoffs {
365	struct backoffs *next;
366	const char *name;
367	lws_retry_bo_t r;
368} backoff_t;
369
370union u {
371	backoff_t		*b;
372	lws_ss_x509_t		*x;
373	lws_ss_trust_store_t	*t;
374	lws_ss_policy_t		*p;
375	lws_ss_auth_t		*a;
376	lws_metric_policy_t	*m;
377};
378
379enum {
380	LTY_BACKOFF,
381	LTY_X509,
382	LTY_TRUSTSTORE,
383	LTY_POLICY,
384	LTY_AUTH,
385	LTY_METRICS,
386
387	_LTY_COUNT /* always last */
388};
389
390
391struct policy_cb_args {
392	struct lejp_ctx jctx;
393	struct lws_context *context;
394	struct lwsac *ac;
395
396	const char *socks5_proxy;
397
398	struct lws_b64state b64;
399
400	lws_ss_http_respmap_t respmap[16];
401
402	union u heads[_LTY_COUNT];
403	union u curr[_LTY_COUNT];
404
405	uint8_t *p;
406
407	int count;
408	char pending_respmap;
409
410	uint8_t parse_data:1;
411};
412
413#if defined(LWS_WITH_SYS_SMD)
414extern const lws_ss_policy_t pol_smd;
415#endif
416
417
418/*
419 * returns one of
420 *
421 * 	LWSSSSRET_OK
422 *	LWSSSSRET_DISCONNECT_ME
423 *	LWSSSSRET_DESTROY_ME
424 */
425int
426lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par,
427			 struct lws_context *context,
428			 struct lws_dsh *dsh, const uint8_t *cp, size_t len,
429			 lws_ss_conn_states_t *state, void *parconn,
430			 lws_ss_handle_t **pss, lws_ss_info_t *ssi, char client);
431int
432lws_ss_serialize_rx_payload(struct lws_dsh *dsh, const uint8_t *buf,
433			    size_t len, int flags, const char *rsp);
434int
435lws_ss_deserialize_tx_payload(struct lws_dsh *dsh, struct lws *wsi,
436			      lws_ss_tx_ordinal_t ord, uint8_t *buf,
437			      size_t *len, int *flags);
438int
439lws_ss_serialize_state(struct lws *wsi, struct lws_dsh *dsh, lws_ss_constate_t state,
440		       lws_ss_tx_ordinal_t ack);
441
442const lws_ss_policy_t *
443lws_ss_policy_lookup(const struct lws_context *context, const char *streamtype);
444
445/* can be used as a cb from lws_dll2_foreach_safe() to destroy ss */
446int
447lws_ss_destroy_dll(struct lws_dll2 *d, void *user);
448
449int
450lws_sspc_destroy_dll(struct lws_dll2 *d, void *user);
451
452void
453lws_sspc_rxmetadata_destroy(lws_sspc_handle_t *h);
454
455int
456lws_ss_policy_set(struct lws_context *context, const char *name);
457
458int
459lws_ss_sys_fetch_policy(struct lws_context *context);
460
461lws_ss_state_return_t
462lws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs);
463
464lws_ss_state_return_t
465_lws_ss_backoff(lws_ss_handle_t *h, lws_usec_t us_override);
466
467lws_ss_state_return_t
468lws_ss_backoff(lws_ss_handle_t *h);
469
470int
471_lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(lws_ss_state_return_t r, struct lws *wsi,
472			 lws_ss_handle_t **ph);
473
474int
475lws_ss_set_timeout_us(lws_ss_handle_t *h, lws_usec_t us);
476
477void
478ss_proxy_onward_txcr(void *userobj, int bump);
479
480int
481lws_ss_serialize_txcr(struct lws_dsh *dsh, int txcr);
482
483int
484lws_ss_sys_auth_api_amazon_com(struct lws_context *context);
485
486lws_ss_metadata_t *
487lws_ss_get_handle_metadata(struct lws_ss_handle *h, const char *name);
488lws_ss_metadata_t *
489lws_ss_policy_metadata_index(const lws_ss_policy_t *p, size_t index);
490
491#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR)
492lws_ss_metadata_t *
493lws_ss_get_handle_instant_metadata(struct lws_ss_handle *h, const char *name);
494#endif
495
496lws_ss_metadata_t *
497lws_ss_policy_metadata(const lws_ss_policy_t *p, const char *name);
498
499int
500lws_ss_exp_cb_metadata(void *priv, const char *name, char *out, size_t *pos,
501			size_t olen, size_t *exp_ofs);
502
503int
504_lws_ss_set_metadata(lws_ss_metadata_t *omd, const char *name,
505		     const void *value, size_t len);
506
507int
508_lws_ss_alloc_set_metadata(lws_ss_metadata_t *omd, const char *name,
509			   const void *value, size_t len);
510
511lws_ss_state_return_t
512_lws_ss_client_connect(lws_ss_handle_t *h, int is_retry, void *conn_if_sspc_onw);
513
514lws_ss_state_return_t
515_lws_ss_request_tx(lws_ss_handle_t *h);
516
517int
518__lws_ss_proxy_bind_ss_to_conn_wsi(void *parconn, size_t dsh_size);
519
520struct lws_vhost *
521lws_ss_policy_ref_trust_store(struct lws_context *context,
522			      const lws_ss_policy_t *pol, char doref);
523
524lws_ss_state_return_t
525lws_sspc_event_helper(lws_sspc_handle_t *h, lws_ss_constate_t cs,
526		      lws_ss_tx_ordinal_t flags);
527
528int
529lws_ss_check_next_state(lws_lifecycle_t *lc, uint8_t *prevstate,
530			lws_ss_constate_t cs);
531
532int
533lws_ss_check_next_state_ss(lws_ss_handle_t *ss, uint8_t *prevstate,
534			   lws_ss_constate_t cs);
535
536int
537lws_ss_check_next_state_sspc(lws_sspc_handle_t *ss, uint8_t *prevstate,
538			     lws_ss_constate_t cs);
539
540void
541lws_proxy_clean_conn_ss(struct lws *wsi);
542
543int
544lws_ss_cancel_notify_dll(struct lws_dll2 *d, void *user);
545
546int
547lws_sspc_cancel_notify_dll(struct lws_dll2 *d, void *user);
548
549#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) || defined(LWS_WITH_SECURE_STREAMS_CPP)
550int
551lws_ss_policy_unref_trust_store(struct lws_context *context,
552				const lws_ss_policy_t *pol);
553#endif
554
555int
556lws_ss_sys_cpd(struct lws_context *cx);
557
558#if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4)
559int lws_ss_apply_sigv4(struct lws *wsi, struct lws_ss_handle *h,
560		       unsigned char **p, unsigned char *end);
561#endif
562
563#if defined(_DEBUG)
564void
565lws_ss_assert_extant(struct lws_context *cx, int tsi, struct lws_ss_handle *h);
566#else
567#define lws_ss_assert_extant(_a, _b, _c)
568#endif
569
570typedef int (* const secstream_protocol_connect_munge_t)(lws_ss_handle_t *h,
571		char *buf, size_t len, struct lws_client_connect_info *i,
572		union lws_ss_contemp *ct);
573
574typedef int (* const secstream_protocol_add_txcr_t)(lws_ss_handle_t *h, int add);
575
576typedef int (* const secstream_protocol_get_txcr_t)(lws_ss_handle_t *h);
577
578struct ss_pcols {
579	const char					*name;
580	const char					*alpn;
581	const struct lws_protocols			*protocol;
582	secstream_protocol_connect_munge_t		munge;
583	secstream_protocol_add_txcr_t			tx_cr_add;
584	secstream_protocol_get_txcr_t			tx_cr_est;
585};
586
587/*
588 * Because both sides of the connection share the conn, we allocate it
589 * during accepted adoption, and both sides point to it.
590 *
591 * When .ss or .wsi close, they must NULL their entry here so no dangling
592 * refereneces.
593 *
594 * The last one of the accepted side and the onward side to close frees it.
595 */
596
597lws_ss_state_return_t
598lws_conmon_ss_json(lws_ss_handle_t *h);
599
600void
601ss_proxy_onward_link_req_writeable(lws_ss_handle_t *h_onward);
602
603struct conn {
604	struct lws_ss_serialization_parser parser;
605
606	lws_dsh_t		*dsh;	/* unified buffer for both sides */
607	struct lws		*wsi;	/* the proxy's client side */
608	lws_ss_handle_t		*ss;	/* the onward, ss side */
609
610	lws_ss_conn_states_t	state;
611
612	char			onward_in_flow_control;
613};
614
615extern const struct ss_pcols ss_pcol_h1;
616extern const struct ss_pcols ss_pcol_h2;
617extern const struct ss_pcols ss_pcol_ws;
618extern const struct ss_pcols ss_pcol_mqtt;
619extern const struct ss_pcols ss_pcol_raw;
620
621extern const struct lws_protocols protocol_secstream_h1;
622extern const struct lws_protocols protocol_secstream_h2;
623extern const struct lws_protocols protocol_secstream_ws;
624extern const struct lws_protocols protocol_secstream_mqtt;
625extern const struct lws_protocols protocol_secstream_raw;
626
627