diff options
-rw-r--r-- | include/libbb.h | 88 | ||||
-rw-r--r-- | networking/ssl_client.c | 55 | ||||
-rw-r--r-- | networking/tls.c | 151 | ||||
-rw-r--r-- | networking/wget.c | 102 |
4 files changed, 221 insertions, 175 deletions
diff --git a/include/libbb.h b/include/libbb.h index 87f89c76d..ba3b1479e 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -355,6 +355,27 @@ extern char *skip_dev_pfx(const char *tty_name) FAST_FUNC; | |||
355 | 355 | ||
356 | extern char *strrstr(const char *haystack, const char *needle) FAST_FUNC; | 356 | extern char *strrstr(const char *haystack, const char *needle) FAST_FUNC; |
357 | 357 | ||
358 | /* dmalloc will redefine these to it's own implementation. It is safe | ||
359 | * to have the prototypes here unconditionally. */ | ||
360 | void *malloc_or_warn(size_t size) FAST_FUNC RETURNS_MALLOC; | ||
361 | void *xmalloc(size_t size) FAST_FUNC RETURNS_MALLOC; | ||
362 | void *xzalloc(size_t size) FAST_FUNC RETURNS_MALLOC; | ||
363 | void *xrealloc(void *old, size_t size) FAST_FUNC; | ||
364 | /* After v = xrealloc_vector(v, SHIFT, idx) it's ok to use | ||
365 | * at least v[idx] and v[idx+1], for all idx values. | ||
366 | * SHIFT specifies how many new elements are added (1:2, 2:4, ..., 8:256...) | ||
367 | * when all elements are used up. New elements are zeroed out. | ||
368 | * xrealloc_vector(v, SHIFT, idx) *MUST* be called with consecutive IDXs - | ||
369 | * skipping an index is a bad bug - it may miss a realloc! | ||
370 | */ | ||
371 | #define xrealloc_vector(vector, shift, idx) \ | ||
372 | xrealloc_vector_helper((vector), (sizeof((vector)[0]) << 8) + (shift), (idx)) | ||
373 | void* xrealloc_vector_helper(void *vector, unsigned sizeof_and_shift, int idx) FAST_FUNC; | ||
374 | char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC; | ||
375 | char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC; | ||
376 | void *xmemdup(const void *s, int n) FAST_FUNC RETURNS_MALLOC; | ||
377 | |||
378 | |||
358 | //TODO: supply a pointer to char[11] buffer (avoid statics)? | 379 | //TODO: supply a pointer to char[11] buffer (avoid statics)? |
359 | extern const char *bb_mode_string(mode_t mode) FAST_FUNC; | 380 | extern const char *bb_mode_string(mode_t mode) FAST_FUNC; |
360 | extern int is_directory(const char *name, int followLinks) FAST_FUNC; | 381 | extern int is_directory(const char *name, int followLinks) FAST_FUNC; |
@@ -692,6 +713,52 @@ struct hostent *xgethostbyname(const char *name) FAST_FUNC; | |||
692 | // Also mount.c and inetd.c are using gethostbyname(), | 713 | // Also mount.c and inetd.c are using gethostbyname(), |
693 | // + inet_common.c has additional IPv4-only stuff | 714 | // + inet_common.c has additional IPv4-only stuff |
694 | 715 | ||
716 | #define SHA256_INSIZE 64 | ||
717 | #define SHA256_OUTSIZE 32 | ||
718 | #define AES_BLOCKSIZE 16 | ||
719 | #define AES128_KEYSIZE 16 | ||
720 | #define AES256_KEYSIZE 32 | ||
721 | struct tls_handshake_data; /* opaque */ | ||
722 | typedef struct tls_state { | ||
723 | int ofd; | ||
724 | int ifd; | ||
725 | |||
726 | int min_encrypted_len_on_read; | ||
727 | uint8_t encrypt_on_write; | ||
728 | |||
729 | uint8_t *outbuf; | ||
730 | int outbuf_size; | ||
731 | |||
732 | int inbuf_size; | ||
733 | int ofs_to_buffered; | ||
734 | int buffered_size; | ||
735 | uint8_t *inbuf; | ||
736 | |||
737 | struct tls_handshake_data *hsd; | ||
738 | |||
739 | // RFC 5246 | ||
740 | // sequence number | ||
741 | // Each connection state contains a sequence number, which is | ||
742 | // maintained separately for read and write states. The sequence | ||
743 | // number MUST be set to zero whenever a connection state is made the | ||
744 | // active state. Sequence numbers are of type uint64 and may not | ||
745 | // exceed 2^64-1. | ||
746 | /*uint64_t read_seq64_be;*/ | ||
747 | uint64_t write_seq64_be; | ||
748 | |||
749 | uint8_t client_write_MAC_key[SHA256_OUTSIZE]; | ||
750 | uint8_t server_write_MAC_key[SHA256_OUTSIZE]; | ||
751 | uint8_t client_write_key[AES256_KEYSIZE]; | ||
752 | uint8_t server_write_key[AES256_KEYSIZE]; | ||
753 | } tls_state_t; | ||
754 | |||
755 | static inline tls_state_t *new_tls_state(void) | ||
756 | { | ||
757 | tls_state_t *tls = xzalloc(sizeof(*tls)); | ||
758 | return tls; | ||
759 | } | ||
760 | void tls_handshake(tls_state_t *tls, const char *sni) FAST_FUNC; | ||
761 | void tls_run_copy_loop(tls_state_t *tls) FAST_FUNC; | ||
695 | 762 | ||
696 | void socket_want_pktinfo(int fd) FAST_FUNC; | 763 | void socket_want_pktinfo(int fd) FAST_FUNC; |
697 | ssize_t send_to_from(int fd, void *buf, size_t len, int flags, | 764 | ssize_t send_to_from(int fd, void *buf, size_t len, int flags, |
@@ -705,9 +772,6 @@ ssize_t recv_from_to(int fd, void *buf, size_t len, int flags, | |||
705 | 772 | ||
706 | uint16_t inet_cksum(uint16_t *addr, int len) FAST_FUNC; | 773 | uint16_t inet_cksum(uint16_t *addr, int len) FAST_FUNC; |
707 | 774 | ||
708 | char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC; | ||
709 | char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC; | ||
710 | void *xmemdup(const void *s, int n) FAST_FUNC RETURNS_MALLOC; | ||
711 | void overlapping_strcpy(char *dst, const char *src) FAST_FUNC; | 775 | void overlapping_strcpy(char *dst, const char *src) FAST_FUNC; |
712 | char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC; | 776 | char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC; |
713 | char *strncpy_IFNAMSIZ(char *dst, const char *src) FAST_FUNC; | 777 | char *strncpy_IFNAMSIZ(char *dst, const char *src) FAST_FUNC; |
@@ -753,24 +817,6 @@ enum { | |||
753 | }; | 817 | }; |
754 | void visible(unsigned ch, char *buf, int flags) FAST_FUNC; | 818 | void visible(unsigned ch, char *buf, int flags) FAST_FUNC; |
755 | 819 | ||
756 | /* dmalloc will redefine these to it's own implementation. It is safe | ||
757 | * to have the prototypes here unconditionally. */ | ||
758 | void *malloc_or_warn(size_t size) FAST_FUNC RETURNS_MALLOC; | ||
759 | void *xmalloc(size_t size) FAST_FUNC RETURNS_MALLOC; | ||
760 | void *xzalloc(size_t size) FAST_FUNC RETURNS_MALLOC; | ||
761 | void *xrealloc(void *old, size_t size) FAST_FUNC; | ||
762 | /* After v = xrealloc_vector(v, SHIFT, idx) it's ok to use | ||
763 | * at least v[idx] and v[idx+1], for all idx values. | ||
764 | * SHIFT specifies how many new elements are added (1:2, 2:4, ..., 8:256...) | ||
765 | * when all elements are used up. New elements are zeroed out. | ||
766 | * xrealloc_vector(v, SHIFT, idx) *MUST* be called with consecutive IDXs - | ||
767 | * skipping an index is a bad bug - it may miss a realloc! | ||
768 | */ | ||
769 | #define xrealloc_vector(vector, shift, idx) \ | ||
770 | xrealloc_vector_helper((vector), (sizeof((vector)[0]) << 8) + (shift), (idx)) | ||
771 | void* xrealloc_vector_helper(void *vector, unsigned sizeof_and_shift, int idx) FAST_FUNC; | ||
772 | |||
773 | |||
774 | extern ssize_t safe_read(int fd, void *buf, size_t count) FAST_FUNC; | 820 | extern ssize_t safe_read(int fd, void *buf, size_t count) FAST_FUNC; |
775 | extern ssize_t nonblock_immune_read(int fd, void *buf, size_t count) FAST_FUNC; | 821 | extern ssize_t nonblock_immune_read(int fd, void *buf, size_t count) FAST_FUNC; |
776 | // NB: will return short read on error, not -1, | 822 | // NB: will return short read on error, not -1, |
diff --git a/networking/ssl_client.c b/networking/ssl_client.c new file mode 100644 index 000000000..cfeae1587 --- /dev/null +++ b/networking/ssl_client.c | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Denys Vlasenko | ||
3 | * | ||
4 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
5 | */ | ||
6 | //config:config SSL_CLIENT | ||
7 | //config: bool "ssl_client" | ||
8 | //config: default y | ||
9 | //config: select TLS | ||
10 | //config: help | ||
11 | //config: This tool pipes data to/from a socket, TLS-encrypting it. | ||
12 | |||
13 | //applet:IF_SSL_CLIENT(APPLET(ssl_client, BB_DIR_USR_BIN, BB_SUID_DROP)) | ||
14 | |||
15 | //kbuild:lib-$(CONFIG_SSL_CLIENT) += ssl_client.o | ||
16 | |||
17 | //usage:#define ssl_client_trivial_usage | ||
18 | //usage: "-s FD [-r FD] [-n SNI]" | ||
19 | //usage:#define ssl_client_full_usage "" | ||
20 | |||
21 | #include "libbb.h" | ||
22 | |||
23 | int ssl_client_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
24 | int ssl_client_main(int argc UNUSED_PARAM, char **argv) | ||
25 | { | ||
26 | tls_state_t *tls; | ||
27 | const char *sni = NULL; | ||
28 | int opt; | ||
29 | |||
30 | // INIT_G(); | ||
31 | |||
32 | tls = new_tls_state(); | ||
33 | opt = getopt32(argv, "s:#r:#n:", &tls->ofd, &tls->ifd, &sni); | ||
34 | if (!(opt & 2)) { | ||
35 | /* -r N defaults to -s N */ | ||
36 | tls->ifd = tls->ofd; | ||
37 | } | ||
38 | |||
39 | if (!(opt & 3)) { | ||
40 | if (!argv[1]) | ||
41 | bb_show_usage(); | ||
42 | /* Undocumented debug feature: without -s and -r, takes HOST arg and connects to it */ | ||
43 | // | ||
44 | // Talk to kernel.org: | ||
45 | // printf "GET / HTTP/1.1\r\nHost: kernel.org\r\n\r\n" | ./busybox ssl_client kernel.org | ||
46 | if (!sni) | ||
47 | sni = argv[1]; | ||
48 | tls->ifd = tls->ofd = create_and_connect_stream_or_die(argv[1], 443); | ||
49 | } | ||
50 | |||
51 | tls_handshake(tls, sni); | ||
52 | tls_run_copy_loop(tls); | ||
53 | |||
54 | return EXIT_SUCCESS; | ||
55 | } | ||
diff --git a/networking/tls.c b/networking/tls.c index b111e4bb4..29cc5b9f3 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -4,11 +4,9 @@ | |||
4 | * Licensed under GPLv2, see file LICENSE in this source tree. | 4 | * Licensed under GPLv2, see file LICENSE in this source tree. |
5 | */ | 5 | */ |
6 | //config:config TLS | 6 | //config:config TLS |
7 | //config: bool "tls (debugging)" | 7 | //config: bool #No description makes it a hidden option |
8 | //config: default n | 8 | //config: default n |
9 | 9 | ||
10 | //applet:IF_TLS(APPLET(tls, BB_DIR_USR_BIN, BB_SUID_DROP)) | ||
11 | |||
12 | //kbuild:lib-$(CONFIG_TLS) += tls.o | 10 | //kbuild:lib-$(CONFIG_TLS) += tls.o |
13 | //kbuild:lib-$(CONFIG_TLS) += tls_pstm.o | 11 | //kbuild:lib-$(CONFIG_TLS) += tls_pstm.o |
14 | //kbuild:lib-$(CONFIG_TLS) += tls_pstm_montgomery_reduce.o | 12 | //kbuild:lib-$(CONFIG_TLS) += tls_pstm_montgomery_reduce.o |
@@ -18,12 +16,7 @@ | |||
18 | //kbuild:lib-$(CONFIG_TLS) += tls_aes.o | 16 | //kbuild:lib-$(CONFIG_TLS) += tls_aes.o |
19 | ////kbuild:lib-$(CONFIG_TLS) += tls_aes_gcm.o | 17 | ////kbuild:lib-$(CONFIG_TLS) += tls_aes_gcm.o |
20 | 18 | ||
21 | //usage:#define tls_trivial_usage | ||
22 | //usage: "HOST[:PORT]" | ||
23 | //usage:#define tls_full_usage "\n\n" | ||
24 | |||
25 | #include "tls.h" | 19 | #include "tls.h" |
26 | //#include "common_bufsiz.h" | ||
27 | 20 | ||
28 | #define TLS_DEBUG 1 | 21 | #define TLS_DEBUG 1 |
29 | #define TLS_DEBUG_HASH 0 | 22 | #define TLS_DEBUG_HASH 0 |
@@ -165,13 +158,6 @@ | |||
165 | #define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE | 158 | #define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE |
166 | 159 | ||
167 | enum { | 160 | enum { |
168 | SHA256_INSIZE = 64, | ||
169 | SHA256_OUTSIZE = 32, | ||
170 | |||
171 | AES_BLOCKSIZE = 16, | ||
172 | AES128_KEYSIZE = 16, | ||
173 | AES256_KEYSIZE = 32, | ||
174 | |||
175 | RSA_PREMASTER_SIZE = 48, | 161 | RSA_PREMASTER_SIZE = 48, |
176 | 162 | ||
177 | RECHDR_LEN = 5, | 163 | RECHDR_LEN = 5, |
@@ -225,20 +211,7 @@ struct record_hdr { | |||
225 | uint8_t len16_hi, len16_lo; | 211 | uint8_t len16_hi, len16_lo; |
226 | }; | 212 | }; |
227 | 213 | ||
228 | typedef struct tls_state { | 214 | struct tls_handshake_data { |
229 | int fd; | ||
230 | |||
231 | int min_encrypted_len_on_read; | ||
232 | uint8_t encrypt_on_write; | ||
233 | |||
234 | uint8_t *outbuf; | ||
235 | int outbuf_size; | ||
236 | |||
237 | int inbuf_size; | ||
238 | int ofs_to_buffered; | ||
239 | int buffered_size; | ||
240 | uint8_t *inbuf; | ||
241 | |||
242 | //TODO: store just the DER key here, parse/use/delete it when sending client key | 215 | //TODO: store just the DER key here, parse/use/delete it when sending client key |
243 | //this way it will stay key type agnostic here. | 216 | //this way it will stay key type agnostic here. |
244 | psRsaKey_t server_rsa_pub_key; | 217 | psRsaKey_t server_rsa_pub_key; |
@@ -247,22 +220,7 @@ typedef struct tls_state { | |||
247 | // these two are unused after finished messages are exchanged: | 220 | // these two are unused after finished messages are exchanged: |
248 | sha256_ctx_t handshake_sha256_ctx; | 221 | sha256_ctx_t handshake_sha256_ctx; |
249 | uint8_t master_secret[48]; | 222 | uint8_t master_secret[48]; |
250 | 223 | }; | |
251 | // RFC 5246 | ||
252 | // sequence number | ||
253 | // Each connection state contains a sequence number, which is | ||
254 | // maintained separately for read and write states. The sequence | ||
255 | // number MUST be set to zero whenever a connection state is made the | ||
256 | // active state. Sequence numbers are of type uint64 and may not | ||
257 | // exceed 2^64-1. | ||
258 | /*uint64_t read_seq64_be;*/ | ||
259 | uint64_t write_seq64_be; | ||
260 | |||
261 | uint8_t client_write_MAC_key[SHA256_OUTSIZE]; | ||
262 | uint8_t server_write_MAC_key[SHA256_OUTSIZE]; | ||
263 | uint8_t client_write_key[AES256_KEYSIZE]; | ||
264 | uint8_t server_write_key[AES256_KEYSIZE]; | ||
265 | } tls_state_t; | ||
266 | 224 | ||
267 | 225 | ||
268 | static unsigned get24be(const uint8_t *p) | 226 | static unsigned get24be(const uint8_t *p) |
@@ -487,14 +445,6 @@ static void prf_hmac_sha256( | |||
487 | #undef SEED | 445 | #undef SEED |
488 | } | 446 | } |
489 | 447 | ||
490 | static tls_state_t *new_tls_state(void) | ||
491 | { | ||
492 | tls_state_t *tls = xzalloc(sizeof(*tls)); | ||
493 | tls->fd = -1; | ||
494 | sha256_begin(&tls->handshake_sha256_ctx); | ||
495 | return tls; | ||
496 | } | ||
497 | |||
498 | static void tls_error_die(tls_state_t *tls) | 448 | static void tls_error_die(tls_state_t *tls) |
499 | { | 449 | { |
500 | dump_tls_record(tls->inbuf, tls->ofs_to_buffered + tls->buffered_size); | 450 | 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) | |||
597 | xhdr->len16_hi = size >> 8; | 547 | xhdr->len16_hi = size >> 8; |
598 | xhdr->len16_lo = size & 0xff; | 548 | xhdr->len16_lo = size & 0xff; |
599 | dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); | 549 | dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); |
600 | xwrite(tls->fd, xhdr, RECHDR_LEN + size); | 550 | xwrite(tls->ofd, xhdr, RECHDR_LEN + size); |
601 | dbg("wrote %u bytes (NULL crypt, SHA256 hash)\n", size); | 551 | dbg("wrote %u bytes (NULL crypt, SHA256 hash)\n", size); |
602 | return; | 552 | return; |
603 | } | 553 | } |
@@ -681,7 +631,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) | |||
681 | xhdr->len16_hi = size >> 8; | 631 | xhdr->len16_hi = size >> 8; |
682 | xhdr->len16_lo = size & 0xff; | 632 | xhdr->len16_lo = size & 0xff; |
683 | dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); | 633 | dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); |
684 | xwrite(tls->fd, xhdr, RECHDR_LEN + size); | 634 | xwrite(tls->ofd, xhdr, RECHDR_LEN + size); |
685 | dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); | 635 | dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); |
686 | } | 636 | } |
687 | 637 | ||
@@ -697,10 +647,10 @@ static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) | |||
697 | xhdr->len16_hi = size >> 8; | 647 | xhdr->len16_hi = size >> 8; |
698 | xhdr->len16_lo = size & 0xff; | 648 | xhdr->len16_lo = size & 0xff; |
699 | dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); | 649 | dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); |
700 | xwrite(tls->fd, xhdr, RECHDR_LEN + size); | 650 | xwrite(tls->ofd, xhdr, RECHDR_LEN + size); |
701 | dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); | 651 | dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); |
702 | /* Handshake hash does not include record headers */ | 652 | /* Handshake hash does not include record headers */ |
703 | sha256_hash_dbg(">> sha256:%s", &tls->handshake_sha256_ctx, buf, size); | 653 | sha256_hash_dbg(">> sha256:%s", &tls->hsd->handshake_sha256_ctx, buf, size); |
704 | return; | 654 | return; |
705 | } | 655 | } |
706 | xwrite_encrypted(tls, size, RECORD_TYPE_HANDSHAKE); | 656 | xwrite_encrypted(tls, size, RECORD_TYPE_HANDSHAKE); |
@@ -769,7 +719,7 @@ static int tls_xread_record(tls_state_t *tls) | |||
769 | rem = tls->inbuf_size - total; | 719 | rem = tls->inbuf_size - total; |
770 | tls->inbuf = xrealloc(tls->inbuf, tls->inbuf_size); | 720 | tls->inbuf = xrealloc(tls->inbuf, tls->inbuf_size); |
771 | } | 721 | } |
772 | sz = safe_read(tls->fd, tls->inbuf + total, rem); | 722 | sz = safe_read(tls->ifd, tls->inbuf + total, rem); |
773 | if (sz <= 0) { | 723 | if (sz <= 0) { |
774 | if (sz == 0 && total == 0) { | 724 | if (sz == 0 && total == 0) { |
775 | /* "Abrupt" EOF, no TLS shutdown (seen from kernel.org) */ | 725 | /* "Abrupt" EOF, no TLS shutdown (seen from kernel.org) */ |
@@ -848,7 +798,7 @@ static int tls_xread_record(tls_state_t *tls) | |||
848 | * in our FINISHED record must include data of incoming packets too! | 798 | * in our FINISHED record must include data of incoming packets too! |
849 | */ | 799 | */ |
850 | if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE) { | 800 | if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE) { |
851 | sha256_hash_dbg("<< sha256:%s", &tls->handshake_sha256_ctx, tls->inbuf + RECHDR_LEN, sz); | 801 | sha256_hash_dbg("<< sha256:%s", &tls->hsd->handshake_sha256_ctx, tls->inbuf + RECHDR_LEN, sz); |
852 | } | 802 | } |
853 | end: | 803 | end: |
854 | dbg("got block len:%u\n", sz); | 804 | 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) | |||
1059 | xfunc_die(); | 1009 | xfunc_die(); |
1060 | der++; | 1010 | der++; |
1061 | der = enter_der_item(der, &end); /* enter SEQ */ | 1011 | der = enter_der_item(der, &end); /* enter SEQ */ |
1062 | /* memset(tls->server_rsa_pub_key, 0, sizeof(tls->server_rsa_pub_key)); - already is */ | 1012 | /* memset(tls->hsd->server_rsa_pub_key, 0, sizeof(tls->hsd->server_rsa_pub_key)); - already is */ |
1063 | der_binary_to_pstm(&tls->server_rsa_pub_key.N, der, end); /* modulus */ | 1013 | der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.N, der, end); /* modulus */ |
1064 | der = skip_der_item(der, end); | 1014 | der = skip_der_item(der, end); |
1065 | der_binary_to_pstm(&tls->server_rsa_pub_key.e, der, end); /* exponent */ | 1015 | der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.e, der, end); /* exponent */ |
1066 | tls->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->server_rsa_pub_key.N); | 1016 | tls->hsd->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->hsd->server_rsa_pub_key.N); |
1067 | dbg("server_rsa_pub_key.size:%d\n", tls->server_rsa_pub_key.size); | 1017 | dbg("server_rsa_pub_key.size:%d\n", tls->hsd->server_rsa_pub_key.size); |
1068 | } | 1018 | } |
1069 | 1019 | ||
1070 | /* | 1020 | /* |
@@ -1140,7 +1090,7 @@ static void send_client_hello(tls_state_t *tls, const char *sni) | |||
1140 | tls_get_random(record->rand32, sizeof(record->rand32)); | 1090 | tls_get_random(record->rand32, sizeof(record->rand32)); |
1141 | if (TLS_DEBUG_FIXED_SECRETS) | 1091 | if (TLS_DEBUG_FIXED_SECRETS) |
1142 | memset(record->rand32, 0x11, sizeof(record->rand32)); | 1092 | memset(record->rand32, 0x11, sizeof(record->rand32)); |
1143 | memcpy(tls->client_and_server_rand32, record->rand32, sizeof(record->rand32)); | 1093 | memcpy(tls->hsd->client_and_server_rand32, record->rand32, sizeof(record->rand32)); |
1144 | /* record->session_id_len = 0; - already is */ | 1094 | /* record->session_id_len = 0; - already is */ |
1145 | /* record->cipherid_len16_hi = 0; */ | 1095 | /* record->cipherid_len16_hi = 0; */ |
1146 | record->cipherid_len16_lo = 2 * 1; | 1096 | record->cipherid_len16_lo = 2 * 1; |
@@ -1225,7 +1175,7 @@ static void get_server_hello(tls_state_t *tls) | |||
1225 | } | 1175 | } |
1226 | 1176 | ||
1227 | dbg("<< SERVER_HELLO\n"); | 1177 | dbg("<< SERVER_HELLO\n"); |
1228 | memcpy(tls->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32)); | 1178 | memcpy(tls->hsd->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32)); |
1229 | } | 1179 | } |
1230 | 1180 | ||
1231 | static void get_server_cert(tls_state_t *tls) | 1181 | static void get_server_cert(tls_state_t *tls) |
@@ -1282,7 +1232,7 @@ static void send_client_key_exchange(tls_state_t *tls) | |||
1282 | rsa_premaster[0] = TLS_MAJ; | 1232 | rsa_premaster[0] = TLS_MAJ; |
1283 | rsa_premaster[1] = TLS_MIN; | 1233 | rsa_premaster[1] = TLS_MIN; |
1284 | len = psRsaEncryptPub(/*pool:*/ NULL, | 1234 | len = psRsaEncryptPub(/*pool:*/ NULL, |
1285 | /* psRsaKey_t* */ &tls->server_rsa_pub_key, | 1235 | /* psRsaKey_t* */ &tls->hsd->server_rsa_pub_key, |
1286 | rsa_premaster, /*inlen:*/ sizeof(rsa_premaster), | 1236 | rsa_premaster, /*inlen:*/ sizeof(rsa_premaster), |
1287 | record->key, sizeof(record->key), | 1237 | record->key, sizeof(record->key), |
1288 | data_param_ignored | 1238 | data_param_ignored |
@@ -1310,12 +1260,12 @@ static void send_client_key_exchange(tls_state_t *tls) | |||
1310 | // The master secret is always exactly 48 bytes in length. The length | 1260 | // The master secret is always exactly 48 bytes in length. The length |
1311 | // of the premaster secret will vary depending on key exchange method. | 1261 | // of the premaster secret will vary depending on key exchange method. |
1312 | prf_hmac_sha256( | 1262 | prf_hmac_sha256( |
1313 | tls->master_secret, sizeof(tls->master_secret), | 1263 | tls->hsd->master_secret, sizeof(tls->hsd->master_secret), |
1314 | rsa_premaster, sizeof(rsa_premaster), | 1264 | rsa_premaster, sizeof(rsa_premaster), |
1315 | "master secret", | 1265 | "master secret", |
1316 | tls->client_and_server_rand32, sizeof(tls->client_and_server_rand32) | 1266 | tls->hsd->client_and_server_rand32, sizeof(tls->hsd->client_and_server_rand32) |
1317 | ); | 1267 | ); |
1318 | dump_hex("master secret:%s\n", tls->master_secret, sizeof(tls->master_secret)); | 1268 | dump_hex("master secret:%s\n", tls->hsd->master_secret, sizeof(tls->hsd->master_secret)); |
1319 | 1269 | ||
1320 | // RFC 5246 | 1270 | // RFC 5246 |
1321 | // 6.3. Key Calculation | 1271 | // 6.3. Key Calculation |
@@ -1354,8 +1304,8 @@ static void send_client_key_exchange(tls_state_t *tls) | |||
1354 | uint8_t tmp64[64]; | 1304 | uint8_t tmp64[64]; |
1355 | 1305 | ||
1356 | /* make "server_rand32 + client_rand32" */ | 1306 | /* make "server_rand32 + client_rand32" */ |
1357 | memcpy(&tmp64[0] , &tls->client_and_server_rand32[32], 32); | 1307 | memcpy(&tmp64[0] , &tls->hsd->client_and_server_rand32[32], 32); |
1358 | memcpy(&tmp64[32], &tls->client_and_server_rand32[0] , 32); | 1308 | memcpy(&tmp64[32], &tls->hsd->client_and_server_rand32[0] , 32); |
1359 | 1309 | ||
1360 | prf_hmac_sha256( | 1310 | prf_hmac_sha256( |
1361 | tls->client_write_MAC_key, 2 * (SHA256_OUTSIZE + AES256_KEYSIZE), | 1311 | tls->client_write_MAC_key, 2 * (SHA256_OUTSIZE + AES256_KEYSIZE), |
@@ -1363,7 +1313,7 @@ static void send_client_key_exchange(tls_state_t *tls) | |||
1363 | // server_write_MAC_key[SHA256_OUTSIZE] | 1313 | // server_write_MAC_key[SHA256_OUTSIZE] |
1364 | // client_write_key[AES256_KEYSIZE] | 1314 | // client_write_key[AES256_KEYSIZE] |
1365 | // server_write_key[AES256_KEYSIZE] | 1315 | // server_write_key[AES256_KEYSIZE] |
1366 | tls->master_secret, sizeof(tls->master_secret), | 1316 | tls->hsd->master_secret, sizeof(tls->hsd->master_secret), |
1367 | "key expansion", | 1317 | "key expansion", |
1368 | tmp64, 64 | 1318 | tmp64, 64 |
1369 | ); | 1319 | ); |
@@ -1384,7 +1334,7 @@ static const uint8_t rec_CHANGE_CIPHER_SPEC[] = { | |||
1384 | static void send_change_cipher_spec(tls_state_t *tls) | 1334 | static void send_change_cipher_spec(tls_state_t *tls) |
1385 | { | 1335 | { |
1386 | dbg(">> CHANGE_CIPHER_SPEC\n"); | 1336 | dbg(">> CHANGE_CIPHER_SPEC\n"); |
1387 | xwrite(tls->fd, rec_CHANGE_CIPHER_SPEC, sizeof(rec_CHANGE_CIPHER_SPEC)); | 1337 | xwrite(tls->ofd, rec_CHANGE_CIPHER_SPEC, sizeof(rec_CHANGE_CIPHER_SPEC)); |
1388 | } | 1338 | } |
1389 | 1339 | ||
1390 | // 7.4.9. Finished | 1340 | // 7.4.9. Finished |
@@ -1436,13 +1386,13 @@ static void send_client_finished(tls_state_t *tls) | |||
1436 | 1386 | ||
1437 | fill_handshake_record_hdr(record, HANDSHAKE_FINISHED, sizeof(*record)); | 1387 | fill_handshake_record_hdr(record, HANDSHAKE_FINISHED, sizeof(*record)); |
1438 | 1388 | ||
1439 | sha256_peek(&tls->handshake_sha256_ctx, handshake_hash); | 1389 | sha256_peek(&tls->hsd->handshake_sha256_ctx, handshake_hash); |
1440 | prf_hmac_sha256(record->prf_result, sizeof(record->prf_result), | 1390 | prf_hmac_sha256(record->prf_result, sizeof(record->prf_result), |
1441 | tls->master_secret, sizeof(tls->master_secret), | 1391 | tls->hsd->master_secret, sizeof(tls->hsd->master_secret), |
1442 | "client finished", | 1392 | "client finished", |
1443 | handshake_hash, sizeof(handshake_hash) | 1393 | handshake_hash, sizeof(handshake_hash) |
1444 | ); | 1394 | ); |
1445 | dump_hex("from secret: %s\n", tls->master_secret, sizeof(tls->master_secret)); | 1395 | dump_hex("from secret: %s\n", tls->hsd->master_secret, sizeof(tls->hsd->master_secret)); |
1446 | dump_hex("from labelSeed: %s", "client finished", sizeof("client finished")-1); | 1396 | dump_hex("from labelSeed: %s", "client finished", sizeof("client finished")-1); |
1447 | dump_hex("%s\n", handshake_hash, sizeof(handshake_hash)); | 1397 | dump_hex("%s\n", handshake_hash, sizeof(handshake_hash)); |
1448 | dump_hex("=> digest: %s\n", record->prf_result, sizeof(record->prf_result)); | 1398 | 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) | |||
1451 | xwrite_encrypted(tls, sizeof(*record), RECORD_TYPE_HANDSHAKE); | 1401 | xwrite_encrypted(tls, sizeof(*record), RECORD_TYPE_HANDSHAKE); |
1452 | } | 1402 | } |
1453 | 1403 | ||
1454 | static void tls_handshake(tls_state_t *tls, const char *sni) | 1404 | void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) |
1455 | { | 1405 | { |
1456 | // Client RFC 5246 Server | 1406 | // Client RFC 5246 Server |
1457 | // (*) - optional messages, not always sent | 1407 | // (*) - optional messages, not always sent |
@@ -1472,6 +1422,9 @@ static void tls_handshake(tls_state_t *tls, const char *sni) | |||
1472 | // Application Data <------> Application Data | 1422 | // Application Data <------> Application Data |
1473 | int len; | 1423 | int len; |
1474 | 1424 | ||
1425 | tls->hsd = xzalloc(sizeof(*tls->hsd)); | ||
1426 | sha256_begin(&tls->hsd->handshake_sha256_ctx); | ||
1427 | |||
1475 | send_client_hello(tls, sni); | 1428 | send_client_hello(tls, sni); |
1476 | get_server_hello(tls); | 1429 | get_server_hello(tls); |
1477 | 1430 | ||
@@ -1541,6 +1494,12 @@ static void tls_handshake(tls_state_t *tls, const char *sni) | |||
1541 | tls_error_die(tls); | 1494 | tls_error_die(tls); |
1542 | dbg("<< FINISHED\n"); | 1495 | dbg("<< FINISHED\n"); |
1543 | /* application data can be sent/received */ | 1496 | /* application data can be sent/received */ |
1497 | |||
1498 | /* free handshake data */ | ||
1499 | // if (PARANOIA) | ||
1500 | // memset(tls->hsd, 0, sizeof(*tls->hsd)); | ||
1501 | free(tls->hsd); | ||
1502 | tls->hsd = NULL; | ||
1544 | } | 1503 | } |
1545 | 1504 | ||
1546 | static void tls_xwrite(tls_state_t *tls, int len) | 1505 | static void tls_xwrite(tls_state_t *tls, int len) |
@@ -1557,35 +1516,17 @@ static void tls_xwrite(tls_state_t *tls, int len) | |||
1557 | // openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' | 1516 | // openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' |
1558 | // openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL | 1517 | // openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL |
1559 | // openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256 | 1518 | // openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256 |
1560 | // | ||
1561 | // Talk to kernel.org: | ||
1562 | // printf "GET / HTTP/1.1\r\nHost: kernel.org\r\n\r\n" | ./busybox tls kernel.org | ||
1563 | 1519 | ||
1564 | int tls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1520 | void FAST_FUNC tls_run_copy_loop(tls_state_t *tls) |
1565 | int tls_main(int argc UNUSED_PARAM, char **argv) | ||
1566 | { | 1521 | { |
1567 | tls_state_t *tls; | ||
1568 | fd_set readfds; | 1522 | fd_set readfds; |
1569 | int inbuf_size; | 1523 | int inbuf_size; |
1570 | const int INBUF_STEP = 4 * 1024; | 1524 | const int INBUF_STEP = 4 * 1024; |
1571 | int cfd; | ||
1572 | |||
1573 | 1525 | ||
1574 | // INIT_G(); | 1526 | //TODO: convert to poll |
1575 | // getopt32(argv, "myopts") | 1527 | /* Select loop copying stdin to ofd, and ifd to stdout */ |
1576 | |||
1577 | if (!argv[1]) | ||
1578 | bb_show_usage(); | ||
1579 | |||
1580 | cfd = create_and_connect_stream_or_die(argv[1], 443); | ||
1581 | |||
1582 | tls = new_tls_state(); | ||
1583 | tls->fd = cfd; | ||
1584 | tls_handshake(tls, argv[1]); | ||
1585 | |||
1586 | /* Select loop copying stdin to cfd, and cfd to stdout */ | ||
1587 | FD_ZERO(&readfds); | 1528 | FD_ZERO(&readfds); |
1588 | FD_SET(cfd, &readfds); | 1529 | FD_SET(tls->ifd, &readfds); |
1589 | FD_SET(STDIN_FILENO, &readfds); | 1530 | FD_SET(STDIN_FILENO, &readfds); |
1590 | 1531 | ||
1591 | inbuf_size = INBUF_STEP; | 1532 | inbuf_size = INBUF_STEP; |
@@ -1594,7 +1535,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) | |||
1594 | int nread; | 1535 | int nread; |
1595 | 1536 | ||
1596 | testfds = readfds; | 1537 | testfds = readfds; |
1597 | if (select(cfd + 1, &testfds, NULL, NULL, NULL) < 0) | 1538 | if (select(tls->ifd + 1, &testfds, NULL, NULL, NULL) < 0) |
1598 | bb_perror_msg_and_die("select"); | 1539 | bb_perror_msg_and_die("select"); |
1599 | 1540 | ||
1600 | if (FD_ISSET(STDIN_FILENO, &testfds)) { | 1541 | if (FD_ISSET(STDIN_FILENO, &testfds)) { |
@@ -1608,7 +1549,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) | |||
1608 | /* Close outgoing half-connection so they get EOF, | 1549 | /* Close outgoing half-connection so they get EOF, |
1609 | * but leave incoming alone so we can see response | 1550 | * but leave incoming alone so we can see response |
1610 | */ | 1551 | */ |
1611 | //shutdown(cfd, SHUT_WR); | 1552 | //shutdown(tls->ofd, SHUT_WR); |
1612 | /* But TLS has no way to encode this, | 1553 | /* But TLS has no way to encode this, |
1613 | * doubt it's ok to do it "raw" | 1554 | * doubt it's ok to do it "raw" |
1614 | */ | 1555 | */ |
@@ -1626,7 +1567,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) | |||
1626 | tls_xwrite(tls, nread); | 1567 | tls_xwrite(tls, nread); |
1627 | } | 1568 | } |
1628 | } | 1569 | } |
1629 | if (FD_ISSET(cfd, &testfds)) { | 1570 | if (FD_ISSET(tls->ifd, &testfds)) { |
1630 | dbg("NETWORK HAS DATA\n"); | 1571 | dbg("NETWORK HAS DATA\n"); |
1631 | read_record: | 1572 | read_record: |
1632 | nread = tls_xread_record(tls); | 1573 | nread = tls_xread_record(tls); |
@@ -1634,7 +1575,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) | |||
1634 | /* TLS protocol has no real concept of one-sided shutdowns: | 1575 | /* TLS protocol has no real concept of one-sided shutdowns: |
1635 | * if we get "TLS EOF" from the peer, writes will fail too | 1576 | * if we get "TLS EOF" from the peer, writes will fail too |
1636 | */ | 1577 | */ |
1637 | //FD_CLR(cfd, &readfds); | 1578 | //FD_CLR(tls->ifd, &readfds); |
1638 | //close(STDOUT_FILENO); | 1579 | //close(STDOUT_FILENO); |
1639 | //tls_free_inbuf(tls); /* mem usage optimization */ | 1580 | //tls_free_inbuf(tls); /* mem usage optimization */ |
1640 | //continue; | 1581 | //continue; |
@@ -1650,6 +1591,4 @@ int tls_main(int argc UNUSED_PARAM, char **argv) | |||
1650 | goto read_record; | 1591 | goto read_record; |
1651 | } | 1592 | } |
1652 | } | 1593 | } |
1653 | |||
1654 | return EXIT_SUCCESS; | ||
1655 | } | 1594 | } |
diff --git a/networking/wget.c b/networking/wget.c index 58ead4c96..a448acdae 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -47,18 +47,26 @@ | |||
47 | //config: FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option | 47 | //config: FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option |
48 | //config: will work in addition to -T. | 48 | //config: will work in addition to -T. |
49 | //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: | ||
50 | //config:config FEATURE_WGET_OPENSSL | 61 | //config:config FEATURE_WGET_OPENSSL |
51 | //config: bool "Try to connect to HTTPS using openssl" | 62 | //config: bool "Try to connect to HTTPS using openssl" |
52 | //config: default y | 63 | //config: default y |
53 | //config: depends on WGET | 64 | //config: depends on WGET |
54 | //config: help | 65 | //config: help |
55 | //config: Choose how wget establishes SSL connection for https:// URLs. | 66 | //config: Try to use openssl to handle HTTPS. |
56 | //config: | ||
57 | //config: Busybox itself contains no SSL code. wget will spawn | ||
58 | //config: a helper program to talk over HTTPS. | ||
59 | //config: | 67 | //config: |
60 | //config: OpenSSL has a simple SSL client for debug purposes. | 68 | //config: OpenSSL has a simple SSL client for debug purposes. |
61 | //config: If you select "openssl" helper, wget will effectively run: | 69 | //config: If you select this option, wget will effectively run: |
62 | //config: "openssl s_client -quiet -connect hostname:443 | 70 | //config: "openssl s_client -quiet -connect hostname:443 |
63 | //config: -servername hostname 2>/dev/null" and pipe its data | 71 | //config: -servername hostname 2>/dev/null" and pipe its data |
64 | //config: through it. -servername is not used if hostname is numeric. | 72 | //config: through it. -servername is not used if hostname is numeric. |
@@ -71,24 +79,9 @@ | |||
71 | //config: openssl is also a big binary, often dynamically linked | 79 | //config: openssl is also a big binary, often dynamically linked |
72 | //config: against ~15 libraries. | 80 | //config: against ~15 libraries. |
73 | //config: | 81 | //config: |
74 | //config:config FEATURE_WGET_SSL_HELPER | 82 | //config: If openssl can't be executed, internal TLS code will be used |
75 | //config: bool "Try to connect to HTTPS using ssl_helper" | 83 | //config: (if you enabled it); if openssl can be executed but fails later, |
76 | //config: default y | 84 | //config: wget can't detect this, and download will fail. |
77 | //config: depends on WGET | ||
78 | //config: help | ||
79 | //config: Choose how wget establishes SSL connection for https:// URLs. | ||
80 | //config: | ||
81 | //config: Busybox itself contains no SSL code. wget will spawn | ||
82 | //config: a helper program to talk over HTTPS. | ||
83 | //config: | ||
84 | //config: ssl_helper is a tool which can be built statically | ||
85 | //config: from busybox sources against a small embedded SSL library. | ||
86 | //config: Please see networking/ssl_helper/README. | ||
87 | //config: It does not require double host resolution and emits | ||
88 | //config: error messages to stderr. | ||
89 | //config: | ||
90 | //config: Precompiled static binary may be available at | ||
91 | //config: http://busybox.net/downloads/binaries/ | ||
92 | 85 | ||
93 | //applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP)) | 86 | //applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP)) |
94 | 87 | ||
@@ -137,7 +130,7 @@ | |||
137 | #endif | 130 | #endif |
138 | 131 | ||
139 | 132 | ||
140 | #define SSL_SUPPORTED (ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER) | 133 | #define SSL_SUPPORTED (ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_HTTPS) |
141 | 134 | ||
142 | struct host_info { | 135 | struct host_info { |
143 | char *allocated; | 136 | char *allocated; |
@@ -657,7 +650,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) | |||
657 | char *servername; | 650 | char *servername; |
658 | int sp[2]; | 651 | int sp[2]; |
659 | int pid; | 652 | int pid; |
660 | IF_FEATURE_WGET_SSL_HELPER(volatile int child_failed = 0;) | 653 | IF_FEATURE_WGET_HTTPS(volatile int child_failed = 0;) |
661 | 654 | ||
662 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0) | 655 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0) |
663 | /* Kernel can have AF_UNIX support disabled */ | 656 | /* Kernel can have AF_UNIX support disabled */ |
@@ -702,7 +695,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) | |||
702 | 695 | ||
703 | BB_EXECVP(argv[0], argv); | 696 | BB_EXECVP(argv[0], argv); |
704 | xmove_fd(3, 2); | 697 | xmove_fd(3, 2); |
705 | # if ENABLE_FEATURE_WGET_SSL_HELPER | 698 | # if ENABLE_FEATURE_WGET_HTTPS |
706 | child_failed = 1; | 699 | child_failed = 1; |
707 | xfunc_die(); | 700 | xfunc_die(); |
708 | # else | 701 | # else |
@@ -715,7 +708,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) | |||
715 | free(servername); | 708 | free(servername); |
716 | free(allocated); | 709 | free(allocated); |
717 | close(sp[1]); | 710 | close(sp[1]); |
718 | # if ENABLE_FEATURE_WGET_SSL_HELPER | 711 | # if ENABLE_FEATURE_WGET_HTTPS |
719 | if (child_failed) { | 712 | if (child_failed) { |
720 | close(sp[0]); | 713 | close(sp[0]); |
721 | return -1; | 714 | return -1; |
@@ -725,38 +718,51 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) | |||
725 | } | 718 | } |
726 | #endif | 719 | #endif |
727 | 720 | ||
728 | /* See networking/ssl_helper/README how to build one */ | 721 | #if ENABLE_FEATURE_WGET_HTTPS |
729 | #if ENABLE_FEATURE_WGET_SSL_HELPER | 722 | static void spawn_ssl_client(const char *host, int network_fd) |
730 | static void spawn_https_helper_small(int network_fd) | ||
731 | { | 723 | { |
732 | int sp[2]; | 724 | int sp[2]; |
733 | int pid; | 725 | int pid; |
726 | char *servername, *p; | ||
727 | |||
728 | servername = xstrdup(host); | ||
729 | p = strrchr(servername, ':'); | ||
730 | if (p) *p = '\0'; | ||
734 | 731 | ||
735 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0) | 732 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0) |
736 | /* Kernel can have AF_UNIX support disabled */ | 733 | /* Kernel can have AF_UNIX support disabled */ |
737 | bb_perror_msg_and_die("socketpair"); | 734 | bb_perror_msg_and_die("socketpair"); |
738 | 735 | ||
736 | fflush_all(); | ||
739 | pid = BB_MMU ? xfork() : xvfork(); | 737 | pid = BB_MMU ? xfork() : xvfork(); |
740 | if (pid == 0) { | 738 | if (pid == 0) { |
741 | /* Child */ | 739 | /* Child */ |
742 | char *argv[3]; | ||
743 | |||
744 | close(sp[0]); | 740 | close(sp[0]); |
745 | xmove_fd(sp[1], 0); | 741 | xmove_fd(sp[1], 0); |
746 | xdup2(0, 1); | 742 | xdup2(0, 1); |
747 | xmove_fd(network_fd, 3); | 743 | if (BB_MMU) { |
748 | /* | 744 | tls_state_t *tls = new_tls_state(); |
749 | * A simple ssl/tls helper | 745 | tls->ifd = tls->ofd = network_fd; |
750 | */ | 746 | tls_handshake(tls, servername); |
751 | argv[0] = (char*)"ssl_helper"; | 747 | tls_run_copy_loop(tls); |
752 | argv[1] = (char*)"-d3"; | 748 | exit(0); |
753 | argv[2] = NULL; | 749 | } else { |
754 | BB_EXECVP(argv[0], argv); | 750 | char *argv[5]; |
755 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); | 751 | xmove_fd(network_fd, 3); |
752 | argv[0] = (char*)"ssl_client"; | ||
753 | argv[1] = (char*)"-s3"; | ||
754 | //TODO: if (!is_ip_address(servername))... | ||
755 | argv[2] = (char*)"-n"; | ||
756 | argv[3] = servername; | ||
757 | argv[4] = NULL; | ||
758 | BB_EXECVP(argv[0], argv); | ||
759 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); | ||
760 | } | ||
756 | /* notreached */ | 761 | /* notreached */ |
757 | } | 762 | } |
758 | 763 | ||
759 | /* Parent */ | 764 | /* Parent */ |
765 | free(servername); | ||
760 | close(sp[1]); | 766 | close(sp[1]); |
761 | xmove_fd(sp[0], network_fd); | 767 | xmove_fd(sp[0], network_fd); |
762 | } | 768 | } |
@@ -1005,16 +1011,16 @@ static void download_one_url(const char *url) | |||
1005 | 1011 | ||
1006 | /* Open socket to http(s) server */ | 1012 | /* Open socket to http(s) server */ |
1007 | #if ENABLE_FEATURE_WGET_OPENSSL | 1013 | #if ENABLE_FEATURE_WGET_OPENSSL |
1008 | /* openssl (and maybe ssl_helper) support is configured */ | 1014 | /* openssl (and maybe internal TLS) support is configured */ |
1009 | if (target.protocol == P_HTTPS) { | 1015 | if (target.protocol == P_HTTPS) { |
1010 | /* openssl-based helper | 1016 | /* openssl-based helper |
1011 | * Inconvenient API since we can't give it an open fd | 1017 | * Inconvenient API since we can't give it an open fd |
1012 | */ | 1018 | */ |
1013 | int fd = spawn_https_helper_openssl(server.host, server.port); | 1019 | int fd = spawn_https_helper_openssl(server.host, server.port); |
1014 | # if ENABLE_FEATURE_WGET_SSL_HELPER | 1020 | # if ENABLE_FEATURE_WGET_HTTPS |
1015 | if (fd < 0) { /* no openssl? try ssl_helper */ | 1021 | if (fd < 0) { /* no openssl? try internal */ |
1016 | sfp = open_socket(lsa); | 1022 | sfp = open_socket(lsa); |
1017 | spawn_https_helper_small(fileno(sfp)); | 1023 | spawn_ssl_client(server.host, fileno(sfp)); |
1018 | goto socket_opened; | 1024 | goto socket_opened; |
1019 | } | 1025 | } |
1020 | # else | 1026 | # else |
@@ -1027,11 +1033,11 @@ static void download_one_url(const char *url) | |||
1027 | } | 1033 | } |
1028 | sfp = open_socket(lsa); | 1034 | sfp = open_socket(lsa); |
1029 | socket_opened: | 1035 | socket_opened: |
1030 | #elif ENABLE_FEATURE_WGET_SSL_HELPER | 1036 | #elif ENABLE_FEATURE_WGET_HTTPS |
1031 | /* Only ssl_helper support is configured */ | 1037 | /* Only internal TLS support is configured */ |
1032 | sfp = open_socket(lsa); | 1038 | sfp = open_socket(lsa); |
1033 | if (target.protocol == P_HTTPS) | 1039 | if (target.protocol == P_HTTPS) |
1034 | spawn_https_helper_small(fileno(sfp)); | 1040 | spawn_ssl_client(server.host, fileno(sfp)); |
1035 | #else | 1041 | #else |
1036 | /* ssl (https) support is not configured */ | 1042 | /* ssl (https) support is not configured */ |
1037 | sfp = open_socket(lsa); | 1043 | sfp = open_socket(lsa); |