diff --git a/include/libwebsockets/lws-secure-streams.h b/include/libwebsockets/lws-secure-streams.h index f52ff1a7d..d00cc00f3 100644 --- a/include/libwebsockets/lws-secure-streams.h +++ b/include/libwebsockets/lws-secure-streams.h @@ -629,6 +629,22 @@ LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, const void *value, size_t len); +/** + * lws_ss_alloc_set_metadata() - copy data and bind to ss metadata + * + * \param h: secure streams handle + * \param name: metadata name from the policy + * \param value: pointer to user-managed data to bind to name + * \param len: length of the user-managed data in value + * + * Same as lws_ss_set_metadata(), but allocates a heap buffer for the data + * first and takes a copy of it, so the original can go out of scope + * immediately after. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_ss_alloc_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 * diff --git a/lib/secure-streams/policy-common.c b/lib/secure-streams/policy-common.c index 18c05ddab..9899b41d7 100644 --- a/lib/secure-streams/policy-common.c +++ b/lib/secure-streams/policy-common.c @@ -93,6 +93,49 @@ lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, return _lws_ss_set_metadata(omd, name, value, len); } +int +_lws_ss_alloc_set_metadata(lws_ss_metadata_t *omd, const char *name, + const void *value, size_t len) +{ + uint8_t *p; + int n; + + if (omd->value_on_lws_heap) { + lws_free_set_NULL(omd->value__may_own_heap); + omd->value_on_lws_heap = 0; + } + + p = lws_malloc(len, __func__); + if (!p) + return 1; + + n = _lws_ss_set_metadata(omd, name, p, len); + if (n) { + lws_free(p); + return n; + } + + memcpy(p, value, len); + + omd->value_on_lws_heap = 1; + + return 0; +} + +int +lws_ss_alloc_set_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; + } + + return _lws_ss_alloc_set_metadata(omd, name, value, len); +} + int lws_ss_get_metadata(struct lws_ss_handle *h, const char *name, const void **value, size_t *len) diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index b386776de..7fe4ff055 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -468,6 +468,10 @@ int _lws_ss_set_metadata(lws_ss_metadata_t *omd, const char *name, const void *value, size_t len); +int +_lws_ss_alloc_set_metadata(lws_ss_metadata_t *omd, const char *name, + const void *value, size_t len); + lws_ss_state_return_t _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry, void *conn_if_sspc_onw); diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index d2dd267ef..339c902a3 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -303,7 +303,8 @@ lws_extract_metadata(lws_ss_handle_t *h, struct lws *wsi) * set the related metadata name to it then */ - _lws_ss_set_metadata(omd, polmd->name, cp, (unsigned int)n); + _lws_ss_alloc_set_metadata(omd, polmd->name, cp, + (unsigned int)n); #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) /* @@ -363,8 +364,8 @@ lws_extract_metadata(lws_ss_handle_t *h, struct lws *wsi) omd = lws_ss_get_handle_metadata(h, polmd->name); - _lws_ss_set_metadata(omd, polmd->name, - p, (size_t)n); + _lws_ss_set_metadata(omd, + polmd->name, p, (size_t)n); omd->value_on_lws_heap = 1; #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) @@ -962,12 +963,12 @@ malformed: #if defined(LWS_ROLE_H2) m = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_METHOD); if (m) { - if (lws_ss_set_metadata(h, "method", + if (lws_ss_alloc_set_metadata(h, "method", lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD), (unsigned int)m)) return -1; m = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH); - if (lws_ss_set_metadata(h, "path", + if (lws_ss_alloc_set_metadata(h, "path", lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_PATH), (unsigned int)m)) return -1; @@ -976,20 +977,20 @@ malformed: { m = lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI); if (m) { - if (lws_ss_set_metadata(h, "path", + if (lws_ss_alloc_set_metadata(h, "path", lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI), (unsigned int)m)) return -1; - if (lws_ss_set_metadata(h, "method", "GET", 3)) + if (lws_ss_alloc_set_metadata(h, "method", "GET", 3)) return -1; } else { m = lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI); if (m) { - if (lws_ss_set_metadata(h, "path", + if (lws_ss_alloc_set_metadata(h, "path", lws_hdr_simple_ptr(wsi, WSI_TOKEN_POST_URI), (unsigned int)m)) return -1; - if (lws_ss_set_metadata(h, "method", "POST", 4)) + if (lws_ss_alloc_set_metadata(h, "method", "POST", 4)) return -1; } } diff --git a/minimal-examples/secure-streams/minimal-secure-streams-sigv4/ss-s3-ss.c b/minimal-examples/secure-streams/minimal-secure-streams-sigv4/ss-s3-ss.c index c1f4692e4..a9cce26df 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-sigv4/ss-s3-ss.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-sigv4/ss-s3-ss.c @@ -146,34 +146,32 @@ ss_s3_state(void *userobj, void *sh, lws_ss_constate_t state, switch (state) { case LWSSSCS_CREATING: - lws_ss_set_metadata(m->ss, "s3bucket", - s3bucketName, strlen(s3bucketName)); - lws_ss_set_metadata(m->ss, "s3Obj", - s3ObjName, strlen(s3ObjName)); - lws_ss_set_metadata(m->ss, "ctype", - "text/plain", strlen("text/plain")); create_payload(jpl, sizeof(jpl)); m->buf = (uint8_t *)jpl; m->total = sizeof(jpl); - lws_ss_set_metadata(m->ss, "region", - awsRegion, strlen(awsRegion)); - lws_ss_set_metadata(m->ss, "service", - awsService, strlen(awsService)); - - lws_ss_set_metadata(m->ss, "xacl", - "bucket-owner-full-control", - strlen("bucket-owner-full-control")); - sigv4_sha256hash_payload(m->buf, m->total, payload_hash); - - lws_ss_set_metadata(m->ss, "xcsha256", - payload_hash, strlen(payload_hash)); - memset(timestamp, 0, sizeof(timestamp)); set_time(timestamp); - lws_ss_set_metadata(m->ss, "xdate", - timestamp, strlen(timestamp)); + + if (lws_ss_set_metadata(m->ss, "s3bucket", + s3bucketName, strlen(s3bucketName)) || + lws_ss_set_metadata(m->ss, "s3Obj", + s3ObjName, strlen(s3ObjName)) || + lws_ss_set_metadata(m->ss, "ctype", + "text/plain", strlen("text/plain")) || + lws_ss_set_metadata(m->ss, "region", + awsRegion, strlen(awsRegion)) || + lws_ss_set_metadata(m->ss, "service", + awsService, strlen(awsService)) || + lws_ss_set_metadata(m->ss, "xacl", + "bucket-owner-full-control", + strlen("bucket-owner-full-control")) || + lws_ss_set_metadata(m->ss, "xcsha256", + payload_hash, strlen(payload_hash)) || + lws_ss_set_metadata(m->ss, "xdate", + timestamp, strlen(timestamp))) + return LWSSSSRET_DESTROY_ME; lws_ss_request_tx_len(m->ss, m->total); break;