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 typedef int (*plugin_auth_status_cb)(struct lws_ss_handle *ss, int status); 28 29 /** 30 * lws_ss_plugin_auth_t - api for an auth plugin 31 * 32 * Auth plugins create and sequence authenticated connections that can carry one 33 * or more streams to an endpoint. That may involve other connections to other 34 * places to eg, gather authenticated tokens and then make the real connection 35 * using the tokens. 36 * 37 * The secure stream object contains members to record which auth plugin the 38 * stream is bound to and an over-allocation of the secure stream object to 39 * contain the plugin auth private data. 40 * 41 * The auth plugin controls the state of the stream connection via the status 42 * callback, and handles retries. 43 * 44 * Network connections may require one kind of auth sequencing, and streams 45 * inside those connections another kind of auth sequencing depending on their 46 * role. So the secure stream object allows defining plugins for both kinds. 47 * 48 * Streams may disappear at any time and require reauth to bring a new one up. 49 * The auth plugin sequencer will connect / reconnect either on demand, or from 50 * the start and after any connectivity loss if any stream using the connection 51 * has the LWSSSPOLF_NAILED_UP flag. 52 */ 53 54 #if defined(LWS_WITH_SSPLUGINS) 55 typedef struct lws_ss_plugin { 56 struct lws_ss_plugin *next; 57 const char *name; /**< auth plugin name */ 58 size_t alloc; /**< size of private allocation */ 59 60 int (*create)(struct lws_ss_handle *ss, void *info, 61 plugin_auth_status_cb status); 62 /**< called when the auth plugin is instantiated 63 and bound to the secure stream. status is 64 called back with advisory information about 65 the authenticated stream state as it 66 proceeds */ 67 int (*destroy)(struct lws_ss_handle *ss); 68 /**< called when the related secure stream is 69 being destroyed, and anything the auth 70 plugin is doing should also be destroyed */ 71 int (*munge)(struct lws_ss_handle *ss, char *path, 72 size_t path_len); 73 /**< if the plugin needs to munge transactions 74 that have metadata outside the payload (eg, 75 add http headers) this callback will give 76 it the opportunity to do so */ 77 } lws_ss_plugin_t; 78 #endif 79 80 /* the public, const metrics policy definition */ 81 82 typedef struct lws_metric_policy { 83 /* order of first two mandated by JSON policy parsing scope union */ 84 const struct lws_metric_policy *next; 85 const char *name; 86 87 const char *report; 88 89 /**< the metrics policy name in the policy, used to bind to it */ 90 uint64_t us_schedule; 91 /**< us interval between lws_system metrics api reports */ 92 93 uint32_t us_decay_unit; 94 /**< how many us to decay avg by half, 0 = no decay */ 95 uint8_t min_contributors; 96 /**< before we can judge something is an outlier */ 97 } lws_metric_policy_t; 98 99 typedef struct lws_ss_x509 { 100 struct lws_ss_x509 *next; 101 const char *vhost_name; /**< vhost name using cert ctx */ 102 const uint8_t *ca_der; /**< DER x.509 cert */ 103 size_t ca_der_len; /**< length of DER cert */ 104 uint8_t keep:1; /**< ie, if used in server tls */ 105 } lws_ss_x509_t; 106 107 enum { 108 LWSSSPOLF_OPPORTUNISTIC = (1 << 0), 109 /**< the connection doesn't exist unless client asks to write */ 110 LWSSSPOLF_NAILED_UP = (1 << 1), 111 /**< the connection tries to be connected the whole life of the ss */ 112 LWSSSPOLF_URGENT_TX = (1 << 2), 113 /**< this connection carries critical tx data */ 114 LWSSSPOLF_URGENT_RX = (1 << 3), 115 /**< this connection carries critical rx data */ 116 LWSSSPOLF_TLS = (1 << 4), 117 /**< stream must be connected via a tls tunnel */ 118 LWSSSPOLF_LONG_POLL = (1 << 5), 119 /**< stream used to receive async rx at arbitrary intervals */ 120 LWSSSPOLF_AUTH_BEARER = (1 << 6), 121 /**< for http, use lws_system auth token 0 in authentication: bearer */ 122 LWSSSPOLF_HTTP_NO_CONTENT_LENGTH = (1 << 7), 123 /**< don't add any content length even if we have it */ 124 LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM = (1 << 8), 125 /**< set the client flag LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM */ 126 LWSSSPOLF_H2_QUIRK_OVERFLOWS_TXCR = (1 << 9), 127 /**< set the client flag LCCSCF_H2_QUIRK_OVERFLOWS_TXCR */ 128 LWSSSPOLF_H2_QUIRK_UNCLEAN_HPACK_STATE = (1 << 10), 129 /**< HPACK decoder state does not end cleanly */ 130 LWSSSPOLF_HTTP_MULTIPART = (1 << 11), 131 /**< indicates stream goes out as specifically a multipart mime POST 132 * section... if the tx has LWSSS_FLAG_COALESCE_CONTINUES flag then more 133 * multipart sections are expected. Without it, the multipart wrapper 134 * is closed and the http transaction issue completed when this message 135 * finishes. */ 136 LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED = (1 << 12), 137 /**< set up lws_system client cert */ 138 LWSSSPOLF_LOCAL_SINK = (1 << 13), 139 /**< expected to bind to a local sink only */ 140 LWSSSPOLF_WAKE_SUSPEND__VALIDITY = (1 << 14), 141 /**< this stream's idle validity checks are critical enough we 142 * should arrange to wake from suspend to perform them 143 */ 144 LWSSSPOLF_SERVER = (1 << 15), 145 /**< we listen on a socket as a server */ 146 LWSSSPOLF_ALLOW_REDIRECTS = (1 << 16), 147 /**< follow redirects */ 148 LWSSSPOLF_HTTP_MULTIPART_IN = (1 << 17), 149 /**< handle inbound multipart mime at SS level */ 150 151 LWSSSPOLF_ATTR_LOW_LATENCY = (1 << 18), 152 /**< stream requires low latency */ 153 LWSSSPOLF_ATTR_HIGH_THROUGHPUT = (1 << 19), 154 /**< stream requires high throughput */ 155 LWSSSPOLF_ATTR_HIGH_RELIABILITY = (1 << 20), 156 /**< stream requires high reliability */ 157 LWSSSPOLF_ATTR_LOW_COST = (1 << 21), 158 /**< stream is not critical and should be handled as cheap as poss */ 159 LWSSSPOLF_PERF = (1 << 22), 160 /**< capture and report performace information */ 161 LWSSSPOLF_DIRECT_PROTO_STR = (1 << 23), 162 /**< metadata as direct protocol string, e.g. http header */ 163 LWSSSPOLF_HTTP_CACHE_COOKIES = (1 << 24), 164 /**< Record http cookies and pass them back on future requests */ 165 LWSSSPOLF_PRIORITIZE_READS = (1 << 25), 166 /**< prioritize clearing reads at expense of writes */ 167 168 }; 169 170 typedef struct lws_ss_trust_store { 171 struct lws_ss_trust_store *next; 172 const char *name; 173 174 const lws_ss_x509_t *ssx509[6]; 175 int count; 176 } lws_ss_trust_store_t; 177 178 enum { 179 LWSSSP_H1, 180 LWSSSP_H2, 181 LWSSSP_WS, 182 LWSSSP_MQTT, 183 LWSSSP_RAW, 184 185 186 LWSSS_HBI_AUTH = 0, 187 LWSSS_HBI_DSN, 188 LWSSS_HBI_FWV, 189 LWSSS_HBI_TYPE, 190 191 _LWSSS_HBI_COUNT /* always last */ 192 }; 193 194 /* 195 * This does for both the static policy metadata entry, and the runtime metadata 196 * handling object. 197 */ 198 199 typedef struct lws_ss_metadata { 200 struct lws_ss_metadata *next; 201 const char *name; 202 void *value__may_own_heap; 203 size_t length; 204 205 uint8_t value_length; /* only valid if set by policy */ 206 uint8_t value_is_http_token; /* valid if set by policy */ 207 #if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) 208 uint8_t name_on_lws_heap:1; /* proxy metatadata does this */ 209 #endif 210 uint8_t value_on_lws_heap:1; /* proxy + rx metadata does this */ 211 #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) 212 uint8_t pending_onward:1; 213 #endif 214 } lws_ss_metadata_t; 215 216 typedef struct lws_ss_http_respmap { 217 uint16_t resp; /* the http response code */ 218 uint16_t state; /* low 16-bits of associated state */ 219 } lws_ss_http_respmap_t; 220 221 /* 222 * This is a mapping between an auth streamtype and a name and other information 223 * that can be independently instantiated. Other streamtypes can indicate they 224 * require this authentication on their connection. 225 */ 226 227 typedef struct lws_ss_auth { 228 struct lws_ss_auth *next; 229 const char *name; 230 231 const char *type; 232 const char *streamtype; 233 uint8_t blob_index; 234 } lws_ss_auth_t; 235 236 /** 237 * lws_ss_policy_t: policy database entry for a stream type 238 * 239 * Decides the system policy for how to implement connections of name 240 * .streamtype. 241 * 242 * Streams may need one kind of auth sequencing for the network connection and 243 * another kind of auth sequencing for the streams that are carried inside it, 244 * this is the purpose of .nauth and .sauth. Both are optional and may be NULL. 245 * 246 * An array of these is set at context creation time, ending with one with a 247 * NULL streamtype. 248 */ 249 typedef struct lws_ss_policy { 250 struct lws_ss_policy *next; 251 const char *streamtype; /**< stream type lhs to match on */ 252 253 const char *endpoint; /**< DNS address to connect to */ 254 const char *rideshare_streamtype; /**< optional transport 255 * on another, preexisting stream of this 256 * streamtype name */ 257 const char *payload_fmt; 258 const char *socks5_proxy; 259 lws_ss_metadata_t *metadata; /* linked-list of metadata */ 260 const lws_metric_policy_t *metrics; /* linked-list of metric policies */ 261 const lws_ss_auth_t *auth; /* NULL or auth object we bind to */ 262 263 /* protocol-specific connection policy details */ 264 265 union { 266 267 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) || defined(LWS_ROLE_WS) 268 269 /* details for http-related protocols... */ 270 271 struct { 272 273 /* common to all http-related protocols */ 274 275 const char *method; 276 const char *url; 277 278 const char *multipart_name; 279 const char *multipart_filename; 280 const char *multipart_content_type; 281 282 const char *blob_header[_LWSSS_HBI_COUNT]; 283 const char *auth_preamble; 284 285 const lws_ss_http_respmap_t *respmap; 286 287 union { 288 // struct { /* LWSSSP_H1 */ 289 // } h1; 290 // struct { /* LWSSSP_H2 */ 291 // } h2; 292 struct { /* LWSSSP_WS */ 293 const char *subprotocol; 294 uint8_t binary; 295 /* false = TEXT, true = BINARY */ 296 } ws; 297 } u; 298 299 uint16_t resp_expect; 300 uint8_t count_respmap; 301 uint8_t fail_redirect:1; 302 } http; 303 304 #endif 305 306 #if defined(LWS_ROLE_MQTT) 307 308 struct { 309 const char *topic; /* stream sends on this topic */ 310 const char *subscribe; /* stream subscribes to this topic */ 311 312 const char *will_topic; 313 const char *will_message; 314 315 const char *birth_topic; 316 const char *birth_message; 317 318 uint16_t keep_alive; 319 uint8_t qos; 320 uint8_t clean_start; 321 uint8_t will_qos; 322 uint8_t will_retain; 323 uint8_t birth_qos; 324 uint8_t birth_retain; 325 uint8_t aws_iot; 326 uint8_t retain; 327 328 } mqtt; 329 330 #endif 331 332 /* details for non-http related protocols... */ 333 } u; 334 335 #if defined(LWS_WITH_SSPLUGINS) 336 const 337 struct lws_ss_plugin *plugins[2]; /**< NULL or auth plugin */ 338 const void *plugins_info[2]; /**< plugin-specific data */ 339 #endif 340 341 #if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4) 342 /* directly point to the metadata name, no need to expand */ 343 const char *aws_region; 344 const char *aws_service; 345 #endif 346 /* 347 * We're either a client connection policy that wants a trust store, 348 * or we're a server policy that wants a mem cert and key... Hold 349 * these mutually-exclusive things in a union. 350 */ 351 352 union { 353 const lws_ss_trust_store_t *store; 354 /**< CA certs needed for conn validation, only set between 355 * policy parsing and vhost creation */ 356 struct { 357 const lws_ss_x509_t *cert; 358 /**< the server's signed cert with the pubkey */ 359 const lws_ss_x509_t *key; 360 /**< the server's matching private key */ 361 } server; 362 } trust; 363 364 const lws_retry_bo_t *retry_bo; /**< retry policy to use */ 365 366 uint32_t proxy_buflen; /**< max dsh alloc for proxy */ 367 uint32_t proxy_buflen_rxflow_on_above; 368 uint32_t proxy_buflen_rxflow_off_below; 369 370 uint32_t client_buflen; /**< max dsh alloc for client */ 371 uint32_t client_buflen_rxflow_on_above; 372 uint32_t client_buflen_rxflow_off_below; 373 374 375 uint32_t timeout_ms; /**< default message response 376 * timeout in ms */ 377 uint32_t flags; /**< stream attribute flags */ 378 379 uint16_t port; /**< endpoint port */ 380 381 uint8_t metadata_count; /**< metadata count */ 382 uint8_t protocol; /**< protocol index */ 383 uint8_t client_cert; /**< which client cert to apply 384 0 = none, 1+ = cc 0+ */ 385 uint8_t priority; /* 0 = normal, 6 = max normal, 386 * 7 = network management */ 387 } lws_ss_policy_t; 388 389 #if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) 390 391 /* 392 * These only exist / have meaning if there's a dynamic JSON policy enabled 393 */ 394 395 LWS_VISIBLE LWS_EXTERN int 396 lws_ss_policy_parse_begin(struct lws_context *context, int overlay); 397 398 LWS_VISIBLE LWS_EXTERN int 399 lws_ss_policy_parse_abandon(struct lws_context *context); 400 401 LWS_VISIBLE LWS_EXTERN int 402 lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len); 403 404 LWS_VISIBLE LWS_EXTERN int 405 lws_ss_policy_overlay(struct lws_context *context, const char *overlay); 406 407 /* 408 * You almost certainly don't want these, they return the first policy or auth 409 * object in a linked-list of objects created by lws_ss_policy_parse above, 410 * they are exported to generate static policy with 411 */ 412 LWS_VISIBLE LWS_EXTERN const lws_ss_policy_t * 413 lws_ss_policy_get(struct lws_context *context); 414 415 LWS_VISIBLE LWS_EXTERN const lws_ss_auth_t * 416 lws_ss_auth_get(struct lws_context *context); 417 418 #endif 419