X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=apps%2Fs_client.c;h=a14d8855b39968a9850c07b201dc68c0beee5188;hb=a55b3959374161e33c68542d27c0fe93c6b7fe81;hp=41fed85ea0ff3e77e703c7020b8797ea75bb1a1d;hpb=a8db2cfa4b293f3db9566a305a26109c4fde74b2;p=oweals%2Fopenssl.git diff --git a/apps/s_client.c b/apps/s_client.c index 41fed85ea0..a14d8855b3 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -83,25 +83,13 @@ typedef unsigned int u_int; #define BUFSIZZ 1024*8 #define S_CLIENT_IRC_READ_TIMEOUT 8 -extern int verify_depth; -extern int verify_error; -extern int verify_return_error; -extern int verify_quiet; - static char *prog; -static int c_nbio = 0; -static int c_tlsextdebug = 0; -static int c_status_req = 0; static int c_debug = 0; -static int c_msg = 0; static int c_showcerts = 0; static char *keymatexportlabel = NULL; static int keymatexportlen = 20; static BIO *bio_c_out = NULL; -static BIO *bio_c_msg = NULL; static int c_quiet = 0; -static int c_ign_eof = 0; -static int c_brief = 0; static void print_stuff(BIO *berr, SSL *con, int full); #ifndef OPENSSL_NO_OCSP @@ -144,7 +132,6 @@ static void do_ssl_shutdown(SSL *ssl) } while (ret < 0); } - #ifndef OPENSSL_NO_PSK /* Default PSK identity and key */ static char *psk_identity = "Client_identity"; @@ -249,10 +236,10 @@ static int srp_Verify_N_and_g(const BIGNUM *N, const BIGNUM *g) BIGNUM *r = BN_new(); int ret = g != NULL && N != NULL && bn_ctx != NULL && BN_is_odd(N) && - BN_is_prime_ex(N, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) && + BN_is_prime_ex(N, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) == 1 && p != NULL && BN_rshift1(p, N) && /* p = (N-1)/2 */ - BN_is_prime_ex(p, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) && + BN_is_prime_ex(p, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) == 1 && r != NULL && /* verify g^((N-1)/2) == -1 (mod N) */ BN_mod_exp(r, g, p, N, bn_ctx) && @@ -404,7 +391,7 @@ static ossl_ssize_t hexdecode(const char **inptr, void *result) { unsigned char **out = (unsigned char **)result; const char *in = *inptr; - unsigned char *ret = app_malloc(strlen(in)/2, "hexdecode"); + unsigned char *ret = app_malloc(strlen(in) / 2, "hexdecode"); unsigned char *cp = ret; uint8_t byte; int nibble = 0; @@ -554,7 +541,8 @@ typedef enum OPTION_choice { OPT_SSL3, OPT_SSL_CONFIG, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1, OPT_DTLS1_2, OPT_TIMEOUT, OPT_MTU, OPT_KEYFORM, OPT_PASS, - OPT_CERT_CHAIN, OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, + OPT_CERT_CHAIN, OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, + OPT_VERIFYCAPATH, OPT_KEY, OPT_RECONNECT, OPT_BUILD_CHAIN, OPT_CAFILE, OPT_NOCAFILE, OPT_CHAINCAFILE, OPT_VERIFYCAFILE, OPT_NEXTPROTONEG, OPT_ALPN, OPT_SERVERINFO, OPT_STARTTLS, OPT_SERVERNAME, @@ -567,7 +555,7 @@ typedef enum OPTION_choice { #ifndef OPENSSL_NO_CT OPT_CT, OPT_NOCT, OPT_CTLOG_FILE, #endif - OPT_DANE_TLSA_RRDATA + OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME } OPTION_CHOICE; OPTIONS s_client_options[] = { @@ -589,8 +577,8 @@ OPTIONS s_client_options[] = { {"cert", OPT_CERT, '<', "Certificate file to use, PEM format assumed"}, {"certform", OPT_CERTFORM, 'F', "Certificate format (PEM or DER) PEM default"}, - {"key", OPT_KEY, '<', "Private key file to use, if not in -cert file"}, - {"keyform", OPT_KEYFORM, 'F', "Key format (PEM or DER) PEM default"}, + {"key", OPT_KEY, 's', "Private key file to use, if not in -cert file"}, + {"keyform", OPT_KEYFORM, 'E', "Key format (PEM, DER or engine) PEM default"}, {"pass", OPT_PASS, 's', "Private key file pass phrase source"}, {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"}, {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"}, @@ -601,6 +589,8 @@ OPTIONS s_client_options[] = { {"dane_tlsa_domain", OPT_DANE_TLSA_DOMAIN, 's', "DANE TLSA base domain"}, {"dane_tlsa_rrdata", OPT_DANE_TLSA_RRDATA, 's', "DANE TLSA rrdata presentation form"}, + {"dane_ee_no_namechecks", OPT_DANE_EE_NO_NAME, '-', + "Disable name checks when matching DANE-EE(3) TLSA records"}, {"reconnect", OPT_RECONNECT, '-', "Drop and re-make the connection with the same Session-ID"}, {"showcerts", OPT_SHOWCERTS, '-', "Show all certificates in the chain"}, @@ -768,6 +758,10 @@ static const OPT_PAIR services[] = { (o == OPT_4 || o == OPT_6 || o == OPT_HOST || o == OPT_PORT || o == OPT_CONNECT) #define IS_UNIX_FLAG(o) (o == OPT_UNIX) +#define IS_PROT_FLAG(o) \ + (o == OPT_SSL3 || o == OPT_TLS1 || o == OPT_TLS1_1 || o == OPT_TLS1_2 \ + || o == OPT_DTLS || o == OPT_DTLS1 || o == OPT_DTLS1_2) + /* Free |*dest| and optionally set it to a copy of |source|. */ static void freeandcopy(char **dest, const char *source) { @@ -791,9 +785,11 @@ int s_client_main(int argc, char **argv) STACK_OF(OPENSSL_STRING) *ssl_args = NULL; char *dane_tlsa_domain = NULL; STACK_OF(OPENSSL_STRING) *dane_tlsa_rrset = NULL; + int dane_ee_no_name = 0; STACK_OF(X509_CRL) *crls = NULL; const SSL_METHOD *meth = TLS_client_method(); - char *CApath = NULL, *CAfile = NULL, *cbuf = NULL, *sbuf = NULL; + const char *CApath = NULL, *CAfile = NULL; + char *cbuf = NULL, *sbuf = NULL; char *mbuf = NULL, *proxystr = NULL, *connectstr = NULL; char *cert_file = NULL, *key_file = NULL, *chain_file = NULL; char *chCApath = NULL, *chCAfile = NULL, *host = NULL; @@ -816,7 +812,9 @@ int s_client_main(int argc, char **argv) int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM; int starttls_proto = PROTO_OFF, crl_format = FORMAT_PEM, crl_download = 0; int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending; +#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) int at_eof = 0; +#endif int read_buf_len = 0; int fallback_scsv = 0; long randamt = 0; @@ -851,12 +849,18 @@ int s_client_main(int argc, char **argv) char *ctlog_file = NULL; int ct_validation = 0; #endif - int min_version = 0, max_version = 0; + int min_version = 0, max_version = 0, prot_opt = 0, no_prot_opt = 0; int async = 0; unsigned int split_send_fragment = 0; unsigned int max_pipelines = 0; enum { use_inet, use_unix, use_unknown } connect_type = use_unknown; int count4or6 = 0; + int c_nbio = 0, c_msg = 0, c_ign_eof = 0, c_brief = 0; + int c_tlsextdebug = 0; +#ifndef OPENSSL_NO_OCSP + int c_status_req = 0; +#endif + BIO *bio_c_msg = NULL; FD_ZERO(&readfds); FD_ZERO(&writefds); @@ -870,17 +874,10 @@ int s_client_main(int argc, char **argv) prog = opt_progname(argv[0]); c_quiet = 0; - c_ign_eof = 0; c_debug = 0; - c_msg = 0; c_showcerts = 0; c_nbio = 0; - verify_depth = 0; - verify_error = X509_V_OK; vpm = X509_VERIFY_PARAM_new(); - cbuf = app_malloc(BUFSIZZ, "cbuf"); - sbuf = app_malloc(BUFSIZZ, "sbuf"); - mbuf = app_malloc(BUFSIZZ, "mbuf"); cctx = SSL_CONF_CTX_new(); if (vpm == NULL || cctx == NULL) { @@ -888,6 +885,10 @@ int s_client_main(int argc, char **argv) goto end; } + cbuf = app_malloc(BUFSIZZ, "cbuf"); + sbuf = app_malloc(BUFSIZZ, "sbuf"); + mbuf = app_malloc(BUFSIZZ, "mbuf"); + SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT | SSL_CONF_FLAG_CMDLINE); prog = opt_init(argc, argv, s_client_options); @@ -895,16 +896,29 @@ int s_client_main(int argc, char **argv) /* Check for intermixing flags. */ if (connect_type == use_unix && IS_INET_FLAG(o)) { BIO_printf(bio_err, - "%s: Intermixed protocol flags (unix and internet domains)\n", - prog); + "%s: Intermixed protocol flags (unix and internet domains)\n", + prog); goto end; } if (connect_type == use_inet && IS_UNIX_FLAG(o)) { BIO_printf(bio_err, - "%s: Intermixed protocol flags (internet and unix domains)\n", - prog); + "%s: Intermixed protocol flags (internet and unix domains)\n", + prog); goto end; } + + if (IS_PROT_FLAG(o) && ++prot_opt > 1) { + BIO_printf(bio_err, "Cannot supply multiple protocol flags\n"); + goto end; + } + if (IS_NO_PROT_FLAG(o)) + no_prot_opt++; + if (prot_opt == 1 && no_prot_opt) { + BIO_printf(bio_err, + "Cannot supply both a protocol flag and '-no_'\n"); + goto end; + } + switch (o) { case OPT_EOF: case OPT_ERR: @@ -958,9 +972,9 @@ int s_client_main(int argc, char **argv) break; case OPT_VERIFY: verify = SSL_VERIFY_PEER; - verify_depth = atoi(opt_arg()); + verify_args.depth = atoi(opt_arg()); if (!c_quiet) - BIO_printf(bio_err, "verify depth is %d\n", verify_depth); + BIO_printf(bio_err, "verify depth is %d\n", verify_args.depth); break; case OPT_CERT: cert_file = opt_arg(); @@ -986,13 +1000,13 @@ int s_client_main(int argc, char **argv) goto opthelp; break; case OPT_VERIFY_RET_ERROR: - verify_return_error = 1; + verify_args.return_error = 1; break; case OPT_VERIFY_QUIET: - verify_quiet = 1; + verify_args.quiet = 1; break; case OPT_BRIEF: - c_brief = verify_quiet = c_quiet = 1; + c_brief = verify_args.quiet = c_quiet = 1; break; case OPT_S_CASES: if (ssl_args == NULL) @@ -1056,7 +1070,9 @@ int s_client_main(int argc, char **argv) c_tlsextdebug = 1; break; case OPT_STATUS: +#ifndef OPENSSL_NO_OCSP c_status_req = 1; +#endif break; case OPT_WDEBUG: #ifdef WATT32 @@ -1186,7 +1202,7 @@ int s_client_main(int argc, char **argv) fallback_scsv = 1; break; case OPT_KEYFORM: - if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &key_format)) + if (!opt_format(opt_arg(), OPT_FMT_PDE, &key_format)) goto opthelp; break; case OPT_PASS: @@ -1251,6 +1267,9 @@ int s_client_main(int argc, char **argv) goto end; } break; + case OPT_DANE_EE_NO_NAME: + dane_ee_no_name = 1; + break; case OPT_NEXTPROTONEG: #ifndef OPENSSL_NO_NEXTPROTONEG next_proto_neg_in = opt_arg(); @@ -1329,8 +1348,8 @@ int s_client_main(int argc, char **argv) if (tmp_port != port) OPENSSL_free(tmp_port); if (!res) { - BIO_printf(bio_err, "%s: -proxy argument malformed or ambiguous\n", - prog); + BIO_printf(bio_err, + "%s: -proxy argument malformed or ambiguous\n", prog); goto end; } } else { @@ -1469,8 +1488,8 @@ int s_client_main(int argc, char **argv) if (SSL_CTX_config(ctx, ssl_config) == 0) { BIO_printf(bio_err, "Error using configuration \"%s\"\n", ssl_config); - ERR_print_errors(bio_err); - goto end; + ERR_print_errors(bio_err); + goto end; } } @@ -1523,8 +1542,7 @@ int s_client_main(int argc, char **argv) #ifndef OPENSSL_NO_PSK if (psk_key != NULL) { if (c_debug) - BIO_printf(bio_c_out, - "PSK key given, setting client callback\n"); + BIO_printf(bio_c_out, "PSK key given, setting client callback\n"); SSL_CTX_set_psk_client_callback(ctx, psk_client_cb); } #endif @@ -1556,7 +1574,7 @@ int s_client_main(int argc, char **argv) } /* Returns 0 on success! */ if (SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len) != 0) { - BIO_printf(bio_err, "Error setting ALPN\n"); + BIO_printf(bio_err, "Error setting ALPN\n"); goto end; } OPENSSL_free(alpn); @@ -1568,8 +1586,8 @@ int s_client_main(int argc, char **argv) NULL, NULL, NULL, serverinfo_cli_parse_cb, NULL)) { BIO_printf(bio_err, - "Warning: Unable to add custom extension %u, skipping\n", - serverinfo_types[i]); + "Warning: Unable to add custom extension %u, skipping\n", + serverinfo_types[i]); } } @@ -1637,7 +1655,8 @@ int s_client_main(int argc, char **argv) if (dane_tlsa_domain != NULL) { if (SSL_CTX_dane_enable(ctx) <= 0) { BIO_printf(bio_err, - "%s: Error enabling DANE TLSA authentication.\n", prog); + "%s: Error enabling DANE TLSA authentication.\n", + prog); ERR_print_errors(bio_err); goto end; } @@ -1687,7 +1706,7 @@ int s_client_main(int argc, char **argv) } if (dane_tlsa_rrset == NULL) { BIO_printf(bio_err, "%s: DANE TLSA authentication requires at " - "least one -dane_tlsa_rrset option.\n", prog); + "least one -dane_tlsa_rrdata option.\n", prog); goto end; } if (tlsa_import_rrset(con, dane_tlsa_rrset) <= 0) { @@ -1695,6 +1714,8 @@ int s_client_main(int argc, char **argv) "records.\n", prog); goto end; } + if (dane_ee_no_name) + SSL_dane_set_flags(con, DANE_FLAG_NO_DANE_EE_NAMECHECKS); } else if (dane_tlsa_rrset != NULL) { BIO_printf(bio_err, "%s: DANE TLSA authentication requires the " "-dane_tlsa_domain option.\n", prog); @@ -1702,8 +1723,7 @@ int s_client_main(int argc, char **argv) } re_start: - if (init_client(&s, host, port, socket_family, socket_type) == 0) - { + if (init_client(&s, host, port, socket_family, socket_type) == 0) { BIO_printf(bio_err, "connect:errno=%d\n", get_last_socket_error()); BIO_closesocket(s); goto end; @@ -1719,18 +1739,25 @@ int s_client_main(int argc, char **argv) } #ifndef OPENSSL_NO_DTLS if (socket_type == SOCK_DGRAM) { - struct sockaddr peer; - int peerlen = sizeof peer; + union BIO_sock_info_u peer_info; sbio = BIO_new_dgram(s, BIO_NOCLOSE); - if (getsockname(s, &peer, (void *)&peerlen) < 0) { + if ((peer_info.addr = BIO_ADDR_new()) == NULL) { + BIO_printf(bio_err, "memory allocation failure\n"); + BIO_closesocket(s); + goto end; + } + if (!BIO_sock_info(s, BIO_SOCK_INFO_ADDRESS, &peer_info)) { BIO_printf(bio_err, "getsockname:errno=%d\n", get_last_socket_error()); + BIO_ADDR_free(peer_info.addr); BIO_closesocket(s); goto end; } - (void)BIO_ctrl_set_connected(sbio, &peer); + (void)BIO_ctrl_set_connected(sbio, peer_info.addr); + BIO_ADDR_free(peer_info.addr); + peer_info.addr = NULL; if (enable_timeouts) { timeout.tv_sec = 0; @@ -1799,7 +1826,10 @@ int s_client_main(int argc, char **argv) SSL_set_connect_state(con); /* ok, lets connect */ - width = SSL_get_fd(con) + 1; + if (fileno_stdin() > SSL_get_fd(con)) + width = fileno_stdin() + 1; + else + width = SSL_get_fd(con) + 1; read_tty = 1; write_tty = 0; @@ -2128,9 +2158,11 @@ int s_client_main(int argc, char **argv) * set the flag so we exit. */ if (read_tty && !at_eof) - openssl_fdset(fileno(stdin), &readfds); + openssl_fdset(fileno_stdin(), &readfds); +#if !defined(OPENSSL_SYS_VMS) if (write_tty) - openssl_fdset(fileno(stdout), &writefds); + openssl_fdset(fileno_stdout(), &writefds); +#endif } if (read_ssl) openssl_fdset(SSL_get_fd(con), &readfds); @@ -2256,11 +2288,11 @@ int s_client_main(int argc, char **argv) goto shut; } } -#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VMS) /* Assume Windows/DOS/BeOS can always write */ else if (!ssl_pending && write_tty) #else - else if (!ssl_pending && FD_ISSET(fileno(stdout), &writefds)) + else if (!ssl_pending && FD_ISSET(fileno_stdout(), &writefds)) #endif { #ifdef CHARSET_EBCDIC @@ -2349,7 +2381,7 @@ int s_client_main(int argc, char **argv) #if defined(OPENSSL_SYS_MSDOS) else if (has_stdin_waiting()) #else - else if (FD_ISSET(fileno(stdin), &readfds)) + else if (FD_ISSET(fileno_stdin(), &readfds)) #endif { if (crlf) { @@ -2372,9 +2404,10 @@ int s_client_main(int argc, char **argv) assert(lf_num == 0); } else i = raw_read_stdin(cbuf, BUFSIZZ); - +#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) if (i == 0) at_eof = 1; +#endif if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q' && cmdletters))) { BIO_printf(bio_err, "DONE\n"); @@ -2441,6 +2474,7 @@ int s_client_main(int argc, char **argv) #ifndef OPENSSL_NO_SRP OPENSSL_free(srp_arg.srppassin); #endif + OPENSSL_free(connectstr); OPENSSL_free(host); OPENSSL_free(port); X509_VERIFY_PARAM_free(vpm); @@ -2451,6 +2485,7 @@ int s_client_main(int argc, char **argv) OPENSSL_clear_free(cbuf, BUFSIZZ); OPENSSL_clear_free(sbuf, BUFSIZZ); OPENSSL_clear_free(mbuf, BUFSIZZ); + release_engine(e); BIO_free(bio_c_out); bio_c_out = NULL; BIO_free(bio_c_msg); @@ -2560,7 +2595,8 @@ static void print_stuff(BIO *bio, SSL *s, int full) #endif BIO_printf(bio, - "---\nSSL handshake has read %"PRIu64" bytes and written %"PRIu64" bytes\n", + "---\nSSL handshake has read %" PRIu64 + " bytes and written %" PRIu64 " bytes\n", BIO_number_read(SSL_get_rbio(s)), BIO_number_written(SSL_get_wbio(s))); } @@ -2591,11 +2627,15 @@ static void print_stuff(BIO *bio, SSL *s, int full) { /* Print out local port of connection: useful for debugging */ int sock; - struct sockaddr_in ladd; - socklen_t ladd_size = sizeof(ladd); + union BIO_sock_info_u info; + sock = SSL_get_fd(s); - getsockname(sock, (struct sockaddr *)&ladd, &ladd_size); - BIO_printf(bio_c_out, "LOCAL PORT is %u\n", ntohs(ladd.sin_port)); + if ((info.addr = BIO_ADDR_new()) != NULL + && BIO_sock_info(sock, BIO_SOCK_INFO_ADDRESS, &info)) { + BIO_printf(bio_c_out, "LOCAL PORT is %u\n", + ntohs(BIO_ADDR_rawport(info.addr))); + } + BIO_ADDR_free(info.addr); } #endif @@ -2633,7 +2673,7 @@ static void print_stuff(BIO *bio, SSL *s, int full) #endif SSL_SESSION_print(bio, SSL_get_session(s)); - if (keymatexportlabel != NULL) { + if (SSL_get_session(s) != NULL && keymatexportlabel != NULL) { BIO_printf(bio, "Keying material exporter:\n"); BIO_printf(bio, " Label: '%s'\n", keymatexportlabel); BIO_printf(bio, " Length: %i bytes\n", keymatexportlen); @@ -2684,4 +2724,4 @@ static int ocsp_resp_cb(SSL *s, void *arg) } # endif -#endif /* OPENSSL_NO_SOCK */ +#endif /* OPENSSL_NO_SOCK */