File curl-CVE-2024-11053.patch of Package curl.37302
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
---
lib/netrc.c | 113 +++++++++++++++++++++++------------------
lib/url.c | 60 +++++++++++++++-------
tests/data/Makefile.am | 2 +-
tests/data/test478 | 73 ++++++++++++++++++++++++++
tests/data/test479 | 107 ++++++++++++++++++++++++++++++++++++++
tests/data/test480 | 38 ++++++++++++++
tests/unit/unit1304.c | 75 ++++++++-------------------
7 files changed, 345 insertions(+), 123 deletions(-)
create mode 100644 tests/data/test478
create mode 100644 tests/data/test479
create mode 100644 tests/data/test480
Index: curl-7.66.0/lib/netrc.c
===================================================================
--- curl-7.66.0.orig/lib/netrc.c
+++ curl-7.66.0/lib/netrc.c
@@ -164,6 +164,16 @@ static int parsenetrc(const char *host,
state = HOSTFOUND;
state_our_login = FALSE;
}
+ else if(strcasecompare("default", tok)) {
+ state = HOSTVALID;
+ retcode = NETRC_SUCCESS; /* we did find our host */
+ Curl_safefree(password);
+ if(!specific_login)
+ if(login_alloc) {
+ free(login);
+ login_alloc = FALSE;
+ }
+ }
break;
} /* switch (state) */
@@ -172,6 +182,12 @@ static int parsenetrc(const char *host,
} /* while fgets() */
out:
+ if(!retcode && !password && state_our_login) {
+ /* success without a password, set a blank one */
+ password = strdup("");
+ if(!password)
+ retcode = 1; /* out of memory */
+ }
if(!retcode) {
/* success */
*login_changed = FALSE;
Index: curl-7.66.0/lib/url.c
===================================================================
--- curl-7.66.0.orig/lib/url.c
+++ curl-7.66.0/lib/url.c
@@ -2674,6 +2674,17 @@ static CURLcode parse_remote_port(struct
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.
@@ -2731,29 +2742,39 @@ static CURLcode override_login(struct Cu
bool netrc_passwd_changed = FALSE;
int ret;
- ret = Curl_parsenetrc(conn->host.name,
- userp, passwdp,
- &netrc_user_changed, &netrc_passwd_changed,
- data->set.str[STRING_NETRC_FILE]);
- if(ret > 0) {
- infof(data, "Couldn't find host %s in the .netrc file; using defaults\n",
- conn->host.name);
- }
- else if(ret < 0) {
- return CURLE_OUT_OF_MEMORY;
- }
- 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;
- conn->bits.user_passwd = TRUE; /* enable user+password */
-
- if(netrc_user_changed) {
- user_changed = TRUE;
+ if(!*passwdp) {
+ ret = Curl_parsenetrc(conn->host.name,
+ userp, passwdp,
+ &netrc_user_changed, &netrc_passwd_changed,
+ data->set.str[STRING_NETRC_FILE]);
+ if(ret > 0) {
+ infof(data, "Couldn't find host %s in the .netrc file; using defaults\n",
+ conn->host.name);
+ }
+ else if(ret < 0) {
+ return CURLE_OUT_OF_MEMORY;
}
- if(netrc_passwd_changed) {
- passwd_changed = TRUE;
+ 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;
+ conn->bits.user_passwd = TRUE; /* enable user+password */
+
+ if(netrc_user_changed) {
+ user_changed = TRUE;
+ }
+ if(netrc_passwd_changed) {
+ passwd_changed = TRUE;
+ }
}
}
}
Index: curl-7.66.0/lib/urldata.h
===================================================================
--- curl-7.66.0.orig/lib/urldata.h
+++ curl-7.66.0/lib/urldata.h
@@ -734,6 +734,9 @@ struct Curl_handler {
HTTP proxy as HTTP proxies may know
this protocol and act as a gateway */
#define PROTOPT_WILDCARD (1<<12) /* protocol supports wildcard matching */
+#define PROTOPT_USERPWDCTRL (1<<13) /* Allow "control bytes" (< 32 ascii) in
+ user name and password */
+
#define CONNCHECK_NONE 0 /* No checks */
#define CONNCHECK_ISDEAD (1<<0) /* Check if the connection is dead. */