summaryrefslogtreecommitdiff
path: root/libfetch/fetch.c
diff options
context:
space:
mode:
authorJan Hendrik Farr <git@jfarr.cc>2021-12-16 23:34:38 +0100
committerTimo Teräs <timo.teras@iki.fi>2021-12-17 10:17:33 +0200
commit06fd9fe1d9899e64ee954a1b1781fb0496925b76 (patch)
treef1001099177aa0cc878a07d0a587cb2574f44d65 /libfetch/fetch.c
parent9c888aa7b9ec733d77a2214e122df9112c7e55ba (diff)
downloadapk-tools-06fd9fe1d9899e64ee954a1b1781fb0496925b76.tar.gz
apk-tools-06fd9fe1d9899e64ee954a1b1781fb0496925b76.tar.bz2
apk-tools-06fd9fe1d9899e64ee954a1b1781fb0496925b76.tar.xz
apk-tools-06fd9fe1d9899e64ee954a1b1781fb0496925b76.zip
libfetch: Allow special characters in http basic auth
Currently, special characters in the username or password are not handled correctly (when set in $http_proxy and $https_proxy). They should be percent encoded in the environment variables then decoded by libfetch and reencoded using base64. This implementation is mainly taken from the current FreeBSD source and adapted to the apk-tools version of libfetch. fixes #10775
Diffstat (limited to 'libfetch/fetch.c')
-rw-r--r--libfetch/fetch.c76
1 files changed, 62 insertions, 14 deletions
diff --git a/libfetch/fetch.c b/libfetch/fetch.c
index 45c92aa..68d920c 100644
--- a/libfetch/fetch.c
+++ b/libfetch/fetch.c
@@ -354,7 +354,55 @@ fetchCopyURL(const struct url *src)
}
/*
- * Split an URL into components. URL syntax is:
+ * Return value of the given hex digit.
+ */
+static int
+fetch_hexval(char ch)
+{
+ if (ch >= '0' && ch <= '9')
+ return (ch - '0');
+ else if (ch >= 'a' && ch <= 'f')
+ return (ch - 'a' + 10);
+ else if (ch >= 'A' && ch <= 'F')
+ return (ch - 'A' + 10);
+ return (-1);
+}
+
+/*
+ * Decode percent-encoded URL component from src into dst, stopping at end
+ * of string or one of the characters contained in brk. Returns a pointer
+ * to the unhandled part of the input string (null terminator, specified
+ * character). No terminator is written to dst (it is the caller's
+ * responsibility).
+ */
+static const char *
+fetch_pctdecode(char *dst, const char *src, const char *brk, size_t dlen)
+{
+ int d1, d2;
+ char c;
+ const char *s;
+
+ for (s = src; *s != '\0' && !strchr(brk, *s); s++) {
+ if (s[0] == '%' && (d1 = fetch_hexval(s[1])) >= 0 &&
+ (d2 = fetch_hexval(s[2])) >= 0 && (d1 > 0 || d2 > 0)) {
+ c = d1 << 4 | d2;
+ s += 2;
+ } else if (s[0] == '%') {
+ /* Invalid escape sequence. */
+ return (NULL);
+ } else {
+ c = *s;
+ }
+ if (!dlen)
+ return NULL;
+ dlen--;
+ *dst++ = c;
+ }
+ return (s);
+}
+
+/*
+ * Split a URL into components. URL syntax is:
* [method:/][/[user[:pwd]@]host[:port]/][document]
* This almost, but not quite, RFC1738 URL syntax.
*/
@@ -428,25 +476,25 @@ find_user:
p = strpbrk(URL, "/@");
if (p != NULL && *p == '@') {
/* username */
- for (q = URL, i = 0; (*q != ':') && (*q != '@'); q++) {
- if (i >= URL_USERLEN) {
- url_seterr(URL_BAD_AUTH);
- goto ouch;
- }
- u->user[i++] = *q;
+ q = URL;
+ q = fetch_pctdecode(u->user, q, ":@", URL_USERLEN);
+ if (q == NULL) {
+ url_seterr(URL_BAD_AUTH);
+ goto ouch;
}
/* password */
if (*q == ':') {
- for (q++, i = 0; (*q != '@'); q++) {
- if (i >= URL_PWDLEN) {
- url_seterr(URL_BAD_AUTH);
- goto ouch;
- }
- u->pwd[i++] = *q;
+ q = fetch_pctdecode(u->pwd, q + 1, "@", URL_PWDLEN);
+ if (q == NULL) {
+ url_seterr(URL_BAD_AUTH);
+ goto ouch;
}
}
-
+ if (*q != '@') {
+ url_seterr(URL_BAD_AUTH);
+ goto ouch;
+ }
p++;
} else {
p = URL;