X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=apps%2Fs_client.c;h=ce7366f8fe6c830b362d35cd29efd5cbdf7ce76b;hp=7c0639faad21e39635afbed886541f521d2578c3;hb=5281435258b5d8201a00b4a9781bb724d99630f0;hpb=3a63c0edab842af3e84ef1cad2b4eb701eece3e1 diff --git a/apps/s_client.c b/apps/s_client.c index 7c0639faad..ce7366f8fe 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2005 Nokia. All rights reserved. * * Licensed under the OpenSSL license (the "License"). You may not use @@ -30,6 +30,7 @@ typedef unsigned int u_int; #endif #include "apps.h" +#include "progs.h" #include #include #include @@ -196,19 +197,13 @@ static int psk_use_session_cb(SSL *s, const EVP_MD *md, return 0; } - if (key_len == EVP_MD_size(EVP_sha256())) - cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id); - else if (key_len == EVP_MD_size(EVP_sha384())) - cipher = SSL_CIPHER_find(s, tls13_aes256gcmsha384_id); - + /* We default to SHA-256 */ + cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id); if (cipher == NULL) { - /* Doesn't look like a suitable TLSv1.3 key. Ignore it */ - OPENSSL_free(key); - *id = NULL; - *idlen = 0; - *sess = NULL; + BIO_printf(bio_err, "Error finding suitable ciphersuite\n"); return 0; } + usesess = SSL_SESSION_new(); if (usesess == NULL || !SSL_SESSION_set1_master_key(usesess, key, key_len) @@ -372,8 +367,6 @@ static char *ssl_give_srp_client_pwd_cb(SSL *s, void *arg) #endif -static char *srtp_profiles = NULL; - #ifndef OPENSSL_NO_NEXTPROTONEG /* This the context that we pass to next_proto_cb */ typedef struct tlsextnextprotoctx_st { @@ -569,7 +562,7 @@ static int tlsa_import_rrset(SSL *con, STACK_OF(OPENSSL_STRING) *rrset) typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, - OPT_4, OPT_6, OPT_HOST, OPT_PORT, OPT_CONNECT, OPT_UNIX, + OPT_4, OPT_6, OPT_HOST, OPT_PORT, OPT_CONNECT, OPT_BIND, OPT_UNIX, OPT_XMPPHOST, OPT_VERIFY, OPT_NAMEOPT, OPT_CERT, OPT_CRL, OPT_CRL_DOWNLOAD, OPT_SESS_OUT, OPT_SESS_IN, OPT_CERTFORM, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET, @@ -601,6 +594,7 @@ typedef enum OPTION_choice { OPT_CT, OPT_NOCT, OPT_CTLOG_FILE, #endif OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME, + OPT_FORCE_PHA, OPT_R_ENUM } OPTION_CHOICE; @@ -610,6 +604,7 @@ const OPTIONS s_client_options[] = { {"port", OPT_PORT, 'p', "Use -connect instead"}, {"connect", OPT_CONNECT, 's', "TCP/IP where to connect (default is :" PORT ")"}, + {"bind", OPT_BIND, 's', "bind local address for connection"}, {"proxy", OPT_PROXY, 's', "Connect to via specified proxy to the real server"}, #ifdef AF_UNIX @@ -660,8 +655,10 @@ const OPTIONS s_client_options[] = { OPT_R_OPTIONS, {"sess_out", OPT_SESS_OUT, '>', "File to write SSL session to"}, {"sess_in", OPT_SESS_IN, '<', "File to read SSL session from"}, +#ifndef OPENSSL_NO_SRTP {"use_srtp", OPT_USE_SRTP, 's', "Offer SRTP key management with a colon-separated profile list"}, +#endif {"keymatexport", OPT_KEYMATEXPORT, 's', "Export keying material using label"}, {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p', @@ -787,6 +784,7 @@ const OPTIONS s_client_options[] = { #endif {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"}, {"early_data", OPT_EARLY_DATA, '<', "File to send as early data"}, + {"force_pha", OPT_FORCE_PHA, '-', "Force-enable post-handshake-authentication"}, {NULL, OPT_EOF, 0x00, NULL} }; @@ -881,10 +879,11 @@ int s_client_main(int argc, char **argv) const SSL_METHOD *meth = TLS_client_method(); const char *CApath = NULL, *CAfile = NULL; char *cbuf = NULL, *sbuf = NULL; - char *mbuf = NULL, *proxystr = NULL, *connectstr = NULL; + char *mbuf = NULL, *proxystr = NULL, *connectstr = NULL, *bindstr = NULL; char *cert_file = NULL, *key_file = NULL, *chain_file = NULL; char *chCApath = NULL, *chCAfile = NULL, *host = NULL; char *port = OPENSSL_strdup(PORT); + char *bindhost = NULL, *bindport = NULL; char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL; char *ReqCAfile = NULL; char *sess_in = NULL, *crl_file = NULL, *p; @@ -935,6 +934,7 @@ int s_client_main(int argc, char **argv) int srp_lateuser = 0; SRP_ARG srp_arg = { NULL, NULL, 0, 0, 0, 1024 }; #endif + char *srtp_profiles = NULL; #ifndef OPENSSL_NO_CT char *ctlog_file = NULL; int ct_validation = 0; @@ -957,6 +957,7 @@ int s_client_main(int argc, char **argv) int isdtls = 0; #endif char *psksessf = NULL; + int force_pha = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); @@ -1049,6 +1050,9 @@ int s_client_main(int argc, char **argv) connect_type = use_inet; freeandcopy(&connectstr, opt_arg()); break; + case OPT_BIND: + freeandcopy(&bindstr, opt_arg()); + break; case OPT_PROXY: proxystr = opt_arg(); starttls_proto = PROTO_CONNECT; @@ -1468,6 +1472,9 @@ int s_client_main(int argc, char **argv) case OPT_EARLY_DATA: early_data_file = opt_arg(); break; + case OPT_FORCE_PHA: + force_pha = 1; + break; } } if (count4or6 >= 2) { @@ -1547,6 +1554,18 @@ int s_client_main(int argc, char **argv) } } + if (bindstr != NULL) { + int res; + res = BIO_parse_hostserv(bindstr, &bindhost, &bindport, + BIO_PARSE_PRIO_HOST); + if (!res) { + BIO_printf(bio_err, + "%s: -bind argument parameter malformed or ambiguous\n", + prog); + goto end; + } + } + #ifdef AF_UNIX if (socket_family == AF_UNIX && socket_type != SOCK_STREAM) { BIO_printf(bio_err, @@ -1654,6 +1673,9 @@ int s_client_main(int argc, char **argv) if (sdebug) ssl_ctx_security_debug(ctx, sdebug); + if (!config_ctx(cctx, ssl_args, ctx)) + goto end; + if (ssl_config != NULL) { if (SSL_CTX_config(ctx, ssl_config) == 0) { BIO_printf(bio_err, "Error using configuration \"%s\"\n", @@ -1663,9 +1685,11 @@ int s_client_main(int argc, char **argv) } } - if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0) + if (min_version != 0 + && SSL_CTX_set_min_proto_version(ctx, min_version) == 0) goto end; - if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0) + if (max_version != 0 + && SSL_CTX_set_max_proto_version(ctx, max_version) == 0) goto end; if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) { @@ -1711,9 +1735,6 @@ int s_client_main(int argc, char **argv) goto end; } - if (!config_ctx(cctx, ssl_args, ctx)) - goto end; - if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile, crls, crl_download)) { BIO_printf(bio_err, "Error loading store locations\n"); @@ -1903,6 +1924,9 @@ int s_client_main(int argc, char **argv) if (con == NULL) goto end; + if (force_pha) + SSL_force_post_handshake_auth(con); + if (sess_in != NULL) { SSL_SESSION *sess; BIO *stmp = BIO_new_file(sess_in, "r"); @@ -1923,18 +1947,7 @@ int s_client_main(int argc, char **argv) ERR_print_errors(bio_err); goto end; } - /* By default the SNI should be the same as was set in the session */ - if (!noservername && servername == NULL) { - servername = SSL_SESSION_get0_hostname(sess); - if (servername == NULL) { - /* - * Force no SNI to be sent so we are consistent with the - * session. - */ - noservername = 1; - } - } SSL_SESSION_free(sess); } @@ -1977,8 +1990,8 @@ int s_client_main(int argc, char **argv) } re_start: - if (init_client(&s, host, port, socket_family, socket_type, protocol) - == 0) { + if (init_client(&s, host, port, bindhost, bindport, socket_family, + socket_type, protocol) == 0) { BIO_printf(bio_err, "connect:errno=%d\n", get_last_socket_error()); BIO_closesocket(s); goto end; @@ -3036,7 +3049,7 @@ int s_client_main(int argc, char **argv) if (in_init) print_stuff(bio_c_out, con, full_log); do_ssl_shutdown(con); -#if defined(OPENSSL_SYS_WINDOWS) + /* * Give the socket time to send its last data before we close it. * No amount of setting SO_LINGER etc on the socket seems to persuade @@ -3044,8 +3057,23 @@ int s_client_main(int argc, char **argv) * for a short time seems to do it (units in ms) * TODO: Find a better way to do this */ +#if defined(OPENSSL_SYS_WINDOWS) Sleep(50); +#elif defined(OPENSSL_SYS_CYGWIN) + usleep(50000); #endif + + /* + * If we ended with an alert being sent, but still with data in the + * network buffer to be read, then calling BIO_closesocket() will + * result in a TCP-RST being sent. On some platforms (notably + * Windows) then this will result in the peer immediately abandoning + * the connection including any buffered alert data before it has + * had a chance to be read. Shutting down the sending side first, + * and then closing the socket sends TCP-FIN first followed by + * TCP-RST. This seems to allow the peer to read the alert data. + */ + shutdown(SSL_get_fd(con), 1); /* SHUT_WR */ BIO_closesocket(SSL_get_fd(con)); end: if (con != NULL) { @@ -3068,6 +3096,7 @@ int s_client_main(int argc, char **argv) OPENSSL_free(srp_arg.srppassin); #endif OPENSSL_free(connectstr); + OPENSSL_free(bindstr); OPENSSL_free(host); OPENSSL_free(port); X509_VERIFY_PARAM_free(vpm);