3 @@ -1368,6 +1368,15 @@ pid_t *find_pid_by_name(const char* proc
4 pid_t *pidlist_reverse(pid_t *pidList) FAST_FUNC;
7 +/* Use strict=1 if you process input from untrusted source:
8 + * it will return NULL on invalid %xx (bad hex chars)
9 + * and str + 1 if decoded char is / or NUL.
10 + * In non-strict mode, it always succeeds (returns str),
11 + * and also it additionally decoded '+' to space.
13 +char *percent_decode_in_place(char *str, int strict) FAST_FUNC;
16 extern const char bb_uuenc_tbl_base64[];
17 extern const char bb_uuenc_tbl_std[];
18 void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC;
21 @@ -66,6 +66,7 @@ lib-y += mtab_file.o
24 lib-y += parse_config.o
25 +lib-y += percent_decode.o
27 lib-y += perror_msg_and_die.o
28 lib-y += perror_nomsg.o
30 +++ b/libbb/percent_decode.c
32 +/* vi: set sw=4 ts=4: */
34 + * Licensed under GPLv2 or later, see file LICENSE in this source tree.
37 +//kbuild:lib-y += percent_decode.o
41 +static unsigned hex_to_bin(unsigned char c)
48 + /* c | 0x20: letters to lower case, non-letters
49 + * to (potentially different) non-letters */
50 + v = (unsigned)(c | 0x20) - 'a';
55 +void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); }
56 +int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f');
57 +t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; }
61 +char* FAST_FUNC percent_decode_in_place(char *str, int strict)
63 + /* note that decoded string is always shorter than original */
68 + while ((c = *src++) != '\0') {
71 + if (!strict && c == '+') {
79 + v = hex_to_bin(src[0]);
87 + v = (v * 16) | hex_to_bin(src[1]);
90 + if (strict && (v == '/' || v == '\0')) {
91 + /* caller takes it as indication of invalid
92 + * (dangerous wrt exploits) chars */
101 --- a/networking/httpd.c
102 +++ b/networking/httpd.c
103 @@ -785,78 +785,6 @@ static char *encodeString(const char *st
105 #endif /* FEATURE_HTTPD_ENCODE_URL_STR */
108 - * Given a URL encoded string, convert it to plain ascii.
109 - * Since decoding always makes strings smaller, the decode is done in-place.
110 - * Thus, callers should xstrdup() the argument if they do not want the
111 - * argument modified. The return is the original pointer, allowing this
112 - * function to be easily used as arguments to other functions.
114 - * string The first string to decode.
115 - * option_d 1 if called for httpd -d
117 - * Returns a pointer to the decoded string (same as input).
119 -static unsigned hex_to_bin(unsigned char c)
126 - /* c | 0x20: letters to lower case, non-letters
127 - * to (potentially different) non-letters */
128 - v = (unsigned)(c | 0x20) - 'a';
134 -void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); }
135 -int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f');
136 -t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; }
138 -static char *decodeString(char *orig, int option_d)
140 - /* note that decoded string is always shorter than original */
141 - char *string = orig;
142 - char *ptr = string;
145 - while ((c = *ptr++) != '\0') {
148 - if (option_d && c == '+') {
156 - v = hex_to_bin(ptr[0]);
164 - v = (v * 16) | hex_to_bin(ptr[1]);
167 - if (!option_d && (v == '/' || v == '\0')) {
168 - /* caller takes it as indication of invalid
169 - * (dangerous wrt exploits) chars */
179 #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
181 * Decode a base64 data stream as per rfc1521.
182 @@ -1876,7 +1804,7 @@ static void handle_incoming_and_exit(con
185 /* Decode URL escape sequences */
186 - tptr = decodeString(urlcopy, 0);
187 + tptr = percent_decode_in_place(urlcopy, /*strict:*/ 1);
189 send_headers_and_exit(HTTP_BAD_REQUEST);
190 if (tptr == urlcopy + 1) {
191 @@ -2319,7 +2247,7 @@ int httpd_main(int argc UNUSED_PARAM, ch
194 if (opt & OPT_DECODE_URL) {
195 - fputs(decodeString(url_for_decode, 1), stdout);
196 + fputs(percent_decode_in_place(url_for_decode, /*strict:*/ 0), stdout);
199 #if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR
200 --- a/networking/wget.c
201 +++ b/networking/wget.c
202 @@ -373,8 +373,13 @@ static void parse_url(char *src_url, str
203 sp = strrchr(h->host, '@');
207 + // URL-decode "user:password" string before base64-encoding:
208 + // wget http://test:my%20pass@example.com should send
209 + // Authorization: Basic dGVzdDpteSBwYXNz
210 + // which decodes to "test:my pass".
211 + // Standard wget and curl do this too.
213 + h->user = percent_decode_in_place(h->host, /*strict:*/ 0);