• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
32 typedef 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 
42 struct conn;
43 
44 /**
45  * lws_ss_handle_t: publicly-opaque secure stream object implementation
46  */
47 
48 typedef 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 
206 union 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 
235 enum {
236 	KIND_C_TO_P,
237 	KIND_SS_TO_P,
238 };
239 
240 struct 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 
284 typedef 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 
295 enum {
296 	LWSSSPC_ONW_NONE,
297 	LWSSSPC_ONW_REQ,
298 	LWSSSPC_ONW_ONGOING,
299 	LWSSSPC_ONW_CONN,
300 };
301 
302 typedef 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 
364 typedef struct backoffs {
365 	struct backoffs *next;
366 	const char *name;
367 	lws_retry_bo_t r;
368 } backoff_t;
369 
370 union 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 
379 enum {
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 
391 struct 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)
414 extern 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  */
425 int
426 lws_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);
431 int
432 lws_ss_serialize_rx_payload(struct lws_dsh *dsh, const uint8_t *buf,
433 			    size_t len, int flags, const char *rsp);
434 int
435 lws_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);
438 int
439 lws_ss_serialize_state(struct lws *wsi, struct lws_dsh *dsh, lws_ss_constate_t state,
440 		       lws_ss_tx_ordinal_t ack);
441 
442 const lws_ss_policy_t *
443 lws_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 */
446 int
447 lws_ss_destroy_dll(struct lws_dll2 *d, void *user);
448 
449 int
450 lws_sspc_destroy_dll(struct lws_dll2 *d, void *user);
451 
452 void
453 lws_sspc_rxmetadata_destroy(lws_sspc_handle_t *h);
454 
455 int
456 lws_ss_policy_set(struct lws_context *context, const char *name);
457 
458 int
459 lws_ss_sys_fetch_policy(struct lws_context *context);
460 
461 lws_ss_state_return_t
462 lws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs);
463 
464 lws_ss_state_return_t
465 _lws_ss_backoff(lws_ss_handle_t *h, lws_usec_t us_override);
466 
467 lws_ss_state_return_t
468 lws_ss_backoff(lws_ss_handle_t *h);
469 
470 int
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 
474 int
475 lws_ss_set_timeout_us(lws_ss_handle_t *h, lws_usec_t us);
476 
477 void
478 ss_proxy_onward_txcr(void *userobj, int bump);
479 
480 int
481 lws_ss_serialize_txcr(struct lws_dsh *dsh, int txcr);
482 
483 int
484 lws_ss_sys_auth_api_amazon_com(struct lws_context *context);
485 
486 lws_ss_metadata_t *
487 lws_ss_get_handle_metadata(struct lws_ss_handle *h, const char *name);
488 lws_ss_metadata_t *
489 lws_ss_policy_metadata_index(const lws_ss_policy_t *p, size_t index);
490 
491 #if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR)
492 lws_ss_metadata_t *
493 lws_ss_get_handle_instant_metadata(struct lws_ss_handle *h, const char *name);
494 #endif
495 
496 lws_ss_metadata_t *
497 lws_ss_policy_metadata(const lws_ss_policy_t *p, const char *name);
498 
499 int
500 lws_ss_exp_cb_metadata(void *priv, const char *name, char *out, size_t *pos,
501 			size_t olen, size_t *exp_ofs);
502 
503 int
504 _lws_ss_set_metadata(lws_ss_metadata_t *omd, const char *name,
505 		     const void *value, size_t len);
506 
507 int
508 _lws_ss_alloc_set_metadata(lws_ss_metadata_t *omd, const char *name,
509 			   const void *value, size_t len);
510 
511 lws_ss_state_return_t
512 _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry, void *conn_if_sspc_onw);
513 
514 lws_ss_state_return_t
515 _lws_ss_request_tx(lws_ss_handle_t *h);
516 
517 int
518 __lws_ss_proxy_bind_ss_to_conn_wsi(void *parconn, size_t dsh_size);
519 
520 struct lws_vhost *
521 lws_ss_policy_ref_trust_store(struct lws_context *context,
522 			      const lws_ss_policy_t *pol, char doref);
523 
524 lws_ss_state_return_t
525 lws_sspc_event_helper(lws_sspc_handle_t *h, lws_ss_constate_t cs,
526 		      lws_ss_tx_ordinal_t flags);
527 
528 int
529 lws_ss_check_next_state(lws_lifecycle_t *lc, uint8_t *prevstate,
530 			lws_ss_constate_t cs);
531 
532 int
533 lws_ss_check_next_state_ss(lws_ss_handle_t *ss, uint8_t *prevstate,
534 			   lws_ss_constate_t cs);
535 
536 int
537 lws_ss_check_next_state_sspc(lws_sspc_handle_t *ss, uint8_t *prevstate,
538 			     lws_ss_constate_t cs);
539 
540 void
541 lws_proxy_clean_conn_ss(struct lws *wsi);
542 
543 int
544 lws_ss_cancel_notify_dll(struct lws_dll2 *d, void *user);
545 
546 int
547 lws_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)
550 int
551 lws_ss_policy_unref_trust_store(struct lws_context *context,
552 				const lws_ss_policy_t *pol);
553 #endif
554 
555 int
556 lws_ss_sys_cpd(struct lws_context *cx);
557 
558 #if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4)
559 int 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)
564 void
565 lws_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 
570 typedef 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 
574 typedef int (* const secstream_protocol_add_txcr_t)(lws_ss_handle_t *h, int add);
575 
576 typedef int (* const secstream_protocol_get_txcr_t)(lws_ss_handle_t *h);
577 
578 struct 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 
597 lws_ss_state_return_t
598 lws_conmon_ss_json(lws_ss_handle_t *h);
599 
600 void
601 ss_proxy_onward_link_req_writeable(lws_ss_handle_t *h_onward);
602 
603 struct 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 
615 extern const struct ss_pcols ss_pcol_h1;
616 extern const struct ss_pcols ss_pcol_h2;
617 extern const struct ss_pcols ss_pcol_ws;
618 extern const struct ss_pcols ss_pcol_mqtt;
619 extern const struct ss_pcols ss_pcol_raw;
620 
621 extern const struct lws_protocols protocol_secstream_h1;
622 extern const struct lws_protocols protocol_secstream_h2;
623 extern const struct lws_protocols protocol_secstream_ws;
624 extern const struct lws_protocols protocol_secstream_mqtt;
625 extern const struct lws_protocols protocol_secstream_raw;
626 
627