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 - 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  *
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 
59 
60 #define LWS_SS_MTU 1540
61 
62 struct lws_ss_handle;
63 typedef uint32_t lws_ss_tx_ordinal_t;
64 
65 #if defined(STANDALONE)
66 #define lws_context lws_context_standalone
68 #endif
69 
70 /*
71  * connection state events
72  *
73  * If you add states, take care about the state names and state transition
74  * validity enforcement tables too
75  */
76 typedef enum {
77  /* zero means unset */
78  LWSSSCS_CREATING = 1,
79  LWSSSCS_DISCONNECTED,
80  LWSSSCS_UNREACHABLE, /* oridinal arg = 1 = caused by dns
81  * server reachability failure */
82  LWSSSCS_AUTH_FAILED,
83  LWSSSCS_CONNECTED,
84  LWSSSCS_CONNECTING,
85  LWSSSCS_DESTROYING,
86  LWSSSCS_POLL,
87  LWSSSCS_ALL_RETRIES_FAILED, /* all retries in bo policy failed */
88  LWSSSCS_QOS_ACK_REMOTE, /* remote peer received and acked tx */
89  LWSSSCS_QOS_NACK_REMOTE,
90  LWSSSCS_QOS_ACK_LOCAL, /* local proxy accepted our tx */
91  LWSSSCS_QOS_NACK_LOCAL, /* local proxy refused our tx */
92  LWSSSCS_TIMEOUT, /* optional timeout timer fired */
93 
94  LWSSSCS_SERVER_TXN,
95  LWSSSCS_SERVER_UPGRADE, /* the server protocol upgraded */
96 
97  LWSSSCS_EVENT_WAIT_CANCELLED, /* somebody called lws_cancel_service */
98 
99  LWSSSCS_UPSTREAM_LINK_RETRY, /* if we are being proxied over some
100  * intermediate link, this transient
101  * state may be sent to indicate we are
102  * waiting to establish that link before
103  * creation can proceed.. ack is the
104  * number of ms we have been trying */
105 
106  LWSSSCS_SINK_JOIN, /* sinks get this when a new source
107  * stream joins the sink */
108  LWSSSCS_SINK_PART, /* sinks get this when a new source
109  * stream leaves the sink */
110 
111  LWSSSCS_USER_BASE = 1000
112 } lws_ss_constate_t;
113 
114 enum {
115  LWSSS_FLAG_SOM = (1 << 0),
116  /* payload contains the start of new message */
117  LWSSS_FLAG_EOM = (1 << 1),
118  /* payload contains the end of message */
119  LWSSS_FLAG_POLL = (1 << 2),
120  /* Not a real transmit... poll for rx if protocol needs it */
121  LWSSS_FLAG_RELATED_START = (1 << 3),
122  /* Appears in a zero-length message indicating a message group of zero
123  * or more messages is now starting. */
124  LWSSS_FLAG_RELATED_END = (1 << 4),
125  /* Appears in a zero-length message indicating a message group of zero
126  * or more messages has now finished. */
127  LWSSS_FLAG_RIDESHARE = (1 << 5),
128  /* Serialized payload starts with non-default rideshare name length and
129  * name string without NUL, then payload */
130  LWSSS_FLAG_PERF_JSON = (1 << 6),
131  /* This RX is JSON performance data, only on streams with "perf" flag
132  * set */
133 };
134 
135 /*
136  * Returns from state() callback can tell the caller what the user code
137  * wants to do
138  */
139 
140 typedef enum lws_ss_state_return {
141  LWSSSSRET_TX_DONT_SEND = 1, /* (*tx) only, or failure */
142 
143  LWSSSSRET_OK = 0, /* no error */
144  LWSSSSRET_DISCONNECT_ME = -1, /* caller should disconnect us */
145  LWSSSSRET_DESTROY_ME = -2, /* caller should destroy us */
146 } lws_ss_state_return_t;
147 
156 enum {
157  LWSSSINFLAGS_REGISTER_SINK = (1 << 0),
166  LWSSSINFLAGS_PROXIED = (1 << 1),
168  LWSSSINFLAGS_SERVER = (1 << 2),
172  LWSSSINFLAGS_ACCEPTED = (1 << 3),
175  LWSSSINFLAGS_ACCEPTED_SINK = (1 << 4),
178 };
179 
180 typedef lws_ss_state_return_t (*lws_sscb_rx)(void *userobj, const uint8_t *buf,
181  size_t len, int flags);
182 typedef lws_ss_state_return_t (*lws_sscb_tx)(void *userobj,
183  lws_ss_tx_ordinal_t ord,
184  uint8_t *buf, size_t *len,
185  int *flags);
186 typedef lws_ss_state_return_t (*lws_sscb_state)(void *userobj, void *h_src,
187  lws_ss_constate_t state,
188  lws_ss_tx_ordinal_t ack);
189 
190 #if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP)
191 typedef void (*lws_ss_buffer_dump_cb)(void *userobj, const uint8_t *buf,
192  size_t len, int done);
193 #endif
194 
195 struct lws_ss_policy;
196 
197 typedef struct lws_ss_info {
198  const char *streamtype;
199  size_t user_alloc;
200  size_t handle_offset;
206 #if defined(LWS_WITH_SECURE_STREAMS_CPP)
207  const struct lws_ss_policy *policy;
210 #endif
211 
212 #if defined(LWS_WITH_SYS_FAULT_INJECTION)
213  lws_fi_ctx_t fic;
216 #endif
217 
218  lws_sscb_rx rx;
220  lws_sscb_tx tx;
223  lws_sscb_state state;
227 #if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP)
228  lws_ss_buffer_dump_cb dump;
230 #endif
239  uint32_t client_pid;
243  uint8_t flags;
252 } lws_ss_info_t;
253 
254 #define LWS_SS_USER_TYPEDEF \
255  typedef struct { \
256  struct lws_ss_handle *ss; \
257  void *opaque_data;
258 
259 #define LWS_SS_INFO(_streamtype, _type) \
260  const lws_ss_info_t ssi_##_type = { \
261  .handle_offset = offsetof(_type, ss), \
262  .opaque_user_data_offset = offsetof(_type, opaque_data), \
263  .user_alloc = sizeof(_type), \
264  .streamtype = _streamtype,
265 
266 #define lws_ss_from_user(_u) (_u)->ss
267 #define lws_ss_opaque_from_user(_u) (_u)->opaque_data
268 #define lws_ss_cx_from_user(_u) lws_ss_get_context((_u)->ss)
269 
270 #if defined(LWS_SS_USE_SSPC)
271 #define lws_context_info_defaults(_x, _y) _lws_context_info_defaults(_x, NULL)
272 #else
273 #define lws_context_info_defaults(_x, _y) _lws_context_info_defaults(_x, _y)
274 #endif
275 
312 LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
313 lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi,
314  void *opaque_user_data, struct lws_ss_handle **ppss,
315  void *reserved, const char **ppayload_fmt);
316 
324 LWS_VISIBLE LWS_EXTERN void
325 lws_ss_destroy(struct lws_ss_handle **ppss);
326 
338 LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT
339 lws_ss_request_tx(struct lws_ss_handle *pss);
340 
354 LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT
355 lws_ss_request_tx_len(struct lws_ss_handle *pss, unsigned long len);
356 
370 LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT
371 lws_ss_client_connect(struct lws_ss_handle *h);
372 
389 LWS_VISIBLE LWS_EXTERN int
390 lws_ss_proxy_create(struct lws_context *context, const char *bind, int port);
391 
399 LWS_VISIBLE LWS_EXTERN const char *
400 lws_ss_state_name(int state);
401 
410 LWS_VISIBLE LWS_EXTERN struct lws_context *
411 lws_ss_get_context(struct lws_ss_handle *h);
412 
413 #define LWSSS_TIMEOUT_FROM_POLICY 0
414 
430 LWS_VISIBLE LWS_EXTERN void
431 lws_ss_start_timeout(struct lws_ss_handle *h, unsigned int timeout_ms);
432 
440 LWS_VISIBLE LWS_EXTERN void
441 lws_ss_cancel_timeout(struct lws_ss_handle *h);
442 
452 LWS_VISIBLE LWS_EXTERN void *
453 lws_ss_to_user_object(struct lws_ss_handle *h);
454 
468 LWS_VISIBLE LWS_EXTERN const char *
469 lws_ss_rideshare(struct lws_ss_handle *h);
470 
471 
497 LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
498 lws_ss_set_metadata(struct lws_ss_handle *h, const char *name,
499  const void *value, size_t len);
500 
513 LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
514 lws_ss_alloc_set_metadata(struct lws_ss_handle *h, const char *name,
515  const void *value, size_t len);
516 
544 LWS_VISIBLE LWS_EXTERN int
545 lws_ss_get_metadata(struct lws_ss_handle *h, const char *name,
546  const void **value, size_t *len);
547 
567 LWS_VISIBLE LWS_EXTERN void
568 lws_ss_server_ack(struct lws_ss_handle *h, int nack);
569 
570 typedef void (*lws_sssfec_cb)(struct lws_ss_handle *h, void *arg);
571 
584 LWS_VISIBLE LWS_EXTERN void
585 lws_ss_server_foreach_client(struct lws_ss_handle *h, lws_sssfec_cb cb,
586  void *arg);
587 
613 LWS_VISIBLE LWS_EXTERN void
614 lws_ss_change_handlers(struct lws_ss_handle *h, lws_sscb_rx rx, lws_sscb_tx tx,
615  lws_sscb_state state);
616 
626 LWS_VISIBLE LWS_EXTERN int
627 lws_ss_add_peer_tx_credit(struct lws_ss_handle *h, int32_t add);
628 
639 LWS_VISIBLE LWS_EXTERN int
640 lws_ss_get_est_peer_tx_credit(struct lws_ss_handle *h);
641 
642 LWS_VISIBLE LWS_EXTERN const char *
643 lws_ss_tag(struct lws_ss_handle *h);
644 
645 
646 #if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4)
660 LWS_VISIBLE LWS_EXTERN int
661 lws_ss_sigv4_set_aws_key(struct lws_context* context, uint8_t idx,
662  const char * keyid, const char * key);
663 
680 LWS_VISIBLE LWS_EXTERN int
681 lws_aws_filesystem_credentials_helper(const char *path, const char *kid,
682  const char *ak, char **aws_keyid,
683  char **aws_key);
684 
685 #endif
686 
687 #if defined(STANDALONE)
688 #undef lws_context
689 #endif
690 
692 
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 lws_ss_state_return_t LWS_WARN_UNUSED_RESULT lws_ss_request_tx_len(struct lws_ss_handle *pss, unsigned long len)
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 lws_ss_state_return_t LWS_WARN_UNUSED_RESULT lws_ss_client_connect(struct lws_ss_handle *h)
LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT lws_ss_request_tx(struct lws_ss_handle *pss)
LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, void *opaque_user_data, struct lws_ss_handle **ppss, void *reserved, const char **ppayload_fmt)
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 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 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:157
@ LWSSSINFLAGS_ACCEPTED_SINK
Definition: lws-secure-streams.h:175
@ LWSSSINFLAGS_SERVER
Definition: lws-secure-streams.h:168
@ LWSSSINFLAGS_ACCEPTED
Definition: lws-secure-streams.h:172
@ LWSSSINFLAGS_PROXIED
Definition: lws-secure-streams.h:166
Definition: lws-secure-streams-client.h:190
Definition: lws-secure-streams.h:197
lws_sscb_state state
Definition: lws-secure-streams.h:223
uint32_t client_pid
Definition: lws-secure-streams.h:239
size_t handle_offset
Definition: lws-secure-streams.h:200
lws_sscb_tx tx
Definition: lws-secure-streams.h:220
uint8_t sss_protocol_version
Definition: lws-secure-streams.h:244
size_t user_alloc
Definition: lws-secure-streams.h:199
const char * streamtype
Definition: lws-secure-streams.h:198
int manual_initial_tx_credit
Definition: lws-secure-streams.h:231
lws_sscb_rx rx
Definition: lws-secure-streams.h:218
size_t opaque_user_data_offset
Definition: lws-secure-streams.h:202
Definition: lws-secure-streams-policy.h:223
uint32_t flags
Definition: lws-secure-streams-policy.h:350
uint16_t port
Definition: lws-secure-streams-policy.h:352