1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2019 - 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  * 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 typedef struct lws_ss_plugin {
55 	struct lws_ss_plugin	*next;
56 	const char		*name;	/**< auth plugin name */
57 	size_t			alloc;	/**< size of private allocation */
58 
59 	int			(*create)(struct lws_ss_handle *ss, void *info,
60 					  plugin_auth_status_cb status);
61 				/**< called when the auth plugin is instantiated
62 				     and bound to the secure stream.  status is
63 				     called back with advisory information about
64 				     the authenticated stream state as it
65 				     proceeds */
66 	int			(*destroy)(struct lws_ss_handle *ss);
67 				/**< called when the related secure stream is
68 				     being destroyed, and anything the auth
69 				     plugin is doing should also be destroyed */
70 	int			(*munge)(struct lws_ss_handle *ss, char *path,
71 					 size_t path_len);
72 				/**< if the plugin needs to munge transactions
73 				     that have metadata outside the payload (eg,
74 				     add http headers) this callback will give
75 				     it the opportunity to do so */
76 } lws_ss_plugin_t;
77 
78 
79 typedef struct lws_ss_x509 {
80 	struct lws_ss_x509	*next;
81 	const char		*vhost_name; /**< vhost name using cert ctx */
82 	const uint8_t		*ca_der;	/**< DER x.509 cert */
83 	size_t			ca_der_len;	/**< length of DER cert */
84 } lws_ss_x509_t;
85 
86 enum {
87 	LWSSSPOLF_OPPORTUNISTIC					= (1 << 0),
88 	/**< the connection doesn't exist unless client asks to write */
89 	LWSSSPOLF_NAILED_UP					= (1 << 1),
90 	/**< the connection tries to be connected the whole life of the ss */
91 	LWSSSPOLF_URGENT_TX					= (1 << 2),
92 	/**< this connection carries critical tx data */
93 	LWSSSPOLF_URGENT_RX					= (1 << 3),
94 	/**< this connection carries critical rx data */
95 	LWSSSPOLF_TLS						= (1 << 4),
96 	/**< stream must be connected via a tls tunnel */
97 	LWSSSPOLF_LONG_POLL					= (1 << 5),
98 	/**< stream used to receive async rx at arbitrary intervals */
99 	LWSSSPOLF_AUTH_BEARER					= (1 << 6),
100 	/**< for http, use lws_system auth token 0 in authentication: bearer */
101 	LWSSSPOLF_HTTP_NO_CONTENT_LENGTH			= (1 << 7),
102 	/**< don't add any content length even if we have it */
103 	LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM			= (1 << 8),
104 	/**< set the client flag LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM */
105 	LWSSSPOLF_H2_QUIRK_OVERFLOWS_TXCR			= (1 << 9),
106 	/**< set the client flag LCCSCF_H2_QUIRK_OVERFLOWS_TXCR */
107 	LWSSSPOLF_H2_QUIRK_UNCLEAN_HPACK_STATE			= (1 << 10),
108 	/**< HPACK decoder state does not end cleanly */
109 	LWSSSPOLF_HTTP_MULTIPART				= (1 << 11),
110 	/**< indicates stream goes out as specifically a multipart mime POST
111 	 * section... if the tx has LWSSS_FLAG_COALESCE_CONTINUES flag then more
112 	 * multipart sections are expected.  Without it, the multipart wrapper
113 	 * is closed and the http transaction issue completed when this message
114 	 * finishes. */
115 	LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED			= (1 << 12),
116 	/**< set up lws_system client cert */
117 	LWSSSPOLF_LOCAL_SINK					= (1 << 13),
118 	/**< expected to bind to a local sink only */
119 };
120 
121 typedef struct lws_ss_trust_store {
122 	struct lws_ss_trust_store	*next;
123 	const char			*name;
124 
125 	lws_ss_x509_t			*ssx509[8];
126 	int				count;
127 } lws_ss_trust_store_t;
128 
129 enum {
130 	LWSSSP_H1,
131 	LWSSSP_H2,
132 	LWSSSP_WS,
133 
134 
135 	LWSSS_HBI_AUTH = 0,
136 	LWSSS_HBI_DSN,
137 	LWSSS_HBI_FWV,
138 	LWSSS_HBI_TYPE,
139 
140 	_LWSSS_HBI_COUNT /* always last */
141 };
142 
143 typedef struct lws_ss_metadata {
144 	struct lws_ss_metadata	*next;
145 	const char		*name;
146 	void			*value;
147 	size_t			length;
148 
149 	uint8_t			value_on_lws_heap; /* proxy does this */
150 } lws_ss_metadata_t;
151 
152 
153 /**
154  * lws_ss_policy_t: policy database entry for a stream type
155  *
156  * Decides the system policy for how to implement connections of name
157  * .streamtype.
158  *
159  * Streams may need one kind of auth sequencing for the network connection and
160  * another kind of auth sequencing for the streams that are carried inside it,
161  * this is the purpose of .nauth and .sauth.  Both are optional and may be NULL.
162  *
163  * An array of these is set at context creation time, ending with one with a
164  * NULL streamtype.
165  */
166 typedef struct lws_ss_policy {
167 	struct lws_ss_policy	*next;
168 	const char		*streamtype; /**< stream type lhs to match on */
169 
170 	const char		*endpoint;   /**< DNS address to connect to */
171 	const char		*rideshare_streamtype; /**< optional transport
172 					* on another, preexisting stream of this
173 					* streamtype name */
174 	const char		*payload_fmt;
175 	const char		*socks5_proxy;
176 	lws_ss_metadata_t	*metadata; /* linked-list of metadata */
177 
178 	/* protocol-specific connection policy details */
179 
180 	union {
181 
182 		/* details for http-related protocols... */
183 
184 		struct {
185 
186 			/* common to all http-related protocols */
187 
188 			const char	*method;
189 			const char	*url;
190 
191 			const char	*multipart_name;
192 			const char	*multipart_filename;
193 			const char	*multipart_content_type;
194 
195 			const char	*blob_header[_LWSSS_HBI_COUNT];
196 			const char	*auth_preamble;
197 
198 			union {
199 //				struct { /* LWSSSP_H1 */
200 //				} h1;
201 //				struct { /* LWSSSP_H2 */
202 //				} h2;
203 				struct { /* LWSSSP_WS */
204 					const char	*subprotocol;
205 					uint8_t		binary;
206 					/* false = TEXT, true = BINARY */
207 				} ws;
208 			} u;
209 		} http;
210 
211 		struct {
212 			const char	*topic;	    /* stream sends on this topic */
213 			const char	*subscribe; /* stream subscribes to this topic */
214 
215 			const char	*will_topic;
216 			const char	*will_message;
217 
218 			uint16_t	keep_alive;
219 			uint8_t		qos;
220 			uint8_t		clean_start;
221 			uint8_t		will_qos;
222 			uint8_t		will_retain;
223 
224 		} mqtt;
225 
226 		/* details for non-http related protocols... */
227 	} u;
228 
229 	const
230 	struct lws_ss_plugin	*plugins[2]; /**< NULL or auth plugin */
231 	const void		*plugins_info[2];   /**< plugin-specific data */
232 
233 	const lws_ss_trust_store_t *trust_store; /**< CA certs needed for conn
234 	       validation, only set between policy parsing and vhost creation */
235 
236 	const lws_retry_bo_t	*retry_bo;   /**< retry policy to use */
237 
238 	uint32_t		flags;	     /**< stream attribute flags */
239 
240 	uint16_t		port;	     /**< endpoint port */
241 
242 	uint8_t			metadata_count;    /**< metadata count */
243 	uint8_t			protocol;    /**< protocol index */
244 	uint8_t			client_cert; /**< which client cert to apply
245 						  0 = none, 1+ = cc 0+ */
246 } lws_ss_policy_t;
247