diff --git a/include/libwebsockets/lws-http.h b/include/libwebsockets/lws-http.h index d5851101a..b228497fd 100644 --- a/include/libwebsockets/lws-http.h +++ b/include/libwebsockets/lws-http.h @@ -850,6 +850,26 @@ lws_http_compression_apply(struct lws *wsi, const char *name, LWS_VISIBLE LWS_EXTERN int lws_http_is_redirected_to_get(struct lws *wsi); +/** + * lws_http_cookie_get() - return copy of named cookie if present + * + * \param wsi: the wsi to check + * \param name: name of the cookie + * \param buf: buffer to store the cookie contents into + * \param max_len: on entry, maximum length of buf... on exit, used len of buf + * + * If no cookie header, or no cookie of the requested name, or the value is + * larger than can fit in buf, returns nonzero. + * + * If the cookie is found, copies its value into buf with a terminating NUL, + * sets *max_len to the used length, and returns 0. + * + * This handles the parsing of the possibly multi-cookie header string and + * terminating the requested cookie at the next ; if present. + */ +LWS_VISIBLE LWS_EXTERN int +lws_http_cookie_get(struct lws *wsi, const char *name, char *buf, size_t *max); + /** * lws_http_client_http_error() - determine if the response code indicates an error * diff --git a/lib/core-net/dummy-callback.c b/lib/core-net/dummy-callback.c index 713b96bba..c28267128 100644 --- a/lib/core-net/dummy-callback.c +++ b/lib/core-net/dummy-callback.c @@ -24,6 +24,9 @@ #include "private-lib-core.h" +/* max individual proxied header payload size */ +#define MAXHDRVAL 1024 + #if defined(LWS_WITH_HTTP_PROXY) static int proxy_header(struct lws *wsi, struct lws *par, unsigned char *temp, @@ -33,16 +36,23 @@ proxy_header(struct lws *wsi, struct lws *par, unsigned char *temp, if (n < 1) { lwsl_debug("%s: no index %d:\n", __func__, index); + return 0; } - if (lws_hdr_copy(par, (char *)temp, temp_len, index) < 0) + if (lws_hdr_copy(par, (char *)temp, temp_len, index) < 0) { + lwsl_notice("%s: unable to copy par hdr idx %d (len %d)\n", + __func__, index, n); return -1; + } lwsl_debug("%s: index %d: %s\n", __func__, index, (char *)temp); - if (lws_add_http_header_by_token(wsi, index, temp, n, p, end)) + if (lws_add_http_header_by_token(wsi, index, temp, n, p, end)) { + lwsl_notice("%s: unable to append par hdr idx %d (len %d)\n", + __func__, index, n); return -1; + } return 0; } @@ -133,7 +143,7 @@ lws_callback_ws_proxy(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER: { unsigned char **p = (unsigned char **)in, *end = (*p) + len, - tmp[128]; + tmp[MAXHDRVAL]; proxy_header(wsi, wsi->parent, tmp, sizeof(tmp), WSI_TOKEN_HTTP_ACCEPT_LANGUAGE, p, end); @@ -250,6 +260,7 @@ const struct lws_protocols lws_ws_proxy = { #endif + int lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) @@ -482,7 +493,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, return 0; start = p = (unsigned char *)buf + LWS_PRE; - end = p + sizeof(buf) - LWS_PRE - 256; + end = p + sizeof(buf) - LWS_PRE - MAXHDRVAL; if (lws_add_http_header_status(lws_get_parent(wsi), lws_http_client_http_response(wsi), &p, end)) @@ -492,21 +503,21 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, * copy these headers from the client connection to the parent */ - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_CONTENT_LENGTH, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_CONTENT_TYPE, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_ETAG, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_ACCEPT_LANGUAGE, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_CONTENT_ENCODING, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_CACHE_CONTROL, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_SET_COOKIE, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_LOCATION, &p, end); if (!parent->mux_substream) diff --git a/lib/roles/http/parsers.c b/lib/roles/http/parsers.c index b74669b17..1382e97e4 100644 --- a/lib/roles/http/parsers.c +++ b/lib/roles/http/parsers.c @@ -1459,3 +1459,41 @@ forbid: return LPR_FORBIDDEN; } +int +lws_http_cookie_get(struct lws *wsi, const char *name, char *buf, + size_t *max_len) +{ + int n, bl = (int)strlen(name); + size_t max = *max_len; + char *p, *bo = buf; + + n = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE); + if (n < bl + 1) + return 1; + + p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COOKIE); + if (!p) + return 1; + + p += bl; + n -= bl; + while (n-- > bl) { + if (*p == '=' && !memcmp(p - bl, name, bl)) { + p++; + while (*p != ';' && n-- && max) { + *buf++ = *p++; + max--; + } + if (!max) + return 2; + + *buf = '\0'; + *max_len = lws_ptr_diff(buf, bo); + + return 0; + } + p++; + } + + return 1; +}