diff --git a/include/libbb.h b/include/libbb.h index bc1453e12..69f76cbb3 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -962,7 +962,7 @@ static inline tls_state_t *new_tls_state(void) tls_state_t *tls = xzalloc(sizeof(*tls)); return tls; } -void tls_handshake(tls_state_t *tls, const char *sni) FAST_FUNC; +//void tls_handshake(tls_state_t *tls, const char *sni) FAST_FUNC; #define TLSLOOP_EXIT_ON_LOCAL_EOF (1 << 0) void tls_run_copy_loop(tls_state_t *tls, unsigned flags) FAST_FUNC; diff --git a/networking/ssl_client.c b/networking/ssl_client.c index 757745896..38163440f 100644 --- a/networking/ssl_client.c +++ b/networking/ssl_client.c @@ -69,7 +69,7 @@ int ssl_client_main(int argc UNUSED_PARAM, char **argv) } #endif - tls_handshake(tls, sni); + //tls_handshake(tls, sni); BUILD_BUG_ON(TLSLOOP_EXIT_ON_LOCAL_EOF != 1); tls_run_copy_loop(tls, /*flags*/ opt & 1); diff --git a/networking/tls.c b/networking/tls.c index 9f1dd67ec..60e1afe99 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -2221,6 +2221,7 @@ static void send_client_finished(tls_state_t *tls) xwrite_encrypted(tls, sizeof(*record), RECORD_TYPE_HANDSHAKE); } +/* void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) { // Client RFC 5246 Server @@ -2291,8 +2292,8 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) // defined in Section 7.4.2." // (i.e. the same format as server certs) - /*send_empty_client_cert(tls); - WRONG (breaks handshake hash calc) */ - /* need to hash _all_ server replies first, up to ServerHelloDone */ + //send_empty_client_cert(tls); - WRONG (breaks handshake hash calc) / + // need to hash _all_ server replies first, up to ServerHelloDone / len = tls_xread_handshake_block(tls, 4); } @@ -2308,13 +2309,13 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) send_client_key_exchange(tls); send_change_cipher_spec(tls); - /* from now on we should send encrypted */ - /* tls->write_seq64_be = 0; - already is */ + // from now on we should send encrypted / + // tls->write_seq64_be = 0; - already is / tls->flags |= ENCRYPT_ON_WRITE; send_client_finished(tls); - /* Get CHANGE_CIPHER_SPEC */ + // Get CHANGE_CIPHER_SPEC / len = tls_xread_record(tls, "switch to encrypted traffic"); if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) bad_record_die(tls, "switch to encrypted traffic", len); @@ -2327,29 +2328,30 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) } else if (!(tls->flags & ENCRYPTION_AESGCM)) { unsigned mac_blocks = (unsigned)(TLS_MAC_SIZE(tls) + AES_BLOCK_SIZE-1) / AES_BLOCK_SIZE; - /* all incoming packets now should be encrypted and have - * at least IV + (MAC padded to blocksize): - */ + // all incoming packets now should be encrypted and have + // at least IV + (MAC padded to blocksize): + // tls->min_encrypted_len_on_read = AES_BLOCK_SIZE + (mac_blocks * AES_BLOCK_SIZE); } else { tls->min_encrypted_len_on_read = 8 + AES_BLOCK_SIZE; } dbg("min_encrypted_len_on_read: %u\n", tls->min_encrypted_len_on_read); - /* Get (encrypted) FINISHED from the server */ + // Get (encrypted) FINISHED from the server / len = tls_xread_record(tls, "'server finished'"); if (len < 4 || tls->inbuf[RECHDR_LEN] != HANDSHAKE_FINISHED) bad_record_die(tls, "'server finished'", len); dbg("<< FINISHED\n"); - /* application data can be sent/received */ + // application data can be sent/received / - /* free handshake data */ + // free handshake data / psRsaKey_clear(&tls->hsd->server_rsa_pub_key); // if (PARANOIA) // memset(tls->hsd, 0, tls->hsd->hsd_size); free(tls->hsd); tls->hsd = NULL; } +*/ static void tls_xwrite(tls_state_t *tls, int len) { diff --git a/networking/wget.c b/networking/wget.c index 6a64836fb..2f3ff4017 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -1,4 +1,3 @@ -/* vi: set sw=4 ts=4: */ /* * wget - retrieve a file using HTTP or FTP * @@ -271,6 +270,9 @@ struct globals { int output_fd; int log_fd; int o_flags; +#if ENABLE_FEATURE_WGET_OPENSSL + struct tls_config *tlscfg; +#endif #if ENABLE_FEATURE_WGET_TIMEOUT unsigned timeout_seconds; smallint die_if_timed_out; @@ -460,6 +462,61 @@ static FILE *open_socket(len_and_sockaddr *lsa) return fp; } +#if ENABLE_PLATFORM_MINGW32 +/* Use windows installed certificates for wget */ +#include +#include +#include +#include +#include +#include +#include +#include +BIO* gather_certificates(struct tls_config *cfg); +BIO* gather_certificates(struct tls_config *cfg) +{ + SSL_library_init(); + SSL_load_error_strings(); + BIO *pemfile; + HCERTSTORE dstore; + PCCERT_CONTEXT ctx; + char *pemmem; + long data_size; + + pemfile = BIO_new(BIO_s_mem()); + dstore = CertOpenSystemStore(0,"ROOT"); + if(dstore == NULL) + bb_error_msg_and_die("Failed to open system store"); + if(!dstore) + bb_error_msg_and_die("Error opening 'CA' cert store"); + ctx = NULL; + for(;;) + { + char *dcert; + size_t dcert_len; + X509 *x509cert; + + ctx = CertEnumCertificatesInStore(dstore,ctx); + if(!ctx) + break; + dcert = ctx->pbCertEncoded; + dcert_len = ctx->cbCertEncoded; + x509cert = d2i_X509(NULL,&dcert,dcert_len); + if(x509cert == NULL) + bb_error_msg_and_die("Failed to convert dcert to x509"); + if(x509cert == NULL) + bb_error_msg_and_die("Failed to convert cert"); + if(!PEM_write_bio_X509(pemfile, x509cert)) + bb_error_msg_and_die("Failed to write cert"); + X509_free(x509cert); + } + CertCloseStore(dstore, CERT_CLOSE_STORE_CHECK_FLAG); + data_size = BIO_get_mem_data(pemfile, &pemmem); + tls_config_set_ca_mem(cfg, pemmem, data_size); + return pemfile; +} +#endif + /* We balk at any control chars in other side's messages. * This prevents nasty surprises (e.g. ESC sequences) in "Location:" URLs * and error messages. @@ -689,6 +746,7 @@ static void reset_beg_range_to_zero(void) } #if ENABLE_FEATURE_WGET_OPENSSL +/* static int spawn_https_helper_openssl(const char *host, unsigned port) { char *allocated = NULL; @@ -698,7 +756,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) 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 */ + // Kernel can have AF_UNIX support disabled / bb_simple_perror_msg_and_die("socketpair"); if (!strchr(host, ':')) @@ -709,18 +767,18 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) fflush_all(); pid = xvfork(); if (pid == 0) { - /* Child */ + // Child / char *argv[13]; char **argp; close(sp[0]); xmove_fd(sp[1], 0); xdup2(0, 1); - /* - * openssl s_client -quiet -connect www.kernel.org:443 2>/dev/null - * It prints some debug stuff on stderr, don't know how to suppress it. - * Work around by dev-nulling stderr. We lose all error messages :( - */ + // + // openssl s_client -quiet -connect www.kernel.org:443 2>/dev/null + // It prints some debug stuff on stderr, don't know how to suppress it. + // Work around by dev-nulling stderr. We lose all error messages :( + // xmove_fd(2, 3); xopen("/dev/null", O_RDWR); memset(&argv, 0, sizeof(argv)); @@ -729,18 +787,18 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) argv[2] = (char*)"-quiet"; argv[3] = (char*)"-connect"; argv[4] = (char*)host; - /* - * Per RFC 6066 Section 3, the only permitted values in the - * TLS server_name (SNI) field are FQDNs (DNS hostnames). - * IPv4 and IPv6 addresses, port numbers are not allowed. - */ + // + // Per RFC 6066 Section 3, the only permitted values in the + // TLS server_name (SNI) field are FQDNs (DNS hostnames). + // IPv4 and IPv6 addresses, port numbers are not allowed. + // argp = &argv[5]; if (!is_ip_address(servername)) { *argp++ = (char*)"-servername"; //[5] *argp++ = (char*)servername; //[6] } if (!(option_mask32 & WGET_OPT_NO_CHECK_CERT)) { - /* Abort on bad server certificate */ + // Abort on bad server certificate / *argp++ = (char*)"-verify"; //[7] *argp++ = (char*)"100"; //[8] *argp++ = (char*)"-verify_return_error"; //[9] @@ -762,10 +820,10 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) # else bb_perror_msg_and_die("can't execute '%s'", argv[0]); # endif - /* notreached */ + // notreached / } - /* Parent */ + // Parent / free(servername); free(allocated); close(sp[1]); @@ -777,6 +835,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) # endif return sp[0]; } +*/ #endif #if ENABLE_FEATURE_WGET_HTTPS @@ -1139,6 +1198,7 @@ static void download_one_url(const char *url) bool use_proxy; /* Use proxies if env vars are set */ int redir_limit; len_and_sockaddr *lsa; + char *sfp_name, *dfp_name; FILE *sfp; /* socket to web/ftp server */ FILE *dfp; /* socket to ftp server (data) */ char *fname_out_alloc; @@ -1151,6 +1211,9 @@ static void download_one_url(const char *url) server.user = NULL; target.user = NULL; + struct tls *ctx; + ctx = NULL; + parse_url(url, &target); /* Use the proxy if necessary */ @@ -1234,22 +1297,38 @@ static void download_one_url(const char *url) /* 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_HTTPS - if (fd < 0) { /* no openssl? try internal */ - sfp = open_socket(lsa); - spawn_ssl_client(server.host, fileno(sfp), /*flags*/ 0); - goto socket_opened; - } + char *allocated, *servername, *host; + if(!strchr(server.host, ':')) + host = allocated = xasprintf("%s:%u", server.host, server.port); + servername = xstrdup(host); + ctx = tls_client(); + if(ctx == NULL) + bb_error_msg_and_die("Out of memory 1"); + if(tls_configure(ctx,G.tlscfg) != 0) + bb_error_msg_and_die("Failed to configure client"); + sfp_name = _tempnam(NULL,"l4w"); + if(sfp_name == NULL) + bb_error_msg_and_die("Failed to generate tmpfile name for sfp"); + sfp = fopen(sfp_name, "w+"); + if(sfp == NULL) + bb_error_msg_and_die("Failed to open source tempfile %d: %s", errno, strerror(errno)); + dfp_name = _tempnam(NULL,"l4w"); + if(dfp_name == NULL) + bb_error_msg_and_die("Failed to generate tmpfile name for dfp"); + dfp = fopen(dfp_name, "w+"); + if(dfp == NULL) + bb_error_msg_and_die("Failed to open source tempfile %d: %s", errno, strerror(errno)); + if(tls_connect(ctx, servername, NULL) != 0) + bb_error_msg_and_die("Failed to connect: %s", tls_error(ctx)); + free(allocated); + free(servername); # else /* We don't check for exec("openssl") failure in this case */ # endif - sfp = fdopen(fd, "r+"); - if (!sfp) - bb_die_memory_exhausted(); goto socket_opened; } - sfp = open_socket(lsa); + //sfp = open_socket(lsa); socket_opened: #elif ENABLE_FEATURE_WGET_HTTPS /* Only internal TLS support is configured */ @@ -1353,7 +1432,42 @@ static void download_one_url(const char *url) shutdown(fileno(sfp), SHUT_WR); } #endif - + //How much data did we actually get? + size_t wlen, bufsize; + wlen = ftell(sfp); + if(wlen < 0) + bb_error_msg_and_die("Failed to get source len %d:%s",errno,strerror(errno)); + bufsize = 4096; + char buf[bufsize]; + char *outbuf; + outbuf = (char*)malloc(sizeof(char) * wlen); + if(outbuf == NULL) + bb_error_msg_and_die("Out of memory"); + rewind(sfp); + rewind(dfp); + if(fread(outbuf, sizeof(char), wlen, sfp) < wlen) + bb_error_msg_and_die("Failed to read tmpfile: %s", strerror(errno)); + if(tls_write(ctx, outbuf, wlen) < wlen) + bb_error_msg_and_die("Failed to write:%s",tls_error(ctx)); + ssize_t len; + len = TLS_WANT_POLLIN; + while(len == TLS_WANT_POLLIN || len > 0){ + len = tls_read(ctx, buf, bufsize); + if(len == -1) + bb_error_msg_and_die("Failed tls read: %s", tls_error(ctx)); + if (len != TLS_WANT_POLLIN){ + wlen = fwrite(buf, sizeof(char), len, dfp); + if(wlen != len) + bb_error_msg_and_die("Failed to write to tempfile: (%zu) (%zd) %s", wlen, len, strerror(errno)); + } + } + if(len == -1) + bb_error_msg_and_die("tls read error: %s", tls_error(ctx)); + rewind(dfp); + fclose(sfp); + DeleteFile(sfp_name); + free(sfp_name); + sfp = dfp; /* * Retrieve HTTP response line and check for "200" status code. */ @@ -1475,6 +1589,11 @@ However, in real world it was observed that some web servers if (--redir_limit == 0) bb_simple_error_msg_and_die("too many redirections"); fclose(sfp); + fclose(dfp); + DeleteFile(sfp_name); + DeleteFile(dfp_name); + free(sfp_name); + free(dfp_name); if (str[0] == '/') { free(redirected_path); target.path = redirected_path = xstrdup(str + 1); @@ -1536,7 +1655,11 @@ However, in real world it was observed that some web servers /* ftpcmd("QUIT", NULL, sfp); - why bother? */ } #endif + if(ctx != NULL) + tls_close(ctx); fclose(sfp); + DeleteFile(dfp_name); + free(dfp_name); free(server.allocated); free(target.allocated); @@ -1690,9 +1813,14 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0") xdup2(G.log_fd, STDERR_FILENO); } } - + G.tlscfg = tls_config_new(); + if(G.tlscfg == NULL) + bb_error_msg_and_die("Out of memory 2"); + BIO *pemmem = gather_certificates(G.tlscfg); while (*argv) download_one_url(*argv++); + BIO_free(pemmem); + tls_config_free(G.tlscfg); if (G.output_fd >= 0) xclose(G.output_fd); @@ -1704,6 +1832,5 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0") free(G.extra_headers); #endif FINI_G(); - return EXIT_SUCCESS; } diff --git a/scripts/trylink b/scripts/trylink index 2456252a3..6186284f1 100755 --- a/scripts/trylink +++ b/scripts/trylink @@ -84,7 +84,8 @@ A_FILES="$6" # a real utmp library in LDLIBS, dropping it "works" but resulting binary # does not work properly). LDLIBS="$7" -CONFIG_EXTRA_LDLIBS="$8" +shift 7 +CONFIG_EXTRA_LDLIBS="$@" # The --sort-section option is not supported by older versions of ld SORT_SECTION="-Wl,--sort-section,alignment" diff --git a/win32/mingw.c b/win32/mingw.c index 87e7ca602..7bad3e4fa 100644 --- a/win32/mingw.c +++ b/win32/mingw.c @@ -1214,11 +1214,13 @@ elevation_state(void) return elevated | (enabled << 1); } +/* int getuid(void) { return elevation_state() == (ELEVATED_PRIVILEGE | ADMIN_ENABLED) ? 0 : DEFAULT_UID; } +*/ struct passwd *getpwnam(const char *name) {