libwebsockets
Lightweight C library for HTML5 websockets
lws-secure-streams.h
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  * Secure Streams is a *payload-only* client communication channel where all the
28  * details about the connection are held in a systemwide policy database and
29  * are keyed by the streamtype field... the user of the communication channel
30  * does not know or manage the choice of endpoint, tls CA, or even wire
31  * protocol. The advantage is he then does not have any dependency on any of
32  * those and they can be changed just by changing the policy database without
33  * touching the code using the stream.
34  *
35  * There are two ways secure streams interfaces to user code:
36  *
37  * 1) [Linux / RTOS] the natural, smallest interface is to call back to user
38  * code that only operates directly from the lws event loop thread context
39  * (direct callbacks from lws_ss_t)
40  *
41  * lws_thread( [user code] ---- lws )
42  *
43  * 2) [Linux] where the user code is in a different process and communicates
44  * asynchronously via a proxy socket
45  *
46  * user_process{ [user code] | shim | socket-}------ lws_process{ lws }
47  *
48  * In the second, IPC, case, all packets are prepended by one or more bytes
49  * indicating the packet type and serializing any associated data, known as
50  * Serialized Secure Streams or SSS.
51  *
52  * Serialized Secure Streams
53  * -------------------------
54  *
55  * On the transport, adjacent packets may be coalesced, that is, the original
56  * packet sizes are lost and two or more packets are combined. For that reason
57  * the serialization format always contains a 1-byte type and then a 2-byte
58  * frame length.
59  *
60  * Client to proxy
61  *
62  * - Proxied connection setup
63  *
64  * - 0: LWSSS_SER_TXPRE_STREAMTYPE
65  * - 1: 2-byte MSB-first rest-of-frame length
66  * - 3: 1-byte Client SSS protocol version (introduced in SSSv1)
67  * - 4: 4-byte Client PID (introduced in SSSv1)
68  * - 8: 4-byte MSB-first initial tx credit
69  * - 12: the streamtype name with no NUL
70  *
71  * - Proxied tx
72  *
73  * - 0: LWSSS_SER_TXPRE_TX_PAYLOAD
74  * - 1: 2 byte MSB-first rest-of-frame length
75  * - 3: 4-byte MSB-first flags
76  * - 7: 4-byte MSB-first us between client requested write and wrote to proxy
77  * - 11: 8-byte MSB-first us resolution unix time client wrote to proxy
78  * - 19: payload
79  *
80  * - Proxied secure stream destroy
81  *
82  * - 0: LWSSS_SER_TXPRE_DESTROYING
83  * - 1: 00, 00
84  *
85  * - Proxied metadata - sent when one metadata item set clientside
86  *
87  * - 0: LWSSS_SER_TXPRE_METADATA
88  * - 1: 2-byte MSB-first rest-of-frame length
89  * - 3: 1-byte metadata name length
90  * - 4: metadata name
91  * - ...: metadata value (for rest of packet)
92  *
93  * - TX credit management - sent when using tx credit apis, cf METADATA
94  *
95  * - 0: LWSSS_SER_TXPRE_TXCR_UPDATE
96  * - 1: 2-byte MSB-first rest-of-frame length 00, 04
97  * - 3: 4-byte additional tx credit adjust value
98  *
99  * - Stream timeout management - forwarded when user applying or cancelling t.o.
100  *
101  * - 0: LWSSS_SER_TXPRE_TIMEOUT_UPDATE
102  * - 1: 2-byte MSB-first rest-of-frame length 00, 04
103  * - 3: 4-byte MSB-first unsigned 32-bit timeout, 0 = use policy, -1 = cancel
104  *
105  * - Passing up payload length hint
106  *
107  * - 0: LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT
108  * - 1: 2-byte MSB-first rest-of-frame length 00, 04
109  * - 3: 4-byte MSB-first unsigned 32-bit payload length hint
110  *
111  * Proxy to client
112  *
113  * - Proxied connection setup result
114  *
115  * - 0: LWSSS_SER_RXPRE_CREATE_RESULT
116  * - 1: 2 byte MSB-first rest-of-frame length (usually 00, 03)
117  * - 3: 1 byte result, 0 = success. On failure, proxy will close connection.
118  * - 4: 4 byte client dsh allocation recommended for stream type, from policy
119  * (introduced in SSSv1)
120  * - 8: 2 byte MSB-first initial tx credit
121  * - 10: if present, comma-sep list of rideshare types from policy
122  *
123  * - Proxied rx
124  *
125  * - 0: LWSSS_SER_RXPRE_RX_PAYLOAD
126  * - 1: 2 byte MSB-first rest-of-frame length
127  * - 3: 4-byte MSB-first flags
128  * - 7: 4-byte MSB-first us between inbound read and wrote to client
129  * - 11: 8-byte MSB-first us resolution unix time proxy wrote to client
130  * - 17: (rideshare name len + rideshare name if flags & LWSSS_FLAG_RIDESHARE)
131  * payload
132  *
133  * - Proxied tx credit
134  *
135  * - 0: LWSSS_SER_RXPRE_TXCR_UPDATE
136  * - 1: 00, 04
137  * - 3: 4-byte MSB-first addition tx credit bytes
138  *
139  * - Proxied rx metadata
140  *
141  * - 0: LWSSS_SER_RXPRE_METADATA
142  * - 1: 2-byte MSB-first rest-of-frame length
143  * - 3: 1-byte metadata name length
144  * - 4: metadata name
145  * - ...: metadata value (for rest of packet)
146  *
147  * - Proxied state (8 or 11 byte packet)
148  *
149  * - 0: LWSSS_SER_RXPRE_CONNSTATE
150  * - 1: 00, 05 if state < 256, else 00, 08
151  * - 3: 1 byte state index if state < 256, else 4-byte MSB-first state index
152  * - 4 or 7: 4-byte MSB-first ordinal
153  *
154  * - Proxied performance information
155  *
156  * - 0: LWSSS_SER_RXPRE_PERF
157  * - 1: 2-byte MSB-first rest-of-frame length
158  * - 3: ... performance JSON (for rest of packet)
159  *
160  * Proxied tx may be read by the proxy but rejected due to lack of buffer space
161  * at the proxy. For that reason, tx must be held at the sender until it has
162  * been acknowledged or denied.
163  *
164  * Sinks
165  * -----
166  *
167  * Sinks are logical "servers", you can register as a sink for a particular
168  * streamtype by using the lws_ss_create() api with ssi->register_sink set to 1.
169  *
170  * For directly fulfilled Secure Streams, new streams of that streamtype bind
171  * to the rx, tx and state handlers given when it was registered.
172  *
173  * - When new streams are created the registered sink handler for (*state) is
174  * called with event LWSSSCS_SINK_JOIN and the new client stream handle in
175  * the h_src parameter.
176  *
177  * - When the client stream sends something to the sink, it calls the sink's
178  * (*rx) with the client stream's
179  */
180 
187 
188 #define LWS_SS_MTU 1540
189 
190 struct lws_ss_handle;
191 typedef uint32_t lws_ss_tx_ordinal_t;
192 
193 /*
194  * connection state events
195  *
196  * If you add states, take care about the state names and state transition
197  * validity enforcement tables too
198  */
199 typedef enum {
200  /* zero means unset */
201  LWSSSCS_CREATING = 1,
202  LWSSSCS_DISCONNECTED,
203  LWSSSCS_UNREACHABLE, /* oridinal arg = 1 = caused by dns
204  * server reachability failure */
205  LWSSSCS_AUTH_FAILED,
206  LWSSSCS_CONNECTED,
207  LWSSSCS_CONNECTING,
208  LWSSSCS_DESTROYING,
209  LWSSSCS_POLL,
210  LWSSSCS_ALL_RETRIES_FAILED, /* all retries in bo policy failed */
211  LWSSSCS_QOS_ACK_REMOTE, /* remote peer received and acked tx */
212  LWSSSCS_QOS_NACK_REMOTE,
213  LWSSSCS_QOS_ACK_LOCAL, /* local proxy accepted our tx */
214  LWSSSCS_QOS_NACK_LOCAL, /* local proxy refused our tx */
215  LWSSSCS_TIMEOUT, /* optional timeout timer fired */
216 
217  LWSSSCS_SERVER_TXN,
218  LWSSSCS_SERVER_UPGRADE, /* the server protocol upgraded */
219 
220  LWSSSCS_EVENT_WAIT_CANCELLED, /* somebody called lws_cancel_service */
221 
222  LWSSSCS_SINK_JOIN, /* sinks get this when a new source
223  * stream joins the sink */
224  LWSSSCS_SINK_PART, /* sinks get this when a new source
225  * stream leaves the sink */
226 
227  LWSSSCS_USER_BASE = 1000
228 } lws_ss_constate_t;
229 
230 enum {
231  LWSSS_FLAG_SOM = (1 << 0),
232  /* payload contains the start of new message */
233  LWSSS_FLAG_EOM = (1 << 1),
234  /* payload contains the end of message */
235  LWSSS_FLAG_POLL = (1 << 2),
236  /* Not a real transmit... poll for rx if protocol needs it */
237  LWSSS_FLAG_RELATED_START = (1 << 3),
238  /* Appears in a zero-length message indicating a message group of zero
239  * or more messages is now starting. */
240  LWSSS_FLAG_RELATED_END = (1 << 4),
241  /* Appears in a zero-length message indicating a message group of zero
242  * or more messages has now finished. */
243  LWSSS_FLAG_RIDESHARE = (1 << 5),
244  /* Serialized payload starts with non-default rideshare name length and
245  * name string without NUL, then payload */
246  LWSSS_FLAG_PERF_JSON = (1 << 6),
247  /* This RX is JSON performance data, only on streams with "perf" flag
248  * set */
249 
250  /*
251  * In the case the secure stream is proxied across a process or thread
252  * boundary, eg by proxying through a socket for IPC, metadata must be
253  * carried in-band. A byte is prepended to each rx payload to
254  * differentiate what it is.
255  *
256  * Secure streams where the user is called back directly does not need
257  * any of this and only pure payloads are passed.
258  *
259  * rx (received by client) prepends for proxied connections
260  */
261 
262  LWSSS_SER_RXPRE_RX_PAYLOAD = 0x55,
263  LWSSS_SER_RXPRE_CREATE_RESULT,
264  LWSSS_SER_RXPRE_CONNSTATE,
265  LWSSS_SER_RXPRE_TXCR_UPDATE,
266  LWSSS_SER_RXPRE_METADATA,
267  LWSSS_SER_RXPRE_TLSNEG_ENCLAVE_SIGN,
268  LWSSS_SER_RXPRE_PERF,
269 
270  /* tx (send by client) prepends for proxied connections */
271 
272  LWSSS_SER_TXPRE_STREAMTYPE = 0xaa,
273  LWSSS_SER_TXPRE_ONWARD_CONNECT,
274  LWSSS_SER_TXPRE_DESTROYING,
275  LWSSS_SER_TXPRE_TX_PAYLOAD,
276  LWSSS_SER_TXPRE_METADATA,
277  LWSSS_SER_TXPRE_TXCR_UPDATE,
278  LWSSS_SER_TXPRE_TIMEOUT_UPDATE,
279  LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT,
280  LWSSS_SER_TXPRE_TLSNEG_ENCLAVE_SIGNED,
281 };
282 
283 typedef enum {
284  LPCSPROX_WAIT_INITIAL_TX = 1, /* after connect, must send streamtype */
285  LPCSPROX_REPORTING_FAIL, /* stream creation failed, wait to to tell */
286  LPCSPROX_REPORTING_OK, /* stream creation succeeded, wait to to tell */
287  LPCSPROX_OPERATIONAL, /* ready for payloads */
288  LPCSPROX_DESTROYED,
289 
290  LPCSCLI_SENDING_INITIAL_TX, /* after connect, must send streamtype */
291  LPCSCLI_WAITING_CREATE_RESULT, /* wait to hear if proxy ss create OK */
292  LPCSCLI_LOCAL_CONNECTED, /* we are in touch with the proxy */
293  LPCSCLI_ONWARD_CONNECT, /* request onward ss connection */
294  LPCSCLI_OPERATIONAL, /* ready for payloads */
295 
296 } lws_ss_conn_states_t;
297 
298 /*
299  * Returns from state() callback can tell the caller what the user code
300  * wants to do
301  */
302 
303 typedef enum lws_ss_state_return {
304  LWSSSSRET_TX_DONT_SEND = 1, /* (*tx) only, or failure */
305 
306  LWSSSSRET_OK = 0, /* no error */
307  LWSSSSRET_DISCONNECT_ME = -1, /* caller should disconnect us */
308  LWSSSSRET_DESTROY_ME = -2, /* caller should destroy us */
309 } lws_ss_state_return_t;
310 
319 enum {
320  LWSSSINFLAGS_REGISTER_SINK = (1 << 0),
329  LWSSSINFLAGS_PROXIED = (1 << 1),
331  LWSSSINFLAGS_SERVER = (1 << 2),
335  LWSSSINFLAGS_ACCEPTED = (1 << 3),
338 };
339 
340 typedef lws_ss_state_return_t (*lws_sscb_rx)(void *userobj, const uint8_t *buf,
341  size_t len, int flags);
342 typedef lws_ss_state_return_t (*lws_sscb_tx)(void *userobj,
343  lws_ss_tx_ordinal_t ord,
344  uint8_t *buf, size_t *len,
345  int *flags);
346 typedef lws_ss_state_return_t (*lws_sscb_state)(void *userobj, void *h_src,
347  lws_ss_constate_t state,
348  lws_ss_tx_ordinal_t ack);
349 
350 #if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP)
351 typedef void (*lws_ss_buffer_dump_cb)(void *userobj, const uint8_t *buf,
352  size_t len, int done);
353 #endif
354 
355 struct lws_ss_policy;
356 
357 typedef struct lws_ss_info {
358  const char *streamtype;
359  size_t user_alloc;
360  size_t handle_offset;
366 #if defined(LWS_WITH_SECURE_STREAMS_CPP)
367  const struct lws_ss_policy *policy;
370 #endif
371 
372 #if defined(LWS_WITH_SYS_FAULT_INJECTION)
373  lws_fi_ctx_t fic;
376 #endif
377 
378  lws_sscb_rx rx;
380  lws_sscb_tx tx;
383  lws_sscb_state state;
387 #if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP)
388  lws_ss_buffer_dump_cb dump;
390 #endif
399  uint32_t client_pid;
403  uint8_t flags;
412 } lws_ss_info_t;
413 
450 LWS_VISIBLE LWS_EXTERN int
451 lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi,
452  void *opaque_user_data, struct lws_ss_handle **ppss,
453  struct lws_sequencer *seq_owner, const char **ppayload_fmt);
454 
462 LWS_VISIBLE LWS_EXTERN void
463 lws_ss_destroy(struct lws_ss_handle **ppss);
464 
476 LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t
477 lws_ss_request_tx(struct lws_ss_handle *pss);
478 
492 LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t
493 lws_ss_request_tx_len(struct lws_ss_handle *pss, unsigned long len);
494 
508 LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t
509 lws_ss_client_connect(struct lws_ss_handle *h);
510 
521 LWS_VISIBLE LWS_EXTERN struct lws_sequencer *
522 lws_ss_get_sequencer(struct lws_ss_handle *h);
523 
540 LWS_VISIBLE LWS_EXTERN int
541 lws_ss_proxy_create(struct lws_context *context, const char *bind, int port);
542 
550 LWS_VISIBLE LWS_EXTERN const char *
551 lws_ss_state_name(int state);
552 
561 LWS_VISIBLE LWS_EXTERN struct lws_context *
562 lws_ss_get_context(struct lws_ss_handle *h);
563 
564 #define LWSSS_TIMEOUT_FROM_POLICY 0
565 
581 LWS_VISIBLE LWS_EXTERN void
582 lws_ss_start_timeout(struct lws_ss_handle *h, unsigned int timeout_ms);
583 
591 LWS_VISIBLE LWS_EXTERN void
592 lws_ss_cancel_timeout(struct lws_ss_handle *h);
593 
603 LWS_VISIBLE LWS_EXTERN void *
604 lws_ss_to_user_object(struct lws_ss_handle *h);
605 
619 LWS_VISIBLE LWS_EXTERN const char *
620 lws_ss_rideshare(struct lws_ss_handle *h);
621 
622 
648 LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
649 lws_ss_set_metadata(struct lws_ss_handle *h, const char *name,
650  const void *value, size_t len);
651 
664 LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
665 lws_ss_alloc_set_metadata(struct lws_ss_handle *h, const char *name,
666  const void *value, size_t len);
667 
695 LWS_VISIBLE LWS_EXTERN int
696 lws_ss_get_metadata(struct lws_ss_handle *h, const char *name,
697  const void **value, size_t *len);
698 
718 LWS_VISIBLE LWS_EXTERN void
719 lws_ss_server_ack(struct lws_ss_handle *h, int nack);
720 
721 typedef void (*lws_sssfec_cb)(struct lws_ss_handle *h, void *arg);
722 
735 LWS_VISIBLE LWS_EXTERN void
736 lws_ss_server_foreach_client(struct lws_ss_handle *h, lws_sssfec_cb cb,
737  void *arg);
738 
764 LWS_VISIBLE LWS_EXTERN void
765 lws_ss_change_handlers(struct lws_ss_handle *h, lws_sscb_rx rx, lws_sscb_tx tx,
766  lws_sscb_state state);
767 
777 LWS_VISIBLE LWS_EXTERN int
778 lws_ss_add_peer_tx_credit(struct lws_ss_handle *h, int32_t add);
779 
790 LWS_VISIBLE LWS_EXTERN int
791 lws_ss_get_est_peer_tx_credit(struct lws_ss_handle *h);
792 
793 LWS_VISIBLE LWS_EXTERN const char *
794 lws_ss_tag(struct lws_ss_handle *h);
795 
796 
797 #if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4)
811 LWS_VISIBLE LWS_EXTERN int
812 lws_ss_sigv4_set_aws_key(struct lws_context* context, uint8_t idx,
813  const char * keyid, const char * key);
814 
831 LWS_VISIBLE LWS_EXTERN int
832 lws_aws_filesystem_credentials_helper(const char *path, const char *kid,
833  const char *ak, char **aws_keyid,
834  char **aws_key);
835 
836 #endif
837 
839 
LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t lws_ss_request_tx(struct lws_ss_handle *pss)
LWS_VISIBLE LWS_EXTERN void lws_ss_destroy(struct lws_ss_handle **ppss)
LWS_VISIBLE LWS_EXTERN void lws_ss_change_handlers(struct lws_ss_handle *h, lws_sscb_rx rx, lws_sscb_tx tx, lws_sscb_state state)
LWS_VISIBLE LWS_EXTERN int lws_ss_add_peer_tx_credit(struct lws_ss_handle *h, int32_t add)
LWS_VISIBLE LWS_EXTERN int lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, void *opaque_user_data, struct lws_ss_handle **ppss, struct lws_sequencer *seq_owner, const char **ppayload_fmt)
LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t lws_ss_client_connect(struct lws_ss_handle *h)
LWS_VISIBLE LWS_EXTERN int lws_ss_proxy_create(struct lws_context *context, const char *bind, int port)
LWS_VISIBLE LWS_EXTERN void lws_ss_start_timeout(struct lws_ss_handle *h, unsigned int timeout_ms)
LWS_VISIBLE LWS_EXTERN void * lws_ss_to_user_object(struct lws_ss_handle *h)
LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT lws_ss_alloc_set_metadata(struct lws_ss_handle *h, const char *name, const void *value, size_t len)
LWS_VISIBLE LWS_EXTERN void lws_ss_cancel_timeout(struct lws_ss_handle *h)
LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, const void *value, size_t len)
LWS_VISIBLE LWS_EXTERN void lws_ss_server_foreach_client(struct lws_ss_handle *h, lws_sssfec_cb cb, void *arg)
LWS_VISIBLE LWS_EXTERN const char * lws_ss_rideshare(struct lws_ss_handle *h)
LWS_VISIBLE LWS_EXTERN struct lws_context * lws_ss_get_context(struct lws_ss_handle *h)
LWS_VISIBLE LWS_EXTERN int lws_ss_get_est_peer_tx_credit(struct lws_ss_handle *h)
LWS_VISIBLE LWS_EXTERN struct lws_sequencer * lws_ss_get_sequencer(struct lws_ss_handle *h)
LWS_VISIBLE LWS_EXTERN const char * lws_ss_state_name(int state)
LWS_VISIBLE LWS_EXTERN void lws_ss_server_ack(struct lws_ss_handle *h, int nack)
LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t lws_ss_request_tx_len(struct lws_ss_handle *pss, unsigned long len)
LWS_VISIBLE LWS_EXTERN int lws_ss_get_metadata(struct lws_ss_handle *h, const char *name, const void **value, size_t *len)
@ LWSSSINFLAGS_REGISTER_SINK
Definition: lws-secure-streams.h:320
@ LWSSSINFLAGS_SERVER
Definition: lws-secure-streams.h:331
@ LWSSSINFLAGS_ACCEPTED
Definition: lws-secure-streams.h:335
@ LWSSSINFLAGS_PROXIED
Definition: lws-secure-streams.h:329
Definition: lws-secure-streams.h:357
lws_sscb_state state
Definition: lws-secure-streams.h:383
uint32_t client_pid
Definition: lws-secure-streams.h:399
size_t handle_offset
Definition: lws-secure-streams.h:360
lws_sscb_tx tx
Definition: lws-secure-streams.h:380
uint8_t sss_protocol_version
Definition: lws-secure-streams.h:404
size_t user_alloc
Definition: lws-secure-streams.h:359
const char * streamtype
Definition: lws-secure-streams.h:358
int manual_initial_tx_credit
Definition: lws-secure-streams.h:391
lws_sscb_rx rx
Definition: lws-secure-streams.h:378
size_t opaque_user_data_offset
Definition: lws-secure-streams.h:362
Definition: lws-secure-streams-policy.h:247
uint32_t flags
Definition: lws-secure-streams-policy.h:369