diff options
author | Denys Vlasenko | 2017-01-23 01:08:16 +0100 |
---|---|---|
committer | Denys Vlasenko | 2017-01-23 01:08:16 +0100 |
commit | 9a647c326a41e8160d53e6cb5470161a44c0e8cf (patch) | |
tree | 1fef73df291e5c5897aef1bb32b65206caacf879 /networking | |
parent | e1f90d13fa07d2974908470ce818ef956b7740f2 (diff) | |
download | busybox-9a647c326a41e8160d53e6cb5470161a44c0e8cf.zip busybox-9a647c326a41e8160d53e6cb5470161a44c0e8cf.tar.gz |
separate TLS code into a library, use in in wget
A new applet, ssl_client, is the TLS debug thing now.
It doubles as wget's NOMMU helper.
In MMU mode, wget still forks, but then directly calls TLS code,
without execing.
This can also be applied to sendmail/popmail (SMTPS / SMTP+starttls support)
and nc --ssl (ncat, nmap's nc clone, has such option).
function old new delta
tls_handshake - 1691 +1691
tls_run_copy_loop - 443 +443
ssl_client_main - 128 +128
packed_usage 30978 31007 +29
wget_main 2508 2535 +27
applet_names 2553 2560 +7
...
xwrite_encrypted 360 342 -18
tls_main 2127 - -2127
------------------------------------------------------------------------------
(add/remove: 4/1 grow/shrink: 13/8 up/down: 2351/-2195) Total: 156 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking')
-rw-r--r-- | networking/ssl_client.c | 55 | ||||
-rw-r--r-- | networking/tls.c | 151 | ||||
-rw-r--r-- | networking/wget.c | 102 |
3 files changed, 154 insertions, 154 deletions
diff --git a/networking/ssl_client.c b/networking/ssl_client.c new file mode 100644 index 0000000..cfeae15 --- /dev/null +++ b/networking/ssl_client.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +//config:config SSL_CLIENT +//config: bool "ssl_client" +//config: default y +//config: select TLS +//config: help +//config: This tool pipes data to/from a socket, TLS-encrypting it. + +//applet:IF_SSL_CLIENT(APPLET(ssl_client, BB_DIR_USR_BIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_SSL_CLIENT) += ssl_client.o + +//usage:#define ssl_client_trivial_usage +//usage: "-s FD [-r FD] [-n SNI]" +//usage:#define ssl_client_full_usage "" + +#include "libbb.h" + +int ssl_client_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int ssl_client_main(int argc UNUSED_PARAM, char **argv) +{ + tls_state_t *tls; + const char *sni = NULL; + int opt; + + // INIT_G(); + + tls = new_tls_state(); + opt = getopt32(argv, "s:#r:#n:", &tls->ofd, &tls->ifd, &sni); + if (!(opt & 2)) { + /* -r N defaults to -s N */ + tls->ifd = tls->ofd; + } + + if (!(opt & 3)) { + if (!argv[1]) + bb_show_usage(); + /* Undocumented debug feature: without -s and -r, takes HOST arg and connects to it */ + // + // Talk to kernel.org: + // printf "GET / HTTP/1.1\r\nHost: kernel.org\r\n\r\n" | ./busybox ssl_client kernel.org + if (!sni) + sni = argv[1]; + tls->ifd = tls->ofd = create_and_connect_stream_or_die(argv[1], 443); + } + + tls_handshake(tls, sni); + tls_run_copy_loop(tls); + + return EXIT_SUCCESS; +} diff --git a/networking/tls.c b/networking/tls.c index b111e4b..29cc5b9 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -4,11 +4,9 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config TLS -//config: bool "tls (debugging)" +//config: bool #No description makes it a hidden option //config: default n -//applet:IF_TLS(APPLET(tls, BB_DIR_USR_BIN, BB_SUID_DROP)) - //kbuild:lib-$(CONFIG_TLS) += tls.o //kbuild:lib-$(CONFIG_TLS) += tls_pstm.o //kbuild:lib-$(CONFIG_TLS) += tls_pstm_montgomery_reduce.o @@ -18,12 +16,7 @@ //kbuild:lib-$(CONFIG_TLS) += tls_aes.o ////kbuild:lib-$(CONFIG_TLS) += tls_aes_gcm.o -//usage:#define tls_trivial_usage -//usage: "HOST[:PORT]" -//usage:#define tls_full_usage "\n\n" - #include "tls.h" -//#include "common_bufsiz.h" #define TLS_DEBUG 1 #define TLS_DEBUG_HASH 0 @@ -165,13 +158,6 @@ #define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE enum { - SHA256_INSIZE = 64, - SHA256_OUTSIZE = 32, - - AES_BLOCKSIZE = 16, - AES128_KEYSIZE = 16, - AES256_KEYSIZE = 32, - RSA_PREMASTER_SIZE = 48, RECHDR_LEN = 5, @@ -225,20 +211,7 @@ struct record_hdr { uint8_t len16_hi, len16_lo; }; -typedef struct tls_state { - int fd; - - int min_encrypted_len_on_read; - uint8_t encrypt_on_write; - - uint8_t *outbuf; - int outbuf_size; - - int inbuf_size; - int ofs_to_buffered; - int buffered_size; - uint8_t *inbuf; - +struct tls_handshake_data { //TODO: store just the DER key here, parse/use/delete it when sending client key //this way it will stay key type agnostic here. psRsaKey_t server_rsa_pub_key; @@ -247,22 +220,7 @@ typedef struct tls_state { // these two are unused after finished messages are exchanged: sha256_ctx_t handshake_sha256_ctx; uint8_t master_secret[48]; - - // RFC 5246 - // sequence number - // Each connection state contains a sequence number, which is - // maintained separately for read and write states. The sequence - // number MUST be set to zero whenever a connection state is made the - // active state. Sequence numbers are of type uint64 and may not - // exceed 2^64-1. - /*uint64_t read_seq64_be;*/ - uint64_t write_seq64_be; - - uint8_t client_write_MAC_key[SHA256_OUTSIZE]; - uint8_t server_write_MAC_key[SHA256_OUTSIZE]; - uint8_t client_write_key[AES256_KEYSIZE]; - uint8_t server_write_key[AES256_KEYSIZE]; -} tls_state_t; +}; static unsigned get24be(const uint8_t *p) @@ -487,14 +445,6 @@ static void prf_hmac_sha256( #undef SEED } -static tls_state_t *new_tls_state(void) -{ - tls_state_t *tls = xzalloc(sizeof(*tls)); - tls->fd = -1; - sha256_begin(&tls->handshake_sha256_ctx); - return tls; -} - static void tls_error_die(tls_state_t *tls) { dump_tls_record(tls->inbuf, tls->ofs_to_buffered + tls->buffered_size); @@ -597,7 +547,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) xhdr->len16_hi = size >> 8; xhdr->len16_lo = size & 0xff; dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); - xwrite(tls->fd, xhdr, RECHDR_LEN + size); + xwrite(tls->ofd, xhdr, RECHDR_LEN + size); dbg("wrote %u bytes (NULL crypt, SHA256 hash)\n", size); return; } @@ -681,7 +631,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) xhdr->len16_hi = size >> 8; xhdr->len16_lo = size & 0xff; dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); - xwrite(tls->fd, xhdr, RECHDR_LEN + size); + xwrite(tls->ofd, xhdr, RECHDR_LEN + size); dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); } @@ -697,10 +647,10 @@ static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) xhdr->len16_hi = size >> 8; xhdr->len16_lo = size & 0xff; dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); - xwrite(tls->fd, xhdr, RECHDR_LEN + size); + xwrite(tls->ofd, xhdr, RECHDR_LEN + size); dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); /* Handshake hash does not include record headers */ - sha256_hash_dbg(">> sha256:%s", &tls->handshake_sha256_ctx, buf, size); + sha256_hash_dbg(">> sha256:%s", &tls->hsd->handshake_sha256_ctx, buf, size); return; } xwrite_encrypted(tls, size, RECORD_TYPE_HANDSHAKE); @@ -769,7 +719,7 @@ static int tls_xread_record(tls_state_t *tls) rem = tls->inbuf_size - total; tls->inbuf = xrealloc(tls->inbuf, tls->inbuf_size); } - sz = safe_read(tls->fd, tls->inbuf + total, rem); + sz = safe_read(tls->ifd, tls->inbuf + total, rem); if (sz <= 0) { if (sz == 0 && total == 0) { /* "Abrupt" EOF, no TLS shutdown (seen from kernel.org) */ @@ -848,7 +798,7 @@ static int tls_xread_record(tls_state_t *tls) * in our FINISHED record must include data of incoming packets too! */ if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE) { - sha256_hash_dbg("<< sha256:%s", &tls->handshake_sha256_ctx, tls->inbuf + RECHDR_LEN, sz); + sha256_hash_dbg("<< sha256:%s", &tls->hsd->handshake_sha256_ctx, tls->inbuf + RECHDR_LEN, sz); } end: dbg("got block len:%u\n", sz); @@ -1059,12 +1009,12 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) xfunc_die(); der++; der = enter_der_item(der, &end); /* enter SEQ */ - /* memset(tls->server_rsa_pub_key, 0, sizeof(tls->server_rsa_pub_key)); - already is */ - der_binary_to_pstm(&tls->server_rsa_pub_key.N, der, end); /* modulus */ + /* memset(tls->hsd->server_rsa_pub_key, 0, sizeof(tls->hsd->server_rsa_pub_key)); - already is */ + der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.N, der, end); /* modulus */ der = skip_der_item(der, end); - der_binary_to_pstm(&tls->server_rsa_pub_key.e, der, end); /* exponent */ - tls->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->server_rsa_pub_key.N); - dbg("server_rsa_pub_key.size:%d\n", tls->server_rsa_pub_key.size); + der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.e, der, end); /* exponent */ + tls->hsd->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->hsd->server_rsa_pub_key.N); + dbg("server_rsa_pub_key.size:%d\n", tls->hsd->server_rsa_pub_key.size); } /* @@ -1140,7 +1090,7 @@ static void send_client_hello(tls_state_t *tls, const char *sni) tls_get_random(record->rand32, sizeof(record->rand32)); if (TLS_DEBUG_FIXED_SECRETS) memset(record->rand32, 0x11, sizeof(record->rand32)); - memcpy(tls->client_and_server_rand32, record->rand32, sizeof(record->rand32)); + memcpy(tls->hsd->client_and_server_rand32, record->rand32, sizeof(record->rand32)); /* record->session_id_len = 0; - already is */ /* record->cipherid_len16_hi = 0; */ record->cipherid_len16_lo = 2 * 1; @@ -1225,7 +1175,7 @@ static void get_server_hello(tls_state_t *tls) } dbg("<< SERVER_HELLO\n"); - memcpy(tls->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32)); + memcpy(tls->hsd->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32)); } static void get_server_cert(tls_state_t *tls) @@ -1282,7 +1232,7 @@ static void send_client_key_exchange(tls_state_t *tls) rsa_premaster[0] = TLS_MAJ; rsa_premaster[1] = TLS_MIN; len = psRsaEncryptPub(/*pool:*/ NULL, - /* psRsaKey_t* */ &tls->server_rsa_pub_key, + /* psRsaKey_t* */ &tls->hsd->server_rsa_pub_key, rsa_premaster, /*inlen:*/ sizeof(rsa_premaster), record->key, sizeof(record->key), data_param_ignored @@ -1310,12 +1260,12 @@ static void send_client_key_exchange(tls_state_t *tls) // The master secret is always exactly 48 bytes in length. The length // of the premaster secret will vary depending on key exchange method. prf_hmac_sha256( - tls->master_secret, sizeof(tls->master_secret), + tls->hsd->master_secret, sizeof(tls->hsd->master_secret), rsa_premaster, sizeof(rsa_premaster), "master secret", - tls->client_and_server_rand32, sizeof(tls->client_and_server_rand32) + tls->hsd->client_and_server_rand32, sizeof(tls->hsd->client_and_server_rand32) ); - dump_hex("master secret:%s\n", tls->master_secret, sizeof(tls->master_secret)); + dump_hex("master secret:%s\n", tls->hsd->master_secret, sizeof(tls->hsd->master_secret)); // RFC 5246 // 6.3. Key Calculation @@ -1354,8 +1304,8 @@ static void send_client_key_exchange(tls_state_t *tls) uint8_t tmp64[64]; /* make "server_rand32 + client_rand32" */ - memcpy(&tmp64[0] , &tls->client_and_server_rand32[32], 32); - memcpy(&tmp64[32], &tls->client_and_server_rand32[0] , 32); + memcpy(&tmp64[0] , &tls->hsd->client_and_server_rand32[32], 32); + memcpy(&tmp64[32], &tls->hsd->client_and_server_rand32[0] , 32); prf_hmac_sha256( tls->client_write_MAC_key, 2 * (SHA256_OUTSIZE + AES256_KEYSIZE), @@ -1363,7 +1313,7 @@ static void send_client_key_exchange(tls_state_t *tls) // server_write_MAC_key[SHA256_OUTSIZE] // client_write_key[AES256_KEYSIZE] // server_write_key[AES256_KEYSIZE] - tls->master_secret, sizeof(tls->master_secret), + tls->hsd->master_secret, sizeof(tls->hsd->master_secret), "key expansion", tmp64, 64 ); @@ -1384,7 +1334,7 @@ static const uint8_t rec_CHANGE_CIPHER_SPEC[] = { static void send_change_cipher_spec(tls_state_t *tls) { dbg(">> CHANGE_CIPHER_SPEC\n"); - xwrite(tls->fd, rec_CHANGE_CIPHER_SPEC, sizeof(rec_CHANGE_CIPHER_SPEC)); + xwrite(tls->ofd, rec_CHANGE_CIPHER_SPEC, sizeof(rec_CHANGE_CIPHER_SPEC)); } // 7.4.9. Finished @@ -1436,13 +1386,13 @@ static void send_client_finished(tls_state_t *tls) fill_handshake_record_hdr(record, HANDSHAKE_FINISHED, sizeof(*record)); - sha256_peek(&tls->handshake_sha256_ctx, handshake_hash); + sha256_peek(&tls->hsd->handshake_sha256_ctx, handshake_hash); prf_hmac_sha256(record->prf_result, sizeof(record->prf_result), - tls->master_secret, sizeof(tls->master_secret), + tls->hsd->master_secret, sizeof(tls->hsd->master_secret), "client finished", handshake_hash, sizeof(handshake_hash) ); - dump_hex("from secret: %s\n", tls->master_secret, sizeof(tls->master_secret)); + dump_hex("from secret: %s\n", tls->hsd->master_secret, sizeof(tls->hsd->master_secret)); dump_hex("from labelSeed: %s", "client finished", sizeof("client finished")-1); dump_hex("%s\n", handshake_hash, sizeof(handshake_hash)); dump_hex("=> digest: %s\n", record->prf_result, sizeof(record->prf_result)); @@ -1451,7 +1401,7 @@ static void send_client_finished(tls_state_t *tls) xwrite_encrypted(tls, sizeof(*record), RECORD_TYPE_HANDSHAKE); } -static void tls_handshake(tls_state_t *tls, const char *sni) +void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) { // Client RFC 5246 Server // (*) - optional messages, not always sent @@ -1472,6 +1422,9 @@ static void tls_handshake(tls_state_t *tls, const char *sni) // Application Data <------> Application Data int len; + tls->hsd = xzalloc(sizeof(*tls->hsd)); + sha256_begin(&tls->hsd->handshake_sha256_ctx); + send_client_hello(tls, sni); get_server_hello(tls); @@ -1541,6 +1494,12 @@ static void tls_handshake(tls_state_t *tls, const char *sni) tls_error_die(tls); dbg("<< FINISHED\n"); /* application data can be sent/received */ + + /* free handshake data */ +// if (PARANOIA) +// memset(tls->hsd, 0, sizeof(*tls->hsd)); + free(tls->hsd); + tls->hsd = NULL; } static void tls_xwrite(tls_state_t *tls, int len) @@ -1557,35 +1516,17 @@ static void tls_xwrite(tls_state_t *tls, int len) // openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' // openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL // openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256 -// -// Talk to kernel.org: -// printf "GET / HTTP/1.1\r\nHost: kernel.org\r\n\r\n" | ./busybox tls kernel.org -int tls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int tls_main(int argc UNUSED_PARAM, char **argv) +void FAST_FUNC tls_run_copy_loop(tls_state_t *tls) { - tls_state_t *tls; fd_set readfds; int inbuf_size; const int INBUF_STEP = 4 * 1024; - int cfd; - - // INIT_G(); - // getopt32(argv, "myopts") - - if (!argv[1]) - bb_show_usage(); - - cfd = create_and_connect_stream_or_die(argv[1], 443); - - tls = new_tls_state(); - tls->fd = cfd; - tls_handshake(tls, argv[1]); - - /* Select loop copying stdin to cfd, and cfd to stdout */ +//TODO: convert to poll + /* Select loop copying stdin to ofd, and ifd to stdout */ FD_ZERO(&readfds); - FD_SET(cfd, &readfds); + FD_SET(tls->ifd, &readfds); FD_SET(STDIN_FILENO, &readfds); inbuf_size = INBUF_STEP; @@ -1594,7 +1535,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) int nread; testfds = readfds; - if (select(cfd + 1, &testfds, NULL, NULL, NULL) < 0) + if (select(tls->ifd + 1, &testfds, NULL, NULL, NULL) < 0) bb_perror_msg_and_die("select"); if (FD_ISSET(STDIN_FILENO, &testfds)) { @@ -1608,7 +1549,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) /* Close outgoing half-connection so they get EOF, * but leave incoming alone so we can see response */ - //shutdown(cfd, SHUT_WR); + //shutdown(tls->ofd, SHUT_WR); /* But TLS has no way to encode this, * doubt it's ok to do it "raw" */ @@ -1626,7 +1567,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) tls_xwrite(tls, nread); } } - if (FD_ISSET(cfd, &testfds)) { + if (FD_ISSET(tls->ifd, &testfds)) { dbg("NETWORK HAS DATA\n"); read_record: nread = tls_xread_record(tls); @@ -1634,7 +1575,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) /* TLS protocol has no real concept of one-sided shutdowns: * if we get "TLS EOF" from the peer, writes will fail too */ - //FD_CLR(cfd, &readfds); + //FD_CLR(tls->ifd, &readfds); //close(STDOUT_FILENO); //tls_free_inbuf(tls); /* mem usage optimization */ //continue; @@ -1650,6 +1591,4 @@ int tls_main(int argc UNUSED_PARAM, char **argv) goto read_record; } } - - return EXIT_SUCCESS; } diff --git a/networking/wget.c b/networking/wget.c index 58ead4c..a448acd 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -47,18 +47,26 @@ //config: FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option //config: will work in addition to -T. //config: +//config:config FEATURE_WGET_HTTPS +//config: bool "Support HTTPS using internal TLS code" +//config: default y +//config: depends on WGET +//config: select TLS +//config: help +//config: wget will use internal TLS code to connect to https:// URLs. +//config: Note: +//config: On NOMMU machines, ssl_helper applet should be available +//config: in the $PATH for this to work. Make sure to select that applet. +//config: //config:config FEATURE_WGET_OPENSSL //config: bool "Try to connect to HTTPS using openssl" //config: default y //config: depends on WGET //config: help -//config: Choose how wget establishes SSL connection for https:// URLs. -//config: -//config: Busybox itself contains no SSL code. wget will spawn -//config: a helper program to talk over HTTPS. +//config: Try to use openssl to handle HTTPS. //config: //config: OpenSSL has a simple SSL client for debug purposes. -//config: If you select "openssl" helper, wget will effectively run: +//config: If you select this option, wget will effectively run: //config: "openssl s_client -quiet -connect hostname:443 //config: -servername hostname 2>/dev/null" and pipe its data //config: through it. -servername is not used if hostname is numeric. @@ -71,24 +79,9 @@ //config: openssl is also a big binary, often dynamically linked //config: against ~15 libraries. //config: -//config:config FEATURE_WGET_SSL_HELPER -//config: bool "Try to connect to HTTPS using ssl_helper" -//config: default y -//config: depends on WGET -//config: help -//config: Choose how wget establishes SSL connection for https:// URLs. -//config: -//config: Busybox itself contains no SSL code. wget will spawn -//config: a helper program to talk over HTTPS. -//config: -//config: ssl_helper is a tool which can be built statically -//config: from busybox sources against a small embedded SSL library. -//config: Please see networking/ssl_helper/README. -//config: It does not require double host resolution and emits -//config: error messages to stderr. -//config: -//config: Precompiled static binary may be available at -//config: http://busybox.net/downloads/binaries/ +//config: If openssl can't be executed, internal TLS code will be used +//config: (if you enabled it); if openssl can be executed but fails later, +//config: wget can't detect this, and download will fail. //applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP)) @@ -137,7 +130,7 @@ #endif -#define SSL_SUPPORTED (ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER) +#define SSL_SUPPORTED (ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_HTTPS) struct host_info { char *allocated; @@ -657,7 +650,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) char *servername; int sp[2]; int pid; - IF_FEATURE_WGET_SSL_HELPER(volatile int child_failed = 0;) + IF_FEATURE_WGET_HTTPS(volatile int child_failed = 0;) if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0) /* Kernel can have AF_UNIX support disabled */ @@ -702,7 +695,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) BB_EXECVP(argv[0], argv); xmove_fd(3, 2); -# if ENABLE_FEATURE_WGET_SSL_HELPER +# if ENABLE_FEATURE_WGET_HTTPS child_failed = 1; xfunc_die(); # else @@ -715,7 +708,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) free(servername); free(allocated); close(sp[1]); -# if ENABLE_FEATURE_WGET_SSL_HELPER +# if ENABLE_FEATURE_WGET_HTTPS if (child_failed) { close(sp[0]); return -1; @@ -725,38 +718,51 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) } #endif -/* See networking/ssl_helper/README how to build one */ -#if ENABLE_FEATURE_WGET_SSL_HELPER -static void spawn_https_helper_small(int network_fd) +#if ENABLE_FEATURE_WGET_HTTPS +static void spawn_ssl_client(const char *host, int network_fd) { int sp[2]; int pid; + char *servername, *p; + + servername = xstrdup(host); + p = strrchr(servername, ':'); + if (p) *p = '\0'; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0) /* Kernel can have AF_UNIX support disabled */ bb_perror_msg_and_die("socketpair"); + fflush_all(); pid = BB_MMU ? xfork() : xvfork(); if (pid == 0) { /* Child */ - char *argv[3]; - close(sp[0]); xmove_fd(sp[1], 0); xdup2(0, 1); - xmove_fd(network_fd, 3); - /* - * A simple ssl/tls helper - */ - argv[0] = (char*)"ssl_helper"; - argv[1] = (char*)"-d3"; - argv[2] = NULL; - BB_EXECVP(argv[0], argv); - bb_perror_msg_and_die("can't execute '%s'", argv[0]); + if (BB_MMU) { + tls_state_t *tls = new_tls_state(); + tls->ifd = tls->ofd = network_fd; + tls_handshake(tls, servername); + tls_run_copy_loop(tls); + exit(0); + } else { + char *argv[5]; + xmove_fd(network_fd, 3); + argv[0] = (char*)"ssl_client"; + argv[1] = (char*)"-s3"; + //TODO: if (!is_ip_address(servername))... + argv[2] = (char*)"-n"; + argv[3] = servername; + argv[4] = NULL; + BB_EXECVP(argv[0], argv); + bb_perror_msg_and_die("can't execute '%s'", argv[0]); + } /* notreached */ } /* Parent */ + free(servername); close(sp[1]); xmove_fd(sp[0], network_fd); } @@ -1005,16 +1011,16 @@ static void download_one_url(const char *url) /* Open socket to http(s) server */ #if ENABLE_FEATURE_WGET_OPENSSL - /* openssl (and maybe ssl_helper) support is configured */ + /* openssl (and maybe internal TLS) support is configured */ if (target.protocol == P_HTTPS) { /* openssl-based helper * Inconvenient API since we can't give it an open fd */ int fd = spawn_https_helper_openssl(server.host, server.port); -# if ENABLE_FEATURE_WGET_SSL_HELPER - if (fd < 0) { /* no openssl? try ssl_helper */ +# if ENABLE_FEATURE_WGET_HTTPS + if (fd < 0) { /* no openssl? try internal */ sfp = open_socket(lsa); - spawn_https_helper_small(fileno(sfp)); + spawn_ssl_client(server.host, fileno(sfp)); goto socket_opened; } # else @@ -1027,11 +1033,11 @@ static void download_one_url(const char *url) } sfp = open_socket(lsa); socket_opened: -#elif ENABLE_FEATURE_WGET_SSL_HELPER - /* Only ssl_helper support is configured */ +#elif ENABLE_FEATURE_WGET_HTTPS + /* Only internal TLS support is configured */ sfp = open_socket(lsa); if (target.protocol == P_HTTPS) - spawn_https_helper_small(fileno(sfp)); + spawn_ssl_client(server.host, fileno(sfp)); #else /* ssl (https) support is not configured */ sfp = open_socket(lsa); |