diff mbox series

[scarthgap,1/3] curl: fix CVE-2024-11053

Message ID 20250214050035.1049565-1-yogita.urade@windriver.com
State Under Review
Delegated to: Steve Sakoman
Headers show
Series [scarthgap,1/3] curl: fix CVE-2024-11053 | expand

Commit Message

yurade Feb. 14, 2025, 5 a.m. UTC
From: Yogita Urade <yogita.urade@windriver.com>

When asked to both use a `.netrc` file for credentials and to
follow HTTP redirects, curl could leak the password used for
the first host to the followed-to host under certain circumstances.

This flaw only manifests itself if the netrc file has an entry
that matches the redirect target hostname but the entry either
omits just the password or omits both login and password.

CVE-2024-11053-0001 is the dependent commit and CVE-2024-11053-0002
is actual CVE fix. CVE-2024-11053-0003 fixes the regression caused by
CVE-2024-11053-0002.

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

Upstream patches:
https://github.com/curl/curl/commit/3b43a05e000aa8f65bda513f733a73fefe35d5ca
https://github.com/curl/curl/commit/e9b9bbac22c26cf67316fa8e6c6b9e831af31949
https://github.com/curl/curl/commit/9fce2c55d4b0273ac99b59bd8cb982a6d96b88cf

Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
---
 .../curl/curl/CVE-2024-11053-0001.patch       | 801 ++++++++++++++++++
 .../curl/curl/CVE-2024-11053-0002.patch       | 734 ++++++++++++++++
 .../curl/curl/CVE-2024-11053-0003.patch       | 130 +++
 meta/recipes-support/curl/curl_8.7.1.bb       |   3 +
 4 files changed, 1668 insertions(+)
 create mode 100644 meta/recipes-support/curl/curl/CVE-2024-11053-0001.patch
 create mode 100644 meta/recipes-support/curl/curl/CVE-2024-11053-0002.patch
 create mode 100644 meta/recipes-support/curl/curl/CVE-2024-11053-0003.patch

Comments

Steve Sakoman Feb. 15, 2025, 2 p.m. UTC | #1
Hi Yogita,

This series caused a number of autobuilder failures.

There were failing curl ptests:

AssertionError:
Failed ptests:
{'curl': ['257_-_HTTP_Location:_following_with_--netrc-optional_-_protocol',
'478_-_.netrc_with_multiple_accounts_for_same_host_-_protocol',
'479_-_.netrc_with_redirect_and_default_without_password_-_protocol',
'486_-_.netrc_with_redirect_and_"default"_with_no_password_or_login_-_protocol',
'2005_-_netrc_match_with_password_only_in_file,_no_username._machine_follows_-_protocol']}

And there were also failures in the sdk test, with the following error message:

fatal: unable to access
'https://git.yoctoproject.org/git/kernel-module-hello-world/': .netrc
parser error

Steve

On Thu, Feb 13, 2025 at 9:01 PM Urade, Yogita via
lists.openembedded.org
<Yogita.Urade=windriver.com@lists.openembedded.org> wrote:
>
> From: Yogita Urade <yogita.urade@windriver.com>
>
> When asked to both use a `.netrc` file for credentials and to
> follow HTTP redirects, curl could leak the password used for
> the first host to the followed-to host under certain circumstances.
>
> This flaw only manifests itself if the netrc file has an entry
> that matches the redirect target hostname but the entry either
> omits just the password or omits both login and password.
>
> CVE-2024-11053-0001 is the dependent commit and CVE-2024-11053-0002
> is actual CVE fix. CVE-2024-11053-0003 fixes the regression caused by
> CVE-2024-11053-0002.
>
> Reference:
> https://curl.se/docs/CVE-2024-11053.html
>
> Upstream patches:
> https://github.com/curl/curl/commit/3b43a05e000aa8f65bda513f733a73fefe35d5ca
> https://github.com/curl/curl/commit/e9b9bbac22c26cf67316fa8e6c6b9e831af31949
> https://github.com/curl/curl/commit/9fce2c55d4b0273ac99b59bd8cb982a6d96b88cf
>
> Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
> ---
>  .../curl/curl/CVE-2024-11053-0001.patch       | 801 ++++++++++++++++++
>  .../curl/curl/CVE-2024-11053-0002.patch       | 734 ++++++++++++++++
>  .../curl/curl/CVE-2024-11053-0003.patch       | 130 +++
>  meta/recipes-support/curl/curl_8.7.1.bb       |   3 +
>  4 files changed, 1668 insertions(+)
>  create mode 100644 meta/recipes-support/curl/curl/CVE-2024-11053-0001.patch
>  create mode 100644 meta/recipes-support/curl/curl/CVE-2024-11053-0002.patch
>  create mode 100644 meta/recipes-support/curl/curl/CVE-2024-11053-0003.patch
>
> diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-0001.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-0001.patch
> new file mode 100644
> index 0000000000..c65c3c9417
> --- /dev/null
> +++ b/meta/recipes-support/curl/curl/CVE-2024-11053-0001.patch
> @@ -0,0 +1,801 @@
> +From 3b43a05e000aa8f65bda513f733a73fefe35d5ca Mon Sep 17 00:00:00 2001
> +From: Daniel Stenberg <daniel@haxx.se>
> +Date: Thu, 10 Oct 2024 18:08:07 +0200
> +Subject: [PATCH] netrc: cache the netrc file in memory
> +
> +So that on redirects etc it does not reread the file but just parses it
> +again.
> +
> +Reported-by: Pierre-Etienne Meunier
> +Fixes #15248
> +Closes #15259
> +
> +CVE: CVE-2024-11053
> +Upstream-Status: Backport [https://github.com/curl/curl/commit/3b43a05e000aa8f65bda513f733a73fefe35d5ca]
> +
> +Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
> +---
> + lib/multi.c           |   3 +
> + lib/netrc.c           | 406 ++++++++++++++++++++++++------------------
> + lib/netrc.h           |  14 +-
> + lib/url.c             |   4 +-
> + lib/urldata.h         |   5 +
> + tests/unit/unit1304.c |  48 ++++-
> + 6 files changed, 292 insertions(+), 188 deletions(-)
> +
> +diff --git a/lib/multi.c b/lib/multi.c
> +index ed9cac7..8a05b37 100644
> +--- a/lib/multi.c
> ++++ b/lib/multi.c
> +@@ -800,6 +800,9 @@ static CURLcode multi_done(struct Curl_easy *data,
> +       data->state.lastconnect_id = -1;
> +   }
> +
> ++  /* flush the netrc cache */
> ++  Curl_netrc_cleanup(&data->state.netrc);
> ++
> +   return result;
> + }
> +
> +diff --git a/lib/netrc.c b/lib/netrc.c
> +index cd2a284..d72959b 100644
> +--- a/lib/netrc.c
> ++++ b/lib/netrc.c
> +@@ -31,7 +31,6 @@
> +
> + #include <curl/curl.h>
> + #include "netrc.h"
> +-#include "strtok.h"
> + #include "strcase.h"
> + #include "curl_get_line.h"
> +
> +@@ -49,21 +48,56 @@ enum host_lookup_state {
> +   MACDEF
> + };
> +
> ++enum found_state {
> ++  NONE,
> ++  LOGIN,
> ++  PASSWORD
> ++};
> ++
> + #define NETRC_FILE_MISSING 1
> + #define NETRC_FAILED -1
> + #define NETRC_SUCCESS 0
> +
> + #define MAX_NETRC_LINE 4096
> ++#define MAX_NETRC_FILE (64*1024)
> ++#define MAX_NETRC_TOKEN 128
> ++
> ++static CURLcode file2memory(const char *filename, struct dynbuf *filebuf)
> ++{
> ++  CURLcode result = CURLE_OK;
> ++  FILE *file = fopen(filename, FOPEN_READTEXT);
> ++  struct dynbuf linebuf;
> ++  Curl_dyn_init(&linebuf, MAX_NETRC_LINE);
> ++
> ++  if(file) {
> ++    while(Curl_get_line(&linebuf, file)) {
> ++      const char *line = Curl_dyn_ptr(&linebuf);
> ++      /* skip comments on load */
> ++      while(ISBLANK(*line))
> ++        line++;
> ++      if(*line == '#')
> ++        continue;
> ++      result = Curl_dyn_add(filebuf, line);
> ++      if(result)
> ++        goto done;
> ++    }
> ++  }
> ++done:
> ++  Curl_dyn_free(&linebuf);
> ++  if(file)
> ++    fclose(file);
> ++  return result;
> ++}
> +
> + /*
> +  * Returns zero on success.
> +  */
> +-static int parsenetrc(const char *host,
> ++static int parsenetrc(struct store_netrc *store,
> ++                      const char *host,
> +                       char **loginp,
> +                       char **passwordp,
> +-                      char *netrcfile)
> ++                      const char *netrcfile)
> + {
> +-  FILE *file;
> +   int retcode = NETRC_FILE_MISSING;
> +   char *login = *loginp;
> +   char *password = *passwordp;
> +@@ -71,204 +105,211 @@ static int parsenetrc(const char *host,
> +   bool login_alloc = FALSE;
> +   bool password_alloc = FALSE;
> +   enum host_lookup_state state = NOTHING;
> ++  enum found_state found = NONE;
> ++  bool our_login = TRUE;  /* With specific_login, found *our* login name (or
> ++                             login-less line) */
> ++  bool done = FALSE;
> ++  char *netrcbuffer;
> ++  struct dynbuf token;
> ++  struct dynbuf *filebuf = &store->filebuf;
> ++  Curl_dyn_init(&token, MAX_NETRC_TOKEN);
> +
> +-  char state_login = 0;      /* Found a login keyword */
> +-  char state_password = 0;   /* Found a password keyword */
> +-  int state_our_login = TRUE;  /* With specific_login, found *our* login
> +-                                  name (or login-less line) */
> +-
> +-  DEBUGASSERT(netrcfile);
> ++  if(!store->loaded) {
> ++    if(file2memory(netrcfile, filebuf))
> ++      return NETRC_FAILED;
> ++    store->loaded = TRUE;
> ++  }
> +
> +-  file = fopen(netrcfile, FOPEN_READTEXT);
> +-  if(file) {
> +-    bool done = FALSE;
> +-    struct dynbuf buf;
> +-    Curl_dyn_init(&buf, MAX_NETRC_LINE);
> ++  netrcbuffer = Curl_dyn_ptr(filebuf);
> +
> +-    while(!done && Curl_get_line(&buf, file)) {
> +-      char *tok;
> ++  while(!done) {
> ++    char *tok = netrcbuffer;
> ++    while(tok) {
> +       char *tok_end;
> +       bool quoted;
> +-      char *netrcbuffer = Curl_dyn_ptr(&buf);
> ++      Curl_dyn_reset(&token);
> ++      while(ISBLANK(*tok))
> ++        tok++;
> ++      /* tok is first non-space letter */
> +       if(state == MACDEF) {
> +-        if((netrcbuffer[0] == '\n') || (netrcbuffer[0] == '\r'))
> +-          state = NOTHING;
> +-        else
> +-          continue;
> ++        if((*tok == '\n') || (*tok == '\r'))
> ++          state = NOTHING; /* end of macro definition */
> +       }
> +-      tok = netrcbuffer;
> +-      while(tok) {
> +-        while(ISBLANK(*tok))
> +-          tok++;
> +-        /* tok is first non-space letter */
> +-        if(!*tok || (*tok == '#'))
> +-          /* end of line or the rest is a comment */
> +-          break;
> ++      if(!*tok || (*tok == '\n'))
> ++        /* end of line  */
> ++        break;
> +
> +-        /* leading double-quote means quoted string */
> +-        quoted = (*tok == '\"');
> ++      /* leading double-quote means quoted string */
> ++      quoted = (*tok == '\"');
> +
> +-        tok_end = tok;
> +-        if(!quoted) {
> +-          while(!ISSPACE(*tok_end))
> +-            tok_end++;
> +-          *tok_end = 0;
> ++      tok_end = tok;
> ++      if(!quoted) {
> ++        size_t len = 0;
> ++        while(!ISSPACE(*tok_end)) {
> ++          tok_end++;
> ++          len++;
> +         }
> +-        else {
> +-          bool escape = FALSE;
> +-          bool endquote = FALSE;
> +-          char *store = tok;
> +-          tok_end++; /* pass the leading quote */
> +-          while(*tok_end) {
> +-            char s = *tok_end;
> +-            if(escape) {
> +-              escape = FALSE;
> +-              switch(s) {
> +-              case 'n':
> +-                s = '\n';
> +-                break;
> +-              case 'r':
> +-                s = '\r';
> +-                break;
> +-              case 't':
> +-                s = '\t';
> +-                break;
> +-              }
> +-            }
> +-            else if(s == '\\') {
> +-              escape = TRUE;
> +-              tok_end++;
> +-              continue;
> +-            }
> +-            else if(s == '\"') {
> +-              tok_end++; /* pass the ending quote */
> +-              endquote = TRUE;
> ++        if(!len || Curl_dyn_addn(&token, tok, len)) {
> ++          retcode = NETRC_FAILED;
> ++          goto out;
> ++        }
> ++      }
> ++      else {
> ++        bool escape = FALSE;
> ++        bool endquote = FALSE;
> ++        tok_end++; /* pass the leading quote */
> ++        while(*tok_end) {
> ++          char s = *tok_end;
> ++          if(escape) {
> ++            escape = FALSE;
> ++            switch(s) {
> ++            case 'n':
> ++              s = '\n';
> ++              break;
> ++            case 'r':
> ++              s = '\r';
> ++              break;
> ++            case 't':
> ++              s = '\t';
> +               break;
> +             }
> +-            *store++ = s;
> ++          }
> ++          else if(s == '\\') {
> ++            escape = TRUE;
> +             tok_end++;
> ++            continue;
> +           }
> +-          *store = 0;
> +-          if(escape || !endquote) {
> +-            /* bad syntax, get out */
> ++          else if(s == '\"') {
> ++            tok_end++; /* pass the ending quote */
> ++            endquote = TRUE;
> ++            break;
> ++          }
> ++          if(Curl_dyn_addn(&token, &s, 1)) {
> +             retcode = NETRC_FAILED;
> +             goto out;
> +           }
> ++          tok_end++;
> +         }
> +-
> +-        if((login && *login) && (password && *password)) {
> +-          done = TRUE;
> +-          break;
> ++        if(escape || !endquote) {
> ++          /* bad syntax, get out */
> ++          retcode = NETRC_FAILED;
> ++          goto out;
> +         }
> ++      }
> +
> +-        switch(state) {
> +-        case NOTHING:
> +-          if(strcasecompare("macdef", tok)) {
> +-            /* Define a macro. A macro is defined with the specified name; its
> +-               contents begin with the next .netrc line and continue until a
> +-               null line (consecutive new-line characters) is encountered. */
> +-            state = MACDEF;
> +-          }
> +-          else if(strcasecompare("machine", tok)) {
> +-            /* the next tok is the machine name, this is in itself the
> +-               delimiter that starts the stuff entered for this machine,
> +-               after this we need to search for 'login' and
> +-               'password'. */
> +-            state = HOSTFOUND;
> +-          }
> +-          else if(strcasecompare("default", tok)) {
> +-            state = HOSTVALID;
> +-            retcode = NETRC_SUCCESS; /* we did find our host */
> +-          }
> +-          break;
> +-        case MACDEF:
> +-          if(!strlen(tok)) {
> +-            state = NOTHING;
> +-          }
> +-          break;
> +-        case HOSTFOUND:
> +-          if(strcasecompare(host, tok)) {
> +-            /* and yes, this is our host! */
> +-            state = HOSTVALID;
> +-            retcode = NETRC_SUCCESS; /* we did find our host */
> ++      if((login && *login) && (password && *password)) {
> ++        done = TRUE;
> ++        break;
> ++      }
> ++
> ++      tok = Curl_dyn_ptr(&token);
> ++
> ++      switch(state) {
> ++      case NOTHING:
> ++        if(strcasecompare("macdef", tok))
> ++          /* Define a macro. A macro is defined with the specified name; its
> ++             contents begin with the next .netrc line and continue until a
> ++             null line (consecutive new-line characters) is encountered. */
> ++          state = MACDEF;
> ++        else if(strcasecompare("machine", tok))
> ++          /* the next tok is the machine name, this is in itself the delimiter
> ++             that starts the stuff entered for this machine, after this we
> ++             need to search for 'login' and 'password'. */
> ++          state = HOSTFOUND;
> ++        else if(strcasecompare("default", tok)) {
> ++          state = HOSTVALID;
> ++          retcode = NETRC_SUCCESS; /* we did find our host */
> ++        }
> ++        break;
> ++      case MACDEF:
> ++        if(!*tok)
> ++          state = NOTHING;
> ++        break;
> ++      case HOSTFOUND:
> ++        if(strcasecompare(host, tok)) {
> ++          /* and yes, this is our host! */
> ++          state = HOSTVALID;
> ++          retcode = NETRC_SUCCESS; /* we did find our host */
> ++        }
> ++        else
> ++          /* not our host */
> ++          state = NOTHING;
> ++        break;
> ++      case HOSTVALID:
> ++        /* we are now parsing sub-keywords concerning "our" host */
> ++        if(found == LOGIN) {
> ++          if(specific_login) {
> ++            our_login = !Curl_timestrcmp(login, tok);
> +           }
> +-          else
> +-            /* not our host */
> +-            state = NOTHING;
> +-          break;
> +-        case HOSTVALID:
> +-          /* we are now parsing sub-keywords concerning "our" host */
> +-          if(state_login) {
> +-            if(specific_login) {
> +-              state_our_login = !Curl_timestrcmp(login, tok);
> +-            }
> +-            else if(!login || Curl_timestrcmp(login, tok)) {
> +-              if(login_alloc) {
> +-                free(login);
> +-                login_alloc = FALSE;
> +-              }
> +-              login = strdup(tok);
> +-              if(!login) {
> +-                retcode = NETRC_FAILED; /* allocation failed */
> +-                goto out;
> +-              }
> +-              login_alloc = TRUE;
> ++          else if(!login || Curl_timestrcmp(login, tok)) {
> ++            if(login_alloc)
> ++              free(login);
> ++            login = strdup(tok);
> ++            if(!login) {
> ++              retcode = NETRC_FAILED; /* allocation failed */
> ++              goto out;
> +             }
> +-            state_login = 0;
> ++            login_alloc = TRUE;
> +           }
> +-          else if(state_password) {
> +-            if((state_our_login || !specific_login)
> +-               && (!password || Curl_timestrcmp(password, tok))) {
> +-              if(password_alloc) {
> +-                free(password);
> +-                password_alloc = FALSE;
> +-              }
> +-              password = strdup(tok);
> +-              if(!password) {
> +-                retcode = NETRC_FAILED; /* allocation failed */
> +-                goto out;
> +-              }
> +-              password_alloc = TRUE;
> ++          found = NONE;
> ++        }
> ++        else if(found == PASSWORD) {
> ++          if((our_login || !specific_login) &&
> ++             (!password || Curl_timestrcmp(password, tok))) {
> ++            if(password_alloc)
> ++              free(password);
> ++            password = strdup(tok);
> ++            if(!password) {
> ++              retcode = NETRC_FAILED; /* allocation failed */
> ++              goto out;
> +             }
> +-            state_password = 0;
> +-          }
> +-          else if(strcasecompare("login", tok))
> +-            state_login = 1;
> +-          else if(strcasecompare("password", tok))
> +-            state_password = 1;
> +-          else if(strcasecompare("machine", tok)) {
> +-            /* ok, there's machine here go => */
> +-            state = HOSTFOUND;
> +-            state_our_login = FALSE;
> ++            password_alloc = TRUE;
> +           }
> +-          break;
> +-        } /* switch (state) */
> +-        tok = ++tok_end;
> +-      }
> +-    } /* while Curl_get_line() */
> ++          found = NONE;
> ++        }
> ++        else if(strcasecompare("login", tok))
> ++          found = LOGIN;
> ++        else if(strcasecompare("password", tok))
> ++          found = PASSWORD;
> ++        else if(strcasecompare("machine", tok)) {
> ++          /* ok, there is machine here go => */
> ++          state = HOSTFOUND;
> ++          found = NONE;
> ++        }
> ++        break;
> ++      } /* switch (state) */
> ++      tok = ++tok_end;
> ++    }
> ++    if(!done) {
> ++      char *nl = NULL;
> ++      if(tok)
> ++        nl = strchr(tok, '\n');
> ++      if(!nl)
> ++        break;
> ++      /* point to next line */
> ++      netrcbuffer = &nl[1];
> ++    }
> ++  } /* while !done */
> +
> + out:
> +-    Curl_dyn_free(&buf);
> +-    if(!retcode) {
> +-      /* success */
> +-      if(login_alloc) {
> +-        if(*loginp)
> +-          free(*loginp);
> +-        *loginp = login;
> +-      }
> +-      if(password_alloc) {
> +-        if(*passwordp)
> +-          free(*passwordp);
> +-        *passwordp = password;
> +-      }
> ++  Curl_dyn_free(&token);
> ++  if(!retcode) {
> ++    /* success */
> ++    if(login_alloc) {
> ++      free(*loginp);
> ++      *loginp = login;
> +     }
> +-    else {
> +-      if(login_alloc)
> +-        free(login);
> +-      if(password_alloc)
> +-        free(password);
> ++    if(password_alloc) {
> ++      free(*passwordp);
> ++      *passwordp = password;
> +     }
> +-    fclose(file);
> ++  }
> ++  else {
> ++    Curl_dyn_free(filebuf);
> ++    if(login_alloc)
> ++      free(login);
> ++    if(password_alloc)
> ++      free(password);
> +   }
> +
> +   return retcode;
> +@@ -280,7 +321,8 @@ out:
> +  * *loginp and *passwordp MUST be allocated if they aren't NULL when passed
> +  * in.
> +  */
> +-int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
> ++int Curl_parsenetrc(struct store_netrc *store, const char *host,
> ++                    char **loginp, char **passwordp,
> +                     char *netrcfile)
> + {
> +   int retcode = 1;
> +@@ -329,7 +371,7 @@ int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
> +       free(homea);
> +       return -1;
> +     }
> +-    retcode = parsenetrc(host, loginp, passwordp, filealloc);
> ++    retcode = parsenetrc(store, host, loginp, passwordp, filealloc);
> +     free(filealloc);
> + #ifdef _WIN32
> +     if(retcode == NETRC_FILE_MISSING) {
> +@@ -339,15 +381,25 @@ int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
> +         free(homea);
> +         return -1;
> +       }
> +-      retcode = parsenetrc(host, loginp, passwordp, filealloc);
> ++      retcode = parsenetrc(store, host, loginp, passwordp, filealloc);
> +       free(filealloc);
> +     }
> + #endif
> +     free(homea);
> +   }
> +   else
> +-    retcode = parsenetrc(host, loginp, passwordp, netrcfile);
> ++    retcode = parsenetrc(store, host, loginp, passwordp, netrcfile);
> +   return retcode;
> + }
> +
> ++void Curl_netrc_init(struct store_netrc *s)
> ++{
> ++  Curl_dyn_init(&s->filebuf, MAX_NETRC_FILE);
> ++  s->loaded = FALSE;
> ++}
> ++void Curl_netrc_cleanup(struct store_netrc *s)
> ++{
> ++  Curl_dyn_free(&s->filebuf);
> ++  s->loaded = FALSE;
> ++}
> + #endif
> +diff --git a/lib/netrc.h b/lib/netrc.h
> +index 9f2815f..fac223a 100644
> +--- a/lib/netrc.h
> ++++ b/lib/netrc.h
> +@@ -26,9 +26,19 @@
> +
> + #include "curl_setup.h"
> + #ifndef CURL_DISABLE_NETRC
> ++#include "dynbuf.h"
> ++
> ++struct store_netrc {
> ++  struct dynbuf filebuf;
> ++  char *filename;
> ++  BIT(loaded);
> ++};
> ++
> ++void Curl_netrc_init(struct store_netrc *s);
> ++void Curl_netrc_cleanup(struct store_netrc *s);
> +
> + /* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
> +-int Curl_parsenetrc(const char *host, char **loginp,
> ++int Curl_parsenetrc(struct store_netrc *s, const char *host, char **loginp,
> +                     char **passwordp, char *filename);
> +   /* Assume: (*passwordp)[0]=0, host[0] != 0.
> +    * If (*loginp)[0] = 0, search for login and password within a machine
> +@@ -38,6 +48,8 @@ int Curl_parsenetrc(const char *host, char **loginp,
> + #else
> + /* disabled */
> + #define Curl_parsenetrc(a,b,c,d,e,f) 1
> ++#define Curl_netrc_init(x)
> ++#define Curl_netrc_cleanup(x)
> + #endif
> +
> + #endif /* HEADER_CURL_NETRC_H */
> +diff --git a/lib/url.c b/lib/url.c
> +index 224b9f3..5cdf83c 100644
> +--- a/lib/url.c
> ++++ b/lib/url.c
> +@@ -329,6 +329,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
> +   Curl_wildcard_dtor(&data->wildcard);
> +   Curl_freeset(data);
> +   Curl_headers_cleanup(data);
> ++  Curl_netrc_cleanup(&data->state.netrc);
> +   free(data);
> +   return CURLE_OK;
> + }
> +@@ -532,6 +533,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
> +
> +     data->progress.flags |= PGRS_HIDE;
> +     data->state.current_speed = -1; /* init to negative == impossible */
> ++    Curl_netrc_init(&data->state.netrc);
> +   }
> +
> +   if(result) {
> +@@ -2736,7 +2738,7 @@ static CURLcode override_login(struct Curl_easy *data,
> +       url_provided = TRUE;
> +     }
> +
> +-    ret = Curl_parsenetrc(conn->host.name,
> ++    ret = Curl_parsenetrc(&data->state.netrc, conn->host.name,
> +                           userp, passwdp,
> +                           data->set.str[STRING_NETRC_FILE]);
> +     if(ret > 0) {
> +diff --git a/lib/urldata.h b/lib/urldata.h
> +index ce28f25..165136e 100644
> +--- a/lib/urldata.h
> ++++ b/lib/urldata.h
> +@@ -144,6 +144,7 @@ typedef unsigned int curl_prot_t;
> + #include "dynbuf.h"
> + #include "dynhds.h"
> + #include "request.h"
> ++#include "netrc.h"
> +
> + /* return the count of bytes sent, or -1 on error */
> + typedef ssize_t (Curl_send)(struct Curl_easy *data,   /* transfer */
> +@@ -1324,6 +1325,10 @@ struct UrlState {
> +   struct curl_trc_feat *feat; /* opt. trace feature transfer is part of */
> + #endif
> +
> ++#ifndef CURL_DISABLE_NETRC
> ++  struct store_netrc netrc;
> ++#endif
> ++
> +   /* Dynamically allocated strings, MUST be freed before this struct is
> +      killed. */
> +   struct dynamically_allocated_data {
> +diff --git a/tests/unit/unit1304.c b/tests/unit/unit1304.c
> +index 0288562..34cfb7a 100644
> +--- a/tests/unit/unit1304.c
> ++++ b/tests/unit/unit1304.c
> +@@ -49,17 +49,22 @@ static void unit_stop(void)
> + }
> +
> + UNITTEST_START
> ++{
> +   int result;
> ++  struct store_netrc store;
> +
> +   /*
> +    * Test a non existent host in our netrc file.
> +    */
> +-  result = Curl_parsenetrc("test.example.com", &login, &password, arg);
> ++  Curl_netrc_init(&store);
> ++  result = Curl_parsenetrc(&store,
> ++                           "test.example.com", &s_login, &s_password, arg);
> +   fail_unless(result == 1, "Host not found should return 1");
> +   abort_unless(password != NULL, "returned NULL!");
> +   fail_unless(password[0] == 0, "password should not have been changed");
> +   abort_unless(login != NULL, "returned NULL!");
> +   fail_unless(login[0] == 0, "login should not have been changed");
> ++  Curl_netrc_cleanup(&store);
> +
> +   /*
> +    * Test a non existent login in our netrc file.
> +@@ -67,13 +72,16 @@ UNITTEST_START
> +   free(login);
> +   login = strdup("me");
> +   abort_unless(login != NULL, "returned NULL!");
> +-  result = Curl_parsenetrc("example.com", &login, &password, arg);
> ++  Curl_netrc_init(&store);
> ++  result = Curl_parsenetrc(&store,
> ++                           "example.com", &s_login, &s_password, arg);
> +   fail_unless(result == 0, "Host should have been found");
> +   abort_unless(password != NULL, "returned NULL!");
> +   fail_unless(password[0] == 0, "password should not have been changed");
> +   abort_unless(login != NULL, "returned NULL!");
> +   fail_unless(strncmp(login, "me", 2) == 0,
> +               "login should not have been changed");
> ++  Curl_netrc_cleanup(&store);
> +
> +   /*
> +    * Test a non existent login and host in our netrc file.
> +@@ -81,13 +89,16 @@ UNITTEST_START
> +   free(login);
> +   login = strdup("me");
> +   abort_unless(login != NULL, "returned NULL!");
> +-  result = Curl_parsenetrc("test.example.com", &login, &password, arg);
> ++  Curl_netrc_init(&store);
> ++  result = Curl_parsenetrc(&store,
> ++                           "test.example.com", &s_login, &s_password, arg);
> +   fail_unless(result == 1, "Host not found should return 1");
> +   abort_unless(password != NULL, "returned NULL!");
> +   fail_unless(password[0] == 0, "password should not have been changed");
> +   abort_unless(login != NULL, "returned NULL!");
> +   fail_unless(strncmp(login, "me", 2) == 0,
> +               "login should not have been changed");
> ++  Curl_netrc_cleanup(&store);
> +
> +   /*
> +    * Test a non existent login (substring of an existing one) in our
> +@@ -96,13 +107,16 @@ UNITTEST_START
> +   free(login);
> +   login = strdup("admi");
> +   abort_unless(login != NULL, "returned NULL!");
> +-  result = Curl_parsenetrc("example.com", &login, &password, arg);
> ++  Curl_netrc_init(&store);
> ++  result = Curl_parsenetrc(&store,
> ++                           "example.com", &s_login, &s_password, arg);
> +   fail_unless(result == 0, "Host should have been found");
> +   abort_unless(password != NULL, "returned NULL!");
> +   fail_unless(password[0] == 0, "password should not have been changed");
> +   abort_unless(login != NULL, "returned NULL!");
> +   fail_unless(strncmp(login, "admi", 4) == 0,
> +               "login should not have been changed");
> ++  Curl_netrc_cleanup(&store);
> +
> +   /*
> +    * Test a non existent login (superstring of an existing one)
> +@@ -111,13 +125,16 @@ UNITTEST_START
> +   free(login);
> +   login = strdup("adminn");
> +   abort_unless(login != NULL, "returned NULL!");
> +-  result = Curl_parsenetrc("example.com", &login, &password, arg);
> ++  Curl_netrc_init(&store);
> ++  result = Curl_parsenetrc(&store,
> ++                           "example.com", &s_login, &s_password, arg);
> +   fail_unless(result == 0, "Host should have been found");
> +   abort_unless(password != NULL, "returned NULL!");
> +   fail_unless(password[0] == 0, "password should not have been changed");
> +   abort_unless(login != NULL, "returned NULL!");
> +   fail_unless(strncmp(login, "adminn", 6) == 0,
> +               "login should not have been changed");
> ++  Curl_netrc_cleanup(&store);
> +
> +   /*
> +    * Test for the first existing host in our netrc file
> +@@ -126,13 +143,16 @@ UNITTEST_START
> +   free(login);
> +   login = strdup("");
> +   abort_unless(login != NULL, "returned NULL!");
> +-  result = Curl_parsenetrc("example.com", &login, &password, arg);
> ++  Curl_netrc_init(&store);
> ++  result = Curl_parsenetrc(&store,
> ++                           "example.com", &s_login, &s_password, arg);
> +   fail_unless(result == 0, "Host should have been found");
> +   abort_unless(password != NULL, "returned NULL!");
> +   fail_unless(strncmp(password, "passwd", 6) == 0,
> +               "password should be 'passwd'");
> +   abort_unless(login != NULL, "returned NULL!");
> +   fail_unless(strncmp(login, "admin", 5) == 0, "login should be 'admin'");
> ++  Curl_netrc_cleanup(&store);
> +
> +   /*
> +    * Test for the first existing host in our netrc file
> +@@ -141,13 +161,16 @@ UNITTEST_START
> +   free(password);
> +   password = strdup("");
> +   abort_unless(password != NULL, "returned NULL!");
> +-  result = Curl_parsenetrc("example.com", &login, &password, arg);
> ++  Curl_netrc_init(&store);
> ++  result = Curl_parsenetrc(&store,
> ++                           "example.com", &s_login, &s_password, arg);
> +   fail_unless(result == 0, "Host should have been found");
> +   abort_unless(password != NULL, "returned NULL!");
> +   fail_unless(strncmp(password, "passwd", 6) == 0,
> +               "password should be 'passwd'");
> +   abort_unless(login != NULL, "returned NULL!");
> +   fail_unless(strncmp(login, "admin", 5) == 0, "login should be 'admin'");
> ++  Curl_netrc_cleanup(&store);
> +
> +   /*
> +    * Test for the second existing host in our netrc file
> +@@ -159,13 +182,16 @@ UNITTEST_START
> +   free(login);
> +   login = strdup("");
> +   abort_unless(login != NULL, "returned NULL!");
> +-  result = Curl_parsenetrc("curl.example.com", &login, &password, arg);
> ++  Curl_netrc_init(&store);
> ++  result = Curl_parsenetrc(&store,
> ++                           "curl.example.com", &s_login, &s_password, arg);
> +   fail_unless(result == 0, "Host should have been found");
> +   abort_unless(password != NULL, "returned NULL!");
> +   fail_unless(strncmp(password, "none", 4) == 0,
> +               "password should be 'none'");
> +   abort_unless(login != NULL, "returned NULL!");
> +   fail_unless(strncmp(login, "none", 4) == 0, "login should be 'none'");
> ++  Curl_netrc_cleanup(&store);
> +
> +   /*
> +    * Test for the second existing host in our netrc file
> +@@ -174,14 +200,18 @@ UNITTEST_START
> +   free(password);
> +   password = strdup("");
> +   abort_unless(password != NULL, "returned NULL!");
> +-  result = Curl_parsenetrc("curl.example.com", &login, &password, arg);
> ++  Curl_netrc_init(&store);
> ++  result = Curl_parsenetrc(&store,
> ++                           "curl.example.com", &s_login, &s_password, arg);
> +   fail_unless(result == 0, "Host should have been found");
> +   abort_unless(password != NULL, "returned NULL!");
> +   fail_unless(strncmp(password, "none", 4) == 0,
> +               "password should be 'none'");
> +   abort_unless(login != NULL, "returned NULL!");
> +   fail_unless(strncmp(login, "none", 4) == 0, "login should be 'none'");
> ++  Curl_netrc_cleanup(&store);
> +
> ++}
> + UNITTEST_STOP
> +
> + #else
> +--
> +2.40.0
> diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-0002.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-0002.patch
> new file mode 100644
> index 0000000000..f066b0b1d5
> --- /dev/null
> +++ b/meta/recipes-support/curl/curl/CVE-2024-11053-0002.patch
> @@ -0,0 +1,734 @@
> +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
> +
> +Conflicts:
> +- Use old variable names password and loging instead of s_password and s_login.
> +- Test files are added in Makefile.inc.
> +
> +CVE: CVE-2024-11053
> +Upstream-Status: Backport [https://github.com/curl/curl/commit/e9b9bbac22c26cf67316fa8e6c6b9e831af31949]
> +
> +Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
> +---
> + lib/netrc.c             | 113 +++++++++++++++++++++++-----------------
> + lib/url.c               |  60 ++++++++++++++-------
> + 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, 345 insertions(+), 123 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 d72959b..8b0192a 100644
> +--- a/lib/netrc.c
> ++++ b/lib/netrc.c
> +@@ -54,6 +54,9 @@ enum found_state {
> +   PASSWORD
> + };
> +
> ++#define FOUND_LOGIN    1
> ++#define FOUND_PASSWORD 2
> ++
> + #define NETRC_FILE_MISSING 1
> + #define NETRC_FAILED -1
> + #define NETRC_SUCCESS 0
> +@@ -94,24 +97,24 @@ done:
> +  */
> + static int parsenetrc(struct store_netrc *store,
> +                       const char *host,
> +-                      char **loginp,
> ++                      char **loginp, /* might point to a username */
> +                       char **passwordp,
> +                       const char *netrcfile)
> + {
> +   int retcode = NETRC_FILE_MISSING;
> +   char *login = *loginp;
> +-  char *password = *passwordp;
> +-  bool specific_login = (login && *login != 0);
> +-  bool login_alloc = FALSE;
> +-  bool password_alloc = FALSE;
> ++  char *password = NULL;
> ++  bool specific_login = login; /* points to something */
> +   enum host_lookup_state state = NOTHING;
> +-  enum found_state found = NONE;
> +-  bool our_login = TRUE;  /* With specific_login, found *our* login name (or
> +-                             login-less line) */
> ++  enum found_state keyword = NONE;
> ++  unsigned char found = 0; /* login + password found bits, as they can come in
> ++                              any order */
> ++  bool our_login = FALSE;  /* found our login name */
> +   bool done = FALSE;
> +   char *netrcbuffer;
> +   struct dynbuf token;
> +   struct dynbuf *filebuf = &store->filebuf;
> ++  DEBUGASSERT(!*passwordp);
> +   Curl_dyn_init(&token, MAX_NETRC_TOKEN);
> +
> +   if(!store->loaded) {
> +@@ -124,7 +127,7 @@ static int parsenetrc(struct store_netrc *store,
> +
> +   while(!done) {
> +     char *tok = netrcbuffer;
> +-    while(tok) {
> ++    while(tok && !done) {
> +       char *tok_end;
> +       bool quoted;
> +       Curl_dyn_reset(&token);
> +@@ -197,11 +200,6 @@ static int parsenetrc(struct store_netrc *store,
> +         }
> +       }
> +
> +-      if((login && *login) && (password && *password)) {
> +-        done = TRUE;
> +-        break;
> +-      }
> +-
> +       tok = Curl_dyn_ptr(&token);
> +
> +       switch(state) {
> +@@ -211,11 +209,18 @@ static int parsenetrc(struct store_netrc *store,
> +              contents begin with the next .netrc line and continue until a
> +              null line (consecutive new-line characters) is encountered. */
> +           state = MACDEF;
> +-        else if(strcasecompare("machine", tok))
> ++        else if(strcasecompare("machine", tok)) {
> +           /* the next tok is the machine name, this is in itself the delimiter
> +              that starts the stuff entered for this machine, after this we
> +              need to search for 'login' and 'password'. */
> +           state = HOSTFOUND;
> ++          keyword = NONE;
> ++          found = 0;
> ++          our_login = FALSE;
> ++          Curl_safefree(password);
> ++          if(!specific_login)
> ++            Curl_safefree(login);
> ++        }
> +         else if(strcasecompare("default", tok)) {
> +           state = HOSTVALID;
> +           retcode = NETRC_SUCCESS; /* we did find our host */
> +@@ -237,44 +242,54 @@ static int parsenetrc(struct store_netrc *store,
> +         break;
> +       case HOSTVALID:
> +         /* we are now parsing sub-keywords concerning "our" host */
> +-        if(found == LOGIN) {
> +-          if(specific_login) {
> ++        if(keyword == LOGIN) {
> ++          if(specific_login)
> +             our_login = !Curl_timestrcmp(login, tok);
> +-          }
> +-          else if(!login || Curl_timestrcmp(login, tok)) {
> +-            if(login_alloc)
> +-              free(login);
> ++          else {
> ++            our_login = TRUE;
> ++            free(login);
> +             login = strdup(tok);
> +             if(!login) {
> +               retcode = NETRC_FAILED; /* allocation failed */
> +               goto out;
> +             }
> +-            login_alloc = TRUE;
> +           }
> +-          found = NONE;
> ++          found |= FOUND_LOGIN;
> ++          keyword = NONE;
> +         }
> +-        else if(found == PASSWORD) {
> +-          if((our_login || !specific_login) &&
> +-             (!password || Curl_timestrcmp(password, tok))) {
> +-            if(password_alloc)
> +-              free(password);
> +-            password = strdup(tok);
> +-            if(!password) {
> +-              retcode = NETRC_FAILED; /* allocation failed */
> +-              goto out;
> +-            }
> +-            password_alloc = TRUE;
> ++        else if(keyword == PASSWORD) {
> ++          free(password);
> ++          password = strdup(tok);
> ++          if(!password) {
> ++            retcode = NETRC_FAILED; /* allocation failed */
> ++            goto out;
> +           }
> +-          found = NONE;
> ++          found |= FOUND_PASSWORD;
> ++          keyword = NONE;
> +         }
> +         else if(strcasecompare("login", tok))
> +-          found = LOGIN;
> ++          keyword = LOGIN;
> +         else if(strcasecompare("password", tok))
> +-          found = PASSWORD;
> ++          keyword = PASSWORD;
> +         else if(strcasecompare("machine", tok)) {
> +-          /* ok, there is machine here go => */
> ++          /* a new machine here */
> +           state = HOSTFOUND;
> +-          found = NONE;
> ++          keyword = NONE;
> ++          found = 0;
> ++          Curl_safefree(password);
> ++          if(!specific_login)
> ++            Curl_safefree(login);
> ++        }
> ++        else if(strcasecompare("default", tok)) {
> ++          state = HOSTVALID;
> ++          retcode = NETRC_SUCCESS; /* we did find our host */
> ++          Curl_safefree(password);
> ++          if(!specific_login)
> ++            Curl_safefree(login);
> ++        }
> ++        if((found == (FOUND_PASSWORD|FOUND_LOGIN)) && our_login) {
> ++          done = TRUE;
> ++          break;
> +         }
> +         break;
> +       } /* switch (state) */
> +@@ -293,23 +308,23 @@ static int parsenetrc(struct store_netrc *store,
> +
> + out:
> +   Curl_dyn_free(&token);
> ++  if(!retcode && !password && our_login) {
> ++    /* success without a password, set a blank one */
> ++    password = strdup("");
> ++    if(!password)
> ++      retcode = 1; /* out of memory */
> ++  }
> +   if(!retcode) {
> +     /* success */
> +-    if(login_alloc) {
> +-      free(*loginp);
> ++    if(!specific_login)
> +       *loginp = login;
> +-    }
> +-    if(password_alloc) {
> +-      free(*passwordp);
> +-      *passwordp = password;
> +-    }
> ++    *passwordp = password;
> +   }
> +   else {
> +     Curl_dyn_free(filebuf);
> +-    if(login_alloc)
> ++    if(!specific_login)
> +       free(login);
> +-    if(password_alloc)
> +-      free(password);
> ++    free(password);
> +   }
> +
> +   return retcode;
> +diff --git a/lib/url.c b/lib/url.c
> +index 5cdf83c..247a8f9 100644
> +--- a/lib/url.c
> ++++ b/lib/url.c
> +@@ -2703,6 +2703,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.
> +@@ -2733,29 +2744,40 @@ static CURLcode override_login(struct Curl_easy *data,
> +     bool url_provided = FALSE;
> +
> +     if(data->state.aptr.user) {
> +-      /* there was a user name in the URL. Use the URL decoded version */
> ++      /* there was a username with a length in the URL. Use the URL decoded
> ++         version */
> +       userp = &data->state.aptr.user;
> +       url_provided = TRUE;
> +     }
> +
> +-    ret = Curl_parsenetrc(&data->state.netrc, conn->host.name,
> +-                          userp, passwdp,
> +-                          data->set.str[STRING_NETRC_FILE]);
> +-    if(ret > 0) {
> +-      infof(data, "Couldn't find host %s in the %s file; using defaults",
> +-            conn->host.name,
> +-            (data->set.str[STRING_NETRC_FILE] ?
> +-             data->set.str[STRING_NETRC_FILE] : ".netrc"));
> +-    }
> +-    else if(ret < 0) {
> +-      failf(data, ".netrc parser error");
> +-      return CURLE_READ_ERROR;
> +-    }
> +-    else {
> +-      /* set bits.netrc TRUE to remember that we got the name from a .netrc
> +-         file, so that it is safe to use even if we followed a Location: to a
> +-         different host or similar. */
> +-      conn->bits.netrc = TRUE;
> ++    if(!*passwdp) {
> ++      ret = Curl_parsenetrc(&data->state.netrc, conn->host.name,
> ++                            userp, passwdp,
> ++                            data->set.str[STRING_NETRC_FILE]);
> ++      if(ret > 0) {
> ++        infof(data, "Couldn't find host %s in the %s file; using defaults",
> ++              conn->host.name,
> ++              (data->set.str[STRING_NETRC_FILE] ?
> ++               data->set.str[STRING_NETRC_FILE] : ".netrc"));
> ++      }
> ++      else if(ret < 0) {
> ++        failf(data, ".netrc parser error");
> ++        return CURLE_READ_ERROR;
> ++      }
> ++      else {
> ++        if(!(conn->handler->flags&PROTOPT_USERPWDCTRL)) {
> ++          /* if the protocol can't handle control codes in credentials, make
> ++             sure there are none */
> ++          if(str_has_ctrl(*userp) || str_has_ctrl(*passwdp)) {
> ++            failf(data, "control code detected in .netrc credentials");
> ++            return CURLE_READ_ERROR;
> ++          }
> ++        }
> ++        /* set bits.netrc TRUE to remember that we got the name from a .netrc
> ++           file, so that it is safe to use even if we followed a Location: to a
> ++           different host or similar. */
> ++        conn->bits.netrc = TRUE;
> ++      }
> +     }
> +     if(url_provided) {
> +       Curl_safefree(conn->user);
> +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
> +index d89e565..7a6b153 100644
> +--- a/tests/data/Makefile.inc
> ++++ b/tests/data/Makefile.inc
> +@@ -73,7 +73,7 @@ test426 test427 test428 test429 test430 test431 test432 test433 test434 \
> + 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 \
> ++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 \
> +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 34cfb7a..db2a2c0 100644
> +--- a/tests/unit/unit1304.c
> ++++ b/tests/unit/unit1304.c
> +@@ -32,13 +32,8 @@ static char *password;
> +
> + static CURLcode unit_setup(void)
> + {
> +-  password = strdup("");
> +-  login = strdup("");
> +-  if(!password || !login) {
> +-    Curl_safefree(password);
> +-    Curl_safefree(login);
> +-    return CURLE_OUT_OF_MEMORY;
> +-  }
> ++  password = NULL;
> ++  login = NULL;
> +   return CURLE_OK;
> + }
> +
> +@@ -60,89 +55,61 @@ UNITTEST_START
> +   result = Curl_parsenetrc(&store,
> +                            "test.example.com", &s_login, &s_password, arg);
> +   fail_unless(result == 1, "Host not found should return 1");
> +-  abort_unless(password != NULL, "returned NULL!");
> +-  fail_unless(password[0] == 0, "password should not have been changed");
> +-  abort_unless(login != NULL, "returned NULL!");
> +-  fail_unless(login[0] == 0, "login should not have been changed");
> ++  abort_unless(password == NULL, "password did not return NULL!");
> ++  abort_unless(login == NULL, "user did not return NULL!");
> +   Curl_netrc_cleanup(&store);
> +
> +   /*
> +    * Test a non existent login in our netrc file.
> +    */
> +-  free(login);
> +-  login = strdup("me");
> +-  abort_unless(login != NULL, "returned NULL!");
> ++  login = (char *)"me";
> +   Curl_netrc_init(&store);
> +   result = Curl_parsenetrc(&store,
> +                            "example.com", &s_login, &s_password, arg);
> +   fail_unless(result == 0, "Host should have been found");
> +-  abort_unless(password != NULL, "returned NULL!");
> +-  fail_unless(password[0] == 0, "password should not have been changed");
> +-  abort_unless(login != NULL, "returned NULL!");
> +-  fail_unless(strncmp(login, "me", 2) == 0,
> +-              "login should not have been changed");
> ++  abort_unless(password == NULL, "password is not NULL!");
> +   Curl_netrc_cleanup(&store);
> +
> +   /*
> +    * Test a non existent login and host in our netrc file.
> +    */
> +-  free(login);
> +-  login = strdup("me");
> +-  abort_unless(login != NULL, "returned NULL!");
> ++  login = (char *)"me";
> +   Curl_netrc_init(&store);
> +   result = Curl_parsenetrc(&store,
> +                            "test.example.com", &s_login, &s_password, arg);
> +   fail_unless(result == 1, "Host not found should return 1");
> +-  abort_unless(password != NULL, "returned NULL!");
> +-  fail_unless(password[0] == 0, "password should not have been changed");
> +-  abort_unless(login != NULL, "returned NULL!");
> +-  fail_unless(strncmp(login, "me", 2) == 0,
> +-              "login should not have been changed");
> ++  abort_unless(password == NULL, "password is not NULL!");
> +   Curl_netrc_cleanup(&store);
> +
> +   /*
> +    * Test a non existent login (substring of an existing one) in our
> +    * netrc file.
> +    */
> +-  free(login);
> +-  login = strdup("admi");
> +-  abort_unless(login != NULL, "returned NULL!");
> ++  login = (char *)"admi";
> +   Curl_netrc_init(&store);
> +   result = Curl_parsenetrc(&store,
> +                            "example.com", &s_login, &s_password, arg);
> +   fail_unless(result == 0, "Host should have been found");
> +-  abort_unless(password != NULL, "returned NULL!");
> +-  fail_unless(password[0] == 0, "password should not have been changed");
> +-  abort_unless(login != NULL, "returned NULL!");
> +-  fail_unless(strncmp(login, "admi", 4) == 0,
> +-              "login should not have been changed");
> ++  abort_unless(password == NULL, "password is not NULL!");
> +   Curl_netrc_cleanup(&store);
> +
> +   /*
> +    * Test a non existent login (superstring of an existing one)
> +    * in our netrc file.
> +    */
> +-  free(login);
> +-  login = strdup("adminn");
> +-  abort_unless(login != NULL, "returned NULL!");
> ++  login = (char *)"adminn";
> +   Curl_netrc_init(&store);
> +   result = Curl_parsenetrc(&store,
> +                            "example.com", &s_login, &s_password, arg);
> +   fail_unless(result == 0, "Host should have been found");
> +-  abort_unless(password != NULL, "returned NULL!");
> +-  fail_unless(password[0] == 0, "password should not have been changed");
> +-  abort_unless(login != NULL, "returned NULL!");
> +-  fail_unless(strncmp(login, "adminn", 6) == 0,
> +-              "login should not have been changed");
> ++  abort_unless(password == NULL, "password is not NULL!");
> +   Curl_netrc_cleanup(&store);
> +
> +   /*
> +    * Test for the first existing host in our netrc file
> +    * with login[0] = 0.
> +    */
> +-  free(login);
> +-  login = strdup("");
> +-  abort_unless(login != NULL, "returned NULL!");
> ++  login = NULL;
> +   Curl_netrc_init(&store);
> +   result = Curl_parsenetrc(&store,
> +                            "example.com", &s_login, &s_password, arg);
> +@@ -159,8 +126,9 @@ UNITTEST_START
> +    * with login[0] != 0.
> +    */
> +   free(password);
> +-  password = strdup("");
> +-  abort_unless(password != NULL, "returned NULL!");
> ++  free(login);
> ++  password = NULL;
> ++  login = NULL;
> +   Curl_netrc_init(&store);
> +   result = Curl_parsenetrc(&store,
> +                            "example.com", &s_login, &s_password, arg);
> +@@ -177,11 +145,9 @@ UNITTEST_START
> +    * with login[0] = 0.
> +    */
> +   free(password);
> +-  password = strdup("");
> +-  abort_unless(password != NULL, "returned NULL!");
> ++  password = NULL;
> +   free(login);
> +-  login = strdup("");
> +-  abort_unless(login != NULL, "returned NULL!");
> ++  login = NULL;
> +   Curl_netrc_init(&store);
> +   result = Curl_parsenetrc(&store,
> +                            "curl.example.com", &s_login, &s_password, arg);
> +@@ -198,8 +164,9 @@ UNITTEST_START
> +    * with login[0] != 0.
> +    */
> +   free(password);
> +-  password = strdup("");
> +-  abort_unless(password != NULL, "returned NULL!");
> ++  free(login);
> ++  password = NULL;
> ++  login = NULL;
> +   Curl_netrc_init(&store);
> +   result = Curl_parsenetrc(&store,
> +                            "curl.example.com", &s_login, &s_password, arg);
> +--
> +2.40.0
> diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-0003.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-0003.patch
> new file mode 100644
> index 0000000000..ec55a68c5b
> --- /dev/null
> +++ b/meta/recipes-support/curl/curl/CVE-2024-11053-0003.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
> +
> +CVE: CVE-2024-11053
> +Upstream-Status: Backport [https://github.com/curl/curl/commit/9fce2c55d4b0273ac99]
> +
> +Signed-off-by: Yogita Urade <yogita.urade@windriver.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 8b0192a..85b72ba 100644
> +--- a/lib/netrc.c
> ++++ b/lib/netrc.c
> +@@ -264,7 +264,8 @@ static int parsenetrc(struct store_netrc *store,
> +             retcode = NETRC_FAILED; /* allocation failed */
> +             goto out;
> +           }
> +-          found |= FOUND_PASSWORD;
> ++          if(!specific_login || our_login)
> ++            found |= FOUND_PASSWORD;
> +           keyword = NONE;
> +         }
> +         else if(strcasecompare("login", tok))
> +@@ -273,6 +274,10 @@ static int parsenetrc(struct store_netrc *store,
> +           keyword = PASSWORD;
> +         else if(strcasecompare("machine", tok)) {
> +           /* a new machine here */
> ++          if(found & FOUND_PASSWORD) {
> ++            done = TRUE;
> ++            break;
> ++          }
> +           state = HOSTFOUND;
> +           keyword = NONE;
> +           found = 0;
> +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
> +index 7a6b153..32d8fee 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.40.0
> diff --git a/meta/recipes-support/curl/curl_8.7.1.bb b/meta/recipes-support/curl/curl_8.7.1.bb
> index 439fcb7881..81243d1873 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-0001.patch \
> +    file://CVE-2024-11053-0002.patch \
> +    file://CVE-2024-11053-0003.patch \
>  "
>  SRC_URI[sha256sum] = "6fea2aac6a4610fbd0400afb0bcddbe7258a64c63f1f68e5855ebc0c659710cd"
>
> --
> 2.40.0
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#211372): https://lists.openembedded.org/g/openembedded-core/message/211372
> Mute This Topic: https://lists.openembedded.org/mt/111177797/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-0001.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-0001.patch
new file mode 100644
index 0000000000..c65c3c9417
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2024-11053-0001.patch
@@ -0,0 +1,801 @@ 
+From 3b43a05e000aa8f65bda513f733a73fefe35d5ca Mon Sep 17 00:00:00 2001
+From: Daniel Stenberg <daniel@haxx.se>
+Date: Thu, 10 Oct 2024 18:08:07 +0200
+Subject: [PATCH] netrc: cache the netrc file in memory
+
+So that on redirects etc it does not reread the file but just parses it
+again.
+
+Reported-by: Pierre-Etienne Meunier
+Fixes #15248
+Closes #15259
+
+CVE: CVE-2024-11053
+Upstream-Status: Backport [https://github.com/curl/curl/commit/3b43a05e000aa8f65bda513f733a73fefe35d5ca]
+
+Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
+---
+ lib/multi.c           |   3 +
+ lib/netrc.c           | 406 ++++++++++++++++++++++++------------------
+ lib/netrc.h           |  14 +-
+ lib/url.c             |   4 +-
+ lib/urldata.h         |   5 +
+ tests/unit/unit1304.c |  48 ++++-
+ 6 files changed, 292 insertions(+), 188 deletions(-)
+
+diff --git a/lib/multi.c b/lib/multi.c
+index ed9cac7..8a05b37 100644
+--- a/lib/multi.c
++++ b/lib/multi.c
+@@ -800,6 +800,9 @@ static CURLcode multi_done(struct Curl_easy *data,
+       data->state.lastconnect_id = -1;
+   }
+
++  /* flush the netrc cache */
++  Curl_netrc_cleanup(&data->state.netrc);
++
+   return result;
+ }
+
+diff --git a/lib/netrc.c b/lib/netrc.c
+index cd2a284..d72959b 100644
+--- a/lib/netrc.c
++++ b/lib/netrc.c
+@@ -31,7 +31,6 @@
+
+ #include <curl/curl.h>
+ #include "netrc.h"
+-#include "strtok.h"
+ #include "strcase.h"
+ #include "curl_get_line.h"
+
+@@ -49,21 +48,56 @@ enum host_lookup_state {
+   MACDEF
+ };
+
++enum found_state {
++  NONE,
++  LOGIN,
++  PASSWORD
++};
++
+ #define NETRC_FILE_MISSING 1
+ #define NETRC_FAILED -1
+ #define NETRC_SUCCESS 0
+
+ #define MAX_NETRC_LINE 4096
++#define MAX_NETRC_FILE (64*1024)
++#define MAX_NETRC_TOKEN 128
++
++static CURLcode file2memory(const char *filename, struct dynbuf *filebuf)
++{
++  CURLcode result = CURLE_OK;
++  FILE *file = fopen(filename, FOPEN_READTEXT);
++  struct dynbuf linebuf;
++  Curl_dyn_init(&linebuf, MAX_NETRC_LINE);
++
++  if(file) {
++    while(Curl_get_line(&linebuf, file)) {
++      const char *line = Curl_dyn_ptr(&linebuf);
++      /* skip comments on load */
++      while(ISBLANK(*line))
++        line++;
++      if(*line == '#')
++        continue;
++      result = Curl_dyn_add(filebuf, line);
++      if(result)
++        goto done;
++    }
++  }
++done:
++  Curl_dyn_free(&linebuf);
++  if(file)
++    fclose(file);
++  return result;
++}
+
+ /*
+  * Returns zero on success.
+  */
+-static int parsenetrc(const char *host,
++static int parsenetrc(struct store_netrc *store,
++                      const char *host,
+                       char **loginp,
+                       char **passwordp,
+-                      char *netrcfile)
++                      const char *netrcfile)
+ {
+-  FILE *file;
+   int retcode = NETRC_FILE_MISSING;
+   char *login = *loginp;
+   char *password = *passwordp;
+@@ -71,204 +105,211 @@ static int parsenetrc(const char *host,
+   bool login_alloc = FALSE;
+   bool password_alloc = FALSE;
+   enum host_lookup_state state = NOTHING;
++  enum found_state found = NONE;
++  bool our_login = TRUE;  /* With specific_login, found *our* login name (or
++                             login-less line) */
++  bool done = FALSE;
++  char *netrcbuffer;
++  struct dynbuf token;
++  struct dynbuf *filebuf = &store->filebuf;
++  Curl_dyn_init(&token, MAX_NETRC_TOKEN);
+
+-  char state_login = 0;      /* Found a login keyword */
+-  char state_password = 0;   /* Found a password keyword */
+-  int state_our_login = TRUE;  /* With specific_login, found *our* login
+-                                  name (or login-less line) */
+-
+-  DEBUGASSERT(netrcfile);
++  if(!store->loaded) {
++    if(file2memory(netrcfile, filebuf))
++      return NETRC_FAILED;
++    store->loaded = TRUE;
++  }
+
+-  file = fopen(netrcfile, FOPEN_READTEXT);
+-  if(file) {
+-    bool done = FALSE;
+-    struct dynbuf buf;
+-    Curl_dyn_init(&buf, MAX_NETRC_LINE);
++  netrcbuffer = Curl_dyn_ptr(filebuf);
+
+-    while(!done && Curl_get_line(&buf, file)) {
+-      char *tok;
++  while(!done) {
++    char *tok = netrcbuffer;
++    while(tok) {
+       char *tok_end;
+       bool quoted;
+-      char *netrcbuffer = Curl_dyn_ptr(&buf);
++      Curl_dyn_reset(&token);
++      while(ISBLANK(*tok))
++        tok++;
++      /* tok is first non-space letter */
+       if(state == MACDEF) {
+-        if((netrcbuffer[0] == '\n') || (netrcbuffer[0] == '\r'))
+-          state = NOTHING;
+-        else
+-          continue;
++        if((*tok == '\n') || (*tok == '\r'))
++          state = NOTHING; /* end of macro definition */
+       }
+-      tok = netrcbuffer;
+-      while(tok) {
+-        while(ISBLANK(*tok))
+-          tok++;
+-        /* tok is first non-space letter */
+-        if(!*tok || (*tok == '#'))
+-          /* end of line or the rest is a comment */
+-          break;
++      if(!*tok || (*tok == '\n'))
++        /* end of line  */
++        break;
+
+-        /* leading double-quote means quoted string */
+-        quoted = (*tok == '\"');
++      /* leading double-quote means quoted string */
++      quoted = (*tok == '\"');
+
+-        tok_end = tok;
+-        if(!quoted) {
+-          while(!ISSPACE(*tok_end))
+-            tok_end++;
+-          *tok_end = 0;
++      tok_end = tok;
++      if(!quoted) {
++        size_t len = 0;
++        while(!ISSPACE(*tok_end)) {
++          tok_end++;
++          len++;
+         }
+-        else {
+-          bool escape = FALSE;
+-          bool endquote = FALSE;
+-          char *store = tok;
+-          tok_end++; /* pass the leading quote */
+-          while(*tok_end) {
+-            char s = *tok_end;
+-            if(escape) {
+-              escape = FALSE;
+-              switch(s) {
+-              case 'n':
+-                s = '\n';
+-                break;
+-              case 'r':
+-                s = '\r';
+-                break;
+-              case 't':
+-                s = '\t';
+-                break;
+-              }
+-            }
+-            else if(s == '\\') {
+-              escape = TRUE;
+-              tok_end++;
+-              continue;
+-            }
+-            else if(s == '\"') {
+-              tok_end++; /* pass the ending quote */
+-              endquote = TRUE;
++        if(!len || Curl_dyn_addn(&token, tok, len)) {
++          retcode = NETRC_FAILED;
++          goto out;
++        }
++      }
++      else {
++        bool escape = FALSE;
++        bool endquote = FALSE;
++        tok_end++; /* pass the leading quote */
++        while(*tok_end) {
++          char s = *tok_end;
++          if(escape) {
++            escape = FALSE;
++            switch(s) {
++            case 'n':
++              s = '\n';
++              break;
++            case 'r':
++              s = '\r';
++              break;
++            case 't':
++              s = '\t';
+               break;
+             }
+-            *store++ = s;
++          }
++          else if(s == '\\') {
++            escape = TRUE;
+             tok_end++;
++            continue;
+           }
+-          *store = 0;
+-          if(escape || !endquote) {
+-            /* bad syntax, get out */
++          else if(s == '\"') {
++            tok_end++; /* pass the ending quote */
++            endquote = TRUE;
++            break;
++          }
++          if(Curl_dyn_addn(&token, &s, 1)) {
+             retcode = NETRC_FAILED;
+             goto out;
+           }
++          tok_end++;
+         }
+-
+-        if((login && *login) && (password && *password)) {
+-          done = TRUE;
+-          break;
++        if(escape || !endquote) {
++          /* bad syntax, get out */
++          retcode = NETRC_FAILED;
++          goto out;
+         }
++      }
+
+-        switch(state) {
+-        case NOTHING:
+-          if(strcasecompare("macdef", tok)) {
+-            /* Define a macro. A macro is defined with the specified name; its
+-               contents begin with the next .netrc line and continue until a
+-               null line (consecutive new-line characters) is encountered. */
+-            state = MACDEF;
+-          }
+-          else if(strcasecompare("machine", tok)) {
+-            /* the next tok is the machine name, this is in itself the
+-               delimiter that starts the stuff entered for this machine,
+-               after this we need to search for 'login' and
+-               'password'. */
+-            state = HOSTFOUND;
+-          }
+-          else if(strcasecompare("default", tok)) {
+-            state = HOSTVALID;
+-            retcode = NETRC_SUCCESS; /* we did find our host */
+-          }
+-          break;
+-        case MACDEF:
+-          if(!strlen(tok)) {
+-            state = NOTHING;
+-          }
+-          break;
+-        case HOSTFOUND:
+-          if(strcasecompare(host, tok)) {
+-            /* and yes, this is our host! */
+-            state = HOSTVALID;
+-            retcode = NETRC_SUCCESS; /* we did find our host */
++      if((login && *login) && (password && *password)) {
++        done = TRUE;
++        break;
++      }
++
++      tok = Curl_dyn_ptr(&token);
++
++      switch(state) {
++      case NOTHING:
++        if(strcasecompare("macdef", tok))
++          /* Define a macro. A macro is defined with the specified name; its
++             contents begin with the next .netrc line and continue until a
++             null line (consecutive new-line characters) is encountered. */
++          state = MACDEF;
++        else if(strcasecompare("machine", tok))
++          /* the next tok is the machine name, this is in itself the delimiter
++             that starts the stuff entered for this machine, after this we
++             need to search for 'login' and 'password'. */
++          state = HOSTFOUND;
++        else if(strcasecompare("default", tok)) {
++          state = HOSTVALID;
++          retcode = NETRC_SUCCESS; /* we did find our host */
++        }
++        break;
++      case MACDEF:
++        if(!*tok)
++          state = NOTHING;
++        break;
++      case HOSTFOUND:
++        if(strcasecompare(host, tok)) {
++          /* and yes, this is our host! */
++          state = HOSTVALID;
++          retcode = NETRC_SUCCESS; /* we did find our host */
++        }
++        else
++          /* not our host */
++          state = NOTHING;
++        break;
++      case HOSTVALID:
++        /* we are now parsing sub-keywords concerning "our" host */
++        if(found == LOGIN) {
++          if(specific_login) {
++            our_login = !Curl_timestrcmp(login, tok);
+           }
+-          else
+-            /* not our host */
+-            state = NOTHING;
+-          break;
+-        case HOSTVALID:
+-          /* we are now parsing sub-keywords concerning "our" host */
+-          if(state_login) {
+-            if(specific_login) {
+-              state_our_login = !Curl_timestrcmp(login, tok);
+-            }
+-            else if(!login || Curl_timestrcmp(login, tok)) {
+-              if(login_alloc) {
+-                free(login);
+-                login_alloc = FALSE;
+-              }
+-              login = strdup(tok);
+-              if(!login) {
+-                retcode = NETRC_FAILED; /* allocation failed */
+-                goto out;
+-              }
+-              login_alloc = TRUE;
++          else if(!login || Curl_timestrcmp(login, tok)) {
++            if(login_alloc)
++              free(login);
++            login = strdup(tok);
++            if(!login) {
++              retcode = NETRC_FAILED; /* allocation failed */
++              goto out;
+             }
+-            state_login = 0;
++            login_alloc = TRUE;
+           }
+-          else if(state_password) {
+-            if((state_our_login || !specific_login)
+-               && (!password || Curl_timestrcmp(password, tok))) {
+-              if(password_alloc) {
+-                free(password);
+-                password_alloc = FALSE;
+-              }
+-              password = strdup(tok);
+-              if(!password) {
+-                retcode = NETRC_FAILED; /* allocation failed */
+-                goto out;
+-              }
+-              password_alloc = TRUE;
++          found = NONE;
++        }
++        else if(found == PASSWORD) {
++          if((our_login || !specific_login) &&
++             (!password || Curl_timestrcmp(password, tok))) {
++            if(password_alloc)
++              free(password);
++            password = strdup(tok);
++            if(!password) {
++              retcode = NETRC_FAILED; /* allocation failed */
++              goto out;
+             }
+-            state_password = 0;
+-          }
+-          else if(strcasecompare("login", tok))
+-            state_login = 1;
+-          else if(strcasecompare("password", tok))
+-            state_password = 1;
+-          else if(strcasecompare("machine", tok)) {
+-            /* ok, there's machine here go => */
+-            state = HOSTFOUND;
+-            state_our_login = FALSE;
++            password_alloc = TRUE;
+           }
+-          break;
+-        } /* switch (state) */
+-        tok = ++tok_end;
+-      }
+-    } /* while Curl_get_line() */
++          found = NONE;
++        }
++        else if(strcasecompare("login", tok))
++          found = LOGIN;
++        else if(strcasecompare("password", tok))
++          found = PASSWORD;
++        else if(strcasecompare("machine", tok)) {
++          /* ok, there is machine here go => */
++          state = HOSTFOUND;
++          found = NONE;
++        }
++        break;
++      } /* switch (state) */
++      tok = ++tok_end;
++    }
++    if(!done) {
++      char *nl = NULL;
++      if(tok)
++        nl = strchr(tok, '\n');
++      if(!nl)
++        break;
++      /* point to next line */
++      netrcbuffer = &nl[1];
++    }
++  } /* while !done */
+
+ out:
+-    Curl_dyn_free(&buf);
+-    if(!retcode) {
+-      /* success */
+-      if(login_alloc) {
+-        if(*loginp)
+-          free(*loginp);
+-        *loginp = login;
+-      }
+-      if(password_alloc) {
+-        if(*passwordp)
+-          free(*passwordp);
+-        *passwordp = password;
+-      }
++  Curl_dyn_free(&token);
++  if(!retcode) {
++    /* success */
++    if(login_alloc) {
++      free(*loginp);
++      *loginp = login;
+     }
+-    else {
+-      if(login_alloc)
+-        free(login);
+-      if(password_alloc)
+-        free(password);
++    if(password_alloc) {
++      free(*passwordp);
++      *passwordp = password;
+     }
+-    fclose(file);
++  }
++  else {
++    Curl_dyn_free(filebuf);
++    if(login_alloc)
++      free(login);
++    if(password_alloc)
++      free(password);
+   }
+
+   return retcode;
+@@ -280,7 +321,8 @@ out:
+  * *loginp and *passwordp MUST be allocated if they aren't NULL when passed
+  * in.
+  */
+-int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
++int Curl_parsenetrc(struct store_netrc *store, const char *host,
++                    char **loginp, char **passwordp,
+                     char *netrcfile)
+ {
+   int retcode = 1;
+@@ -329,7 +371,7 @@ int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
+       free(homea);
+       return -1;
+     }
+-    retcode = parsenetrc(host, loginp, passwordp, filealloc);
++    retcode = parsenetrc(store, host, loginp, passwordp, filealloc);
+     free(filealloc);
+ #ifdef _WIN32
+     if(retcode == NETRC_FILE_MISSING) {
+@@ -339,15 +381,25 @@ int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
+         free(homea);
+         return -1;
+       }
+-      retcode = parsenetrc(host, loginp, passwordp, filealloc);
++      retcode = parsenetrc(store, host, loginp, passwordp, filealloc);
+       free(filealloc);
+     }
+ #endif
+     free(homea);
+   }
+   else
+-    retcode = parsenetrc(host, loginp, passwordp, netrcfile);
++    retcode = parsenetrc(store, host, loginp, passwordp, netrcfile);
+   return retcode;
+ }
+
++void Curl_netrc_init(struct store_netrc *s)
++{
++  Curl_dyn_init(&s->filebuf, MAX_NETRC_FILE);
++  s->loaded = FALSE;
++}
++void Curl_netrc_cleanup(struct store_netrc *s)
++{
++  Curl_dyn_free(&s->filebuf);
++  s->loaded = FALSE;
++}
+ #endif
+diff --git a/lib/netrc.h b/lib/netrc.h
+index 9f2815f..fac223a 100644
+--- a/lib/netrc.h
++++ b/lib/netrc.h
+@@ -26,9 +26,19 @@
+
+ #include "curl_setup.h"
+ #ifndef CURL_DISABLE_NETRC
++#include "dynbuf.h"
++
++struct store_netrc {
++  struct dynbuf filebuf;
++  char *filename;
++  BIT(loaded);
++};
++
++void Curl_netrc_init(struct store_netrc *s);
++void Curl_netrc_cleanup(struct store_netrc *s);
+
+ /* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
+-int Curl_parsenetrc(const char *host, char **loginp,
++int Curl_parsenetrc(struct store_netrc *s, const char *host, char **loginp,
+                     char **passwordp, char *filename);
+   /* Assume: (*passwordp)[0]=0, host[0] != 0.
+    * If (*loginp)[0] = 0, search for login and password within a machine
+@@ -38,6 +48,8 @@ int Curl_parsenetrc(const char *host, char **loginp,
+ #else
+ /* disabled */
+ #define Curl_parsenetrc(a,b,c,d,e,f) 1
++#define Curl_netrc_init(x)
++#define Curl_netrc_cleanup(x)
+ #endif
+
+ #endif /* HEADER_CURL_NETRC_H */
+diff --git a/lib/url.c b/lib/url.c
+index 224b9f3..5cdf83c 100644
+--- a/lib/url.c
++++ b/lib/url.c
+@@ -329,6 +329,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
+   Curl_wildcard_dtor(&data->wildcard);
+   Curl_freeset(data);
+   Curl_headers_cleanup(data);
++  Curl_netrc_cleanup(&data->state.netrc);
+   free(data);
+   return CURLE_OK;
+ }
+@@ -532,6 +533,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
+
+     data->progress.flags |= PGRS_HIDE;
+     data->state.current_speed = -1; /* init to negative == impossible */
++    Curl_netrc_init(&data->state.netrc);
+   }
+
+   if(result) {
+@@ -2736,7 +2738,7 @@ static CURLcode override_login(struct Curl_easy *data,
+       url_provided = TRUE;
+     }
+
+-    ret = Curl_parsenetrc(conn->host.name,
++    ret = Curl_parsenetrc(&data->state.netrc, conn->host.name,
+                           userp, passwdp,
+                           data->set.str[STRING_NETRC_FILE]);
+     if(ret > 0) {
+diff --git a/lib/urldata.h b/lib/urldata.h
+index ce28f25..165136e 100644
+--- a/lib/urldata.h
++++ b/lib/urldata.h
+@@ -144,6 +144,7 @@ typedef unsigned int curl_prot_t;
+ #include "dynbuf.h"
+ #include "dynhds.h"
+ #include "request.h"
++#include "netrc.h"
+
+ /* return the count of bytes sent, or -1 on error */
+ typedef ssize_t (Curl_send)(struct Curl_easy *data,   /* transfer */
+@@ -1324,6 +1325,10 @@ struct UrlState {
+   struct curl_trc_feat *feat; /* opt. trace feature transfer is part of */
+ #endif
+
++#ifndef CURL_DISABLE_NETRC
++  struct store_netrc netrc;
++#endif
++
+   /* Dynamically allocated strings, MUST be freed before this struct is
+      killed. */
+   struct dynamically_allocated_data {
+diff --git a/tests/unit/unit1304.c b/tests/unit/unit1304.c
+index 0288562..34cfb7a 100644
+--- a/tests/unit/unit1304.c
++++ b/tests/unit/unit1304.c
+@@ -49,17 +49,22 @@ static void unit_stop(void)
+ }
+
+ UNITTEST_START
++{
+   int result;
++  struct store_netrc store;
+
+   /*
+    * Test a non existent host in our netrc file.
+    */
+-  result = Curl_parsenetrc("test.example.com", &login, &password, arg);
++  Curl_netrc_init(&store);
++  result = Curl_parsenetrc(&store,
++                           "test.example.com", &s_login, &s_password, arg);
+   fail_unless(result == 1, "Host not found should return 1");
+   abort_unless(password != NULL, "returned NULL!");
+   fail_unless(password[0] == 0, "password should not have been changed");
+   abort_unless(login != NULL, "returned NULL!");
+   fail_unless(login[0] == 0, "login should not have been changed");
++  Curl_netrc_cleanup(&store);
+
+   /*
+    * Test a non existent login in our netrc file.
+@@ -67,13 +72,16 @@ UNITTEST_START
+   free(login);
+   login = strdup("me");
+   abort_unless(login != NULL, "returned NULL!");
+-  result = Curl_parsenetrc("example.com", &login, &password, arg);
++  Curl_netrc_init(&store);
++  result = Curl_parsenetrc(&store,
++                           "example.com", &s_login, &s_password, arg);
+   fail_unless(result == 0, "Host should have been found");
+   abort_unless(password != NULL, "returned NULL!");
+   fail_unless(password[0] == 0, "password should not have been changed");
+   abort_unless(login != NULL, "returned NULL!");
+   fail_unless(strncmp(login, "me", 2) == 0,
+               "login should not have been changed");
++  Curl_netrc_cleanup(&store);
+
+   /*
+    * Test a non existent login and host in our netrc file.
+@@ -81,13 +89,16 @@ UNITTEST_START
+   free(login);
+   login = strdup("me");
+   abort_unless(login != NULL, "returned NULL!");
+-  result = Curl_parsenetrc("test.example.com", &login, &password, arg);
++  Curl_netrc_init(&store);
++  result = Curl_parsenetrc(&store,
++                           "test.example.com", &s_login, &s_password, arg);
+   fail_unless(result == 1, "Host not found should return 1");
+   abort_unless(password != NULL, "returned NULL!");
+   fail_unless(password[0] == 0, "password should not have been changed");
+   abort_unless(login != NULL, "returned NULL!");
+   fail_unless(strncmp(login, "me", 2) == 0,
+               "login should not have been changed");
++  Curl_netrc_cleanup(&store);
+
+   /*
+    * Test a non existent login (substring of an existing one) in our
+@@ -96,13 +107,16 @@ UNITTEST_START
+   free(login);
+   login = strdup("admi");
+   abort_unless(login != NULL, "returned NULL!");
+-  result = Curl_parsenetrc("example.com", &login, &password, arg);
++  Curl_netrc_init(&store);
++  result = Curl_parsenetrc(&store,
++                           "example.com", &s_login, &s_password, arg);
+   fail_unless(result == 0, "Host should have been found");
+   abort_unless(password != NULL, "returned NULL!");
+   fail_unless(password[0] == 0, "password should not have been changed");
+   abort_unless(login != NULL, "returned NULL!");
+   fail_unless(strncmp(login, "admi", 4) == 0,
+               "login should not have been changed");
++  Curl_netrc_cleanup(&store);
+
+   /*
+    * Test a non existent login (superstring of an existing one)
+@@ -111,13 +125,16 @@ UNITTEST_START
+   free(login);
+   login = strdup("adminn");
+   abort_unless(login != NULL, "returned NULL!");
+-  result = Curl_parsenetrc("example.com", &login, &password, arg);
++  Curl_netrc_init(&store);
++  result = Curl_parsenetrc(&store,
++                           "example.com", &s_login, &s_password, arg);
+   fail_unless(result == 0, "Host should have been found");
+   abort_unless(password != NULL, "returned NULL!");
+   fail_unless(password[0] == 0, "password should not have been changed");
+   abort_unless(login != NULL, "returned NULL!");
+   fail_unless(strncmp(login, "adminn", 6) == 0,
+               "login should not have been changed");
++  Curl_netrc_cleanup(&store);
+
+   /*
+    * Test for the first existing host in our netrc file
+@@ -126,13 +143,16 @@ UNITTEST_START
+   free(login);
+   login = strdup("");
+   abort_unless(login != NULL, "returned NULL!");
+-  result = Curl_parsenetrc("example.com", &login, &password, arg);
++  Curl_netrc_init(&store);
++  result = Curl_parsenetrc(&store,
++                           "example.com", &s_login, &s_password, arg);
+   fail_unless(result == 0, "Host should have been found");
+   abort_unless(password != NULL, "returned NULL!");
+   fail_unless(strncmp(password, "passwd", 6) == 0,
+               "password should be 'passwd'");
+   abort_unless(login != NULL, "returned NULL!");
+   fail_unless(strncmp(login, "admin", 5) == 0, "login should be 'admin'");
++  Curl_netrc_cleanup(&store);
+
+   /*
+    * Test for the first existing host in our netrc file
+@@ -141,13 +161,16 @@ UNITTEST_START
+   free(password);
+   password = strdup("");
+   abort_unless(password != NULL, "returned NULL!");
+-  result = Curl_parsenetrc("example.com", &login, &password, arg);
++  Curl_netrc_init(&store);
++  result = Curl_parsenetrc(&store,
++                           "example.com", &s_login, &s_password, arg);
+   fail_unless(result == 0, "Host should have been found");
+   abort_unless(password != NULL, "returned NULL!");
+   fail_unless(strncmp(password, "passwd", 6) == 0,
+               "password should be 'passwd'");
+   abort_unless(login != NULL, "returned NULL!");
+   fail_unless(strncmp(login, "admin", 5) == 0, "login should be 'admin'");
++  Curl_netrc_cleanup(&store);
+
+   /*
+    * Test for the second existing host in our netrc file
+@@ -159,13 +182,16 @@ UNITTEST_START
+   free(login);
+   login = strdup("");
+   abort_unless(login != NULL, "returned NULL!");
+-  result = Curl_parsenetrc("curl.example.com", &login, &password, arg);
++  Curl_netrc_init(&store);
++  result = Curl_parsenetrc(&store,
++                           "curl.example.com", &s_login, &s_password, arg);
+   fail_unless(result == 0, "Host should have been found");
+   abort_unless(password != NULL, "returned NULL!");
+   fail_unless(strncmp(password, "none", 4) == 0,
+               "password should be 'none'");
+   abort_unless(login != NULL, "returned NULL!");
+   fail_unless(strncmp(login, "none", 4) == 0, "login should be 'none'");
++  Curl_netrc_cleanup(&store);
+
+   /*
+    * Test for the second existing host in our netrc file
+@@ -174,14 +200,18 @@ UNITTEST_START
+   free(password);
+   password = strdup("");
+   abort_unless(password != NULL, "returned NULL!");
+-  result = Curl_parsenetrc("curl.example.com", &login, &password, arg);
++  Curl_netrc_init(&store);
++  result = Curl_parsenetrc(&store,
++                           "curl.example.com", &s_login, &s_password, arg);
+   fail_unless(result == 0, "Host should have been found");
+   abort_unless(password != NULL, "returned NULL!");
+   fail_unless(strncmp(password, "none", 4) == 0,
+               "password should be 'none'");
+   abort_unless(login != NULL, "returned NULL!");
+   fail_unless(strncmp(login, "none", 4) == 0, "login should be 'none'");
++  Curl_netrc_cleanup(&store);
+
++}
+ UNITTEST_STOP
+
+ #else
+--
+2.40.0
diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-0002.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-0002.patch
new file mode 100644
index 0000000000..f066b0b1d5
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2024-11053-0002.patch
@@ -0,0 +1,734 @@ 
+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
+
+Conflicts:
+- Use old variable names password and loging instead of s_password and s_login.
+- Test files are added in Makefile.inc.
+
+CVE: CVE-2024-11053
+Upstream-Status: Backport [https://github.com/curl/curl/commit/e9b9bbac22c26cf67316fa8e6c6b9e831af31949]
+
+Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
+---
+ lib/netrc.c             | 113 +++++++++++++++++++++++-----------------
+ lib/url.c               |  60 ++++++++++++++-------
+ 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, 345 insertions(+), 123 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 d72959b..8b0192a 100644
+--- a/lib/netrc.c
++++ b/lib/netrc.c
+@@ -54,6 +54,9 @@ enum found_state {
+   PASSWORD
+ };
+
++#define FOUND_LOGIN    1
++#define FOUND_PASSWORD 2
++
+ #define NETRC_FILE_MISSING 1
+ #define NETRC_FAILED -1
+ #define NETRC_SUCCESS 0
+@@ -94,24 +97,24 @@ done:
+  */
+ static int parsenetrc(struct store_netrc *store,
+                       const char *host,
+-                      char **loginp,
++                      char **loginp, /* might point to a username */
+                       char **passwordp,
+                       const char *netrcfile)
+ {
+   int retcode = NETRC_FILE_MISSING;
+   char *login = *loginp;
+-  char *password = *passwordp;
+-  bool specific_login = (login && *login != 0);
+-  bool login_alloc = FALSE;
+-  bool password_alloc = FALSE;
++  char *password = NULL;
++  bool specific_login = login; /* points to something */
+   enum host_lookup_state state = NOTHING;
+-  enum found_state found = NONE;
+-  bool our_login = TRUE;  /* With specific_login, found *our* login name (or
+-                             login-less line) */
++  enum found_state keyword = NONE;
++  unsigned char found = 0; /* login + password found bits, as they can come in
++                              any order */
++  bool our_login = FALSE;  /* found our login name */
+   bool done = FALSE;
+   char *netrcbuffer;
+   struct dynbuf token;
+   struct dynbuf *filebuf = &store->filebuf;
++  DEBUGASSERT(!*passwordp);
+   Curl_dyn_init(&token, MAX_NETRC_TOKEN);
+
+   if(!store->loaded) {
+@@ -124,7 +127,7 @@ static int parsenetrc(struct store_netrc *store,
+
+   while(!done) {
+     char *tok = netrcbuffer;
+-    while(tok) {
++    while(tok && !done) {
+       char *tok_end;
+       bool quoted;
+       Curl_dyn_reset(&token);
+@@ -197,11 +200,6 @@ static int parsenetrc(struct store_netrc *store,
+         }
+       }
+
+-      if((login && *login) && (password && *password)) {
+-        done = TRUE;
+-        break;
+-      }
+-
+       tok = Curl_dyn_ptr(&token);
+
+       switch(state) {
+@@ -211,11 +209,18 @@ static int parsenetrc(struct store_netrc *store,
+              contents begin with the next .netrc line and continue until a
+              null line (consecutive new-line characters) is encountered. */
+           state = MACDEF;
+-        else if(strcasecompare("machine", tok))
++        else if(strcasecompare("machine", tok)) {
+           /* the next tok is the machine name, this is in itself the delimiter
+              that starts the stuff entered for this machine, after this we
+              need to search for 'login' and 'password'. */
+           state = HOSTFOUND;
++          keyword = NONE;
++          found = 0;
++          our_login = FALSE;
++          Curl_safefree(password);
++          if(!specific_login)
++            Curl_safefree(login);
++        }
+         else if(strcasecompare("default", tok)) {
+           state = HOSTVALID;
+           retcode = NETRC_SUCCESS; /* we did find our host */
+@@ -237,44 +242,54 @@ static int parsenetrc(struct store_netrc *store,
+         break;
+       case HOSTVALID:
+         /* we are now parsing sub-keywords concerning "our" host */
+-        if(found == LOGIN) {
+-          if(specific_login) {
++        if(keyword == LOGIN) {
++          if(specific_login)
+             our_login = !Curl_timestrcmp(login, tok);
+-          }
+-          else if(!login || Curl_timestrcmp(login, tok)) {
+-            if(login_alloc)
+-              free(login);
++          else {
++            our_login = TRUE;
++            free(login);
+             login = strdup(tok);
+             if(!login) {
+               retcode = NETRC_FAILED; /* allocation failed */
+               goto out;
+             }
+-            login_alloc = TRUE;
+           }
+-          found = NONE;
++          found |= FOUND_LOGIN;
++          keyword = NONE;
+         }
+-        else if(found == PASSWORD) {
+-          if((our_login || !specific_login) &&
+-             (!password || Curl_timestrcmp(password, tok))) {
+-            if(password_alloc)
+-              free(password);
+-            password = strdup(tok);
+-            if(!password) {
+-              retcode = NETRC_FAILED; /* allocation failed */
+-              goto out;
+-            }
+-            password_alloc = TRUE;
++        else if(keyword == PASSWORD) {
++          free(password);
++          password = strdup(tok);
++          if(!password) {
++            retcode = NETRC_FAILED; /* allocation failed */
++            goto out;
+           }
+-          found = NONE;
++          found |= FOUND_PASSWORD;
++          keyword = NONE;
+         }
+         else if(strcasecompare("login", tok))
+-          found = LOGIN;
++          keyword = LOGIN;
+         else if(strcasecompare("password", tok))
+-          found = PASSWORD;
++          keyword = PASSWORD;
+         else if(strcasecompare("machine", tok)) {
+-          /* ok, there is machine here go => */
++          /* a new machine here */
+           state = HOSTFOUND;
+-          found = NONE;
++          keyword = NONE;
++          found = 0;
++          Curl_safefree(password);
++          if(!specific_login)
++            Curl_safefree(login);
++        }
++        else if(strcasecompare("default", tok)) {
++          state = HOSTVALID;
++          retcode = NETRC_SUCCESS; /* we did find our host */
++          Curl_safefree(password);
++          if(!specific_login)
++            Curl_safefree(login);
++        }
++        if((found == (FOUND_PASSWORD|FOUND_LOGIN)) && our_login) {
++          done = TRUE;
++          break;
+         }
+         break;
+       } /* switch (state) */
+@@ -293,23 +308,23 @@ static int parsenetrc(struct store_netrc *store,
+
+ out:
+   Curl_dyn_free(&token);
++  if(!retcode && !password && our_login) {
++    /* success without a password, set a blank one */
++    password = strdup("");
++    if(!password)
++      retcode = 1; /* out of memory */
++  }
+   if(!retcode) {
+     /* success */
+-    if(login_alloc) {
+-      free(*loginp);
++    if(!specific_login)
+       *loginp = login;
+-    }
+-    if(password_alloc) {
+-      free(*passwordp);
+-      *passwordp = password;
+-    }
++    *passwordp = password;
+   }
+   else {
+     Curl_dyn_free(filebuf);
+-    if(login_alloc)
++    if(!specific_login)
+       free(login);
+-    if(password_alloc)
+-      free(password);
++    free(password);
+   }
+
+   return retcode;
+diff --git a/lib/url.c b/lib/url.c
+index 5cdf83c..247a8f9 100644
+--- a/lib/url.c
++++ b/lib/url.c
+@@ -2703,6 +2703,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.
+@@ -2733,29 +2744,40 @@ static CURLcode override_login(struct Curl_easy *data,
+     bool url_provided = FALSE;
+
+     if(data->state.aptr.user) {
+-      /* there was a user name in the URL. Use the URL decoded version */
++      /* there was a username with a length in the URL. Use the URL decoded
++         version */
+       userp = &data->state.aptr.user;
+       url_provided = TRUE;
+     }
+
+-    ret = Curl_parsenetrc(&data->state.netrc, conn->host.name,
+-                          userp, passwdp,
+-                          data->set.str[STRING_NETRC_FILE]);
+-    if(ret > 0) {
+-      infof(data, "Couldn't find host %s in the %s file; using defaults",
+-            conn->host.name,
+-            (data->set.str[STRING_NETRC_FILE] ?
+-             data->set.str[STRING_NETRC_FILE] : ".netrc"));
+-    }
+-    else if(ret < 0) {
+-      failf(data, ".netrc parser error");
+-      return CURLE_READ_ERROR;
+-    }
+-    else {
+-      /* set bits.netrc TRUE to remember that we got the name from a .netrc
+-         file, so that it is safe to use even if we followed a Location: to a
+-         different host or similar. */
+-      conn->bits.netrc = TRUE;
++    if(!*passwdp) {
++      ret = Curl_parsenetrc(&data->state.netrc, conn->host.name,
++                            userp, passwdp,
++                            data->set.str[STRING_NETRC_FILE]);
++      if(ret > 0) {
++        infof(data, "Couldn't find host %s in the %s file; using defaults",
++              conn->host.name,
++              (data->set.str[STRING_NETRC_FILE] ?
++               data->set.str[STRING_NETRC_FILE] : ".netrc"));
++      }
++      else if(ret < 0) {
++        failf(data, ".netrc parser error");
++        return CURLE_READ_ERROR;
++      }
++      else {
++        if(!(conn->handler->flags&PROTOPT_USERPWDCTRL)) {
++          /* if the protocol can't handle control codes in credentials, make
++             sure there are none */
++          if(str_has_ctrl(*userp) || str_has_ctrl(*passwdp)) {
++            failf(data, "control code detected in .netrc credentials");
++            return CURLE_READ_ERROR;
++          }
++        }
++        /* set bits.netrc TRUE to remember that we got the name from a .netrc
++           file, so that it is safe to use even if we followed a Location: to a
++           different host or similar. */
++        conn->bits.netrc = TRUE;
++      }
+     }
+     if(url_provided) {
+       Curl_safefree(conn->user);
+diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
+index d89e565..7a6b153 100644
+--- a/tests/data/Makefile.inc
++++ b/tests/data/Makefile.inc
+@@ -73,7 +73,7 @@ test426 test427 test428 test429 test430 test431 test432 test433 test434 \
+ 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 \
++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 \
+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 34cfb7a..db2a2c0 100644
+--- a/tests/unit/unit1304.c
++++ b/tests/unit/unit1304.c
+@@ -32,13 +32,8 @@ static char *password;
+
+ static CURLcode unit_setup(void)
+ {
+-  password = strdup("");
+-  login = strdup("");
+-  if(!password || !login) {
+-    Curl_safefree(password);
+-    Curl_safefree(login);
+-    return CURLE_OUT_OF_MEMORY;
+-  }
++  password = NULL;
++  login = NULL;
+   return CURLE_OK;
+ }
+
+@@ -60,89 +55,61 @@ UNITTEST_START
+   result = Curl_parsenetrc(&store,
+                            "test.example.com", &s_login, &s_password, arg);
+   fail_unless(result == 1, "Host not found should return 1");
+-  abort_unless(password != NULL, "returned NULL!");
+-  fail_unless(password[0] == 0, "password should not have been changed");
+-  abort_unless(login != NULL, "returned NULL!");
+-  fail_unless(login[0] == 0, "login should not have been changed");
++  abort_unless(password == NULL, "password did not return NULL!");
++  abort_unless(login == NULL, "user did not return NULL!");
+   Curl_netrc_cleanup(&store);
+
+   /*
+    * Test a non existent login in our netrc file.
+    */
+-  free(login);
+-  login = strdup("me");
+-  abort_unless(login != NULL, "returned NULL!");
++  login = (char *)"me";
+   Curl_netrc_init(&store);
+   result = Curl_parsenetrc(&store,
+                            "example.com", &s_login, &s_password, arg);
+   fail_unless(result == 0, "Host should have been found");
+-  abort_unless(password != NULL, "returned NULL!");
+-  fail_unless(password[0] == 0, "password should not have been changed");
+-  abort_unless(login != NULL, "returned NULL!");
+-  fail_unless(strncmp(login, "me", 2) == 0,
+-              "login should not have been changed");
++  abort_unless(password == NULL, "password is not NULL!");
+   Curl_netrc_cleanup(&store);
+
+   /*
+    * Test a non existent login and host in our netrc file.
+    */
+-  free(login);
+-  login = strdup("me");
+-  abort_unless(login != NULL, "returned NULL!");
++  login = (char *)"me";
+   Curl_netrc_init(&store);
+   result = Curl_parsenetrc(&store,
+                            "test.example.com", &s_login, &s_password, arg);
+   fail_unless(result == 1, "Host not found should return 1");
+-  abort_unless(password != NULL, "returned NULL!");
+-  fail_unless(password[0] == 0, "password should not have been changed");
+-  abort_unless(login != NULL, "returned NULL!");
+-  fail_unless(strncmp(login, "me", 2) == 0,
+-              "login should not have been changed");
++  abort_unless(password == NULL, "password is not NULL!");
+   Curl_netrc_cleanup(&store);
+
+   /*
+    * Test a non existent login (substring of an existing one) in our
+    * netrc file.
+    */
+-  free(login);
+-  login = strdup("admi");
+-  abort_unless(login != NULL, "returned NULL!");
++  login = (char *)"admi";
+   Curl_netrc_init(&store);
+   result = Curl_parsenetrc(&store,
+                            "example.com", &s_login, &s_password, arg);
+   fail_unless(result == 0, "Host should have been found");
+-  abort_unless(password != NULL, "returned NULL!");
+-  fail_unless(password[0] == 0, "password should not have been changed");
+-  abort_unless(login != NULL, "returned NULL!");
+-  fail_unless(strncmp(login, "admi", 4) == 0,
+-              "login should not have been changed");
++  abort_unless(password == NULL, "password is not NULL!");
+   Curl_netrc_cleanup(&store);
+
+   /*
+    * Test a non existent login (superstring of an existing one)
+    * in our netrc file.
+    */
+-  free(login);
+-  login = strdup("adminn");
+-  abort_unless(login != NULL, "returned NULL!");
++  login = (char *)"adminn";
+   Curl_netrc_init(&store);
+   result = Curl_parsenetrc(&store,
+                            "example.com", &s_login, &s_password, arg);
+   fail_unless(result == 0, "Host should have been found");
+-  abort_unless(password != NULL, "returned NULL!");
+-  fail_unless(password[0] == 0, "password should not have been changed");
+-  abort_unless(login != NULL, "returned NULL!");
+-  fail_unless(strncmp(login, "adminn", 6) == 0,
+-              "login should not have been changed");
++  abort_unless(password == NULL, "password is not NULL!");
+   Curl_netrc_cleanup(&store);
+
+   /*
+    * Test for the first existing host in our netrc file
+    * with login[0] = 0.
+    */
+-  free(login);
+-  login = strdup("");
+-  abort_unless(login != NULL, "returned NULL!");
++  login = NULL;
+   Curl_netrc_init(&store);
+   result = Curl_parsenetrc(&store,
+                            "example.com", &s_login, &s_password, arg);
+@@ -159,8 +126,9 @@ UNITTEST_START
+    * with login[0] != 0.
+    */
+   free(password);
+-  password = strdup("");
+-  abort_unless(password != NULL, "returned NULL!");
++  free(login);
++  password = NULL;
++  login = NULL;
+   Curl_netrc_init(&store);
+   result = Curl_parsenetrc(&store,
+                            "example.com", &s_login, &s_password, arg);
+@@ -177,11 +145,9 @@ UNITTEST_START
+    * with login[0] = 0.
+    */
+   free(password);
+-  password = strdup("");
+-  abort_unless(password != NULL, "returned NULL!");
++  password = NULL;
+   free(login);
+-  login = strdup("");
+-  abort_unless(login != NULL, "returned NULL!");
++  login = NULL;
+   Curl_netrc_init(&store);
+   result = Curl_parsenetrc(&store,
+                            "curl.example.com", &s_login, &s_password, arg);
+@@ -198,8 +164,9 @@ UNITTEST_START
+    * with login[0] != 0.
+    */
+   free(password);
+-  password = strdup("");
+-  abort_unless(password != NULL, "returned NULL!");
++  free(login);
++  password = NULL;
++  login = NULL;
+   Curl_netrc_init(&store);
+   result = Curl_parsenetrc(&store,
+                            "curl.example.com", &s_login, &s_password, arg);
+--
+2.40.0
diff --git a/meta/recipes-support/curl/curl/CVE-2024-11053-0003.patch b/meta/recipes-support/curl/curl/CVE-2024-11053-0003.patch
new file mode 100644
index 0000000000..ec55a68c5b
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2024-11053-0003.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
+
+CVE: CVE-2024-11053
+Upstream-Status: Backport [https://github.com/curl/curl/commit/9fce2c55d4b0273ac99]
+
+Signed-off-by: Yogita Urade <yogita.urade@windriver.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 8b0192a..85b72ba 100644
+--- a/lib/netrc.c
++++ b/lib/netrc.c
+@@ -264,7 +264,8 @@ static int parsenetrc(struct store_netrc *store,
+             retcode = NETRC_FAILED; /* allocation failed */
+             goto out;
+           }
+-          found |= FOUND_PASSWORD;
++          if(!specific_login || our_login)
++            found |= FOUND_PASSWORD;
+           keyword = NONE;
+         }
+         else if(strcasecompare("login", tok))
+@@ -273,6 +274,10 @@ static int parsenetrc(struct store_netrc *store,
+           keyword = PASSWORD;
+         else if(strcasecompare("machine", tok)) {
+           /* a new machine here */
++          if(found & FOUND_PASSWORD) {
++            done = TRUE;
++            break;
++          }
+           state = HOSTFOUND;
+           keyword = NONE;
+           found = 0;
+diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
+index 7a6b153..32d8fee 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.40.0
diff --git a/meta/recipes-support/curl/curl_8.7.1.bb b/meta/recipes-support/curl/curl_8.7.1.bb
index 439fcb7881..81243d1873 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-0001.patch \
+    file://CVE-2024-11053-0002.patch \
+    file://CVE-2024-11053-0003.patch \
 "
 SRC_URI[sha256sum] = "6fea2aac6a4610fbd0400afb0bcddbe7258a64c63f1f68e5855ebc0c659710cd"