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_SINK_JOIN, /* sinks get this when a new source
221  * stream joins the sink */
222  LWSSSCS_SINK_PART, /* sinks get this when a new source
223  * stream leaves the sink */
224 
225  LWSSSCS_USER_BASE = 1000
226 } lws_ss_constate_t;
227 
228 enum {
229  LWSSS_FLAG_SOM = (1 << 0),
230  /* payload contains the start of new message */
231  LWSSS_FLAG_EOM = (1 << 1),
232  /* payload contains the end of message */
233  LWSSS_FLAG_POLL = (1 << 2),
234  /* Not a real transmit... poll for rx if protocol needs it */
235  LWSSS_FLAG_RELATED_START = (1 << 3),
236  /* Appears in a zero-length message indicating a message group of zero
237  * or more messages is now starting. */
238  LWSSS_FLAG_RELATED_END = (1 << 4),
239  /* Appears in a zero-length message indicating a message group of zero
240  * or more messages has now finished. */
241  LWSSS_FLAG_RIDESHARE = (1 << 5),
242  /* Serialized payload starts with non-default rideshare name length and
243  * name string without NUL, then payload */
244  LWSSS_FLAG_PERF_JSON = (1 << 6),
245  /* This RX is JSON performance data, only on streams with "perf" flag
246  * set */
247 
248  /*
249  * In the case the secure stream is proxied across a process or thread
250  * boundary, eg by proxying through a socket for IPC, metadata must be
251  * carried in-band. A byte is prepended to each rx payload to
252  * differentiate what it is.
253  *
254  * Secure streams where the user is called back directly does not need
255  * any of this and only pure payloads are passed.
256  *
257  * rx (received by client) prepends for proxied connections
258  */
259 
260  LWSSS_SER_RXPRE_RX_PAYLOAD = 0x55,
261  LWSSS_SER_RXPRE_CREATE_RESULT,
262  LWSSS_SER_RXPRE_CONNSTATE,
263  LWSSS_SER_RXPRE_TXCR_UPDATE,
264  LWSSS_SER_RXPRE_METADATA,
265  LWSSS_SER_RXPRE_TLSNEG_ENCLAVE_SIGN,
266  LWSSS_SER_RXPRE_PERF,
267 
268  /* tx (send by client) prepends for proxied connections */
269 
270  LWSSS_SER_TXPRE_STREAMTYPE = 0xaa,
271  LWSSS_SER_TXPRE_ONWARD_CONNECT,
272  LWSSS_SER_TXPRE_DESTROYING,
273  LWSSS_SER_TXPRE_TX_PAYLOAD,
274  LWSSS_SER_TXPRE_METADATA,
275  LWSSS_SER_TXPRE_TXCR_UPDATE,
276  LWSSS_SER_TXPRE_TIMEOUT_UPDATE,
277  LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT,
278  LWSSS_SER_TXPRE_TLSNEG_ENCLAVE_SIGNED,
279 };
280 
281 typedef enum {
282  LPCSPROX_WAIT_INITIAL_TX = 1, /* after connect, must send streamtype */
283  LPCSPROX_REPORTING_FAIL, /* stream creation failed, wait to to tell */
284  LPCSPROX_REPORTING_OK, /* stream creation succeeded, wait to to tell */
285  LPCSPROX_OPERATIONAL, /* ready for payloads */
286  LPCSPROX_DESTROYED,
287 
288  LPCSCLI_SENDING_INITIAL_TX, /* after connect, must send streamtype */
289  LPCSCLI_WAITING_CREATE_RESULT, /* wait to hear if proxy ss create OK */
290  LPCSCLI_LOCAL_CONNECTED, /* we are in touch with the proxy */
291  LPCSCLI_ONWARD_CONNECT, /* request onward ss connection */
292  LPCSCLI_OPERATIONAL, /* ready for payloads */
293 
294 } lws_ss_conn_states_t;
295 
296 /*
297  * Returns from state() callback can tell the caller what the user code
298  * wants to do
299  */
300 
301 typedef enum lws_ss_state_return {
302  LWSSSSRET_TX_DONT_SEND = 1, /* (*tx) only, or failure */
303 
304  LWSSSSRET_OK = 0, /* no error */
305  LWSSSSRET_DISCONNECT_ME = -1, /* caller should disconnect us */
306  LWSSSSRET_DESTROY_ME = -2, /* caller should destroy us */
307 } lws_ss_state_return_t;
308 
317 enum {
318  LWSSSINFLAGS_REGISTER_SINK = (1 << 0),
327  LWSSSINFLAGS_PROXIED = (1 << 1),
329  LWSSSINFLAGS_SERVER = (1 << 2),
333  LWSSSINFLAGS_ACCEPTED = (1 << 3),
336 };
337 
338 typedef lws_ss_state_return_t (*lws_sscb_rx)(void *userobj, const uint8_t *buf,
339  size_t len, int flags);
340 typedef lws_ss_state_return_t (*lws_sscb_tx)(void *userobj,
341  lws_ss_tx_ordinal_t ord,
342  uint8_t *buf, size_t *len,
343  int *flags);
344 typedef lws_ss_state_return_t (*lws_sscb_state)(void *userobj, void *h_src,
345  lws_ss_constate_t state,
346  lws_ss_tx_ordinal_t ack);
347 
348 struct lws_ss_policy;
349 
350 typedef struct lws_ss_info {
351  const char *streamtype;
352  size_t user_alloc;
353  size_t handle_offset;
359 #if defined(LWS_WITH_SECURE_STREAMS_CPP)
360  const struct lws_ss_policy *policy;
363 #endif
364 
365 #if defined(LWS_WITH_SYS_FAULT_INJECTION)
366  lws_fi_ctx_t fic;
369 #endif
370 
371  lws_sscb_rx rx;
373  lws_sscb_tx tx;
376  lws_sscb_state state;
388  uint32_t client_pid;
392  uint8_t flags;
401 } lws_ss_info_t;
402 
439 LWS_VISIBLE LWS_EXTERN int
440 lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi,
441  void *opaque_user_data, struct lws_ss_handle **ppss,
442  struct lws_sequencer *seq_owner, const char **ppayload_fmt);
443 
451 LWS_VISIBLE LWS_EXTERN void
452 lws_ss_destroy(struct lws_ss_handle **ppss);
453 
465 LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t
466 lws_ss_request_tx(struct lws_ss_handle *pss);
467 
481 LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t
482 lws_ss_request_tx_len(struct lws_ss_handle *pss, unsigned long len);
483 
497 LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t
498 lws_ss_client_connect(struct lws_ss_handle *h);
499 
510 LWS_VISIBLE LWS_EXTERN struct lws_sequencer *
511 lws_ss_get_sequencer(struct lws_ss_handle *h);
512 
529 LWS_VISIBLE LWS_EXTERN int
530 lws_ss_proxy_create(struct lws_context *context, const char *bind, int port);
531 
539 LWS_VISIBLE LWS_EXTERN const char *
540 lws_ss_state_name(int state);
541 
550 LWS_VISIBLE LWS_EXTERN struct lws_context *
551 lws_ss_get_context(struct lws_ss_handle *h);
552 
553 #define LWSSS_TIMEOUT_FROM_POLICY 0
554 
570 LWS_VISIBLE LWS_EXTERN void
571 lws_ss_start_timeout(struct lws_ss_handle *h, unsigned int timeout_ms);
572 
580 LWS_VISIBLE LWS_EXTERN void
581 lws_ss_cancel_timeout(struct lws_ss_handle *h);
582 
592 LWS_VISIBLE LWS_EXTERN void *
593 lws_ss_to_user_object(struct lws_ss_handle *h);
594 
608 LWS_VISIBLE LWS_EXTERN const char *
609 lws_ss_rideshare(struct lws_ss_handle *h);
610 
611 
637 LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
638 lws_ss_set_metadata(struct lws_ss_handle *h, const char *name,
639  const void *value, size_t len);
640 
653 LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
654 lws_ss_alloc_set_metadata(struct lws_ss_handle *h, const char *name,
655  const void *value, size_t len);
656 
684 LWS_VISIBLE LWS_EXTERN int
685 lws_ss_get_metadata(struct lws_ss_handle *h, const char *name,
686  const void **value, size_t *len);
687 
707 LWS_VISIBLE LWS_EXTERN void
708 lws_ss_server_ack(struct lws_ss_handle *h, int nack);
709 
710 typedef void (*lws_sssfec_cb)(struct lws_ss_handle *h, void *arg);
711 
724 LWS_VISIBLE LWS_EXTERN void
725 lws_ss_server_foreach_client(struct lws_ss_handle *h, lws_sssfec_cb cb,
726  void *arg);
727 
753 LWS_VISIBLE LWS_EXTERN void
754 lws_ss_change_handlers(struct lws_ss_handle *h, lws_sscb_rx rx, lws_sscb_tx tx,
755  lws_sscb_state state);
756 
766 LWS_VISIBLE LWS_EXTERN int
767 lws_ss_add_peer_tx_credit(struct lws_ss_handle *h, int32_t add);
768 
779 LWS_VISIBLE LWS_EXTERN int
780 lws_ss_get_est_peer_tx_credit(struct lws_ss_handle *h);
781 
782 LWS_VISIBLE LWS_EXTERN const char *
783 lws_ss_tag(struct lws_ss_handle *h);
784 
785 
786 #if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4)
800 LWS_VISIBLE LWS_EXTERN int
801 lws_ss_sigv4_set_aws_key(struct lws_context* context, uint8_t idx,
802  const char * keyid, const char * key);
803 
820 LWS_VISIBLE LWS_EXTERN int
821 lws_aws_filesystem_credentials_helper(const char *path, const char *kid,
822  const char *ak, char **aws_keyid,
823  char **aws_key);
824 
825 #endif
826 
828 
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:318
@ LWSSSINFLAGS_SERVER
Definition: lws-secure-streams.h:329
@ LWSSSINFLAGS_ACCEPTED
Definition: lws-secure-streams.h:333
@ LWSSSINFLAGS_PROXIED
Definition: lws-secure-streams.h:327
Definition: lws-secure-streams.h:350
lws_sscb_state state
Definition: lws-secure-streams.h:376
uint32_t client_pid
Definition: lws-secure-streams.h:388
size_t handle_offset
Definition: lws-secure-streams.h:353
lws_sscb_tx tx
Definition: lws-secure-streams.h:373
uint8_t sss_protocol_version
Definition: lws-secure-streams.h:393
size_t user_alloc
Definition: lws-secure-streams.h:352
const char * streamtype
Definition: lws-secure-streams.h:351
int manual_initial_tx_credit
Definition: lws-secure-streams.h:380
lws_sscb_rx rx
Definition: lws-secure-streams.h:371
size_t opaque_user_data_offset
Definition: lws-secure-streams.h:355
Definition: lws-secure-streams-policy.h:239
uint32_t flags
Definition: lws-secure-streams-policy.h:361