Unverified Commit 98e66291 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

xattr: strip credentials from any URL that is stored

Both user and password are cleared uncondtitionally.

Added unit test 1621 to verify.

Fixes #3423
Closes #3433
parent afeb8d99
Loading
Loading
Loading
Loading
+55 −8
Original line number Original line Diff line number Diff line
@@ -5,7 +5,7 @@
 *                            | (__| |_| |  _ <| |___
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *                             \___|\___/|_| \_\_____|
 *
 *
 * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 *
 * This software is licensed as described in the file COPYING, which
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * you should have received as part of this distribution. The terms
@@ -49,6 +49,46 @@ static const struct xattr_mapping {
  { NULL,                  CURLINFO_NONE } /* last element, abort loop here */
  { NULL,                  CURLINFO_NONE } /* last element, abort loop here */
};
};


/* returns TRUE if a new URL is returned, that then needs to be freed */
/* @unittest: 1621 */
#ifdef UNITTESTS
bool stripcredentials(char **url);
#else
static
#endif
bool stripcredentials(char **url)
{
  CURLU *u;
  CURLUcode uc;
  char *nurl;
  u = curl_url();
  if(u) {
    uc = curl_url_set(u, CURLUPART_URL, *url, 0);
    if(uc)
      goto error;

    uc = curl_url_set(u, CURLUPART_USER, NULL, 0);
    if(uc)
      goto error;

    uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0);
    if(uc)
      goto error;

    uc = curl_url_get(u, CURLUPART_URL, &nurl, 0);
    if(uc)
      goto error;

    curl_url_cleanup(u);

    *url = nurl;
    return TRUE;
  }
  error:
  curl_url_cleanup(u);
  return FALSE;
}

/* store metadata from the curl request alongside the downloaded
/* store metadata from the curl request alongside the downloaded
 * file using extended attributes
 * file using extended attributes
 */
 */
@@ -62,17 +102,24 @@ int fwrite_xattr(CURL *curl, int fd)
    char *value = NULL;
    char *value = NULL;
    CURLcode result = curl_easy_getinfo(curl, mappings[i].info, &value);
    CURLcode result = curl_easy_getinfo(curl, mappings[i].info, &value);
    if(!result && value) {
    if(!result && value) {
      bool freeptr = FALSE;
      if(CURLINFO_EFFECTIVE_URL == mappings[i].info)
        freeptr = stripcredentials(&value);
      if(value) {
#ifdef HAVE_FSETXATTR_6
#ifdef HAVE_FSETXATTR_6
        err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0, 0);
        err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0, 0);
#elif defined(HAVE_FSETXATTR_5)
#elif defined(HAVE_FSETXATTR_5)
        err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0);
        err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0);
#elif defined(__FreeBSD_version)
#elif defined(__FreeBSD_version)
      err = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, mappings[i].attr, value,
        err = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, mappings[i].attr,
                           strlen(value));
                             value, strlen(value));
      /* FreeBSD's extattr_set_fd returns the length of the extended attribute
        /* FreeBSD's extattr_set_fd returns the length of the extended
       */
           attribute */
        err = err < 0 ? err : 0;
        err = err < 0 ? err : 0;
#endif
#endif
        if(freeptr)
          curl_free(value);
      }
    }
    }
    i++;
    i++;
  }
  }
+1 −1
Original line number Original line Diff line number Diff line
@@ -182,7 +182,7 @@ test1560 test1561 test1562 \
test1590 test1591 test1592 \
test1590 test1591 test1592 \
\
\
test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 \
test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 \
test1608 test1609 test1620 \
test1608 test1609 test1620 test1621 \
\
\
test1650 test1651 test1652 test1653 \
test1650 test1651 test1652 test1653 \
\
\

tests/data/test1621

0 → 100644
+27 −0
Original line number Original line Diff line number Diff line
<testcase>
<info>
<keywords>
unittest
stripcredentials
</keywords>
</info>

#
# Client-side
<client>
<server>
none
</server>
<features>
unittest
https
</features>
 <name>
unit tests for stripcredentials from URL
 </name>
<tool>
unit1621
</tool>
</client>

</testcase>
+5 −1
Original line number Original line Diff line number Diff line
@@ -10,7 +10,7 @@ UNITPROGS = unit1300 unit1301 unit1302 unit1303 unit1304 unit1305 unit1307 \
 unit1330 unit1394 unit1395 unit1396 unit1397 unit1398 \
 unit1330 unit1394 unit1395 unit1396 unit1397 unit1398 \
 unit1399 \
 unit1399 \
 unit1600 unit1601 unit1602 unit1603 unit1604 unit1605 unit1606 unit1607 \
 unit1600 unit1601 unit1602 unit1603 unit1604 unit1605 unit1606 unit1607 \
 unit1608 unit1609 unit1620 \
 unit1608 unit1609 unit1620 unit1621 \
 unit1650 unit1651 unit1652 unit1653
 unit1650 unit1651 unit1652 unit1653


unit1300_SOURCES = unit1300.c $(UNITFILES)
unit1300_SOURCES = unit1300.c $(UNITFILES)
@@ -100,6 +100,10 @@ unit1609_CPPFLAGS = $(AM_CPPFLAGS)
unit1620_SOURCES = unit1620.c $(UNITFILES)
unit1620_SOURCES = unit1620.c $(UNITFILES)
unit1620_CPPFLAGS = $(AM_CPPFLAGS)
unit1620_CPPFLAGS = $(AM_CPPFLAGS)


unit1621_SOURCES = unit1621.c $(UNITFILES)
unit1621_CPPFLAGS = $(AM_CPPFLAGS)
unit1621_LDADD = $(top_builddir)/src/libcurltool.la $(top_builddir)/lib/libcurl.la

unit1650_SOURCES = unit1650.c $(UNITFILES)
unit1650_SOURCES = unit1650.c $(UNITFILES)
unit1650_CPPFLAGS = $(AM_CPPFLAGS)
unit1650_CPPFLAGS = $(AM_CPPFLAGS)


tests/unit/unit1621.c

0 → 100644
+89 −0
Original line number Original line Diff line number Diff line
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * are also available at https://curl.haxx.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 * copies of the Software, and permit persons to whom the Software is
 * furnished to do so, under the terms of the COPYING file.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ***************************************************************************/
#include "curlcheck.h"

#include "urldata.h"
#include "url.h"

#include "memdebug.h" /* LAST include file */

static CURLcode unit_setup(void)
{
  return CURLE_OK;
}

static void unit_stop(void)
{
}

#ifdef __MINGW32__
UNITTEST_START
{
  return 0;
}
UNITTEST_STOP
#else

bool stripcredentials(char **url);

struct checkthis {
  const char *input;
  const char *output;
};

static struct checkthis tests[] = {
  { "ninja://foo@example.com", "ninja://foo@example.com" },
  { "https://foo@example.com", "https://example.com/" },
  { "https://localhost:45", "https://localhost:45/" },
  { "https://foo@localhost:45", "https://localhost:45/" },
  { "http://daniel:password@localhost", "http://localhost/" },
  { "http://daniel@localhost", "http://localhost/" },
  { "http://localhost/", "http://localhost/" },
  { NULL, NULL } /* end marker */
};

UNITTEST_START
{
  bool cleanup;
  char *url;
  int i;
  int rc = 0;

  for(i = 0; tests[i].input; i++) {
    url = (char *)tests[i].input;
    cleanup = stripcredentials(&url);
    printf("Test %u got input \"%s\", output: \"%s\"\n",
           i, tests[i].input, url);

    if(strcmp(tests[i].output, url)) {
      fprintf(stderr, "Test %u got input \"%s\", expected output \"%s\"\n"
              " Actual output: \"%s\"\n", i, tests[i].input, tests[i].output,
              url);
      rc++;
    }
    if(cleanup)
      curl_free(url);
  }
  return rc;
}
UNITTEST_STOP
#endif