diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-02-06 15:15:08 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-02-06 15:15:08 +0100 |
commit | 403f2999f94937ba3f37db6d093832f636815bb9 (patch) | |
tree | 8a9167e639458e9aee5cdc4fa6685b179c02239d | |
parent | e999657f6da95b8a40e51978461d964b56189e92 (diff) | |
download | busybox-w32-403f2999f94937ba3f37db6d093832f636815bb9.tar.gz busybox-w32-403f2999f94937ba3f37db6d093832f636815bb9.tar.bz2 busybox-w32-403f2999f94937ba3f37db6d093832f636815bb9.zip |
wget: initial support for ftps://
function old new delta
spawn_ssl_client - 185 +185
parse_url 409 461 +52
packed_usage 32259 32278 +19
tls_run_copy_loop 293 306 +13
ssl_client_main 128 138 +10
showmode 330 338 +8
P_FTPS - 5 +5
filter_datapoints 177 179 +2
deflate 907 905 -2
decode_one_format 723 716 -7
wget_main 2591 2440 -151
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 6/3 up/down: 294/-160) Total: 134 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | include/libbb.h | 3 | ||||
-rw-r--r-- | networking/ssl_client.c | 14 | ||||
-rw-r--r-- | networking/tls.c | 4 | ||||
-rw-r--r-- | networking/wget.c | 37 |
4 files changed, 42 insertions, 16 deletions
diff --git a/include/libbb.h b/include/libbb.h index 2bb364366..a4eb6ee67 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -772,7 +772,8 @@ static inline tls_state_t *new_tls_state(void) | |||
772 | return tls; | 772 | return tls; |
773 | } | 773 | } |
774 | void tls_handshake(tls_state_t *tls, const char *sni) FAST_FUNC; | 774 | void tls_handshake(tls_state_t *tls, const char *sni) FAST_FUNC; |
775 | void tls_run_copy_loop(tls_state_t *tls) FAST_FUNC; | 775 | #define TLSLOOP_EXIT_ON_LOCAL_EOF (1 << 0) |
776 | void tls_run_copy_loop(tls_state_t *tls, unsigned flags) FAST_FUNC; | ||
776 | 777 | ||
777 | 778 | ||
778 | void socket_want_pktinfo(int fd) FAST_FUNC; | 779 | void socket_want_pktinfo(int fd) FAST_FUNC; |
diff --git a/networking/ssl_client.c b/networking/ssl_client.c index d479846d7..eb84e7726 100644 --- a/networking/ssl_client.c +++ b/networking/ssl_client.c | |||
@@ -15,7 +15,7 @@ | |||
15 | //kbuild:lib-$(CONFIG_SSL_CLIENT) += ssl_client.o | 15 | //kbuild:lib-$(CONFIG_SSL_CLIENT) += ssl_client.o |
16 | 16 | ||
17 | //usage:#define ssl_client_trivial_usage | 17 | //usage:#define ssl_client_trivial_usage |
18 | //usage: "-s FD [-r FD] [-n SNI]" | 18 | //usage: "[-e] -s FD [-r FD] [-n SNI]" |
19 | //usage:#define ssl_client_full_usage "" | 19 | //usage:#define ssl_client_full_usage "" |
20 | 20 | ||
21 | #include "libbb.h" | 21 | #include "libbb.h" |
@@ -30,26 +30,28 @@ int ssl_client_main(int argc UNUSED_PARAM, char **argv) | |||
30 | // INIT_G(); | 30 | // INIT_G(); |
31 | 31 | ||
32 | tls = new_tls_state(); | 32 | tls = new_tls_state(); |
33 | opt = getopt32(argv, "s:#r:#n:", &tls->ofd, &tls->ifd, &sni); | 33 | opt = getopt32(argv, "es:#r:#n:", &tls->ofd, &tls->ifd, &sni); |
34 | if (!(opt & 2)) { | 34 | if (!(opt & (1<<2))) { |
35 | /* -r N defaults to -s N */ | 35 | /* -r N defaults to -s N */ |
36 | tls->ifd = tls->ofd; | 36 | tls->ifd = tls->ofd; |
37 | } | 37 | } |
38 | 38 | ||
39 | if (!(opt & 3)) { | 39 | if (!(opt & (3<<1))) { |
40 | if (!argv[1]) | 40 | if (!argv[1]) |
41 | bb_show_usage(); | 41 | bb_show_usage(); |
42 | /* Undocumented debug feature: without -s and -r, takes HOST arg and connects to it */ | 42 | /* Undocumented debug feature: without -s and -r, takes HOST arg and connects to it */ |
43 | // | 43 | // |
44 | // Talk to kernel.org: | 44 | // Talk to kernel.org: |
45 | // printf "GET / HTTP/1.1\r\nHost: kernel.org\r\n\r\n" | ./busybox ssl_client kernel.org | 45 | // printf "GET / HTTP/1.1\r\nHost: kernel.org\r\n\r\n" | busybox ssl_client kernel.org |
46 | if (!sni) | 46 | if (!sni) |
47 | sni = argv[1]; | 47 | sni = argv[1]; |
48 | tls->ifd = tls->ofd = create_and_connect_stream_or_die(argv[1], 443); | 48 | tls->ifd = tls->ofd = create_and_connect_stream_or_die(argv[1], 443); |
49 | } | 49 | } |
50 | 50 | ||
51 | tls_handshake(tls, sni); | 51 | tls_handshake(tls, sni); |
52 | tls_run_copy_loop(tls); | 52 | |
53 | BUILD_BUG_ON(TLSLOOP_EXIT_ON_LOCAL_EOF != 1); | ||
54 | tls_run_copy_loop(tls, /*flags*/ opt & 1); | ||
53 | 55 | ||
54 | return EXIT_SUCCESS; | 56 | return EXIT_SUCCESS; |
55 | } | 57 | } |
diff --git a/networking/tls.c b/networking/tls.c index 7936afca2..da7b6058f 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -1727,7 +1727,7 @@ static void tls_xwrite(tls_state_t *tls, int len) | |||
1727 | // openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL | 1727 | // openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL |
1728 | // openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256 | 1728 | // openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256 |
1729 | 1729 | ||
1730 | void FAST_FUNC tls_run_copy_loop(tls_state_t *tls) | 1730 | void FAST_FUNC tls_run_copy_loop(tls_state_t *tls, unsigned flags) |
1731 | { | 1731 | { |
1732 | int inbuf_size; | 1732 | int inbuf_size; |
1733 | const int INBUF_STEP = 4 * 1024; | 1733 | const int INBUF_STEP = 4 * 1024; |
@@ -1762,6 +1762,8 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t *tls) | |||
1762 | */ | 1762 | */ |
1763 | pfds[0].fd = -1; | 1763 | pfds[0].fd = -1; |
1764 | tls_free_outbuf(tls); /* mem usage optimization */ | 1764 | tls_free_outbuf(tls); /* mem usage optimization */ |
1765 | if (flags & TLSLOOP_EXIT_ON_LOCAL_EOF) | ||
1766 | break; | ||
1765 | } else { | 1767 | } else { |
1766 | if (nread == inbuf_size) { | 1768 | if (nread == inbuf_size) { |
1767 | /* TLS has per record overhead, if input comes fast, | 1769 | /* TLS has per record overhead, if input comes fast, |
diff --git a/networking/wget.c b/networking/wget.c index 9300fa30b..daa728a9d 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 | ||
@@ -484,6 +488,12 @@ static void parse_url(const char *src_url, struct host_info *h) | |||
484 | h->port = bb_lookup_port(P_FTP, "tcp", 21); | 488 | h->port = bb_lookup_port(P_FTP, "tcp", 21); |
485 | } else | 489 | } else |
486 | #if SSL_SUPPORTED | 490 | #if SSL_SUPPORTED |
491 | # if ENABLE_FEATURE_WGET_HTTPS | ||
492 | if (strcmp(url, P_FTPS) == 0) { | ||
493 | h->port = bb_lookup_port(P_FTPS, "tcp", 990); | ||
494 | h->protocol = P_FTPS; | ||
495 | } else | ||
496 | # endif | ||
487 | if (strcmp(url, P_HTTPS) == 0) { | 497 | if (strcmp(url, P_HTTPS) == 0) { |
488 | h->port = bb_lookup_port(P_HTTPS, "tcp", 443); | 498 | h->port = bb_lookup_port(P_HTTPS, "tcp", 443); |
489 | h->protocol = P_HTTPS; | 499 | h->protocol = P_HTTPS; |
@@ -678,7 +688,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) | |||
678 | #endif | 688 | #endif |
679 | 689 | ||
680 | #if ENABLE_FEATURE_WGET_HTTPS | 690 | #if ENABLE_FEATURE_WGET_HTTPS |
681 | static void spawn_ssl_client(const char *host, int network_fd) | 691 | static void spawn_ssl_client(const char *host, int network_fd, int flags) |
682 | { | 692 | { |
683 | int sp[2]; | 693 | int sp[2]; |
684 | int pid; | 694 | int pid; |
@@ -703,17 +713,19 @@ static void spawn_ssl_client(const char *host, int network_fd) | |||
703 | tls_state_t *tls = new_tls_state(); | 713 | tls_state_t *tls = new_tls_state(); |
704 | tls->ifd = tls->ofd = network_fd; | 714 | tls->ifd = tls->ofd = network_fd; |
705 | tls_handshake(tls, servername); | 715 | tls_handshake(tls, servername); |
706 | tls_run_copy_loop(tls); | 716 | tls_run_copy_loop(tls, flags); |
707 | exit(0); | 717 | exit(0); |
708 | } else { | 718 | } else { |
709 | char *argv[5]; | 719 | char *argv[6]; |
720 | |||
710 | xmove_fd(network_fd, 3); | 721 | xmove_fd(network_fd, 3); |
711 | argv[0] = (char*)"ssl_client"; | 722 | argv[0] = (char*)"ssl_client"; |
712 | argv[1] = (char*)"-s3"; | 723 | argv[1] = (char*)"-s3"; |
713 | //TODO: if (!is_ip_address(servername))... | 724 | //TODO: if (!is_ip_address(servername))... |
714 | argv[2] = (char*)"-n"; | 725 | argv[2] = (char*)"-n"; |
715 | argv[3] = servername; | 726 | argv[3] = servername; |
716 | argv[4] = NULL; | 727 | argv[4] = (flags & TLSLOOP_EXIT_ON_LOCAL_EOF ? (char*)"-e" : NULL); |
728 | argv[5] = NULL; | ||
717 | BB_EXECVP(argv[0], argv); | 729 | BB_EXECVP(argv[0], argv); |
718 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); | 730 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); |
719 | } | 731 | } |
@@ -737,6 +749,11 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ | |||
737 | target->user = xstrdup("anonymous:busybox@"); | 749 | target->user = xstrdup("anonymous:busybox@"); |
738 | 750 | ||
739 | sfp = open_socket(lsa); | 751 | sfp = open_socket(lsa); |
752 | #if ENABLE_FEATURE_WGET_HTTPS | ||
753 | if (target->protocol == P_FTPS) | ||
754 | spawn_ssl_client(target->host, fileno(sfp), TLSLOOP_EXIT_ON_LOCAL_EOF); | ||
755 | #endif | ||
756 | |||
740 | if (ftpcmd(NULL, NULL, sfp) != 220) | 757 | if (ftpcmd(NULL, NULL, sfp) != 220) |
741 | bb_error_msg_and_die("%s", sanitize_string(G.wget_buf + 4)); | 758 | bb_error_msg_and_die("%s", sanitize_string(G.wget_buf + 4)); |
742 | 759 | ||
@@ -794,6 +811,10 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ | |||
794 | 811 | ||
795 | *dfpp = open_socket(lsa); | 812 | *dfpp = open_socket(lsa); |
796 | 813 | ||
814 | //For encrypted data, need to send "PROT P" and get "200 PROT now Private" response first | ||
815 | //Without it (or with "PROT C"), data is sent unencrypted | ||
816 | //spawn_ssl_client(target->host, fileno(*dfpp), /*flags*/ 0); | ||
817 | |||
797 | if (G.beg_range != 0) { | 818 | if (G.beg_range != 0) { |
798 | sprintf(G.wget_buf, "REST %"OFF_FMT"u", G.beg_range); | 819 | sprintf(G.wget_buf, "REST %"OFF_FMT"u", G.beg_range); |
799 | if (ftpcmd(G.wget_buf, NULL, sfp) == 350) | 820 | if (ftpcmd(G.wget_buf, NULL, sfp) == 350) |
@@ -981,7 +1002,7 @@ static void download_one_url(const char *url) | |||
981 | /* Use the proxy if necessary */ | 1002 | /* Use the proxy if necessary */ |
982 | use_proxy = (strcmp(G.proxy_flag, "off") != 0); | 1003 | use_proxy = (strcmp(G.proxy_flag, "off") != 0); |
983 | if (use_proxy) { | 1004 | if (use_proxy) { |
984 | proxy = getenv(target.protocol == P_FTP ? "ftp_proxy" : "http_proxy"); | 1005 | proxy = getenv(target.protocol[0] == 'f' ? "ftp_proxy" : "http_proxy"); |
985 | //FIXME: what if protocol is https? Ok to use http_proxy? | 1006 | //FIXME: what if protocol is https? Ok to use http_proxy? |
986 | use_proxy = (proxy && proxy[0]); | 1007 | use_proxy = (proxy && proxy[0]); |
987 | if (use_proxy) | 1008 | if (use_proxy) |
@@ -1042,7 +1063,7 @@ static void download_one_url(const char *url) | |||
1042 | /*G.content_len = 0; - redundant, got_clen = 0 is enough */ | 1063 | /*G.content_len = 0; - redundant, got_clen = 0 is enough */ |
1043 | G.got_clen = 0; | 1064 | G.got_clen = 0; |
1044 | G.chunked = 0; | 1065 | G.chunked = 0; |
1045 | if (use_proxy || target.protocol != P_FTP) { | 1066 | if (use_proxy || target.protocol[0] != 'f' /*not ftp[s]*/) { |
1046 | /* | 1067 | /* |
1047 | * HTTP session | 1068 | * HTTP session |
1048 | */ | 1069 | */ |
@@ -1060,7 +1081,7 @@ static void download_one_url(const char *url) | |||
1060 | # if ENABLE_FEATURE_WGET_HTTPS | 1081 | # if ENABLE_FEATURE_WGET_HTTPS |
1061 | if (fd < 0) { /* no openssl? try internal */ | 1082 | if (fd < 0) { /* no openssl? try internal */ |
1062 | sfp = open_socket(lsa); | 1083 | sfp = open_socket(lsa); |
1063 | spawn_ssl_client(server.host, fileno(sfp)); | 1084 | spawn_ssl_client(server.host, fileno(sfp), /*flags*/ 0); |
1064 | goto socket_opened; | 1085 | goto socket_opened; |
1065 | } | 1086 | } |
1066 | # else | 1087 | # else |
@@ -1077,7 +1098,7 @@ static void download_one_url(const char *url) | |||
1077 | /* Only internal TLS support is configured */ | 1098 | /* Only internal TLS support is configured */ |
1078 | sfp = open_socket(lsa); | 1099 | sfp = open_socket(lsa); |
1079 | if (target.protocol == P_HTTPS) | 1100 | if (target.protocol == P_HTTPS) |
1080 | spawn_ssl_client(server.host, fileno(sfp)); | 1101 | spawn_ssl_client(server.host, fileno(sfp), /*flags*/ 0); |
1081 | #else | 1102 | #else |
1082 | /* ssl (https) support is not configured */ | 1103 | /* ssl (https) support is not configured */ |
1083 | sfp = open_socket(lsa); | 1104 | sfp = open_socket(lsa); |