wget: add support for https using "openssl s_client" as a helper
www.kernel.org started redirecting http:// to https:// making https support mandatory for any auto build scripts. function old new delta wget_main 2631 2971 +340 parse_url 409 471 +62 .rodata 115607 115626 +19 P_HTTPS - 6 +6 P_HTTP - 5 +5 P_FTP - 4 +4 ------------------------------------------------------------------------------ (add/remove: 3/0 grow/shrink: 3/0 up/down: 436/0) Total: 436 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
192c14bd87
commit
8b7e8ae224
@ -47,10 +47,13 @@ struct host_info {
|
|||||||
char *allocated;
|
char *allocated;
|
||||||
const char *path;
|
const char *path;
|
||||||
char *user;
|
char *user;
|
||||||
|
const char *protocol;
|
||||||
char *host;
|
char *host;
|
||||||
int port;
|
int port;
|
||||||
smallint is_ftp;
|
|
||||||
};
|
};
|
||||||
|
static const char P_FTP[] = "ftp";
|
||||||
|
static const char P_HTTP[] = "http";
|
||||||
|
static const char P_HTTPS[] = "https";
|
||||||
|
|
||||||
|
|
||||||
/* Globals */
|
/* Globals */
|
||||||
@ -219,7 +222,7 @@ static FILE *open_socket(len_and_sockaddr *lsa)
|
|||||||
/* glibc 2.4 seems to try seeking on it - ??! */
|
/* glibc 2.4 seems to try seeking on it - ??! */
|
||||||
/* hopefully it understands what ESPIPE means... */
|
/* hopefully it understands what ESPIPE means... */
|
||||||
fp = fdopen(fd, "r+");
|
fp = fdopen(fd, "r+");
|
||||||
if (fp == NULL)
|
if (!fp)
|
||||||
bb_perror_msg_and_die(bb_msg_memory_exhausted);
|
bb_perror_msg_and_die(bb_msg_memory_exhausted);
|
||||||
|
|
||||||
return fp;
|
return fp;
|
||||||
@ -274,23 +277,31 @@ static void parse_url(const char *src_url, struct host_info *h)
|
|||||||
free(h->allocated);
|
free(h->allocated);
|
||||||
h->allocated = url = xstrdup(src_url);
|
h->allocated = url = xstrdup(src_url);
|
||||||
|
|
||||||
if (strncmp(url, "ftp://", 6) == 0) {
|
h->protocol = P_FTP;
|
||||||
h->port = bb_lookup_port("ftp", "tcp", 21);
|
p = strstr(url, "://");
|
||||||
h->host = url + 6;
|
if (p) {
|
||||||
h->is_ftp = 1;
|
*p = '\0';
|
||||||
} else
|
h->host = p + 3;
|
||||||
if (strncmp(url, "http://", 7) == 0) {
|
if (strcmp(url, P_FTP) == 0) {
|
||||||
h->host = url + 7;
|
h->port = bb_lookup_port(P_FTP, "tcp", 21);
|
||||||
|
} else
|
||||||
|
if (strcmp(url, P_HTTPS) == 0) {
|
||||||
|
h->port = bb_lookup_port(P_HTTPS, "tcp", 443);
|
||||||
|
h->protocol = P_HTTPS;
|
||||||
|
} else
|
||||||
|
if (strcmp(url, P_HTTP) == 0) {
|
||||||
http:
|
http:
|
||||||
h->port = bb_lookup_port("http", "tcp", 80);
|
h->port = bb_lookup_port(P_HTTP, "tcp", 80);
|
||||||
h->is_ftp = 0;
|
h->protocol = P_HTTP;
|
||||||
} else
|
} else {
|
||||||
if (!strstr(url, "//")) {
|
*p = ':';
|
||||||
|
bb_error_msg_and_die("not an http or ftp url: %s", sanitize_string(url));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// GNU wget is user-friendly and falls back to http://
|
// GNU wget is user-friendly and falls back to http://
|
||||||
h->host = url;
|
h->host = url;
|
||||||
goto http;
|
goto http;
|
||||||
} else
|
}
|
||||||
bb_error_msg_and_die("not an http or ftp url: %s", sanitize_string(url));
|
|
||||||
|
|
||||||
// FYI:
|
// FYI:
|
||||||
// "Real" wget 'http://busybox.net?var=a/b' sends this request:
|
// "Real" wget 'http://busybox.net?var=a/b' sends this request:
|
||||||
@ -472,6 +483,56 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_
|
|||||||
return sfp;
|
return sfp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int spawn_https_helper(const char *host, unsigned port)
|
||||||
|
{
|
||||||
|
char *allocated = NULL;
|
||||||
|
int sp[2];
|
||||||
|
int pid;
|
||||||
|
|
||||||
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0)
|
||||||
|
/* Kernel can have AF_UNIX support disabled */
|
||||||
|
bb_perror_msg_and_die("socketpair");
|
||||||
|
|
||||||
|
if (!strchr(host, ':'))
|
||||||
|
host = allocated = xasprintf("%s:%u", host, port);
|
||||||
|
|
||||||
|
pid = BB_MMU ? xfork() : xvfork();
|
||||||
|
if (pid == 0) {
|
||||||
|
/* Child */
|
||||||
|
char *argv[6];
|
||||||
|
|
||||||
|
close(sp[0]);
|
||||||
|
xmove_fd(sp[1], 0);
|
||||||
|
xdup2(0, 1);
|
||||||
|
/*
|
||||||
|
* TODO: develop a tiny ssl/tls helper (using matrixssl?),
|
||||||
|
* try to exec it here before falling back to big fat openssl.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* openssl s_client -quiet -connect www.kernel.org:443 2>/dev/null
|
||||||
|
* It prints some debug stuff on stderr, don't know how to suppress it.
|
||||||
|
* Work around by dev-nulling stderr. We lose all error messages :(
|
||||||
|
*/
|
||||||
|
xmove_fd(2, 3);
|
||||||
|
xopen("/dev/null", O_RDWR);
|
||||||
|
argv[0] = (char*)"openssl";
|
||||||
|
argv[1] = (char*)"s_client";
|
||||||
|
argv[2] = (char*)"-quiet";
|
||||||
|
argv[3] = (char*)"-connect";
|
||||||
|
argv[4] = (char*)host;
|
||||||
|
argv[5] = NULL;
|
||||||
|
BB_EXECVP(argv[0], argv);
|
||||||
|
xmove_fd(3, 2);
|
||||||
|
bb_perror_msg_and_die("can't execute '%s'", argv[0]);
|
||||||
|
/* notreached */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parent process */
|
||||||
|
free(allocated);
|
||||||
|
close(sp[1]);
|
||||||
|
return sp[0];
|
||||||
|
}
|
||||||
|
|
||||||
static void NOINLINE retrieve_file_data(FILE *dfp)
|
static void NOINLINE retrieve_file_data(FILE *dfp)
|
||||||
{
|
{
|
||||||
#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
|
#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
|
||||||
@ -644,7 +705,8 @@ static void download_one_url(const char *url)
|
|||||||
/* Use the proxy if necessary */
|
/* Use the proxy if necessary */
|
||||||
use_proxy = (strcmp(G.proxy_flag, "off") != 0);
|
use_proxy = (strcmp(G.proxy_flag, "off") != 0);
|
||||||
if (use_proxy) {
|
if (use_proxy) {
|
||||||
proxy = getenv(target.is_ftp ? "ftp_proxy" : "http_proxy");
|
proxy = getenv(target.protocol == P_FTP ? "ftp_proxy" : "http_proxy");
|
||||||
|
//FIXME: what if protocol is https? Ok to use http_proxy?
|
||||||
use_proxy = (proxy && proxy[0]);
|
use_proxy = (proxy && proxy[0]);
|
||||||
if (use_proxy)
|
if (use_proxy)
|
||||||
parse_url(proxy, &server);
|
parse_url(proxy, &server);
|
||||||
@ -704,27 +766,31 @@ static void download_one_url(const char *url)
|
|||||||
/*G.content_len = 0; - redundant, got_clen = 0 is enough */
|
/*G.content_len = 0; - redundant, got_clen = 0 is enough */
|
||||||
G.got_clen = 0;
|
G.got_clen = 0;
|
||||||
G.chunked = 0;
|
G.chunked = 0;
|
||||||
if (use_proxy || !target.is_ftp) {
|
if (use_proxy || target.protocol != P_FTP) {
|
||||||
/*
|
/*
|
||||||
* HTTP session
|
* HTTP session
|
||||||
*/
|
*/
|
||||||
char *str;
|
char *str;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
/* Open socket to http(s) server */
|
||||||
/* Open socket to http server */
|
if (target.protocol == P_HTTPS) {
|
||||||
sfp = open_socket(lsa);
|
int fd = spawn_https_helper(server.host, server.port);
|
||||||
|
sfp = fdopen(fd, "r+");
|
||||||
|
if (!sfp)
|
||||||
|
bb_perror_msg_and_die(bb_msg_memory_exhausted);
|
||||||
|
} else
|
||||||
|
sfp = open_socket(lsa);
|
||||||
|
|
||||||
/* Send HTTP request */
|
/* Send HTTP request */
|
||||||
if (use_proxy) {
|
if (use_proxy) {
|
||||||
fprintf(sfp, "GET %stp://%s/%s HTTP/1.1\r\n",
|
fprintf(sfp, "GET %s://%s/%s HTTP/1.1\r\n",
|
||||||
target.is_ftp ? "f" : "ht", target.host,
|
target.protocol, target.host,
|
||||||
target.path);
|
target.path);
|
||||||
} else {
|
} else {
|
||||||
if (option_mask32 & WGET_OPT_POST_DATA)
|
fprintf(sfp, "%s /%s HTTP/1.1\r\n",
|
||||||
fprintf(sfp, "POST /%s HTTP/1.1\r\n", target.path);
|
(option_mask32 & WGET_OPT_POST_DATA) ? "POST" : "GET",
|
||||||
else
|
target.path);
|
||||||
fprintf(sfp, "GET /%s HTTP/1.1\r\n", target.path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n",
|
fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n",
|
||||||
|
Loading…
Reference in New Issue
Block a user