• 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