fix CVE-2024-11053
This commit is contained in:
parent
f1d1ed229a
commit
5f58cdffa3
37
backport-CVE-2024-11053-post1.patch
Normal file
37
backport-CVE-2024-11053-post1.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From 4b07b7ebadfbff1d26622719b9048673a78f0bf0 Mon Sep 17 00:00:00 2001
|
||||
From: Viktor Szakats <commit@vsz.me>
|
||||
Date: Sun, 17 Nov 2024 12:46:25 +0100
|
||||
Subject: [PATCH] netrc: fix pointer to bool conversion
|
||||
|
||||
with MSVC 2008 and 2010:
|
||||
```
|
||||
lib/netrc.c(107): error C2440: 'initializing' : cannot convert from 'char *' to 'bool'
|
||||
```
|
||||
Ref: https://ci.appveyor.com/project/curlorg/curl/builds/51002792/job/jtoxd4mk984oi6fd#L164
|
||||
Ref: https://ci.appveyor.com/project/curlorg/curl/builds/51002792/job/0wxlw9a8g04e56vt#L177
|
||||
|
||||
Follow-up to e9b9bbac22c26cf67316fa8e6c6b9e831af31949 #15586
|
||||
Closes #15601
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/curl/curl/commit/4b07b7ebadfbff1d26622719b9048673a78f0bf0
|
||||
---
|
||||
lib/netrc.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/netrc.c b/lib/netrc.c
|
||||
index e787a6ffc..d5ee3c0fd 100644
|
||||
--- a/lib/netrc.c
|
||||
+++ b/lib/netrc.c
|
||||
@@ -104,7 +104,7 @@ static int parsenetrc(struct store_netrc *store,
|
||||
int retcode = NETRC_FILE_MISSING;
|
||||
char *login = *loginp;
|
||||
char *password = NULL;
|
||||
- bool specific_login = login; /* points to something */
|
||||
+ bool specific_login = !!login; /* points to something */
|
||||
enum host_lookup_state state = NOTHING;
|
||||
enum found_state keyword = NONE;
|
||||
unsigned char found = 0; /* login + password found bits, as they can come in
|
||||
--
|
||||
2.33.0
|
||||
|
||||
129
backport-CVE-2024-11053-post2.patch
Normal file
129
backport-CVE-2024-11053-post2.patch
Normal file
@ -0,0 +1,129 @@
|
||||
From 9fce2c55d4b0273ac99b59bd8cb982a6d96b88cf Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Stenberg <daniel@haxx.se>
|
||||
Date: Tue, 17 Dec 2024 23:56:42 +0100
|
||||
Subject: [PATCH] netrc: fix password-only entries
|
||||
|
||||
When a specific hostname matched, and only a password is set before
|
||||
another machine is specified in the netrc file, the parser would not be
|
||||
happy and stop there and return the password-only state. It instead
|
||||
continued and did not return a match.
|
||||
|
||||
Add test 2005 to verify this case
|
||||
|
||||
Regression from e9b9bba, shipped in 8.11.1.
|
||||
|
||||
Reported-by: Ben Zanin
|
||||
Fixes #15767
|
||||
Closes #15768
|
||||
|
||||
Conflict:context adapt
|
||||
Reference:https://github.com/curl/curl/commit/9fce2c55d4b0273ac99b59bd8cb982a6d96b88cf
|
||||
---
|
||||
lib/netrc.c | 7 +++++-
|
||||
tests/data/Makefile.inc | 2 +-
|
||||
tests/data/test2005 | 55 ++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 62 insertions(+), 2 deletions(-)
|
||||
create mode 100644 tests/data/test2005
|
||||
|
||||
diff --git a/lib/netrc.c b/lib/netrc.c
|
||||
index cbc86484f..b517c1dfa 100644
|
||||
--- a/lib/netrc.c
|
||||
+++ b/lib/netrc.c
|
||||
@@ -267,7 +267,8 @@ static int parsenetrc(struct store_netrc *store,
|
||||
retcode = NETRC_FAILED; /* allocation failed */
|
||||
goto out;
|
||||
}
|
||||
- found |= FOUND_PASSWORD;
|
||||
+ if(!specific_login || our_login)
|
||||
+ found |= FOUND_PASSWORD;
|
||||
keyword = NONE;
|
||||
}
|
||||
else if(strcasecompare("login", tok))
|
||||
@@ -276,6 +277,10 @@ static int parsenetrc(struct store_netrc *store,
|
||||
keyword = PASSWORD;
|
||||
else if(strcasecompare("machine", tok)) {
|
||||
/* a new machine here */
|
||||
+ if(found & FOUND_PASSWORD) {
|
||||
+ done = TRUE;
|
||||
+ break;
|
||||
+ }
|
||||
state = HOSTFOUND;
|
||||
keyword = NONE;
|
||||
found = 0;
|
||||
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
|
||||
index bd9a0bbaa..105108309 100644
|
||||
--- a/tests/data/Makefile.inc
|
||||
+++ b/tests/data/Makefile.inc
|
||||
@@ -238,7 +238,7 @@ test1941 test1942 test1943 test1944 test1945 test1946 test1947 test1948 \
|
||||
test1955 test1956 test1957 test1958 test1959 test1960 test1964 \
|
||||
test1970 test1971 test1972 test1973 test1974 test1975 \
|
||||
\
|
||||
-test2000 test2001 test2002 test2003 test2004 \
|
||||
+test2000 test2001 test2002 test2003 test2004 test2005 \
|
||||
\
|
||||
test2023 \
|
||||
test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
|
||||
diff --git a/tests/data/test2005 b/tests/data/test2005
|
||||
new file mode 100644
|
||||
index 000000000..91e256298
|
||||
--- /dev/null
|
||||
+++ b/tests/data/test2005
|
||||
@@ -0,0 +1,55 @@
|
||||
+<testcase>
|
||||
+<info>
|
||||
+<keywords>
|
||||
+HTTP
|
||||
+netrc
|
||||
+</keywords>
|
||||
+</info>
|
||||
+#
|
||||
+# Server-side
|
||||
+<reply>
|
||||
+<data>
|
||||
+HTTP/1.1 200 OK
|
||||
+Date: Fri, 05 Aug 2022 10:09:00 GMT
|
||||
+Server: test-server/fake
|
||||
+Content-Type: text/plain
|
||||
+Content-Length: 6
|
||||
+Connection: close
|
||||
+
|
||||
+-foo-
|
||||
+</data>
|
||||
+</reply>
|
||||
+
|
||||
+#
|
||||
+# Client-side
|
||||
+<client>
|
||||
+<server>
|
||||
+http
|
||||
+</server>
|
||||
+<name>
|
||||
+netrc match with password only in file, no username. machine follows
|
||||
+</name>
|
||||
+<command>
|
||||
+--netrc-optional --netrc-file %LOGDIR/netrc%TESTNUMBER http://%HOSTIP:%HTTPPORT/
|
||||
+</command>
|
||||
+<file name="%LOGDIR/netrc%TESTNUMBER" >
|
||||
+machine %HOSTIP
|
||||
+password 5up3r53cr37
|
||||
+
|
||||
+machine example.com
|
||||
+</file>
|
||||
+</client>
|
||||
+
|
||||
+#
|
||||
+# Verify data after the test has been "shot"
|
||||
+<verify>
|
||||
+<protocol>
|
||||
+GET / HTTP/1.1
|
||||
+Host: %HOSTIP:%HTTPPORT
|
||||
+Authorization: Basic %b64[:5up3r53cr37]b64%
|
||||
+User-Agent: curl/%VERSION
|
||||
+Accept: */*
|
||||
+
|
||||
+</protocol>
|
||||
+</verify>
|
||||
+</testcase>
|
||||
--
|
||||
2.33.0
|
||||
|
||||
453
backport-CVE-2024-11053-pre1.patch
Normal file
453
backport-CVE-2024-11053-pre1.patch
Normal file
@ -0,0 +1,453 @@
|
||||
From 142ac257b3242459b284020c59f1902b9687a954 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Stenberg <daniel@haxx.se>
|
||||
Date: Tue, 6 Feb 2024 10:15:52 +0100
|
||||
Subject: [PATCH] lib: convert Curl_get_line to use dynbuf
|
||||
|
||||
Create the line in a dynbuf. Aborts the reading of the file on
|
||||
errors. Avoids having to always allocate maximum amount from the
|
||||
start. Avoids direct malloc.
|
||||
|
||||
Closes #12846
|
||||
|
||||
Conflict:context adapt
|
||||
Reference:https://github.com/curl/curl/commit/142ac257b3242459b284020c59f1902b9687a954
|
||||
---
|
||||
lib/altsvc.c | 18 +++-------
|
||||
lib/cookie.c | 29 ++++------------
|
||||
lib/curl_get_line.c | 55 +++++++++++++----------------
|
||||
lib/curl_get_line.h | 7 ++--
|
||||
lib/hsts.c | 17 +++------
|
||||
lib/netrc.c | 10 ++++--
|
||||
tests/unit/unit3200.c | 80 ++++++++++++++++++++++++-------------------
|
||||
7 files changed, 96 insertions(+), 120 deletions(-)
|
||||
|
||||
diff --git a/lib/altsvc.c b/lib/altsvc.c
|
||||
index e9f62bf0e..c12d7bda1 100644
|
||||
--- a/lib/altsvc.c
|
||||
+++ b/lib/altsvc.c
|
||||
@@ -209,7 +209,6 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
|
||||
static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
- char *line = NULL;
|
||||
FILE *fp;
|
||||
|
||||
/* we need a private copy of the file name so that the altsvc cache file
|
||||
@@ -221,11 +220,10 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
|
||||
|
||||
fp = fopen(file, FOPEN_READTEXT);
|
||||
if(fp) {
|
||||
- line = malloc(MAX_ALTSVC_LINE);
|
||||
- if(!line)
|
||||
- goto fail;
|
||||
- while(Curl_get_line(line, MAX_ALTSVC_LINE, fp)) {
|
||||
- char *lineptr = line;
|
||||
+ struct dynbuf buf;
|
||||
+ Curl_dyn_init(&buf, MAX_ALTSVC_LINE);
|
||||
+ while(Curl_get_line(&buf, fp)) {
|
||||
+ char *lineptr = Curl_dyn_ptr(&buf);
|
||||
while(*lineptr && ISBLANK(*lineptr))
|
||||
lineptr++;
|
||||
if(*lineptr == '#')
|
||||
@@ -234,16 +232,10 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
|
||||
|
||||
altsvc_add(asi, lineptr);
|
||||
}
|
||||
- free(line); /* free the line buffer */
|
||||
+ Curl_dyn_free(&buf); /* free the line buffer */
|
||||
fclose(fp);
|
||||
}
|
||||
return result;
|
||||
-
|
||||
-fail:
|
||||
- Curl_safefree(asi->filename);
|
||||
- free(line);
|
||||
- fclose(fp);
|
||||
- return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/*
|
||||
diff --git a/lib/cookie.c b/lib/cookie.c
|
||||
index dc319b611..d10dd572b 100644
|
||||
--- a/lib/cookie.c
|
||||
+++ b/lib/cookie.c
|
||||
@@ -1205,7 +1205,6 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||
bool newsession)
|
||||
{
|
||||
struct CookieInfo *c;
|
||||
- char *line = NULL;
|
||||
FILE *handle = NULL;
|
||||
|
||||
if(!inc) {
|
||||
@@ -1241,16 +1240,14 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||
|
||||
c->running = FALSE; /* this is not running, this is init */
|
||||
if(fp) {
|
||||
-
|
||||
- line = malloc(MAX_COOKIE_LINE);
|
||||
- if(!line)
|
||||
- goto fail;
|
||||
- while(Curl_get_line(line, MAX_COOKIE_LINE, fp)) {
|
||||
- char *lineptr = line;
|
||||
+ struct dynbuf buf;
|
||||
+ Curl_dyn_init(&buf, MAX_COOKIE_LINE);
|
||||
+ while(Curl_get_line(&buf, fp)) {
|
||||
+ char *lineptr = Curl_dyn_ptr(&buf);
|
||||
bool headerline = FALSE;
|
||||
- if(checkprefix("Set-Cookie:", line)) {
|
||||
+ if(checkprefix("Set-Cookie:", lineptr)) {
|
||||
/* This is a cookie line, get it! */
|
||||
- lineptr = &line[11];
|
||||
+ lineptr += 11;
|
||||
headerline = TRUE;
|
||||
while(*lineptr && ISBLANK(*lineptr))
|
||||
lineptr++;
|
||||
@@ -1258,7 +1255,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||
|
||||
Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE);
|
||||
}
|
||||
- free(line); /* free the line buffer */
|
||||
+ Curl_dyn_free(&buf); /* free the line buffer */
|
||||
|
||||
/*
|
||||
* Remove expired cookies from the hash. We must make sure to run this
|
||||
@@ -1274,18 +1271,6 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||
c->running = TRUE; /* now, we're running */
|
||||
|
||||
return c;
|
||||
-
|
||||
-fail:
|
||||
- free(line);
|
||||
- /*
|
||||
- * Only clean up if we allocated it here, as the original could still be in
|
||||
- * use by a share handle.
|
||||
- */
|
||||
- if(!inc)
|
||||
- Curl_cookie_cleanup(c);
|
||||
- if(handle)
|
||||
- fclose(handle);
|
||||
- return NULL; /* out of memory */
|
||||
}
|
||||
|
||||
/*
|
||||
diff --git a/lib/curl_get_line.c b/lib/curl_get_line.c
|
||||
index 686abe751..100207331 100644
|
||||
--- a/lib/curl_get_line.c
|
||||
+++ b/lib/curl_get_line.c
|
||||
@@ -33,14 +33,16 @@
|
||||
#include "memdebug.h"
|
||||
|
||||
/*
|
||||
- * Curl_get_line() makes sure to only return complete whole lines that fit in
|
||||
- * 'len' bytes and end with a newline.
|
||||
+ * Curl_get_line() makes sure to only return complete whole lines that end
|
||||
+ * newlines.
|
||||
*/
|
||||
-char *Curl_get_line(char *buf, int len, FILE *input)
|
||||
+int Curl_get_line(struct dynbuf *buf, FILE *input)
|
||||
{
|
||||
- bool partial = FALSE;
|
||||
+ CURLcode result;
|
||||
+ char buffer[128];
|
||||
+ Curl_dyn_reset(buf);
|
||||
while(1) {
|
||||
- char *b = fgets(buf, len, input);
|
||||
+ char *b = fgets(buffer, sizeof(buffer), input);
|
||||
|
||||
if(b) {
|
||||
size_t rlen = strlen(b);
|
||||
@@ -48,39 +50,28 @@ char *Curl_get_line(char *buf, int len, FILE *input)
|
||||
if(!rlen)
|
||||
break;
|
||||
|
||||
- if(b[rlen-1] == '\n') {
|
||||
- /* b is \n terminated */
|
||||
- if(partial) {
|
||||
- partial = FALSE;
|
||||
- continue;
|
||||
- }
|
||||
- return b;
|
||||
- }
|
||||
- else if(feof(input)) {
|
||||
- if(partial)
|
||||
- /* Line is already too large to return, ignore rest */
|
||||
- break;
|
||||
+ result = Curl_dyn_addn(buf, b, rlen);
|
||||
+ if(result)
|
||||
+ /* too long line or out of memory */
|
||||
+ return 0; /* error */
|
||||
|
||||
- if(rlen + 1 < (size_t) len) {
|
||||
- /* b is EOF terminated, insert missing \n */
|
||||
- b[rlen] = '\n';
|
||||
- b[rlen + 1] = '\0';
|
||||
- return b;
|
||||
- }
|
||||
- else
|
||||
- /* Maximum buffersize reached + EOF
|
||||
- * This line is impossible to add a \n to so we'll ignore it
|
||||
- */
|
||||
- break;
|
||||
+ else if(b[rlen-1] == '\n')
|
||||
+ /* end of the line */
|
||||
+ return 1; /* all good */
|
||||
+
|
||||
+ else if(feof(input)) {
|
||||
+ /* append a newline */
|
||||
+ result = Curl_dyn_addn(buf, "\n", 1);
|
||||
+ if(result)
|
||||
+ /* too long line or out of memory */
|
||||
+ return 0; /* error */
|
||||
+ return 1; /* all good */
|
||||
}
|
||||
- else
|
||||
- /* Maximum buffersize reached */
|
||||
- partial = TRUE;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
- return NULL;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
#endif /* if not disabled */
|
||||
diff --git a/lib/curl_get_line.h b/lib/curl_get_line.h
|
||||
index 0ff32c5c2..7907cde88 100644
|
||||
--- a/lib/curl_get_line.h
|
||||
+++ b/lib/curl_get_line.h
|
||||
@@ -24,8 +24,9 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
-/* get_line() makes sure to only return complete whole lines that fit in 'len'
|
||||
- * bytes and end with a newline. */
|
||||
-char *Curl_get_line(char *buf, int len, FILE *input);
|
||||
+#include "dynbuf.h"
|
||||
+
|
||||
+/* Curl_get_line() returns complete lines that end with a newline. */
|
||||
+int Curl_get_line(struct dynbuf *buf, FILE *input);
|
||||
|
||||
#endif /* HEADER_CURL_GET_LINE_H */
|
||||
diff --git a/lib/hsts.c b/lib/hsts.c
|
||||
index 8725a35c1..607755e6b 100644
|
||||
--- a/lib/hsts.c
|
||||
+++ b/lib/hsts.c
|
||||
@@ -511,7 +511,6 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h)
|
||||
static CURLcode hsts_load(struct hsts *h, const char *file)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
- char *line = NULL;
|
||||
FILE *fp;
|
||||
|
||||
/* we need a private copy of the file name so that the hsts cache file
|
||||
@@ -523,11 +522,10 @@ static CURLcode hsts_load(struct hsts *h, const char *file)
|
||||
|
||||
fp = fopen(file, FOPEN_READTEXT);
|
||||
if(fp) {
|
||||
- line = malloc(MAX_HSTS_LINE);
|
||||
- if(!line)
|
||||
- goto fail;
|
||||
- while(Curl_get_line(line, MAX_HSTS_LINE, fp)) {
|
||||
- char *lineptr = line;
|
||||
+ struct dynbuf buf;
|
||||
+ Curl_dyn_init(&buf, MAX_HSTS_LINE);
|
||||
+ while(Curl_get_line(&buf, fp)) {
|
||||
+ char *lineptr = Curl_dyn_ptr(&buf);
|
||||
while(*lineptr && ISBLANK(*lineptr))
|
||||
lineptr++;
|
||||
if(*lineptr == '#')
|
||||
@@ -536,15 +534,10 @@ static CURLcode hsts_load(struct hsts *h, const char *file)
|
||||
|
||||
hsts_add(h, lineptr);
|
||||
}
|
||||
- free(line); /* free the line buffer */
|
||||
+ Curl_dyn_free(&buf); /* free the line buffer */
|
||||
fclose(fp);
|
||||
}
|
||||
return result;
|
||||
-
|
||||
-fail:
|
||||
- Curl_safefree(h->filename);
|
||||
- fclose(fp);
|
||||
- return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/*
|
||||
diff --git a/lib/netrc.c b/lib/netrc.c
|
||||
index 038c6dca6..cd2a2844e 100644
|
||||
--- a/lib/netrc.c
|
||||
+++ b/lib/netrc.c
|
||||
@@ -53,6 +53,8 @@ enum host_lookup_state {
|
||||
#define NETRC_FAILED -1
|
||||
#define NETRC_SUCCESS 0
|
||||
|
||||
+#define MAX_NETRC_LINE 4096
|
||||
+
|
||||
/*
|
||||
* Returns zero on success.
|
||||
*/
|
||||
@@ -80,13 +82,14 @@ static int parsenetrc(const char *host,
|
||||
file = fopen(netrcfile, FOPEN_READTEXT);
|
||||
if(file) {
|
||||
bool done = FALSE;
|
||||
- char netrcbuffer[4096];
|
||||
- int netrcbuffsize = (int)sizeof(netrcbuffer);
|
||||
+ struct dynbuf buf;
|
||||
+ Curl_dyn_init(&buf, MAX_NETRC_LINE);
|
||||
|
||||
- while(!done && Curl_get_line(netrcbuffer, netrcbuffsize, file)) {
|
||||
+ while(!done && Curl_get_line(&buf, file)) {
|
||||
char *tok;
|
||||
char *tok_end;
|
||||
bool quoted;
|
||||
+ char *netrcbuffer = Curl_dyn_ptr(&buf);
|
||||
if(state == MACDEF) {
|
||||
if((netrcbuffer[0] == '\n') || (netrcbuffer[0] == '\r'))
|
||||
state = NOTHING;
|
||||
@@ -245,6 +248,7 @@ static int parsenetrc(const char *host,
|
||||
} /* while Curl_get_line() */
|
||||
|
||||
out:
|
||||
+ Curl_dyn_free(&buf);
|
||||
if(!retcode) {
|
||||
/* success */
|
||||
if(login_alloc) {
|
||||
diff --git a/tests/unit/unit3200.c b/tests/unit/unit3200.c
|
||||
index 0544bcc93..6f508ce07 100644
|
||||
--- a/tests/unit/unit3200.c
|
||||
+++ b/tests/unit/unit3200.c
|
||||
@@ -69,7 +69,7 @@ static const char *filecontents[] = {
|
||||
"LINE1\n"
|
||||
C4096 "SOME EXTRA TEXT",
|
||||
|
||||
- /* First and third line should be read */
|
||||
+ /* Only first should be read */
|
||||
"LINE1\n"
|
||||
C4096 "SOME EXTRA TEXT\n"
|
||||
"LINE3\n",
|
||||
@@ -84,11 +84,13 @@ static const char *filecontents[] = {
|
||||
|
||||
UNITTEST_START
|
||||
size_t i;
|
||||
+ int rc = 0;
|
||||
for(i = 0; i < NUMTESTS; i++) {
|
||||
FILE *fp;
|
||||
- char buf[4096];
|
||||
+ struct dynbuf buf;
|
||||
int len = 4096;
|
||||
char *line;
|
||||
+ Curl_dyn_init(&buf, len);
|
||||
|
||||
fp = fopen(arg, "wb");
|
||||
abort_unless(fp != NULL, "Cannot open testfile");
|
||||
@@ -101,65 +103,73 @@ UNITTEST_START
|
||||
fprintf(stderr, "Test %zd...", i);
|
||||
switch(i) {
|
||||
case 0:
|
||||
- line = Curl_get_line(buf, len, fp);
|
||||
+ rc = Curl_get_line(&buf, fp);
|
||||
+ line = Curl_dyn_ptr(&buf);
|
||||
fail_unless(line && !strcmp("LINE1\n", line),
|
||||
- "First line failed (1)");
|
||||
- line = Curl_get_line(buf, len, fp);
|
||||
+ "First line failed (1)");
|
||||
+ rc = Curl_get_line(&buf, fp);
|
||||
+ line = Curl_dyn_ptr(&buf);
|
||||
fail_unless(line && !strcmp("LINE2 NEWLINE\n", line),
|
||||
- "Second line failed (1)");
|
||||
- line = Curl_get_line(buf, len, fp);
|
||||
- abort_unless(line == NULL, "Missed EOF (1)");
|
||||
+ "Second line failed (1)");
|
||||
+ rc = Curl_get_line(&buf, fp);
|
||||
+ abort_unless(!Curl_dyn_len(&buf), "Missed EOF (1)");
|
||||
break;
|
||||
case 1:
|
||||
- line = Curl_get_line(buf, len, fp);
|
||||
+ rc = Curl_get_line(&buf, fp);
|
||||
+ line = Curl_dyn_ptr(&buf);
|
||||
fail_unless(line && !strcmp("LINE1\n", line),
|
||||
- "First line failed (2)");
|
||||
- line = Curl_get_line(buf, len, fp);
|
||||
+ "First line failed (2)");
|
||||
+ rc = Curl_get_line(&buf, fp);
|
||||
+ line = Curl_dyn_ptr(&buf);
|
||||
fail_unless(line && !strcmp("LINE2 NONEWLINE\n", line),
|
||||
- "Second line failed (2)");
|
||||
- line = Curl_get_line(buf, len, fp);
|
||||
- abort_unless(line == NULL, "Missed EOF (2)");
|
||||
+ "Second line failed (2)");
|
||||
+ rc = Curl_get_line(&buf, fp);
|
||||
+ abort_unless(!Curl_dyn_len(&buf), "Missed EOF (2)");
|
||||
break;
|
||||
case 2:
|
||||
- line = Curl_get_line(buf, len, fp);
|
||||
+ rc = Curl_get_line(&buf, fp);
|
||||
+ line = Curl_dyn_ptr(&buf);
|
||||
fail_unless(line && !strcmp("LINE1\n", line),
|
||||
- "First line failed (3)");
|
||||
- line = Curl_get_line(buf, len, fp);
|
||||
- fail_unless(line == NULL,
|
||||
- "Did not detect max read on EOF (3)");
|
||||
+ "First line failed (3)");
|
||||
+ rc = Curl_get_line(&buf, fp);
|
||||
+ fail_unless(!Curl_dyn_len(&buf),
|
||||
+ "Did not detect max read on EOF (3)");
|
||||
break;
|
||||
case 3:
|
||||
- line = Curl_get_line(buf, len, fp);
|
||||
+ rc = Curl_get_line(&buf, fp);
|
||||
+ line = Curl_dyn_ptr(&buf);
|
||||
fail_unless(line && !strcmp("LINE1\n", line),
|
||||
- "First line failed (4)");
|
||||
- line = Curl_get_line(buf, len, fp);
|
||||
- fail_unless(line == NULL,
|
||||
- "Did not ignore partial on EOF (4)");
|
||||
+ "First line failed (4)");
|
||||
+ rc = Curl_get_line(&buf, fp);
|
||||
+ fail_unless(!Curl_dyn_len(&buf),
|
||||
+ "Did not ignore partial on EOF (4)");
|
||||
break;
|
||||
case 4:
|
||||
- line = Curl_get_line(buf, len, fp);
|
||||
+ rc = Curl_get_line(&buf, fp);
|
||||
+ line = Curl_dyn_ptr(&buf);
|
||||
fail_unless(line && !strcmp("LINE1\n", line),
|
||||
- "First line failed (5)");
|
||||
- line = Curl_get_line(buf, len, fp);
|
||||
- fail_unless(line && !strcmp("LINE3\n", line),
|
||||
- "Third line failed (5)");
|
||||
- line = Curl_get_line(buf, len, fp);
|
||||
- abort_unless(line == NULL, "Missed EOF (5)");
|
||||
+ "First line failed (5)");
|
||||
+ rc = Curl_get_line(&buf, fp);
|
||||
+ fail_unless(!Curl_dyn_len(&buf),
|
||||
+ "Did not bail out on too long line");
|
||||
break;
|
||||
case 5:
|
||||
- line = Curl_get_line(buf, len, fp);
|
||||
+ rc = Curl_get_line(&buf, fp);
|
||||
+ line = Curl_dyn_ptr(&buf);
|
||||
fail_unless(line && !strcmp("LINE1\x1aTEST\n", line),
|
||||
- "Missed/Misinterpreted ^Z (6)");
|
||||
- line = Curl_get_line(buf, len, fp);
|
||||
- abort_unless(line == NULL, "Missed EOF (6)");
|
||||
+ "Missed/Misinterpreted ^Z (6)");
|
||||
+ rc = Curl_get_line(&buf, fp);
|
||||
+ abort_unless(!Curl_dyn_len(&buf), "Missed EOF (6)");
|
||||
break;
|
||||
default:
|
||||
abort_unless(1, "Unknown case");
|
||||
break;
|
||||
}
|
||||
+ Curl_dyn_free(&buf);
|
||||
fclose(fp);
|
||||
fprintf(stderr, "OK\n");
|
||||
}
|
||||
+ return rc;
|
||||
UNITTEST_STOP
|
||||
|
||||
#else
|
||||
--
|
||||
2.33.0
|
||||
|
||||
800
backport-CVE-2024-11053-pre2.patch
Normal file
800
backport-CVE-2024-11053-pre2.patch
Normal file
@ -0,0 +1,800 @@
|
||||
From 3b43a05e000aa8f65bda513f733a73fefe35d5ca Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Stenberg <daniel@haxx.se>
|
||||
Date: Thu, 10 Oct 2024 18:08:07 +0200
|
||||
Subject: [PATCH] netrc: cache the netrc file in memory
|
||||
|
||||
So that on redirects etc it does not reread the file but just parses it
|
||||
again.
|
||||
|
||||
Reported-by: Pierre-Etienne Meunier
|
||||
Fixes #15248
|
||||
Closes #15259
|
||||
|
||||
Conflict:context adapt
|
||||
Reference:https://github.com/curl/curl/commit/3b43a05e000aa8f65bda513f733a73fefe35d5ca
|
||||
---
|
||||
lib/multi.c | 2 +
|
||||
lib/netrc.c | 407 ++++++++++++++++++++++++------------------
|
||||
lib/netrc.h | 14 +-
|
||||
lib/url.c | 4 +-
|
||||
lib/urldata.h | 5 +
|
||||
tests/unit/unit1304.c | 48 ++++-
|
||||
6 files changed, 292 insertions(+), 188 deletions(-)
|
||||
|
||||
diff --git a/lib/multi.c b/lib/multi.c
|
||||
index 223c2339c..0f9fedaff 100644
|
||||
--- a/lib/multi.c
|
||||
+++ b/lib/multi.c
|
||||
@@ -757,6 +757,8 @@ static CURLcode multi_done(struct Curl_easy *data,
|
||||
data->state.lastconnect_id = -1;
|
||||
}
|
||||
|
||||
+ /* flush the netrc cache */
|
||||
+ Curl_netrc_cleanup(&data->state.netrc);
|
||||
Curl_safefree(data->state.buffer);
|
||||
return result;
|
||||
}
|
||||
diff --git a/lib/netrc.c b/lib/netrc.c
|
||||
index 3c0651dcc..c23f927ce 100644
|
||||
--- a/lib/netrc.c
|
||||
+++ b/lib/netrc.c
|
||||
@@ -31,7 +31,6 @@
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include "netrc.h"
|
||||
-#include "strtok.h"
|
||||
#include "strcase.h"
|
||||
#include "curl_get_line.h"
|
||||
|
||||
@@ -49,21 +48,56 @@ enum host_lookup_state {
|
||||
MACDEF
|
||||
};
|
||||
|
||||
+enum found_state {
|
||||
+ NONE,
|
||||
+ LOGIN,
|
||||
+ PASSWORD
|
||||
+};
|
||||
+
|
||||
#define NETRC_FILE_MISSING 1
|
||||
#define NETRC_FAILED -1
|
||||
#define NETRC_SUCCESS 0
|
||||
|
||||
#define MAX_NETRC_LINE 4096
|
||||
+#define MAX_NETRC_FILE (64*1024)
|
||||
+#define MAX_NETRC_TOKEN 128
|
||||
+
|
||||
+static CURLcode file2memory(const char *filename, struct dynbuf *filebuf)
|
||||
+{
|
||||
+ CURLcode result = CURLE_OK;
|
||||
+ FILE *file = fopen(filename, FOPEN_READTEXT);
|
||||
+ struct dynbuf linebuf;
|
||||
+ Curl_dyn_init(&linebuf, MAX_NETRC_LINE);
|
||||
+
|
||||
+ if(file) {
|
||||
+ while(Curl_get_line(&linebuf, file)) {
|
||||
+ const char *line = Curl_dyn_ptr(&linebuf);
|
||||
+ /* skip comments on load */
|
||||
+ while(ISBLANK(*line))
|
||||
+ line++;
|
||||
+ if(*line == '#')
|
||||
+ continue;
|
||||
+ result = Curl_dyn_add(filebuf, line);
|
||||
+ if(result)
|
||||
+ goto done;
|
||||
+ }
|
||||
+ }
|
||||
+done:
|
||||
+ Curl_dyn_free(&linebuf);
|
||||
+ if(file)
|
||||
+ fclose(file);
|
||||
+ return result;
|
||||
+}
|
||||
|
||||
/*
|
||||
* Returns zero on success.
|
||||
*/
|
||||
-static int parsenetrc(const char *host,
|
||||
+static int parsenetrc(struct store_netrc *store,
|
||||
+ const char *host,
|
||||
char **loginp,
|
||||
char **passwordp,
|
||||
- char *netrcfile)
|
||||
+ const char *netrcfile)
|
||||
{
|
||||
- FILE *file;
|
||||
int retcode = NETRC_FILE_MISSING;
|
||||
char *login = *loginp;
|
||||
char *password = *passwordp;
|
||||
@@ -71,204 +105,212 @@ static int parsenetrc(const char *host,
|
||||
bool login_alloc = FALSE;
|
||||
bool password_alloc = FALSE;
|
||||
enum host_lookup_state state = NOTHING;
|
||||
+ enum found_state found = NONE;
|
||||
+ bool our_login = TRUE; /* With specific_login, found *our* login name (or
|
||||
+ login-less line) */
|
||||
+ bool done = FALSE;
|
||||
+ char *netrcbuffer;
|
||||
+ struct dynbuf token;
|
||||
+ struct dynbuf *filebuf = &store->filebuf;
|
||||
+ Curl_dyn_init(&token, MAX_NETRC_TOKEN);
|
||||
|
||||
- char state_login = 0; /* Found a login keyword */
|
||||
- char state_password = 0; /* Found a password keyword */
|
||||
- int state_our_login = TRUE; /* With specific_login, found *our* login
|
||||
- name (or login-less line) */
|
||||
-
|
||||
- DEBUGASSERT(netrcfile);
|
||||
+ if(!store->loaded) {
|
||||
+ if(file2memory(netrcfile, filebuf))
|
||||
+ return NETRC_FAILED;
|
||||
+ store->loaded = TRUE;
|
||||
+ }
|
||||
|
||||
- file = fopen(netrcfile, FOPEN_READTEXT);
|
||||
- if(file) {
|
||||
- bool done = FALSE;
|
||||
- struct dynbuf buf;
|
||||
- Curl_dyn_init(&buf, MAX_NETRC_LINE);
|
||||
+ netrcbuffer = Curl_dyn_ptr(filebuf);
|
||||
|
||||
- while(!done && Curl_get_line(&buf, file)) {
|
||||
- char *tok;
|
||||
+ while(!done) {
|
||||
+ char *tok = netrcbuffer;
|
||||
+ while(tok) {
|
||||
char *tok_end;
|
||||
bool quoted;
|
||||
- char *netrcbuffer = Curl_dyn_ptr(&buf);
|
||||
+ Curl_dyn_reset(&token);
|
||||
+ while(ISBLANK(*tok))
|
||||
+ tok++;
|
||||
+ /* tok is first non-space letter */
|
||||
if(state == MACDEF) {
|
||||
- if((netrcbuffer[0] == '\n') || (netrcbuffer[0] == '\r'))
|
||||
- state = NOTHING;
|
||||
- else
|
||||
- continue;
|
||||
+ if((*tok == '\n') || (*tok == '\r'))
|
||||
+ state = NOTHING; /* end of macro definition */
|
||||
}
|
||||
- tok = netrcbuffer;
|
||||
- while(tok) {
|
||||
- while(ISBLANK(*tok))
|
||||
- tok++;
|
||||
- /* tok is first non-space letter */
|
||||
- if(!*tok || (*tok == '#'))
|
||||
- /* end of line or the rest is a comment */
|
||||
- break;
|
||||
|
||||
- /* leading double-quote means quoted string */
|
||||
- quoted = (*tok == '\"');
|
||||
+ if(!*tok || (*tok == '\n'))
|
||||
+ /* end of line */
|
||||
+ break;
|
||||
|
||||
- tok_end = tok;
|
||||
- if(!quoted) {
|
||||
- while(!ISSPACE(*tok_end))
|
||||
- tok_end++;
|
||||
- *tok_end = 0;
|
||||
+ /* leading double-quote means quoted string */
|
||||
+ quoted = (*tok == '\"');
|
||||
+
|
||||
+ tok_end = tok;
|
||||
+ if(!quoted) {
|
||||
+ size_t len = 0;
|
||||
+ while(!ISSPACE(*tok_end)) {
|
||||
+ tok_end++;
|
||||
+ len++;
|
||||
}
|
||||
- else {
|
||||
- bool escape = FALSE;
|
||||
- bool endquote = FALSE;
|
||||
- char *store = tok;
|
||||
- tok_end++; /* pass the leading quote */
|
||||
- while(*tok_end) {
|
||||
- char s = *tok_end;
|
||||
- if(escape) {
|
||||
- escape = FALSE;
|
||||
- switch(s) {
|
||||
- case 'n':
|
||||
- s = '\n';
|
||||
- break;
|
||||
- case 'r':
|
||||
- s = '\r';
|
||||
- break;
|
||||
- case 't':
|
||||
- s = '\t';
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
- else if(s == '\\') {
|
||||
- escape = TRUE;
|
||||
- tok_end++;
|
||||
- continue;
|
||||
- }
|
||||
- else if(s == '\"') {
|
||||
- tok_end++; /* pass the ending quote */
|
||||
- endquote = TRUE;
|
||||
+ if(!len || Curl_dyn_addn(&token, tok, len)) {
|
||||
+ retcode = NETRC_FAILED;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+ else {
|
||||
+ bool escape = FALSE;
|
||||
+ bool endquote = FALSE;
|
||||
+ tok_end++; /* pass the leading quote */
|
||||
+ while(*tok_end) {
|
||||
+ char s = *tok_end;
|
||||
+ if(escape) {
|
||||
+ escape = FALSE;
|
||||
+ switch(s) {
|
||||
+ case 'n':
|
||||
+ s = '\n';
|
||||
+ break;
|
||||
+ case 'r':
|
||||
+ s = '\r';
|
||||
+ break;
|
||||
+ case 't':
|
||||
+ s = '\t';
|
||||
break;
|
||||
}
|
||||
- *store++ = s;
|
||||
+ }
|
||||
+ else if(s == '\\') {
|
||||
+ escape = TRUE;
|
||||
tok_end++;
|
||||
+ continue;
|
||||
+ }
|
||||
+ else if(s == '\"') {
|
||||
+ tok_end++; /* pass the ending quote */
|
||||
+ endquote = TRUE;
|
||||
+ break;
|
||||
}
|
||||
- *store = 0;
|
||||
- if(escape || !endquote) {
|
||||
- /* bad syntax, get out */
|
||||
+ if(Curl_dyn_addn(&token, &s, 1)) {
|
||||
retcode = NETRC_FAILED;
|
||||
goto out;
|
||||
}
|
||||
+ tok_end++;
|
||||
}
|
||||
-
|
||||
- if((login && *login) && (password && *password)) {
|
||||
- done = TRUE;
|
||||
- break;
|
||||
+ if(escape || !endquote) {
|
||||
+ /* bad syntax, get out */
|
||||
+ retcode = NETRC_FAILED;
|
||||
+ goto out;
|
||||
}
|
||||
+ }
|
||||
|
||||
- switch(state) {
|
||||
- case NOTHING:
|
||||
- if(strcasecompare("macdef", tok)) {
|
||||
- /* Define a macro. A macro is defined with the specified name; its
|
||||
- contents begin with the next .netrc line and continue until a
|
||||
- null line (consecutive new-line characters) is encountered. */
|
||||
- state = MACDEF;
|
||||
- }
|
||||
- else if(strcasecompare("machine", tok)) {
|
||||
- /* the next tok is the machine name, this is in itself the
|
||||
- delimiter that starts the stuff entered for this machine,
|
||||
- after this we need to search for 'login' and
|
||||
- 'password'. */
|
||||
- state = HOSTFOUND;
|
||||
- }
|
||||
- else if(strcasecompare("default", tok)) {
|
||||
- state = HOSTVALID;
|
||||
- retcode = NETRC_SUCCESS; /* we did find our host */
|
||||
- }
|
||||
- break;
|
||||
- case MACDEF:
|
||||
- if(!strlen(tok)) {
|
||||
- state = NOTHING;
|
||||
- }
|
||||
- break;
|
||||
- case HOSTFOUND:
|
||||
- if(strcasecompare(host, tok)) {
|
||||
- /* and yes, this is our host! */
|
||||
- state = HOSTVALID;
|
||||
- retcode = NETRC_SUCCESS; /* we did find our host */
|
||||
+ if((login && *login) && (password && *password)) {
|
||||
+ done = TRUE;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ tok = Curl_dyn_ptr(&token);
|
||||
+
|
||||
+ switch(state) {
|
||||
+ case NOTHING:
|
||||
+ if(strcasecompare("macdef", tok))
|
||||
+ /* Define a macro. A macro is defined with the specified name; its
|
||||
+ contents begin with the next .netrc line and continue until a
|
||||
+ null line (consecutive new-line characters) is encountered. */
|
||||
+ state = MACDEF;
|
||||
+ else if(strcasecompare("machine", tok))
|
||||
+ /* the next tok is the machine name, this is in itself the delimiter
|
||||
+ that starts the stuff entered for this machine, after this we
|
||||
+ need to search for 'login' and 'password'. */
|
||||
+ state = HOSTFOUND;
|
||||
+ else if(strcasecompare("default", tok)) {
|
||||
+ state = HOSTVALID;
|
||||
+ retcode = NETRC_SUCCESS; /* we did find our host */
|
||||
+ }
|
||||
+ break;
|
||||
+ case MACDEF:
|
||||
+ if(!*tok)
|
||||
+ state = NOTHING;
|
||||
+ break;
|
||||
+ case HOSTFOUND:
|
||||
+ if(strcasecompare(host, tok)) {
|
||||
+ /* and yes, this is our host! */
|
||||
+ state = HOSTVALID;
|
||||
+ retcode = NETRC_SUCCESS; /* we did find our host */
|
||||
+ }
|
||||
+ else
|
||||
+ /* not our host */
|
||||
+ state = NOTHING;
|
||||
+ break;
|
||||
+ case HOSTVALID:
|
||||
+ /* we are now parsing sub-keywords concerning "our" host */
|
||||
+ if(found == LOGIN) {
|
||||
+ if(specific_login) {
|
||||
+ our_login = !Curl_timestrcmp(login, tok);
|
||||
}
|
||||
- else
|
||||
- /* not our host */
|
||||
- state = NOTHING;
|
||||
- break;
|
||||
- case HOSTVALID:
|
||||
- /* we are now parsing sub-keywords concerning "our" host */
|
||||
- if(state_login) {
|
||||
- if(specific_login) {
|
||||
- state_our_login = !Curl_timestrcmp(login, tok);
|
||||
+ else if(!login || Curl_timestrcmp(login, tok)) {
|
||||
+ if(login_alloc)
|
||||
+ free(login);
|
||||
+ login = strdup(tok);
|
||||
+ if(!login) {
|
||||
+ retcode = NETRC_FAILED; /* allocation failed */
|
||||
+ goto out;
|
||||
}
|
||||
- else if(!login || Curl_timestrcmp(login, tok)) {
|
||||
- if(login_alloc) {
|
||||
- free(login);
|
||||
- login_alloc = FALSE;
|
||||
- }
|
||||
- login = strdup(tok);
|
||||
- if(!login) {
|
||||
- retcode = NETRC_FAILED; /* allocation failed */
|
||||
- goto out;
|
||||
- }
|
||||
- login_alloc = TRUE;
|
||||
- }
|
||||
- state_login = 0;
|
||||
+ login_alloc = TRUE;
|
||||
}
|
||||
- else if(state_password) {
|
||||
- if((state_our_login || !specific_login)
|
||||
- && (!password || Curl_timestrcmp(password, tok))) {
|
||||
- if(password_alloc) {
|
||||
- free(password);
|
||||
- password_alloc = FALSE;
|
||||
- }
|
||||
- password = strdup(tok);
|
||||
- if(!password) {
|
||||
- retcode = NETRC_FAILED; /* allocation failed */
|
||||
- goto out;
|
||||
- }
|
||||
- password_alloc = TRUE;
|
||||
+ found = NONE;
|
||||
+ }
|
||||
+ else if(found == PASSWORD) {
|
||||
+ if((our_login || !specific_login) &&
|
||||
+ (!password || Curl_timestrcmp(password, tok))) {
|
||||
+ if(password_alloc)
|
||||
+ free(password);
|
||||
+ password = strdup(tok);
|
||||
+ if(!password) {
|
||||
+ retcode = NETRC_FAILED; /* allocation failed */
|
||||
+ goto out;
|
||||
}
|
||||
- state_password = 0;
|
||||
- }
|
||||
- else if(strcasecompare("login", tok))
|
||||
- state_login = 1;
|
||||
- else if(strcasecompare("password", tok))
|
||||
- state_password = 1;
|
||||
- else if(strcasecompare("machine", tok)) {
|
||||
- /* ok, there's machine here go => */
|
||||
- state = HOSTFOUND;
|
||||
- state_our_login = FALSE;
|
||||
+ password_alloc = TRUE;
|
||||
}
|
||||
- break;
|
||||
- } /* switch (state) */
|
||||
- tok = ++tok_end;
|
||||
- }
|
||||
- } /* while Curl_get_line() */
|
||||
+ found = NONE;
|
||||
+ }
|
||||
+ else if(strcasecompare("login", tok))
|
||||
+ found = LOGIN;
|
||||
+ else if(strcasecompare("password", tok))
|
||||
+ found = PASSWORD;
|
||||
+ else if(strcasecompare("machine", tok)) {
|
||||
+ /* ok, there is machine here go => */
|
||||
+ state = HOSTFOUND;
|
||||
+ found = NONE;
|
||||
+ }
|
||||
+ break;
|
||||
+ } /* switch (state) */
|
||||
+ tok = ++tok_end;
|
||||
+ }
|
||||
+ if(!done) {
|
||||
+ char *nl = NULL;
|
||||
+ if(tok)
|
||||
+ nl = strchr(tok, '\n');
|
||||
+ if(!nl)
|
||||
+ break;
|
||||
+ /* point to next line */
|
||||
+ netrcbuffer = &nl[1];
|
||||
+ }
|
||||
+ } /* while !done */
|
||||
|
||||
out:
|
||||
- Curl_dyn_free(&buf);
|
||||
- if(!retcode) {
|
||||
- /* success */
|
||||
- if(login_alloc) {
|
||||
- if(*loginp)
|
||||
- free(*loginp);
|
||||
- *loginp = login;
|
||||
- }
|
||||
- if(password_alloc) {
|
||||
- if(*passwordp)
|
||||
- free(*passwordp);
|
||||
- *passwordp = password;
|
||||
- }
|
||||
+ Curl_dyn_free(&token);
|
||||
+ if(!retcode) {
|
||||
+ /* success */
|
||||
+ if(login_alloc) {
|
||||
+ free(*loginp);
|
||||
+ *loginp = login;
|
||||
}
|
||||
- else {
|
||||
- if(login_alloc)
|
||||
- free(login);
|
||||
- if(password_alloc)
|
||||
- free(password);
|
||||
+ if(password_alloc) {
|
||||
+ free(*passwordp);
|
||||
+ *passwordp = password;
|
||||
}
|
||||
- fclose(file);
|
||||
+ }
|
||||
+ else {
|
||||
+ Curl_dyn_free(filebuf);
|
||||
+ if(login_alloc)
|
||||
+ free(login);
|
||||
+ if(password_alloc)
|
||||
+ free(password);
|
||||
}
|
||||
|
||||
return retcode;
|
||||
@@ -280,7 +322,8 @@ out:
|
||||
* *loginp and *passwordp MUST be allocated if they aren't NULL when passed
|
||||
* in.
|
||||
*/
|
||||
-int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
|
||||
+int Curl_parsenetrc(struct store_netrc *store, const char *host,
|
||||
+ char **loginp, char **passwordp,
|
||||
char *netrcfile)
|
||||
{
|
||||
int retcode = 1;
|
||||
@@ -329,7 +372,7 @@ int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
|
||||
free(homea);
|
||||
return -1;
|
||||
}
|
||||
- retcode = parsenetrc(host, loginp, passwordp, filealloc);
|
||||
+ retcode = parsenetrc(store, host, loginp, passwordp, filealloc);
|
||||
free(filealloc);
|
||||
#ifdef WIN32
|
||||
if(retcode == NETRC_FILE_MISSING) {
|
||||
@@ -339,15 +382,25 @@ int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
|
||||
free(homea);
|
||||
return -1;
|
||||
}
|
||||
- retcode = parsenetrc(host, loginp, passwordp, filealloc);
|
||||
+ retcode = parsenetrc(store, host, loginp, passwordp, filealloc);
|
||||
free(filealloc);
|
||||
}
|
||||
#endif
|
||||
free(homea);
|
||||
}
|
||||
else
|
||||
- retcode = parsenetrc(host, loginp, passwordp, netrcfile);
|
||||
+ retcode = parsenetrc(store, host, loginp, passwordp, netrcfile);
|
||||
return retcode;
|
||||
}
|
||||
|
||||
+void Curl_netrc_init(struct store_netrc *s)
|
||||
+{
|
||||
+ Curl_dyn_init(&s->filebuf, MAX_NETRC_FILE);
|
||||
+ s->loaded = FALSE;
|
||||
+}
|
||||
+void Curl_netrc_cleanup(struct store_netrc *s)
|
||||
+{
|
||||
+ Curl_dyn_free(&s->filebuf);
|
||||
+ s->loaded = FALSE;
|
||||
+}
|
||||
#endif
|
||||
diff --git a/lib/netrc.h b/lib/netrc.h
|
||||
index 37c95db5e..0ef9ff78e 100644
|
||||
--- a/lib/netrc.h
|
||||
+++ b/lib/netrc.h
|
||||
@@ -26,9 +26,19 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
#ifndef CURL_DISABLE_NETRC
|
||||
+#include "dynbuf.h"
|
||||
+
|
||||
+struct store_netrc {
|
||||
+ struct dynbuf filebuf;
|
||||
+ char *filename;
|
||||
+ BIT(loaded);
|
||||
+};
|
||||
+
|
||||
+void Curl_netrc_init(struct store_netrc *s);
|
||||
+void Curl_netrc_cleanup(struct store_netrc *s);
|
||||
|
||||
/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
|
||||
-int Curl_parsenetrc(const char *host, char **loginp,
|
||||
+int Curl_parsenetrc(struct store_netrc *s, const char *host, char **loginp,
|
||||
char **passwordp, char *filename);
|
||||
/* Assume: (*passwordp)[0]=0, host[0] != 0.
|
||||
* If (*loginp)[0] = 0, search for login and password within a machine
|
||||
@@ -38,6 +48,8 @@ int Curl_parsenetrc(const char *host, char **loginp,
|
||||
#else
|
||||
/* disabled */
|
||||
#define Curl_parsenetrc(a,b,c,d,e,f) 1
|
||||
+#define Curl_netrc_init(x)
|
||||
+#define Curl_netrc_cleanup(x)
|
||||
#endif
|
||||
|
||||
#endif /* HEADER_CURL_NETRC_H */
|
||||
diff --git a/lib/url.c b/lib/url.c
|
||||
index a59cb0e34..45745bc60 100644
|
||||
--- a/lib/url.c
|
||||
+++ b/lib/url.c
|
||||
@@ -338,6 +338,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
|
||||
Curl_wildcard_dtor(&data->wildcard);
|
||||
Curl_freeset(data);
|
||||
Curl_headers_cleanup(data);
|
||||
+ Curl_netrc_cleanup(&data->state.netrc);
|
||||
free(data);
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -545,6 +546,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
|
||||
|
||||
data->progress.flags |= PGRS_HIDE;
|
||||
data->state.current_speed = -1; /* init to negative == impossible */
|
||||
+ Curl_netrc_init(&data->state.netrc);
|
||||
}
|
||||
|
||||
if(result) {
|
||||
@@ -2689,7 +2691,7 @@ static CURLcode override_login(struct Curl_easy *data,
|
||||
url_provided = TRUE;
|
||||
}
|
||||
|
||||
- ret = Curl_parsenetrc(conn->host.name,
|
||||
+ ret = Curl_parsenetrc(&data->state.netrc, conn->host.name,
|
||||
userp, passwdp,
|
||||
data->set.str[STRING_NETRC_FILE]);
|
||||
if(ret > 0) {
|
||||
diff --git a/lib/urldata.h b/lib/urldata.h
|
||||
index 4e0d6ef98..6aa26237d 100644
|
||||
--- a/lib/urldata.h
|
||||
+++ b/lib/urldata.h
|
||||
@@ -163,6 +163,7 @@ typedef unsigned int curl_prot_t;
|
||||
#include "splay.h"
|
||||
#include "dynbuf.h"
|
||||
#include "dynhds.h"
|
||||
+#include "netrc.h"
|
||||
|
||||
/* return the count of bytes sent, or -1 on error */
|
||||
typedef ssize_t (Curl_send)(struct Curl_easy *data, /* transfer */
|
||||
@@ -1313,6 +1314,10 @@ struct UrlState {
|
||||
CURLcode hresult; /* used to pass return codes back from hyper callbacks */
|
||||
#endif
|
||||
|
||||
+#ifndef CURL_DISABLE_NETRC
|
||||
+ struct store_netrc netrc;
|
||||
+#endif
|
||||
+
|
||||
/* Dynamically allocated strings, MUST be freed before this struct is
|
||||
killed. */
|
||||
struct dynamically_allocated_data {
|
||||
diff --git a/tests/unit/unit1304.c b/tests/unit/unit1304.c
|
||||
index 2171c0736..238d3c0f7 100644
|
||||
--- a/tests/unit/unit1304.c
|
||||
+++ b/tests/unit/unit1304.c
|
||||
@@ -49,17 +49,22 @@ static void unit_stop(void)
|
||||
}
|
||||
|
||||
UNITTEST_START
|
||||
+{
|
||||
int result;
|
||||
+ struct store_netrc store;
|
||||
|
||||
/*
|
||||
* Test a non existent host in our netrc file.
|
||||
*/
|
||||
- result = Curl_parsenetrc("test.example.com", &login, &password, arg);
|
||||
+ Curl_netrc_init(&store);
|
||||
+ result = Curl_parsenetrc(&store,
|
||||
+ "test.example.com", &login, &password, arg);
|
||||
fail_unless(result == 1, "Host not found should return 1");
|
||||
abort_unless(password != NULL, "returned NULL!");
|
||||
fail_unless(password[0] == 0, "password should not have been changed");
|
||||
abort_unless(login != NULL, "returned NULL!");
|
||||
fail_unless(login[0] == 0, "login should not have been changed");
|
||||
+ Curl_netrc_cleanup(&store);
|
||||
|
||||
/*
|
||||
* Test a non existent login in our netrc file.
|
||||
@@ -67,13 +72,16 @@ UNITTEST_START
|
||||
free(login);
|
||||
login = strdup("me");
|
||||
abort_unless(login != NULL, "returned NULL!");
|
||||
- result = Curl_parsenetrc("example.com", &login, &password, arg);
|
||||
+ Curl_netrc_init(&store);
|
||||
+ result = Curl_parsenetrc(&store,
|
||||
+ "example.com", &login, &password, arg);
|
||||
fail_unless(result == 0, "Host should have been found");
|
||||
abort_unless(password != NULL, "returned NULL!");
|
||||
fail_unless(password[0] == 0, "password should not have been changed");
|
||||
abort_unless(login != NULL, "returned NULL!");
|
||||
fail_unless(strncmp(login, "me", 2) == 0,
|
||||
"login should not have been changed");
|
||||
+ Curl_netrc_cleanup(&store);
|
||||
|
||||
/*
|
||||
* Test a non existent login and host in our netrc file.
|
||||
@@ -81,13 +89,16 @@ UNITTEST_START
|
||||
free(login);
|
||||
login = strdup("me");
|
||||
abort_unless(login != NULL, "returned NULL!");
|
||||
- result = Curl_parsenetrc("test.example.com", &login, &password, arg);
|
||||
+ Curl_netrc_init(&store);
|
||||
+ result = Curl_parsenetrc(&store,
|
||||
+ "test.example.com", &login, &password, arg);
|
||||
fail_unless(result == 1, "Host not found should return 1");
|
||||
abort_unless(password != NULL, "returned NULL!");
|
||||
fail_unless(password[0] == 0, "password should not have been changed");
|
||||
abort_unless(login != NULL, "returned NULL!");
|
||||
fail_unless(strncmp(login, "me", 2) == 0,
|
||||
"login should not have been changed");
|
||||
+ Curl_netrc_cleanup(&store);
|
||||
|
||||
/*
|
||||
* Test a non existent login (substring of an existing one) in our
|
||||
@@ -96,13 +107,16 @@ UNITTEST_START
|
||||
free(login);
|
||||
login = strdup("admi");
|
||||
abort_unless(login != NULL, "returned NULL!");
|
||||
- result = Curl_parsenetrc("example.com", &login, &password, arg);
|
||||
+ Curl_netrc_init(&store);
|
||||
+ result = Curl_parsenetrc(&store,
|
||||
+ "example.com", &login, &password, arg);
|
||||
fail_unless(result == 0, "Host should have been found");
|
||||
abort_unless(password != NULL, "returned NULL!");
|
||||
fail_unless(password[0] == 0, "password should not have been changed");
|
||||
abort_unless(login != NULL, "returned NULL!");
|
||||
fail_unless(strncmp(login, "admi", 4) == 0,
|
||||
"login should not have been changed");
|
||||
+ Curl_netrc_cleanup(&store);
|
||||
|
||||
/*
|
||||
* Test a non existent login (superstring of an existing one)
|
||||
@@ -111,13 +125,16 @@ UNITTEST_START
|
||||
free(login);
|
||||
login = strdup("adminn");
|
||||
abort_unless(login != NULL, "returned NULL!");
|
||||
- result = Curl_parsenetrc("example.com", &login, &password, arg);
|
||||
+ Curl_netrc_init(&store);
|
||||
+ result = Curl_parsenetrc(&store,
|
||||
+ "example.com", &login, &password, arg);
|
||||
fail_unless(result == 0, "Host should have been found");
|
||||
abort_unless(password != NULL, "returned NULL!");
|
||||
fail_unless(password[0] == 0, "password should not have been changed");
|
||||
abort_unless(login != NULL, "returned NULL!");
|
||||
fail_unless(strncmp(login, "adminn", 6) == 0,
|
||||
"login should not have been changed");
|
||||
+ Curl_netrc_cleanup(&store);
|
||||
|
||||
/*
|
||||
* Test for the first existing host in our netrc file
|
||||
@@ -126,13 +143,16 @@ UNITTEST_START
|
||||
free(login);
|
||||
login = strdup("");
|
||||
abort_unless(login != NULL, "returned NULL!");
|
||||
- result = Curl_parsenetrc("example.com", &login, &password, arg);
|
||||
+ Curl_netrc_init(&store);
|
||||
+ result = Curl_parsenetrc(&store,
|
||||
+ "example.com", &login, &password, arg);
|
||||
fail_unless(result == 0, "Host should have been found");
|
||||
abort_unless(password != NULL, "returned NULL!");
|
||||
fail_unless(strncmp(password, "passwd", 6) == 0,
|
||||
"password should be 'passwd'");
|
||||
abort_unless(login != NULL, "returned NULL!");
|
||||
fail_unless(strncmp(login, "admin", 5) == 0, "login should be 'admin'");
|
||||
+ Curl_netrc_cleanup(&store);
|
||||
|
||||
/*
|
||||
* Test for the first existing host in our netrc file
|
||||
@@ -141,13 +161,16 @@ UNITTEST_START
|
||||
free(password);
|
||||
password = strdup("");
|
||||
abort_unless(password != NULL, "returned NULL!");
|
||||
- result = Curl_parsenetrc("example.com", &login, &password, arg);
|
||||
+ Curl_netrc_init(&store);
|
||||
+ result = Curl_parsenetrc(&store,
|
||||
+ "example.com", &login, &password, arg);
|
||||
fail_unless(result == 0, "Host should have been found");
|
||||
abort_unless(password != NULL, "returned NULL!");
|
||||
fail_unless(strncmp(password, "passwd", 6) == 0,
|
||||
"password should be 'passwd'");
|
||||
abort_unless(login != NULL, "returned NULL!");
|
||||
fail_unless(strncmp(login, "admin", 5) == 0, "login should be 'admin'");
|
||||
+ Curl_netrc_cleanup(&store);
|
||||
|
||||
/*
|
||||
* Test for the second existing host in our netrc file
|
||||
@@ -159,13 +182,16 @@ UNITTEST_START
|
||||
free(login);
|
||||
login = strdup("");
|
||||
abort_unless(login != NULL, "returned NULL!");
|
||||
- result = Curl_parsenetrc("curl.example.com", &login, &password, arg);
|
||||
+ Curl_netrc_init(&store);
|
||||
+ result = Curl_parsenetrc(&store,
|
||||
+ "curl.example.com", &login, &password, arg);
|
||||
fail_unless(result == 0, "Host should have been found");
|
||||
abort_unless(password != NULL, "returned NULL!");
|
||||
fail_unless(strncmp(password, "none", 4) == 0,
|
||||
"password should be 'none'");
|
||||
abort_unless(login != NULL, "returned NULL!");
|
||||
fail_unless(strncmp(login, "none", 4) == 0, "login should be 'none'");
|
||||
+ Curl_netrc_cleanup(&store);
|
||||
|
||||
/*
|
||||
* Test for the second existing host in our netrc file
|
||||
@@ -174,14 +200,18 @@ UNITTEST_START
|
||||
free(password);
|
||||
password = strdup("");
|
||||
abort_unless(password != NULL, "returned NULL!");
|
||||
- result = Curl_parsenetrc("curl.example.com", &login, &password, arg);
|
||||
+ Curl_netrc_init(&store);
|
||||
+ result = Curl_parsenetrc(&store,
|
||||
+ "curl.example.com", &login, &password, arg);
|
||||
fail_unless(result == 0, "Host should have been found");
|
||||
abort_unless(password != NULL, "returned NULL!");
|
||||
fail_unless(strncmp(password, "none", 4) == 0,
|
||||
"password should be 'none'");
|
||||
abort_unless(login != NULL, "returned NULL!");
|
||||
fail_unless(strncmp(login, "none", 4) == 0, "login should be 'none'");
|
||||
+ Curl_netrc_cleanup(&store);
|
||||
|
||||
+}
|
||||
UNITTEST_STOP
|
||||
|
||||
#else
|
||||
--
|
||||
2.33.0
|
||||
|
||||
349
backport-CVE-2024-11053-pre3.patch
Normal file
349
backport-CVE-2024-11053-pre3.patch
Normal file
@ -0,0 +1,349 @@
|
||||
From 9bee39bfed2c413b4cc4eb306a57ac92a1854907 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Stenberg <daniel@haxx.se>
|
||||
Date: Sat, 12 Oct 2024 23:54:39 +0200
|
||||
Subject: [PATCH] url: use same credentials on redirect
|
||||
|
||||
Previously it could lose the username and only use the password.
|
||||
|
||||
Added test 998 and 999 to verify.
|
||||
|
||||
Reported-by: Tobias Bora
|
||||
Fixes #15262
|
||||
Closes #15282
|
||||
|
||||
Conflict:context adapt
|
||||
Reference:https://github.com/curl/curl/commit/9bee39bfed2c413b4cc4eb306a57ac92a1854907
|
||||
---
|
||||
lib/transfer.c | 3 +
|
||||
lib/url.c | 19 ++++---
|
||||
lib/urldata.h | 9 ++-
|
||||
tests/data/Makefile.inc | 14 +++++++-------
|
||||
tests/data/test998 | 92 ++++++++++++++++++++++++++++++
|
||||
tests/data/test999 | 81 ++++++++++++++++++++++++++
|
||||
6 files changed, 195 insertions(+), 11 deletions(-)
|
||||
create mode 100644 tests/data/test998
|
||||
create mode 100644 tests/data/test999
|
||||
|
||||
diff --git a/lib/transfer.c b/lib/transfer.c
|
||||
index 79d648cab..3a9239254 100644
|
||||
--- a/lib/transfer.c
|
||||
+++ b/lib/transfer.c
|
||||
@@ -679,6 +679,9 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
+ if(data->set.str[STRING_USERNAME] ||
|
||||
+ data->set.str[STRING_PASSWORD])
|
||||
+ data->state.creds_from = CREDS_OPTION;
|
||||
if(!result)
|
||||
result = Curl_setstropt(&data->state.aptr.user,
|
||||
data->set.str[STRING_USERNAME]);
|
||||
diff --git a/lib/url.c b/lib/url.c
|
||||
index 45745bc60..261f61d8d 100644
|
||||
--- a/lib/url.c
|
||||
+++ b/lib/url.c
|
||||
@@ -1860,10 +1860,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
|
||||
return result;
|
||||
|
||||
/*
|
||||
- * User name and password set with their own options override the
|
||||
- * credentials possibly set in the URL.
|
||||
+ * username and password set with their own options override the credentials
|
||||
+ * possibly set in the URL, but netrc does not.
|
||||
*/
|
||||
- if(!data->set.str[STRING_PASSWORD]) {
|
||||
+ if(!data->state.aptr.passwd || (data->state.creds_from != CREDS_OPTION)) {
|
||||
uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
|
||||
if(!uc) {
|
||||
char *decoded;
|
||||
@@ -1876,12 +1876,13 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
|
||||
result = Curl_setstropt(&data->state.aptr.passwd, decoded);
|
||||
if(result)
|
||||
return result;
|
||||
+ data->state.creds_from = CREDS_URL;
|
||||
}
|
||||
else if(uc != CURLUE_NO_PASSWORD)
|
||||
return Curl_uc_to_curlcode(uc);
|
||||
}
|
||||
|
||||
- if(!data->set.str[STRING_USERNAME]) {
|
||||
+ if(!data->state.aptr.user || (data->state.creds_from != CREDS_OPTION)) {
|
||||
/* we don't use the URL API's URL decoder option here since it rejects
|
||||
control codes and we want to allow them for some schemes in the user
|
||||
and password fields */
|
||||
@@ -1895,13 +1896,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
|
||||
return result;
|
||||
conn->user = decoded;
|
||||
result = Curl_setstropt(&data->state.aptr.user, decoded);
|
||||
+ data->state.creds_from = CREDS_URL;
|
||||
}
|
||||
else if(uc != CURLUE_NO_USER)
|
||||
return Curl_uc_to_curlcode(uc);
|
||||
- else if(data->state.aptr.passwd) {
|
||||
- /* no user was set but a password, set a blank user */
|
||||
- result = Curl_setstropt(&data->state.aptr.user, "");
|
||||
- }
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
@@ -2685,7 +2683,8 @@ static CURLcode override_login(struct Curl_easy *data,
|
||||
int ret;
|
||||
bool url_provided = FALSE;
|
||||
|
||||
- if(data->state.aptr.user) {
|
||||
+ if(data->state.aptr.user &&
|
||||
+ (data->state.creds_from != CREDS_NETRC)) {
|
||||
/* there was a user name in the URL. Use the URL decoded version */
|
||||
userp = &data->state.aptr.user;
|
||||
url_provided = TRUE;
|
||||
@@ -2733,6 +2732,7 @@ static CURLcode override_login(struct Curl_easy *data,
|
||||
result = Curl_setstropt(&data->state.aptr.user, *userp);
|
||||
if(result)
|
||||
return result;
|
||||
+ data->state.creds_from = CREDS_NETRC;
|
||||
}
|
||||
}
|
||||
if(data->state.aptr.user) {
|
||||
@@ -2750,6 +2750,7 @@ static CURLcode override_login(struct Curl_easy *data,
|
||||
CURLcode result = Curl_setstropt(&data->state.aptr.passwd, *passwdp);
|
||||
if(result)
|
||||
return result;
|
||||
+ data->state.creds_from = CREDS_NETRC;
|
||||
}
|
||||
if(data->state.aptr.passwd) {
|
||||
uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD,
|
||||
diff --git a/lib/urldata.h b/lib/urldata.h
|
||||
index 6aa26237d..73f662159 100644
|
||||
--- a/lib/urldata.h
|
||||
+++ b/lib/urldata.h
|
||||
@@ -1206,6 +1206,11 @@ struct urlpieces {
|
||||
char *query;
|
||||
};
|
||||
|
||||
+#define CREDS_NONE 0
|
||||
+#define CREDS_URL 1 /* from URL */
|
||||
+#define CREDS_OPTION 2 /* set with a CURLOPT_ */
|
||||
+#define CREDS_NETRC 3 /* found in netrc */
|
||||
+
|
||||
struct UrlState {
|
||||
/* Points to the connection cache */
|
||||
struct conncache *conn_cache;
|
||||
@@ -1344,7 +1349,6 @@ struct UrlState {
|
||||
char *proxyuser;
|
||||
char *proxypasswd;
|
||||
} aptr;
|
||||
-
|
||||
unsigned char httpwant; /* when non-zero, a specific HTTP version requested
|
||||
to be used in the library's request(s) */
|
||||
unsigned char httpversion; /* the lowest HTTP version*10 reported by any
|
||||
@@ -1354,6 +1358,9 @@ struct UrlState {
|
||||
unsigned char dselect_bits; /* != 0 -> bitmask of socket events for this
|
||||
transfer overriding anything the socket may
|
||||
report */
|
||||
+ unsigned int creds_from:2; /* where is the server credentials originating
|
||||
+ from, see the CREDS_* defines above */
|
||||
+
|
||||
#ifdef CURLDEBUG
|
||||
BIT(conncache_lock);
|
||||
#endif
|
||||
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
|
||||
index 480a88208..02bf2ae25 100644
|
||||
--- a/tests/data/Makefile.inc
|
||||
+++ b/tests/data/Makefile.inc
|
||||
@@ -133,7 +133,7 @@ test961 test962 test963 test964 test965 test966 test967 test968 test969 \
|
||||
test961 test962 test963 test964 test965 test966 test967 test968 test969 \
|
||||
test970 test971 test972 test973 test974 test975 test976 test977 test978 \
|
||||
test979 test980 test981 test982 test983 test984 test985 test986 test987 \
|
||||
-test988 test989 test990 test991 \
|
||||
+test988 test989 test990 test991 test998 test999 \
|
||||
\
|
||||
test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
|
||||
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
|
||||
diff --git a/tests/data/test998 b/tests/data/test998
|
||||
new file mode 100644
|
||||
index 000000000..c3a8f5169
|
||||
--- /dev/null
|
||||
+++ b/tests/data/test998
|
||||
@@ -0,0 +1,92 @@
|
||||
+<testcase>
|
||||
+<info>
|
||||
+<keywords>
|
||||
+HTTP
|
||||
+--location-trusted
|
||||
+</keywords>
|
||||
+</info>
|
||||
+
|
||||
+#
|
||||
+# Server-side
|
||||
+<reply>
|
||||
+<data>
|
||||
+HTTP/1.1 301 redirect
|
||||
+Date: Tue, 09 Nov 2010 14:49:00 GMT
|
||||
+Server: test-server/fake
|
||||
+Content-Length: 0
|
||||
+Connection: close
|
||||
+Content-Type: text/html
|
||||
+Location: http://somewhere.else.example/a/path/%TESTNUMBER0002
|
||||
+
|
||||
+</data>
|
||||
+<data2>
|
||||
+HTTP/1.1 200 OK
|
||||
+Date: Tue, 09 Nov 2010 14:49:00 GMT
|
||||
+Content-Length: 6
|
||||
+Content-Type: text/html
|
||||
+Funny-head: yesyes
|
||||
+
|
||||
+-foo-
|
||||
+</data2>
|
||||
+
|
||||
+<datacheck>
|
||||
+HTTP/1.1 301 redirect
|
||||
+Date: Tue, 09 Nov 2010 14:49:00 GMT
|
||||
+Server: test-server/fake
|
||||
+Content-Length: 0
|
||||
+Connection: close
|
||||
+Content-Type: text/html
|
||||
+Location: http://somewhere.else.example/a/path/%TESTNUMBER0002
|
||||
+
|
||||
+HTTP/1.1 200 OK
|
||||
+Date: Tue, 09 Nov 2010 14:49:00 GMT
|
||||
+Content-Length: 6
|
||||
+Content-Type: text/html
|
||||
+Funny-head: yesyes
|
||||
+
|
||||
+-foo-
|
||||
+</datacheck>
|
||||
+
|
||||
+</reply>
|
||||
+
|
||||
+#
|
||||
+# Client-side
|
||||
+<client>
|
||||
+<features>
|
||||
+proxy
|
||||
+</features>
|
||||
+<server>
|
||||
+http
|
||||
+</server>
|
||||
+<name>
|
||||
+HTTP with auth in URL redirected to another host
|
||||
+</name>
|
||||
+<command>
|
||||
+-x %HOSTIP:%HTTPPORT http://alberto:einstein@somwhere.example/%TESTNUMBER --location-trusted
|
||||
+</command>
|
||||
+</client>
|
||||
+
|
||||
+#
|
||||
+# Verify data after the test has been "shot"
|
||||
+<verify>
|
||||
+<strip>
|
||||
+QUIT
|
||||
+</strip>
|
||||
+<protocol>
|
||||
+GET http://somwhere.example/998 HTTP/1.1
|
||||
+Host: somwhere.example
|
||||
+Authorization: Basic YWxiZXJ0bzplaW5zdGVpbg==
|
||||
+User-Agent: curl/%VERSION
|
||||
+Accept: */*
|
||||
+Proxy-Connection: Keep-Alive
|
||||
+
|
||||
+GET http://somewhere.else.example/a/path/9980002 HTTP/1.1
|
||||
+Host: somewhere.else.example
|
||||
+Authorization: Basic YWxiZXJ0bzplaW5zdGVpbg==
|
||||
+User-Agent: curl/%VERSION
|
||||
+Accept: */*
|
||||
+Proxy-Connection: Keep-Alive
|
||||
+
|
||||
+</protocol>
|
||||
+</verify>
|
||||
+</testcase>
|
||||
diff --git a/tests/data/test999 b/tests/data/test999
|
||||
new file mode 100644
|
||||
index 000000000..990a8d09a
|
||||
--- /dev/null
|
||||
+++ b/tests/data/test999
|
||||
@@ -0,0 +1,81 @@
|
||||
+<testcase>
|
||||
+<info>
|
||||
+<keywords>
|
||||
+HTTP
|
||||
+--location-trusted
|
||||
+</keywords>
|
||||
+</info>
|
||||
+
|
||||
+#
|
||||
+# Server-side
|
||||
+<reply>
|
||||
+<data nocheck="yes">
|
||||
+HTTP/1.1 200 OK
|
||||
+Date: Tue, 09 Nov 2010 14:49:00 GMT
|
||||
+Content-Length: 6
|
||||
+Content-Type: text/html
|
||||
+Funny-head: yesyes
|
||||
+
|
||||
+-foo-
|
||||
+</data>
|
||||
+
|
||||
+<datacheck>
|
||||
+HTTP/1.1 301 redirect
|
||||
+Date: Tue, 09 Nov 2010 14:49:00 GMT
|
||||
+Server: test-server/fake
|
||||
+Content-Length: 0
|
||||
+Connection: close
|
||||
+Content-Type: text/html
|
||||
+Location: http://somewhere.else.example/a/path/%TESTNUMBER0002
|
||||
+
|
||||
+HTTP/1.1 200 OK
|
||||
+Date: Tue, 09 Nov 2010 14:49:00 GMT
|
||||
+Content-Length: 6
|
||||
+Content-Type: text/html
|
||||
+Funny-head: yesyes
|
||||
+
|
||||
+-foo-
|
||||
+</datacheck>
|
||||
+
|
||||
+</reply>
|
||||
+
|
||||
+#
|
||||
+# Client-side
|
||||
+<client>
|
||||
+<features>
|
||||
+proxy
|
||||
+</features>
|
||||
+<server>
|
||||
+http
|
||||
+</server>
|
||||
+<name>
|
||||
+HTTP with auth in first URL but not second
|
||||
+</name>
|
||||
+<command>
|
||||
+-x %HOSTIP:%HTTPPORT http://alberto:einstein@somwhere.example/%TESTNUMBER http://somewhere.else.example/%TESTNUMBER
|
||||
+</command>
|
||||
+</client>
|
||||
+
|
||||
+#
|
||||
+# Verify data after the test has been "shot"
|
||||
+<verify>
|
||||
+<strip>
|
||||
+QUIT
|
||||
+</strip>
|
||||
+<protocol>
|
||||
+GET http://somwhere.example/%TESTNUMBER HTTP/1.1
|
||||
+Host: somwhere.example
|
||||
+Authorization: Basic YWxiZXJ0bzplaW5zdGVpbg==
|
||||
+User-Agent: curl/%VERSION
|
||||
+Accept: */*
|
||||
+Proxy-Connection: Keep-Alive
|
||||
+
|
||||
+GET http://somewhere.else.example/%TESTNUMBER HTTP/1.1
|
||||
+Host: somewhere.else.example
|
||||
+User-Agent: curl/%VERSION
|
||||
+Accept: */*
|
||||
+Proxy-Connection: Keep-Alive
|
||||
+
|
||||
+</protocol>
|
||||
+</verify>
|
||||
+</testcase>
|
||||
--
|
||||
2.33.0
|
||||
|
||||
223
backport-CVE-2024-11053-pre4.patch
Normal file
223
backport-CVE-2024-11053-pre4.patch
Normal file
@ -0,0 +1,223 @@
|
||||
From f5c616930b5cf148b1b2632da4f5963ff48bdf88 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Stenberg <daniel@haxx.se>
|
||||
Date: Thu, 7 Nov 2024 08:52:38 +0100
|
||||
Subject: [PATCH] duphandle: also init netrc
|
||||
|
||||
The netrc init was only done in the Curl_open, meaning that a duplicated
|
||||
handle would not get inited properly.
|
||||
|
||||
Added test 2309 to verify. It does netrc auth with a duplicated handle.
|
||||
|
||||
Regression from 3b43a05e000aa8f65bda513f733a
|
||||
|
||||
Reported-by: tranzystorekk on github
|
||||
Fixes #15496
|
||||
Closes #15503
|
||||
|
||||
Conflict:context adapt
|
||||
Reference:https://github.com/curl/curl/commit/f5c616930b5cf148b1b2632da4f5963ff48bdf88
|
||||
---
|
||||
lib/easy.c | 1 +
|
||||
tests/data/Makefile.inc | 2 ++
|
||||
tests/data/test2309 | 66 ++++++++++++++++++++++++++++++++++++++
|
||||
tests/libtest/Makefile.inc | 5 ++-
|
||||
tests/libtest/lib2309.c | 66 ++++++++++++++++++++++++++++++++++++++
|
||||
5 files changed, 139 insertions(+), 1 deletions(-)
|
||||
create mode 100644 tests/data/test2309
|
||||
create mode 100644 tests/libtest/lib2309.c
|
||||
|
||||
diff --git a/lib/easy.c b/lib/easy.c
|
||||
index d16fa8c07..ac8fab342 100644
|
||||
--- a/lib/easy.c
|
||||
+++ b/lib/easy.c
|
||||
@@ -940,6 +940,7 @@ CURL *curl_easy_duphandle(CURL *d)
|
||||
goto fail;
|
||||
|
||||
Curl_dyn_init(&outcurl->state.headerb, CURL_MAX_HTTP_HEADER);
|
||||
+ Curl_netrc_init(&outcurl->state.netrc);
|
||||
|
||||
/* the connection cache is setup on demand */
|
||||
outcurl->state.conn_cache = NULL;
|
||||
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
|
||||
index 02bf2ae25..ea5221c00 100644
|
||||
--- a/tests/data/Makefile.inc
|
||||
+++ b/tests/data/Makefile.inc
|
||||
@@ -255,6 +255,8 @@ test2100 \
|
||||
test2200 test2201 test2202 test2203 test2204 test2205 \
|
||||
\
|
||||
test2300 test2301 test2302 test2303 test2304 test2305 test2306 \
|
||||
+\
|
||||
+test2309 \
|
||||
\
|
||||
test2400 test2401 test2402 test2403 test2404 \
|
||||
\
|
||||
diff --git a/tests/data/test2309 b/tests/data/test2309
|
||||
new file mode 100644
|
||||
index 000000000..4ba78ee91
|
||||
--- /dev/null
|
||||
+++ b/tests/data/test2309
|
||||
@@ -0,0 +1,66 @@
|
||||
+<testcase>
|
||||
+<info>
|
||||
+<keywords>
|
||||
+netrc
|
||||
+HTTP
|
||||
+</keywords>
|
||||
+</info>
|
||||
+#
|
||||
+# Server-side
|
||||
+<reply>
|
||||
+<data crlf="yes" nocheck="yes">
|
||||
+HTTP/1.1 200 OK
|
||||
+Date: Tue, 09 Nov 2010 14:49:00 GMT
|
||||
+Server: test-server/fake
|
||||
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||
+ETag: "21025-dc7-39462498"
|
||||
+Accept-Ranges: bytes
|
||||
+Content-Length: 6
|
||||
+Connection: close
|
||||
+Content-Type: text/html
|
||||
+Funny-head: yesyes
|
||||
+
|
||||
+-foo-
|
||||
+</data>
|
||||
+</reply>
|
||||
+
|
||||
+#
|
||||
+# Client-side
|
||||
+<client>
|
||||
+<server>
|
||||
+http
|
||||
+</server>
|
||||
+<features>
|
||||
+proxy
|
||||
+</features>
|
||||
+
|
||||
+# Reproducing issue 15496
|
||||
+<name>
|
||||
+HTTP with .netrc using duped easy handle
|
||||
+</name>
|
||||
+<tool>
|
||||
+lib%TESTNUMBER
|
||||
+</tool>
|
||||
+<command>
|
||||
+http://github.com %LOGDIR/netrc%TESTNUMBER http://%HOSTIP:%HTTPPORT/
|
||||
+</command>
|
||||
+<file name="%LOGDIR/netrc%TESTNUMBER" >
|
||||
+
|
||||
+machine github.com
|
||||
+
|
||||
+login daniel
|
||||
+password $y$j9T$WUVjiVvDbRAWafDLs6cab1$01NX.oaZKf5lw8MR2Nk9Yaxv4CqbE0IaDF.GpGxPul1
|
||||
+</file>
|
||||
+</client>
|
||||
+
|
||||
+<verify>
|
||||
+<protocol>
|
||||
+GET http://github.com/ HTTP/1.1
|
||||
+Host: github.com
|
||||
+Authorization: Basic %b64[daniel:$y$j9T$WUVjiVvDbRAWafDLs6cab1$01NX.oaZKf5lw8MR2Nk9Yaxv4CqbE0IaDF.GpGxPul1]b64%
|
||||
+Accept: */*
|
||||
+Proxy-Connection: Keep-Alive
|
||||
+
|
||||
+</protocol>
|
||||
+</verify>
|
||||
+</testcase>
|
||||
diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
|
||||
index 339a00fc4..8f58fd642 100644
|
||||
--- a/tests/libtest/Makefile.inc
|
||||
+++ b/tests/libtest/Makefile.inc
|
||||
@@ -77,7 +77,7 @@ LIBTESTPROGS = libauthretry libntlmconnect libprereq \
|
||||
lib1945 lib1946 lib1947 lib1948 lib1955 lib1956 lib1957 lib1958 lib1959 \
|
||||
lib1960 lib1964 \
|
||||
lib1970 lib1971 lib1972 lib1973 lib1974 lib1975 \
|
||||
- lib2301 lib2302 lib2304 lib2305 lib2306 \
|
||||
+ lib2301 lib2302 lib2304 lib2305 lib2306 lib2309 \
|
||||
lib2402 lib2404 \
|
||||
lib2502 \
|
||||
lib3010 lib3025 lib3026 lib3027 \
|
||||
@@ -683,6 +683,9 @@ lib2306_LDADD = $(TESTUTIL_LIBS)
|
||||
lib2306_SOURCES = lib2306.c $(SUPPORTFILES)
|
||||
lib2306_LDADD = $(TESTUTIL_LIBS)
|
||||
|
||||
+lib2309_SOURCES = lib2309.c $(SUPPORTFILES)
|
||||
+lib2309_LDADD = $(TESTUTIL_LIBS)
|
||||
+
|
||||
lib2402_SOURCES = lib2402.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
|
||||
lib2402_LDADD = $(TESTUTIL_LIBS)
|
||||
|
||||
diff --git a/tests/libtest/lib2309.c b/tests/libtest/lib2309.c
|
||||
new file mode 100644
|
||||
index 000000000..11f1c1fbd
|
||||
--- /dev/null
|
||||
+++ b/tests/libtest/lib2309.c
|
||||
@@ -0,0 +1,66 @@
|
||||
+/***************************************************************************
|
||||
+ * _ _ ____ _
|
||||
+ * Project ___| | | | _ \| |
|
||||
+ * / __| | | | |_) | |
|
||||
+ * | (__| |_| | _ <| |___
|
||||
+ * \___|\___/|_| \_\_____|
|
||||
+ *
|
||||
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
+ *
|
||||
+ * This software is licensed as described in the file COPYING, which
|
||||
+ * you should have received as part of this distribution. The terms
|
||||
+ * are also available at https://curl.se/docs/copyright.html.
|
||||
+ *
|
||||
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
+ * copies of the Software, and permit persons to whom the Software is
|
||||
+ * furnished to do so, under the terms of the COPYING file.
|
||||
+ *
|
||||
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
+ * KIND, either express or implied.
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: curl
|
||||
+ *
|
||||
+ ***************************************************************************/
|
||||
+
|
||||
+#include "test.h"
|
||||
+#include "testtrace.h"
|
||||
+
|
||||
+#include <curl/curl.h>
|
||||
+
|
||||
+static size_t cb_ignore(char *buffer, size_t size, size_t nmemb, void *userp)
|
||||
+{
|
||||
+ (void)buffer;
|
||||
+ (void)size;
|
||||
+ (void)nmemb;
|
||||
+ (void)userp;
|
||||
+ return CURL_WRITEFUNC_ERROR;
|
||||
+}
|
||||
+
|
||||
+int test(char *URL)
|
||||
+{
|
||||
+ CURL *curl;
|
||||
+ CURL *curldupe;
|
||||
+ int res = CURLE_OK;
|
||||
+
|
||||
+ global_init(CURL_GLOBAL_ALL);
|
||||
+ curl = curl_easy_init();
|
||||
+ if(curl) {
|
||||
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cb_ignore);
|
||||
+ curl_easy_setopt(curl, CURLOPT_URL, URL);
|
||||
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
||||
+ curl_easy_setopt(curl, CURLOPT_PROXY, libtest_arg3);
|
||||
+ curl_easy_setopt(curl, CURLOPT_NETRC, (long)CURL_NETRC_REQUIRED);
|
||||
+ curl_easy_setopt(curl, CURLOPT_NETRC_FILE, libtest_arg2);
|
||||
+
|
||||
+ curldupe = curl_easy_duphandle(curl);
|
||||
+ if(curldupe) {
|
||||
+ res = curl_easy_perform(curldupe);
|
||||
+ printf("Returned %d, should be %d.\n", res, CURLE_WRITE_ERROR);
|
||||
+ fflush(stdout);
|
||||
+ curl_easy_cleanup(curldupe);
|
||||
+ }
|
||||
+ curl_easy_cleanup(curl);
|
||||
+ }
|
||||
+ curl_global_cleanup();
|
||||
+ return 0;
|
||||
+}
|
||||
--
|
||||
2.33.0
|
||||
|
||||
37
backport-CVE-2024-11053-pre5.patch
Normal file
37
backport-CVE-2024-11053-pre5.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From 0cdde0fdfbeb8c35420f6d03fa4b77ed73497694 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Stenberg <daniel@haxx.se>
|
||||
Date: Thu, 7 Nov 2024 17:03:54 +0100
|
||||
Subject: [PATCH] netrc: support large file, longer lines, longer tokens
|
||||
|
||||
Regression from 3b43a05e000aa8f6 (shipped in 8.11.0)
|
||||
|
||||
Reported-by: Moritz
|
||||
Fixes #15513
|
||||
Closes #15514
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/curl/curl/commit/0cdde0fdfbeb8c35420f6d03fa4b77ed73497694
|
||||
---
|
||||
lib/netrc.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/lib/netrc.c b/lib/netrc.c
|
||||
index c23f927ce..034c0307a 100644
|
||||
--- a/lib/netrc.c
|
||||
+++ b/lib/netrc.c
|
||||
@@ -58,9 +58,9 @@ enum found_state {
|
||||
#define NETRC_FAILED -1
|
||||
#define NETRC_SUCCESS 0
|
||||
|
||||
-#define MAX_NETRC_LINE 4096
|
||||
-#define MAX_NETRC_FILE (64*1024)
|
||||
-#define MAX_NETRC_TOKEN 128
|
||||
+#define MAX_NETRC_LINE 16384
|
||||
+#define MAX_NETRC_FILE (128*1024)
|
||||
+#define MAX_NETRC_TOKEN 4096
|
||||
|
||||
static CURLcode file2memory(const char *filename, struct dynbuf *filebuf)
|
||||
{
|
||||
--
|
||||
2.33.0
|
||||
|
||||
728
backport-CVE-2024-11053.patch
Normal file
728
backport-CVE-2024-11053.patch
Normal file
@ -0,0 +1,728 @@
|
||||
From e9b9bbac22c26cf67316fa8e6c6b9e831af31949 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Stenberg <daniel@haxx.se>
|
||||
Date: Fri, 15 Nov 2024 11:06:36 +0100
|
||||
Subject: [PATCH] netrc: address several netrc parser flaws
|
||||
|
||||
- make sure that a match that returns a username also returns a
|
||||
password, that should be blank if no password is found
|
||||
|
||||
- fix handling of multiple logins for same host where the password/login
|
||||
order might be reversed.
|
||||
|
||||
- reject credentials provided in the .netrc if they contain ASCII control
|
||||
codes - if the used protocol does not support such (like HTTP and WS do)
|
||||
|
||||
Reported-by: Harry Sintonen
|
||||
|
||||
Add test 478, 479 and 480 to verify. Updated unit 1304.
|
||||
|
||||
Closes #15586
|
||||
|
||||
Conflict:context adapt
|
||||
Reference:https://github.com/curl/curl/e9b9bbac22c26cf67316fa8e6c6b9e831af31949
|
||||
---
|
||||
lib/netrc.c | 113 +++++++++++++++++++++++------------------
|
||||
lib/url.c | 60 +++++++++++++++-------
|
||||
tests/data/Makefile.inc | 1 +
|
||||
tests/data/test478 | 73 ++++++++++++++++++++++++++
|
||||
tests/data/test479 | 107 ++++++++++++++++++++++++++++++++++++++
|
||||
tests/data/test480 | 38 ++++++++++++++
|
||||
tests/unit/unit1304.c | 75 ++++++++-------------------
|
||||
7 files changed, 345 insertions(+), 122 deletions(-)
|
||||
create mode 100644 tests/data/test478
|
||||
create mode 100644 tests/data/test479
|
||||
create mode 100644 tests/data/test480
|
||||
|
||||
diff --git a/lib/netrc.c b/lib/netrc.c
|
||||
index 034c0307a..e787a6ffc 100644
|
||||
--- a/lib/netrc.c
|
||||
+++ b/lib/netrc.c
|
||||
@@ -54,6 +54,9 @@ enum found_state {
|
||||
PASSWORD
|
||||
};
|
||||
|
||||
+#define FOUND_LOGIN 1
|
||||
+#define FOUND_PASSWORD 2
|
||||
+
|
||||
#define NETRC_FILE_MISSING 1
|
||||
#define NETRC_FAILED -1
|
||||
#define NETRC_SUCCESS 0
|
||||
@@ -94,24 +97,24 @@ done:
|
||||
*/
|
||||
static int parsenetrc(struct store_netrc *store,
|
||||
const char *host,
|
||||
- char **loginp,
|
||||
+ char **loginp, /* might point to a username */
|
||||
char **passwordp,
|
||||
const char *netrcfile)
|
||||
{
|
||||
int retcode = NETRC_FILE_MISSING;
|
||||
char *login = *loginp;
|
||||
- char *password = *passwordp;
|
||||
- bool specific_login = (login && *login != 0);
|
||||
- bool login_alloc = FALSE;
|
||||
- bool password_alloc = FALSE;
|
||||
+ char *password = NULL;
|
||||
+ bool specific_login = login; /* points to something */
|
||||
enum host_lookup_state state = NOTHING;
|
||||
- enum found_state found = NONE;
|
||||
- bool our_login = TRUE; /* With specific_login, found *our* login name (or
|
||||
- login-less line) */
|
||||
+ enum found_state keyword = NONE;
|
||||
+ unsigned char found = 0; /* login + password found bits, as they can come in
|
||||
+ any order */
|
||||
+ bool our_login = FALSE; /* found our login name */
|
||||
bool done = FALSE;
|
||||
char *netrcbuffer;
|
||||
struct dynbuf token;
|
||||
struct dynbuf *filebuf = &store->filebuf;
|
||||
+ DEBUGASSERT(!*passwordp);
|
||||
Curl_dyn_init(&token, MAX_NETRC_TOKEN);
|
||||
|
||||
if(!store->loaded) {
|
||||
@@ -124,7 +127,7 @@ static int parsenetrc(struct store_netrc *store,
|
||||
|
||||
while(!done) {
|
||||
char *tok = netrcbuffer;
|
||||
- while(tok) {
|
||||
+ while(tok && !done) {
|
||||
char *tok_end;
|
||||
bool quoted;
|
||||
Curl_dyn_reset(&token);
|
||||
@@ -198,11 +201,6 @@ static int parsenetrc(struct store_netrc *store,
|
||||
}
|
||||
}
|
||||
|
||||
- if((login && *login) && (password && *password)) {
|
||||
- done = TRUE;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
tok = Curl_dyn_ptr(&token);
|
||||
|
||||
switch(state) {
|
||||
@@ -212,11 +210,18 @@ static int parsenetrc(struct store_netrc *store,
|
||||
contents begin with the next .netrc line and continue until a
|
||||
null line (consecutive new-line characters) is encountered. */
|
||||
state = MACDEF;
|
||||
- else if(strcasecompare("machine", tok))
|
||||
+ else if(strcasecompare("machine", tok)) {
|
||||
/* the next tok is the machine name, this is in itself the delimiter
|
||||
that starts the stuff entered for this machine, after this we
|
||||
need to search for 'login' and 'password'. */
|
||||
state = HOSTFOUND;
|
||||
+ keyword = NONE;
|
||||
+ found = 0;
|
||||
+ our_login = FALSE;
|
||||
+ Curl_safefree(password);
|
||||
+ if(!specific_login)
|
||||
+ Curl_safefree(login);
|
||||
+ }
|
||||
else if(strcasecompare("default", tok)) {
|
||||
state = HOSTVALID;
|
||||
retcode = NETRC_SUCCESS; /* we did find our host */
|
||||
@@ -238,44 +243,54 @@ static int parsenetrc(struct store_netrc *store,
|
||||
break;
|
||||
case HOSTVALID:
|
||||
/* we are now parsing sub-keywords concerning "our" host */
|
||||
- if(found == LOGIN) {
|
||||
- if(specific_login) {
|
||||
+ if(keyword == LOGIN) {
|
||||
+ if(specific_login)
|
||||
our_login = !Curl_timestrcmp(login, tok);
|
||||
- }
|
||||
- else if(!login || Curl_timestrcmp(login, tok)) {
|
||||
- if(login_alloc)
|
||||
- free(login);
|
||||
+ else {
|
||||
+ our_login = TRUE;
|
||||
+ free(login);
|
||||
login = strdup(tok);
|
||||
if(!login) {
|
||||
retcode = NETRC_FAILED; /* allocation failed */
|
||||
goto out;
|
||||
}
|
||||
- login_alloc = TRUE;
|
||||
}
|
||||
- found = NONE;
|
||||
+ found |= FOUND_LOGIN;
|
||||
+ keyword = NONE;
|
||||
}
|
||||
- else if(found == PASSWORD) {
|
||||
- if((our_login || !specific_login) &&
|
||||
- (!password || Curl_timestrcmp(password, tok))) {
|
||||
- if(password_alloc)
|
||||
- free(password);
|
||||
- password = strdup(tok);
|
||||
- if(!password) {
|
||||
- retcode = NETRC_FAILED; /* allocation failed */
|
||||
- goto out;
|
||||
- }
|
||||
- password_alloc = TRUE;
|
||||
+ else if(keyword == PASSWORD) {
|
||||
+ free(password);
|
||||
+ password = strdup(tok);
|
||||
+ if(!password) {
|
||||
+ retcode = NETRC_FAILED; /* allocation failed */
|
||||
+ goto out;
|
||||
}
|
||||
- found = NONE;
|
||||
+ found |= FOUND_PASSWORD;
|
||||
+ keyword = NONE;
|
||||
}
|
||||
else if(strcasecompare("login", tok))
|
||||
- found = LOGIN;
|
||||
+ keyword = LOGIN;
|
||||
else if(strcasecompare("password", tok))
|
||||
- found = PASSWORD;
|
||||
+ keyword = PASSWORD;
|
||||
else if(strcasecompare("machine", tok)) {
|
||||
- /* ok, there is machine here go => */
|
||||
+ /* a new machine here */
|
||||
state = HOSTFOUND;
|
||||
- found = NONE;
|
||||
+ keyword = NONE;
|
||||
+ found = 0;
|
||||
+ Curl_safefree(password);
|
||||
+ if(!specific_login)
|
||||
+ Curl_safefree(login);
|
||||
+ }
|
||||
+ else if(strcasecompare("default", tok)) {
|
||||
+ state = HOSTVALID;
|
||||
+ retcode = NETRC_SUCCESS; /* we did find our host */
|
||||
+ Curl_safefree(password);
|
||||
+ if(!specific_login)
|
||||
+ Curl_safefree(login);
|
||||
+ }
|
||||
+ if((found == (FOUND_PASSWORD|FOUND_LOGIN)) && our_login) {
|
||||
+ done = TRUE;
|
||||
+ break;
|
||||
}
|
||||
break;
|
||||
} /* switch (state) */
|
||||
@@ -294,23 +309,23 @@ static int parsenetrc(struct store_netrc *store,
|
||||
|
||||
out:
|
||||
Curl_dyn_free(&token);
|
||||
+ if(!retcode && !password && our_login) {
|
||||
+ /* success without a password, set a blank one */
|
||||
+ password = strdup("");
|
||||
+ if(!password)
|
||||
+ retcode = 1; /* out of memory */
|
||||
+ }
|
||||
if(!retcode) {
|
||||
/* success */
|
||||
- if(login_alloc) {
|
||||
- free(*loginp);
|
||||
+ if(!specific_login)
|
||||
*loginp = login;
|
||||
- }
|
||||
- if(password_alloc) {
|
||||
- free(*passwordp);
|
||||
- *passwordp = password;
|
||||
- }
|
||||
+ *passwordp = password;
|
||||
}
|
||||
else {
|
||||
Curl_dyn_free(filebuf);
|
||||
- if(login_alloc)
|
||||
+ if(!specific_login)
|
||||
free(login);
|
||||
- if(password_alloc)
|
||||
- free(password);
|
||||
+ free(password);
|
||||
}
|
||||
|
||||
return retcode;
|
||||
diff --git a/lib/url.c b/lib/url.c
|
||||
index f9bb05f79..436edd891 100644
|
||||
--- a/lib/url.c
|
||||
+++ b/lib/url.c
|
||||
@@ -2651,6 +2651,17 @@ static CURLcode parse_remote_port(struct Curl_easy *data,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
+static bool str_has_ctrl(const char *input)
|
||||
+{
|
||||
+ const unsigned char *str = (const unsigned char *)input;
|
||||
+ while(*str) {
|
||||
+ if(*str < 0x20)
|
||||
+ return TRUE;
|
||||
+ str++;
|
||||
+ }
|
||||
+ return FALSE;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Override the login details from the URL with that in the CURLOPT_USERPWD
|
||||
* option or a .netrc file, if applicable.
|
||||
@@ -2682,29 +2693,40 @@ static CURLcode override_login(struct Curl_easy *data,
|
||||
|
||||
if(data->state.aptr.user &&
|
||||
(data->state.creds_from != CREDS_NETRC)) {
|
||||
- /* there was a user name in the URL. Use the URL decoded version */
|
||||
+ /* there was a username with a length in the URL. Use the URL decoded
|
||||
+ version */
|
||||
userp = &data->state.aptr.user;
|
||||
url_provided = TRUE;
|
||||
}
|
||||
|
||||
- ret = Curl_parsenetrc(&data->state.netrc, conn->host.name,
|
||||
- userp, passwdp,
|
||||
- data->set.str[STRING_NETRC_FILE]);
|
||||
- if(ret > 0) {
|
||||
- infof(data, "Couldn't find host %s in the %s file; using defaults",
|
||||
- conn->host.name,
|
||||
- (data->set.str[STRING_NETRC_FILE] ?
|
||||
- data->set.str[STRING_NETRC_FILE] : ".netrc"));
|
||||
- }
|
||||
- else if(ret < 0) {
|
||||
- failf(data, ".netrc parser error");
|
||||
- return CURLE_READ_ERROR;
|
||||
- }
|
||||
- else {
|
||||
- /* set bits.netrc TRUE to remember that we got the name from a .netrc
|
||||
- file, so that it is safe to use even if we followed a Location: to a
|
||||
- different host or similar. */
|
||||
- conn->bits.netrc = TRUE;
|
||||
+ if(!*passwdp) {
|
||||
+ ret = Curl_parsenetrc(&data->state.netrc, conn->host.name,
|
||||
+ userp, passwdp,
|
||||
+ data->set.str[STRING_NETRC_FILE]);
|
||||
+ if(ret > 0) {
|
||||
+ infof(data, "Couldn't find host %s in the %s file; using defaults",
|
||||
+ conn->host.name,
|
||||
+ (data->set.str[STRING_NETRC_FILE] ?
|
||||
+ data->set.str[STRING_NETRC_FILE] : ".netrc"));
|
||||
+ }
|
||||
+ else if(ret < 0) {
|
||||
+ failf(data, ".netrc parser error");
|
||||
+ return CURLE_READ_ERROR;
|
||||
+ }
|
||||
+ else {
|
||||
+ if(!(conn->handler->flags&PROTOPT_USERPWDCTRL)) {
|
||||
+ /* if the protocol can't handle control codes in credentials, make
|
||||
+ sure there are none */
|
||||
+ if(str_has_ctrl(*userp) || str_has_ctrl(*passwdp)) {
|
||||
+ failf(data, "control code detected in .netrc credentials");
|
||||
+ return CURLE_READ_ERROR;
|
||||
+ }
|
||||
+ }
|
||||
+ /* set bits.netrc TRUE to remember that we got the name from a .netrc
|
||||
+ file, so that it is safe to use even if we followed a Location: to a
|
||||
+ different host or similar. */
|
||||
+ conn->bits.netrc = TRUE;
|
||||
+ }
|
||||
}
|
||||
if(url_provided) {
|
||||
Curl_safefree(conn->user);
|
||||
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
|
||||
index ea5221c00..53f62c6e2 100644
|
||||
--- a/tests/data/Makefile.inc
|
||||
+++ b/tests/data/Makefile.inc
|
||||
@@ -77,6 +77,7 @@ test435 test436 test437 test438 test439 test440 test441 test442 test443 \
|
||||
test435 test436 test437 test438 test439 test440 test441 test442 test443 \
|
||||
test444 test445 test446 test447 test448 test449 test450 test451 test452 \
|
||||
test453 test454 test455 test456 test457 test458 \
|
||||
+test478 test479 test480 \
|
||||
\
|
||||
test490 test491 test492 test493 test494 test495 test496 test497 test498 \
|
||||
\
|
||||
diff --git a/tests/data/test478 b/tests/data/test478
|
||||
new file mode 100644
|
||||
index 000000000..6558363f5
|
||||
--- /dev/null
|
||||
+++ b/tests/data/test478
|
||||
@@ -0,0 +1,73 @@
|
||||
+<testcase>
|
||||
+<info>
|
||||
+<keywords>
|
||||
+netrc
|
||||
+HTTP
|
||||
+</keywords>
|
||||
+</info>
|
||||
+#
|
||||
+# Server-side
|
||||
+<reply>
|
||||
+<data crlf="yes">
|
||||
+HTTP/1.1 200 OK
|
||||
+Date: Tue, 09 Nov 2010 14:49:00 GMT
|
||||
+Server: test-server/fake
|
||||
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||
+ETag: "21025-dc7-39462498"
|
||||
+Accept-Ranges: bytes
|
||||
+Content-Length: 6
|
||||
+Connection: close
|
||||
+Content-Type: text/html
|
||||
+Funny-head: yesyes
|
||||
+
|
||||
+-foo-
|
||||
+</data>
|
||||
+</reply>
|
||||
+
|
||||
+#
|
||||
+# Client-side
|
||||
+<client>
|
||||
+<server>
|
||||
+http
|
||||
+</server>
|
||||
+<features>
|
||||
+proxy
|
||||
+</features>
|
||||
+<name>
|
||||
+.netrc with multiple accounts for same host
|
||||
+</name>
|
||||
+<command>
|
||||
+--netrc --netrc-file %LOGDIR/netrc%TESTNUMBER -x http://%HOSTIP:%HTTPPORT/ http://debbie@github.com/
|
||||
+</command>
|
||||
+<file name="%LOGDIR/netrc%TESTNUMBER" >
|
||||
+
|
||||
+machine github.com
|
||||
+password weird
|
||||
+password firstone
|
||||
+login daniel
|
||||
+
|
||||
+machine github.com
|
||||
+
|
||||
+machine github.com
|
||||
+login debbie
|
||||
+
|
||||
+machine github.com
|
||||
+password weird
|
||||
+password "second\r"
|
||||
+login debbie
|
||||
+
|
||||
+</file>
|
||||
+</client>
|
||||
+
|
||||
+<verify>
|
||||
+<protocol>
|
||||
+GET http://github.com/ HTTP/1.1
|
||||
+Host: github.com
|
||||
+Authorization: Basic %b64[debbie:second%0D]b64%
|
||||
+User-Agent: curl/%VERSION
|
||||
+Accept: */*
|
||||
+Proxy-Connection: Keep-Alive
|
||||
+
|
||||
+</protocol>
|
||||
+</verify>
|
||||
+</testcase>
|
||||
diff --git a/tests/data/test479 b/tests/data/test479
|
||||
new file mode 100644
|
||||
index 000000000..d7ce4652f
|
||||
--- /dev/null
|
||||
+++ b/tests/data/test479
|
||||
@@ -0,0 +1,107 @@
|
||||
+<testcase>
|
||||
+<info>
|
||||
+<keywords>
|
||||
+netrc
|
||||
+HTTP
|
||||
+</keywords>
|
||||
+</info>
|
||||
+#
|
||||
+# Server-side
|
||||
+<reply>
|
||||
+<data crlf="yes">
|
||||
+HTTP/1.1 301 Follow this you fool
|
||||
+Date: Tue, 09 Nov 2010 14:49:00 GMT
|
||||
+Server: test-server/fake
|
||||
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||
+ETag: "21025-dc7-39462498"
|
||||
+Accept-Ranges: bytes
|
||||
+Content-Length: 6
|
||||
+Connection: close
|
||||
+Location: http://b.com/%TESTNUMBER0002
|
||||
+
|
||||
+-foo-
|
||||
+</data>
|
||||
+
|
||||
+<data2 crlf="yes">
|
||||
+HTTP/1.1 200 OK
|
||||
+Date: Tue, 09 Nov 2010 14:49:00 GMT
|
||||
+Server: test-server/fake
|
||||
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||
+ETag: "21025-dc7-39462498"
|
||||
+Accept-Ranges: bytes
|
||||
+Content-Length: 7
|
||||
+Connection: close
|
||||
+
|
||||
+target
|
||||
+</data2>
|
||||
+
|
||||
+<datacheck crlf="yes">
|
||||
+HTTP/1.1 301 Follow this you fool
|
||||
+Date: Tue, 09 Nov 2010 14:49:00 GMT
|
||||
+Server: test-server/fake
|
||||
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||
+ETag: "21025-dc7-39462498"
|
||||
+Accept-Ranges: bytes
|
||||
+Content-Length: 6
|
||||
+Connection: close
|
||||
+Location: http://b.com/%TESTNUMBER0002
|
||||
+
|
||||
+HTTP/1.1 200 OK
|
||||
+Date: Tue, 09 Nov 2010 14:49:00 GMT
|
||||
+Server: test-server/fake
|
||||
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||
+ETag: "21025-dc7-39462498"
|
||||
+Accept-Ranges: bytes
|
||||
+Content-Length: 7
|
||||
+Connection: close
|
||||
+
|
||||
+target
|
||||
+</datacheck>
|
||||
+</reply>
|
||||
+
|
||||
+#
|
||||
+# Client-side
|
||||
+<client>
|
||||
+<server>
|
||||
+http
|
||||
+</server>
|
||||
+<features>
|
||||
+proxy
|
||||
+</features>
|
||||
+<name>
|
||||
+.netrc with redirect and default without password
|
||||
+</name>
|
||||
+<command>
|
||||
+--netrc --netrc-file %LOGDIR/netrc%TESTNUMBER -L -x http://%HOSTIP:%HTTPPORT/ http://a.com/
|
||||
+</command>
|
||||
+<file name="%LOGDIR/netrc%TESTNUMBER" >
|
||||
+
|
||||
+machine a.com
|
||||
+ login alice
|
||||
+ password alicespassword
|
||||
+
|
||||
+default
|
||||
+ login bob
|
||||
+
|
||||
+</file>
|
||||
+</client>
|
||||
+
|
||||
+<verify>
|
||||
+<protocol>
|
||||
+GET http://a.com/ HTTP/1.1
|
||||
+Host: a.com
|
||||
+Authorization: Basic %b64[alice:alicespassword]b64%
|
||||
+User-Agent: curl/%VERSION
|
||||
+Accept: */*
|
||||
+Proxy-Connection: Keep-Alive
|
||||
+
|
||||
+GET http://b.com/%TESTNUMBER0002 HTTP/1.1
|
||||
+Host: b.com
|
||||
+Authorization: Basic %b64[bob:]b64%
|
||||
+User-Agent: curl/%VERSION
|
||||
+Accept: */*
|
||||
+Proxy-Connection: Keep-Alive
|
||||
+
|
||||
+</protocol>
|
||||
+</verify>
|
||||
+</testcase>
|
||||
diff --git a/tests/data/test480 b/tests/data/test480
|
||||
new file mode 100644
|
||||
index 000000000..aab889f47
|
||||
--- /dev/null
|
||||
+++ b/tests/data/test480
|
||||
@@ -0,0 +1,38 @@
|
||||
+<testcase>
|
||||
+<info>
|
||||
+<keywords>
|
||||
+netrc
|
||||
+pop3
|
||||
+</keywords>
|
||||
+</info>
|
||||
+#
|
||||
+# Server-side
|
||||
+<reply>
|
||||
+
|
||||
+</reply>
|
||||
+
|
||||
+#
|
||||
+# Client-side
|
||||
+<client>
|
||||
+<server>
|
||||
+pop3
|
||||
+</server>
|
||||
+<name>
|
||||
+Reject .netrc with credentials using CRLF for POP3
|
||||
+</name>
|
||||
+<command>
|
||||
+--netrc --netrc-file %LOGDIR/netrc%TESTNUMBER pop3://%HOSTIP:%POP3PORT/%TESTNUMBER
|
||||
+</command>
|
||||
+<file name="%LOGDIR/netrc%TESTNUMBER" >
|
||||
+machine %HOSTIP
|
||||
+ login alice
|
||||
+ password "password\r\ncommand"
|
||||
+</file>
|
||||
+</client>
|
||||
+
|
||||
+<verify>
|
||||
+<errorcode>
|
||||
+26
|
||||
+</errorcode>
|
||||
+</verify>
|
||||
+</testcase>
|
||||
diff --git a/tests/unit/unit1304.c b/tests/unit/unit1304.c
|
||||
index 238d3c0f7..817887b94 100644
|
||||
--- a/tests/unit/unit1304.c
|
||||
+++ b/tests/unit/unit1304.c
|
||||
@@ -32,13 +32,8 @@ static char *password;
|
||||
|
||||
static CURLcode unit_setup(void)
|
||||
{
|
||||
- password = strdup("");
|
||||
- login = strdup("");
|
||||
- if(!password || !login) {
|
||||
- Curl_safefree(password);
|
||||
- Curl_safefree(login);
|
||||
- return CURLE_OUT_OF_MEMORY;
|
||||
- }
|
||||
+ password = NULL;
|
||||
+ login = NULL;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@@ -60,89 +55,61 @@ UNITTEST_START
|
||||
result = Curl_parsenetrc(&store,
|
||||
"test.example.com", &login, &password, arg);
|
||||
fail_unless(result == 1, "Host not found should return 1");
|
||||
- abort_unless(password != NULL, "returned NULL!");
|
||||
- fail_unless(password[0] == 0, "password should not have been changed");
|
||||
- abort_unless(login != NULL, "returned NULL!");
|
||||
- fail_unless(login[0] == 0, "login should not have been changed");
|
||||
+ abort_unless(password == NULL, "password did not return NULL!");
|
||||
+ abort_unless(login == NULL, "user did not return NULL!");
|
||||
Curl_netrc_cleanup(&store);
|
||||
|
||||
/*
|
||||
* Test a non existent login in our netrc file.
|
||||
*/
|
||||
- free(login);
|
||||
- login = strdup("me");
|
||||
- abort_unless(login != NULL, "returned NULL!");
|
||||
+ login = (char *)"me";
|
||||
Curl_netrc_init(&store);
|
||||
result = Curl_parsenetrc(&store,
|
||||
"example.com", &login, &password, arg);
|
||||
fail_unless(result == 0, "Host should have been found");
|
||||
- abort_unless(password != NULL, "returned NULL!");
|
||||
- fail_unless(password[0] == 0, "password should not have been changed");
|
||||
- abort_unless(login != NULL, "returned NULL!");
|
||||
- fail_unless(strncmp(login, "me", 2) == 0,
|
||||
- "login should not have been changed");
|
||||
+ abort_unless(password == NULL, "password is not NULL!");
|
||||
Curl_netrc_cleanup(&store);
|
||||
|
||||
/*
|
||||
* Test a non existent login and host in our netrc file.
|
||||
*/
|
||||
- free(login);
|
||||
- login = strdup("me");
|
||||
- abort_unless(login != NULL, "returned NULL!");
|
||||
+ login = (char *)"me";
|
||||
Curl_netrc_init(&store);
|
||||
result = Curl_parsenetrc(&store,
|
||||
"test.example.com", &login, &password, arg);
|
||||
fail_unless(result == 1, "Host not found should return 1");
|
||||
- abort_unless(password != NULL, "returned NULL!");
|
||||
- fail_unless(password[0] == 0, "password should not have been changed");
|
||||
- abort_unless(login != NULL, "returned NULL!");
|
||||
- fail_unless(strncmp(login, "me", 2) == 0,
|
||||
- "login should not have been changed");
|
||||
+ abort_unless(password == NULL, "password is not NULL!");
|
||||
Curl_netrc_cleanup(&store);
|
||||
|
||||
/*
|
||||
* Test a non existent login (substring of an existing one) in our
|
||||
* netrc file.
|
||||
*/
|
||||
- free(login);
|
||||
- login = strdup("admi");
|
||||
- abort_unless(login != NULL, "returned NULL!");
|
||||
+ login = (char *)"admi";
|
||||
Curl_netrc_init(&store);
|
||||
result = Curl_parsenetrc(&store,
|
||||
"example.com", &login, &password, arg);
|
||||
fail_unless(result == 0, "Host should have been found");
|
||||
- abort_unless(password != NULL, "returned NULL!");
|
||||
- fail_unless(password[0] == 0, "password should not have been changed");
|
||||
- abort_unless(login != NULL, "returned NULL!");
|
||||
- fail_unless(strncmp(login, "admi", 4) == 0,
|
||||
- "login should not have been changed");
|
||||
+ abort_unless(password == NULL, "password is not NULL!");
|
||||
Curl_netrc_cleanup(&store);
|
||||
|
||||
/*
|
||||
* Test a non existent login (superstring of an existing one)
|
||||
* in our netrc file.
|
||||
*/
|
||||
- free(login);
|
||||
- login = strdup("adminn");
|
||||
- abort_unless(login != NULL, "returned NULL!");
|
||||
+ login = (char *)"adminn";
|
||||
Curl_netrc_init(&store);
|
||||
result = Curl_parsenetrc(&store,
|
||||
"example.com", &login, &password, arg);
|
||||
fail_unless(result == 0, "Host should have been found");
|
||||
- abort_unless(password != NULL, "returned NULL!");
|
||||
- fail_unless(password[0] == 0, "password should not have been changed");
|
||||
- abort_unless(login != NULL, "returned NULL!");
|
||||
- fail_unless(strncmp(login, "adminn", 6) == 0,
|
||||
- "login should not have been changed");
|
||||
+ abort_unless(password == NULL, "password is not NULL!");
|
||||
Curl_netrc_cleanup(&store);
|
||||
|
||||
/*
|
||||
* Test for the first existing host in our netrc file
|
||||
* with login[0] = 0.
|
||||
*/
|
||||
- free(login);
|
||||
- login = strdup("");
|
||||
- abort_unless(login != NULL, "returned NULL!");
|
||||
+ login = NULL;
|
||||
Curl_netrc_init(&store);
|
||||
result = Curl_parsenetrc(&store,
|
||||
"example.com", &login, &password, arg);
|
||||
@@ -159,8 +126,9 @@ UNITTEST_START
|
||||
* with login[0] != 0.
|
||||
*/
|
||||
free(password);
|
||||
- password = strdup("");
|
||||
- abort_unless(password != NULL, "returned NULL!");
|
||||
+ free(login);
|
||||
+ password = NULL;
|
||||
+ login = NULL;
|
||||
Curl_netrc_init(&store);
|
||||
result = Curl_parsenetrc(&store,
|
||||
"example.com", &login, &password, arg);
|
||||
@@ -177,11 +145,9 @@ UNITTEST_START
|
||||
* with login[0] = 0.
|
||||
*/
|
||||
free(password);
|
||||
- password = strdup("");
|
||||
- abort_unless(password != NULL, "returned NULL!");
|
||||
+ password = NULL;
|
||||
free(login);
|
||||
- login = strdup("");
|
||||
- abort_unless(login != NULL, "returned NULL!");
|
||||
+ login = NULL;
|
||||
Curl_netrc_init(&store);
|
||||
result = Curl_parsenetrc(&store,
|
||||
"curl.example.com", &login, &password, arg);
|
||||
@@ -198,8 +164,9 @@ UNITTEST_START
|
||||
* with login[0] != 0.
|
||||
*/
|
||||
free(password);
|
||||
- password = strdup("");
|
||||
- abort_unless(password != NULL, "returned NULL!");
|
||||
+ free(login);
|
||||
+ password = NULL;
|
||||
+ login = NULL;
|
||||
Curl_netrc_init(&store);
|
||||
result = Curl_parsenetrc(&store,
|
||||
"curl.example.com", &login, &password, arg);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
16
curl.spec
16
curl.spec
@ -7,7 +7,7 @@
|
||||
|
||||
Name: curl
|
||||
Version: 8.4.0
|
||||
Release: 13
|
||||
Release: 14
|
||||
Summary: Curl is used in command lines or scripts to transfer data
|
||||
License: curl
|
||||
URL: https://curl.se/
|
||||
@ -38,6 +38,14 @@ Patch29: backport-pre-CVE-2024-9681.patch
|
||||
Patch30: backport-CVE-2024-9681.patch
|
||||
Patch31: backport-multi-check-that-the-multi-handle-is-valid-in-curl_m.patch
|
||||
Patch32: backport-cookie-treat-cookie-name-case-sensitively.patch
|
||||
Patch33: backport-CVE-2024-11053-pre1.patch
|
||||
Patch34: backport-CVE-2024-11053-pre2.patch
|
||||
Patch35: backport-CVE-2024-11053-pre3.patch
|
||||
Patch36: backport-CVE-2024-11053-pre4.patch
|
||||
Patch37: backport-CVE-2024-11053-pre5.patch
|
||||
Patch38: backport-CVE-2024-11053.patch
|
||||
Patch39: backport-CVE-2024-11053-post1.patch
|
||||
Patch40: backport-CVE-2024-11053-post2.patch
|
||||
|
||||
BuildRequires: automake brotli-devel coreutils gcc groff krb5-devel
|
||||
BuildRequires: libidn2-devel libnghttp2-devel libpsl-devel
|
||||
@ -223,6 +231,12 @@ rm -rf ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la
|
||||
%{_mandir}/man3/*
|
||||
|
||||
%changelog
|
||||
* Tue Jan 07 2025 zhouyihang <zhouyihang3@h-partners.com> - 8.4.0-14
|
||||
- Type:CVE
|
||||
- CVE:CVE-2024-11053
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2024-11053
|
||||
|
||||
* Mon Dec 09 2024 zhouyihang <zhouyihang3@h-partners.com> - 8.4.0-13
|
||||
- Type:bugfix
|
||||
- CVE:NA
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user