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 25 /* current SS Serialization protocol version */ 26 #define LWS_SSS_CLIENT_PROTOCOL_VERSION 1 27 28 /* 29 * Secure Stream state 30 */ 31 32 typedef enum { 33 SSSEQ_IDLE, 34 SSSEQ_TRY_CONNECT, 35 SSSEQ_TRY_CONNECT_NAUTH, 36 SSSEQ_TRY_CONNECT_SAUTH, 37 SSSEQ_RECONNECT_WAIT, 38 SSSEQ_DO_RETRY, 39 SSSEQ_CONNECTED, 40 } lws_ss_seq_state_t; 41 42 struct conn; 43 44 /** 45 * lws_ss_handle_t: publicly-opaque secure stream object implementation 46 */ 47 48 typedef struct lws_ss_handle { 49 lws_ss_info_t info; /**< copy of stream creation info */ 50 51 lws_lifecycle_t lc; 52 53 #if defined(LWS_WITH_SYS_METRICS) 54 lws_metrics_caliper_compose(cal_txn) 55 #endif 56 57 struct lws_dll2 list; /**< pt lists active ss */ 58 struct lws_dll2 to_list; /**< pt lists ss with pending to-s */ 59 #if defined(LWS_WITH_SERVER) 60 struct lws_dll2 cli_list; /**< same server clients list */ 61 #endif 62 #if defined(LWS_WITH_SYS_FAULT_INJECTION) 63 lws_fi_ctx_t fic; /**< Fault Injection context */ 64 #endif 65 66 struct lws_dll2_owner src_list; /**< sink's list of bound sources */ 67 68 struct lws_context *context; /**< lws context we are created on */ 69 const lws_ss_policy_t *policy; /**< system policy for stream */ 70 71 struct lws_sequencer *seq; /**< owning sequencer if any */ 72 struct lws *wsi; /**< the stream wsi if any */ 73 74 struct conn *conn_if_sspc_onw; 75 76 #if defined(LWS_WITH_SSPLUGINS) 77 void *nauthi; /**< the nauth plugin instance data */ 78 void *sauthi; /**< the sauth plugin instance data */ 79 #endif 80 81 lws_ss_metadata_t *metadata; 82 #if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) 83 lws_ss_metadata_t *instant_metadata; /**< for set instant metadata */ 84 struct lwsac *imd_ac; /**< for get custom header */ 85 #endif 86 const lws_ss_policy_t *rideshare; 87 struct lws_ss_handle *h_in_svc; 88 89 #if defined(LWS_WITH_CONMON) 90 char *conmon_json; 91 #endif 92 93 //struct lws_ss_handle *h_sink; /**< sink we are bound to, or NULL */ 94 //void *sink_obj;/**< sink's private object representing us */ 95 96 lws_sorted_usec_list_t sul_timeout; 97 lws_sorted_usec_list_t sul; 98 lws_ss_tx_ordinal_t txord; 99 100 /* protocol-specific connection helpers */ 101 102 union { 103 104 /* ...for http-related protocols... */ 105 106 struct { 107 108 /* common to all http-related protocols */ 109 110 /* incoming multipart parsing */ 111 112 char boundary[24]; /* --boundary from headers */ 113 uint8_t boundary_len; /* length of --boundary */ 114 uint8_t boundary_seq; /* current match amount */ 115 uint8_t boundary_dashes; /* check for -- after */ 116 uint8_t boundary_post; /* swallow post CRLF */ 117 118 uint8_t som:1; /* SOM has been sent */ 119 uint8_t eom:1; /* EOM has been sent */ 120 uint8_t any:1; /* any content has been sent */ 121 122 123 uint8_t good_respcode:1; /* 200 type response code */ 124 125 union { 126 struct { /* LWSSSP_H1 */ 127 #if defined(WIN32) 128 uint8_t dummy; 129 #endif 130 } h1; 131 struct { /* LWSSSP_H2 */ 132 #if defined(WIN32) 133 uint8_t dummy; 134 #endif 135 } h2; 136 struct { /* LWSSSP_WS */ 137 #if defined(WIN32) 138 uint8_t dummy; 139 #endif 140 } ws; 141 } u; 142 } http; 143 144 /* details for non-http related protocols... */ 145 #if defined(LWS_ROLE_MQTT) 146 struct { 147 lws_mqtt_topic_elem_t topic_qos; 148 lws_mqtt_topic_elem_t sub_top; 149 lws_mqtt_subscribe_param_t sub_info; 150 lws_mqtt_subscribe_param_t shadow_sub; 151 /* allocation that must be destroyed with conn */ 152 void *heap_baggage; 153 const char *subscribe_to; 154 size_t subscribe_to_len; 155 struct lws_buflist *buflist_unacked; 156 uint32_t unacked_size; 157 uint8_t retry_count; 158 uint8_t send_unacked:1; 159 } mqtt; 160 #endif 161 #if defined(LWS_WITH_SYS_SMD) 162 struct { 163 struct lws_smd_peer *smd_peer; 164 lws_sorted_usec_list_t sul_write; 165 } smd; 166 #endif 167 } u; 168 169 unsigned long writeable_len; 170 171 lws_ss_constate_t connstate;/**< public connection state */ 172 lws_ss_seq_state_t seqstate; /**< private connection state */ 173 lws_ss_state_return_t pending_ret; /**< holds desired disposition 174 * for ss during CCE */ 175 176 #if defined(LWS_WITH_SERVER) 177 int txn_resp; 178 #endif 179 180 uint16_t retry; /**< retry / backoff tracking */ 181 #if defined(LWS_WITH_CONMON) 182 uint16_t conmon_len; 183 #endif 184 int16_t temp16; 185 186 uint8_t tsi; /**< service thread idx, usually 0 */ 187 uint8_t subseq; /**< emulate SOM tracking */ 188 uint8_t txn_ok; /**< 1 = transaction was OK */ 189 uint8_t prev_ss_state; 190 191 uint8_t txn_resp_set:1; /**< user code set one */ 192 uint8_t txn_resp_pending:1; /**< we have yet to send */ 193 uint8_t hanging_som:1; 194 uint8_t inside_msg:1; 195 uint8_t being_serialized:1; /* we are not the consumer */ 196 uint8_t destroying:1; 197 uint8_t ss_dangling_connected:1; 198 uint8_t proxy_onward:1; /* opaque is conn */ 199 uint8_t inside_connect:1; /* set if we are currently 200 * creating the onward 201 * connect */ 202 } lws_ss_handle_t; 203 204 /* connection helper that doesn't need to hang around after connection starts */ 205 206 union lws_ss_contemp { 207 #if defined(LWS_ROLE_MQTT) 208 lws_mqtt_client_connect_param_t ccp; 209 #else 210 #if defined(WIN32) 211 uint8_t dummy; 212 #endif 213 #endif 214 }; 215 216 /* 217 * When allocating the opaque handle, we overallocate for: 218 * 219 * 1) policy->nauth_plugin->alloc (.nauthi) if any 220 * 2) policy->sauth_plugin->alloc (.sauthi) if any 221 * 3) copy of creation info stream type pointed to by info.streamtype... this 222 * may be arbitrarily long and since it may be coming from socket ipc and be 223 * temporary at creation time, we need a place for the copy to stay in scope 224 * 4) copy of info->streamtype contents 225 */ 226 227 228 /* the user object allocation is immediately after the ss object allocation */ 229 #define ss_to_userobj(ss) ((void *)&(ss)[1]) 230 231 /* 232 * serialization parser state 233 */ 234 235 enum { 236 KIND_C_TO_P, 237 KIND_SS_TO_P, 238 }; 239 240 struct lws_ss_serialization_parser { 241 char streamtype[32]; 242 char rideshare[32]; 243 char metadata_name[32]; 244 245 uint64_t ust_pwait; 246 247 lws_ss_metadata_t *ssmd; 248 uint8_t *rxmetaval; 249 250 int ps; 251 int ctr; 252 253 uint32_t usd_phandling; 254 uint32_t flags; 255 uint32_t client_pid; 256 int32_t temp32; 257 258 int32_t txcr_out; 259 int32_t txcr_in; 260 uint16_t rem; 261 262 uint8_t type; 263 uint8_t frag1; 264 uint8_t slen; 265 uint8_t rsl_pos; 266 uint8_t rsl_idx; 267 uint8_t protocol_version; 268 }; 269 270 /* 271 * Unlike locally-fulfilled SS, SSS doesn't have to hold metadata on client side 272 * but pass it through to the proxy. The client side doesn't know the real 273 * metadata names that are available in the policy (since it's hardcoded in code 274 * no point passing them back to the client from the policy). Because of that, 275 * it doesn't know how many to allocate when we create the sspc_handle either. 276 * 277 * So we use a linked-list of changed-but-not-yet-proxied metadata allocated 278 * on the heap and items removed as they are proxied out. Anything on the list 279 * is sent to the proxy before any requested tx is handled. 280 * 281 * This is also used to queue tx credit changes 282 */ 283 284 typedef struct lws_sspc_metadata { 285 lws_dll2_t list; 286 char name[32]; /* empty string, then actually TCXR */ 287 size_t len; 288 int tx_cr_adjust; 289 290 /* the value of length .len is overallocated after this */ 291 } lws_sspc_metadata_t; 292 293 /* state of the upstream proxy onward connection */ 294 295 enum { 296 LWSSSPC_ONW_NONE, 297 LWSSSPC_ONW_REQ, 298 LWSSSPC_ONW_ONGOING, 299 LWSSSPC_ONW_CONN, 300 }; 301 302 typedef struct lws_sspc_handle { 303 char rideshare_list[128]; 304 305 lws_lifecycle_t lc; 306 307 lws_ss_info_t ssi; 308 lws_sorted_usec_list_t sul_retry; 309 310 struct lws_ss_serialization_parser parser; 311 312 #if defined(LWS_WITH_SYS_FAULT_INJECTION) 313 lws_fi_ctx_t fic; /**< Fault Injection context */ 314 #endif 315 316 lws_dll2_owner_t metadata_owner; 317 lws_dll2_owner_t metadata_owner_rx; 318 319 struct lws_dll2 client_list; 320 struct lws_tx_credit txc; 321 322 #if defined(LWS_WITH_SYS_METRICS) 323 lws_metrics_caliper_compose(cal_txn) 324 #endif 325 326 struct lws *cwsi; 327 328 struct lws_dsh *dsh; 329 struct lws_context *context; 330 331 struct lws_sspc_handle *h_in_svc; 332 /* 333 * Used to detect illegal lws_sspc_destroy() calls while still 334 * being serviced 335 */ 336 337 lws_usec_t us_earliest_write_req; 338 lws_usec_t us_start_upstream; 339 340 unsigned long writeable_len; 341 342 lws_ss_conn_states_t state; 343 344 uint32_t timeout_ms; 345 uint32_t ord; 346 347 int16_t temp16; 348 349 uint8_t rideshare_ofs[4]; 350 uint8_t rsidx; 351 352 uint8_t prev_ss_state; 353 354 uint8_t conn_req_state:2; 355 uint8_t destroying:1; 356 uint8_t non_wsi:1; 357 uint8_t ignore_txc:1; 358 uint8_t pending_timeout_update:1; 359 uint8_t pending_writeable_len:1; 360 uint8_t creating_cb_done:1; 361 uint8_t ss_dangling_connected:1; 362 } lws_sspc_handle_t; 363 364 typedef struct backoffs { 365 struct backoffs *next; 366 const char *name; 367 lws_retry_bo_t r; 368 } backoff_t; 369 370 union u { 371 backoff_t *b; 372 lws_ss_x509_t *x; 373 lws_ss_trust_store_t *t; 374 lws_ss_policy_t *p; 375 lws_ss_auth_t *a; 376 lws_metric_policy_t *m; 377 }; 378 379 enum { 380 LTY_BACKOFF, 381 LTY_X509, 382 LTY_TRUSTSTORE, 383 LTY_POLICY, 384 LTY_AUTH, 385 LTY_METRICS, 386 387 _LTY_COUNT /* always last */ 388 }; 389 390 391 struct policy_cb_args { 392 struct lejp_ctx jctx; 393 struct lws_context *context; 394 struct lwsac *ac; 395 396 const char *socks5_proxy; 397 398 struct lws_b64state b64; 399 400 lws_ss_http_respmap_t respmap[16]; 401 402 union u heads[_LTY_COUNT]; 403 union u curr[_LTY_COUNT]; 404 405 uint8_t *p; 406 407 int count; 408 char pending_respmap; 409 410 uint8_t parse_data:1; 411 }; 412 413 #if defined(LWS_WITH_SYS_SMD) 414 extern const lws_ss_policy_t pol_smd; 415 #endif 416 417 418 /* 419 * returns one of 420 * 421 * LWSSSSRET_OK 422 * LWSSSSRET_DISCONNECT_ME 423 * LWSSSSRET_DESTROY_ME 424 */ 425 int 426 lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, 427 struct lws_context *context, 428 struct lws_dsh *dsh, const uint8_t *cp, size_t len, 429 lws_ss_conn_states_t *state, void *parconn, 430 lws_ss_handle_t **pss, lws_ss_info_t *ssi, char client); 431 int 432 lws_ss_serialize_rx_payload(struct lws_dsh *dsh, const uint8_t *buf, 433 size_t len, int flags, const char *rsp); 434 int 435 lws_ss_deserialize_tx_payload(struct lws_dsh *dsh, struct lws *wsi, 436 lws_ss_tx_ordinal_t ord, uint8_t *buf, 437 size_t *len, int *flags); 438 int 439 lws_ss_serialize_state(struct lws *wsi, struct lws_dsh *dsh, lws_ss_constate_t state, 440 lws_ss_tx_ordinal_t ack); 441 442 const lws_ss_policy_t * 443 lws_ss_policy_lookup(const struct lws_context *context, const char *streamtype); 444 445 /* can be used as a cb from lws_dll2_foreach_safe() to destroy ss */ 446 int 447 lws_ss_destroy_dll(struct lws_dll2 *d, void *user); 448 449 int 450 lws_sspc_destroy_dll(struct lws_dll2 *d, void *user); 451 452 void 453 lws_sspc_rxmetadata_destroy(lws_sspc_handle_t *h); 454 455 int 456 lws_ss_policy_set(struct lws_context *context, const char *name); 457 458 int 459 lws_ss_sys_fetch_policy(struct lws_context *context); 460 461 lws_ss_state_return_t 462 lws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs); 463 464 lws_ss_state_return_t 465 _lws_ss_backoff(lws_ss_handle_t *h, lws_usec_t us_override); 466 467 lws_ss_state_return_t 468 lws_ss_backoff(lws_ss_handle_t *h); 469 470 int 471 _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(lws_ss_state_return_t r, struct lws *wsi, 472 lws_ss_handle_t **ph); 473 474 int 475 lws_ss_set_timeout_us(lws_ss_handle_t *h, lws_usec_t us); 476 477 void 478 ss_proxy_onward_txcr(void *userobj, int bump); 479 480 int 481 lws_ss_serialize_txcr(struct lws_dsh *dsh, int txcr); 482 483 int 484 lws_ss_sys_auth_api_amazon_com(struct lws_context *context); 485 486 lws_ss_metadata_t * 487 lws_ss_get_handle_metadata(struct lws_ss_handle *h, const char *name); 488 lws_ss_metadata_t * 489 lws_ss_policy_metadata_index(const lws_ss_policy_t *p, size_t index); 490 491 #if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) 492 lws_ss_metadata_t * 493 lws_ss_get_handle_instant_metadata(struct lws_ss_handle *h, const char *name); 494 #endif 495 496 lws_ss_metadata_t * 497 lws_ss_policy_metadata(const lws_ss_policy_t *p, const char *name); 498 499 int 500 lws_ss_exp_cb_metadata(void *priv, const char *name, char *out, size_t *pos, 501 size_t olen, size_t *exp_ofs); 502 503 int 504 _lws_ss_set_metadata(lws_ss_metadata_t *omd, const char *name, 505 const void *value, size_t len); 506 507 int 508 _lws_ss_alloc_set_metadata(lws_ss_metadata_t *omd, const char *name, 509 const void *value, size_t len); 510 511 lws_ss_state_return_t 512 _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry, void *conn_if_sspc_onw); 513 514 lws_ss_state_return_t 515 _lws_ss_request_tx(lws_ss_handle_t *h); 516 517 int 518 __lws_ss_proxy_bind_ss_to_conn_wsi(void *parconn, size_t dsh_size); 519 520 struct lws_vhost * 521 lws_ss_policy_ref_trust_store(struct lws_context *context, 522 const lws_ss_policy_t *pol, char doref); 523 524 lws_ss_state_return_t 525 lws_sspc_event_helper(lws_sspc_handle_t *h, lws_ss_constate_t cs, 526 lws_ss_tx_ordinal_t flags); 527 528 int 529 lws_ss_check_next_state(lws_lifecycle_t *lc, uint8_t *prevstate, 530 lws_ss_constate_t cs); 531 532 int 533 lws_ss_check_next_state_ss(lws_ss_handle_t *ss, uint8_t *prevstate, 534 lws_ss_constate_t cs); 535 536 int 537 lws_ss_check_next_state_sspc(lws_sspc_handle_t *ss, uint8_t *prevstate, 538 lws_ss_constate_t cs); 539 540 void 541 lws_proxy_clean_conn_ss(struct lws *wsi); 542 543 int 544 lws_ss_cancel_notify_dll(struct lws_dll2 *d, void *user); 545 546 int 547 lws_sspc_cancel_notify_dll(struct lws_dll2 *d, void *user); 548 549 #if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) || defined(LWS_WITH_SECURE_STREAMS_CPP) 550 int 551 lws_ss_policy_unref_trust_store(struct lws_context *context, 552 const lws_ss_policy_t *pol); 553 #endif 554 555 int 556 lws_ss_sys_cpd(struct lws_context *cx); 557 558 #if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4) 559 int lws_ss_apply_sigv4(struct lws *wsi, struct lws_ss_handle *h, 560 unsigned char **p, unsigned char *end); 561 #endif 562 563 #if defined(_DEBUG) 564 void 565 lws_ss_assert_extant(struct lws_context *cx, int tsi, struct lws_ss_handle *h); 566 #else 567 #define lws_ss_assert_extant(_a, _b, _c) 568 #endif 569 570 typedef int (* const secstream_protocol_connect_munge_t)(lws_ss_handle_t *h, 571 char *buf, size_t len, struct lws_client_connect_info *i, 572 union lws_ss_contemp *ct); 573 574 typedef int (* const secstream_protocol_add_txcr_t)(lws_ss_handle_t *h, int add); 575 576 typedef int (* const secstream_protocol_get_txcr_t)(lws_ss_handle_t *h); 577 578 struct ss_pcols { 579 const char *name; 580 const char *alpn; 581 const struct lws_protocols *protocol; 582 secstream_protocol_connect_munge_t munge; 583 secstream_protocol_add_txcr_t tx_cr_add; 584 secstream_protocol_get_txcr_t tx_cr_est; 585 }; 586 587 /* 588 * Because both sides of the connection share the conn, we allocate it 589 * during accepted adoption, and both sides point to it. 590 * 591 * When .ss or .wsi close, they must NULL their entry here so no dangling 592 * refereneces. 593 * 594 * The last one of the accepted side and the onward side to close frees it. 595 */ 596 597 lws_ss_state_return_t 598 lws_conmon_ss_json(lws_ss_handle_t *h); 599 600 void 601 ss_proxy_onward_link_req_writeable(lws_ss_handle_t *h_onward); 602 603 struct conn { 604 struct lws_ss_serialization_parser parser; 605 606 lws_dsh_t *dsh; /* unified buffer for both sides */ 607 struct lws *wsi; /* the proxy's client side */ 608 lws_ss_handle_t *ss; /* the onward, ss side */ 609 610 lws_ss_conn_states_t state; 611 612 char onward_in_flow_control; 613 }; 614 615 extern const struct ss_pcols ss_pcol_h1; 616 extern const struct ss_pcols ss_pcol_h2; 617 extern const struct ss_pcols ss_pcol_ws; 618 extern const struct ss_pcols ss_pcol_mqtt; 619 extern const struct ss_pcols ss_pcol_raw; 620 621 extern const struct lws_protocols protocol_secstream_h1; 622 extern const struct lws_protocols protocol_secstream_h2; 623 extern const struct lws_protocols protocol_secstream_ws; 624 extern const struct lws_protocols protocol_secstream_mqtt; 625 extern const struct lws_protocols protocol_secstream_raw; 626 627