From: Michael R Sweet Date: Thu, 1 May 2025 18:27:38 +0000 (-0400) Subject: Cookie handling support: X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e8252e6117af500b18d5edf8ba1caee7bd64af51;p=thirdparty%2Fcups.git Cookie handling support: - Add httpGetCookieValue API. - Increase CGI cookie value size limit to 2k. --- diff --git a/CHANGES.md b/CHANGES.md index cc60b6b9be..cc21aaa9db 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,9 +7,8 @@ Changes in CUPS v2.5b1 (YYYY-MM-DD) - Added multiple language support for IPP Everywhere. - Added `cupsConcatString`, `cupsCopyString`, and `cupsFormatString` string APIs. -- Added new `cupsRasterInitHeader` API. -- Added `httpConnectURI` API. -- Added `httpGetSecurity` API. +- Added `cupsRasterInitHeader` API. +- Added `httpConnectURI`, `httpGetCookieValue`, and `httpGetSecurity` APIs. - Added `ippAddCredentialsString`, `ippGetFirstAttribute`, `ippGetNextAttribute`, `ippRestore`, and `ippSave` APIs. - Added new DNS-SD APIs. @@ -33,8 +32,8 @@ Changes in CUPS v2.5b1 (YYYY-MM-DD) - Added a systemd slice to the systemd services included with the scheduler - Added localizations for deprecated IPP attributes/options (Issue #1020) - Added support for specifying permissions with the `cupsFileOpen` API. -- Added new `cupsGetClock` API. -- Added new `cupsParseOptions2` API with "end" argument. +- Added `cupsGetClock` API. +- Added `cupsParseOptions2` API with "end" argument. - Added `cups-oauth` and `cups-x509` utilities (Issue #1184) - Added `DNSSDComputerName` directive to "cupsd.conf" and updated cupsd to correctly update the mDNS hostname only if the `DNSSDHostName` directive is diff --git a/cgi-bin/var.c b/cgi-bin/var.c index 8bb70513ee..ff13e9f719 100644 --- a/cgi-bin/var.c +++ b/cgi-bin/var.c @@ -708,7 +708,7 @@ cgi_initialize_cookies(void) { const char *cookie; /* HTTP_COOKIE environment variable */ char name[128], /* Name string */ - value[512], /* Value string */ + value[2048], /* Value string */ *ptr; /* Pointer into name/value */ @@ -733,6 +733,7 @@ cgi_initialize_cookies(void) */ for (ptr = name; *cookie && *cookie != '=';) + { if (ptr < (name + sizeof(name) - 1)) { *ptr++ = *cookie++; @@ -742,6 +743,7 @@ cgi_initialize_cookies(void) skip = 1; cookie ++; } + } if (*cookie != '=') break; @@ -756,6 +758,7 @@ cgi_initialize_cookies(void) if (*cookie == '\"') { for (cookie ++, ptr = value; *cookie && *cookie != '\"';) + { if (ptr < (value + sizeof(value) - 1)) { *ptr++ = *cookie++; @@ -765,6 +768,7 @@ cgi_initialize_cookies(void) skip = 1; cookie ++; } + } if (*cookie == '\"') cookie ++; @@ -774,6 +778,7 @@ cgi_initialize_cookies(void) else { for (ptr = value; *cookie && *cookie != ';';) + { if (ptr < (value + sizeof(value) - 1)) { *ptr++ = *cookie++; @@ -783,6 +788,7 @@ cgi_initialize_cookies(void) skip = 1; cookie ++; } + } } if (*cookie == ';') diff --git a/cups/http.c b/cups/http.c index e16c9ac01a..71cb1d97b8 100644 --- a/cups/http.c +++ b/cups/http.c @@ -1030,7 +1030,11 @@ httpGetContentEncoding(http_t *http) // I - HTTP connection // -// 'httpGetCookie()' - Get any cookie data from the response. +// 'httpGetCookie()' - Get "Cookie:" data from the HTTP connection. +// +// This function returns any HTTP "Cookie:" header data for the given HTTP +// connection as described in RFC 6265. Use the @link httpGetCookieValue@ to +// get the value of a named cookie. // // @since CUPS 1.1.19@ // @@ -1042,6 +1046,107 @@ httpGetCookie(http_t *http) // I - HTTP connection } +// +// 'httpGetCookieValue()' - Get the value of a named cookie from the HTTP connection. +// +// This function copies the value of a named cookie in the HTTP "Cookie:" header +// for the given HTTP connection as described in RFC 6265. Use the +// @link httpGetCookie@ function to get the original "Cookie:" string. +// +// @since CUPS 2.5@ +// + +char * // O - Cookie value or `NULL` if not present +httpGetCookieValue(http_t *http, // I - HTTP connection + const char *name, // I - Cookie name + char *buffer, // I - Value buffer + size_t bufsize) // I - Size of value buffer +{ + const char *cookie; // Cookie: header value + char current[128], // Current name string + *ptr, // Pointer into name/buffer + *end; // End of name/buffer + bool match; // Does the current name match? + + + // Range check input... + if (buffer) + *buffer = '\0'; + + if (!http || !http->cookie || !name || !buffer || bufsize < 2) + return (NULL); + + // Loop through the cookie string... + for (cookie = http->cookie; *cookie;) + { + // Skip leading whitespace... + while (isspace(*cookie & 255)) + cookie ++; + if (!*cookie) + break; + + // Copy the name... + for (ptr = current, end = current + sizeof(current) - 1; *cookie && *cookie != '=';) + { + if (ptr < end) + *ptr++ = *cookie++; + else + cookie ++; + } + + if (*cookie != '=') + break; + + *ptr = '\0'; + match = !strcmp(current, name); + cookie ++; + + // Then the value... + if (*cookie == '\"') + { + // Copy quoted value... + for (cookie ++, ptr = buffer, end = buffer + bufsize - 1; *cookie && *cookie != '\"';) + { + if (match && ptr < end) + *ptr++ = *cookie++; + else + cookie ++; + } + + if (*cookie == '\"') + cookie ++; + else + match = false; + } + else + { + // Copy unquoted value... + for (ptr = buffer, end = buffer + bufsize - 1; *cookie && *cookie != ';';) + { + if (match && ptr < end) + *ptr++ = *cookie++; + else + cookie ++; + } + } + + if (match) + { + // Got the value we were looking for, nul-terminate and return... + *ptr = '\0'; + return (buffer); + } + + // Skip over separator... + if (*cookie == ';') + cookie ++; + } + + // If we get here then we never found the cookie... + return (NULL); +} + + // // 'httpGetEncryption()' - Get the current encryption mode of a connection. // diff --git a/cups/http.h b/cups/http.h index d8aa2e7e5c..bb6815608d 100644 --- a/cups/http.h +++ b/cups/http.h @@ -438,6 +438,7 @@ extern char *httpGetAuthString(http_t *http) _CUPS_PUBLIC; extern int httpGetBlocking(http_t *http) _CUPS_PUBLIC; extern const char *httpGetContentEncoding(http_t *http) _CUPS_PUBLIC; extern const char *httpGetCookie(http_t *http) _CUPS_PUBLIC; +extern char *httpGetCookieValue(http_t *http, const char *name, char *buffer, size_t bufsize) _CUPS_PUBLIC; extern const char *httpGetDateString(time_t t) _CUPS_PUBLIC; extern const char *httpGetDateString2(time_t t, char *s, int slen) _CUPS_PUBLIC; extern time_t httpGetDateTime(const char *s) _CUPS_PUBLIC;