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 25 /* 26 * Secure Stream state 27 */ 28 29 typedef enum { 30 SSSEQ_IDLE, 31 SSSEQ_TRY_CONNECT, 32 SSSEQ_TRY_CONNECT_NAUTH, 33 SSSEQ_TRY_CONNECT_SAUTH, 34 SSSEQ_RECONNECT_WAIT, 35 SSSEQ_DO_RETRY, 36 SSSEQ_CONNECTED, 37 } lws_ss_seq_state_t; 38 39 40 /** 41 * lws_ss_handle_t: publicly-opaque secure stream object implementation 42 */ 43 44 typedef struct lws_ss_handle { 45 lws_ss_info_t info; /**< copy of stream creation info */ 46 struct lws_dll2 list; /**< pt lists active ss */ 47 struct lws_dll2 to_list; /**< pt lists ss with pending to-s */ 48 49 struct lws_dll2_owner src_list; /**< sink's list of bound sources */ 50 51 struct lws_context *context; /**< lws context we are created on */ 52 const lws_ss_policy_t *policy; /**< system policy for stream */ 53 54 struct lws_sequencer *seq; /**< owning sequencer if any */ 55 struct lws *wsi; /**< the stream wsi if any */ 56 57 void *nauthi; /**< the nauth plugin instance data */ 58 void *sauthi; /**< the sauth plugin instance data */ 59 60 lws_ss_metadata_t *metadata; 61 const lws_ss_policy_t *rideshare; 62 63 struct lws_ss_handle *h_sink; /**< sink we are bound to, or NULL */ 64 void *sink_obj;/**< sink's private object representing us */ 65 66 lws_sorted_usec_list_t sul; 67 lws_ss_tx_ordinal_t txord; 68 69 /* protocol-specific connection helpers */ 70 71 union { 72 73 /* ...for http-related protocols... */ 74 75 struct { 76 77 /* common to all http-related protocols */ 78 79 /* incoming multipart parsing */ 80 81 char boundary[24]; /* --boundary from headers */ 82 uint8_t boundary_len; /* length of --boundary */ 83 uint8_t boundary_seq; /* current match amount */ 84 uint8_t boundary_dashes; /* check for -- after */ 85 uint8_t boundary_post; /* swallow post CRLF */ 86 87 uint8_t som:1; /* SOM has been sent */ 88 uint8_t any:1; /* any content has been sent */ 89 90 91 uint8_t good_respcode:1; /* 200 type response code */ 92 93 union { 94 struct { /* LWSSSP_H1 */ 95 } h1; 96 struct { /* LWSSSP_H2 */ 97 } h2; 98 struct { /* LWSSSP_WS */ 99 } ws; 100 } u; 101 } http; 102 103 /* details for non-http related protocols... */ 104 #if defined(LWS_ROLE_MQTT) 105 struct { 106 lws_mqtt_topic_elem_t topic_qos; 107 lws_mqtt_topic_elem_t sub_top; 108 lws_mqtt_subscribe_param_t sub_info; 109 } mqtt; 110 #endif 111 } u; 112 113 unsigned long writeable_len; 114 115 lws_ss_constate_t connstate;/**< public connection state */ 116 lws_ss_seq_state_t seqstate; /**< private connection state */ 117 118 uint16_t retry; /**< retry / backoff tracking */ 119 int16_t temp16; 120 121 uint8_t tsi; /**< service thread idx, usually 0 */ 122 uint8_t subseq; /**< emulate SOM tracking */ 123 uint8_t txn_ok; /**< 1 = transaction was OK */ 124 125 uint8_t hanging_som:1; 126 uint8_t inside_msg:1; 127 uint8_t being_serialized:1; /* we are not the consumer */ 128 } lws_ss_handle_t; 129 130 /* connection helper that doesn't need to hang around after connection starts */ 131 132 union lws_ss_contemp { 133 #if defined(LWS_ROLE_MQTT) 134 lws_mqtt_client_connect_param_t ccp; 135 #endif 136 }; 137 138 /* 139 * When allocating the opaque handle, we overallocate for: 140 * 141 * 1) policy->nauth_plugin->alloc (.nauthi) if any 142 * 2) policy->sauth_plugin->alloc (.sauthi) if any 143 * 3) copy of creation info stream type pointed to by info.streamtype... this 144 * may be arbitrarily long and since it may be coming from socket ipc and be 145 * temporary at creation time, we need a place for the copy to stay in scope 146 * 4) copy of info->streamtype contents 147 */ 148 149 150 /* the user object allocation is immediately after the ss object allocation */ 151 #define ss_to_userobj(ss) ((void *)&(ss)[1]) 152 153 /* 154 * serialization parser state 155 */ 156 157 enum { 158 KIND_C_TO_P, 159 KIND_SS_TO_P, 160 }; 161 162 struct lws_ss_serialization_parser { 163 char streamtype[32]; 164 char rideshare[32]; 165 char metadata_name[32]; 166 167 uint64_t ust_pwait; 168 169 lws_ss_metadata_t *ssmd; 170 171 int ps; 172 int ctr; 173 174 uint32_t usd_phandling; 175 uint32_t flags; 176 int32_t temp32; 177 178 int32_t txcr_out; 179 int32_t txcr_in; 180 uint16_t rem; 181 182 uint8_t type; 183 uint8_t frag1; 184 uint8_t slen; 185 uint8_t rsl_pos; 186 uint8_t rsl_idx; 187 }; 188 189 /* 190 * Unlike locally-fulfilled SS, SSS doesn't have to hold metadata on client side 191 * but pass it through to the proxy. The client side doesn't know the real 192 * metadata names that are available in the policy (since it's hardcoded in code 193 * no point passing them back to the client from the policy). Because of that, 194 * it doesn't know how many to allocate when we create the sspc_handle either. 195 * 196 * So we use a linked-list of changed-but-not-yet-proxied metadata allocated 197 * on the heap and items removed as they are proxied out. Anything on the list 198 * is sent to the proxy before any requested tx is handled. 199 * 200 * This is also used to queue tx credit changes 201 */ 202 203 typedef struct lws_sspc_metadata { 204 lws_dll2_t list; 205 char name[32]; /* empty string, then actually TCXR */ 206 size_t len; 207 int tx_cr_adjust; 208 209 /* the value of length .len is overallocated after this */ 210 } lws_sspc_metadata_t; 211 212 213 typedef struct lws_sspc_handle { 214 char rideshare_list[128]; 215 lws_ss_info_t ssi; 216 lws_sorted_usec_list_t sul_retry; 217 218 struct lws_ss_serialization_parser parser; 219 220 lws_dll2_owner_t metadata_owner; 221 222 struct lws_dll2 client_list; 223 struct lws_tx_credit txc; 224 225 struct lws *cwsi; 226 227 struct lws_dsh *dsh; 228 struct lws_context *context; 229 230 lws_usec_t us_earliest_write_req; 231 232 lws_ss_conn_states_t state; 233 234 int16_t temp16; 235 236 uint32_t ord; 237 238 uint8_t rideshare_ofs[4]; 239 uint8_t conn_req; 240 uint8_t rsidx; 241 242 uint8_t destroying:1; 243 } lws_sspc_handle_t; 244 245 int 246 lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, 247 struct lws_context *context, 248 struct lws_dsh *dsh, const uint8_t *cp, size_t len, 249 lws_ss_conn_states_t *state, void *parconn, 250 lws_ss_handle_t **pss, lws_ss_info_t *ssi, char client); 251 int 252 lws_ss_serialize_rx_payload(struct lws_dsh *dsh, const uint8_t *buf, 253 size_t len, int flags, const char *rsp); 254 int 255 lws_ss_deserialize_tx_payload(struct lws_dsh *dsh, struct lws *wsi, 256 lws_ss_tx_ordinal_t ord, uint8_t *buf, 257 size_t *len, int *flags); 258 int 259 lws_ss_serialize_state(struct lws_dsh *dsh, lws_ss_constate_t state, 260 lws_ss_tx_ordinal_t ack); 261 262 void 263 lws_ss_serialize_state_transition(lws_ss_conn_states_t *state, int new_state); 264 265 const lws_ss_policy_t * 266 lws_ss_policy_lookup(const struct lws_context *context, const char *streamtype); 267 268 /* can be used as a cb from lws_dll2_foreach_safe() to destroy ss */ 269 int 270 lws_ss_destroy_dll(struct lws_dll2 *d, void *user); 271 272 int 273 lws_sspc_destroy_dll(struct lws_dll2 *d, void *user); 274 275 276 int 277 lws_ss_policy_parse_begin(struct lws_context *context); 278 279 int 280 lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len); 281 282 int 283 lws_ss_policy_set(struct lws_context *context, const char *name); 284 285 int 286 lws_ss_policy_parse_abandon(struct lws_context *context); 287 288 int 289 lws_ss_sys_fetch_policy(struct lws_context *context); 290 291 int 292 lws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs); 293 294 int 295 lws_ss_backoff(lws_ss_handle_t *h); 296 297 int 298 lws_ss_set_timeout_us(lws_ss_handle_t *h, lws_usec_t us); 299 300 void 301 ss_proxy_onward_txcr(void *userobj, int bump); 302 303 int 304 lws_ss_serialize_txcr(struct lws_dsh *dsh, int txcr); 305 306 int 307 lws_ss_sys_auth_api_amazon_com(struct lws_context *context); 308 309 lws_ss_metadata_t * 310 lws_ss_get_handle_metadata(struct lws_ss_handle *h, const char *name); 311 lws_ss_metadata_t * 312 lws_ss_policy_metadata_index(const lws_ss_policy_t *p, size_t index); 313 314 lws_ss_metadata_t * 315 lws_ss_policy_metadata(const lws_ss_policy_t *p, const char *name); 316 317 int 318 lws_ss_exp_cb_metadata(void *priv, const char *name, char *out, size_t *pos, 319 size_t olen, size_t *exp_ofs); 320 321 typedef int (* const secstream_protocol_connect_munge_t)(lws_ss_handle_t *h, 322 char *buf, size_t len, struct lws_client_connect_info *i, 323 union lws_ss_contemp *ct); 324 325 typedef int (* const secstream_protocol_add_txcr_t)(lws_ss_handle_t *h, int add); 326 327 typedef int (* const secstream_protocol_get_txcr_t)(lws_ss_handle_t *h); 328 329 struct ss_pcols { 330 const char *name; 331 const char *alpn; 332 const char *protocol_name; 333 const secstream_protocol_connect_munge_t munge; 334 const secstream_protocol_add_txcr_t tx_cr_add; 335 const secstream_protocol_get_txcr_t tx_cr_est; 336 }; 337 338 extern const struct ss_pcols ss_pcol_h1; 339 extern const struct ss_pcols ss_pcol_h2; 340 extern const struct ss_pcols ss_pcol_ws; 341 extern const struct ss_pcols ss_pcol_mqtt; 342 343 extern const struct lws_protocols protocol_secstream_h1; 344 extern const struct lws_protocols protocol_secstream_h2; 345 extern const struct lws_protocols protocol_secstream_ws; 346 extern const struct lws_protocols protocol_secstream_mqtt; 347 348