diff mbox series

[scarthgap] curl: Backport fix for CVE-2024-11053

Message ID 20250226133957.954654-1-vanusuri@mvista.com
State Changes Requested
Delegated to: Steve Sakoman
Headers show
Series [scarthgap] curl: Backport fix for CVE-2024-11053 | expand

Commit Message

Vijay Anusuri Feb. 26, 2025, 1:39 p.m. UTC
From: Vijay Anusuri <vanusuri@mvista.com>

Upstream-Status: Backport
https://github.com/curl/curl/commit/9bee39bfed2c413b4cc4eb306a57ac92a1854907
& https://github.com/curl/curl/commit/e9b9bbac22c26cf6731 & https://github.com/curl/curl/commit/9fce2c55d4b0273ac99

Reference:
https://curl.se/docs/CVE-2024-11053.html
https://ubuntu.com/security/CVE-2024-11053

Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
---
 .../curl/curl/CVE-2024-11053-1.patch          | 718 ++++++++++++++++++
 .../curl/curl/CVE-2024-11053-2.patch          | 130 ++++
 .../curl/curl/CVE-2024-11053-pre1.patch       | 350 +++++++++
 meta/recipes-support/curl/curl_8.7.1.bb       |   3 +
 4 files changed, 1201 insertions(+)
 create mode 100644 meta/recipes-support/curl/curl/CVE-2024-11053-1.patch
 create mode 100644 meta/recipes-support/curl/curl/CVE-2024-11053-2.patch
 create mode 100644 meta/recipes-support/curl/curl/CVE-2024-11053-pre1.patch

Comments

Steve Sakoman Feb. 27, 2025, 8:16 p.m. UTC | #1
A similar patch was submitted and rejected recently, and your version
has the same issues.

Please see message link below below for details of the failure:

https://lists.openembedded.org/g/openembedded-core/message/211372

Steve

On Wed, Feb 26, 2025 at 5:40 AM Vijay Anusuri via
lists.openembedded.org <vanusuri=mvista.com@lists.openembedded.org>
wrote:
>
> From: Vijay Anusuri <vanusuri@mvista.com>
>
> Upstream-Status: Backport
> https://github.com/curl/curl/commit/9bee39bfed2c413b4cc4eb306a57ac92a1854907
> & https://github.com/curl/curl/commit/e9b9bbac22c26cf6731 & https://github.com/curl/curl/commit/9fce2c55d4b0273ac99
>
> Reference:
> https://curl.se/docs/CVE-2024-11053.html
> https://ubuntu.com/security/CVE-2024-11053
>
> Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
> ---
>  .../curl/curl/CVE-2024-11053-1.patch          | 718 ++++++++++++++++++
>  .../curl/curl/CVE-2024-11053-2.patch          | 130 ++++
>  .../curl/curl/CVE-2024-11053-pre1.patch       | 350 +++++++++
>  meta/recipes-support/curl/curl_8.7.1.bb       |   3 +
>  4 files changed, 1201 insertions(+)
>  create mode 100644 meta/recipes-support/curl/curl/CVE-2024-11053-1.patch
>  create mode 100644 meta/recipes-support/curl/curl/CVE-2024-11053-2.patch
>  create mode 100644 meta/recipes-support/curl/curl/CVE-2024-11053-pre1.patch
>
> diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-1.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-1.patch
> new file mode 100644
> index 0000000000..14080c7bd0
> --- /dev/null
> +++ b/meta/recipes-support/curl/curl/CVE-2024-11053-1.patch
> @@ -0,0 +1,718 @@
> +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
> +
> +Upstream-Status: Backport [https://github.com/curl/curl/commit/e9b9bbac22c26cf6731]
> +CVE: CVE-2024-11053
> +Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
> +---
> + lib/netrc.c             | 122 ++++++++++++++++++++++------------------
> + lib/url.c               |  59 ++++++++++++-------
> + tests/data/Makefile.inc |   2 +-
> + tests/data/test478      |  73 ++++++++++++++++++++++++
> + tests/data/test479      | 107 +++++++++++++++++++++++++++++++++++
> + tests/data/test480      |  38 +++++++++++++
> + tests/unit/unit1304.c   |  75 +++++++-----------------
> + 7 files changed, 347 insertions(+), 129 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 cd2a284..b582c10 100644
> +--- a/lib/netrc.c
> ++++ b/lib/netrc.c
> +@@ -49,6 +49,15 @@ enum host_lookup_state {
> +   MACDEF
> + };
> +
> ++enum found_state {
> ++  NONE,
> ++  LOGIN,
> ++  PASSWORD
> ++};
> ++
> ++#define FOUND_LOGIN    1
> ++#define FOUND_PASSWORD 2
> ++
> + #define NETRC_FILE_MISSING 1
> + #define NETRC_FAILED -1
> + #define NETRC_SUCCESS 0
> +@@ -59,23 +68,20 @@ enum host_lookup_state {
> +  * Returns zero on success.
> +  */
> + static int parsenetrc(const char *host,
> +-                      char **loginp,
> ++                      char **loginp, /* might point to a username */
> +                       char **passwordp,
> +                       char *netrcfile)
> + {
> +   FILE *file;
> +   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;
> +-
> +-  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) */
> ++  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 */
> +
> +   DEBUGASSERT(netrcfile);
> +
> +@@ -97,7 +103,7 @@ static int parsenetrc(const char *host,
> +           continue;
> +       }
> +       tok = netrcbuffer;
> +-      while(tok) {
> ++      while(tok && !done) {
> +         while(ISBLANK(*tok))
> +           tok++;
> +         /* tok is first non-space letter */
> +@@ -156,11 +162,6 @@ static int parsenetrc(const char *host,
> +           }
> +         }
> +
> +-        if((login && *login) && (password && *password)) {
> +-          done = TRUE;
> +-          break;
> +-        }
> +-
> +         switch(state) {
> +         case NOTHING:
> +           if(strcasecompare("macdef", tok)) {
> +@@ -175,6 +176,12 @@ static int parsenetrc(const char *host,
> +                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;
> +@@ -198,48 +205,55 @@ static int parsenetrc(const char *host,
> +           break;
> +         case HOSTVALID:
> +           /* we are now parsing sub-keywords concerning "our" host */
> +-          if(state_login) {
> ++          if(keyword == LOGIN) {
> +             if(specific_login) {
> +-              state_our_login = !Curl_timestrcmp(login, tok);
> ++              our_login = !Curl_timestrcmp(login, tok);
> +             }
> +-            else if(!login || Curl_timestrcmp(login, tok)) {
> +-              if(login_alloc) {
> +-                free(login);
> +-                login_alloc = FALSE;
> +-              }
> ++            else {
> ++              our_login = TRUE;
> ++              free(login);
> +               login = strdup(tok);
> +               if(!login) {
> +                 retcode = NETRC_FAILED; /* allocation failed */
> +                 goto out;
> +               }
> +-              login_alloc = TRUE;
> +             }
> +-            state_login = 0;
> ++          found |= FOUND_LOGIN;
> ++          keyword = NONE;
> +           }
> +-          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;
> ++          else if(keyword == PASSWORD) {
> ++            free(password);
> ++            password = strdup(tok);
> ++            if(!password) {
> ++            retcode = NETRC_FAILED; /* allocation failed */
> ++            goto out;
> +             }
> +-            state_password = 0;
> ++          found |= FOUND_PASSWORD;
> ++          keyword = NONE;
> +           }
> +           else if(strcasecompare("login", tok))
> +-            state_login = 1;
> ++            keyword = LOGIN;
> +           else if(strcasecompare("password", tok))
> +-            state_password = 1;
> ++            keyword = PASSWORD;
> +           else if(strcasecompare("machine", tok)) {
> +-            /* ok, there's machine here go => */
> ++            /* a new machine here */
> +             state = HOSTFOUND;
> +-            state_our_login = FALSE;
> ++            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) */
> +@@ -249,24 +263,22 @@ static int parsenetrc(const char *host,
> +
> + out:
> +     Curl_dyn_free(&buf);
> ++    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) {
> +-        if(*loginp)
> +-          free(*loginp);
> ++      if(!specific_login)
> +         *loginp = login;
> +-      }
> +-      if(password_alloc) {
> +-        if(*passwordp)
> +-          free(*passwordp);
> +-        *passwordp = password;
> +-      }
> ++      *passwordp = password;
> +     }
> +     else {
> +-      if(login_alloc)
> ++      if(!specific_login)
> +         free(login);
> +-      if(password_alloc)
> +-        free(password);
> ++      free(password);
> +     }
> +     fclose(file);
> +   }
> +diff --git a/lib/url.c b/lib/url.c
> +index 8892450..e121d45 100644
> +--- a/lib/url.c
> ++++ b/lib/url.c
> +@@ -2699,6 +2699,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.
> +@@ -2730,29 +2741,39 @@ 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(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(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 03cb6a0..f608a7d 100644
> +--- a/tests/data/Makefile.inc
> ++++ b/tests/data/Makefile.inc
> +@@ -74,7 +74,7 @@ test435 test436 test437 test438 test439 test440 test441 test442 test443 \
> + test444 test445 test446 test447 test448 test449 test450 test451 test452 \
> + test453 test454 test455 test456 test457 test458 test459 test460 test461 \
> + test462 test463 test467 test468 \
> +-\
> ++test478 test479 test480 \
> + test490 test491 test492 test493 test494 test495 test496 test497 test498 \
> + test499 test500 test501 test502 test503 test504 test505 test506 test507 \
> + test508 test509 test510 test511 test512 test513 test514 test515 test516 \
> +diff --git a/tests/data/test478 b/tests/data/test478
> +new file mode 100644
> +index 0000000..7d7454d
> +--- /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 0000000..48bcdfe
> +--- /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 0000000..aab889f
> +--- /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 0288562..b2b4366 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;
> + }
> +
> +@@ -56,76 +51,48 @@ UNITTEST_START
> +    */
> +   result = Curl_parsenetrc("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!");
> +
> +   /*
> +    * Test a non existent login in our netrc file.
> +    */
> +-  free(login);
> +-  login = strdup("me");
> +-  abort_unless(login != NULL, "returned NULL!");
> ++  login = (char *)"me";
> +   result = Curl_parsenetrc("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!");
> +
> +   /*
> +    * 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";
> +   result = Curl_parsenetrc("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!");
> +
> +   /*
> +    * 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";
> +   result = Curl_parsenetrc("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!");
> +
> +   /*
> +    * 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";
> +   result = Curl_parsenetrc("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!");
> +
> +   /*
> +    * 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;
> +   result = Curl_parsenetrc("example.com", &login, &password, arg);
> +   fail_unless(result == 0, "Host should have been found");
> +   abort_unless(password != NULL, "returned NULL!");
> +@@ -139,8 +106,9 @@ UNITTEST_START
> +    * with login[0] != 0.
> +    */
> +   free(password);
> +-  password = strdup("");
> +-  abort_unless(password != NULL, "returned NULL!");
> ++  free(login);
> ++  password = NULL;
> ++  login = NULL;
> +   result = Curl_parsenetrc("example.com", &login, &password, arg);
> +   fail_unless(result == 0, "Host should have been found");
> +   abort_unless(password != NULL, "returned NULL!");
> +@@ -154,11 +122,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;
> +   result = Curl_parsenetrc("curl.example.com", &login, &password, arg);
> +   fail_unless(result == 0, "Host should have been found");
> +   abort_unless(password != NULL, "returned NULL!");
> +@@ -172,8 +138,9 @@ UNITTEST_START
> +    * with login[0] != 0.
> +    */
> +   free(password);
> +-  password = strdup("");
> +-  abort_unless(password != NULL, "returned NULL!");
> ++  free(login);
> ++  password = NULL;
> ++  login = NULL;
> +   result = Curl_parsenetrc("curl.example.com", &login, &password, arg);
> +   fail_unless(result == 0, "Host should have been found");
> +   abort_unless(password != NULL, "returned NULL!");
> +--
> +2.25.1
> +
> diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-2.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-2.patch
> new file mode 100644
> index 0000000000..2f35a86eb9
> --- /dev/null
> +++ b/meta/recipes-support/curl/curl/CVE-2024-11053-2.patch
> @@ -0,0 +1,130 @@
> +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
> +
> +Upstream-Status: Backport [https://github.com/curl/curl/commit/9fce2c55d4b0273ac99]
> +CVE: CVE-2024-11053 #Regression fix
> +Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
> +---
> + 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 b582c10..a282fce 100644
> +--- a/lib/netrc.c
> ++++ b/lib/netrc.c
> +@@ -228,7 +228,8 @@ static int parsenetrc(const char *host,
> +             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))
> +@@ -237,6 +238,10 @@ static int parsenetrc(const char *host,
> +             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 f608a7d..2823d96 100644
> +--- a/tests/data/Makefile.inc
> ++++ b/tests/data/Makefile.inc
> +@@ -230,7 +230,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 0000000..69e14d9
> +--- /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.25.1
> +
> diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-pre1.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-pre1.patch
> new file mode 100644
> index 0000000000..55fccae316
> --- /dev/null
> +++ b/meta/recipes-support/curl/curl/CVE-2024-11053-pre1.patch
> @@ -0,0 +1,350 @@
> +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
> +
> +Upstream-Status: Backport [https://github.com/curl/curl/commit/9bee39bfed2c413b4cc4eb306a57ac92a1854907]
> +CVE: CVE-2024-11053 #Dependency Patch
> +Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
> +---
> + lib/transfer.c          |  3 ++
> + lib/url.c               | 19 +++++----
> + lib/urldata.h           |  9 +++-
> + tests/data/Makefile.inc |  2 +-
> + 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 e31d1d6..ccd042b 100644
> +--- a/lib/transfer.c
> ++++ b/lib/transfer.c
> +@@ -700,6 +700,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 224b9f3..8892450 100644
> +--- a/lib/url.c
> ++++ b/lib/url.c
> +@@ -1899,10 +1899,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.
> ++   * User name 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;
> +@@ -1915,12 +1915,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 */
> +@@ -1934,13 +1935,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;
> +   }
> +@@ -2730,7 +2728,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;
> +@@ -2778,6 +2777,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) {
> +@@ -2795,6 +2795,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 ce28f25..b68d023 100644
> +--- a/lib/urldata.h
> ++++ b/lib/urldata.h
> +@@ -1207,6 +1207,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 select_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 d89e565..03cb6a0 100644
> +--- a/tests/data/Makefile.inc
> ++++ b/tests/data/Makefile.inc
> +@@ -126,7 +126,7 @@ test952 test953 test954 test955 test956 test957 test958 test959 test960 \
> + 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 test992 \
> ++test988 test989 test990 test991 test992 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 0000000..6dcd95f
> +--- /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 0000000..e805cde
> +--- /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.25.1
> +
> diff --git a/meta/recipes-support/curl/curl_8.7.1.bb b/meta/recipes-support/curl/curl_8.7.1.bb
> index 439fcb7881..23bc6f429a 100644
> --- a/meta/recipes-support/curl/curl_8.7.1.bb
> +++ b/meta/recipes-support/curl/curl_8.7.1.bb
> @@ -20,6 +20,9 @@ SRC_URI = " \
>      file://CVE-2024-7264-2.patch \
>      file://CVE-2024-8096.patch \
>      file://CVE-2024-9681.patch \
> +    file://CVE-2024-11053-pre1.patch \
> +    file://CVE-2024-11053-1.patch \
> +    file://CVE-2024-11053-2.patch \
>  "
>  SRC_URI[sha256sum] = "6fea2aac6a4610fbd0400afb0bcddbe7258a64c63f1f68e5855ebc0c659710cd"
>
> --
> 2.25.1
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#211960): https://lists.openembedded.org/g/openembedded-core/message/211960
> Mute This Topic: https://lists.openembedded.org/mt/111395659/3620601
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [steve@sakoman.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
Steve Sakoman Feb. 27, 2025, 8:19 p.m. UTC | #2
Oops, wrong link! See:

https://lists.openembedded.org/g/openembedded-core/message/211487

On Thu, Feb 27, 2025 at 12:17 PM Steve Sakoman via
lists.openembedded.org <steve=sakoman.com@lists.openembedded.org>
wrote:
>
> A similar patch was submitted and rejected recently, and your version
> has the same issues.
>
> Please see message link below below for details of the failure:
>
> https://lists.openembedded.org/g/openembedded-core/message/211372
>
> Steve
>
> On Wed, Feb 26, 2025 at 5:40 AM Vijay Anusuri via
> lists.openembedded.org <vanusuri=mvista.com@lists.openembedded.org>
> wrote:
> >
> > From: Vijay Anusuri <vanusuri@mvista.com>
> >
> > Upstream-Status: Backport
> > https://github.com/curl/curl/commit/9bee39bfed2c413b4cc4eb306a57ac92a1854907
> > & https://github.com/curl/curl/commit/e9b9bbac22c26cf6731 & https://github.com/curl/curl/commit/9fce2c55d4b0273ac99
> >
> > Reference:
> > https://curl.se/docs/CVE-2024-11053.html
> > https://ubuntu.com/security/CVE-2024-11053
> >
> > Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
> > ---
> >  .../curl/curl/CVE-2024-11053-1.patch          | 718 ++++++++++++++++++
> >  .../curl/curl/CVE-2024-11053-2.patch          | 130 ++++
> >  .../curl/curl/CVE-2024-11053-pre1.patch       | 350 +++++++++
> >  meta/recipes-support/curl/curl_8.7.1.bb       |   3 +
> >  4 files changed, 1201 insertions(+)
> >  create mode 100644 meta/recipes-support/curl/curl/CVE-2024-11053-1.patch
> >  create mode 100644 meta/recipes-support/curl/curl/CVE-2024-11053-2.patch
> >  create mode 100644 meta/recipes-support/curl/curl/CVE-2024-11053-pre1.patch
> >
> > diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-1.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-1.patch
> > new file mode 100644
> > index 0000000000..14080c7bd0
> > --- /dev/null
> > +++ b/meta/recipes-support/curl/curl/CVE-2024-11053-1.patch
> > @@ -0,0 +1,718 @@
> > +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
> > +
> > +Upstream-Status: Backport [https://github.com/curl/curl/commit/e9b9bbac22c26cf6731]
> > +CVE: CVE-2024-11053
> > +Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
> > +---
> > + lib/netrc.c             | 122 ++++++++++++++++++++++------------------
> > + lib/url.c               |  59 ++++++++++++-------
> > + tests/data/Makefile.inc |   2 +-
> > + tests/data/test478      |  73 ++++++++++++++++++++++++
> > + tests/data/test479      | 107 +++++++++++++++++++++++++++++++++++
> > + tests/data/test480      |  38 +++++++++++++
> > + tests/unit/unit1304.c   |  75 +++++++-----------------
> > + 7 files changed, 347 insertions(+), 129 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 cd2a284..b582c10 100644
> > +--- a/lib/netrc.c
> > ++++ b/lib/netrc.c
> > +@@ -49,6 +49,15 @@ enum host_lookup_state {
> > +   MACDEF
> > + };
> > +
> > ++enum found_state {
> > ++  NONE,
> > ++  LOGIN,
> > ++  PASSWORD
> > ++};
> > ++
> > ++#define FOUND_LOGIN    1
> > ++#define FOUND_PASSWORD 2
> > ++
> > + #define NETRC_FILE_MISSING 1
> > + #define NETRC_FAILED -1
> > + #define NETRC_SUCCESS 0
> > +@@ -59,23 +68,20 @@ enum host_lookup_state {
> > +  * Returns zero on success.
> > +  */
> > + static int parsenetrc(const char *host,
> > +-                      char **loginp,
> > ++                      char **loginp, /* might point to a username */
> > +                       char **passwordp,
> > +                       char *netrcfile)
> > + {
> > +   FILE *file;
> > +   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;
> > +-
> > +-  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) */
> > ++  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 */
> > +
> > +   DEBUGASSERT(netrcfile);
> > +
> > +@@ -97,7 +103,7 @@ static int parsenetrc(const char *host,
> > +           continue;
> > +       }
> > +       tok = netrcbuffer;
> > +-      while(tok) {
> > ++      while(tok && !done) {
> > +         while(ISBLANK(*tok))
> > +           tok++;
> > +         /* tok is first non-space letter */
> > +@@ -156,11 +162,6 @@ static int parsenetrc(const char *host,
> > +           }
> > +         }
> > +
> > +-        if((login && *login) && (password && *password)) {
> > +-          done = TRUE;
> > +-          break;
> > +-        }
> > +-
> > +         switch(state) {
> > +         case NOTHING:
> > +           if(strcasecompare("macdef", tok)) {
> > +@@ -175,6 +176,12 @@ static int parsenetrc(const char *host,
> > +                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;
> > +@@ -198,48 +205,55 @@ static int parsenetrc(const char *host,
> > +           break;
> > +         case HOSTVALID:
> > +           /* we are now parsing sub-keywords concerning "our" host */
> > +-          if(state_login) {
> > ++          if(keyword == LOGIN) {
> > +             if(specific_login) {
> > +-              state_our_login = !Curl_timestrcmp(login, tok);
> > ++              our_login = !Curl_timestrcmp(login, tok);
> > +             }
> > +-            else if(!login || Curl_timestrcmp(login, tok)) {
> > +-              if(login_alloc) {
> > +-                free(login);
> > +-                login_alloc = FALSE;
> > +-              }
> > ++            else {
> > ++              our_login = TRUE;
> > ++              free(login);
> > +               login = strdup(tok);
> > +               if(!login) {
> > +                 retcode = NETRC_FAILED; /* allocation failed */
> > +                 goto out;
> > +               }
> > +-              login_alloc = TRUE;
> > +             }
> > +-            state_login = 0;
> > ++          found |= FOUND_LOGIN;
> > ++          keyword = NONE;
> > +           }
> > +-          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;
> > ++          else if(keyword == PASSWORD) {
> > ++            free(password);
> > ++            password = strdup(tok);
> > ++            if(!password) {
> > ++            retcode = NETRC_FAILED; /* allocation failed */
> > ++            goto out;
> > +             }
> > +-            state_password = 0;
> > ++          found |= FOUND_PASSWORD;
> > ++          keyword = NONE;
> > +           }
> > +           else if(strcasecompare("login", tok))
> > +-            state_login = 1;
> > ++            keyword = LOGIN;
> > +           else if(strcasecompare("password", tok))
> > +-            state_password = 1;
> > ++            keyword = PASSWORD;
> > +           else if(strcasecompare("machine", tok)) {
> > +-            /* ok, there's machine here go => */
> > ++            /* a new machine here */
> > +             state = HOSTFOUND;
> > +-            state_our_login = FALSE;
> > ++            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) */
> > +@@ -249,24 +263,22 @@ static int parsenetrc(const char *host,
> > +
> > + out:
> > +     Curl_dyn_free(&buf);
> > ++    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) {
> > +-        if(*loginp)
> > +-          free(*loginp);
> > ++      if(!specific_login)
> > +         *loginp = login;
> > +-      }
> > +-      if(password_alloc) {
> > +-        if(*passwordp)
> > +-          free(*passwordp);
> > +-        *passwordp = password;
> > +-      }
> > ++      *passwordp = password;
> > +     }
> > +     else {
> > +-      if(login_alloc)
> > ++      if(!specific_login)
> > +         free(login);
> > +-      if(password_alloc)
> > +-        free(password);
> > ++      free(password);
> > +     }
> > +     fclose(file);
> > +   }
> > +diff --git a/lib/url.c b/lib/url.c
> > +index 8892450..e121d45 100644
> > +--- a/lib/url.c
> > ++++ b/lib/url.c
> > +@@ -2699,6 +2699,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.
> > +@@ -2730,29 +2741,39 @@ 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(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(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 03cb6a0..f608a7d 100644
> > +--- a/tests/data/Makefile.inc
> > ++++ b/tests/data/Makefile.inc
> > +@@ -74,7 +74,7 @@ test435 test436 test437 test438 test439 test440 test441 test442 test443 \
> > + test444 test445 test446 test447 test448 test449 test450 test451 test452 \
> > + test453 test454 test455 test456 test457 test458 test459 test460 test461 \
> > + test462 test463 test467 test468 \
> > +-\
> > ++test478 test479 test480 \
> > + test490 test491 test492 test493 test494 test495 test496 test497 test498 \
> > + test499 test500 test501 test502 test503 test504 test505 test506 test507 \
> > + test508 test509 test510 test511 test512 test513 test514 test515 test516 \
> > +diff --git a/tests/data/test478 b/tests/data/test478
> > +new file mode 100644
> > +index 0000000..7d7454d
> > +--- /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 0000000..48bcdfe
> > +--- /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 0000000..aab889f
> > +--- /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 0288562..b2b4366 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;
> > + }
> > +
> > +@@ -56,76 +51,48 @@ UNITTEST_START
> > +    */
> > +   result = Curl_parsenetrc("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!");
> > +
> > +   /*
> > +    * Test a non existent login in our netrc file.
> > +    */
> > +-  free(login);
> > +-  login = strdup("me");
> > +-  abort_unless(login != NULL, "returned NULL!");
> > ++  login = (char *)"me";
> > +   result = Curl_parsenetrc("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!");
> > +
> > +   /*
> > +    * 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";
> > +   result = Curl_parsenetrc("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!");
> > +
> > +   /*
> > +    * 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";
> > +   result = Curl_parsenetrc("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!");
> > +
> > +   /*
> > +    * 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";
> > +   result = Curl_parsenetrc("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!");
> > +
> > +   /*
> > +    * 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;
> > +   result = Curl_parsenetrc("example.com", &login, &password, arg);
> > +   fail_unless(result == 0, "Host should have been found");
> > +   abort_unless(password != NULL, "returned NULL!");
> > +@@ -139,8 +106,9 @@ UNITTEST_START
> > +    * with login[0] != 0.
> > +    */
> > +   free(password);
> > +-  password = strdup("");
> > +-  abort_unless(password != NULL, "returned NULL!");
> > ++  free(login);
> > ++  password = NULL;
> > ++  login = NULL;
> > +   result = Curl_parsenetrc("example.com", &login, &password, arg);
> > +   fail_unless(result == 0, "Host should have been found");
> > +   abort_unless(password != NULL, "returned NULL!");
> > +@@ -154,11 +122,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;
> > +   result = Curl_parsenetrc("curl.example.com", &login, &password, arg);
> > +   fail_unless(result == 0, "Host should have been found");
> > +   abort_unless(password != NULL, "returned NULL!");
> > +@@ -172,8 +138,9 @@ UNITTEST_START
> > +    * with login[0] != 0.
> > +    */
> > +   free(password);
> > +-  password = strdup("");
> > +-  abort_unless(password != NULL, "returned NULL!");
> > ++  free(login);
> > ++  password = NULL;
> > ++  login = NULL;
> > +   result = Curl_parsenetrc("curl.example.com", &login, &password, arg);
> > +   fail_unless(result == 0, "Host should have been found");
> > +   abort_unless(password != NULL, "returned NULL!");
> > +--
> > +2.25.1
> > +
> > diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-2.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-2.patch
> > new file mode 100644
> > index 0000000000..2f35a86eb9
> > --- /dev/null
> > +++ b/meta/recipes-support/curl/curl/CVE-2024-11053-2.patch
> > @@ -0,0 +1,130 @@
> > +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
> > +
> > +Upstream-Status: Backport [https://github.com/curl/curl/commit/9fce2c55d4b0273ac99]
> > +CVE: CVE-2024-11053 #Regression fix
> > +Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
> > +---
> > + 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 b582c10..a282fce 100644
> > +--- a/lib/netrc.c
> > ++++ b/lib/netrc.c
> > +@@ -228,7 +228,8 @@ static int parsenetrc(const char *host,
> > +             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))
> > +@@ -237,6 +238,10 @@ static int parsenetrc(const char *host,
> > +             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 f608a7d..2823d96 100644
> > +--- a/tests/data/Makefile.inc
> > ++++ b/tests/data/Makefile.inc
> > +@@ -230,7 +230,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 0000000..69e14d9
> > +--- /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.25.1
> > +
> > diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-pre1.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-pre1.patch
> > new file mode 100644
> > index 0000000000..55fccae316
> > --- /dev/null
> > +++ b/meta/recipes-support/curl/curl/CVE-2024-11053-pre1.patch
> > @@ -0,0 +1,350 @@
> > +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
> > +
> > +Upstream-Status: Backport [https://github.com/curl/curl/commit/9bee39bfed2c413b4cc4eb306a57ac92a1854907]
> > +CVE: CVE-2024-11053 #Dependency Patch
> > +Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
> > +---
> > + lib/transfer.c          |  3 ++
> > + lib/url.c               | 19 +++++----
> > + lib/urldata.h           |  9 +++-
> > + tests/data/Makefile.inc |  2 +-
> > + 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 e31d1d6..ccd042b 100644
> > +--- a/lib/transfer.c
> > ++++ b/lib/transfer.c
> > +@@ -700,6 +700,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 224b9f3..8892450 100644
> > +--- a/lib/url.c
> > ++++ b/lib/url.c
> > +@@ -1899,10 +1899,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.
> > ++   * User name 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;
> > +@@ -1915,12 +1915,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 */
> > +@@ -1934,13 +1935,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;
> > +   }
> > +@@ -2730,7 +2728,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;
> > +@@ -2778,6 +2777,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) {
> > +@@ -2795,6 +2795,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 ce28f25..b68d023 100644
> > +--- a/lib/urldata.h
> > ++++ b/lib/urldata.h
> > +@@ -1207,6 +1207,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 select_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 d89e565..03cb6a0 100644
> > +--- a/tests/data/Makefile.inc
> > ++++ b/tests/data/Makefile.inc
> > +@@ -126,7 +126,7 @@ test952 test953 test954 test955 test956 test957 test958 test959 test960 \
> > + 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 test992 \
> > ++test988 test989 test990 test991 test992 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 0000000..6dcd95f
> > +--- /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 0000000..e805cde
> > +--- /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.25.1
> > +
> > diff --git a/meta/recipes-support/curl/curl_8.7.1.bb b/meta/recipes-support/curl/curl_8.7.1.bb
> > index 439fcb7881..23bc6f429a 100644
> > --- a/meta/recipes-support/curl/curl_8.7.1.bb
> > +++ b/meta/recipes-support/curl/curl_8.7.1.bb
> > @@ -20,6 +20,9 @@ SRC_URI = " \
> >      file://CVE-2024-7264-2.patch \
> >      file://CVE-2024-8096.patch \
> >      file://CVE-2024-9681.patch \
> > +    file://CVE-2024-11053-pre1.patch \
> > +    file://CVE-2024-11053-1.patch \
> > +    file://CVE-2024-11053-2.patch \
> >  "
> >  SRC_URI[sha256sum] = "6fea2aac6a4610fbd0400afb0bcddbe7258a64c63f1f68e5855ebc0c659710cd"
> >
> > --
> > 2.25.1
> >
> >
> >
> >
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#212039): https://lists.openembedded.org/g/openembedded-core/message/212039
> Mute This Topic: https://lists.openembedded.org/mt/111395659/3620601
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [steve@sakoman.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
diff mbox series

Patch

diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-1.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-1.patch
new file mode 100644
index 0000000000..14080c7bd0
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2024-11053-1.patch
@@ -0,0 +1,718 @@ 
+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
+
+Upstream-Status: Backport [https://github.com/curl/curl/commit/e9b9bbac22c26cf6731]
+CVE: CVE-2024-11053
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ lib/netrc.c             | 122 ++++++++++++++++++++++------------------
+ lib/url.c               |  59 ++++++++++++-------
+ tests/data/Makefile.inc |   2 +-
+ tests/data/test478      |  73 ++++++++++++++++++++++++
+ tests/data/test479      | 107 +++++++++++++++++++++++++++++++++++
+ tests/data/test480      |  38 +++++++++++++
+ tests/unit/unit1304.c   |  75 +++++++-----------------
+ 7 files changed, 347 insertions(+), 129 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 cd2a284..b582c10 100644
+--- a/lib/netrc.c
++++ b/lib/netrc.c
+@@ -49,6 +49,15 @@ enum host_lookup_state {
+   MACDEF
+ };
+ 
++enum found_state {
++  NONE,
++  LOGIN,
++  PASSWORD
++};
++
++#define FOUND_LOGIN    1
++#define FOUND_PASSWORD 2
++
+ #define NETRC_FILE_MISSING 1
+ #define NETRC_FAILED -1
+ #define NETRC_SUCCESS 0
+@@ -59,23 +68,20 @@ enum host_lookup_state {
+  * Returns zero on success.
+  */
+ static int parsenetrc(const char *host,
+-                      char **loginp,
++                      char **loginp, /* might point to a username */
+                       char **passwordp,
+                       char *netrcfile)
+ {
+   FILE *file;
+   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;
+-
+-  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) */
++  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 */
+ 
+   DEBUGASSERT(netrcfile);
+ 
+@@ -97,7 +103,7 @@ static int parsenetrc(const char *host,
+           continue;
+       }
+       tok = netrcbuffer;
+-      while(tok) {
++      while(tok && !done) {
+         while(ISBLANK(*tok))
+           tok++;
+         /* tok is first non-space letter */
+@@ -156,11 +162,6 @@ static int parsenetrc(const char *host,
+           }
+         }
+ 
+-        if((login && *login) && (password && *password)) {
+-          done = TRUE;
+-          break;
+-        }
+-
+         switch(state) {
+         case NOTHING:
+           if(strcasecompare("macdef", tok)) {
+@@ -175,6 +176,12 @@ static int parsenetrc(const char *host,
+                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;
+@@ -198,48 +205,55 @@ static int parsenetrc(const char *host,
+           break;
+         case HOSTVALID:
+           /* we are now parsing sub-keywords concerning "our" host */
+-          if(state_login) {
++          if(keyword == LOGIN) {
+             if(specific_login) {
+-              state_our_login = !Curl_timestrcmp(login, tok);
++              our_login = !Curl_timestrcmp(login, tok);
+             }
+-            else if(!login || Curl_timestrcmp(login, tok)) {
+-              if(login_alloc) {
+-                free(login);
+-                login_alloc = FALSE;
+-              }
++            else {
++              our_login = TRUE;
++              free(login);
+               login = strdup(tok);
+               if(!login) {
+                 retcode = NETRC_FAILED; /* allocation failed */
+                 goto out;
+               }
+-              login_alloc = TRUE;
+             }
+-            state_login = 0;
++          found |= FOUND_LOGIN;
++          keyword = NONE;
+           }
+-          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;
++          else if(keyword == PASSWORD) {
++            free(password);
++            password = strdup(tok);
++            if(!password) {
++	      retcode = NETRC_FAILED; /* allocation failed */
++	      goto out;
+             }
+-            state_password = 0;
++          found |= FOUND_PASSWORD;
++          keyword = NONE;
+           }
+           else if(strcasecompare("login", tok))
+-            state_login = 1;
++            keyword = LOGIN;
+           else if(strcasecompare("password", tok))
+-            state_password = 1;
++            keyword = PASSWORD;
+           else if(strcasecompare("machine", tok)) {
+-            /* ok, there's machine here go => */
++            /* a new machine here */
+             state = HOSTFOUND;
+-            state_our_login = FALSE;
++            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) */
+@@ -249,24 +263,22 @@ static int parsenetrc(const char *host,
+ 
+ out:
+     Curl_dyn_free(&buf);
++    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) {
+-        if(*loginp)
+-          free(*loginp);
++      if(!specific_login)
+         *loginp = login;
+-      }
+-      if(password_alloc) {
+-        if(*passwordp)
+-          free(*passwordp);
+-        *passwordp = password;
+-      }
++      *passwordp = password;
+     }
+     else {
+-      if(login_alloc)
++      if(!specific_login)
+         free(login);
+-      if(password_alloc)
+-        free(password);
++      free(password);
+     }
+     fclose(file);
+   }
+diff --git a/lib/url.c b/lib/url.c
+index 8892450..e121d45 100644
+--- a/lib/url.c
++++ b/lib/url.c
+@@ -2699,6 +2699,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.
+@@ -2730,29 +2741,39 @@ 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(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(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 03cb6a0..f608a7d 100644
+--- a/tests/data/Makefile.inc
++++ b/tests/data/Makefile.inc
+@@ -74,7 +74,7 @@ test435 test436 test437 test438 test439 test440 test441 test442 test443 \
+ test444 test445 test446 test447 test448 test449 test450 test451 test452 \
+ test453 test454 test455 test456 test457 test458 test459 test460 test461 \
+ test462 test463 test467 test468 \
+-\
++test478 test479 test480 \
+ test490 test491 test492 test493 test494 test495 test496 test497 test498 \
+ test499 test500 test501 test502 test503 test504 test505 test506 test507 \
+ test508 test509 test510 test511 test512 test513 test514 test515 test516 \
+diff --git a/tests/data/test478 b/tests/data/test478
+new file mode 100644
+index 0000000..7d7454d
+--- /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 0000000..48bcdfe
+--- /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 0000000..aab889f
+--- /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 0288562..b2b4366 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;
+ }
+ 
+@@ -56,76 +51,48 @@ UNITTEST_START
+    */
+   result = Curl_parsenetrc("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!");
+ 
+   /*
+    * Test a non existent login in our netrc file.
+    */
+-  free(login);
+-  login = strdup("me");
+-  abort_unless(login != NULL, "returned NULL!");
++  login = (char *)"me";
+   result = Curl_parsenetrc("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!");
+ 
+   /*
+    * 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";
+   result = Curl_parsenetrc("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!");
+ 
+   /*
+    * 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";
+   result = Curl_parsenetrc("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!");
+ 
+   /*
+    * 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";
+   result = Curl_parsenetrc("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!");
+ 
+   /*
+    * 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;
+   result = Curl_parsenetrc("example.com", &login, &password, arg);
+   fail_unless(result == 0, "Host should have been found");
+   abort_unless(password != NULL, "returned NULL!");
+@@ -139,8 +106,9 @@ UNITTEST_START
+    * with login[0] != 0.
+    */
+   free(password);
+-  password = strdup("");
+-  abort_unless(password != NULL, "returned NULL!");
++  free(login);
++  password = NULL;
++  login = NULL;
+   result = Curl_parsenetrc("example.com", &login, &password, arg);
+   fail_unless(result == 0, "Host should have been found");
+   abort_unless(password != NULL, "returned NULL!");
+@@ -154,11 +122,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;
+   result = Curl_parsenetrc("curl.example.com", &login, &password, arg);
+   fail_unless(result == 0, "Host should have been found");
+   abort_unless(password != NULL, "returned NULL!");
+@@ -172,8 +138,9 @@ UNITTEST_START
+    * with login[0] != 0.
+    */
+   free(password);
+-  password = strdup("");
+-  abort_unless(password != NULL, "returned NULL!");
++  free(login);
++  password = NULL;
++  login = NULL;
+   result = Curl_parsenetrc("curl.example.com", &login, &password, arg);
+   fail_unless(result == 0, "Host should have been found");
+   abort_unless(password != NULL, "returned NULL!");
+-- 
+2.25.1
+
diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-2.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-2.patch
new file mode 100644
index 0000000000..2f35a86eb9
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2024-11053-2.patch
@@ -0,0 +1,130 @@ 
+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
+
+Upstream-Status: Backport [https://github.com/curl/curl/commit/9fce2c55d4b0273ac99]
+CVE: CVE-2024-11053 #Regression fix
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ 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 b582c10..a282fce 100644
+--- a/lib/netrc.c
++++ b/lib/netrc.c
+@@ -228,7 +228,8 @@ static int parsenetrc(const char *host,
+ 	      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))
+@@ -237,6 +238,10 @@ static int parsenetrc(const char *host,
+             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 f608a7d..2823d96 100644
+--- a/tests/data/Makefile.inc
++++ b/tests/data/Makefile.inc
+@@ -230,7 +230,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 0000000..69e14d9
+--- /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.25.1
+
diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-pre1.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-pre1.patch
new file mode 100644
index 0000000000..55fccae316
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2024-11053-pre1.patch
@@ -0,0 +1,350 @@ 
+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
+
+Upstream-Status: Backport [https://github.com/curl/curl/commit/9bee39bfed2c413b4cc4eb306a57ac92a1854907]
+CVE: CVE-2024-11053 #Dependency Patch
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ lib/transfer.c          |  3 ++
+ lib/url.c               | 19 +++++----
+ lib/urldata.h           |  9 +++-
+ tests/data/Makefile.inc |  2 +-
+ 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 e31d1d6..ccd042b 100644
+--- a/lib/transfer.c
++++ b/lib/transfer.c
+@@ -700,6 +700,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 224b9f3..8892450 100644
+--- a/lib/url.c
++++ b/lib/url.c
+@@ -1899,10 +1899,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.
++   * User name 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;
+@@ -1915,12 +1915,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 */
+@@ -1934,13 +1935,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;
+   }
+@@ -2730,7 +2728,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;
+@@ -2778,6 +2777,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) {
+@@ -2795,6 +2795,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 ce28f25..b68d023 100644
+--- a/lib/urldata.h
++++ b/lib/urldata.h
+@@ -1207,6 +1207,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 select_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 d89e565..03cb6a0 100644
+--- a/tests/data/Makefile.inc
++++ b/tests/data/Makefile.inc
+@@ -126,7 +126,7 @@ test952 test953 test954 test955 test956 test957 test958 test959 test960 \
+ 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 test992 \
++test988 test989 test990 test991 test992 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 0000000..6dcd95f
+--- /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 0000000..e805cde
+--- /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.25.1
+
diff --git a/meta/recipes-support/curl/curl_8.7.1.bb b/meta/recipes-support/curl/curl_8.7.1.bb
index 439fcb7881..23bc6f429a 100644
--- a/meta/recipes-support/curl/curl_8.7.1.bb
+++ b/meta/recipes-support/curl/curl_8.7.1.bb
@@ -20,6 +20,9 @@  SRC_URI = " \
     file://CVE-2024-7264-2.patch \
     file://CVE-2024-8096.patch \
     file://CVE-2024-9681.patch \
+    file://CVE-2024-11053-pre1.patch \
+    file://CVE-2024-11053-1.patch \
+    file://CVE-2024-11053-2.patch \
 "
 SRC_URI[sha256sum] = "6fea2aac6a4610fbd0400afb0bcddbe7258a64c63f1f68e5855ebc0c659710cd"