1 http://git.busybox.net/busybox/commit/?id=dd1061b6a79b0161597799e825bfefc27993ace5
3 From dd1061b6a79b0161597799e825bfefc27993ace5 Mon Sep 17 00:00:00 2001
4 From: Denys Vlasenko <vda.linux@googlemail.com>
5 Date: Sun, 11 Sep 2011 21:04:02 +0200
6 Subject: [PATCH] wget: URL-decode user:password before base64-encoding it into auth hdr. Closes 3625.
9 percent_decode_in_place - 152 +152
11 handle_incoming_and_exit 2795 2798 +3
13 decodeString 152 - -152
14 ------------------------------------------------------------------------------
15 (add/remove: 2/1 grow/shrink: 2/1 up/down: 168/-155) Total: 13 bytes
17 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
21 @@ -1570,6 +1570,15 @@ int starts_with_cpu(const char *str) FAS
22 unsigned get_cpu_count(void) FAST_FUNC;
25 +/* Use strict=1 if you process input from untrusted source:
26 + * it will return NULL on invalid %xx (bad hex chars)
27 + * and str + 1 if decoded char is / or NUL.
28 + * In non-strict mode, it always succeeds (returns str),
29 + * and also it additionally decoded '+' to space.
31 +char *percent_decode_in_place(char *str, int strict) FAST_FUNC;
34 extern const char bb_uuenc_tbl_base64[];
35 extern const char bb_uuenc_tbl_std[];
36 void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC;
38 +++ b/libbb/percent_decode.c
40 +/* vi: set sw=4 ts=4: */
42 + * Licensed under GPLv2 or later, see file LICENSE in this source tree.
45 +//kbuild:lib-y += percent_decode.o
49 +static unsigned hex_to_bin(unsigned char c)
56 + /* c | 0x20: letters to lower case, non-letters
57 + * to (potentially different) non-letters */
58 + v = (unsigned)(c | 0x20) - 'a';
63 +void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); }
64 +int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f');
65 +t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; }
69 +char* FAST_FUNC percent_decode_in_place(char *str, int strict)
71 + /* note that decoded string is always shorter than original */
76 + while ((c = *src++) != '\0') {
79 + if (!strict && c == '+') {
87 + v = hex_to_bin(src[0]);
95 + v = (v * 16) | hex_to_bin(src[1]);
98 + if (strict && (v == '/' || v == '\0')) {
99 + /* caller takes it as indication of invalid
100 + * (dangerous wrt exploits) chars */
109 --- a/networking/httpd.c
110 +++ b/networking/httpd.c
111 @@ -820,78 +820,6 @@ static char *encodeString(const char *st
116 - * Given a URL encoded string, convert it to plain ascii.
117 - * Since decoding always makes strings smaller, the decode is done in-place.
118 - * Thus, callers should xstrdup() the argument if they do not want the
119 - * argument modified. The return is the original pointer, allowing this
120 - * function to be easily used as arguments to other functions.
122 - * string The first string to decode.
123 - * option_d 1 if called for httpd -d
125 - * Returns a pointer to the decoded string (same as input).
127 -static unsigned hex_to_bin(unsigned char c)
134 - /* c | 0x20: letters to lower case, non-letters
135 - * to (potentially different) non-letters */
136 - v = (unsigned)(c | 0x20) - 'a';
141 -void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); }
142 -int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f');
143 -t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; }
146 -static char *decodeString(char *orig, int option_d)
148 - /* note that decoded string is always shorter than original */
149 - char *string = orig;
150 - char *ptr = string;
153 - while ((c = *ptr++) != '\0') {
156 - if (option_d && c == '+') {
164 - v = hex_to_bin(ptr[0]);
172 - v = (v * 16) | hex_to_bin(ptr[1]);
175 - if (!option_d && (v == '/' || v == '\0')) {
176 - /* caller takes it as indication of invalid
177 - * (dangerous wrt exploits) chars */
187 #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
189 * Decode a base64 data stream as per rfc1521.
190 @@ -1949,7 +1877,7 @@ static void handle_incoming_and_exit(con
193 /* Decode URL escape sequences */
194 - tptr = decodeString(urlcopy, 0);
195 + tptr = percent_decode_in_place(urlcopy, /*strict:*/ 1);
197 send_headers_and_exit(HTTP_BAD_REQUEST);
198 if (tptr == urlcopy + 1) {
199 @@ -2408,7 +2336,7 @@ int httpd_main(int argc UNUSED_PARAM, ch
202 if (opt & OPT_DECODE_URL) {
203 - fputs(decodeString(url_for_decode, 1), stdout);
204 + fputs(percent_decode_in_place(url_for_decode, /*strict:*/ 0), stdout);
207 #if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR
208 --- a/networking/wget.c
209 +++ b/networking/wget.c
210 @@ -298,8 +298,13 @@ static void parse_url(const char *src_ur
212 sp = strrchr(h->host, '@');
215 + // URL-decode "user:password" string before base64-encoding:
216 + // wget http://test:my%20pass@example.com should send
217 + // Authorization: Basic dGVzdDpteSBwYXNz
218 + // which decodes to "test:my pass".
219 + // Standard wget and curl do this too.
221 + h->user = percent_decode_in_place(h->host, /*strict:*/ 0);
225 @@ -660,12 +665,6 @@ static void download_one_url(const char
227 #if ENABLE_FEATURE_WGET_AUTHENTICATION
229 -//TODO: URL-decode "user:password" string before base64-encoding:
230 -//wget http://test:my%20pass@example.com should send
231 -// Authorization: Basic dGVzdDpteSBwYXNz
232 -//which decodes to "test:my pass", instead of what we send now:
233 -// Authorization: Basic dGVzdDpteSUyMHBhc3M=
234 -//Can reuse decodeString() from httpd.c
235 fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6,
236 base64enc(target.user));