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: 4 byte MSB-first initial tx credit 67 * - 7: the streamtype name with no NUL 68 * 69 * - Proxied tx 70 * 71 * - 0: LWSSS_SER_TXPRE_TX_PAYLOAD 72 * - 1: 2 byte MSB-first rest-of-frame length 73 * - 3: 4-byte MSB-first flags 74 * - 7: 4-byte MSB-first us between client requested write and wrote to proxy 75 * - 11: 8-byte MSB-first us resolution unix time client wrote to proxy 76 * - 17: payload 77 * 78 * - Proxied secure stream destroy 79 * 80 * - 0: LWSSS_SER_TXPRE_DESTROYING 81 * - 1: 00, 00 82 * 83 * - Proxied metadata - sent when one metadata item set clientside 84 * 85 * - 0: LWSSS_SER_TXPRE_METADATA 86 * - 1: 2-byte MSB-first rest-of-frame length 87 * - 2: 1-byte metadata name length 88 * - 3: metadata name 89 * - ...: metadata value (for rest of packet) 90 * 91 * Proxy to client 92 * 93 * - Proxied connection setup result 94 * 95 * - 0: LWSSS_SER_RXPRE_CREATE_RESULT 96 * - 1: 2 byte MSB-first rest-of-frame length (usually 00, 03) 97 * - 3: 1 byte result, 0 = success. On failure, proxy will close connection. 98 * - 4: 2 byte MSB-first initial tx credit 99 * - 6: if present, comma-sep list of rideshare types from policy 100 * 101 * - Proxied rx 102 * 103 * - 0: LWSSS_SER_RXPRE_RX_PAYLOAD 104 * - 1: 2 byte MSB-first rest-of-frame length 105 * - 3: 4-byte MSB-first flags 106 * - 7: 4-byte MSB-first us between inbound read and wrote to client 107 * - 11: 8-byte MSB-first us resolution unix time proxy wrote to client 108 * - 17: (rideshare name len + rideshare name if flags & LWSSS_FLAG_RIDESHARE) 109 * payload 110 * 111 * - Proxied tx credit 112 * 113 * - 0: LWSSS_SER_RXPRE_TXCR_UPDATE 114 * - 1: 00, 04 115 * - 3: 4-byte MSB-first addition tx credit bytes 116 * 117 * - Proxied state 118 * 119 * - 0: LWSSS_SER_RXPRE_CONNSTATE 120 * - 1: 00, 05 121 * - 3: 1 byte state index 122 * - 7: 4-byte MSB-first ordinal 123 * 124 * 125 * Proxied tx may be read by the proxy but rejected due to lack of buffer space 126 * at the proxy. For that reason, tx must be held at the sender until it has 127 * been acknowledged or denied. 128 * 129 * Sinks 130 * ----- 131 * 132 * Sinks are logical "servers", you can register as a sink for a particular 133 * streamtype by using the lws_ss_create() api with ssi->register_sink set to 1. 134 * 135 * For directly fulfilled Secure Streams, new streams of that streamtype bind 136 * to the rx, tx and state handlers given when it was registered. 137 * 138 * - When new streams are created the registered sink handler for (*state) is 139 * called with event LWSSSCS_SINK_JOIN and the new client stream handle in 140 * the h_src parameter. 141 * 142 * - When the client stream sends something to the sink, it calls the sink's 143 * (*rx) with the client stream's 144 */ 145 146 #define LWS_SS_MTU 1540 147 148 struct lws_ss_handle; 149 typedef uint32_t lws_ss_tx_ordinal_t; 150 151 /* 152 * connection state events 153 */ 154 typedef enum { 155 LWSSSCS_CREATING, 156 LWSSSCS_DISCONNECTED, 157 LWSSSCS_UNREACHABLE, 158 LWSSSCS_AUTH_FAILED, 159 LWSSSCS_CONNECTED, 160 LWSSSCS_CONNECTING, 161 LWSSSCS_DESTROYING, 162 LWSSSCS_POLL, 163 LWSSSCS_ALL_RETRIES_FAILED, /* all retries in bo policy failed */ 164 LWSSSCS_QOS_ACK_REMOTE, /* remote peer received and acked tx */ 165 LWSSSCS_QOS_NACK_REMOTE, 166 LWSSSCS_QOS_ACK_LOCAL, /* local proxy accepted our tx */ 167 LWSSSCS_QOS_NACK_LOCAL, /* local proxy refused our tx */ 168 169 LWSSSCS_SINK_JOIN, /* sinks get this when a new source 170 * stream joins the sink */ 171 LWSSSCS_SINK_PART, /* sinks get this when a new source 172 * stream leaves the sink */ 173 } lws_ss_constate_t; 174 175 enum { 176 LWSSS_FLAG_SOM = (1 << 0), 177 /* payload contains the start of new message */ 178 LWSSS_FLAG_EOM = (1 << 1), 179 /* payload contains the end of message */ 180 LWSSS_FLAG_POLL = (1 << 2), 181 /* Not a real transmit... poll for rx if protocol needs it */ 182 LWSSS_FLAG_RELATED_START = (1 << 3), 183 /* Appears in a zero-length message indicating a message group of zero 184 * or more messages is now starting. */ 185 LWSSS_FLAG_RELATED_END = (1 << 4), 186 /* Appears in a zero-length message indicating a message group of zero 187 * or more messages has now finished. */ 188 LWSSS_FLAG_RIDESHARE = (1 << 5), 189 /* Serialized payload starts with non-default rideshare name length and 190 * name string without NUL, then payload */ 191 192 /* 193 * In the case the secure stream is proxied across a process or thread 194 * boundary, eg by proxying through a socket for IPC, metadata must be 195 * carried in-band. A byte is prepended to each rx payload to 196 * differentiate what it is. 197 * 198 * Secure streams where the user is called back directly does not need 199 * any of this and only pure payloads are passed. 200 * 201 * rx (received by client) prepends for proxied connections 202 */ 203 204 LWSSS_SER_RXPRE_RX_PAYLOAD = 0x55, 205 LWSSS_SER_RXPRE_CREATE_RESULT, 206 LWSSS_SER_RXPRE_CONNSTATE, 207 LWSSS_SER_RXPRE_TXCR_UPDATE, 208 LWSSS_SER_RXPRE_TLSNEG_ENCLAVE_SIGN, 209 210 /* tx (send by client) prepends for proxied connections */ 211 212 LWSSS_SER_TXPRE_STREAMTYPE = 0xaa, 213 LWSSS_SER_TXPRE_ONWARD_CONNECT, 214 LWSSS_SER_TXPRE_DESTROYING, 215 LWSSS_SER_TXPRE_TX_PAYLOAD, 216 LWSSS_SER_TXPRE_METADATA, 217 LWSSS_SER_TXPRE_TXCR_UPDATE, 218 LWSSS_SER_TXPRE_TLSNEG_ENCLAVE_SIGNED, 219 }; 220 221 typedef enum { 222 LPCS_WAIT_INITIAL_TX = 1, /* after connect, must send streamtype */ 223 LPCS_REPORTING_FAIL, /* stream creation failed, wait to to tell */ 224 LPCS_REPORTING_OK, /* stream creation succeeded, wait to to tell */ 225 LPCS_OPERATIONAL, /* ready for payloads */ 226 LPCS_DESTROYED, 227 228 LPCS_SENDING_INITIAL_TX = 1, /* after connect, must send streamtype */ 229 LPCS_WAITING_CREATE_RESULT, /* wait to hear if proxy ss create OK */ 230 LPCS_LOCAL_CONNECTED, /* we are in touch with the proxy */ 231 LPCS_ONWARD_CONNECT, /* request onward ss connection */ 232 233 } lws_ss_conn_states_t; 234 235 /** 236 * lws_ss_info_t: information about stream to be created 237 * 238 * Prepare this struct with information about what the stream type is and how 239 * the stream should interface with your code, and pass it to lws_ss_create() 240 * to create the requested stream. 241 */ 242 243 typedef struct lws_ss_info { 244 const char *streamtype; /**< type of stream we want to create */ 245 size_t user_alloc; /**< size of user allocation */ 246 size_t handle_offset; /**< offset of handle stg in user_alloc type, 247 set to offsetof(mytype, my_handle_member) */ 248 size_t opaque_user_data_offset; 249 /**< offset of opaque user data ptr in user_alloc type, set to 250 offsetof(mytype, opaque_ud_member) */ 251 252 int (*rx)(void *userobj, const uint8_t *buf, size_t len, 253 int flags); 254 /**< callback with rx payload for this stream */ 255 int (*tx)(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, 256 size_t *len, int *flags); 257 /**< callback to send payload on this stream... 0 = send as set in 258 * len and flags, 1 = do not send anything (ie, not even 0 len frame) */ 259 int (*state)(void *userobj, void *h_src /* ss handle type */, 260 lws_ss_constate_t state, lws_ss_tx_ordinal_t ack); 261 /**< advisory cb about state of stream and QoS status if applicable... 262 * h_src is only used with sinks and LWSSSCS_SINK_JOIN/_PART events. 263 * Return nonzero to indicate you want to destroy the stream. */ 264 int manual_initial_tx_credit; 265 /**< 0 = manage any tx credit automatically, nonzero explicitly sets the 266 * peer stream to have the given amount of tx credit, if the protocol 267 * can support it. */ 268 char register_sink; 269 /**< If set, we're not creating a specific stream, but registering 270 * ourselves as the "sink" for .streamtype. It's analogous to saying 271 * we want to be the many-to-one "server" for .streamtype; when other 272 * streams are created with that streamtype, they should be forwarded 273 * to this stream owner, where they join and part from the sink via 274 * (*state) LWSSSCS_SINK_JOIN / _PART events, the new client handle 275 * being provided in the h_src parameter. 276 */ 277 } lws_ss_info_t; 278 279 /** 280 * lws_ss_create() - Create secure stream 281 * 282 * \param context: the lws context to create this inside 283 * \param tsi: service thread index to create on (normally 0) 284 * \param ssi: pointer to lws_ss_info_t filled in with info about desired stream 285 * \param opaque_user_data: opaque data to set in the stream's user object 286 * \param ppss: pointer to secure stream handle pointer set on exit 287 * \param ppayload_fmt: NULL or pointer to a string ptr to take payload format 288 * name from the policy 289 * 290 * Requests a new secure stream described by \p ssi be created. If successful, 291 * the stream is created, its state callback called with LWSSSCS_CREATING, *ppss 292 * is set to point to the handle, and it returns 0. If it failed, it returns 293 * nonzero. 294 * 295 * Along with the opaque stream object, streams overallocate 296 * 297 * 1) a user data struct whose size is set in ssi 298 * 2) nauth plugin instantiation data (size set in the plugin struct) 299 * 3) sauth plugin instantiation data (size set in the plugin struct) 300 * 4) space for a copy of the stream type name 301 * 302 * The user data struct is initialized to all zeros, then the .handle_offset and 303 * .opaque_user_data_offset fields of the ssi are used to prepare the user data 304 * struct with the ss handle that was created, and a copy of the 305 * opaque_user_data pointer given as an argument. 306 * 307 * If you want to set up the stream with specific information, point to it in 308 * opaque_user_data and use the copy of that pointer in your user data member 309 * for it starting from the LWSSSCS_CREATING state call. 310 * 311 * Since different endpoints chosen by the policy may require different payload 312 * formats, \p ppayload_fmt is set to point to the name of the needed payload 313 * format from the policy database if non-NULL. 314 */ 315 LWS_VISIBLE LWS_EXTERN int 316 lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, 317 void *opaque_user_data, struct lws_ss_handle **ppss, 318 struct lws_sequencer *seq_owner, const char **ppayload_fmt); 319 320 /** 321 * lws_ss_destroy() - Destroy secure stream 322 * 323 * \param ppss: pointer to lws_ss_t pointer to be destroyed 324 * 325 * Destroys the lws_ss_t pointed to by *ppss, and sets *ppss to NULL. 326 */ 327 LWS_VISIBLE LWS_EXTERN void 328 lws_ss_destroy(struct lws_ss_handle **ppss); 329 330 /** 331 * lws_ss_request_tx() - Schedule stream for tx 332 * 333 * \param pss: pointer to lws_ss_t representing stream that wants to transmit 334 * 335 * Schedules a write on the stream represented by \p pss. When it's possible to 336 * write on this stream, the *tx callback will occur with an empty buffer for 337 * the stream owner to fill in. 338 */ 339 LWS_VISIBLE LWS_EXTERN void 340 lws_ss_request_tx(struct lws_ss_handle *pss); 341 342 /** 343 * lws_ss_request_tx() - Schedule stream for tx 344 * 345 * \param pss: pointer to lws_ss_t representing stream that wants to transmit 346 * \param len: the length of the write in bytes 347 * 348 * Schedules a write on the stream represented by \p pss. When it's possible to 349 * write on this stream, the *tx callback will occur with an empty buffer for 350 * the stream owner to fill in. 351 * 352 * This api variant should be used when it's possible the payload will go out 353 * over h1 with x-web-form-urlencoded or similar Content-Type. 354 */ 355 LWS_VISIBLE LWS_EXTERN void 356 lws_ss_request_tx_len(struct lws_ss_handle *pss, unsigned long len); 357 358 359 /** 360 * lws_ss_client_connect() - Attempt the client connect 361 * 362 * \param h: secure streams handle 363 * 364 * Starts the connection process for the secure stream. Returns 0 if OK or 365 * nonzero if we have already failed. 366 */ 367 LWS_VISIBLE LWS_EXTERN int 368 lws_ss_client_connect(struct lws_ss_handle *h); 369 370 /** 371 * lws_ss_get_sequencer() - Return parent sequencer pointer if any 372 * 373 * \param h: secure streams handle 374 * 375 * Returns NULL if the secure stream is not associated with a sequencer. 376 * Otherwise returns a pointer to the owning sequencer. You can use this to 377 * identify which sequencer to direct messages to, from the secure stream 378 * callback. 379 */ 380 LWS_VISIBLE LWS_EXTERN struct lws_sequencer * 381 lws_ss_get_sequencer(struct lws_ss_handle *h); 382 383 /** 384 * lws_ss_proxy_create() - Start a unix domain socket proxy for Secure Streams 385 * 386 * \param context: lws_context 387 * \param bind: if port is 0, unix domain path with leading @ for abstract. 388 * if port nonzero, NULL, or network interface to bind listen to 389 * \param port: tcp port to listen on 390 * 391 * Creates a vhost that listens either on an abstract namespace unix domain 392 * socket (port = 0) or a tcp listen socket (port nonzero). If bind is NULL 393 * and port is 0, the abstract unix domain socket defaults to "proxy.ss.lws". 394 * 395 * Client connections to this proxy to Secure Streams are fulfilled using the 396 * policy local to the proxy and the data passed between the client and the 397 * proxy using serialized Secure Streams protocol. 398 */ 399 LWS_VISIBLE LWS_EXTERN int 400 lws_ss_proxy_create(struct lws_context *context, const char *bind, int port); 401 402 /** 403 * lws_ss_state_name() - convenience helper to get a printable conn state name 404 * 405 * \param state: the connection state index 406 * 407 * Returns a printable name for the connection state index passed in. 408 */ 409 LWS_VISIBLE LWS_EXTERN const char * 410 lws_ss_state_name(int state); 411 412 /** 413 * lws_ss_get_context() - convenience helper to recover the lws context 414 * 415 * \param h: secure streams handle 416 * 417 * Returns the lws context. Dispenses with the need to pass a copy of it into 418 * your secure streams handler. 419 */ 420 LWS_VISIBLE LWS_EXTERN struct lws_context * 421 lws_ss_get_context(struct lws_ss_handle *h); 422 423 /** 424 * lws_ss_rideshare() - find the current streamtype when types rideshare 425 * 426 * \param h: the stream handle 427 * 428 * Under some conditions, the payloads may be structured using protocol- 429 * specific formatting, eg, http multipart mime. It's possible to map the 430 * logical partitions in the payload to different stream types using 431 * the policy "rideshare" feature. 432 * 433 * This api lets the callback code find out which rideshare stream type the 434 * current payload chunk belongs to. 435 */ 436 LWS_VISIBLE LWS_EXTERN const char * 437 lws_ss_rideshare(struct lws_ss_handle *h); 438 439 440 /** 441 * lws_ss_set_metadata() - allow user to bind external data to defined ss metadata 442 * 443 * \param h: secure streams handle 444 * \param name: metadata name from the policy 445 * \param value: pointer to user-managed data to bind to name 446 * \param len: length of the user-managed data in value 447 * 448 * Binds user-managed data to the named metadata item from the ss policy. 449 * If present, the metadata item is handled in a protocol-specific way using 450 * the associated policy information. For example, in the policy 451 * 452 * "\"metadata\":" "[" 453 * "{\"uptag\":" "\"X-Upload-Tag:\"}," 454 * "{\"ctype\":" "\"Content-Type:\"}," 455 * "{\"xctype\":" "\"\"}" 456 * "]," 457 * 458 * when the policy is using h1 is interpreted to add h1 headers of the given 459 * name with the value of the metadata on the left. 460 * 461 * Return 0 if OK or nonzero if, eg, metadata name does not exist on the 462 * streamtype. 463 */ 464 LWS_VISIBLE LWS_EXTERN int 465 lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, 466 void *value, size_t len); 467 468 469 /** 470 * lws_ss_add_peer_tx_credit() - allow peer to transmit more to us 471 * 472 * \param h: secure streams handle 473 * \param add: additional tx credit (signed) 474 * 475 * Indicate to remote peer that we can accept \p add bytes more payload being 476 * sent to us. 477 */ 478 LWS_VISIBLE LWS_EXTERN int 479 lws_ss_add_peer_tx_credit(struct lws_ss_handle *h, int32_t add); 480 481 /** 482 * lws_ss_get_est_peer_tx_credit() - get our current estimate of peer's tx credit 483 * 484 * \param h: secure streams handle 485 * 486 * Based on what credit we gave it, and what we have received, report our 487 * estimate of peer's tx credit usable to transmit to us. This may be outdated 488 * in that some or all of its credit may already have been expended by sending 489 * stuff to us that is in flight already. 490 */ 491 LWS_VISIBLE LWS_EXTERN int 492 lws_ss_get_est_peer_tx_credit(struct lws_ss_handle *h); 493