libwebsockets
Lightweight C library for HTML5 websockets
lws-secure-streams-serialization.h
Go to the documentation of this file.
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  * This defines the Serialized Secure Streams framing, and the optional
27  * lws_transport_mux framing.
28  *
29  * APIs are declared for lws_transport and binding those to the SSPC and proxy
30  * sides in lws.
31  */
32 
33 #if defined(STANDALONE)
35 #define lws_context lws_context_standalone
36 #endif
37 
38 #define LWSSSS_VERSION 1
39 
40 typedef enum {
41  /*
42  * This is the Serialized Serure Streams framing. It's sufficient to
43  * carry all SS API actions over a point-to-point bytestream between
44  * an SSPC client and an SS oroxy, in both directions.
45  *
46  * These serialized streams may be multiplexed by the transport (eg,
47  * for unix domain sockets transport, each SS opens its own UDS socket
48  * to the proxy) or via lws_transport_mux framing encapsulation.
49  *
50  *
51  * Framing for Proxy -> Client direction
52  */
53 
55  /*
56  * Proxied rx
57  *
58  * - 0: LWSSS_SER_RXPRE_RX_PAYLOAD
59  * - 1: 2 byte MSB-first rest-of-frame length
60  * - 3: 4-byte MSB-first flags
61  * - 7: 4-byte MSB-first us between inbound read and wrote to client
62  * - 11: 8-byte MSB-first us resolution unix time proxy wrote to client
63  * - 17: (rideshare name len + rideshare name if flags &
64  * LWSSS_FLAG_RIDESHARE) payload
65  */
67  /*
68  * Proxied connection setup result
69  *
70  * - 0: LWSSS_SER_RXPRE_CREATE_RESULT
71  * - 1: 2 byte MSB-first rest-of-frame length (usually 00, 03)
72  * - 3: 1 byte result, 0 = success. On failure, proxy will close
73  * connection.
74  * - 4: 4 byte client dsh allocation recommended for stream type,
75  * from policy (introduced in SSSv1)
76  * - 8: 2 byte MSB-first initial tx credit
77  * - 10: if present, comma-sep list of rideshare types from policy
78  */
80  /*
81  * Proxied state (8 or 11 byte packet)
82  *
83  * - 0: LWSSS_SER_RXPRE_CONNSTATE
84  * - 1: 00, 05 if state < 256, else 00, 08
85  * - 3: 1 byte state index if state < 256, else 4-byte MSB-first
86  * state index
87  * - 4 or 7: 4-byte MSB-first ordinal
88  */
90  /*
91  * Proxied tx credit
92  *
93  * - 0: LWSSS_SER_RXPRE_TXCR_UPDATE
94  * - 1: 00, 04
95  * - 3: 4-byte MSB-first addition tx credit bytes
96  */
98  /*
99  * Proxied rx metadata
100  *
101  * - 0: LWSSS_SER_RXPRE_METADATA
102  * - 1: 2-byte MSB-first rest-of-frame length
103  * - 3: 1-byte metadata name length
104  * - 4: metadata name
105  * - ...: metadata value (for rest of packet)
106  */
108  /* reserved */
110  /*
111  * Proxied performance information
112  *
113  * - 0: LWSSS_SER_RXPRE_PERF
114  * - 1: 2-byte MSB-first rest-of-frame length
115  * - 3: ... performance JSON (for rest of packet)
116  */
117 
118  /*
119  * Framing for Client -> Proxy direction
120  */
121 
123  /*
124  * Proxied connection setup
125  *
126  * - 0: LWSSS_SER_TXPRE_STREAMTYPE
127  * - 1: 2-byte MSB-first rest-of-frame length
128  * - 3: 1-byte Client SSS protocol version (introduced in SSSv1)
129  * - 4: 4-byte Client PID (introduced in SSSv1)
130  * - 8: 4-byte MSB-first initial tx credit
131  * - 12: the streamtype name with no NUL
132  */
134  /*
135  * Proxied request for onward connection
136  *
137  * - 0: LWSSS_SER_TXPRE_ONWARD_CONNECT
138  * - 1: 00, 00
139  */
141  /*
142  * Proxied secure stream destroy
143  *
144  * - 0: LWSSS_SER_TXPRE_DESTROYING
145  * - 1: 00, 00
146  */
148  /*
149  * Proxied tx
150  *
151  * - 0: LWSSS_SER_TXPRE_TX_PAYLOAD
152  * - 1: 2 byte MSB-first rest-of-frame length
153  * - 3: 4-byte MSB-first flags
154  * - 7: 4-byte MSB-first us between client requested write and wrote
155  * to proxy
156  * - 11: 8-byte MSB-first us resolution unix time client wrote to proxy
157  * - 19: ...payload (for rest of packet)
158  */
160  /*
161  * Proxied metadata - sent when one metadata item set clientside
162  *
163  * - 0: LWSSS_SER_TXPRE_METADATA
164  * - 1: 2-byte MSB-first rest-of-frame length
165  * - 3: 1-byte metadata name length
166  * - 4: metadata name
167  * - ...: metadata value (for rest of packet)
168  */
170  /*
171  * TX credit management - sent when using tx credit apis, cf METADATA
172  *
173  * - 0: LWSSS_SER_TXPRE_TXCR_UPDATE
174  * - 1: 2-byte MSB-first rest-of-frame length 00, 04
175  * - 3: 4-byte additional tx credit adjust value
176  */
178  /*
179  * Stream timeout management - forwarded when user applying or
180  * cancelling t.o.
181  *
182  * - 0: LWSSS_SER_TXPRE_TIMEOUT_UPDATE
183  * - 1: 2-byte MSB-first rest-of-frame length 00, 04
184  * - 3: 4-byte MSB-first unsigned 32-bit timeout,
185  * 0 = use policy, -1 = cancel
186  */
188  /*
189  * Passing up payload length hint
190  *
191  * - 0: LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT
192  * - 1: 2-byte MSB-first rest-of-frame length 00, 04
193  * - 3: 4-byte MSB-first unsigned 32-bit payload length hint
194  */
196  /* reserved */
199 
200 /* SSPC serialization states */
201 
202  typedef enum {
203  LPCSPROX_WAIT_INITIAL_TX = 1, /* after connect, must send streamtype */
204  LPCSPROX_REPORTING_FAIL, /* stream creation failed, wait to to tell */
205  LPCSPROX_REPORTING_OK, /* stream creation succeeded, wait to to tell */
206  LPCSPROX_OPERATIONAL, /* ready for payloads */
208 
209  LPCSCLI_SENDING_INITIAL_TX, /* after connect, must send streamtype */
210  LPCSCLI_WAITING_CREATE_RESULT, /* wait to hear if proxy ss create OK */
211  LPCSCLI_LOCAL_CONNECTED, /* we are in touch with the proxy */
212  LPCSCLI_ONWARD_CONNECT, /* request onward ss connection */
213  LPCSCLI_OPERATIONAL, /* ready for payloads */
214 
216 
217  /*
218  * Optional multiplexing layer
219  *
220  * Either side can:
221  *
222  * - open and close channels asynchronously
223  * - send and receive transport-level (not mux channel) timed PINGs / PONGs
224  * - send and receive data bound to an open mux channel
225  *
226  * PONGs are produced and sent automatically on recipt of a PING from the peer
227  * The peer sends a PONGACK so the single transaction can validate connection
228  * viability in both directions.
229  */
230 
231  enum {
232  LWSSSS_LLM_CHANNEL_REQ = 0xf0,
312 };
313 
314 typedef void * lws_transport_priv_t; /* care - this is a pointer type already */
315 struct lws_transport_mux;
316 struct lws_sss_proxy_conn;
319 struct lws_sspc_handle;
320 
321 /*
322  * These describe the path through different transport layers. Each has an
323  * 'in' and 'onw' (onward) side that can be bound to different parts in lws.
324  * SSPC and the SS Proxy code in lws each exposes one of these as terminals
325  * for the "path" to handle the SS Serialization on each side.
326  *
327  * sspc-transport-wsi and proxy-transport-wsi expose possible endpoints for the
328  * paths, so you can simply "wire SSPC and proxy up to a wsi transport".
329  *
330  * You can also create a lws_transport_mux_t and interpose it in the transport
331  * path on each side, and produce your own custom lws_transport ops implementing
332  * arbitrary transport support.
333  */
334 
335 typedef struct lws_txp_path_client {
342 
343 typedef struct lws_txp_path_proxy {
350 
351 /*
352  * Operations for client-side transport
353  */
354 
355 typedef struct lws_transport_client_ops {
356  const char *name;
357 
359  struct lws_sspc_handle *h);
362  struct lws_sspc_handle *h, int disposition);
366  int (*_write)(lws_transport_priv_t priv, uint8_t *buf, size_t len);
370  const uint8_t *buf, size_t len);
380  lws_ss_state_return_t (*event_can_write)(struct lws_sspc_handle *h,
381  size_t metadata_limit);
383  lws_ss_state_return_t (*event_closed)(lws_transport_priv_t priv /*struct lws_sspc_handle *h */);
389 
390 /*
391  * Operations for proxy-side transport
392  */
393 
394 typedef struct lws_transport_proxy_ops {
395  const char *name;
396  int (*init_proxy_server)(struct lws_context *context,
397  const struct lws_transport_proxy_ops *txp_ops_inward,
398  lws_transport_priv_t txp_priv_inward,
399  lws_txp_path_proxy_t *txp_ppath, const void *aux,
400  const char *bind, int port);
403  int (*destroy_proxy_server)(struct lws_context *context);
404  lws_ss_state_return_t (*event_new_conn)(struct lws_context *cx,
405  const struct lws_transport_proxy_ops *txp_ops_inward,
406  lws_transport_priv_t txp_priv_inward,
407  #if defined(LWS_WITH_SYS_FAULT_INJECTION)
408  const lws_fi_ctx_t *fic,
409  #endif
410  struct lws_sss_proxy_conn **conn,
411  lws_transport_priv_t txp_priv);
414  struct lws_ss_handle *h);
420 #if defined(LWS_WITH_SYS_FAULT_INJECTION)
421  , const lws_fi_ctx_t *fic
422 #endif
423  );
425  int (*proxy_write)(lws_transport_priv_t priv, uint8_t *buf, size_t *len);
430  struct lws_sss_proxy_conn *conn);
432 #if defined(LWS_WITH_SYS_FAULT_INJECTION)
433  const lws_fi_ctx_t * (*fault_context)(lws_transport_priv_t priv);
435 #endif
436  lws_ss_state_return_t (*close_conn)(struct lws_sss_proxy_conn *conn);
439  const uint8_t *buf, size_t len);
444  uint32_t flags; /* dsh flags */
446 
447 /* lws_transport_mux parser states */
448 
458 };
459 
460 /* lws_transport_mux channel definitions */
461 
463 #define LWS_MUCH_RANGE 256
464 
465 /* lws_transport mux states */
466 
467 enum {
468  /* lws_transport_mux_ch_t created */
469  LWSTMC_PENDING_CREATE_CHANNEL, /* waiting to send create channel */
470  LWSTMC_AWAITING_CREATE_CHANNEL_ACK, /* sent create ch, awaiting ack */
471  LWSTMC_PENDING_CREATE_CHANNEL_NACK, /* waiting to send create ch ack */
472  LWSTMC_PENDING_CREATE_CHANNEL_ACK, /* waiting to send create ch ack */
473  LWSTMC_OPERATIONAL, /* had ack, we are operational */
474  LWSTMC_PENDING_CLOSE_CHANNEL, /* waiting to send close channel */
475  LWSTMC_AWAITING_CLOSE_CHANNEL_ACK, /* sent close ch, awaiting ack */
476  LWSTMC_PENDING_CLOSE_CHANNEL_ACK, /* waiting to send close ch ack */
477  /* lws_transport_mux_ch_t destroyed */
478 };
479 
480 #define LWS_TRANSPORT_MUXCH_MAGIC LWS_FOURCC('T', 'm', 'C', 'h')
481 #define assert_is_tmch(_tm) lws_assert_fourcc(_tm->magic, LWS_TRANSPORT_MUXCH_MAGIC)
482 
483 typedef struct lws_transport_mux_ch {
484 #if defined(_DEBUG)
485  uint32_t magic;
486 #endif
491  void *opaque;
496 
497 enum { /* states of the transport */
500 };
501 
502 #define LWSTMINFO_SERVER (1 << 0)
503 
504 typedef struct lws_transport_info {
512  uint32_t flags; /* LWSTMINFO_.... */
514 
515 #define LWS_TRANSPORT_MUX_MAGIC LWS_FOURCC('I', 's', 'T', 'M')
516 #define assert_is_tm(_tm) lws_assert_fourcc(_tm->magic, LWS_TRANSPORT_MUX_MAGIC)
517 
518 typedef struct lws_transport_mux {
519 #if defined(_DEBUG)
520  uint32_t magic;
521 #endif
522  struct lws_context *cx;
525  void *txp_handle;
526  void *txp_aux;
527  uint64_t us_ping_in;
528  uint64_t us_ping_out;
531  uint64_t mp_time;
532  uint64_t mp_time1;
533  enum lwstmc_parser mp_state;
534  uint32_t mp_pay; /* remaining payload */
541  lws_dll2_owner_t owner; /* lws_mux_ch_t */
548 
550 lws_transport_mux_create(struct lws_context *cx, lws_transport_info_t *info,
551  void *txp_handle);
552 
553 void
555 
556 void
558 
559 #if defined(_DEBUG)
560 void
562 void
564 #else
565 #define lws_transport_path_client_dump(_a, _b)
566 #define lws_transport_path_proxy_dump(_a, _b)
567 #endif
568 
569 /*
570  * Callback set used to customize parser and _pending apis
571  */
572 
573 typedef struct lws_txp_mux_parse_cbs {
574  int (*payload)(lws_transport_mux_ch_t *tmc, const uint8_t *buf,
575  size_t len);
576  int (*ch_opens)(lws_transport_mux_ch_t *tmc, int determination);
581 
582 int
584  size_t len, const lws_txp_mux_parse_cbs_t *cbs);
585 
586 int /* nonzero if the transport mux has filled buf and wants to write it */
588  const lws_txp_mux_parse_cbs_t *cbs);
589 
592 
595 
596 #if defined(STANDALONE)
597 #undef lws_context
598 #endif
599 
enum lws_ss_state_return lws_ss_state_return_t
unsigned int uint32_t
unsigned char uint8_t
uint32_t _open[LWS_MUCH_RANGE/32]
int lws_transport_mux_pending(lws_transport_mux_t *tm, uint8_t *buf, size_t *len, const lws_txp_mux_parse_cbs_t *cbs)
struct lws_txp_mux_parse_cbs lws_txp_mux_parse_cbs_t
const struct lws_transport_client_ops * ops_onw
@ LWSTMC_PENDING_CREATE_CHANNEL_NACK
@ LWSTMC_AWAITING_CREATE_CHANNEL_ACK
@ LWSSS_SER_RXPRE_TLSNEG_ENCLAVE_SIGN
@ LWSSS_SER_TXPRE_LINK_VALIDITY_PROBE
@ LWSSS_SER_TXPRE_TLSNEG_ENCLAVE_SIGNED
@ LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT
uint8_t lws_mux_ch_idx_t
struct lws_transport_client_ops lws_transport_client_ops_t
struct lws_transport_info lws_transport_info_t
int lws_transport_mux_rx_parse(lws_transport_mux_t *tm, const uint8_t *buf, size_t len, const lws_txp_mux_parse_cbs_t *cbs)
void lws_transport_mux_request_tx(lws_transport_mux_t *tm)
struct lws_transport_mux lws_transport_mux_t
struct lws_transport_proxy_ops lws_transport_proxy_ops_t
struct lws_transport_info * onward_txp_info
uint32_t fin[LWS_MUCH_RANGE/32]
struct lws_transport_mux * mux
const struct lws_transport_proxy_ops * ops_in
struct lws_txp_path_client lws_txp_path_client_t
#define lws_transport_path_proxy_dump(_a, _b)
lws_transport_mux_t * lws_transport_mux_create(struct lws_context *cx, lws_transport_info_t *info, void *txp_handle)
const struct lws_transport_client_ops * ops_in
void lws_transport_mux_destroy(lws_transport_mux_t **tm)
struct lws_transport_mux * mux
void * lws_transport_priv_t
#define lws_transport_path_client_dump(_a, _b)
struct lws_txp_path_proxy lws_txp_path_proxy_t
const struct lws_transport_proxy_ops * ops_onw
const lws_transport_proxy_ops_t lws_transport_mux_proxy_ops
const lws_transport_proxy_ops_t lws_txp_inside_proxy
const lws_transport_client_ops_t lws_txp_inside_sspc
const lws_transport_client_ops_t lws_transport_mux_client_ops
struct lws_transport_mux_ch lws_transport_mux_ch_t
void(* req_write)(lws_transport_priv_t priv)
int(* event_retry_connect)(lws_txp_path_client_t *path, struct lws_sspc_handle *h)
lws_ss_state_return_t(* event_can_write)(struct lws_sspc_handle *h, size_t metadata_limit)
void(* event_client_up)(lws_transport_priv_t priv)
void(* lost_coherence)(lws_transport_priv_t priv)
void(* event_stream_up)(lws_transport_priv_t priv)
lws_ss_state_return_t(* event_read)(lws_transport_priv_t priv, const uint8_t *buf, size_t len)
lws_ss_state_return_t(* event_closed)(lws_transport_priv_t priv)
void(* _close)(lws_transport_priv_t priv)
int(* _write)(lws_transport_priv_t priv, uint8_t *buf, size_t len)
lws_ss_state_return_t(* event_connect_disposition)(struct lws_sspc_handle *h, int disposition)
void(* event_client_up)(lws_transport_priv_t priv)
lws_ss_state_return_t(* event_new_conn)(struct lws_context *cx, const struct lws_transport_proxy_ops *txp_ops_inward, lws_transport_priv_t txp_priv_inward, struct lws_sss_proxy_conn **conn, lws_transport_priv_t txp_priv)
void(* proxy_req_write)(lws_transport_priv_t priv)
int(* proxy_check_write_more)(lws_transport_priv_t priv)
lws_ss_state_return_t(* event_close_conn)(struct lws_sss_proxy_conn *conn)
lws_ss_state_return_t(* event_proxy_can_write)(lws_transport_priv_t priv)
void(* event_onward_bind)(lws_transport_priv_t priv, struct lws_ss_handle *h)
lws_ss_state_return_t(* close_conn)(struct lws_sss_proxy_conn *conn)
int(* init_proxy_server)(struct lws_context *context, const struct lws_transport_proxy_ops *txp_ops_inward, lws_transport_priv_t txp_priv_inward, lws_txp_path_proxy_t *txp_ppath, const void *aux, const char *bind, int port)
lws_ss_state_return_t(* proxy_read)(lws_transport_priv_t priv, const uint8_t *buf, size_t len)
int(* proxy_write)(lws_transport_priv_t priv, uint8_t *buf, size_t *len)
int(* destroy_proxy_server)(struct lws_context *context)
int(* txp_can_write)(lws_transport_mux_ch_t *tmc)
int(* ch_opens)(lws_transport_mux_ch_t *tmc, int determination)
int(* ch_closes)(lws_transport_mux_ch_t *tmc)
int(* payload)(lws_transport_mux_ch_t *tmc, const uint8_t *buf, size_t len)
void(* txp_req_write)(lws_transport_mux_t *tm)