aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-01-23 01:08:16 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2017-01-23 01:08:16 +0100
commit9a647c326a41e8160d53e6cb5470161a44c0e8cf (patch)
tree1fef73df291e5c5897aef1bb32b65206caacf879
parente1f90d13fa07d2974908470ce818ef956b7740f2 (diff)
downloadbusybox-w32-9a647c326a41e8160d53e6cb5470161a44c0e8cf.tar.gz
busybox-w32-9a647c326a41e8160d53e6cb5470161a44c0e8cf.tar.bz2
busybox-w32-9a647c326a41e8160d53e6cb5470161a44c0e8cf.zip
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>
-rw-r--r--include/libbb.h88
-rw-r--r--networking/ssl_client.c55
-rw-r--r--networking/tls.c151
-rw-r--r--networking/wget.c102
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
356extern char *strrstr(const char *haystack, const char *needle) FAST_FUNC; 356extern 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. */
360void *malloc_or_warn(size_t size) FAST_FUNC RETURNS_MALLOC;
361void *xmalloc(size_t size) FAST_FUNC RETURNS_MALLOC;
362void *xzalloc(size_t size) FAST_FUNC RETURNS_MALLOC;
363void *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))
373void* xrealloc_vector_helper(void *vector, unsigned sizeof_and_shift, int idx) FAST_FUNC;
374char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC;
375char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC;
376void *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)?
359extern const char *bb_mode_string(mode_t mode) FAST_FUNC; 380extern const char *bb_mode_string(mode_t mode) FAST_FUNC;
360extern int is_directory(const char *name, int followLinks) FAST_FUNC; 381extern 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
721struct tls_handshake_data; /* opaque */
722typedef 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
755static inline tls_state_t *new_tls_state(void)
756{
757 tls_state_t *tls = xzalloc(sizeof(*tls));
758 return tls;
759}
760void tls_handshake(tls_state_t *tls, const char *sni) FAST_FUNC;
761void tls_run_copy_loop(tls_state_t *tls) FAST_FUNC;
695 762
696void socket_want_pktinfo(int fd) FAST_FUNC; 763void socket_want_pktinfo(int fd) FAST_FUNC;
697ssize_t send_to_from(int fd, void *buf, size_t len, int flags, 764ssize_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
706uint16_t inet_cksum(uint16_t *addr, int len) FAST_FUNC; 773uint16_t inet_cksum(uint16_t *addr, int len) FAST_FUNC;
707 774
708char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC;
709char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC;
710void *xmemdup(const void *s, int n) FAST_FUNC RETURNS_MALLOC;
711void overlapping_strcpy(char *dst, const char *src) FAST_FUNC; 775void overlapping_strcpy(char *dst, const char *src) FAST_FUNC;
712char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC; 776char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC;
713char *strncpy_IFNAMSIZ(char *dst, const char *src) FAST_FUNC; 777char *strncpy_IFNAMSIZ(char *dst, const char *src) FAST_FUNC;
@@ -753,24 +817,6 @@ enum {
753}; 817};
754void visible(unsigned ch, char *buf, int flags) FAST_FUNC; 818void 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. */
758void *malloc_or_warn(size_t size) FAST_FUNC RETURNS_MALLOC;
759void *xmalloc(size_t size) FAST_FUNC RETURNS_MALLOC;
760void *xzalloc(size_t size) FAST_FUNC RETURNS_MALLOC;
761void *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))
771void* xrealloc_vector_helper(void *vector, unsigned sizeof_and_shift, int idx) FAST_FUNC;
772
773
774extern ssize_t safe_read(int fd, void *buf, size_t count) FAST_FUNC; 820extern ssize_t safe_read(int fd, void *buf, size_t count) FAST_FUNC;
775extern ssize_t nonblock_immune_read(int fd, void *buf, size_t count) FAST_FUNC; 821extern 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
23int ssl_client_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
24int 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
167enum { 160enum {
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
228typedef struct tls_state { 214struct 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
268static unsigned get24be(const uint8_t *p) 226static 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
490static 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
498static void tls_error_die(tls_state_t *tls) 448static 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
1231static void get_server_cert(tls_state_t *tls) 1181static 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[] = {
1384static void send_change_cipher_spec(tls_state_t *tls) 1334static 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
1454static void tls_handshake(tls_state_t *tls, const char *sni) 1404void 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
1546static void tls_xwrite(tls_state_t *tls, int len) 1505static 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
1564int tls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 1520void FAST_FUNC tls_run_copy_loop(tls_state_t *tls)
1565int 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
142struct host_info { 135struct 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 722static void spawn_ssl_client(const char *host, int network_fd)
730static 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);