Root/package/busybox/patches/004-upstream-percent_decode_in_place.patch

1http://git.busybox.net/busybox/commit/?id=dd1061b6a79b0161597799e825bfefc27993ace5
2
3From dd1061b6a79b0161597799e825bfefc27993ace5 Mon Sep 17 00:00:00 2001
4From: Denys Vlasenko <vda.linux@googlemail.com>
5Date: Sun, 11 Sep 2011 21:04:02 +0200
6Subject: [PATCH] wget: URL-decode user:password before base64-encoding it into auth hdr. Closes 3625.
7
8function old new delta
9percent_decode_in_place - 152 +152
10parse_url 304 317 +13
11handle_incoming_and_exit 2795 2798 +3
12httpd_main 763 760 -3
13decodeString 152 - -152
14------------------------------------------------------------------------------
15(add/remove: 2/1 grow/shrink: 2/1 up/down: 168/-155) Total: 13 bytes
16
17Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
18
19--- a/include/libbb.h
20+++ b/include/libbb.h
21@@ -1570,6 +1570,15 @@ int starts_with_cpu(const char *str) FAS
22 unsigned get_cpu_count(void) FAST_FUNC;
23 
24 
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.
30+ */
31+char *percent_decode_in_place(char *str, int strict) FAST_FUNC;
32+
33+
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;
37--- /dev/null
38+++ b/libbb/percent_decode.c
39@@ -0,0 +1,69 @@
40+/* vi: set sw=4 ts=4: */
41+/*
42+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
43+ */
44+
45+//kbuild:lib-y += percent_decode.o
46+
47+#include "libbb.h"
48+
49+static unsigned hex_to_bin(unsigned char c)
50+{
51+ unsigned v;
52+
53+ v = c - '0';
54+ if (v <= 9)
55+ return v;
56+ /* c | 0x20: letters to lower case, non-letters
57+ * to (potentially different) non-letters */
58+ v = (unsigned)(c | 0x20) - 'a';
59+ if (v <= 5)
60+ return v + 10;
61+ return ~0;
62+/* For testing:
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; }
66+*/
67+}
68+
69+char* FAST_FUNC percent_decode_in_place(char *str, int strict)
70+{
71+ /* note that decoded string is always shorter than original */
72+ char *src = str;
73+ char *dst = str;
74+ char c;
75+
76+ while ((c = *src++) != '\0') {
77+ unsigned v;
78+
79+ if (!strict && c == '+') {
80+ *dst++ = ' ';
81+ continue;
82+ }
83+ if (c != '%') {
84+ *dst++ = c;
85+ continue;
86+ }
87+ v = hex_to_bin(src[0]);
88+ if (v > 15) {
89+ bad_hex:
90+ if (strict)
91+ return NULL;
92+ *dst++ = '%';
93+ continue;
94+ }
95+ v = (v * 16) | hex_to_bin(src[1]);
96+ if (v > 255)
97+ goto bad_hex;
98+ if (strict && (v == '/' || v == '\0')) {
99+ /* caller takes it as indication of invalid
100+ * (dangerous wrt exploits) chars */
101+ return str + 1;
102+ }
103+ *dst++ = v;
104+ src += 2;
105+ }
106+ *dst = '\0';
107+ return str;
108+}
109--- a/networking/httpd.c
110+++ b/networking/httpd.c
111@@ -820,78 +820,6 @@ static char *encodeString(const char *st
112 }
113 #endif
114 
115-/*
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.
121- *
122- * string The first string to decode.
123- * option_d 1 if called for httpd -d
124- *
125- * Returns a pointer to the decoded string (same as input).
126- */
127-static unsigned hex_to_bin(unsigned char c)
128-{
129- unsigned v;
130-
131- v = c - '0';
132- if (v <= 9)
133- return v;
134- /* c | 0x20: letters to lower case, non-letters
135- * to (potentially different) non-letters */
136- v = (unsigned)(c | 0x20) - 'a';
137- if (v <= 5)
138- return v + 10;
139- return ~0;
140-/* For testing:
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; }
144-*/
145-}
146-static char *decodeString(char *orig, int option_d)
147-{
148- /* note that decoded string is always shorter than original */
149- char *string = orig;
150- char *ptr = string;
151- char c;
152-
153- while ((c = *ptr++) != '\0') {
154- unsigned v;
155-
156- if (option_d && c == '+') {
157- *string++ = ' ';
158- continue;
159- }
160- if (c != '%') {
161- *string++ = c;
162- continue;
163- }
164- v = hex_to_bin(ptr[0]);
165- if (v > 15) {
166- bad_hex:
167- if (!option_d)
168- return NULL;
169- *string++ = '%';
170- continue;
171- }
172- v = (v * 16) | hex_to_bin(ptr[1]);
173- if (v > 255)
174- goto bad_hex;
175- if (!option_d && (v == '/' || v == '\0')) {
176- /* caller takes it as indication of invalid
177- * (dangerous wrt exploits) chars */
178- return orig + 1;
179- }
180- *string++ = v;
181- ptr += 2;
182- }
183- *string = '\0';
184- return orig;
185-}
186-
187 #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
188 /*
189  * Decode a base64 data stream as per rfc1521.
190@@ -1949,7 +1877,7 @@ static void handle_incoming_and_exit(con
191     }
192 
193     /* Decode URL escape sequences */
194- tptr = decodeString(urlcopy, 0);
195+ tptr = percent_decode_in_place(urlcopy, /*strict:*/ 1);
196     if (tptr == NULL)
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
200             , &verbose
201         );
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);
205         return 0;
206     }
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
211 
212     sp = strrchr(h->host, '@');
213     if (sp != NULL) {
214- h->user = 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.
220         *sp = '\0';
221+ h->user = percent_decode_in_place(h->host, /*strict:*/ 0);
222         h->host = sp + 1;
223     }
224 
225@@ -661,12 +666,6 @@ static void download_one_url(const char
226 
227 #if ENABLE_FEATURE_WGET_AUTHENTICATION
228         if (target.user) {
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));
237         }
238

Archive Download this file



interactive