aboutsummaryrefslogtreecommitdiff
path: root/networking/wget.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2017-02-08 20:09:29 +0000
committerRon Yorston <rmy@pobox.com>2017-02-08 20:09:29 +0000
commit373275a708bafb88fa4f0519de2166154f44fed9 (patch)
tree4587b4fd3f695e0f3705b2a217e199f3144df931 /networking/wget.c
parentb74b2619779b1deb903b7766261807df1e9b1f7f (diff)
parentc2b18583a3df06aeecf535c3cea6856aa1f2e205 (diff)
downloadbusybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.tar.gz
busybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.tar.bz2
busybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'networking/wget.c')
-rw-r--r--networking/wget.c226
1 files changed, 140 insertions, 86 deletions
diff --git a/networking/wget.c b/networking/wget.c
index 460b4b833..b9d840328 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -16,12 +16,15 @@
16//config: wget is a utility for non-interactive download of files from HTTP 16//config: wget is a utility for non-interactive download of files from HTTP
17//config: and FTP servers. 17//config: and FTP servers.
18//config: 18//config:
19//config:config FEATURE_WGET_LONG_OPTIONS
20//config: bool "Enable long options"
21//config: default y
22//config: depends on WGET && LONG_OPTS
23//config:
19//config:config FEATURE_WGET_STATUSBAR 24//config:config FEATURE_WGET_STATUSBAR
20//config: bool "Enable a nifty process meter (+2k)" 25//config: bool "Enable progress bar (+2k)"
21//config: default y 26//config: default y
22//config: depends on WGET 27//config: depends on WGET
23//config: help
24//config: Enable the transfer progress bar for wget transfers.
25//config: 28//config:
26//config:config FEATURE_WGET_AUTHENTICATION 29//config:config FEATURE_WGET_AUTHENTICATION
27//config: bool "Enable HTTP authentication" 30//config: bool "Enable HTTP authentication"
@@ -30,13 +33,6 @@
30//config: help 33//config: help
31//config: Support authenticated HTTP transfers. 34//config: Support authenticated HTTP transfers.
32//config: 35//config:
33//config:config FEATURE_WGET_LONG_OPTIONS
34//config: bool "Enable long options"
35//config: default y
36//config: depends on WGET && LONG_OPTS
37//config: help
38//config: Support long options for the wget applet.
39//config:
40//config:config FEATURE_WGET_TIMEOUT 36//config:config FEATURE_WGET_TIMEOUT
41//config: bool "Enable timeout option -T SEC" 37//config: bool "Enable timeout option -T SEC"
42//config: default y 38//config: default y
@@ -51,18 +47,59 @@
51//config: FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option 47//config: FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option
52//config: will work in addition to -T. 48//config: will work in addition to -T.
53//config: 49//config:
50//config:config FEATURE_WGET_HTTPS
51//config: bool "Support HTTPS using internal TLS code"
52//config: default y
53//config: depends on WGET
54//config: select TLS
55//config: help
56//config: wget will use internal TLS code to connect to https:// URLs.
57//config: Note:
58//config: On NOMMU machines, ssl_helper applet should be available
59//config: in the $PATH for this to work. Make sure to select that applet.
60//config:
61//config: Note: currently, TLS code only makes TLS I/O work, it
62//config: does *not* check that the peer is who it claims to be, etc.
63//config: IOW: it uses peer-supplied public keys to establish encryption
64//config: and signing keys, then encrypts and signs outgoing data and
65//config: decrypts incoming data.
66//config: It does not check signature hashes on the incoming data:
67//config: this means that attackers manipulating TCP packets can
68//config: send altered data and we unknowingly receive garbage.
69//config: (This check might be relatively easy to add).
70//config: It does not check public key's certificate:
71//config: this means that the peer may be an attacker impersonating
72//config: the server we think we are talking to.
73//config:
74//config: If you think this is unacceptable, consider this. As more and more
75//config: servers switch to HTTPS-only operation, without such "crippled"
76//config: TLS code it is *impossible* to simply download a kernel source
77//config: from kernel.org. Which can in real world translate into
78//config: "my small automatic tooling to build cross-compilers from sources
79//config: no longer works, I need to additionally keep a local copy
80//config: of ~4 megabyte source tarball of a SSL library and ~2 megabyte
81//config: source of wget, need to compile and built both before I can
82//config: download anything. All this despite the fact that the build
83//config: is done in a QEMU sandbox on a machine with absolutely nothing
84//config: worth stealing, so I don't care if someone would go to a lot
85//config: of trouble to intercept my HTTPS download to send me an altered
86//config: kernel tarball".
87//config:
88//config: If you still think this is unacceptable, send patches.
89//config:
90//config: If you still think this is unacceptable, do not want to send
91//config: patches, but do want to waste bandwidth expaining how wrong
92//config: it is, you will be ignored.
93//config:
54//config:config FEATURE_WGET_OPENSSL 94//config:config FEATURE_WGET_OPENSSL
55//config: bool "Try to connect to HTTPS using openssl" 95//config: bool "Try to connect to HTTPS using openssl"
56//config: default y 96//config: default y
57//config: depends on WGET 97//config: depends on WGET
58//config: help 98//config: help
59//config: Choose how wget establishes SSL connection for https:// URLs. 99//config: Try to use openssl to handle HTTPS.
60//config:
61//config: Busybox itself contains no SSL code. wget will spawn
62//config: a helper program to talk over HTTPS.
63//config: 100//config:
64//config: OpenSSL has a simple SSL client for debug purposes. 101//config: OpenSSL has a simple SSL client for debug purposes.
65//config: If you select "openssl" helper, wget will effectively run: 102//config: If you select this option, wget will effectively run:
66//config: "openssl s_client -quiet -connect hostname:443 103//config: "openssl s_client -quiet -connect hostname:443
67//config: -servername hostname 2>/dev/null" and pipe its data 104//config: -servername hostname 2>/dev/null" and pipe its data
68//config: through it. -servername is not used if hostname is numeric. 105//config: through it. -servername is not used if hostname is numeric.
@@ -75,24 +112,9 @@
75//config: openssl is also a big binary, often dynamically linked 112//config: openssl is also a big binary, often dynamically linked
76//config: against ~15 libraries. 113//config: against ~15 libraries.
77//config: 114//config:
78//config:config FEATURE_WGET_SSL_HELPER 115//config: If openssl can't be executed, internal TLS code will be used
79//config: bool "Try to connect to HTTPS using ssl_helper" 116//config: (if you enabled it); if openssl can be executed but fails later,
80//config: default y 117//config: wget can't detect this, and download will fail.
81//config: depends on WGET
82//config: help
83//config: Choose how wget establishes SSL connection for https:// URLs.
84//config:
85//config: Busybox itself contains no SSL code. wget will spawn
86//config: a helper program to talk over HTTPS.
87//config:
88//config: ssl_helper is a tool which can be built statically
89//config: from busybox sources against a small embedded SSL library.
90//config: Please see networking/ssl_helper/README.
91//config: It does not require double host resolution and emits
92//config: error messages to stderr.
93//config:
94//config: Precompiled static binary may be available at
95//config: http://busybox.net/downloads/binaries/
96 118
97//applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP)) 119//applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP))
98 120
@@ -105,20 +127,21 @@
105/* Since we ignore these opts, we don't show them in --help */ 127/* Since we ignore these opts, we don't show them in --help */
106/* //usage: " [--no-check-certificate] [--no-cache] [--passive-ftp] [-t TRIES]" */ 128/* //usage: " [--no-check-certificate] [--no-cache] [--passive-ftp] [-t TRIES]" */
107/* //usage: " [-nv] [-nc] [-nH] [-np]" */ 129/* //usage: " [-nv] [-nc] [-nH] [-np]" */
108//usage: " [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." 130//usage: " [-S|--server-response] [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
109//usage: ) 131//usage: )
110//usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS( 132//usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS(
111//usage: "[-cq] [-O FILE] [-Y on/off] [-P DIR] [-U AGENT]" 133//usage: "[-cq] [-O FILE] [-Y on/off] [-P DIR] [-S] [-U AGENT]"
112//usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." 134//usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
113//usage: ) 135//usage: )
114//usage:#define wget_full_usage "\n\n" 136//usage:#define wget_full_usage "\n\n"
115//usage: "Retrieve files via HTTP or FTP\n" 137//usage: "Retrieve files via HTTP or FTP\n"
116//usage: IF_FEATURE_WGET_LONG_OPTIONS( 138//usage: IF_FEATURE_WGET_LONG_OPTIONS(
117//usage: "\n --spider Spider mode - only check file existence" 139//usage: "\n --spider Only check URL existence: $? is 0 if exists"
118//usage: ) 140//usage: )
119//usage: "\n -c Continue retrieval of aborted transfer" 141//usage: "\n -c Continue retrieval of aborted transfer"
120//usage: "\n -q Quiet" 142//usage: "\n -q Quiet"
121//usage: "\n -P DIR Save to DIR (default .)" 143//usage: "\n -P DIR Save to DIR (default .)"
144//usage: "\n -S Show server response"
122//usage: IF_FEATURE_WGET_TIMEOUT( 145//usage: IF_FEATURE_WGET_TIMEOUT(
123//usage: "\n -T SEC Network read timeout is SEC seconds" 146//usage: "\n -T SEC Network read timeout is SEC seconds"
124//usage: ) 147//usage: )
@@ -141,6 +164,8 @@
141#endif 164#endif
142 165
143 166
167#define SSL_SUPPORTED (ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_HTTPS)
168
144struct host_info { 169struct host_info {
145 char *allocated; 170 char *allocated;
146 const char *path; 171 const char *path;
@@ -151,7 +176,7 @@ struct host_info {
151}; 176};
152static const char P_FTP[] ALIGN1 = "ftp"; 177static const char P_FTP[] ALIGN1 = "ftp";
153static const char P_HTTP[] ALIGN1 = "http"; 178static const char P_HTTP[] ALIGN1 = "http";
154#if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER 179#if SSL_SUPPORTED
155static const char P_HTTPS[] ALIGN1 = "https"; 180static const char P_HTTPS[] ALIGN1 = "https";
156#endif 181#endif
157 182
@@ -232,16 +257,17 @@ struct globals {
232enum { 257enum {
233 WGET_OPT_CONTINUE = (1 << 0), 258 WGET_OPT_CONTINUE = (1 << 0),
234 WGET_OPT_QUIET = (1 << 1), 259 WGET_OPT_QUIET = (1 << 1),
235 WGET_OPT_OUTNAME = (1 << 2), 260 WGET_OPT_SERVER_RESPONSE = (1 << 2),
236 WGET_OPT_PREFIX = (1 << 3), 261 WGET_OPT_OUTNAME = (1 << 3),
237 WGET_OPT_PROXY = (1 << 4), 262 WGET_OPT_PREFIX = (1 << 4),
238 WGET_OPT_USER_AGENT = (1 << 5), 263 WGET_OPT_PROXY = (1 << 5),
239 WGET_OPT_NETWORK_READ_TIMEOUT = (1 << 6), 264 WGET_OPT_USER_AGENT = (1 << 6),
240 WGET_OPT_RETRIES = (1 << 7), 265 WGET_OPT_NETWORK_READ_TIMEOUT = (1 << 7),
241 WGET_OPT_nsomething = (1 << 8), 266 WGET_OPT_RETRIES = (1 << 8),
242 WGET_OPT_HEADER = (1 << 9) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 267 WGET_OPT_nsomething = (1 << 9),
243 WGET_OPT_POST_DATA = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 268 WGET_OPT_HEADER = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
244 WGET_OPT_SPIDER = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 269 WGET_OPT_POST_DATA = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
270 WGET_OPT_SPIDER = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
245}; 271};
246 272
247enum { 273enum {
@@ -395,7 +421,7 @@ static FILE *open_socket(len_and_sockaddr *lsa)
395} 421}
396 422
397/* Returns '\n' if it was seen, else '\0'. Trims at first '\r' or '\n' */ 423/* Returns '\n' if it was seen, else '\0'. Trims at first '\r' or '\n' */
398static char fgets_and_trim(FILE *fp) 424static char fgets_and_trim(FILE *fp, const char *fmt)
399{ 425{
400 char c; 426 char c;
401 char *buf_ptr; 427 char *buf_ptr;
@@ -413,6 +439,9 @@ static char fgets_and_trim(FILE *fp)
413 439
414 log_io("< %s", G.wget_buf); 440 log_io("< %s", G.wget_buf);
415 441
442 if (fmt && (option_mask32 & WGET_OPT_SERVER_RESPONSE))
443 fprintf(stderr, fmt, G.wget_buf);
444
416 return c; 445 return c;
417} 446}
418 447
@@ -423,6 +452,9 @@ static int ftpcmd(const char *s1, const char *s2, FILE *fp)
423 if (!s2) 452 if (!s2)
424 s2 = ""; 453 s2 = "";
425 fprintf(fp, "%s%s\r\n", s1, s2); 454 fprintf(fp, "%s%s\r\n", s1, s2);
455 /* With --server-response, wget also shows its ftp commands */
456 if (option_mask32 & WGET_OPT_SERVER_RESPONSE)
457 fprintf(stderr, "--> %s%s\n\n", s1, s2);
426 fflush(fp); 458 fflush(fp);
427 log_io("> %s%s", s1, s2); 459 log_io("> %s%s", s1, s2);
428#if ENABLE_PLATFORM_MINGW32 460#if ENABLE_PLATFORM_MINGW32
@@ -431,7 +463,7 @@ static int ftpcmd(const char *s1, const char *s2, FILE *fp)
431 } 463 }
432 464
433 do { 465 do {
434 fgets_and_trim(fp); 466 fgets_and_trim(fp, "%s\n");
435 } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' '); 467 } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' ');
436#if ENABLE_PLATFORM_MINGW32 468#if ENABLE_PLATFORM_MINGW32
437 fseek(fp, 0L, SEEK_CUR); 469 fseek(fp, 0L, SEEK_CUR);
@@ -458,7 +490,7 @@ static void parse_url(const char *src_url, struct host_info *h)
458 if (strcmp(url, P_FTP) == 0) { 490 if (strcmp(url, P_FTP) == 0) {
459 h->port = bb_lookup_port(P_FTP, "tcp", 21); 491 h->port = bb_lookup_port(P_FTP, "tcp", 21);
460 } else 492 } else
461#if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER 493#if SSL_SUPPORTED
462 if (strcmp(url, P_HTTPS) == 0) { 494 if (strcmp(url, P_HTTPS) == 0) {
463 h->port = bb_lookup_port(P_HTTPS, "tcp", 443); 495 h->port = bb_lookup_port(P_HTTPS, "tcp", 443);
464 h->protocol = P_HTTPS; 496 h->protocol = P_HTTPS;
@@ -480,7 +512,7 @@ static void parse_url(const char *src_url, struct host_info *h)
480 512
481 // FYI: 513 // FYI:
482 // "Real" wget 'http://busybox.net?var=a/b' sends this request: 514 // "Real" wget 'http://busybox.net?var=a/b' sends this request:
483 // 'GET /?var=a/b HTTP 1.0' 515 // 'GET /?var=a/b HTTP/1.0'
484 // and saves 'index.html?var=a%2Fb' (we save 'b') 516 // and saves 'index.html?var=a%2Fb' (we save 'b')
485 // wget 'http://busybox.net?login=john@doe': 517 // wget 'http://busybox.net?login=john@doe':
486 // request: 'GET /?login=john@doe HTTP/1.0' 518 // request: 'GET /?login=john@doe HTTP/1.0'
@@ -531,7 +563,7 @@ static char *gethdr(FILE *fp)
531 int c; 563 int c;
532 564
533 /* retrieve header line */ 565 /* retrieve header line */
534 c = fgets_and_trim(fp); 566 c = fgets_and_trim(fp, " %s\n");
535 567
536 /* end of the headers? */ 568 /* end of the headers? */
537 if (G.wget_buf[0] == '\0') 569 if (G.wget_buf[0] == '\0')
@@ -665,7 +697,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
665 char *servername; 697 char *servername;
666 int sp[2]; 698 int sp[2];
667 int pid; 699 int pid;
668 IF_FEATURE_WGET_SSL_HELPER(volatile int child_failed = 0;) 700 IF_FEATURE_WGET_HTTPS(volatile int child_failed = 0;)
669 701
670 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0) 702 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0)
671 /* Kernel can have AF_UNIX support disabled */ 703 /* Kernel can have AF_UNIX support disabled */
@@ -710,7 +742,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
710 742
711 BB_EXECVP(argv[0], argv); 743 BB_EXECVP(argv[0], argv);
712 xmove_fd(3, 2); 744 xmove_fd(3, 2);
713# if ENABLE_FEATURE_WGET_SSL_HELPER 745# if ENABLE_FEATURE_WGET_HTTPS
714 child_failed = 1; 746 child_failed = 1;
715 xfunc_die(); 747 xfunc_die();
716# else 748# else
@@ -723,7 +755,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
723 free(servername); 755 free(servername);
724 free(allocated); 756 free(allocated);
725 close(sp[1]); 757 close(sp[1]);
726# if ENABLE_FEATURE_WGET_SSL_HELPER 758# if ENABLE_FEATURE_WGET_HTTPS
727 if (child_failed) { 759 if (child_failed) {
728 close(sp[0]); 760 close(sp[0]);
729 return -1; 761 return -1;
@@ -733,38 +765,51 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
733} 765}
734#endif 766#endif
735 767
736/* See networking/ssl_helper/README how to build one */ 768#if ENABLE_FEATURE_WGET_HTTPS
737#if ENABLE_FEATURE_WGET_SSL_HELPER 769static void spawn_ssl_client(const char *host, int network_fd)
738static void spawn_https_helper_small(int network_fd)
739{ 770{
740 int sp[2]; 771 int sp[2];
741 int pid; 772 int pid;
773 char *servername, *p;
774
775 servername = xstrdup(host);
776 p = strrchr(servername, ':');
777 if (p) *p = '\0';
742 778
743 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0) 779 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0)
744 /* Kernel can have AF_UNIX support disabled */ 780 /* Kernel can have AF_UNIX support disabled */
745 bb_perror_msg_and_die("socketpair"); 781 bb_perror_msg_and_die("socketpair");
746 782
783 fflush_all();
747 pid = BB_MMU ? xfork() : xvfork(); 784 pid = BB_MMU ? xfork() : xvfork();
748 if (pid == 0) { 785 if (pid == 0) {
749 /* Child */ 786 /* Child */
750 char *argv[3];
751
752 close(sp[0]); 787 close(sp[0]);
753 xmove_fd(sp[1], 0); 788 xmove_fd(sp[1], 0);
754 xdup2(0, 1); 789 xdup2(0, 1);
755 xmove_fd(network_fd, 3); 790 if (BB_MMU) {
756 /* 791 tls_state_t *tls = new_tls_state();
757 * A simple ssl/tls helper 792 tls->ifd = tls->ofd = network_fd;
758 */ 793 tls_handshake(tls, servername);
759 argv[0] = (char*)"ssl_helper"; 794 tls_run_copy_loop(tls);
760 argv[1] = (char*)"-d3"; 795 exit(0);
761 argv[2] = NULL; 796 } else {
762 BB_EXECVP(argv[0], argv); 797 char *argv[5];
763 bb_perror_msg_and_die("can't execute '%s'", argv[0]); 798 xmove_fd(network_fd, 3);
799 argv[0] = (char*)"ssl_client";
800 argv[1] = (char*)"-s3";
801 //TODO: if (!is_ip_address(servername))...
802 argv[2] = (char*)"-n";
803 argv[3] = servername;
804 argv[4] = NULL;
805 BB_EXECVP(argv[0], argv);
806 bb_perror_msg_and_die("can't execute '%s'", argv[0]);
807 }
764 /* notreached */ 808 /* notreached */
765 } 809 }
766 810
767 /* Parent */ 811 /* Parent */
812 free(servername);
768 close(sp[1]); 813 close(sp[1]);
769 xmove_fd(sp[0], network_fd); 814 xmove_fd(sp[0], network_fd);
770} 815}
@@ -886,9 +931,9 @@ static void NOINLINE retrieve_file_data(FILE *dfp)
886 if (!G.chunked) 931 if (!G.chunked)
887 break; 932 break;
888 933
889 fgets_and_trim(dfp); /* Eat empty line */ 934 fgets_and_trim(dfp, NULL); /* Eat empty line */
890 get_clen: 935 get_clen:
891 fgets_and_trim(dfp); 936 fgets_and_trim(dfp, NULL);
892 G.content_len = STRTOOFF(G.wget_buf, NULL, 16); 937 G.content_len = STRTOOFF(G.wget_buf, NULL, 16);
893 /* FIXME: error check? */ 938 /* FIXME: error check? */
894 if (G.content_len == 0) 939 if (G.content_len == 0)
@@ -1013,16 +1058,16 @@ static void download_one_url(const char *url)
1013 1058
1014 /* Open socket to http(s) server */ 1059 /* Open socket to http(s) server */
1015#if ENABLE_FEATURE_WGET_OPENSSL 1060#if ENABLE_FEATURE_WGET_OPENSSL
1016 /* openssl (and maybe ssl_helper) support is configured */ 1061 /* openssl (and maybe internal TLS) support is configured */
1017 if (target.protocol == P_HTTPS) { 1062 if (target.protocol == P_HTTPS) {
1018 /* openssl-based helper 1063 /* openssl-based helper
1019 * Inconvenient API since we can't give it an open fd 1064 * Inconvenient API since we can't give it an open fd
1020 */ 1065 */
1021 int fd = spawn_https_helper_openssl(server.host, server.port); 1066 int fd = spawn_https_helper_openssl(server.host, server.port);
1022# if ENABLE_FEATURE_WGET_SSL_HELPER 1067# if ENABLE_FEATURE_WGET_HTTPS
1023 if (fd < 0) { /* no openssl? try ssl_helper */ 1068 if (fd < 0) { /* no openssl? try internal */
1024 sfp = open_socket(lsa); 1069 sfp = open_socket(lsa);
1025 spawn_https_helper_small(fileno(sfp)); 1070 spawn_ssl_client(server.host, fileno(sfp));
1026 goto socket_opened; 1071 goto socket_opened;
1027 } 1072 }
1028# else 1073# else
@@ -1035,11 +1080,11 @@ static void download_one_url(const char *url)
1035 } 1080 }
1036 sfp = open_socket(lsa); 1081 sfp = open_socket(lsa);
1037 socket_opened: 1082 socket_opened:
1038#elif ENABLE_FEATURE_WGET_SSL_HELPER 1083#elif ENABLE_FEATURE_WGET_HTTPS
1039 /* Only ssl_helper support is configured */ 1084 /* Only internal TLS support is configured */
1040 sfp = open_socket(lsa); 1085 sfp = open_socket(lsa);
1041 if (target.protocol == P_HTTPS) 1086 if (target.protocol == P_HTTPS)
1042 spawn_https_helper_small(fileno(sfp)); 1087 spawn_ssl_client(server.host, fileno(sfp));
1043#else 1088#else
1044 /* ssl (https) support is not configured */ 1089 /* ssl (https) support is not configured */
1045 sfp = open_socket(lsa); 1090 sfp = open_socket(lsa);
@@ -1099,18 +1144,26 @@ static void download_one_url(const char *url)
1099 } 1144 }
1100 1145
1101 fflush(sfp); 1146 fflush(sfp);
1102 /* If we use SSL helper, keeping our end of the socket open for writing 1147
1103 * makes our end (i.e. the same fd!) readable (EAGAIN instead of EOF) 1148/* Tried doing this unconditionally.
1104 * even after child closes its copy of the fd. 1149 * Cloudflare and nginx/1.11.5 are shocked to see SHUT_WR on non-HTTPS.
1105 * This helps: 1150 */
1106 */ 1151#if SSL_SUPPORTED
1107 shutdown(fileno(sfp), SHUT_WR); 1152 if (target.protocol == P_HTTPS) {
1153 /* If we use SSL helper, keeping our end of the socket open for writing
1154 * makes our end (i.e. the same fd!) readable (EAGAIN instead of EOF)
1155 * even after child closes its copy of the fd.
1156 * This helps:
1157 */
1158 shutdown(fileno(sfp), SHUT_WR);
1159 }
1160#endif
1108 1161
1109 /* 1162 /*
1110 * Retrieve HTTP response line and check for "200" status code. 1163 * Retrieve HTTP response line and check for "200" status code.
1111 */ 1164 */
1112 read_response: 1165 read_response:
1113 fgets_and_trim(sfp); 1166 fgets_and_trim(sfp, " %s\n");
1114 1167
1115 str = G.wget_buf; 1168 str = G.wget_buf;
1116 str = skip_non_whitespace(str); 1169 str = skip_non_whitespace(str);
@@ -1295,6 +1348,7 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
1295 /* name, has_arg, val */ 1348 /* name, has_arg, val */
1296 "continue\0" No_argument "c" 1349 "continue\0" No_argument "c"
1297 "quiet\0" No_argument "q" 1350 "quiet\0" No_argument "q"
1351 "server-response\0" No_argument "S"
1298 "output-document\0" Required_argument "O" 1352 "output-document\0" Required_argument "O"
1299 "directory-prefix\0" Required_argument "P" 1353 "directory-prefix\0" Required_argument "P"
1300 "proxy\0" Required_argument "Y" 1354 "proxy\0" Required_argument "Y"
@@ -1337,7 +1391,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0")
1337#endif 1391#endif
1338 opt_complementary = "-1" /* at least one URL */ 1392 opt_complementary = "-1" /* at least one URL */
1339 IF_FEATURE_WGET_LONG_OPTIONS(":\xff::"); /* --header is a list */ 1393 IF_FEATURE_WGET_LONG_OPTIONS(":\xff::"); /* --header is a list */
1340 getopt32(argv, "cqO:P:Y:U:T:+" 1394 getopt32(argv, "cqSO:P:Y:U:T:+"
1341 /*ignored:*/ "t:" 1395 /*ignored:*/ "t:"
1342 /*ignored:*/ "n::" 1396 /*ignored:*/ "n::"
1343 /* wget has exactly four -n<letter> opts, all of which we can ignore: 1397 /* wget has exactly four -n<letter> opts, all of which we can ignore: