diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-09-11 21:04:02 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-09-11 21:04:02 +0200 |
commit | dd1061b6a79b0161597799e825bfefc27993ace5 (patch) | |
tree | f7099078291da669907c5e3f428c10af27a54417 /networking | |
parent | 5126cf9a15f9e5c3986be0fc2743b63adcc6b1fb (diff) | |
download | busybox-w32-dd1061b6a79b0161597799e825bfefc27993ace5.tar.gz busybox-w32-dd1061b6a79b0161597799e825bfefc27993ace5.tar.bz2 busybox-w32-dd1061b6a79b0161597799e825bfefc27993ace5.zip |
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 <vda.linux@googlemail.com>
Diffstat (limited to 'networking')
-rw-r--r-- | networking/httpd.c | 76 | ||||
-rw-r--r-- | networking/wget.c | 13 |
2 files changed, 8 insertions, 81 deletions
diff --git a/networking/httpd.c b/networking/httpd.c index ba5eebad5..24482fe52 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -820,78 +820,6 @@ static char *encodeString(const char *string) | |||
820 | } | 820 | } |
821 | #endif | 821 | #endif |
822 | 822 | ||
823 | /* | ||
824 | * Given a URL encoded string, convert it to plain ascii. | ||
825 | * Since decoding always makes strings smaller, the decode is done in-place. | ||
826 | * Thus, callers should xstrdup() the argument if they do not want the | ||
827 | * argument modified. The return is the original pointer, allowing this | ||
828 | * function to be easily used as arguments to other functions. | ||
829 | * | ||
830 | * string The first string to decode. | ||
831 | * option_d 1 if called for httpd -d | ||
832 | * | ||
833 | * Returns a pointer to the decoded string (same as input). | ||
834 | */ | ||
835 | static unsigned hex_to_bin(unsigned char c) | ||
836 | { | ||
837 | unsigned v; | ||
838 | |||
839 | v = c - '0'; | ||
840 | if (v <= 9) | ||
841 | return v; | ||
842 | /* c | 0x20: letters to lower case, non-letters | ||
843 | * to (potentially different) non-letters */ | ||
844 | v = (unsigned)(c | 0x20) - 'a'; | ||
845 | if (v <= 5) | ||
846 | return v + 10; | ||
847 | return ~0; | ||
848 | /* For testing: | ||
849 | void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); } | ||
850 | int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f'); | ||
851 | t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; } | ||
852 | */ | ||
853 | } | ||
854 | static char *decodeString(char *orig, int option_d) | ||
855 | { | ||
856 | /* note that decoded string is always shorter than original */ | ||
857 | char *string = orig; | ||
858 | char *ptr = string; | ||
859 | char c; | ||
860 | |||
861 | while ((c = *ptr++) != '\0') { | ||
862 | unsigned v; | ||
863 | |||
864 | if (option_d && c == '+') { | ||
865 | *string++ = ' '; | ||
866 | continue; | ||
867 | } | ||
868 | if (c != '%') { | ||
869 | *string++ = c; | ||
870 | continue; | ||
871 | } | ||
872 | v = hex_to_bin(ptr[0]); | ||
873 | if (v > 15) { | ||
874 | bad_hex: | ||
875 | if (!option_d) | ||
876 | return NULL; | ||
877 | *string++ = '%'; | ||
878 | continue; | ||
879 | } | ||
880 | v = (v * 16) | hex_to_bin(ptr[1]); | ||
881 | if (v > 255) | ||
882 | goto bad_hex; | ||
883 | if (!option_d && (v == '/' || v == '\0')) { | ||
884 | /* caller takes it as indication of invalid | ||
885 | * (dangerous wrt exploits) chars */ | ||
886 | return orig + 1; | ||
887 | } | ||
888 | *string++ = v; | ||
889 | ptr += 2; | ||
890 | } | ||
891 | *string = '\0'; | ||
892 | return orig; | ||
893 | } | ||
894 | |||
895 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 823 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
896 | /* | 824 | /* |
897 | * Decode a base64 data stream as per rfc1521. | 825 | * Decode a base64 data stream as per rfc1521. |
@@ -1949,7 +1877,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1949 | } | 1877 | } |
1950 | 1878 | ||
1951 | /* Decode URL escape sequences */ | 1879 | /* Decode URL escape sequences */ |
1952 | tptr = decodeString(urlcopy, 0); | 1880 | tptr = percent_decode_in_place(urlcopy, /*strict:*/ 1); |
1953 | if (tptr == NULL) | 1881 | if (tptr == NULL) |
1954 | send_headers_and_exit(HTTP_BAD_REQUEST); | 1882 | send_headers_and_exit(HTTP_BAD_REQUEST); |
1955 | if (tptr == urlcopy + 1) { | 1883 | if (tptr == urlcopy + 1) { |
@@ -2408,7 +2336,7 @@ int httpd_main(int argc UNUSED_PARAM, char **argv) | |||
2408 | , &verbose | 2336 | , &verbose |
2409 | ); | 2337 | ); |
2410 | if (opt & OPT_DECODE_URL) { | 2338 | if (opt & OPT_DECODE_URL) { |
2411 | fputs(decodeString(url_for_decode, 1), stdout); | 2339 | fputs(percent_decode_in_place(url_for_decode, /*strict:*/ 0), stdout); |
2412 | return 0; | 2340 | return 0; |
2413 | } | 2341 | } |
2414 | #if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR | 2342 | #if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR |
diff --git a/networking/wget.c b/networking/wget.c index 6443705fd..94a2f7c3d 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -298,8 +298,13 @@ static void parse_url(const char *src_url, struct host_info *h) | |||
298 | 298 | ||
299 | sp = strrchr(h->host, '@'); | 299 | sp = strrchr(h->host, '@'); |
300 | if (sp != NULL) { | 300 | if (sp != NULL) { |
301 | h->user = h->host; | 301 | // URL-decode "user:password" string before base64-encoding: |
302 | // wget http://test:my%20pass@example.com should send | ||
303 | // Authorization: Basic dGVzdDpteSBwYXNz | ||
304 | // which decodes to "test:my pass". | ||
305 | // Standard wget and curl do this too. | ||
302 | *sp = '\0'; | 306 | *sp = '\0'; |
307 | h->user = percent_decode_in_place(h->host, /*strict:*/ 0); | ||
303 | h->host = sp + 1; | 308 | h->host = sp + 1; |
304 | } | 309 | } |
305 | 310 | ||
@@ -660,12 +665,6 @@ static void download_one_url(const char *url) | |||
660 | 665 | ||
661 | #if ENABLE_FEATURE_WGET_AUTHENTICATION | 666 | #if ENABLE_FEATURE_WGET_AUTHENTICATION |
662 | if (target.user) { | 667 | if (target.user) { |
663 | //TODO: URL-decode "user:password" string before base64-encoding: | ||
664 | //wget http://test:my%20pass@example.com should send | ||
665 | // Authorization: Basic dGVzdDpteSBwYXNz | ||
666 | //which decodes to "test:my pass", instead of what we send now: | ||
667 | // Authorization: Basic dGVzdDpteSUyMHBhc3M= | ||
668 | //Can reuse decodeString() from httpd.c | ||
669 | fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6, | 668 | fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6, |
670 | base64enc(target.user)); | 669 | base64enc(target.user)); |
671 | } | 670 | } |