diff options
Diffstat (limited to 'meta/recipes-support/curl/curl/CVE-2023-27535-pre1.patch')
-rw-r--r-- | meta/recipes-support/curl/curl/CVE-2023-27535-pre1.patch | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/meta/recipes-support/curl/curl/CVE-2023-27535-pre1.patch b/meta/recipes-support/curl/curl/CVE-2023-27535-pre1.patch new file mode 100644 index 0000000000..034b72f7e6 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-27535-pre1.patch | |||
@@ -0,0 +1,236 @@ | |||
1 | From ed5095ed94281989e103c72e032200b83be37878 Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Stenberg <daniel@haxx.se> | ||
3 | Date: Thu, 6 Oct 2022 00:49:10 +0200 | ||
4 | Subject: [PATCH] strcase: add and use Curl_timestrcmp | ||
5 | |||
6 | This is a strcmp() alternative function for comparing "secrets", | ||
7 | designed to take the same time no matter the content to not leak | ||
8 | match/non-match info to observers based on how fast it is. | ||
9 | |||
10 | The time this function takes is only a function of the shortest input | ||
11 | string. | ||
12 | |||
13 | Reported-by: Trail of Bits | ||
14 | |||
15 | Closes #9658 | ||
16 | |||
17 | Upstream-Status: Backport from [https://github.com/curl/curl/commit/ed5095ed94281989e103c72e032200b83be37878 & https://github.com/curl/curl/commit/f18af4f874cecab82a9797e8c7541e0990c7a64c] | ||
18 | Comment: to backport fix for CVE-2023-27535, add function Curl_timestrcmp. | ||
19 | Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> | ||
20 | --- | ||
21 | lib/netrc.c | 6 +++--- | ||
22 | lib/strcase.c | 22 ++++++++++++++++++++++ | ||
23 | lib/strcase.h | 1 + | ||
24 | lib/url.c | 33 +++++++++++++-------------------- | ||
25 | lib/vauth/digest_sspi.c | 4 ++-- | ||
26 | lib/vtls/vtls.c | 21 ++++++++++++++++++++- | ||
27 | 6 files changed, 61 insertions(+), 26 deletions(-) | ||
28 | |||
29 | diff --git a/lib/netrc.c b/lib/netrc.c | ||
30 | index 9323913..fe3fd1e 100644 | ||
31 | --- a/lib/netrc.c | ||
32 | +++ b/lib/netrc.c | ||
33 | @@ -124,9 +124,9 @@ static int parsenetrc(const char *host, | ||
34 | /* we are now parsing sub-keywords concerning "our" host */ | ||
35 | if(state_login) { | ||
36 | if(specific_login) { | ||
37 | - state_our_login = strcasecompare(login, tok); | ||
38 | + state_our_login = !Curl_timestrcmp(login, tok); | ||
39 | } | ||
40 | - else if(!login || strcmp(login, tok)) { | ||
41 | + else if(!login || Curl_timestrcmp(login, tok)) { | ||
42 | if(login_alloc) { | ||
43 | free(login); | ||
44 | login_alloc = FALSE; | ||
45 | @@ -142,7 +142,7 @@ static int parsenetrc(const char *host, | ||
46 | } | ||
47 | else if(state_password) { | ||
48 | if((state_our_login || !specific_login) | ||
49 | - && (!password || strcmp(password, tok))) { | ||
50 | + && (!password || Curl_timestrcmp(password, tok))) { | ||
51 | if(password_alloc) { | ||
52 | free(password); | ||
53 | password_alloc = FALSE; | ||
54 | diff --git a/lib/strcase.c b/lib/strcase.c | ||
55 | index 70bf21c..ec776b3 100644 | ||
56 | --- a/lib/strcase.c | ||
57 | +++ b/lib/strcase.c | ||
58 | @@ -261,6 +261,28 @@ bool Curl_safecmp(char *a, char *b) | ||
59 | return !a && !b; | ||
60 | } | ||
61 | |||
62 | +/* | ||
63 | + * Curl_timestrcmp() returns 0 if the two strings are identical. The time this | ||
64 | + * function spends is a function of the shortest string, not of the contents. | ||
65 | + */ | ||
66 | +int Curl_timestrcmp(const char *a, const char *b) | ||
67 | +{ | ||
68 | + int match = 0; | ||
69 | + int i = 0; | ||
70 | + | ||
71 | + if(a && b) { | ||
72 | + while(1) { | ||
73 | + match |= a[i]^b[i]; | ||
74 | + if(!a[i] || !b[i]) | ||
75 | + break; | ||
76 | + i++; | ||
77 | + } | ||
78 | + } | ||
79 | + else | ||
80 | + return a || b; | ||
81 | + return match; | ||
82 | +} | ||
83 | + | ||
84 | /* --- public functions --- */ | ||
85 | |||
86 | int curl_strequal(const char *first, const char *second) | ||
87 | diff --git a/lib/strcase.h b/lib/strcase.h | ||
88 | index 8929a53..8077108 100644 | ||
89 | --- a/lib/strcase.h | ||
90 | +++ b/lib/strcase.h | ||
91 | @@ -49,5 +49,6 @@ void Curl_strntoupper(char *dest, const char *src, size_t n); | ||
92 | void Curl_strntolower(char *dest, const char *src, size_t n); | ||
93 | |||
94 | bool Curl_safecmp(char *a, char *b); | ||
95 | +int Curl_timestrcmp(const char *first, const char *second); | ||
96 | |||
97 | #endif /* HEADER_CURL_STRCASE_H */ | ||
98 | diff --git a/lib/url.c b/lib/url.c | ||
99 | index 9f14a7b..dfbde3b 100644 | ||
100 | --- a/lib/url.c | ||
101 | +++ b/lib/url.c | ||
102 | @@ -886,19 +886,10 @@ socks_proxy_info_matches(const struct proxy_info* data, | ||
103 | /* the user information is case-sensitive | ||
104 | or at least it is not defined as case-insensitive | ||
105 | see https://tools.ietf.org/html/rfc3986#section-3.2.1 */ | ||
106 | - if((data->user == NULL) != (needle->user == NULL)) | ||
107 | - return FALSE; | ||
108 | - /* curl_strequal does a case insentive comparison, so do not use it here! */ | ||
109 | - if(data->user && | ||
110 | - needle->user && | ||
111 | - strcmp(data->user, needle->user) != 0) | ||
112 | - return FALSE; | ||
113 | - if((data->passwd == NULL) != (needle->passwd == NULL)) | ||
114 | - return FALSE; | ||
115 | + | ||
116 | /* curl_strequal does a case insentive comparison, so do not use it here! */ | ||
117 | - if(data->passwd && | ||
118 | - needle->passwd && | ||
119 | - strcmp(data->passwd, needle->passwd) != 0) | ||
120 | + if(Curl_timestrcmp(data->user, needle->user) || | ||
121 | + Curl_timestrcmp(data->passwd, needle->passwd)) | ||
122 | return FALSE; | ||
123 | return TRUE; | ||
124 | } | ||
125 | @@ -1257,10 +1248,10 @@ ConnectionExists(struct Curl_easy *data, | ||
126 | if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) { | ||
127 | /* This protocol requires credentials per connection, | ||
128 | so verify that we're using the same name and password as well */ | ||
129 | - if(strcmp(needle->user, check->user) || | ||
130 | - strcmp(needle->passwd, check->passwd) || | ||
131 | - !Curl_safecmp(needle->sasl_authzid, check->sasl_authzid) || | ||
132 | - !Curl_safecmp(needle->oauth_bearer, check->oauth_bearer)) { | ||
133 | + if(Curl_timestrcmp(needle->user, check->user) || | ||
134 | + Curl_timestrcmp(needle->passwd, check->passwd) || | ||
135 | + Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) || | ||
136 | + Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) { | ||
137 | /* one of them was different */ | ||
138 | continue; | ||
139 | } | ||
140 | @@ -1326,8 +1317,8 @@ ConnectionExists(struct Curl_easy *data, | ||
141 | possible. (Especially we must not reuse the same connection if | ||
142 | partway through a handshake!) */ | ||
143 | if(wantNTLMhttp) { | ||
144 | - if(strcmp(needle->user, check->user) || | ||
145 | - strcmp(needle->passwd, check->passwd)) { | ||
146 | + if(Curl_timestrcmp(needle->user, check->user) || | ||
147 | + Curl_timestrcmp(needle->passwd, check->passwd)) { | ||
148 | |||
149 | /* we prefer a credential match, but this is at least a connection | ||
150 | that can be reused and "upgraded" to NTLM */ | ||
151 | @@ -1348,8 +1339,10 @@ ConnectionExists(struct Curl_easy *data, | ||
152 | if(!check->http_proxy.user || !check->http_proxy.passwd) | ||
153 | continue; | ||
154 | |||
155 | - if(strcmp(needle->http_proxy.user, check->http_proxy.user) || | ||
156 | - strcmp(needle->http_proxy.passwd, check->http_proxy.passwd)) | ||
157 | + if(Curl_timestrcmp(needle->http_proxy.user, | ||
158 | + check->http_proxy.user) || | ||
159 | + Curl_timestrcmp(needle->http_proxy.passwd, | ||
160 | + check->http_proxy.passwd)) | ||
161 | continue; | ||
162 | } | ||
163 | else if(check->proxy_ntlm_state != NTLMSTATE_NONE) { | ||
164 | diff --git a/lib/vauth/digest_sspi.c b/lib/vauth/digest_sspi.c | ||
165 | index a109056..3986386 100644 | ||
166 | --- a/lib/vauth/digest_sspi.c | ||
167 | +++ b/lib/vauth/digest_sspi.c | ||
168 | @@ -450,8 +450,8 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, | ||
169 | has changed then delete that context. */ | ||
170 | if((userp && !digest->user) || (!userp && digest->user) || | ||
171 | (passwdp && !digest->passwd) || (!passwdp && digest->passwd) || | ||
172 | - (userp && digest->user && strcmp(userp, digest->user)) || | ||
173 | - (passwdp && digest->passwd && strcmp(passwdp, digest->passwd))) { | ||
174 | + (userp && digest->user && Curl_timestrcmp(userp, digest->user)) || | ||
175 | + (passwdp && digest->passwd && Curl_timestrcmp(passwdp, digest->passwd))) { | ||
176 | if(digest->http_context) { | ||
177 | s_pSecFn->DeleteSecurityContext(digest->http_context); | ||
178 | Curl_safefree(digest->http_context); | ||
179 | diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c | ||
180 | index e8cb70f..70a9391 100644 | ||
181 | --- a/lib/vtls/vtls.c | ||
182 | +++ b/lib/vtls/vtls.c | ||
183 | @@ -98,9 +98,15 @@ Curl_ssl_config_matches(struct ssl_primary_config* data, | ||
184 | Curl_safecmp(data->issuercert, needle->issuercert) && | ||
185 | Curl_safecmp(data->clientcert, needle->clientcert) && | ||
186 | Curl_safecmp(data->random_file, needle->random_file) && | ||
187 | - Curl_safecmp(data->egdsocket, needle->egdsocket) && | ||
188 | + Curl_safecmp(data->egdsocket, needle->egdsocket) && | ||
189 | +#ifdef USE_TLS_SRP | ||
190 | + !Curl_timestrcmp(data->username, needle->username) && | ||
191 | + !Curl_timestrcmp(data->password, needle->password) && | ||
192 | + (data->authtype == needle->authtype) && | ||
193 | +#endif | ||
194 | Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) && | ||
195 | Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) && | ||
196 | + Curl_safe_strcasecompare(data->CRLfile, needle->CRLfile) && | ||
197 | Curl_safe_strcasecompare(data->pinned_key, needle->pinned_key)) | ||
198 | return TRUE; | ||
199 | |||
200 | @@ -117,6 +123,9 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source, | ||
201 | dest->verifyhost = source->verifyhost; | ||
202 | dest->verifystatus = source->verifystatus; | ||
203 | dest->sessionid = source->sessionid; | ||
204 | +#ifdef USE_TLS_SRP | ||
205 | + dest->authtype = source->authtype; | ||
206 | +#endif | ||
207 | |||
208 | CLONE_STRING(CApath); | ||
209 | CLONE_STRING(CAfile); | ||
210 | @@ -127,6 +136,11 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source, | ||
211 | CLONE_STRING(cipher_list); | ||
212 | CLONE_STRING(cipher_list13); | ||
213 | CLONE_STRING(pinned_key); | ||
214 | + CLONE_STRING(CRLfile); | ||
215 | +#ifdef USE_TLS_SRP | ||
216 | + CLONE_STRING(username); | ||
217 | + CLONE_STRING(password); | ||
218 | +#endif | ||
219 | |||
220 | return TRUE; | ||
221 | } | ||
222 | @@ -142,6 +156,11 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc) | ||
223 | Curl_safefree(sslc->cipher_list); | ||
224 | Curl_safefree(sslc->cipher_list13); | ||
225 | Curl_safefree(sslc->pinned_key); | ||
226 | + Curl_safefree(sslc->CRLfile); | ||
227 | +#ifdef USE_TLS_SRP | ||
228 | + Curl_safefree(sslc->username); | ||
229 | + Curl_safefree(sslc->password); | ||
230 | +#endif | ||
231 | } | ||
232 | |||
233 | #ifdef USE_SSL | ||
234 | -- | ||
235 | 2.25.1 | ||
236 | |||