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