diff --git a/include/libwebsockets/lws-secure-streams-client.h b/include/libwebsockets/lws-secure-streams-client.h index 035c7c3a1..042716ac8 100644 --- a/include/libwebsockets/lws-secure-streams-client.h +++ b/include/libwebsockets/lws-secure-streams-client.h @@ -52,6 +52,7 @@ #define lws_ss_get_context lws_sspc_get_context #define lws_ss_rideshare lws_sspc_rideshare #define lws_ss_set_metadata lws_sspc_set_metadata +#define lws_ss_get_metadata lws_sspc_get_metadata #define lws_ss_add_peer_tx_credit lws_sspc_add_peer_tx_credit #define lws_ss_get_est_peer_tx_credit lws_sspc_get_est_peer_tx_credit #define lws_ss_start_timeout lws_sspc_start_timeout @@ -190,6 +191,10 @@ LWS_VISIBLE LWS_EXTERN int lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, const void *value, size_t len); +LWS_VISIBLE LWS_EXTERN int +lws_sspc_get_metadata(struct lws_sspc_handle *h, const char *name, + const void **value, size_t *len); + LWS_VISIBLE LWS_EXTERN int lws_sspc_add_peer_tx_credit(struct lws_sspc_handle *h, int32_t add); diff --git a/include/libwebsockets/lws-secure-streams-policy.h b/include/libwebsockets/lws-secure-streams-policy.h index 0337d72ff..ac73d0e63 100644 --- a/include/libwebsockets/lws-secure-streams-policy.h +++ b/include/libwebsockets/lws-secure-streams-policy.h @@ -154,13 +154,23 @@ enum { _LWSSS_HBI_COUNT /* always last */ }; +/* + * This does for both the static policy metadata entry, and the runtime metadata + * handling object. + */ + typedef struct lws_ss_metadata { struct lws_ss_metadata *next; const char *name; void *value; size_t length; - uint8_t value_on_lws_heap; /* proxy does this */ + uint8_t value_on_lws_heap; /* proxy + rx metadata does this */ + uint8_t value_is_http_token; /* valid if set by policy */ + uint8_t value_length; /* only valid if set by policy */ +#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) + uint8_t pending_onward:1; +#endif } lws_ss_metadata_t; diff --git a/include/libwebsockets/lws-secure-streams.h b/include/libwebsockets/lws-secure-streams.h index 34a3aad1c..4cffc6d36 100644 --- a/include/libwebsockets/lws-secure-streams.h +++ b/include/libwebsockets/lws-secure-streams.h @@ -132,6 +132,14 @@ * - 1: 00, 04 * - 3: 4-byte MSB-first addition tx credit bytes * + * - Proxied rx metadata + * + * - 0: LWSSS_SER_RXPRE_METADATA + * - 1: 2-byte MSB-first rest-of-frame length + * - 3: 1-byte metadata name length + * - 4: metadata name + * - ...: metadata value (for rest of packet) + * * - Proxied state * * - 0: LWSSS_SER_RXPRE_CONNSTATE @@ -227,6 +235,7 @@ enum { LWSSS_SER_RXPRE_CREATE_RESULT, LWSSS_SER_RXPRE_CONNSTATE, LWSSS_SER_RXPRE_TXCR_UPDATE, + LWSSS_SER_RXPRE_METADATA, LWSSS_SER_RXPRE_TLSNEG_ENCLAVE_SIGN, /* tx (send by client) prepends for proxied connections */ @@ -564,6 +573,37 @@ LWS_VISIBLE LWS_EXTERN int lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, const void *value, size_t len); +/** + * lws_ss_get_metadata() - get current value of stream metadata item + * + * \param h: secure streams handle + * \param name: metadata name from the policy + * \param value: pointer to pointer to be set to point at the value + * \param len: pointer to size_t to set to the length of the value + * + * Binds user-managed data to the named metadata item from the ss policy. + * If present, the metadata item is handled in a protocol-specific way using + * the associated policy information. For example, in the policy + * + * "\"metadata\":" "[" + * "{\"uptag\":" "\"X-Upload-Tag:\"}," + * "{\"ctype\":" "\"Content-Type:\"}," + * "{\"xctype\":" "\"\"}" + * "]," + * + * when the policy is using h1 is interpreted to add h1 headers of the given + * name with the value of the metadata on the left. + * + * Return 0 if *value and *len set OK, or nonzero if, eg, metadata name does + * not exist on the streamtype. + * + * The pointed-to values may only exist until the next time around the event + * loop. + */ +LWS_VISIBLE LWS_EXTERN int +lws_ss_get_metadata(struct lws_ss_handle *h, const char *name, + const void **value, size_t *len); + /* * lws_ss_server_ack() - indicate how we feel about what the server has sent * diff --git a/lib/roles/http/header.c b/lib/roles/http/header.c index 02c3a9f5b..7597824a7 100644 --- a/lib/roles/http/header.c +++ b/lib/roles/http/header.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -35,6 +35,22 @@ lws_token_to_string(enum lws_token_indexes token) return (unsigned char *)set[token]; } +/* + * Return http header index if one matches slen chars of s, or -1 + */ + +int +lws_http_string_to_known_header(const char *s, size_t slen) +{ + int n; + + for (n = 0; n < (int)LWS_ARRAY_SIZE(set); n++) + if (!strncmp(set[n], s, slen)) + return n; + + return -1; +} + int lws_add_http_header_by_name(struct lws *wsi, const unsigned char *name, const unsigned char *value, int length, diff --git a/lib/roles/http/private-lib-roles-http.h b/lib/roles/http/private-lib-roles-http.h index 7d02c7ef5..c79bcef71 100644 --- a/lib/roles/http/private-lib-roles-http.h +++ b/lib/roles/http/private-lib-roles-http.h @@ -327,6 +327,9 @@ lws_sul_http_ah_lifecheck(lws_sorted_usec_list_t *sul); uint8_t * lws_http_multipart_headers(struct lws *wsi, uint8_t *p); +int +lws_http_string_to_known_header(const char *s, size_t slen); + enum { CCTLS_RETURN_ERROR = -1, CCTLS_RETURN_DONE = 0, diff --git a/lib/secure-streams/README.md b/lib/secure-streams/README.md index ca0dfbdb5..a5b1df89a 100644 --- a/lib/secure-streams/README.md +++ b/lib/secure-streams/README.md @@ -326,6 +326,33 @@ interval described in the associated retry / backoff selection, are important enough to wake the whole system from low power suspend so they happen on schedule. +### `metadata` + +This allows declaring basically dynamic symbol names to be used by the streamtype, +along with an optional mapping to a protocol-specific entity such as a given +http header. Eg: + +``` + "metadata": [ { "myname": "" }, { "ctype": "content-type:" } ], +``` + +In this example "ctype" is associated with the http header "content-type" while +"myname" doesn't have any association to a header. + +Symbol names may be used in the other policy for the streamtype for string +substitution using the syntax like `xxx${myname}yyy`, forward references are +valid but the scope of the symbols is just the streamtype the metadata is +defined for. + +Client code can set metadata by name, using the `lws_ss_set_metadata()` api, this +should be done before a transaction. And for metadata associated with a +protocol-specific entity, like http headers, if incoming responses contain the +mentioned header, the metadata symbol is set to that value at the client before +any rx proceeds. + +Metadata continues to work the same for the client in the case it is proxying its +connectivity, metadata is passed in both directions serialized over the proxy link. + ## http transport ### `http_method` diff --git a/lib/secure-streams/policy-common.c b/lib/secure-streams/policy-common.c index a4b2ab6b2..4f1771ec1 100644 --- a/lib/secure-streams/policy-common.c +++ b/lib/secure-streams/policy-common.c @@ -59,16 +59,35 @@ int lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, const void *value, size_t len) { - lws_ss_metadata_t *omd = lws_ss_policy_metadata(h->policy, name); + lws_ss_metadata_t *omd = lws_ss_get_handle_metadata(h, name); if (!omd) { lwsl_info("%s: unknown metadata %s\n", __func__, name); return 1; } - h->metadata[omd->length].name = name; - h->metadata[omd->length].value = (void *)value; - h->metadata[omd->length].length = len; + // lwsl_notice("%s: %s %s\n", __func__, name, (const char *)value); + + omd->name = name; + omd->value = (void *)value; + omd->length = len; + + return 0; +} + +int +lws_ss_get_metadata(struct lws_ss_handle *h, const char *name, + const void **value, size_t *len) +{ + lws_ss_metadata_t *omd = lws_ss_get_handle_metadata(h, name); + + if (!omd) { + lwsl_info("%s: unknown metadata %s\n", __func__, name); + return 1; + } + + *value = omd->value; + *len = omd->length; return 0; } @@ -76,12 +95,13 @@ lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, lws_ss_metadata_t * lws_ss_get_handle_metadata(struct lws_ss_handle *h, const char *name) { - lws_ss_metadata_t *omd = lws_ss_policy_metadata(h->policy, name); + int n = 0; - if (!omd) - return NULL; + for (n = 0; n < h->policy->metadata_count; n++) + if (!strcmp(name, h->metadata[n].name)) + return &h->metadata[n]; - return &h->metadata[omd->length]; + return NULL; } lws_ss_metadata_t * diff --git a/lib/secure-streams/policy-json.c b/lib/secure-streams/policy-json.c index 718e6c4d9..d0a452fc9 100644 --- a/lib/secure-streams/policy-json.c +++ b/lib/secure-streams/policy-json.c @@ -642,8 +642,20 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) a->curr[LTY_POLICY].p->metadata->value = q; memcpy(q, ctx->buf, ctx->npos); +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) + /* + * Check the metadata value part to see if it's a well-known + * http header... if so, 0xff means no header string match else + * it's the well-known header index + */ + a->curr[LTY_POLICY].p->metadata->value_is_http_token = (uint8_t) + lws_http_string_to_known_header(ctx->buf, ctx->npos); +#endif + a->curr[LTY_POLICY].p->metadata->length = /* the index in handle->metadata */ a->curr[LTY_POLICY].p->metadata_count++; + + a->curr[LTY_POLICY].p->metadata->value_length = ctx->npos; break; #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index 4905cde13..07bee1b5b 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -200,6 +200,7 @@ struct lws_ss_serialization_parser { uint64_t ust_pwait; lws_ss_metadata_t *ssmd; + uint8_t *rxmetaval; int ps; int ctr; @@ -259,6 +260,7 @@ typedef struct lws_sspc_handle { struct lws_ss_serialization_parser parser; lws_dll2_owner_t metadata_owner; + lws_dll2_owner_t metadata_owner_rx; struct lws_dll2 client_list; struct lws_tx_credit txc; @@ -373,6 +375,9 @@ lws_ss_destroy_dll(struct lws_dll2 *d, void *user); int lws_sspc_destroy_dll(struct lws_dll2 *d, void *user); +void +lws_sspc_rxmetadata_destroy(lws_sspc_handle_t *h); + int lws_ss_policy_set(struct lws_context *context, const char *name); diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index 5e1236508..8055ab866 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -152,26 +152,21 @@ around: } #endif +/* + * This converts any set metadata items into outgoing http headers + */ + static int lws_apply_metadata(lws_ss_handle_t *h, struct lws *wsi, uint8_t *buf, uint8_t **pp, uint8_t *end) { - int m; + lws_ss_metadata_t *polmd = h->policy->metadata; + int m = 0; - for (m = 0; m < h->policy->metadata_count; m++) { - lws_ss_metadata_t *polmd; + while (polmd) { - /* has to have a header string listed */ - if (!h->metadata[m].value) - continue; + /* has to have a non-empty header string */ - polmd = lws_ss_policy_metadata_index(h->policy, m); - - assert(polmd); - if (!polmd) - return -1; - - /* has to have a value */ if (polmd->value && ((uint8_t *)polmd->value)[0]) { if (lws_add_http_header_by_name(wsi, polmd->value, @@ -179,6 +174,9 @@ lws_apply_metadata(lws_ss_handle_t *h, struct lws *wsi, uint8_t *buf, (int)h->metadata[m].length, pp, end)) return -1; } + + m++; + polmd = polmd->next; } /* @@ -204,6 +202,111 @@ lws_apply_metadata(lws_ss_handle_t *h, struct lws *wsi, uint8_t *buf, return 0; } + +/* + * Check if any metadata headers present in the server headers, and record + * them into the associated metadata item if so. + */ + +static int +lws_extract_metadata(lws_ss_handle_t *h, struct lws *wsi) +{ + lws_ss_metadata_t *polmd = h->policy->metadata, *omd; + int n, m = 0; + + while (polmd) { + + if (polmd->value_is_http_token != 0xff) { + + /* it's a well-known header token */ + + n = lws_hdr_total_length(wsi, polmd->value_is_http_token); + if (n) { + const char *cp = lws_hdr_simple_ptr(wsi, + polmd->value_is_http_token); + + /* + * it's present on the wsi, we want to + * set the related metadata name to it then + */ + + lws_ss_set_metadata(h, polmd->name, cp, n); + + /* + * ...and because we are doing it from parsing + * onward rx, we want to mark the metadata as + * needing passing to the client + */ + + omd = lws_ss_get_handle_metadata(h, polmd->name); + assert(!strcmp(omd->name, polmd->name)); +#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) + omd->pending_onward = 1; +#endif + } + } + +#if defined(LWS_WITH_CUSTOM_HEADERS) + else + + /* has to have a non-empty header string */ + + if (polmd->value && ((uint8_t *)polmd->value)[0]) { + char *p; + + /* + * Can it be a custom header? + */ + + n = lws_hdr_custom_length(wsi, + (const char *)polmd->value, + polmd->value_length); + if (n > 0) { + + p = lws_malloc(n + 1, __func__); + if (!p) + return 1; + + /* if needed, free any previous value */ + + if (polmd->value_on_lws_heap) { + lws_free(polmd->value); + polmd->value_on_lws_heap = 0; + } + + /* + * copy the named custom header value into the + * malloc'd buffer + */ + + if (lws_hdr_custom_copy(wsi, p, n + 1, + (const char *)polmd->value, + polmd->value_length) < 0) { + lws_free(p); + + return 1; + } + + omd = lws_ss_get_handle_metadata(h, + polmd->name); + +#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) + omd->pending_onward = 1; +#endif + omd->value = p; + omd->length = (size_t)n; + omd->value_on_lws_heap = 1; + } + } +#endif + + m++; + polmd = polmd->next; + } + + return 0; +} + static const uint8_t blob_idx[] = { LWS_SYSBLOB_TYPE_AUTH, LWS_SYSBLOB_TYPE_DEVICE_SERIAL, @@ -295,6 +398,12 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, h->u.http.good_respcode = (status >= 200 && status < 300); // lwsl_err("%s: good resp %d %d\n", __func__, status, h->u.http.good_respcode); + if (lws_extract_metadata(h, wsi)) { + lwsl_info("%s: rx metadata extract failed\n", __func__); + + return -1; + } + if (h->u.http.good_respcode) lwsl_info("%s: Connected streamtype %s, %d\n", __func__, h->policy->streamtype, status); @@ -747,6 +856,9 @@ secstream_connect_munge_h1(lws_ss_handle_t *h, char *buf, size_t len, if (!pbasis) return 0; + /* uncomment to force h1 */ + // i->alpn = "http/1.1"; + #if defined(LWS_WITH_SS_RIDESHARE) if (h->policy->flags & LWSSSPOLF_HTTP_MULTIPART) i->ssl_connection |= LCCSCF_HTTP_MULTIPART_MIME; diff --git a/lib/secure-streams/secure-streams-client.c b/lib/secure-streams/secure-streams-client.c index fd1c1962c..7f612a1c2 100644 --- a/lib/secure-streams/secure-streams-client.c +++ b/lib/secure-streams/secure-streams-client.c @@ -302,8 +302,6 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, case LPCSCLI_OPERATIONAL: - lwsl_notice("%s: LPCSCLI_OPERATIONAL\n", __func__); - /* * * - Do we need to prioritize sending any metadata @@ -486,6 +484,19 @@ lws_sspc_destroy_dll(struct lws_dll2 *d, void *user) return 0; } +void +lws_sspc_rxmetadata_destroy(lws_sspc_handle_t *h) +{ + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, + lws_dll2_get_head(&h->metadata_owner_rx)) { + lws_sspc_metadata_t *md = + lws_container_of(d, lws_sspc_metadata_t, list); + + lws_dll2_remove(&md->list); + lws_free(md); + + } lws_end_foreach_dll_safe(d, d1); +} void lws_sspc_destroy(lws_sspc_handle_t **ph) @@ -530,6 +541,8 @@ lws_sspc_destroy(lws_sspc_handle_t **ph) } lws_end_foreach_dll_safe(d, d1); + lws_sspc_rxmetadata_destroy(h); + h->ssi.state(m, NULL, LWSSSCS_DESTROYING, 0); *ph = NULL; free(h); @@ -726,6 +739,36 @@ lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, return _lws_sspc_set_metadata(h, name, value, len, 0); } +int +lws_sspc_get_metadata(struct lws_sspc_handle *h, const char *name, + const void **value, size_t *len) +{ + lws_sspc_metadata_t *md; + + /* + * client side does not have access to policy + * and any metadata are new to it each time, + * we allocate them, removing any existing with + * the same name first + */ + + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, + lws_dll2_get_head(&h->metadata_owner_rx)) { + md = lws_container_of(d, + lws_sspc_metadata_t, list); + + if (!strcmp(md->name, name)) { + *len = md->len; + *value = &md[1]; + + return 0; + } + + } lws_end_foreach_dll_safe(d, d1); + + return 1; +} + int lws_sspc_add_peer_tx_credit(struct lws_sspc_handle *h, int32_t bump) { diff --git a/lib/secure-streams/secure-streams-process.c b/lib/secure-streams/secure-streams-process.c index 0402a8d27..920c55aa3 100644 --- a/lib/secure-streams/secure-streams-process.c +++ b/lib/secure-streams/secure-streams-process.c @@ -231,12 +231,13 @@ callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason, struct raw_pss *pss = (struct raw_pss *)user; const lws_ss_policy_t *rsp; struct conn *conn = NULL; + lws_ss_metadata_t *md; lws_ss_info_t ssi; const uint8_t *cp; #if defined(LWS_WITH_DETAILED_LATENCY) lws_usec_t us; #endif - char s[128]; + char s[256]; uint8_t *p; size_t si; char pay; @@ -430,6 +431,48 @@ callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason, lws_set_timeout(wsi, 0, 0); break; case LPCSPROX_OPERATIONAL: + + /* + * rx metadata has priority + */ + + md = conn->ss->metadata; + while (md) { + // lwsl_notice("%s: check %s: %d\n", __func__, + // md->name, md->pending_onward); + if (md->pending_onward) { + size_t naml = strlen(md->name); + + // lwsl_notice("%s: proxy issuing rxmd\n", __func__); + + if (4 + naml + md->length > sizeof(s)) { + lwsl_err("%s: rxmdata too big\n", + __func__); + goto hangup; + } + md->pending_onward = 0; + p = (uint8_t *)s; + p[0] = LWSSS_SER_RXPRE_METADATA; + lws_ser_wu16be(&p[1], 1 + naml + + md->length); + p[3] = (uint8_t)naml; + memcpy(&p[4], md->name, naml); + p += 4 + naml; + memcpy(p, md->value, md->length); + p += md->length; + + n = lws_ptr_diff(p, cp); + goto again; + } + + md = md->next; + } + + /* + * if no fresh rx metadata, just pass through incoming + * dsh + */ + if (lws_dsh_get_head(conn->dsh, KIND_SS_TO_P, (void **)&p, &si)) break; @@ -511,10 +554,8 @@ again: return lws_callback_http_dummy(wsi, reason, user, in, len); hangup: - //lws_ss_destroy(&conn->ss); - //conn->state = LPCSPROX_DESTROYED; - /* hang up on him */ + return -1; } diff --git a/lib/secure-streams/secure-streams-serialize.c b/lib/secure-streams/secure-streams-serialize.c index 0e0e03a1c..1a69dcfc8 100644 --- a/lib/secure-streams/secure-streams-serialize.c +++ b/lib/secure-streams/secure-streams-serialize.c @@ -487,6 +487,15 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, par->ps = RPAR_STATEINDEX; break; + case LWSSS_SER_RXPRE_METADATA: + if (!client) + goto hangup; + if (par->rem < 3) + goto hangup; + par->ctr = 0; + par->ps = RPAR_METADATA_NAMELEN; + break; + case LWSSS_SER_RXPRE_TXCR_UPDATE: par->ctr = 0; par->ps = RPAR_RX_TXCR_UPDATE; @@ -870,6 +879,7 @@ payload_ff: break; case RPAR_METADATA_NAMELEN: + /* both client and proxy */ if (!--par->rem) goto hangup; par->slen = *cp++; @@ -880,6 +890,7 @@ payload_ff: break; case RPAR_METADATA_NAME: + /* both client and proxy */ if (!--par->rem) goto hangup; par->metadata_name[par->ctr++] = *cp++; @@ -888,7 +899,62 @@ payload_ff: par->metadata_name[par->ctr] = '\0'; par->ps = RPAR_METADATA_VALUE; - /* only proxy side can receive these */ + if (client) { + lws_sspc_metadata_t *md; + lws_sspc_handle_t *h = + client_pss_to_sspc_h(pss, ssi); + + /* + * client side does not have access to policy + * and any metadata are new to it each time, + * we allocate them, removing any existing with + * the same name first + */ + + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, + lws_dll2_get_head( + &h->metadata_owner_rx)) { + md = lws_container_of(d, + lws_sspc_metadata_t, list); + + if (!strcmp(md->name, + par->metadata_name)) { + lws_dll2_remove(&md->list); + lws_free(md); + } + + } lws_end_foreach_dll_safe(d, d1); + + /* + * Create the client's rx metadata entry + */ + + md = lws_malloc(sizeof(lws_sspc_metadata_t) + + par->rem + 1, "rxmeta"); + if (!md) { + lwsl_err("%s: OOM\n", __func__); + goto hangup; + } + memset(md, 0, sizeof(lws_sspc_metadata_t)); + + lws_strncpy(md->name, par->metadata_name, + sizeof(md->name)); + md->len = par->rem; + par->rxmetaval = (uint8_t *)&md[1]; + /* + * Overallocate by 1 and put a NUL just beyond + * the official md->len, so value can be easily + * dereferenced safely for NUL-terminated string + * apis that's the most common usage + */ + par->rxmetaval[md->len] = '\0'; + lws_dll2_add_tail(&md->list, + &h->metadata_owner_rx); + par->ctr = 0; + break; + } + + /* proxy side is receiving it */ if (!proxy_pss_to_ss_h(pss)) goto hangup; @@ -897,8 +963,9 @@ payload_ff: * This is the policy's metadata list for the given * name */ - pm = lws_ss_policy_metadata(proxy_pss_to_ss_h(pss)->policy, - par->metadata_name); + pm = lws_ss_policy_metadata( + proxy_pss_to_ss_h(pss)->policy, + par->metadata_name); if (!pm) { lwsl_err("%s: metadata %s not in proxy policy\n", __func__, par->metadata_name); @@ -906,7 +973,9 @@ payload_ff: goto hangup; } - par->ssmd = &proxy_pss_to_ss_h(pss)->metadata[pm->length]; + par->ssmd = lws_ss_get_handle_metadata( + proxy_pss_to_ss_h(pss), + par->metadata_name); if (par->ssmd->value_on_lws_heap) lws_free_set_NULL(par->ssmd->value); @@ -918,21 +987,33 @@ payload_ff: goto hangup; } par->ssmd->length = par->rem; + ((uint8_t *)par->ssmd->value)[par->rem] = '\0'; /* mark it as needing cleanup */ par->ssmd->value_on_lws_heap = 1; par->ctr = 0; break; case RPAR_METADATA_VALUE: - ((uint8_t *)(par->ssmd->value))[par->ctr++] = *cp++; + /* both client and proxy */ + + if (client) { + *par->rxmetaval++ = *cp++; + } else + ((uint8_t *)(par->ssmd->value))[par->ctr++] = *cp++; + if (--par->rem) break; /* we think we got all the value */ - lwsl_info("%s: RPAR_METADATA_VALUE for %s (len %d)\n", + if (client) + lwsl_notice("%s: RX METADATA %s\n", __func__, + par->metadata_name); + else { + lwsl_info("%s: RPAR_METADATA_VALUE for %s (len %d)\n", __func__, par->ssmd->name, (int)par->ssmd->length); - lwsl_hexdump_info(par->ssmd->value, par->ssmd->length); + lwsl_hexdump_info(par->ssmd->value, par->ssmd->length); + } par->ps = RPAR_TYPE; break; diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 06e1cf96c..7fceb0179 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -142,7 +142,8 @@ lws_ss_exp_cb_metadata(void *priv, const char *name, char *out, size_t *pos, lws_ss_handle_t *h = (lws_ss_handle_t *)priv; const char *replace = NULL; size_t total, budget; - lws_ss_metadata_t *md = lws_ss_policy_metadata(h->policy, name); + lws_ss_metadata_t *md = lws_ss_policy_metadata(h->policy, name), + *hmd = lws_ss_get_handle_metadata(h, name); if (!md) { lwsl_err("%s: Unknown metadata %s\n", __func__, name); @@ -150,10 +151,8 @@ lws_ss_exp_cb_metadata(void *priv, const char *name, char *out, size_t *pos, return LSTRX_FATAL_NAME_UNKNOWN; } - lwsl_info("%s %s %d\n", __func__, name, (int)md->length); - - replace = h->metadata[md->length].value; - total = h->metadata[md->length].length; + replace = hmd->value; + total = hmd->length; // lwsl_hexdump_err(replace, total); budget = olen - *pos; diff --git a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c index f45f4a95a..fa33cfced 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c @@ -181,10 +181,15 @@ int main(int argc, const char **argv) printf("\t.name = \"%s\",\n", (const char *)md->name); if (md->value) - printf("\t.value = (void *)\"%s\",\n", (const char *)md->value); + printf("\t.value = (void *)\"%s\",\n", + (const char *)md->value); printf("\t.length = %d,\n", idx++); // md->length); - + printf("\t.value_length = 0x%x,\n", + (unsigned int)strlen( + (const char *)md->value)); + printf("\t.value_is_http_token = 0x%x,\n", + (unsigned int)md->value_is_http_token); printf("}"); if (md->next) printf(",\n"); diff --git a/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/minimal-secure-streams.c index 3febea07a..efdbf7749 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/minimal-secure-streams.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/minimal-secure-streams.c @@ -1,5 +1,5 @@ /* - * lws-minimal-secure-streams + * lws-minimal-secure-streams-staticpolicy * * Written in 2010-2020 by Andy Green * @@ -276,7 +276,7 @@ int main(int argc, const char **argv) lws_system_blob_heap_append(lws_system_get_blob(context, LWS_SYSBLOB_TYPE_DEVICE_TYPE, 0), - (const uint8_t *)"spacerocket", 11); + (const uint8_t *)"spacerocket", 11); /* the event loop */ diff --git a/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c index 4a79881e1..262097530 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c +++ b/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c @@ -230,9 +230,16 @@ static const char *canned_root_token_payload = static int myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) { -// myss_t *m = (myss_t *)userobj; + myss_t *m = (myss_t *)userobj; + const char *md_srv = NULL, *md_test = NULL; + size_t md_len; - lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); + lws_ss_get_metadata(m->ss, "srv", (const void **)&md_srv, &md_len); + lws_ss_get_metadata(m->ss, "test", (const void **)&md_test, &md_len); + + lwsl_user("%s: len %d, flags: %d, srv: %s, test: %s\n", __func__, + (int)len, flags, md_srv ? md_srv : "not set", + md_test ? md_test : "not set"); lwsl_hexdump_info(buf, len); /*