• 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  * included from libwebsockets.h
25  */
26 
27 typedef int (*plugin_auth_status_cb)(struct lws_ss_handle *ss, int status);
28 
29 /**
30  * lws_ss_plugin_auth_t - api for an auth plugin
31  *
32  * Auth plugins create and sequence authenticated connections that can carry one
33  * or more streams to an endpoint.  That may involve other connections to other
34  * places to eg, gather authenticated tokens and then make the real connection
35  * using the tokens.
36  *
37  * The secure stream object contains members to record which auth plugin the
38  * stream is bound to and an over-allocation of the secure stream object to
39  * contain the plugin auth private data.
40  *
41  * The auth plugin controls the state of the stream connection via the status
42  * callback, and handles retries.
43  *
44  * Network connections may require one kind of auth sequencing, and streams
45  * inside those connections another kind of auth sequencing depending on their
46  * role.  So the secure stream object allows defining plugins for both kinds.
47  *
48  * Streams may disappear at any time and require reauth to bring a new one up.
49  * The auth plugin sequencer will connect / reconnect either on demand, or from
50  * the start and after any connectivity loss if any stream using the connection
51  * has the LWSSSPOLF_NAILED_UP flag.
52  */
53 
54 #if defined(LWS_WITH_SSPLUGINS)
55 typedef struct lws_ss_plugin {
56 	struct lws_ss_plugin	*next;
57 	const char		*name;	/**< auth plugin name */
58 	size_t			alloc;	/**< size of private allocation */
59 
60 	int			(*create)(struct lws_ss_handle *ss, void *info,
61 					  plugin_auth_status_cb status);
62 				/**< called when the auth plugin is instantiated
63 				     and bound to the secure stream.  status is
64 				     called back with advisory information about
65 				     the authenticated stream state as it
66 				     proceeds */
67 	int			(*destroy)(struct lws_ss_handle *ss);
68 				/**< called when the related secure stream is
69 				     being destroyed, and anything the auth
70 				     plugin is doing should also be destroyed */
71 	int			(*munge)(struct lws_ss_handle *ss, char *path,
72 					 size_t path_len);
73 				/**< if the plugin needs to munge transactions
74 				     that have metadata outside the payload (eg,
75 				     add http headers) this callback will give
76 				     it the opportunity to do so */
77 } lws_ss_plugin_t;
78 #endif
79 
80 /* the public, const metrics policy definition */
81 
82 typedef struct lws_metric_policy {
83 	/* order of first two mandated by JSON policy parsing scope union */
84 	const struct lws_metric_policy	*next;
85 	const char			*name;
86 
87 	const char			*report;
88 
89 	/**< the metrics policy name in the policy, used to bind to it */
90 	uint64_t			us_schedule;
91 	/**< us interval between lws_system metrics api reports */
92 
93 	uint32_t			us_decay_unit;
94 	/**< how many us to decay avg by half, 0 = no decay */
95 	uint8_t				min_contributors;
96 	/**< before we can judge something is an outlier */
97 } lws_metric_policy_t;
98 
99 typedef struct lws_ss_x509 {
100 	struct lws_ss_x509	*next;
101 	const char		*vhost_name; /**< vhost name using cert ctx */
102 	const uint8_t		*ca_der;	/**< DER x.509 cert */
103 	size_t			ca_der_len;	/**< length of DER cert */
104 	uint8_t			keep:1; /**< ie, if used in server tls */
105 } lws_ss_x509_t;
106 
107 enum {
108 	LWSSSPOLF_OPPORTUNISTIC					= (1 << 0),
109 	/**< the connection doesn't exist unless client asks to write */
110 	LWSSSPOLF_NAILED_UP					= (1 << 1),
111 	/**< the connection tries to be connected the whole life of the ss */
112 	LWSSSPOLF_URGENT_TX					= (1 << 2),
113 	/**< this connection carries critical tx data */
114 	LWSSSPOLF_URGENT_RX					= (1 << 3),
115 	/**< this connection carries critical rx data */
116 	LWSSSPOLF_TLS						= (1 << 4),
117 	/**< stream must be connected via a tls tunnel */
118 	LWSSSPOLF_LONG_POLL					= (1 << 5),
119 	/**< stream used to receive async rx at arbitrary intervals */
120 	LWSSSPOLF_AUTH_BEARER					= (1 << 6),
121 	/**< for http, use lws_system auth token 0 in authentication: bearer */
122 	LWSSSPOLF_HTTP_NO_CONTENT_LENGTH			= (1 << 7),
123 	/**< don't add any content length even if we have it */
124 	LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM			= (1 << 8),
125 	/**< set the client flag LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM */
126 	LWSSSPOLF_H2_QUIRK_OVERFLOWS_TXCR			= (1 << 9),
127 	/**< set the client flag LCCSCF_H2_QUIRK_OVERFLOWS_TXCR */
128 	LWSSSPOLF_H2_QUIRK_UNCLEAN_HPACK_STATE			= (1 << 10),
129 	/**< HPACK decoder state does not end cleanly */
130 	LWSSSPOLF_HTTP_MULTIPART				= (1 << 11),
131 	/**< indicates stream goes out as specifically a multipart mime POST
132 	 * section... if the tx has LWSSS_FLAG_COALESCE_CONTINUES flag then more
133 	 * multipart sections are expected.  Without it, the multipart wrapper
134 	 * is closed and the http transaction issue completed when this message
135 	 * finishes. */
136 	LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED			= (1 << 12),
137 	/**< set up lws_system client cert */
138 	LWSSSPOLF_LOCAL_SINK					= (1 << 13),
139 	/**< expected to bind to a local sink only */
140 	LWSSSPOLF_WAKE_SUSPEND__VALIDITY			= (1 << 14),
141 	/**< this stream's idle validity checks are critical enough we
142 	 * should arrange to wake from suspend to perform them
143 	 */
144 	LWSSSPOLF_SERVER					= (1 << 15),
145 	/**< we listen on a socket as a server */
146 	LWSSSPOLF_ALLOW_REDIRECTS				= (1 << 16),
147 	/**< follow redirects */
148 	LWSSSPOLF_HTTP_MULTIPART_IN				= (1 << 17),
149 	/**< handle inbound multipart mime at SS level */
150 
151 	LWSSSPOLF_ATTR_LOW_LATENCY				= (1 << 18),
152 	/**< stream requires low latency */
153 	LWSSSPOLF_ATTR_HIGH_THROUGHPUT				= (1 << 19),
154 	/**< stream requires high throughput */
155 	LWSSSPOLF_ATTR_HIGH_RELIABILITY				= (1 << 20),
156 	/**< stream requires high reliability */
157 	LWSSSPOLF_ATTR_LOW_COST					= (1 << 21),
158 	/**< stream is not critical and should be handled as cheap as poss */
159 	LWSSSPOLF_PERF						= (1 << 22),
160 	/**< capture and report performace information */
161 	LWSSSPOLF_DIRECT_PROTO_STR				= (1 << 23),
162 	/**< metadata as direct protocol string, e.g. http header */
163 	LWSSSPOLF_HTTP_CACHE_COOKIES				= (1 << 24),
164 	/**< Record http cookies and pass them back on future requests */
165 	LWSSSPOLF_PRIORITIZE_READS				= (1 << 25),
166 	/**< prioritize clearing reads at expense of writes */
167 
168 };
169 
170 typedef struct lws_ss_trust_store {
171 	struct lws_ss_trust_store	*next;
172 	const char			*name;
173 
174 	const lws_ss_x509_t		*ssx509[6];
175 	int				count;
176 } lws_ss_trust_store_t;
177 
178 enum {
179 	LWSSSP_H1,
180 	LWSSSP_H2,
181 	LWSSSP_WS,
182 	LWSSSP_MQTT,
183 	LWSSSP_RAW,
184 
185 
186 	LWSSS_HBI_AUTH = 0,
187 	LWSSS_HBI_DSN,
188 	LWSSS_HBI_FWV,
189 	LWSSS_HBI_TYPE,
190 
191 	_LWSSS_HBI_COUNT /* always last */
192 };
193 
194 /*
195  * This does for both the static policy metadata entry, and the runtime metadata
196  * handling object.
197  */
198 
199 typedef struct lws_ss_metadata {
200 	struct lws_ss_metadata	*next;
201 	const char		*name;
202 	void			*value__may_own_heap;
203 	size_t			length;
204 
205 	uint8_t			value_length; /* only valid if set by policy */
206 	uint8_t			value_is_http_token; /* valid if set by policy */
207 #if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR)
208 	uint8_t			name_on_lws_heap:1;  /* proxy metatadata does this */
209 #endif
210 	uint8_t			value_on_lws_heap:1; /* proxy + rx metadata does this */
211 #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
212 	uint8_t			pending_onward:1;
213 #endif
214 } lws_ss_metadata_t;
215 
216 typedef struct lws_ss_http_respmap {
217 	uint16_t		resp;	/* the http response code */
218 	uint16_t		state;	/* low 16-bits of associated state */
219 } lws_ss_http_respmap_t;
220 
221 /*
222  * This is a mapping between an auth streamtype and a name and other information
223  * that can be independently instantiated.  Other streamtypes can indicate they
224  * require this authentication on their connection.
225  */
226 
227 typedef struct lws_ss_auth {
228 	struct lws_ss_auth	*next;
229 	const char		*name;
230 
231 	const char		*type;
232 	const char		*streamtype;
233 	uint8_t			blob_index;
234 } lws_ss_auth_t;
235 
236 /**
237  * lws_ss_policy_t: policy database entry for a stream type
238  *
239  * Decides the system policy for how to implement connections of name
240  * .streamtype.
241  *
242  * Streams may need one kind of auth sequencing for the network connection and
243  * another kind of auth sequencing for the streams that are carried inside it,
244  * this is the purpose of .nauth and .sauth.  Both are optional and may be NULL.
245  *
246  * An array of these is set at context creation time, ending with one with a
247  * NULL streamtype.
248  */
249 typedef struct lws_ss_policy {
250 	struct lws_ss_policy	*next;
251 	const char		*streamtype; /**< stream type lhs to match on */
252 
253 	const char		*endpoint;   /**< DNS address to connect to */
254 	const char		*rideshare_streamtype; /**< optional transport
255 					* on another, preexisting stream of this
256 					* streamtype name */
257 	const char		*payload_fmt;
258 	const char		*socks5_proxy;
259 	lws_ss_metadata_t	*metadata; /* linked-list of metadata */
260 	const lws_metric_policy_t *metrics; /* linked-list of metric policies */
261 	const lws_ss_auth_t	*auth; /* NULL or auth object we bind to */
262 
263 	/* protocol-specific connection policy details */
264 
265 	union {
266 
267 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) || defined(LWS_ROLE_WS)
268 
269 		/* details for http-related protocols... */
270 
271 		struct {
272 
273 			/* common to all http-related protocols */
274 
275 			const char	*method;
276 			const char	*url;
277 
278 			const char	*multipart_name;
279 			const char	*multipart_filename;
280 			const char	*multipart_content_type;
281 
282 			const char	*blob_header[_LWSSS_HBI_COUNT];
283 			const char	*auth_preamble;
284 
285 			const lws_ss_http_respmap_t *respmap;
286 
287 			union {
288 //				struct { /* LWSSSP_H1 */
289 //				} h1;
290 //				struct { /* LWSSSP_H2 */
291 //				} h2;
292 				struct { /* LWSSSP_WS */
293 					const char	*subprotocol;
294 					uint8_t		binary;
295 					/* false = TEXT, true = BINARY */
296 				} ws;
297 			} u;
298 
299 			uint16_t	resp_expect;
300 			uint8_t		count_respmap;
301 			uint8_t		fail_redirect:1;
302 		} http;
303 
304 #endif
305 
306 #if defined(LWS_ROLE_MQTT)
307 
308 		struct {
309 			const char	*topic;	    /* stream sends on this topic */
310 			const char	*subscribe; /* stream subscribes to this topic */
311 
312 			const char	*will_topic;
313 			const char	*will_message;
314 
315 			const char	*birth_topic;
316 			const char	*birth_message;
317 
318 			uint16_t	keep_alive;
319 			uint8_t		qos;
320 			uint8_t		clean_start;
321 			uint8_t		will_qos;
322 			uint8_t		will_retain;
323 			uint8_t		birth_qos;
324 			uint8_t		birth_retain;
325 			uint8_t		aws_iot;
326 
327 		} mqtt;
328 
329 #endif
330 
331 		/* details for non-http related protocols... */
332 	} u;
333 
334 #if defined(LWS_WITH_SSPLUGINS)
335 	const
336 	struct lws_ss_plugin	*plugins[2]; /**< NULL or auth plugin */
337 	const void		*plugins_info[2];   /**< plugin-specific data */
338 #endif
339 
340 #if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4)
341 	/* directly point to the metadata name, no need to expand */
342 	const char *aws_region;
343 	const char *aws_service;
344 #endif
345 	/*
346 	 * We're either a client connection policy that wants a trust store,
347 	 * or we're a server policy that wants a mem cert and key... Hold
348 	 * these mutually-exclusive things in a union.
349 	 */
350 
351 	union {
352 		const lws_ss_trust_store_t		*store;
353 		/**< CA certs needed for conn validation, only set between
354 		 * policy parsing and vhost creation */
355 		struct {
356 			const lws_ss_x509_t		*cert;
357 			/**< the server's signed cert with the pubkey */
358 			const lws_ss_x509_t		*key;
359 			/**< the server's matching private key */
360 		} server;
361 	} trust;
362 
363 	const lws_retry_bo_t	*retry_bo;   /**< retry policy to use */
364 
365 	uint32_t		proxy_buflen; /**< max dsh alloc for proxy */
366 	uint32_t		proxy_buflen_rxflow_on_above;
367 	uint32_t		proxy_buflen_rxflow_off_below;
368 
369 	uint32_t		client_buflen; /**< max dsh alloc for client */
370 	uint32_t		client_buflen_rxflow_on_above;
371 	uint32_t		client_buflen_rxflow_off_below;
372 
373 
374 	uint32_t		timeout_ms;  /**< default message response
375 					      * timeout in ms */
376 	uint32_t		flags;	     /**< stream attribute flags */
377 
378 	uint16_t		port;	     /**< endpoint port */
379 
380 	uint8_t			metadata_count;    /**< metadata count */
381 	uint8_t			protocol;    /**< protocol index */
382 	uint8_t			client_cert; /**< which client cert to apply
383 						  0 = none, 1+ = cc 0+ */
384 	uint8_t			priority;	/* 0 = normal, 6 = max normal,
385 						 * 7 = network management */
386 } lws_ss_policy_t;
387 
388 #if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
389 
390 /*
391  * These only exist / have meaning if there's a dynamic JSON policy enabled
392  */
393 
394 LWS_VISIBLE LWS_EXTERN int
395 lws_ss_policy_parse_begin(struct lws_context *context, int overlay);
396 
397 LWS_VISIBLE LWS_EXTERN int
398 lws_ss_policy_parse_abandon(struct lws_context *context);
399 
400 LWS_VISIBLE LWS_EXTERN int
401 lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len);
402 
403 LWS_VISIBLE LWS_EXTERN int
404 lws_ss_policy_overlay(struct lws_context *context, const char *overlay);
405 
406 /*
407  * You almost certainly don't want these, they return the first policy or auth
408  * object in a linked-list of objects created by lws_ss_policy_parse above,
409  * they are exported to generate static policy with
410  */
411 LWS_VISIBLE LWS_EXTERN const lws_ss_policy_t *
412 lws_ss_policy_get(struct lws_context *context);
413 
414 LWS_VISIBLE LWS_EXTERN const lws_ss_auth_t *
415 lws_ss_auth_get(struct lws_context *context);
416 
417 #endif
418