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
27typedef 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)
55typedef 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
82typedef 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
99typedef 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
107enum {
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
170typedef 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
178enum {
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
199typedef 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
216typedef 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
227typedef 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 */
249typedef 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 uint8_t retain;
327
328 } mqtt;
329
330#endif
331
332 /* details for non-http related protocols... */
333 } u;
334
335#if defined(LWS_WITH_SSPLUGINS)
336 const
337 struct lws_ss_plugin *plugins[2]; /**< NULL or auth plugin */
338 const void *plugins_info[2]; /**< plugin-specific data */
339#endif
340
341#if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4)
342 /* directly point to the metadata name, no need to expand */
343 const char *aws_region;
344 const char *aws_service;
345#endif
346 /*
347 * We're either a client connection policy that wants a trust store,
348 * or we're a server policy that wants a mem cert and key... Hold
349 * these mutually-exclusive things in a union.
350 */
351
352 union {
353 const lws_ss_trust_store_t *store;
354 /**< CA certs needed for conn validation, only set between
355 * policy parsing and vhost creation */
356 struct {
357 const lws_ss_x509_t *cert;
358 /**< the server's signed cert with the pubkey */
359 const lws_ss_x509_t *key;
360 /**< the server's matching private key */
361 } server;
362 } trust;
363
364 const lws_retry_bo_t *retry_bo; /**< retry policy to use */
365
366 uint32_t proxy_buflen; /**< max dsh alloc for proxy */
367 uint32_t proxy_buflen_rxflow_on_above;
368 uint32_t proxy_buflen_rxflow_off_below;
369
370 uint32_t client_buflen; /**< max dsh alloc for client */
371 uint32_t client_buflen_rxflow_on_above;
372 uint32_t client_buflen_rxflow_off_below;
373
374
375 uint32_t timeout_ms; /**< default message response
376 * timeout in ms */
377 uint32_t flags; /**< stream attribute flags */
378
379 uint16_t port; /**< endpoint port */
380
381 uint8_t metadata_count; /**< metadata count */
382 uint8_t protocol; /**< protocol index */
383 uint8_t client_cert; /**< which client cert to apply
384 0 = none, 1+ = cc 0+ */
385 uint8_t priority; /* 0 = normal, 6 = max normal,
386 * 7 = network management */
387} lws_ss_policy_t;
388
389#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
390
391/*
392 * These only exist / have meaning if there's a dynamic JSON policy enabled
393 */
394
395LWS_VISIBLE LWS_EXTERN int
396lws_ss_policy_parse_begin(struct lws_context *context, int overlay);
397
398LWS_VISIBLE LWS_EXTERN int
399lws_ss_policy_parse_abandon(struct lws_context *context);
400
401LWS_VISIBLE LWS_EXTERN int
402lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len);
403
404LWS_VISIBLE LWS_EXTERN int
405lws_ss_policy_overlay(struct lws_context *context, const char *overlay);
406
407/*
408 * You almost certainly don't want these, they return the first policy or auth
409 * object in a linked-list of objects created by lws_ss_policy_parse above,
410 * they are exported to generate static policy with
411 */
412LWS_VISIBLE LWS_EXTERN const lws_ss_policy_t *
413lws_ss_policy_get(struct lws_context *context);
414
415LWS_VISIBLE LWS_EXTERN const lws_ss_auth_t *
416lws_ss_auth_get(struct lws_context *context);
417
418#endif
419