xref: /OK3568_Linux_fs/yocto/poky/meta/recipes-support/curl/curl/CVE-2022-32205.patch (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1From a91c22a072cbb32e296f1efba3502f1b7775dfaf Mon Sep 17 00:00:00 2001
2From: Daniel Stenberg <daniel@haxx.se>
3Date: Sun, 26 Jun 2022 11:00:48 +0200
4Subject: [PATCH] cookie: apply limits
5
6- Send no more than 150 cookies per request
7- Cap the max length used for a cookie: header to 8K
8- Cap the max number of received Set-Cookie: headers to 50
9
10Bug: https://curl.se/docs/CVE-2022-32205.html
11CVE-2022-32205
12Reported-by: Harry Sintonen
13Closes #9048
14
15Upstream-Status: Backport [https://github.com/curl/curl/commit/48d7064a49148f0394]
16Signed-off-by: Robert Joslyn <robert.joslyn@redrectangle.org>
17---
18 lib/cookie.c  | 14 ++++++++++++--
19 lib/cookie.h  | 21 +++++++++++++++++++--
20 lib/http.c    | 13 +++++++++++--
21 lib/urldata.h |  1 +
22 4 files changed, 43 insertions(+), 6 deletions(-)
23
24diff --git a/lib/cookie.c b/lib/cookie.c
25index 1b8c8f9..8a6aa1a 100644
26--- a/lib/cookie.c
27+++ b/lib/cookie.c
28@@ -477,6 +477,10 @@ Curl_cookie_add(struct Curl_easy *data,
29   (void)data;
30 #endif
31
32+  DEBUGASSERT(MAX_SET_COOKIE_AMOUNT <= 255); /* counter is an unsigned char */
33+  if(data->req.setcookies >= MAX_SET_COOKIE_AMOUNT)
34+    return NULL;
35+
36   /* First, alloc and init a new struct for it */
37   co = calloc(1, sizeof(struct Cookie));
38   if(!co)
39@@ -816,7 +820,7 @@ Curl_cookie_add(struct Curl_easy *data,
40       freecookie(co);
41       return NULL;
42     }
43-
44+    data->req.setcookies++;
45   }
46   else {
47     /*
48@@ -1354,7 +1358,8 @@ static struct Cookie *dup_cookie(struct Cookie *src)
49  *
50  * It shall only return cookies that haven't expired.
51  */
52-struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
53+struct Cookie *Curl_cookie_getlist(struct Curl_easy *data,
54+                                   struct CookieInfo *c,
55                                    const char *host, const char *path,
56                                    bool secure)
57 {
58@@ -1409,6 +1414,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
59             mainco = newco;
60
61             matches++;
62+            if(matches >= MAX_COOKIE_SEND_AMOUNT) {
63+              infof(data, "Included max number of cookies (%u) in request!",
64+                    matches);
65+              break;
66+            }
67           }
68           else
69             goto fail;
70diff --git a/lib/cookie.h b/lib/cookie.h
71index 0ffe08e..7411980 100644
72--- a/lib/cookie.h
73+++ b/lib/cookie.h
74@@ -81,10 +81,26 @@ struct CookieInfo {
75 */
76 #define MAX_COOKIE_LINE 5000
77
78-/* This is the maximum length of a cookie name or content we deal with: */
79+/* Maximum length of an incoming cookie name or content we deal with. Longer
80+   cookies are ignored. */
81 #define MAX_NAME 4096
82 #define MAX_NAME_TXT "4095"
83
84+/* Maximum size for an outgoing cookie line libcurl will use in an http
85+   request. This is the default maximum length used in some versions of Apache
86+   httpd. */
87+#define MAX_COOKIE_HEADER_LEN 8190
88+
89+/* Maximum number of cookies libcurl will send in a single request, even if
90+   there might be more cookies that match. One reason to cap the number is to
91+   keep the maximum HTTP request within the maximum allowed size. */
92+#define MAX_COOKIE_SEND_AMOUNT 150
93+
94+/* Maximum number of Set-Cookie: lines accepted in a single response. If more
95+   such header lines are received, they are ignored. This value must be less
96+   than 256 since an unsigned char is used to count. */
97+#define MAX_SET_COOKIE_AMOUNT 50
98+
99 struct Curl_easy;
100 /*
101  * Add a cookie to the internal list of cookies. The domain and path arguments
102@@ -97,7 +113,8 @@ struct Cookie *Curl_cookie_add(struct Curl_easy *data,
103                                const char *domain, const char *path,
104                                bool secure);
105
106-struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, const char *host,
107+struct Cookie *Curl_cookie_getlist(struct Curl_easy *data,
108+                                   struct CookieInfo *c, const char *host,
109                                    const char *path, bool secure);
110 void Curl_cookie_freelist(struct Cookie *cookies);
111 void Curl_cookie_clearall(struct CookieInfo *cookies);
112diff --git a/lib/http.c b/lib/http.c
113index 4433824..2c8b0c4 100644
114--- a/lib/http.c
115+++ b/lib/http.c
116@@ -2709,12 +2709,14 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
117 }
118
119 #if !defined(CURL_DISABLE_COOKIES)
120+
121 CURLcode Curl_http_cookies(struct Curl_easy *data,
122                            struct connectdata *conn,
123                            struct dynbuf *r)
124 {
125   CURLcode result = CURLE_OK;
126   char *addcookies = NULL;
127+  bool linecap = FALSE;
128   if(data->set.str[STRING_COOKIE] &&
129      !Curl_checkheaders(data, STRCONST("Cookie")))
130     addcookies = data->set.str[STRING_COOKIE];
131@@ -2732,7 +2734,7 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
132         !strcmp(host, "127.0.0.1") ||
133         !strcmp(host, "[::1]") ? TRUE : FALSE;
134       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
135-      co = Curl_cookie_getlist(data->cookies, host, data->state.up.path,
136+      co = Curl_cookie_getlist(data, data->cookies, host, data->state.up.path,
137                                secure_context);
138       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
139     }
140@@ -2746,6 +2748,13 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
141             if(result)
142               break;
143           }
144+          if((Curl_dyn_len(r) + strlen(co->name) + strlen(co->value) + 1) >=
145+             MAX_COOKIE_HEADER_LEN) {
146+            infof(data, "Restricted outgoing cookies due to header size, "
147+                  "'%s' not sent", co->name);
148+            linecap = TRUE;
149+            break;
150+          }
151           result = Curl_dyn_addf(r, "%s%s=%s", count?"; ":"",
152                                  co->name, co->value);
153           if(result)
154@@ -2756,7 +2765,7 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
155       }
156       Curl_cookie_freelist(store);
157     }
158-    if(addcookies && !result) {
159+    if(addcookies && !result && !linecap) {
160       if(!count)
161         result = Curl_dyn_addn(r, STRCONST("Cookie: "));
162       if(!result) {
163diff --git a/lib/urldata.h b/lib/urldata.h
164index e006495..54faf7d 100644
165--- a/lib/urldata.h
166+++ b/lib/urldata.h
167@@ -707,6 +707,7 @@ struct SingleRequest {
168 #ifndef CURL_DISABLE_DOH
169   struct dohdata *doh; /* DoH specific data for this request */
170 #endif
171+  unsigned char setcookies;
172   BIT(header);        /* incoming data has HTTP header */
173   BIT(content_range); /* set TRUE if Content-Range: was found */
174   BIT(upload_done);   /* set to TRUE when doing chunked transfer-encoding
175