Received: from mail-lf1-f48.google.com (mail-lf1-f48.google.com [209.85.167.48]) by nld3-dev1.alpinelinux.org (Postfix) with ESMTPS id E054678114B for <~alpine/apk-tools@lists.alpinelinux.org>; Tue, 14 Dec 2021 19:34:34 +0000 (UTC) Received: by mail-lf1-f48.google.com with SMTP id c32so38917815lfv.4 for <~alpine/apk-tools@lists.alpinelinux.org>; Tue, 14 Dec 2021 11:34:34 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0rq54aUSB/JH27tISlgcphPcLOdhztRWw8bfEVahaJ8=; b=lqFCRSlIyNBdsSRabW/PVHUwh7eKwu9Bk39xuHcVelBbLZz1ly82AddDcYXqioRNuQ PtBdTKlgsMMUGUW2qDh8e//8KVrBJOQgxisIfadgZY7w/CUbYeKJLL+N/djr/dHVWjQ4 Z2RcF9aquZQSLAygGL2a2g66vM/+VA8/naZIx80U8gTriyiB1Hn6zDqO5eQqESyrIg8r Sr7XeT5+Nm3YwLKFgS38EpPDT+0wK4XlkGanClR1fgvCZbX3dTtEBXWtji35fbeMZwPU 8h8+Kv2pN/qtV0NkII2/yY0JsmLxmVuAitBrj7Zs+aZebJ4gN+CEqeM9U/2JPtD0oWqR yGnA== X-Gm-Message-State: AOAM533eR86aQZVtF7Wr/AiyZYlPc0ipIv5VMJ8nkjXPr+cgErK8G41M gruv5IrUAnRN6dzCxBO39nWFV5xPw6s= X-Google-Smtp-Source: ABdhPJwMMkGJSlouxdAV9qw3ZJuNIoSbqdcO22vTVV49OPg867A3A5Bk0ECIcVZuN0UyRiL8K16eVw== X-Received: by 2002:ac2:4f8e:: with SMTP id z14mr6273353lfs.316.1639510472964; Tue, 14 Dec 2021 11:34:32 -0800 (PST) Received: from vostro (dzb11pyyk-djbcnv6-kny-3.rev.dnainternet.fi. [2001:14ba:a06b:5600:8f8:ce11:2e3a:fa16]) by smtp.gmail.com with ESMTPSA id l4sm107533lfk.5.2021.12.14.11.34.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Dec 2021 11:34:32 -0800 (PST) Date: Tue, 14 Dec 2021 21:34:30 +0200 From: Timo Teras To: Jan Hendrik Farr Cc: ~alpine/apk-tools@lists.alpinelinux.org Subject: Re: [PATCH 1/1] libfetch: Allow special characters in http basic auth Message-ID: <20211214213430.029b34c5@vostro> In-Reply-To: <20211213212929.925-1-git@jfarr.cc> References: <20211213212929.925-1-git@jfarr.cc> X-Mailer: Claws Mail 4.0.0 (GTK+ 3.24.30; x86_64-alpine-linux-musl) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Hi, On Mon, 13 Dec 2021 21:29:29 +0000 Jan Hendrik Farr wrote: > 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. Thanks! There is a related bug https://gitlab.alpinelinux.org/alpine/apk-tools/-/issues/10775 If this get's fixed, add to commit message: ref #10775 > --- > libfetch/fetch.c | 69 > +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 57 > insertions(+), 12 deletions(-) > > diff --git a/libfetch/fetch.c b/libfetch/fetch.c > index 45c92aa..ced8411 100644 > --- a/libfetch/fetch.c > +++ b/libfetch/fetch.c > @@ -353,6 +353,54 @@ fetchCopyURL(const struct url *src) > return dst; > } > > +/* > + * 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 at @ or : separators. Returns a pointer to the > unhandled > + * part of the input string (null terminator, @, or :). No > terminator is > + * written to dst (it is the caller's responsibility). > + */ > +static const char * > +fetch_pctdecode(char *dst, const char *src, size_t dlen) > +{ > + int d1, d2; > + char c; > + const char *s; > + > + for (s = src; *s != '\0' && *s != '@' && *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-- > 0) > + *dst++ = c; > + else > + return (NULL); minor readability issue; i'd prefer something like: if (!dlen) return NULL; dlen--; *dst++ = c; To make the error path and normal path more obvious. > + } > + return (s); > +} > + > /* > * Split an URL into components. URL syntax is: > * [method:/][/[user[:pwd]@]host[:port]/][document] > @@ -428,22 +476,19 @@ 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); This will terminate also with ':' in the string now. And will handle the rest of the URL incorrectly, and break password with ':'. Is the upstream file somewhere? > + if (q == NULL) { > + url_seterr(URL_BAD_AUTH); > + goto ouch; > } > } > Other than the above, it looks good. Thanks for working on this! Timo