#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
} while (ret < 0);
}
-
#ifndef OPENSSL_NO_PSK
/* Default PSK identity and key */
static char *psk_identity = "Client_identity";
unsigned char *psk,
unsigned int max_psk_len)
{
- unsigned int psk_len = 0;
int ret;
- BIGNUM *bn = NULL;
+ long key_len;
+ unsigned char *key;
if (c_debug)
BIO_printf(bio_c_out, "psk_client_cb\n");
if (c_debug)
BIO_printf(bio_c_out, "created identity '%s' len=%d\n", identity,
ret);
- ret = BN_hex2bn(&bn, psk_key);
- if (!ret) {
- BIO_printf(bio_err, "Could not convert PSK key '%s' to BIGNUM\n",
+
+ /* convert the PSK key to binary */
+ key = OPENSSL_hexstr2buf(psk_key, &key_len);
+ if (key == NULL) {
+ BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n",
psk_key);
- BN_free(bn);
return 0;
}
-
- if ((unsigned int)BN_num_bytes(bn) > max_psk_len) {
+ if (key_len > max_psk_len) {
BIO_printf(bio_err,
- "psk buffer of callback is too small (%d) for key (%d)\n",
- max_psk_len, BN_num_bytes(bn));
- BN_free(bn);
+ "psk buffer of callback is too small (%d) for key (%ld)\n",
+ max_psk_len, key_len);
+ OPENSSL_free(key);
return 0;
}
- psk_len = BN_bn2bin(bn, psk);
- BN_free(bn);
- if (psk_len == 0)
- goto out_err;
+ memcpy(psk, key, key_len);
+ OPENSSL_free(key);
if (c_debug)
- BIO_printf(bio_c_out, "created PSK len=%d\n", psk_len);
+ BIO_printf(bio_c_out, "created PSK len=%ld\n", key_len);
- return psk_len;
+ return key_len;
out_err:
if (c_debug)
BIO_printf(bio_err, "Error in PSK client callback\n");
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) &&
{
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;
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,
#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[] = {
{"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"},
(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)
{
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;
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;
+ int at_eof = 0;
int read_buf_len = 0;
int fallback_scsv = 0;
long randamt = 0;
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, c_status_req = 0;
+ BIO *bio_c_msg = NULL;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
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) {
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);
/* 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_<prot>'\n");
goto end;
}
+
switch (o) {
case OPT_EOF:
case OPT_ERR:
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();
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)
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();
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 {
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;
}
}
#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
}
/* 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);
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]);
}
}
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;
}
}
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) {
"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);
}
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;
}
#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;
if (!ssl_pending) {
#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS)
if (tty_on) {
- if (read_tty)
+ /*
+ * Note that select() returns when read _would not block_,
+ * and EOF satisfies that. To avoid a CPU-hogging loop,
+ * set the flag so we exit.
+ */
+ if (read_tty && !at_eof)
openssl_fdset(fileno(stdin), &readfds);
if (write_tty)
openssl_fdset(fileno(stdout), &writefds);
} else
i = raw_read_stdin(cbuf, BUFSIZZ);
+ if (i == 0)
+ at_eof = 1;
+
if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q' && cmdletters))) {
BIO_printf(bio_err, "DONE\n");
ret = 0;
#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)));
}
{
/* 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
#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);
}
# endif
-#endif
+#endif /* OPENSSL_NO_SOCK */