diff options
author | Ron Yorston <rmy@pobox.com> | 2018-02-13 09:44:44 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-02-13 09:44:44 +0000 |
commit | dc19a361bd6c6df30338371532691bbc7f7126bb (patch) | |
tree | 1fb2cd646d54b5f8e425c4f11f3e09fc21d1966b /networking/wget.c | |
parent | 096aee2bb468d1ab044de36e176ed1f6c7e3674d (diff) | |
parent | 3459024bf404af814cacfe90a0deb719e282ae62 (diff) | |
download | busybox-w32-dc19a361bd6c6df30338371532691bbc7f7126bb.tar.gz busybox-w32-dc19a361bd6c6df30338371532691bbc7f7126bb.tar.bz2 busybox-w32-dc19a361bd6c6df30338371532691bbc7f7126bb.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'networking/wget.c')
-rw-r--r-- | networking/wget.c | 278 |
1 files changed, 162 insertions, 116 deletions
diff --git a/networking/wget.c b/networking/wget.c index 1f5ab8bc2..b9225fac0 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -48,6 +48,7 @@ | |||
48 | //config: | 48 | //config: |
49 | //config:config FEATURE_WGET_HTTPS | 49 | //config:config FEATURE_WGET_HTTPS |
50 | //config: bool "Support HTTPS using internal TLS code" | 50 | //config: bool "Support HTTPS using internal TLS code" |
51 | //it also enables FTPS support, but it's not well tested yet | ||
51 | //config: default y | 52 | //config: default y |
52 | //config: depends on WGET | 53 | //config: depends on WGET |
53 | //config: select TLS | 54 | //config: select TLS |
@@ -176,6 +177,9 @@ struct host_info { | |||
176 | static const char P_FTP[] ALIGN1 = "ftp"; | 177 | static const char P_FTP[] ALIGN1 = "ftp"; |
177 | static const char P_HTTP[] ALIGN1 = "http"; | 178 | static const char P_HTTP[] ALIGN1 = "http"; |
178 | #if SSL_SUPPORTED | 179 | #if SSL_SUPPORTED |
180 | # if ENABLE_FEATURE_WGET_HTTPS | ||
181 | static const char P_FTPS[] ALIGN1 = "ftps"; | ||
182 | # endif | ||
179 | static const char P_HTTPS[] ALIGN1 = "https"; | 183 | static const char P_HTTPS[] ALIGN1 = "https"; |
180 | #endif | 184 | #endif |
181 | 185 | ||
@@ -348,15 +352,6 @@ static char *base64enc(const char *str) | |||
348 | } | 352 | } |
349 | #endif | 353 | #endif |
350 | 354 | ||
351 | static char* sanitize_string(char *s) | ||
352 | { | ||
353 | unsigned char *p = (void *) s; | ||
354 | while (*p >= ' ') | ||
355 | p++; | ||
356 | *p = '\0'; | ||
357 | return s; | ||
358 | } | ||
359 | |||
360 | #if ENABLE_FEATURE_WGET_TIMEOUT | 355 | #if ENABLE_FEATURE_WGET_TIMEOUT |
361 | static void alarm_handler(int sig UNUSED_PARAM) | 356 | static void alarm_handler(int sig UNUSED_PARAM) |
362 | { | 357 | { |
@@ -419,22 +414,49 @@ static FILE *open_socket(len_and_sockaddr *lsa) | |||
419 | return fp; | 414 | return fp; |
420 | } | 415 | } |
421 | 416 | ||
417 | /* We balk at any control chars in other side's messages. | ||
418 | * This prevents nasty surprises (e.g. ESC sequences) in "Location:" URLs | ||
419 | * and error messages. | ||
420 | * | ||
421 | * The only exception is tabs, which are converted to (one) space: | ||
422 | * HTTP's "headers: <whitespace> values" may have those. | ||
423 | */ | ||
424 | static char* sanitize_string(char *s) | ||
425 | { | ||
426 | unsigned char *p = (void *) s; | ||
427 | while (*p) { | ||
428 | if (*p < ' ') { | ||
429 | if (*p != '\t') | ||
430 | break; | ||
431 | *p = ' '; | ||
432 | } | ||
433 | p++; | ||
434 | } | ||
435 | *p = '\0'; | ||
436 | return s; | ||
437 | } | ||
438 | |||
422 | /* Returns '\n' if it was seen, else '\0'. Trims at first '\r' or '\n' */ | 439 | /* Returns '\n' if it was seen, else '\0'. Trims at first '\r' or '\n' */ |
423 | static char fgets_and_trim(FILE *fp, const char *fmt) | 440 | static char fgets_trim_sanitize(FILE *fp, const char *fmt) |
424 | { | 441 | { |
425 | char c; | 442 | char c; |
426 | char *buf_ptr; | 443 | char *buf_ptr; |
427 | 444 | ||
428 | set_alarm(); | 445 | set_alarm(); |
429 | if (fgets(G.wget_buf, sizeof(G.wget_buf) - 1, fp) == NULL) | 446 | if (fgets(G.wget_buf, sizeof(G.wget_buf), fp) == NULL) |
430 | bb_perror_msg_and_die("error getting response"); | 447 | bb_perror_msg_and_die("error getting response"); |
431 | clear_alarm(); | 448 | clear_alarm(); |
432 | 449 | ||
433 | buf_ptr = strchrnul(G.wget_buf, '\n'); | 450 | buf_ptr = strchrnul(G.wget_buf, '\n'); |
434 | c = *buf_ptr; | 451 | c = *buf_ptr; |
452 | #if 1 | ||
453 | /* Disallow any control chars: trim at first char < 0x20 */ | ||
454 | sanitize_string(G.wget_buf); | ||
455 | #else | ||
435 | *buf_ptr = '\0'; | 456 | *buf_ptr = '\0'; |
436 | buf_ptr = strchrnul(G.wget_buf, '\r'); | 457 | buf_ptr = strchrnul(G.wget_buf, '\r'); |
437 | *buf_ptr = '\0'; | 458 | *buf_ptr = '\0'; |
459 | #endif | ||
438 | 460 | ||
439 | log_io("< %s", G.wget_buf); | 461 | log_io("< %s", G.wget_buf); |
440 | 462 | ||
@@ -461,8 +483,10 @@ static int ftpcmd(const char *s1, const char *s2, FILE *fp) | |||
461 | #endif | 483 | #endif |
462 | } | 484 | } |
463 | 485 | ||
486 | /* Read until "Nxx something" is received */ | ||
487 | G.wget_buf[3] = 0; | ||
464 | do { | 488 | do { |
465 | fgets_and_trim(fp, "%s\n"); | 489 | fgets_trim_sanitize(fp, "%s\n"); |
466 | } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' '); | 490 | } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' '); |
467 | #if ENABLE_PLATFORM_MINGW32 | 491 | #if ENABLE_PLATFORM_MINGW32 |
468 | fseek(fp, 0L, SEEK_CUR); | 492 | fseek(fp, 0L, SEEK_CUR); |
@@ -490,6 +514,12 @@ static void parse_url(const char *src_url, struct host_info *h) | |||
490 | h->port = bb_lookup_port(P_FTP, "tcp", 21); | 514 | h->port = bb_lookup_port(P_FTP, "tcp", 21); |
491 | } else | 515 | } else |
492 | #if SSL_SUPPORTED | 516 | #if SSL_SUPPORTED |
517 | # if ENABLE_FEATURE_WGET_HTTPS | ||
518 | if (strcmp(url, P_FTPS) == 0) { | ||
519 | h->port = bb_lookup_port(P_FTPS, "tcp", 990); | ||
520 | h->protocol = P_FTPS; | ||
521 | } else | ||
522 | # endif | ||
493 | if (strcmp(url, P_HTTPS) == 0) { | 523 | if (strcmp(url, P_HTTPS) == 0) { |
494 | h->port = bb_lookup_port(P_HTTPS, "tcp", 443); | 524 | h->port = bb_lookup_port(P_HTTPS, "tcp", 443); |
495 | h->protocol = P_HTTPS; | 525 | h->protocol = P_HTTPS; |
@@ -501,7 +531,7 @@ static void parse_url(const char *src_url, struct host_info *h) | |||
501 | h->protocol = P_HTTP; | 531 | h->protocol = P_HTTP; |
502 | } else { | 532 | } else { |
503 | *p = ':'; | 533 | *p = ':'; |
504 | bb_error_msg_and_die("not an http or ftp url: %s", sanitize_string(url)); | 534 | bb_error_msg_and_die("not an http or ftp url: %s", url); |
505 | } | 535 | } |
506 | } else { | 536 | } else { |
507 | // GNU wget is user-friendly and falls back to http:// | 537 | // GNU wget is user-friendly and falls back to http:// |
@@ -556,13 +586,13 @@ static void parse_url(const char *src_url, struct host_info *h) | |||
556 | */ | 586 | */ |
557 | } | 587 | } |
558 | 588 | ||
559 | static char *gethdr(FILE *fp) | 589 | static char *get_sanitized_hdr(FILE *fp) |
560 | { | 590 | { |
561 | char *s, *hdrval; | 591 | char *s, *hdrval; |
562 | int c; | 592 | int c; |
563 | 593 | ||
564 | /* retrieve header line */ | 594 | /* retrieve header line */ |
565 | c = fgets_and_trim(fp, " %s\n"); | 595 | c = fgets_trim_sanitize(fp, " %s\n"); |
566 | 596 | ||
567 | /* end of the headers? */ | 597 | /* end of the headers? */ |
568 | if (G.wget_buf[0] == '\0') | 598 | if (G.wget_buf[0] == '\0') |
@@ -584,7 +614,7 @@ static char *gethdr(FILE *fp) | |||
584 | 614 | ||
585 | /* verify we are at the end of the header name */ | 615 | /* verify we are at the end of the header name */ |
586 | if (*s != ':') | 616 | if (*s != ':') |
587 | bb_error_msg_and_die("bad header line: %s", sanitize_string(G.wget_buf)); | 617 | bb_error_msg_and_die("bad header line: %s", G.wget_buf); |
588 | 618 | ||
589 | /* locate the start of the header value */ | 619 | /* locate the start of the header value */ |
590 | *s++ = '\0'; | 620 | *s++ = '\0'; |
@@ -608,87 +638,6 @@ static void reset_beg_range_to_zero(void) | |||
608 | /* ftruncate(G.output_fd, 0); */ | 638 | /* ftruncate(G.output_fd, 0); */ |
609 | } | 639 | } |
610 | 640 | ||
611 | static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_sockaddr *lsa) | ||
612 | { | ||
613 | FILE *sfp; | ||
614 | char *str; | ||
615 | int port; | ||
616 | |||
617 | if (!target->user) | ||
618 | target->user = xstrdup("anonymous:busybox@"); | ||
619 | |||
620 | sfp = open_socket(lsa); | ||
621 | if (ftpcmd(NULL, NULL, sfp) != 220) | ||
622 | bb_error_msg_and_die("%s", sanitize_string(G.wget_buf + 4)); | ||
623 | |||
624 | /* | ||
625 | * Splitting username:password pair, | ||
626 | * trying to log in | ||
627 | */ | ||
628 | str = strchr(target->user, ':'); | ||
629 | if (str) | ||
630 | *str++ = '\0'; | ||
631 | switch (ftpcmd("USER ", target->user, sfp)) { | ||
632 | case 230: | ||
633 | break; | ||
634 | case 331: | ||
635 | if (ftpcmd("PASS ", str, sfp) == 230) | ||
636 | break; | ||
637 | /* fall through (failed login) */ | ||
638 | default: | ||
639 | bb_error_msg_and_die("ftp login: %s", sanitize_string(G.wget_buf + 4)); | ||
640 | } | ||
641 | |||
642 | ftpcmd("TYPE I", NULL, sfp); | ||
643 | |||
644 | /* | ||
645 | * Querying file size | ||
646 | */ | ||
647 | if (ftpcmd("SIZE ", target->path, sfp) == 213) { | ||
648 | G.content_len = BB_STRTOOFF(G.wget_buf + 4, NULL, 10); | ||
649 | if (G.content_len < 0 || errno) { | ||
650 | bb_error_msg_and_die("SIZE value is garbage"); | ||
651 | } | ||
652 | G.got_clen = 1; | ||
653 | } | ||
654 | |||
655 | /* | ||
656 | * Entering passive mode | ||
657 | */ | ||
658 | if (ftpcmd("PASV", NULL, sfp) != 227) { | ||
659 | pasv_error: | ||
660 | bb_error_msg_and_die("bad response to %s: %s", "PASV", sanitize_string(G.wget_buf)); | ||
661 | } | ||
662 | // Response is "227 garbageN1,N2,N3,N4,P1,P2[)garbage] | ||
663 | // Server's IP is N1.N2.N3.N4 (we ignore it) | ||
664 | // Server's port for data connection is P1*256+P2 | ||
665 | str = strrchr(G.wget_buf, ')'); | ||
666 | if (str) str[0] = '\0'; | ||
667 | str = strrchr(G.wget_buf, ','); | ||
668 | if (!str) goto pasv_error; | ||
669 | port = xatou_range(str+1, 0, 255); | ||
670 | *str = '\0'; | ||
671 | str = strrchr(G.wget_buf, ','); | ||
672 | if (!str) goto pasv_error; | ||
673 | port += xatou_range(str+1, 0, 255) * 256; | ||
674 | set_nport(&lsa->u.sa, htons(port)); | ||
675 | |||
676 | *dfpp = open_socket(lsa); | ||
677 | |||
678 | if (G.beg_range != 0) { | ||
679 | sprintf(G.wget_buf, "REST %"OFF_FMT"u", G.beg_range); | ||
680 | if (ftpcmd(G.wget_buf, NULL, sfp) == 350) | ||
681 | G.content_len -= G.beg_range; | ||
682 | else | ||
683 | reset_beg_range_to_zero(); | ||
684 | } | ||
685 | |||
686 | if (ftpcmd("RETR ", target->path, sfp) > 150) | ||
687 | bb_error_msg_and_die("bad response to %s: %s", "RETR", sanitize_string(G.wget_buf)); | ||
688 | |||
689 | return sfp; | ||
690 | } | ||
691 | |||
692 | #if ENABLE_FEATURE_WGET_OPENSSL | 641 | #if ENABLE_FEATURE_WGET_OPENSSL |
693 | static int spawn_https_helper_openssl(const char *host, unsigned port) | 642 | static int spawn_https_helper_openssl(const char *host, unsigned port) |
694 | { | 643 | { |
@@ -765,7 +714,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) | |||
765 | #endif | 714 | #endif |
766 | 715 | ||
767 | #if ENABLE_FEATURE_WGET_HTTPS | 716 | #if ENABLE_FEATURE_WGET_HTTPS |
768 | static void spawn_ssl_client(const char *host, int network_fd) | 717 | static void spawn_ssl_client(const char *host, int network_fd, int flags) |
769 | { | 718 | { |
770 | int sp[2]; | 719 | int sp[2]; |
771 | int pid; | 720 | int pid; |
@@ -790,17 +739,19 @@ static void spawn_ssl_client(const char *host, int network_fd) | |||
790 | tls_state_t *tls = new_tls_state(); | 739 | tls_state_t *tls = new_tls_state(); |
791 | tls->ifd = tls->ofd = network_fd; | 740 | tls->ifd = tls->ofd = network_fd; |
792 | tls_handshake(tls, servername); | 741 | tls_handshake(tls, servername); |
793 | tls_run_copy_loop(tls); | 742 | tls_run_copy_loop(tls, flags); |
794 | exit(0); | 743 | exit(0); |
795 | } else { | 744 | } else { |
796 | char *argv[5]; | 745 | char *argv[6]; |
746 | |||
797 | xmove_fd(network_fd, 3); | 747 | xmove_fd(network_fd, 3); |
798 | argv[0] = (char*)"ssl_client"; | 748 | argv[0] = (char*)"ssl_client"; |
799 | argv[1] = (char*)"-s3"; | 749 | argv[1] = (char*)"-s3"; |
800 | //TODO: if (!is_ip_address(servername))... | 750 | //TODO: if (!is_ip_address(servername))... |
801 | argv[2] = (char*)"-n"; | 751 | argv[2] = (char*)"-n"; |
802 | argv[3] = servername; | 752 | argv[3] = servername; |
803 | argv[4] = NULL; | 753 | argv[4] = (flags & TLSLOOP_EXIT_ON_LOCAL_EOF ? (char*)"-e" : NULL); |
754 | argv[5] = NULL; | ||
804 | BB_EXECVP(argv[0], argv); | 755 | BB_EXECVP(argv[0], argv); |
805 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); | 756 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); |
806 | } | 757 | } |
@@ -814,6 +765,101 @@ static void spawn_ssl_client(const char *host, int network_fd) | |||
814 | } | 765 | } |
815 | #endif | 766 | #endif |
816 | 767 | ||
768 | static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_sockaddr *lsa) | ||
769 | { | ||
770 | FILE *sfp; | ||
771 | char *str; | ||
772 | int port; | ||
773 | |||
774 | if (!target->user) | ||
775 | target->user = xstrdup("anonymous:busybox@"); | ||
776 | |||
777 | sfp = open_socket(lsa); | ||
778 | #if ENABLE_FEATURE_WGET_HTTPS | ||
779 | if (target->protocol == P_FTPS) | ||
780 | spawn_ssl_client(target->host, fileno(sfp), TLSLOOP_EXIT_ON_LOCAL_EOF); | ||
781 | #endif | ||
782 | |||
783 | if (ftpcmd(NULL, NULL, sfp) != 220) | ||
784 | bb_error_msg_and_die("%s", G.wget_buf); | ||
785 | /* note: ftpcmd() sanitizes G.wget_buf, ok to print */ | ||
786 | |||
787 | /* | ||
788 | * Splitting username:password pair, | ||
789 | * trying to log in | ||
790 | */ | ||
791 | str = strchr(target->user, ':'); | ||
792 | if (str) | ||
793 | *str++ = '\0'; | ||
794 | switch (ftpcmd("USER ", target->user, sfp)) { | ||
795 | case 230: | ||
796 | break; | ||
797 | case 331: | ||
798 | if (ftpcmd("PASS ", str, sfp) == 230) | ||
799 | break; | ||
800 | /* fall through (failed login) */ | ||
801 | default: | ||
802 | bb_error_msg_and_die("ftp login: %s", G.wget_buf); | ||
803 | } | ||
804 | |||
805 | ftpcmd("TYPE I", NULL, sfp); | ||
806 | |||
807 | /* | ||
808 | * Querying file size | ||
809 | */ | ||
810 | if (ftpcmd("SIZE ", target->path, sfp) == 213) { | ||
811 | G.content_len = BB_STRTOOFF(G.wget_buf + 4, NULL, 10); | ||
812 | if (G.content_len < 0 || errno) { | ||
813 | bb_error_msg_and_die("SIZE value is garbage"); | ||
814 | } | ||
815 | G.got_clen = 1; | ||
816 | } | ||
817 | |||
818 | /* | ||
819 | * Entering passive mode | ||
820 | */ | ||
821 | if (ENABLE_FEATURE_IPV6 && ftpcmd("EPSV", NULL, sfp) == 229) { | ||
822 | /* good */ | ||
823 | } else | ||
824 | if (ftpcmd("PASV", NULL, sfp) != 227) { | ||
825 | pasv_error: | ||
826 | bb_error_msg_and_die("bad response to %s: %s", "PASV", G.wget_buf); | ||
827 | } | ||
828 | port = parse_pasv_epsv(G.wget_buf); | ||
829 | if (port < 0) | ||
830 | goto pasv_error; | ||
831 | |||
832 | set_nport(&lsa->u.sa, htons(port)); | ||
833 | |||
834 | *dfpp = open_socket(lsa); | ||
835 | |||
836 | #if ENABLE_FEATURE_WGET_HTTPS | ||
837 | if (target->protocol == P_FTPS) { | ||
838 | /* "PROT P" enables encryption of data stream. | ||
839 | * Without it (or with "PROT C"), data is sent unencrypted. | ||
840 | */ | ||
841 | if (ftpcmd("PROT P", NULL, sfp) == 200) | ||
842 | spawn_ssl_client(target->host, fileno(*dfpp), /*flags*/ 0); | ||
843 | } | ||
844 | #endif | ||
845 | |||
846 | if (G.beg_range != 0) { | ||
847 | sprintf(G.wget_buf, "REST %"OFF_FMT"u", G.beg_range); | ||
848 | if (ftpcmd(G.wget_buf, NULL, sfp) == 350) | ||
849 | G.content_len -= G.beg_range; | ||
850 | else | ||
851 | reset_beg_range_to_zero(); | ||
852 | } | ||
853 | |||
854 | //TODO: needs ftp-escaping 0xff and '\n' bytes here. | ||
855 | //Or disallow '\n' altogether via sanitize_string() in parse_url(). | ||
856 | //But 0xff's are possible in valid utf8 filenames. | ||
857 | if (ftpcmd("RETR ", target->path, sfp) > 150) | ||
858 | bb_error_msg_and_die("bad response to %s: %s", "RETR", G.wget_buf); | ||
859 | |||
860 | return sfp; | ||
861 | } | ||
862 | |||
817 | static void NOINLINE retrieve_file_data(FILE *dfp) | 863 | static void NOINLINE retrieve_file_data(FILE *dfp) |
818 | { | 864 | { |
819 | #if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT | 865 | #if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT |
@@ -930,9 +976,9 @@ static void NOINLINE retrieve_file_data(FILE *dfp) | |||
930 | if (!G.chunked) | 976 | if (!G.chunked) |
931 | break; | 977 | break; |
932 | 978 | ||
933 | fgets_and_trim(dfp, NULL); /* Eat empty line */ | 979 | fgets_trim_sanitize(dfp, NULL); /* Eat empty line */ |
934 | get_clen: | 980 | get_clen: |
935 | fgets_and_trim(dfp, NULL); | 981 | fgets_trim_sanitize(dfp, NULL); |
936 | G.content_len = STRTOOFF(G.wget_buf, NULL, 16); | 982 | G.content_len = STRTOOFF(G.wget_buf, NULL, 16); |
937 | /* FIXME: error check? */ | 983 | /* FIXME: error check? */ |
938 | if (G.content_len == 0) | 984 | if (G.content_len == 0) |
@@ -987,7 +1033,7 @@ static void download_one_url(const char *url) | |||
987 | /* Use the proxy if necessary */ | 1033 | /* Use the proxy if necessary */ |
988 | use_proxy = (strcmp(G.proxy_flag, "off") != 0); | 1034 | use_proxy = (strcmp(G.proxy_flag, "off") != 0); |
989 | if (use_proxy) { | 1035 | if (use_proxy) { |
990 | proxy = getenv(target.protocol == P_FTP ? "ftp_proxy" : "http_proxy"); | 1036 | proxy = getenv(target.protocol[0] == 'f' ? "ftp_proxy" : "http_proxy"); |
991 | //FIXME: what if protocol is https? Ok to use http_proxy? | 1037 | //FIXME: what if protocol is https? Ok to use http_proxy? |
992 | use_proxy = (proxy && proxy[0]); | 1038 | use_proxy = (proxy && proxy[0]); |
993 | if (use_proxy) | 1039 | if (use_proxy) |
@@ -1048,7 +1094,7 @@ static void download_one_url(const char *url) | |||
1048 | /*G.content_len = 0; - redundant, got_clen = 0 is enough */ | 1094 | /*G.content_len = 0; - redundant, got_clen = 0 is enough */ |
1049 | G.got_clen = 0; | 1095 | G.got_clen = 0; |
1050 | G.chunked = 0; | 1096 | G.chunked = 0; |
1051 | if (use_proxy || target.protocol != P_FTP) { | 1097 | if (use_proxy || target.protocol[0] != 'f' /*not ftp[s]*/) { |
1052 | /* | 1098 | /* |
1053 | * HTTP session | 1099 | * HTTP session |
1054 | */ | 1100 | */ |
@@ -1066,7 +1112,7 @@ static void download_one_url(const char *url) | |||
1066 | # if ENABLE_FEATURE_WGET_HTTPS | 1112 | # if ENABLE_FEATURE_WGET_HTTPS |
1067 | if (fd < 0) { /* no openssl? try internal */ | 1113 | if (fd < 0) { /* no openssl? try internal */ |
1068 | sfp = open_socket(lsa); | 1114 | sfp = open_socket(lsa); |
1069 | spawn_ssl_client(server.host, fileno(sfp)); | 1115 | spawn_ssl_client(server.host, fileno(sfp), /*flags*/ 0); |
1070 | goto socket_opened; | 1116 | goto socket_opened; |
1071 | } | 1117 | } |
1072 | # else | 1118 | # else |
@@ -1083,7 +1129,7 @@ static void download_one_url(const char *url) | |||
1083 | /* Only internal TLS support is configured */ | 1129 | /* Only internal TLS support is configured */ |
1084 | sfp = open_socket(lsa); | 1130 | sfp = open_socket(lsa); |
1085 | if (target.protocol == P_HTTPS) | 1131 | if (target.protocol == P_HTTPS) |
1086 | spawn_ssl_client(server.host, fileno(sfp)); | 1132 | spawn_ssl_client(server.host, fileno(sfp), /*flags*/ 0); |
1087 | #else | 1133 | #else |
1088 | /* ssl (https) support is not configured */ | 1134 | /* ssl (https) support is not configured */ |
1089 | sfp = open_socket(lsa); | 1135 | sfp = open_socket(lsa); |
@@ -1162,7 +1208,7 @@ static void download_one_url(const char *url) | |||
1162 | * Retrieve HTTP response line and check for "200" status code. | 1208 | * Retrieve HTTP response line and check for "200" status code. |
1163 | */ | 1209 | */ |
1164 | read_response: | 1210 | read_response: |
1165 | fgets_and_trim(sfp, " %s\n"); | 1211 | fgets_trim_sanitize(sfp, " %s\n"); |
1166 | 1212 | ||
1167 | str = G.wget_buf; | 1213 | str = G.wget_buf; |
1168 | str = skip_non_whitespace(str); | 1214 | str = skip_non_whitespace(str); |
@@ -1173,7 +1219,7 @@ static void download_one_url(const char *url) | |||
1173 | switch (status) { | 1219 | switch (status) { |
1174 | case 0: | 1220 | case 0: |
1175 | case 100: | 1221 | case 100: |
1176 | while (gethdr(sfp) != NULL) | 1222 | while (get_sanitized_hdr(sfp) != NULL) |
1177 | /* eat all remaining headers */; | 1223 | /* eat all remaining headers */; |
1178 | goto read_response; | 1224 | goto read_response; |
1179 | 1225 | ||
@@ -1237,13 +1283,13 @@ However, in real world it was observed that some web servers | |||
1237 | /* Partial Content even though we did not ask for it??? */ | 1283 | /* Partial Content even though we did not ask for it??? */ |
1238 | /* fall through */ | 1284 | /* fall through */ |
1239 | default: | 1285 | default: |
1240 | bb_error_msg_and_die("server returned error: %s", sanitize_string(G.wget_buf)); | 1286 | bb_error_msg_and_die("server returned error: %s", G.wget_buf); |
1241 | } | 1287 | } |
1242 | 1288 | ||
1243 | /* | 1289 | /* |
1244 | * Retrieve HTTP headers. | 1290 | * Retrieve HTTP headers. |
1245 | */ | 1291 | */ |
1246 | while ((str = gethdr(sfp)) != NULL) { | 1292 | while ((str = get_sanitized_hdr(sfp)) != NULL) { |
1247 | static const char keywords[] ALIGN1 = | 1293 | static const char keywords[] ALIGN1 = |
1248 | "content-length\0""transfer-encoding\0""location\0"; | 1294 | "content-length\0""transfer-encoding\0""location\0"; |
1249 | enum { | 1295 | enum { |
@@ -1251,7 +1297,7 @@ However, in real world it was observed that some web servers | |||
1251 | }; | 1297 | }; |
1252 | smalluint key; | 1298 | smalluint key; |
1253 | 1299 | ||
1254 | /* gethdr converted "FOO:" string to lowercase */ | 1300 | /* get_sanitized_hdr converted "FOO:" string to lowercase */ |
1255 | 1301 | ||
1256 | /* strip trailing whitespace */ | 1302 | /* strip trailing whitespace */ |
1257 | char *s = strchrnul(str, '\0') - 1; | 1303 | char *s = strchrnul(str, '\0') - 1; |
@@ -1263,14 +1309,14 @@ However, in real world it was observed that some web servers | |||
1263 | if (key == KEY_content_length) { | 1309 | if (key == KEY_content_length) { |
1264 | G.content_len = BB_STRTOOFF(str, NULL, 10); | 1310 | G.content_len = BB_STRTOOFF(str, NULL, 10); |
1265 | if (G.content_len < 0 || errno) { | 1311 | if (G.content_len < 0 || errno) { |
1266 | bb_error_msg_and_die("content-length %s is garbage", sanitize_string(str)); | 1312 | bb_error_msg_and_die("content-length %s is garbage", str); |
1267 | } | 1313 | } |
1268 | G.got_clen = 1; | 1314 | G.got_clen = 1; |
1269 | continue; | 1315 | continue; |
1270 | } | 1316 | } |
1271 | if (key == KEY_transfer_encoding) { | 1317 | if (key == KEY_transfer_encoding) { |
1272 | if (strcmp(str_tolower(str), "chunked") != 0) | 1318 | if (strcmp(str_tolower(str), "chunked") != 0) |
1273 | bb_error_msg_and_die("transfer encoding '%s' is not supported", sanitize_string(str)); | 1319 | bb_error_msg_and_die("transfer encoding '%s' is not supported", str); |
1274 | G.chunked = 1; | 1320 | G.chunked = 1; |
1275 | } | 1321 | } |
1276 | if (key == KEY_location && status >= 300) { | 1322 | if (key == KEY_location && status >= 300) { |
@@ -1279,7 +1325,7 @@ However, in real world it was observed that some web servers | |||
1279 | fclose(sfp); | 1325 | fclose(sfp); |
1280 | if (str[0] == '/') { | 1326 | if (str[0] == '/') { |
1281 | free(redirected_path); | 1327 | free(redirected_path); |
1282 | target.path = redirected_path = xstrdup(str+1); | 1328 | target.path = redirected_path = xstrdup(str + 1); |
1283 | /* lsa stays the same: it's on the same server */ | 1329 | /* lsa stays the same: it's on the same server */ |
1284 | } else { | 1330 | } else { |
1285 | parse_url(str, &target); | 1331 | parse_url(str, &target); |
@@ -1326,7 +1372,7 @@ However, in real world it was observed that some web servers | |||
1326 | /* It's ftp. Close data connection properly */ | 1372 | /* It's ftp. Close data connection properly */ |
1327 | fclose(dfp); | 1373 | fclose(dfp); |
1328 | if (ftpcmd(NULL, NULL, sfp) != 226) | 1374 | if (ftpcmd(NULL, NULL, sfp) != 226) |
1329 | bb_error_msg_and_die("ftp error: %s", sanitize_string(G.wget_buf + 4)); | 1375 | bb_error_msg_and_die("ftp error: %s", G.wget_buf); |
1330 | /* ftpcmd("QUIT", NULL, sfp); - why bother? */ | 1376 | /* ftpcmd("QUIT", NULL, sfp); - why bother? */ |
1331 | } | 1377 | } |
1332 | fclose(sfp); | 1378 | fclose(sfp); |