From be4f27f38b4238088cfd9cecbdae1e462ef3005a Mon Sep 17 00:00:00 2001 From: Nicolas Thill Date: Wed, 23 Nov 2011 19:41:36 +0000 Subject: [PATCH] package/busybox: wget: URL-decode user:password before base64-encoding it into auth hdr (upstream fix) SVN-Revision: 29299 --- package/busybox/Makefile | 2 +- ...004-upstream-percent_decode_in_place.patch | 237 ++++++++++++++++++ .../busybox/patches/110-wget_getopt_fix.patch | 2 +- .../busybox/patches/310-passwd_access.patch | 2 +- package/busybox/patches/350-httpd_redir.patch | 8 +- .../patches/410-httpd_cgi_headers.patch | 2 +- package/busybox/patches/440-httpd_chdir.patch | 2 +- 7 files changed, 246 insertions(+), 9 deletions(-) create mode 100644 package/busybox/patches/004-upstream-percent_decode_in_place.patch diff --git a/package/busybox/Makefile b/package/busybox/Makefile index 2a92d57315..528631a249 100644 --- a/package/busybox/Makefile +++ b/package/busybox/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=busybox PKG_VERSION:=1.19.3 -PKG_RELEASE:=8 +PKG_RELEASE:=9 PKG_FLAGS:=essential PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 diff --git a/package/busybox/patches/004-upstream-percent_decode_in_place.patch b/package/busybox/patches/004-upstream-percent_decode_in_place.patch new file mode 100644 index 0000000000..83d68f3470 --- /dev/null +++ b/package/busybox/patches/004-upstream-percent_decode_in_place.patch @@ -0,0 +1,237 @@ +http://git.busybox.net/busybox/commit/?id=dd1061b6a79b0161597799e825bfefc27993ace5 + +From dd1061b6a79b0161597799e825bfefc27993ace5 Mon Sep 17 00:00:00 2001 +From: Denys Vlasenko +Date: Sun, 11 Sep 2011 21:04:02 +0200 +Subject: [PATCH] wget: URL-decode user:password before base64-encoding it into auth hdr. Closes 3625. + +function old new delta +percent_decode_in_place - 152 +152 +parse_url 304 317 +13 +handle_incoming_and_exit 2795 2798 +3 +httpd_main 763 760 -3 +decodeString 152 - -152 +------------------------------------------------------------------------------ +(add/remove: 2/1 grow/shrink: 2/1 up/down: 168/-155) Total: 13 bytes + +Signed-off-by: Denys Vlasenko + +--- a/include/libbb.h ++++ b/include/libbb.h +@@ -1570,6 +1570,15 @@ int starts_with_cpu(const char *str) FAS + unsigned get_cpu_count(void) FAST_FUNC; + + ++/* Use strict=1 if you process input from untrusted source: ++ * it will return NULL on invalid %xx (bad hex chars) ++ * and str + 1 if decoded char is / or NUL. ++ * In non-strict mode, it always succeeds (returns str), ++ * and also it additionally decoded '+' to space. ++ */ ++char *percent_decode_in_place(char *str, int strict) FAST_FUNC; ++ ++ + extern const char bb_uuenc_tbl_base64[]; + extern const char bb_uuenc_tbl_std[]; + void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC; +--- /dev/null ++++ b/libbb/percent_decode.c +@@ -0,0 +1,69 @@ ++/* vi: set sw=4 ts=4: */ ++/* ++ * Licensed under GPLv2 or later, see file LICENSE in this source tree. ++ */ ++ ++//kbuild:lib-y += percent_decode.o ++ ++#include "libbb.h" ++ ++static unsigned hex_to_bin(unsigned char c) ++{ ++ unsigned v; ++ ++ v = c - '0'; ++ if (v <= 9) ++ return v; ++ /* c | 0x20: letters to lower case, non-letters ++ * to (potentially different) non-letters */ ++ v = (unsigned)(c | 0x20) - 'a'; ++ if (v <= 5) ++ return v + 10; ++ return ~0; ++/* For testing: ++void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); } ++int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f'); ++t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; } ++*/ ++} ++ ++char* FAST_FUNC percent_decode_in_place(char *str, int strict) ++{ ++ /* note that decoded string is always shorter than original */ ++ char *src = str; ++ char *dst = str; ++ char c; ++ ++ while ((c = *src++) != '\0') { ++ unsigned v; ++ ++ if (!strict && c == '+') { ++ *dst++ = ' '; ++ continue; ++ } ++ if (c != '%') { ++ *dst++ = c; ++ continue; ++ } ++ v = hex_to_bin(src[0]); ++ if (v > 15) { ++ bad_hex: ++ if (strict) ++ return NULL; ++ *dst++ = '%'; ++ continue; ++ } ++ v = (v * 16) | hex_to_bin(src[1]); ++ if (v > 255) ++ goto bad_hex; ++ if (strict && (v == '/' || v == '\0')) { ++ /* caller takes it as indication of invalid ++ * (dangerous wrt exploits) chars */ ++ return str + 1; ++ } ++ *dst++ = v; ++ src += 2; ++ } ++ *dst = '\0'; ++ return str; ++} +--- a/networking/httpd.c ++++ b/networking/httpd.c +@@ -820,78 +820,6 @@ static char *encodeString(const char *st + } + #endif + +-/* +- * Given a URL encoded string, convert it to plain ascii. +- * Since decoding always makes strings smaller, the decode is done in-place. +- * Thus, callers should xstrdup() the argument if they do not want the +- * argument modified. The return is the original pointer, allowing this +- * function to be easily used as arguments to other functions. +- * +- * string The first string to decode. +- * option_d 1 if called for httpd -d +- * +- * Returns a pointer to the decoded string (same as input). +- */ +-static unsigned hex_to_bin(unsigned char c) +-{ +- unsigned v; +- +- v = c - '0'; +- if (v <= 9) +- return v; +- /* c | 0x20: letters to lower case, non-letters +- * to (potentially different) non-letters */ +- v = (unsigned)(c | 0x20) - 'a'; +- if (v <= 5) +- return v + 10; +- return ~0; +-/* For testing: +-void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); } +-int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f'); +-t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; } +-*/ +-} +-static char *decodeString(char *orig, int option_d) +-{ +- /* note that decoded string is always shorter than original */ +- char *string = orig; +- char *ptr = string; +- char c; +- +- while ((c = *ptr++) != '\0') { +- unsigned v; +- +- if (option_d && c == '+') { +- *string++ = ' '; +- continue; +- } +- if (c != '%') { +- *string++ = c; +- continue; +- } +- v = hex_to_bin(ptr[0]); +- if (v > 15) { +- bad_hex: +- if (!option_d) +- return NULL; +- *string++ = '%'; +- continue; +- } +- v = (v * 16) | hex_to_bin(ptr[1]); +- if (v > 255) +- goto bad_hex; +- if (!option_d && (v == '/' || v == '\0')) { +- /* caller takes it as indication of invalid +- * (dangerous wrt exploits) chars */ +- return orig + 1; +- } +- *string++ = v; +- ptr += 2; +- } +- *string = '\0'; +- return orig; +-} +- + #if ENABLE_FEATURE_HTTPD_BASIC_AUTH + /* + * Decode a base64 data stream as per rfc1521. +@@ -1949,7 +1877,7 @@ static void handle_incoming_and_exit(con + } + + /* Decode URL escape sequences */ +- tptr = decodeString(urlcopy, 0); ++ tptr = percent_decode_in_place(urlcopy, /*strict:*/ 1); + if (tptr == NULL) + send_headers_and_exit(HTTP_BAD_REQUEST); + if (tptr == urlcopy + 1) { +@@ -2408,7 +2336,7 @@ int httpd_main(int argc UNUSED_PARAM, ch + , &verbose + ); + if (opt & OPT_DECODE_URL) { +- fputs(decodeString(url_for_decode, 1), stdout); ++ fputs(percent_decode_in_place(url_for_decode, /*strict:*/ 0), stdout); + return 0; + } + #if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR +--- a/networking/wget.c ++++ b/networking/wget.c +@@ -298,8 +298,13 @@ static void parse_url(const char *src_ur + + sp = strrchr(h->host, '@'); + if (sp != NULL) { +- h->user = h->host; ++ // URL-decode "user:password" string before base64-encoding: ++ // wget http://test:my%20pass@example.com should send ++ // Authorization: Basic dGVzdDpteSBwYXNz ++ // which decodes to "test:my pass". ++ // Standard wget and curl do this too. + *sp = '\0'; ++ h->user = percent_decode_in_place(h->host, /*strict:*/ 0); + h->host = sp + 1; + } + +@@ -660,12 +665,6 @@ static void download_one_url(const char + + #if ENABLE_FEATURE_WGET_AUTHENTICATION + if (target.user) { +-//TODO: URL-decode "user:password" string before base64-encoding: +-//wget http://test:my%20pass@example.com should send +-// Authorization: Basic dGVzdDpteSBwYXNz +-//which decodes to "test:my pass", instead of what we send now: +-// Authorization: Basic dGVzdDpteSUyMHBhc3M= +-//Can reuse decodeString() from httpd.c + fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6, + base64enc(target.user)); + } diff --git a/package/busybox/patches/110-wget_getopt_fix.patch b/package/busybox/patches/110-wget_getopt_fix.patch index e679870b92..52b9d94be0 100644 --- a/package/busybox/patches/110-wget_getopt_fix.patch +++ b/package/busybox/patches/110-wget_getopt_fix.patch @@ -1,6 +1,6 @@ --- a/networking/wget.c +++ b/networking/wget.c -@@ -872,7 +872,7 @@ int wget_main(int argc UNUSED_PARAM, cha +@@ -871,7 +871,7 @@ int wget_main(int argc UNUSED_PARAM, cha /* Ignored: */ // "tries\0" Required_argument "t" /* Ignored (we always use PASV): */ diff --git a/package/busybox/patches/310-passwd_access.patch b/package/busybox/patches/310-passwd_access.patch index 6d0affd165..b995599de7 100644 --- a/package/busybox/patches/310-passwd_access.patch +++ b/package/busybox/patches/310-passwd_access.patch @@ -3,7 +3,7 @@ --- a/networking/httpd.c +++ b/networking/httpd.c -@@ -1772,21 +1772,32 @@ static int check_user_passwd(const char +@@ -1700,21 +1700,32 @@ static int check_user_passwd(const char if (ENABLE_FEATURE_HTTPD_AUTH_MD5) { char *md5_passwd; diff --git a/package/busybox/patches/350-httpd_redir.patch b/package/busybox/patches/350-httpd_redir.patch index d5f64e332a..11125e71f1 100644 --- a/package/busybox/patches/350-httpd_redir.patch +++ b/package/busybox/patches/350-httpd_redir.patch @@ -35,7 +35,7 @@ #define last_mod (G.last_mod ) #define ip_a_d (G.ip_a_d ) #define g_realm (G.g_realm ) -@@ -1028,8 +1035,11 @@ static void send_headers(int responseNum +@@ -956,8 +963,11 @@ static void send_headers(int responseNum } #endif if (responseNum == HTTP_MOVED_TEMPORARILY) { @@ -48,7 +48,7 @@ (g_query ? "?" : ""), (g_query ? g_query : "")); } -@@ -1997,8 +2007,12 @@ static void handle_incoming_and_exit(con +@@ -1925,8 +1935,12 @@ static void handle_incoming_and_exit(con } while (*++tptr); *++urlp = '\0'; /* terminate after last character */ @@ -62,7 +62,7 @@ if (is_directory(urlcopy + 1, 1, NULL)) { found_moved_temporarily = urlcopy; } -@@ -2355,7 +2369,9 @@ static void sighup_handler(int sig UNUSE +@@ -2283,7 +2297,9 @@ static void sighup_handler(int sig UNUSE } enum { @@ -73,7 +73,7 @@ d_opt_decode_url, h_opt_home_httpd, IF_FEATURE_HTTPD_ENCODE_URL_STR(e_opt_encode_url,) -@@ -2404,12 +2420,13 @@ int httpd_main(int argc UNUSED_PARAM, ch +@@ -2332,12 +2348,13 @@ int httpd_main(int argc UNUSED_PARAM, ch /* We do not "absolutize" path given by -h (home) opt. * If user gives relative path in -h, * $SCRIPT_FILENAME will not be set. */ diff --git a/package/busybox/patches/410-httpd_cgi_headers.patch b/package/busybox/patches/410-httpd_cgi_headers.patch index 7cc4f936ad..b02a5b9d71 100644 --- a/package/busybox/patches/410-httpd_cgi_headers.patch +++ b/package/busybox/patches/410-httpd_cgi_headers.patch @@ -1,6 +1,6 @@ --- a/networking/httpd.c +++ b/networking/httpd.c -@@ -1294,10 +1294,10 @@ static NOINLINE void cgi_io_loop_and_exi +@@ -1222,10 +1222,10 @@ static NOINLINE void cgi_io_loop_and_exi if (full_write(STDOUT_FILENO, HTTP_200, sizeof(HTTP_200)-1) != sizeof(HTTP_200)-1) break; } diff --git a/package/busybox/patches/440-httpd_chdir.patch b/package/busybox/patches/440-httpd_chdir.patch index da069f6fff..401c6eb5d0 100644 --- a/package/busybox/patches/440-httpd_chdir.patch +++ b/package/busybox/patches/440-httpd_chdir.patch @@ -1,6 +1,6 @@ --- a/networking/httpd.c +++ b/networking/httpd.c -@@ -1886,6 +1886,7 @@ static void handle_incoming_and_exit(con +@@ -1814,6 +1814,7 @@ static void handle_incoming_and_exit(con char *header_ptr = header_ptr; Htaccess_Proxy *proxy_entry; #endif -- 2.25.1