Example #1
0
int swClient_enable_ssl_encrypt(swClient *cli)
{
    cli->ssl_context = swSSL_get_context(&cli->ssl_option);
    if (cli->ssl_context == NULL)
    {
        return SW_ERR;
    }

    if (cli->ssl_option.verify_peer)
    {
        if (swSSL_set_capath(&cli->ssl_option, cli->ssl_context) < 0)
        {
            return SW_ERR;
        }
    }

    cli->socket->ssl_send = 1;
#if defined(SW_USE_HTTP2) && defined(SW_USE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10002000L
    if (cli->http2)
    {
        if (SSL_CTX_set_alpn_protos(cli->ssl_context, (const unsigned char *) "\x02h2", 3) < 0)
        {
            return SW_ERR;
        }
    }
#endif
    return SW_OK;
}
Example #2
0
bool SSLContext::setRandomizedAdvertisedNextProtocols(
    const std::list<NextProtocolsItem>& items, NextProtocolType protocolType) {
  unsetNextProtocols();
  if (items.size() == 0) {
    return false;
  }
  int total_weight = 0;
  for (const auto &item : items) {
    if (item.protocols.size() == 0) {
      continue;
    }
    AdvertisedNextProtocolsItem advertised_item;
    advertised_item.length = 0;
    for (const auto& proto : item.protocols) {
      ++advertised_item.length;
      unsigned protoLength = proto.length();
      if (protoLength >= 256) {
        deleteNextProtocolsStrings();
        return false;
      }
      advertised_item.length += protoLength;
    }
    advertised_item.protocols = new unsigned char[advertised_item.length];
    if (!advertised_item.protocols) {
      throw std::runtime_error("alloc failure");
    }
    unsigned char* dst = advertised_item.protocols;
    for (auto& proto : item.protocols) {
      unsigned protoLength = proto.length();
      *dst++ = (unsigned char)protoLength;
      memcpy(dst, proto.data(), protoLength);
      dst += protoLength;
    }
    total_weight += item.weight;
    advertisedNextProtocols_.push_back(advertised_item);
    advertisedNextProtocolWeights_.push_back(item.weight);
  }
  if (total_weight == 0) {
    deleteNextProtocolsStrings();
    return false;
  }
  nextProtocolDistribution_ =
      std::discrete_distribution<>(advertisedNextProtocolWeights_.begin(),
                                   advertisedNextProtocolWeights_.end());
  if ((uint8_t)protocolType & (uint8_t)NextProtocolType::NPN) {
    SSL_CTX_set_next_protos_advertised_cb(
        ctx_, advertisedNextProtocolCallback, this);
    SSL_CTX_set_next_proto_select_cb(ctx_, selectNextProtocolCallback, this);
  }
#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(OPENSSL_NO_TLSEXT)
  if ((uint8_t)protocolType & (uint8_t)NextProtocolType::ALPN) {
    SSL_CTX_set_alpn_select_cb(ctx_, alpnSelectCallback, this);
    // Client cannot really use randomized alpn
    SSL_CTX_set_alpn_protos(ctx_,
                            advertisedNextProtocols_[0].protocols,
                            advertisedNextProtocols_[0].length);
  }
#endif
  return true;
}
Example #3
0
void SSLContext::unsetNextProtocols() {
  deleteNextProtocolsStrings();
  SSL_CTX_set_next_protos_advertised_cb(ctx_, nullptr, nullptr);
  SSL_CTX_set_next_proto_select_cb(ctx_, nullptr, nullptr);
#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(OPENSSL_NO_TLSEXT)
  SSL_CTX_set_alpn_select_cb(ctx_, nullptr, nullptr);
  SSL_CTX_set_alpn_protos(ctx_, nullptr, 0);
#endif
}
Example #4
0
extern "C" int32_t CryptoNative_SslCtxSetAlpnProtos(SSL_CTX* ctx, const uint8_t* protos, uint32_t protos_len)
{
#ifdef HAVE_OPENSSL_ALPN
    if (API_EXISTS(SSL_CTX_set_alpn_protos))
    {
        return SSL_CTX_set_alpn_protos(ctx, protos, protos_len);
    }
    else
#endif
    {
        return 0;
    }
}
Example #5
0
int
tls_configure_ssl(struct tls *ctx, SSL_CTX *ssl_ctx)
{
	SSL_CTX_set_mode(ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
	SSL_CTX_set_mode(ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

	SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2);
	SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv3);

	SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1);
	SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1_1);
	SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1_2);

	if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_0) == 0)
		SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1);
	if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_1) == 0)
		SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_1);
	if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_2) == 0)
		SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_2);

	if (ctx->config->alpn != NULL) {
		if (SSL_CTX_set_alpn_protos(ssl_ctx, ctx->config->alpn,
		    ctx->config->alpn_len) != 0) {
			tls_set_errorx(ctx, "failed to set alpn");
			goto err;
		}
	}

	if (ctx->config->ciphers != NULL) {
		if (SSL_CTX_set_cipher_list(ssl_ctx,
		    ctx->config->ciphers) != 1) {
			tls_set_errorx(ctx, "failed to set ciphers");
			goto err;
		}
	}

	if (ctx->config->verify_time == 0) {
		X509_VERIFY_PARAM_set_flags(ssl_ctx->param,
		    X509_V_FLAG_NO_CHECK_TIME);
	}

	/* Disable any form of session caching by default */
	SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_OFF);
	SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TICKET);

	return (0);

 err:
	return (-1);
}
Example #6
0
int swClient_enable_ssl_encrypt(swClient *cli)
{
    cli->ssl_context = swSSL_get_context(cli->ssl_method, cli->ssl_cert_file, cli->ssl_key_file);
    if (cli->ssl_context == NULL)
    {
        return SW_ERR;
    }
    cli->socket->ssl_send = 1;
#if defined(SW_USE_HTTP2) && defined(SW_USE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10002000L
    if (cli->http2)
    {
        if (SSL_CTX_set_alpn_protos(cli->ssl_context, (const unsigned char *) "\x02h2", 3) < 0)
        {
            return SW_ERR;
        }
    }
#endif
    return SW_OK;
}
Example #7
0
/* Create SSL_CTX. */
static SSL_CTX *create_ssl_ctx(void) {
  SSL_CTX *ssl_ctx;
  ssl_ctx = SSL_CTX_new(SSLv23_client_method());
  if (!ssl_ctx) {
    errx(1, "Could not create SSL/TLS context: %s",
         ERR_error_string(ERR_get_error(), NULL));
  }
  SSL_CTX_set_options(ssl_ctx,
                      SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
                          SSL_OP_NO_COMPRESSION |
                          SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
#ifndef OPENSSL_NO_NEXTPROTONEG
  SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
#endif /* !OPENSSL_NO_NEXTPROTONEG */

#if OPENSSL_VERSION_NUMBER >= 0x10002000L
  SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */

  return ssl_ctx;
}
Example #8
0
/*
 * Configure callbacks and other properties that can't be set directly
 * in the server/client CONF.
 */
static void configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
                                    SSL_CTX *client_ctx,
                                    const SSL_TEST_CTX *test_ctx,
                                    CTX_DATA *server_ctx_data,
                                    CTX_DATA *server2_ctx_data,
                                    CTX_DATA *client_ctx_data)
{
    unsigned char *ticket_keys;
    size_t ticket_key_len;

    switch (test_ctx->client_verify_callback) {
    case SSL_TEST_VERIFY_ACCEPT_ALL:
        SSL_CTX_set_cert_verify_callback(client_ctx, &verify_accept_cb,
                                         NULL);
        break;
    case SSL_TEST_VERIFY_REJECT_ALL:
        SSL_CTX_set_cert_verify_callback(client_ctx, &verify_reject_cb,
                                         NULL);
        break;
    default:
        break;
    }

    /* link the two contexts for SNI purposes */
    switch (test_ctx->servername_callback) {
    case SSL_TEST_SERVERNAME_IGNORE_MISMATCH:
        SSL_CTX_set_tlsext_servername_callback(server_ctx, servername_ignore_cb);
        SSL_CTX_set_tlsext_servername_arg(server_ctx, server2_ctx);
        break;
    case SSL_TEST_SERVERNAME_REJECT_MISMATCH:
        SSL_CTX_set_tlsext_servername_callback(server_ctx, servername_reject_cb);
        SSL_CTX_set_tlsext_servername_arg(server_ctx, server2_ctx);
        break;
    default:
        break;
    }

    /*
     * The initial_ctx/session_ctx always handles the encrypt/decrypt of the
     * session ticket. This ticket_key callback is assigned to the second
     * session (assigned via SNI), and should never be invoked
     */
    if (server2_ctx != NULL)
        SSL_CTX_set_tlsext_ticket_key_cb(server2_ctx,
                                         do_not_call_session_ticket_cb);

    if (test_ctx->session_ticket_expected == SSL_TEST_SESSION_TICKET_BROKEN) {
        SSL_CTX_set_tlsext_ticket_key_cb(server_ctx, broken_session_ticket_cb);
    }
    if (test_ctx->server_npn_protocols != NULL) {
        parse_protos(test_ctx->server_npn_protocols,
                     &server_ctx_data->npn_protocols,
                     &server_ctx_data->npn_protocols_len);
        SSL_CTX_set_next_protos_advertised_cb(server_ctx, server_npn_cb,
                                              server_ctx_data);
    }
    if (test_ctx->server2_npn_protocols != NULL) {
        parse_protos(test_ctx->server2_npn_protocols,
                     &server2_ctx_data->npn_protocols,
                     &server2_ctx_data->npn_protocols_len);
        OPENSSL_assert(server2_ctx != NULL);
        SSL_CTX_set_next_protos_advertised_cb(server2_ctx, server_npn_cb,
                                              server2_ctx_data);
    }
    if (test_ctx->client_npn_protocols != NULL) {
        parse_protos(test_ctx->client_npn_protocols,
                     &client_ctx_data->npn_protocols,
                     &client_ctx_data->npn_protocols_len);
        SSL_CTX_set_next_proto_select_cb(client_ctx, client_npn_cb,
                                         client_ctx_data);
    }
    if (test_ctx->server_alpn_protocols != NULL) {
        parse_protos(test_ctx->server_alpn_protocols,
                     &server_ctx_data->alpn_protocols,
                     &server_ctx_data->alpn_protocols_len);
        SSL_CTX_set_alpn_select_cb(server_ctx, server_alpn_cb, server_ctx_data);
    }
    if (test_ctx->server2_alpn_protocols != NULL) {
        OPENSSL_assert(server2_ctx != NULL);
        parse_protos(test_ctx->server2_alpn_protocols,
                     &server2_ctx_data->alpn_protocols,
                     &server2_ctx_data->alpn_protocols_len);
        SSL_CTX_set_alpn_select_cb(server2_ctx, server_alpn_cb, server2_ctx_data);
    }
    if (test_ctx->client_alpn_protocols != NULL) {
        unsigned char *alpn_protos = NULL;
        size_t alpn_protos_len;
        parse_protos(test_ctx->client_alpn_protocols,
                     &alpn_protos, &alpn_protos_len);
        /* Reversed return value convention... */
        OPENSSL_assert(SSL_CTX_set_alpn_protos(client_ctx, alpn_protos,
                                               alpn_protos_len) == 0);
        OPENSSL_free(alpn_protos);
    }
    /*
     * Use fixed session ticket keys so that we can decrypt a ticket created with
     * one CTX in another CTX. Don't address server2 for the moment.
     */
    ticket_key_len = SSL_CTX_set_tlsext_ticket_keys(server_ctx, NULL, 0);
    ticket_keys = OPENSSL_zalloc(ticket_key_len);
    OPENSSL_assert(ticket_keys != NULL);
    OPENSSL_assert(SSL_CTX_set_tlsext_ticket_keys(server_ctx, ticket_keys,
                                                  ticket_key_len) == 1);
    OPENSSL_free(ticket_keys);
}
Example #9
0
int
s_client_main(int argc, char **argv)
{
	unsigned int off = 0, clr = 0;
	SSL *con = NULL;
	int s, k, state = 0, af = AF_UNSPEC;
	char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL;
	int cbuf_len, cbuf_off;
	int sbuf_len, sbuf_off;
	char *port = PORT_STR;
	int full_log = 1;
	char *host = SSL_HOST_NAME;
	char *xmpphost = NULL;
	char *proxy = NULL, *connect = NULL;
	char *cert_file = NULL, *key_file = NULL;
	int cert_format = FORMAT_PEM, key_format = FORMAT_PEM;
	char *passarg = NULL, *pass = NULL;
	X509 *cert = NULL;
	EVP_PKEY *key = NULL;
	char *CApath = NULL, *CAfile = NULL, *cipher = NULL;
	int reconnect = 0, badop = 0, verify = SSL_VERIFY_NONE, bugs = 0;
	int crlf = 0;
	int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending;
	SSL_CTX *ctx = NULL;
	int ret = 1, in_init = 1, i, nbio_test = 0;
	int starttls_proto = PROTO_OFF;
	int prexit = 0;
	X509_VERIFY_PARAM *vpm = NULL;
	int badarg = 0;
	const SSL_METHOD *meth = NULL;
	int socket_type = SOCK_STREAM;
	BIO *sbio;
	int mbuf_len = 0;
	struct timeval timeout;
	const char *errstr = NULL;
	char *servername = NULL;
	tlsextctx tlsextcbp =
	{NULL, 0};
	const char *next_proto_neg_in = NULL;
	const char *alpn_in = NULL;
	char *sess_in = NULL;
	char *sess_out = NULL;
	struct sockaddr peer;
	int peerlen = sizeof(peer);
	int enable_timeouts = 0;
	long socket_mtu = 0;

	meth = SSLv23_client_method();

	c_Pause = 0;
	c_quiet = 0;
	c_ign_eof = 0;
	c_debug = 0;
	c_msg = 0;
	c_showcerts = 0;

	if (((cbuf = malloc(BUFSIZZ)) == NULL) ||
	    ((sbuf = malloc(BUFSIZZ)) == NULL) ||
	    ((mbuf = malloc(BUFSIZZ + 1)) == NULL)) {	/* NUL byte */
		BIO_printf(bio_err, "out of memory\n");
		goto end;
	}
	verify_depth = 0;
	c_nbio = 0;

	argc--;
	argv++;
	while (argc >= 1) {
		if (strcmp(*argv, "-host") == 0) {
			if (--argc < 1)
				goto bad;
			host = *(++argv);
		} else if (strcmp(*argv, "-port") == 0) {
			if (--argc < 1)
				goto bad;
			port = *(++argv);
			if (port == NULL || *port == '\0')
				goto bad;
		} else if (strcmp(*argv, "-connect") == 0) {
			if (--argc < 1)
				goto bad;
			connect = *(++argv);
		} else if (strcmp(*argv, "-proxy") == 0) {
			if (--argc < 1)
				goto bad;
			proxy = *(++argv);
		} else if (strcmp(*argv,"-xmpphost") == 0) {
			if (--argc < 1)
				goto bad;
			xmpphost= *(++argv);
		} else if (strcmp(*argv, "-verify") == 0) {
			verify = SSL_VERIFY_PEER;
			if (--argc < 1)
				goto bad;
			verify_depth = strtonum(*(++argv), 0, INT_MAX, &errstr);
			if (errstr)
				goto bad;
			BIO_printf(bio_err, "verify depth is %d\n", verify_depth);
		} else if (strcmp(*argv, "-cert") == 0) {
			if (--argc < 1)
				goto bad;
			cert_file = *(++argv);
		} else if (strcmp(*argv, "-sess_out") == 0) {
			if (--argc < 1)
				goto bad;
			sess_out = *(++argv);
		} else if (strcmp(*argv, "-sess_in") == 0) {
			if (--argc < 1)
				goto bad;
			sess_in = *(++argv);
		} else if (strcmp(*argv, "-certform") == 0) {
			if (--argc < 1)
				goto bad;
			cert_format = str2fmt(*(++argv));
		} else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) {
			if (badarg)
				goto bad;
			continue;
		} else if (strcmp(*argv, "-verify_return_error") == 0)
			verify_return_error = 1;
		else if (strcmp(*argv, "-prexit") == 0)
			prexit = 1;
		else if (strcmp(*argv, "-crlf") == 0)
			crlf = 1;
		else if (strcmp(*argv, "-quiet") == 0) {
			c_quiet = 1;
			c_ign_eof = 1;
		} else if (strcmp(*argv, "-ign_eof") == 0)
			c_ign_eof = 1;
		else if (strcmp(*argv, "-no_ign_eof") == 0)
			c_ign_eof = 0;
		else if (strcmp(*argv, "-pause") == 0)
			c_Pause = 1;
		else if (strcmp(*argv, "-debug") == 0)
			c_debug = 1;
		else if (strcmp(*argv, "-tlsextdebug") == 0)
			c_tlsextdebug = 1;
		else if (strcmp(*argv, "-status") == 0)
			c_status_req = 1;
		else if (strcmp(*argv, "-msg") == 0)
			c_msg = 1;
		else if (strcmp(*argv, "-showcerts") == 0)
			c_showcerts = 1;
		else if (strcmp(*argv, "-nbio_test") == 0)
			nbio_test = 1;
		else if (strcmp(*argv, "-state") == 0)
			state = 1;
		else if (strcmp(*argv, "-tls1_2") == 0)
			meth = TLSv1_2_client_method();
		else if (strcmp(*argv, "-tls1_1") == 0)
			meth = TLSv1_1_client_method();
		else if (strcmp(*argv, "-tls1") == 0)
			meth = TLSv1_client_method();
#ifndef OPENSSL_NO_DTLS1
		else if (strcmp(*argv, "-dtls1") == 0) {
			meth = DTLSv1_client_method();
			socket_type = SOCK_DGRAM;
		} else if (strcmp(*argv, "-timeout") == 0)
			enable_timeouts = 1;
		else if (strcmp(*argv, "-mtu") == 0) {
			if (--argc < 1)
				goto bad;
			socket_mtu = strtonum(*(++argv), 0, LONG_MAX, &errstr);
			if (errstr)
				goto bad;
		}
#endif
		else if (strcmp(*argv, "-bugs") == 0)
			bugs = 1;
		else if (strcmp(*argv, "-keyform") == 0) {
			if (--argc < 1)
				goto bad;
			key_format = str2fmt(*(++argv));
		} else if (strcmp(*argv, "-pass") == 0) {
			if (--argc < 1)
				goto bad;
			passarg = *(++argv);
		} else if (strcmp(*argv, "-key") == 0) {
			if (--argc < 1)
				goto bad;
			key_file = *(++argv);
		} else if (strcmp(*argv, "-reconnect") == 0) {
			reconnect = 5;
		} else if (strcmp(*argv, "-CApath") == 0) {
			if (--argc < 1)
				goto bad;
			CApath = *(++argv);
		} else if (strcmp(*argv, "-CAfile") == 0) {
			if (--argc < 1)
				goto bad;
			CAfile = *(++argv);
		} else if (strcmp(*argv, "-no_tls1_2") == 0)
			off |= SSL_OP_NO_TLSv1_2;
		else if (strcmp(*argv, "-no_tls1_1") == 0)
			off |= SSL_OP_NO_TLSv1_1;
		else if (strcmp(*argv, "-no_tls1") == 0)
			off |= SSL_OP_NO_TLSv1;
		else if (strcmp(*argv, "-no_ssl3") == 0)
			off |= SSL_OP_NO_SSLv3;
		else if (strcmp(*argv, "-no_ssl2") == 0)
			off |= SSL_OP_NO_SSLv2;
		else if (strcmp(*argv, "-no_comp") == 0) {
			off |= SSL_OP_NO_COMPRESSION;
		}
		else if (strcmp(*argv, "-no_ticket") == 0) {
			off |= SSL_OP_NO_TICKET;
		}
		else if (strcmp(*argv, "-nextprotoneg") == 0) {
			if (--argc < 1)
				goto bad;
			next_proto_neg_in = *(++argv);
		}
		else if (strcmp(*argv, "-alpn") == 0) {
			if (--argc < 1)
				goto bad;
			alpn_in = *(++argv);
		} else if (strcmp(*argv, "-serverpref") == 0)
			off |= SSL_OP_CIPHER_SERVER_PREFERENCE;
		else if (strcmp(*argv, "-legacy_renegotiation") == 0)
			; /* no-op */
		else if (strcmp(*argv, "-legacy_server_connect") == 0) {
			off |= SSL_OP_LEGACY_SERVER_CONNECT;
		} else if (strcmp(*argv, "-no_legacy_server_connect") == 0) {
			clr |= SSL_OP_LEGACY_SERVER_CONNECT;
		} else if (strcmp(*argv, "-cipher") == 0) {
			if (--argc < 1)
				goto bad;
			cipher = *(++argv);
		}
		else if (strcmp(*argv, "-nbio") == 0) {
			c_nbio = 1;
		}
		else if (strcmp(*argv, "-starttls") == 0) {
			if (--argc < 1)
				goto bad;
			++argv;
			if (strcmp(*argv, "smtp") == 0)
				starttls_proto = PROTO_SMTP;
			else if (strcmp(*argv, "lmtp") == 0)
				starttls_proto = PROTO_LMTP;
			else if (strcmp(*argv, "pop3") == 0)
				starttls_proto = PROTO_POP3;
			else if (strcmp(*argv, "imap") == 0)
				starttls_proto = PROTO_IMAP;
			else if (strcmp(*argv, "ftp") == 0)
				starttls_proto = PROTO_FTP;
			else if (strcmp(*argv, "xmpp") == 0)
				starttls_proto = PROTO_XMPP;
			else
				goto bad;
		}
		else if (strcmp(*argv, "-4") == 0) {
			af = AF_INET;
		} else if (strcmp(*argv, "-6") == 0) {
			af = AF_INET6;
		}
		else if (strcmp(*argv, "-servername") == 0) {
			if (--argc < 1)
				goto bad;
			servername = *(++argv);
			/* meth=TLSv1_client_method(); */
		}
#ifndef OPENSSL_NO_SRTP
		else if (strcmp(*argv, "-use_srtp") == 0) {
			if (--argc < 1)
				goto bad;
			srtp_profiles = *(++argv);
		}
#endif
		else if (strcmp(*argv, "-keymatexport") == 0) {
			if (--argc < 1)
				goto bad;
			keymatexportlabel = *(++argv);
		} else if (strcmp(*argv, "-keymatexportlen") == 0) {
			if (--argc < 1)
				goto bad;
			keymatexportlen = strtonum(*(++argv), 1, INT_MAX, &errstr);
			if (errstr)
				goto bad;
		} else {
			BIO_printf(bio_err, "unknown option %s\n", *argv);
			badop = 1;
			break;
		}
		argc--;
		argv++;
	}
	if (proxy != NULL) {
		if (!extract_host_port(proxy, &host, NULL, &port))
			goto bad;
		if (connect == NULL)
			connect = SSL_HOST_NAME;
	} else if (connect != NULL) {
		if (!extract_host_port(connect, &host, NULL, &port))
			goto bad;
	}
	if (badop) {
bad:
		if (errstr)
			BIO_printf(bio_err, "invalid argument %s: %s\n",
			    *argv, errstr);
		else
			sc_usage();
		goto end;
	}

	next_proto.status = -1;
	if (next_proto_neg_in) {
		next_proto.data = next_protos_parse(&next_proto.len, next_proto_neg_in);
		if (next_proto.data == NULL) {
			BIO_printf(bio_err, "Error parsing -nextprotoneg argument\n");
			goto end;
		}
	} else
		next_proto.data = NULL;

	if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) {
		BIO_printf(bio_err, "Error getting password\n");
		goto end;
	}
	if (key_file == NULL)
		key_file = cert_file;


	if (key_file) {

		key = load_key(bio_err, key_file, key_format, 0, pass,
		    "client certificate private key file");
		if (!key) {
			ERR_print_errors(bio_err);
			goto end;
		}
	}
	if (cert_file) {
		cert = load_cert(bio_err, cert_file, cert_format,
		    NULL, "client certificate file");

		if (!cert) {
			ERR_print_errors(bio_err);
			goto end;
		}
	}
	if (bio_c_out == NULL) {
		if (c_quiet && !c_debug && !c_msg) {
			bio_c_out = BIO_new(BIO_s_null());
		} else {
			if (bio_c_out == NULL)
				bio_c_out = BIO_new_fp(stdout, BIO_NOCLOSE);
		}
	}

	ctx = SSL_CTX_new(meth);
	if (ctx == NULL) {
		ERR_print_errors(bio_err);
		goto end;
	}
	if (vpm)
		SSL_CTX_set1_param(ctx, vpm);

#ifndef OPENSSL_NO_SRTP
	if (srtp_profiles != NULL)
		SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles);
#endif
	if (bugs)
		SSL_CTX_set_options(ctx, SSL_OP_ALL | off);
	else
		SSL_CTX_set_options(ctx, off);

	if (clr)
		SSL_CTX_clear_options(ctx, clr);
	/*
	 * DTLS: partial reads end up discarding unread UDP bytes :-( Setting
	 * read ahead solves this problem.
	 */
	if (socket_type == SOCK_DGRAM)
		SSL_CTX_set_read_ahead(ctx, 1);

	if (next_proto.data)
		SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto);
	if (alpn_in) {
		unsigned short alpn_len;
		unsigned char *alpn = next_protos_parse(&alpn_len, alpn_in);

		if (alpn == NULL) {
			BIO_printf(bio_err, "Error parsing -alpn argument\n");
			goto end;
		}
		SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len);
		free(alpn);
	}

	if (state)
		SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
	if (cipher != NULL)
		if (!SSL_CTX_set_cipher_list(ctx, cipher)) {
			BIO_printf(bio_err, "error setting cipher list\n");
			ERR_print_errors(bio_err);
			goto end;
		}

	SSL_CTX_set_verify(ctx, verify, verify_callback);
	if (!set_cert_key_stuff(ctx, cert, key))
		goto end;

	if ((!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) ||
	    (!SSL_CTX_set_default_verify_paths(ctx))) {
		/*
		 * BIO_printf(bio_err,"error setting default verify
		 * locations\n");
		 */
		ERR_print_errors(bio_err);
		/* goto end; */
	}
	if (servername != NULL) {
		tlsextcbp.biodebug = bio_err;
		SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
		SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
	}

	con = SSL_new(ctx);
	if (sess_in) {
		SSL_SESSION *sess;
		BIO *stmp = BIO_new_file(sess_in, "r");
		if (!stmp) {
			BIO_printf(bio_err, "Can't open session file %s\n",
			    sess_in);
			ERR_print_errors(bio_err);
			goto end;
		}
		sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL);
		BIO_free(stmp);
		if (!sess) {
			BIO_printf(bio_err, "Can't open session file %s\n",
			    sess_in);
			ERR_print_errors(bio_err);
			goto end;
		}
		SSL_set_session(con, sess);
		SSL_SESSION_free(sess);
	}
	if (servername != NULL) {
		if (!SSL_set_tlsext_host_name(con, servername)) {
			BIO_printf(bio_err, "Unable to set TLS servername extension.\n");
			ERR_print_errors(bio_err);
			goto end;
		}
	}
/*	SSL_set_cipher_list(con,"RC4-MD5"); */

re_start:

	if (init_client(&s, host, port, socket_type, af) == 0) {
		BIO_printf(bio_err, "connect:errno=%d\n", errno);
		goto end;
	}
	BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s);

	if (c_nbio) {
		if (!c_quiet)
			BIO_printf(bio_c_out, "turning on non blocking io\n");
		if (!BIO_socket_nbio(s, 1)) {
			ERR_print_errors(bio_err);
			goto end;
		}
	}
	if (c_Pause & 0x01)
		SSL_set_debug(con, 1);

	if (SSL_version(con) == DTLS1_VERSION) {

		sbio = BIO_new_dgram(s, BIO_NOCLOSE);
		if (getsockname(s, &peer, (void *) &peerlen) < 0) {
			BIO_printf(bio_err, "getsockname:errno=%d\n",
			    errno);
			shutdown(s, SHUT_RD);
			close(s);
			goto end;
		}
		(void) BIO_ctrl_set_connected(sbio, 1, &peer);

		if (enable_timeouts) {
			timeout.tv_sec = 0;
			timeout.tv_usec = DGRAM_RCV_TIMEOUT;
			BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);

			timeout.tv_sec = 0;
			timeout.tv_usec = DGRAM_SND_TIMEOUT;
			BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout);
		}
		if (socket_mtu > 28) {
			SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
			SSL_set_mtu(con, socket_mtu - 28);
		} else
			/* want to do MTU discovery */
			BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);
	} else
		sbio = BIO_new_socket(s, BIO_NOCLOSE);

	if (nbio_test) {
		BIO *test;

		test = BIO_new(BIO_f_nbio_test());
		sbio = BIO_push(test, sbio);
	}
	if (c_debug) {
		SSL_set_debug(con, 1);
		BIO_set_callback(sbio, bio_dump_callback);
		BIO_set_callback_arg(sbio, (char *) bio_c_out);
	}
	if (c_msg) {
		SSL_set_msg_callback(con, msg_cb);
		SSL_set_msg_callback_arg(con, bio_c_out);
	}
	if (c_tlsextdebug) {
		SSL_set_tlsext_debug_callback(con, tlsext_cb);
		SSL_set_tlsext_debug_arg(con, bio_c_out);
	}
	if (c_status_req) {
		SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp);
		SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb);
		SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out);
	}

	SSL_set_bio(con, sbio, sbio);
	SSL_set_connect_state(con);

	/* ok, lets connect */
	read_tty = 1;
	write_tty = 0;
	tty_on = 0;
	read_ssl = 1;
	write_ssl = 1;

	cbuf_len = 0;
	cbuf_off = 0;
	sbuf_len = 0;
	sbuf_off = 0;

	/* This is an ugly hack that does a lot of assumptions */
	/*
	 * We do have to handle multi-line responses which may come in a
	 * single packet or not. We therefore have to use BIO_gets() which
	 * does need a buffering BIO. So during the initial chitchat we do
	 * push a buffering BIO into the chain that is removed again later on
	 * to not disturb the rest of the s_client operation.
	 */
	if (starttls_proto == PROTO_SMTP || starttls_proto == PROTO_LMTP) {
		int foundit = 0;
		BIO *fbio = BIO_new(BIO_f_buffer());
		BIO_push(fbio, sbio);
		/* wait for multi-line response to end from SMTP */
		do {
			mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
		}
		while (mbuf_len > 3 && mbuf[3] == '-');
		/* STARTTLS command requires EHLO... */
		BIO_printf(fbio, "%cHLO openssl.client.net\r\n",
			   starttls_proto == PROTO_SMTP ? 'E' : 'L');
		(void) BIO_flush(fbio);
		/* wait for multi-line response to end EHLO SMTP response */
		do {
			mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
			if (strstr(mbuf, "STARTTLS"))
				foundit = 1;
		}
		while (mbuf_len > 3 && mbuf[3] == '-');
		(void) BIO_flush(fbio);
		BIO_pop(fbio);
		BIO_free(fbio);
		if (!foundit)
			BIO_printf(bio_err,
			    "didn't found starttls in server response,"
			    " try anyway...\n");
		BIO_printf(sbio, "STARTTLS\r\n");
		BIO_read(sbio, sbuf, BUFSIZZ);
	} else if (starttls_proto == PROTO_POP3) {
		mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
		if (mbuf_len == -1) {
			BIO_printf(bio_err, "BIO_read failed\n");
			goto end;
		}
		BIO_printf(sbio, "STLS\r\n");
		BIO_read(sbio, sbuf, BUFSIZZ);
	} else if (starttls_proto == PROTO_IMAP) {
		int foundit = 0;
		BIO *fbio = BIO_new(BIO_f_buffer());
		BIO_push(fbio, sbio);
		BIO_gets(fbio, mbuf, BUFSIZZ);
		/* STARTTLS command requires CAPABILITY... */
		BIO_printf(fbio, ". CAPABILITY\r\n");
		(void) BIO_flush(fbio);
		/* wait for multi-line CAPABILITY response */
		do {
			mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
			if (strstr(mbuf, "STARTTLS"))
				foundit = 1;
		}
		while (mbuf_len > 3 && mbuf[0] != '.');
		(void) BIO_flush(fbio);
		BIO_pop(fbio);
		BIO_free(fbio);
		if (!foundit)
			BIO_printf(bio_err,
			    "didn't found STARTTLS in server response,"
			    " try anyway...\n");
		BIO_printf(sbio, ". STARTTLS\r\n");
		BIO_read(sbio, sbuf, BUFSIZZ);
	} else if (starttls_proto == PROTO_FTP) {
		BIO *fbio = BIO_new(BIO_f_buffer());
		BIO_push(fbio, sbio);
		/* wait for multi-line response to end from FTP */
		do {
			mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
		}
		while (mbuf_len > 3 && mbuf[3] == '-');
		(void) BIO_flush(fbio);
		BIO_pop(fbio);
		BIO_free(fbio);
		BIO_printf(sbio, "AUTH TLS\r\n");
		BIO_read(sbio, sbuf, BUFSIZZ);
	} else if (starttls_proto == PROTO_XMPP) {
		int seen = 0;
		BIO_printf(sbio, "<stream:stream "
		    "xmlns:stream='http://etherx.jabber.org/streams' "
		    "xmlns='jabber:client' to='%s' version='1.0'>", xmpphost ? xmpphost : host);
		seen = BIO_read(sbio, mbuf, BUFSIZZ);

		if (seen <= 0)
			goto shut;

		mbuf[seen] = 0;
		while (!strstr(mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'") &&
		       !strstr(mbuf, "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"")) {
			seen = BIO_read(sbio, mbuf, BUFSIZZ);

			if (seen <= 0)
				goto shut;

			mbuf[seen] = 0;
		}
		BIO_printf(sbio, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
		seen = BIO_read(sbio, sbuf, BUFSIZZ);
		sbuf[seen] = 0;
		if (!strstr(sbuf, "<proceed"))
			goto shut;
		mbuf[0] = 0;
	} else if (proxy != NULL) {
		BIO_printf(sbio, "CONNECT %s HTTP/1.0\r\n\r\n", connect);
		mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
		if (mbuf_len == -1) {
			BIO_printf(bio_err, "BIO_read failed\n");
			goto end;
		}
	}
	for (;;) {
		struct pollfd pfd[3];	/* stdin, stdout, socket */
		int ptimeout = -1;

		if ((SSL_version(con) == DTLS1_VERSION) &&
		    DTLSv1_get_timeout(con, &timeout))
			ptimeout = timeout.tv_sec * 1000 + timeout.tv_usec / 1000;

		if (SSL_in_init(con) && !SSL_total_renegotiations(con)) {
			in_init = 1;
			tty_on = 0;
		} else {
			tty_on = 1;
			if (in_init) {
				in_init = 0;
				if (sess_out) {
					BIO *stmp = BIO_new_file(sess_out, "w");
					if (stmp) {
						PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con));
						BIO_free(stmp);
					} else
						BIO_printf(bio_err, "Error writing session file %s\n", sess_out);
				}
				print_stuff(bio_c_out, con, full_log);
				if (full_log > 0)
					full_log--;

				if (starttls_proto) {
					BIO_write(bio_err, mbuf, mbuf_len);
					/* We don't need to know any more */
					starttls_proto = PROTO_OFF;
				}
				if (reconnect) {
					reconnect--;
					BIO_printf(bio_c_out, "drop connection and then reconnect\n");
					SSL_shutdown(con);
					SSL_set_connect_state(con);
					shutdown(SSL_get_fd(con), SHUT_RD);
					close(SSL_get_fd(con));
					goto re_start;
				}
			}
		}

		ssl_pending = read_ssl && SSL_pending(con);

		pfd[0].fd = -1;
		pfd[1].fd = -1;
		if (!ssl_pending) {
			if (tty_on) {
				if (read_tty) {
					pfd[0].fd = fileno(stdin);
					pfd[0].events = POLLIN;
				}
				if (write_tty) {
					pfd[1].fd = fileno(stdout);
					pfd[1].events = POLLOUT;
				}
			}

			pfd[2].fd = SSL_get_fd(con);
			pfd[2].events = 0;
			if (read_ssl)
				pfd[2].events |= POLLIN;
			if (write_ssl)
				pfd[2].events |= POLLOUT;

/*			printf("mode tty(%d %d%d) ssl(%d%d)\n",
				tty_on,read_tty,write_tty,read_ssl,write_ssl);*/

			i = poll(pfd, 3, ptimeout);
			if (i < 0) {
				BIO_printf(bio_err, "bad select %d\n",
				    errno);
				goto shut;
				/* goto end; */
			}
		}
		if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_handle_timeout(con) > 0) {
			BIO_printf(bio_err, "TIMEOUT occured\n");
		}
		if (!ssl_pending && (pfd[2].revents & (POLLOUT|POLLERR|POLLNVAL))) {
			if (pfd[2].revents & (POLLERR|POLLNVAL)) {
				BIO_printf(bio_err, "poll error");
				goto shut;
			}
			k = SSL_write(con, &(cbuf[cbuf_off]),
			    (unsigned int) cbuf_len);
			switch (SSL_get_error(con, k)) {
			case SSL_ERROR_NONE:
				cbuf_off += k;
				cbuf_len -= k;
				if (k <= 0)
					goto end;
				/* we have done a  write(con,NULL,0); */
				if (cbuf_len <= 0) {
					read_tty = 1;
					write_ssl = 0;
				} else {	/* if (cbuf_len > 0) */
					read_tty = 0;
					write_ssl = 1;
				}
				break;
			case SSL_ERROR_WANT_WRITE:
				BIO_printf(bio_c_out, "write W BLOCK\n");
				write_ssl = 1;
				read_tty = 0;
				break;
			case SSL_ERROR_WANT_READ:
				BIO_printf(bio_c_out, "write R BLOCK\n");
				write_tty = 0;
				read_ssl = 1;
				write_ssl = 0;
				break;
			case SSL_ERROR_WANT_X509_LOOKUP:
				BIO_printf(bio_c_out, "write X BLOCK\n");
				break;
			case SSL_ERROR_ZERO_RETURN:
				if (cbuf_len != 0) {
					BIO_printf(bio_c_out, "shutdown\n");
					ret = 0;
					goto shut;
				} else {
					read_tty = 1;
					write_ssl = 0;
					break;
				}

			case SSL_ERROR_SYSCALL:
				if ((k != 0) || (cbuf_len != 0)) {
					BIO_printf(bio_err, "write:errno=%d\n",
					    errno);
					goto shut;
				} else {
					read_tty = 1;
					write_ssl = 0;
				}
				break;
			case SSL_ERROR_SSL:
				ERR_print_errors(bio_err);
				goto shut;
			}
		} else if (!ssl_pending &&
		    (pfd[1].revents & (POLLOUT|POLLERR|POLLNVAL))) {
			if (pfd[1].revents & (POLLERR|POLLNVAL)) {
				BIO_printf(bio_err, "poll error");
				goto shut;
			}
			i = write(fileno(stdout), &(sbuf[sbuf_off]), sbuf_len);

			if (i <= 0) {
				BIO_printf(bio_c_out, "DONE\n");
				ret = 0;
				goto shut;
				/* goto end; */
			}
			sbuf_len -= i;
			sbuf_off += i;
			if (sbuf_len <= 0) {
				read_ssl = 1;
				write_tty = 0;
			}
		} else if (ssl_pending || (pfd[2].revents & (POLLIN|POLLHUP))) {
#ifdef RENEG
			{
				static int iiii;
				if (++iiii == 52) {
					SSL_renegotiate(con);
					iiii = 0;
				}
			}
#endif
			k = SSL_read(con, sbuf, 1024 /* BUFSIZZ */ );

			switch (SSL_get_error(con, k)) {
			case SSL_ERROR_NONE:
				if (k <= 0)
					goto end;
				sbuf_off = 0;
				sbuf_len = k;

				read_ssl = 0;
				write_tty = 1;
				break;
			case SSL_ERROR_WANT_WRITE:
				BIO_printf(bio_c_out, "read W BLOCK\n");
				write_ssl = 1;
				read_tty = 0;
				break;
			case SSL_ERROR_WANT_READ:
				BIO_printf(bio_c_out, "read R BLOCK\n");
				write_tty = 0;
				read_ssl = 1;
				if ((read_tty == 0) && (write_ssl == 0))
					write_ssl = 1;
				break;
			case SSL_ERROR_WANT_X509_LOOKUP:
				BIO_printf(bio_c_out, "read X BLOCK\n");
				break;
			case SSL_ERROR_SYSCALL:
				ret = errno;
				BIO_printf(bio_err, "read:errno=%d\n", ret);
				goto shut;
			case SSL_ERROR_ZERO_RETURN:
				BIO_printf(bio_c_out, "closed\n");
				ret = 0;
				goto shut;
			case SSL_ERROR_SSL:
				ERR_print_errors(bio_err);
				goto shut;
				/* break; */
			}
		} else if (pfd[0].revents) {
			if (pfd[0].revents & (POLLERR|POLLNVAL)) {
				BIO_printf(bio_err, "poll error");
				goto shut;
			}
			if (crlf) {
				int j, lf_num;

				i = read(fileno(stdin), cbuf, BUFSIZZ / 2);
				lf_num = 0;
				/* both loops are skipped when i <= 0 */
				for (j = 0; j < i; j++)
					if (cbuf[j] == '\n')
						lf_num++;
				for (j = i - 1; j >= 0; j--) {
					cbuf[j + lf_num] = cbuf[j];
					if (cbuf[j] == '\n') {
						lf_num--;
						i++;
						cbuf[j + lf_num] = '\r';
					}
				}
				assert(lf_num == 0);
			} else
				i = read(fileno(stdin), cbuf, BUFSIZZ);

			if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q'))) {
				BIO_printf(bio_err, "DONE\n");
				ret = 0;
				goto shut;
			}
			if ((!c_ign_eof) && (cbuf[0] == 'R')) {
				BIO_printf(bio_err, "RENEGOTIATING\n");
				SSL_renegotiate(con);
				cbuf_len = 0;
			} else {
				cbuf_len = i;
				cbuf_off = 0;
			}

			write_ssl = 1;
			read_tty = 0;
		}
	}

	ret = 0;
shut:
	if (in_init)
		print_stuff(bio_c_out, con, full_log);
	SSL_shutdown(con);
	shutdown(SSL_get_fd(con), SHUT_RD);
	close(SSL_get_fd(con));
end:
	if (con != NULL) {
		if (prexit != 0)
			print_stuff(bio_c_out, con, 1);
		SSL_free(con);
	}
	free(next_proto.data);
	if (ctx != NULL)
		SSL_CTX_free(ctx);
	if (cert)
		X509_free(cert);
	if (key)
		EVP_PKEY_free(key);
	free(pass);
	if (vpm)
		X509_VERIFY_PARAM_free(vpm);
	if (cbuf != NULL) {
		explicit_bzero(cbuf, BUFSIZZ);
		free(cbuf);
	}
	if (sbuf != NULL) {
		explicit_bzero(sbuf, BUFSIZZ);
		free(sbuf);
	}
	if (mbuf != NULL) {
		explicit_bzero(mbuf, BUFSIZZ);
		free(mbuf);
	}
	if (bio_c_out != NULL) {
		BIO_free(bio_c_out);
		bio_c_out = NULL;
	}

	return (ret);
}
Example #10
0
static int test_client_hello(int currtest)
{
    SSL_CTX *ctx;
    SSL *con = NULL;
    BIO *rbio;
    BIO *wbio;
    long len;
    unsigned char *data;
    PACKET pkt = {0}, pkt2 = {0}, pkt3 = {0};
    char *dummytick = "Hello World!";
    unsigned int type = 0;
    int testresult = 0;
    size_t msglen;
    BIO *sessbio = NULL;
    SSL_SESSION *sess = NULL;

#ifdef OPENSSL_NO_TLS1_3
    if (currtest == TEST_ADD_PADDING_AND_PSK)
        return 1;
#endif

    /*
     * For each test set up an SSL_CTX and SSL and see what ClientHello gets
     * produced when we try to connect
     */
    ctx = SSL_CTX_new(TLS_method());
    if (!TEST_ptr(ctx))
        goto end;

    switch(currtest) {
    case TEST_SET_SESSION_TICK_DATA_VER_NEG:
        /* Testing for session tickets <= TLS1.2; not relevant for 1.3 */
        if (!TEST_true(SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)))
            goto end;
        break;

    case TEST_ADD_PADDING_AND_PSK:
    case TEST_ADD_PADDING:
    case TEST_PADDING_NOT_NEEDED:
        SSL_CTX_set_options(ctx, SSL_OP_TLSEXT_PADDING);
        /*
         * Add lots of ciphersuites so that the ClientHello is at least
         * F5_WORKAROUND_MIN_MSG_LEN bytes long - meaning padding will be
         * needed. Also add some dummy ALPN protocols in case we still don't
         * have enough.
         */
        if (currtest == TEST_ADD_PADDING
                && (!TEST_true(SSL_CTX_set_cipher_list(ctx, "ALL"))
                    || !TEST_false(SSL_CTX_set_alpn_protos(ctx,
                                               (unsigned char *)alpn_prots,
                                               sizeof(alpn_prots) - 1))))
            goto end;

        break;

    default:
        goto end;
    }

    con = SSL_new(ctx);
    if (!TEST_ptr(con))
        goto end;

    if (currtest == TEST_ADD_PADDING_AND_PSK) {
        sessbio = BIO_new_file(sessionfile, "r");
        if (!TEST_ptr(sessbio)) {
            TEST_info("Unable to open session.pem");
            goto end;
        }
        sess = PEM_read_bio_SSL_SESSION(sessbio, NULL, NULL, NULL);
        if (!TEST_ptr(sess)) {
            TEST_info("Unable to load SSL_SESSION");
            goto end;
        }
        /*
         * We reset the creation time so that we don't discard the session as
         * too old.
         */
        if (!TEST_true(SSL_SESSION_set_time(sess, time(NULL)))
                || !TEST_true(SSL_set_session(con, sess)))
            goto end;
    }

    rbio = BIO_new(BIO_s_mem());
    wbio = BIO_new(BIO_s_mem());
    if (!TEST_ptr(rbio)|| !TEST_ptr(wbio)) {
        BIO_free(rbio);
        BIO_free(wbio);
        goto end;
    }

    SSL_set_bio(con, rbio, wbio);
    SSL_set_connect_state(con);

    if (currtest == TEST_SET_SESSION_TICK_DATA_VER_NEG) {
        if (!TEST_true(SSL_set_session_ticket_ext(con, dummytick,
                                                  strlen(dummytick))))
            goto end;
    }

    if (!TEST_int_le(SSL_connect(con), 0)) {
        /* This shouldn't succeed because we don't have a server! */
        goto end;
    }

    len = BIO_get_mem_data(wbio, (char **)&data);
    if (!TEST_true(PACKET_buf_init(&pkt, data, len))
               /* Skip the record header */
            || !PACKET_forward(&pkt, SSL3_RT_HEADER_LENGTH))
        goto end;

    msglen = PACKET_remaining(&pkt);

    /* Skip the handshake message header */
    if (!TEST_true(PACKET_forward(&pkt, SSL3_HM_HEADER_LENGTH))
               /* Skip client version and random */
            || !TEST_true(PACKET_forward(&pkt, CLIENT_VERSION_LEN
                                               + SSL3_RANDOM_SIZE))
               /* Skip session id */
            || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2))
               /* Skip ciphers */
            || !TEST_true(PACKET_get_length_prefixed_2(&pkt, &pkt2))
               /* Skip compression */
            || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2))
               /* Extensions len */
            || !TEST_true(PACKET_as_length_prefixed_2(&pkt, &pkt2)))
        goto end;

    /* Loop through all extensions */
    while (PACKET_remaining(&pkt2)) {

        if (!TEST_true(PACKET_get_net_2(&pkt2, &type))
                || !TEST_true(PACKET_get_length_prefixed_2(&pkt2, &pkt3)))
            goto end;

        if (type == TLSEXT_TYPE_session_ticket) {
            if (currtest == TEST_SET_SESSION_TICK_DATA_VER_NEG) {
                if (TEST_true(PACKET_equal(&pkt3, dummytick,
                                           strlen(dummytick)))) {
                    /* Ticket data is as we expected */
                    testresult = 1;
                }
                goto end;
            }
        }
        if (type == TLSEXT_TYPE_padding) {
            if (!TEST_false(currtest == TEST_PADDING_NOT_NEEDED))
                goto end;
            else if (TEST_true(currtest == TEST_ADD_PADDING
                    || currtest == TEST_ADD_PADDING_AND_PSK))
                testresult = TEST_true(msglen == F5_WORKAROUND_MAX_MSG_LEN);
        }
    }

    if (currtest == TEST_PADDING_NOT_NEEDED)
        testresult = 1;

end:
    SSL_free(con);
    SSL_CTX_free(ctx);
    SSL_SESSION_free(sess);
    BIO_free(sessbio);

    return testresult;
}
Example #11
0
/*
 * Configure callbacks and other properties that can't be set directly
 * in the server/client CONF.
 */
static void configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
                                    SSL_CTX *client_ctx,
                                    const SSL_TEST_CTX *test,
                                    const SSL_TEST_EXTRA_CONF *extra,
                                    CTX_DATA *server_ctx_data,
                                    CTX_DATA *server2_ctx_data,
                                    CTX_DATA *client_ctx_data)
{
    unsigned char *ticket_keys;
    size_t ticket_key_len;

    TEST_check(SSL_CTX_set_max_send_fragment(server_ctx,
                                             test->max_fragment_size) == 1);
    if (server2_ctx != NULL) {
        TEST_check(SSL_CTX_set_max_send_fragment(server2_ctx,
                                                 test->max_fragment_size) == 1);
    }
    TEST_check(SSL_CTX_set_max_send_fragment(client_ctx,
                                             test->max_fragment_size) == 1);

    switch (extra->client.verify_callback) {
    case SSL_TEST_VERIFY_ACCEPT_ALL:
        SSL_CTX_set_cert_verify_callback(client_ctx, &verify_accept_cb,
                                         NULL);
        break;
    case SSL_TEST_VERIFY_REJECT_ALL:
        SSL_CTX_set_cert_verify_callback(client_ctx, &verify_reject_cb,
                                         NULL);
        break;
    default:
        break;
    }

    /* link the two contexts for SNI purposes */
    switch (extra->server.servername_callback) {
    case SSL_TEST_SERVERNAME_IGNORE_MISMATCH:
        SSL_CTX_set_tlsext_servername_callback(server_ctx, servername_ignore_cb);
        SSL_CTX_set_tlsext_servername_arg(server_ctx, server2_ctx);
        break;
    case SSL_TEST_SERVERNAME_REJECT_MISMATCH:
        SSL_CTX_set_tlsext_servername_callback(server_ctx, servername_reject_cb);
        SSL_CTX_set_tlsext_servername_arg(server_ctx, server2_ctx);
        break;
    default:
        break;
    }

    /*
     * The initial_ctx/session_ctx always handles the encrypt/decrypt of the
     * session ticket. This ticket_key callback is assigned to the second
     * session (assigned via SNI), and should never be invoked
     */
    if (server2_ctx != NULL)
        SSL_CTX_set_tlsext_ticket_key_cb(server2_ctx,
                                         do_not_call_session_ticket_cb);

    if (extra->server.broken_session_ticket) {
        SSL_CTX_set_tlsext_ticket_key_cb(server_ctx, broken_session_ticket_cb);
    }
#ifndef OPENSSL_NO_NEXTPROTONEG
    if (extra->server.npn_protocols != NULL) {
        parse_protos(extra->server.npn_protocols,
                     &server_ctx_data->npn_protocols,
                     &server_ctx_data->npn_protocols_len);
        SSL_CTX_set_next_protos_advertised_cb(server_ctx, server_npn_cb,
                                              server_ctx_data);
    }
    if (extra->server2.npn_protocols != NULL) {
        parse_protos(extra->server2.npn_protocols,
                     &server2_ctx_data->npn_protocols,
                     &server2_ctx_data->npn_protocols_len);
        TEST_check(server2_ctx != NULL);
        SSL_CTX_set_next_protos_advertised_cb(server2_ctx, server_npn_cb,
                                              server2_ctx_data);
    }
    if (extra->client.npn_protocols != NULL) {
        parse_protos(extra->client.npn_protocols,
                     &client_ctx_data->npn_protocols,
                     &client_ctx_data->npn_protocols_len);
        SSL_CTX_set_next_proto_select_cb(client_ctx, client_npn_cb,
                                         client_ctx_data);
    }
#endif
    if (extra->server.alpn_protocols != NULL) {
        parse_protos(extra->server.alpn_protocols,
                     &server_ctx_data->alpn_protocols,
                     &server_ctx_data->alpn_protocols_len);
        SSL_CTX_set_alpn_select_cb(server_ctx, server_alpn_cb, server_ctx_data);
    }
    if (extra->server2.alpn_protocols != NULL) {
        TEST_check(server2_ctx != NULL);
        parse_protos(extra->server2.alpn_protocols,
                     &server2_ctx_data->alpn_protocols,
                     &server2_ctx_data->alpn_protocols_len);
        SSL_CTX_set_alpn_select_cb(server2_ctx, server_alpn_cb, server2_ctx_data);
    }
    if (extra->client.alpn_protocols != NULL) {
        unsigned char *alpn_protos = NULL;
        size_t alpn_protos_len;
        parse_protos(extra->client.alpn_protocols,
                     &alpn_protos, &alpn_protos_len);
        /* Reversed return value convention... */
        TEST_check(SSL_CTX_set_alpn_protos(client_ctx, alpn_protos,
                                           alpn_protos_len) == 0);
        OPENSSL_free(alpn_protos);
    }

    /*
     * Use fixed session ticket keys so that we can decrypt a ticket created with
     * one CTX in another CTX. Don't address server2 for the moment.
     */
    ticket_key_len = SSL_CTX_set_tlsext_ticket_keys(server_ctx, NULL, 0);
    ticket_keys = OPENSSL_zalloc(ticket_key_len);
    TEST_check(ticket_keys != NULL);
    TEST_check(SSL_CTX_set_tlsext_ticket_keys(server_ctx, ticket_keys,
                                              ticket_key_len) == 1);
    OPENSSL_free(ticket_keys);

    /* The default log list includes EC keys, so CT can't work without EC. */
#if !defined(OPENSSL_NO_CT) && !defined(OPENSSL_NO_EC)
    TEST_check(SSL_CTX_set_default_ctlog_list_file(client_ctx));
    switch (extra->client.ct_validation) {
    case SSL_TEST_CT_VALIDATION_PERMISSIVE:
        TEST_check(SSL_CTX_enable_ct(client_ctx, SSL_CT_VALIDATION_PERMISSIVE));
        break;
    case SSL_TEST_CT_VALIDATION_STRICT:
        TEST_check(SSL_CTX_enable_ct(client_ctx, SSL_CT_VALIDATION_STRICT));
        break;
    case SSL_TEST_CT_VALIDATION_NONE:
        break;
    }
#endif
}
Example #12
0
// This test launches a gRPC server on a separate thread and then establishes a
// TLS handshake via a minimal TLS client. The TLS client has configurable (via
// alpn_list) ALPN settings and can probe at the supported ALPN preferences
// using this (via alpn_expected).
static bool server_ssl_test(const char *alpn_list[], unsigned int alpn_list_len,
                            const char *alpn_expected) {
  bool success = true;

  grpc_init();
  int port = grpc_pick_unused_port_or_die();
  gpr_event_init(&client_handshake_complete);

  // Launch the gRPC server thread.
  gpr_thd_options thdopt = gpr_thd_options_default();
  gpr_thd_id thdid;
  gpr_thd_options_set_joinable(&thdopt);
  GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &port, &thdopt));

  SSL_load_error_strings();
  OpenSSL_add_ssl_algorithms();

  const SSL_METHOD *method = TLSv1_2_client_method();
  SSL_CTX *ctx = SSL_CTX_new(method);
  if (!ctx) {
    perror("Unable to create SSL context");
    ERR_print_errors_fp(stderr);
    abort();
  }

  // Load key pair.
  if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) {
    ERR_print_errors_fp(stderr);
    abort();
  }
  if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) {
    ERR_print_errors_fp(stderr);
    abort();
  }

  // Set the cipher list to match the one expressed in
  // src/core/lib/tsi/ssl_transport_security.c.
  const char *cipher_list =
      "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-"
      "SHA384:ECDHE-RSA-AES256-GCM-SHA384";
  if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) {
    ERR_print_errors_fp(stderr);
    gpr_log(GPR_ERROR, "Couldn't set server cipher list.");
    abort();
  }

  // Configure ALPN list the client will send to the server. This must match the
  // wire format, see documentation for SSL_CTX_set_alpn_protos.
  unsigned int alpn_protos_len = alpn_list_len;
  for (unsigned int i = 0; i < alpn_list_len; ++i) {
    alpn_protos_len += (unsigned int)strlen(alpn_list[i]);
  }
  unsigned char *alpn_protos = gpr_malloc(alpn_protos_len);
  unsigned char *p = alpn_protos;
  for (unsigned int i = 0; i < alpn_list_len; ++i) {
    const uint8_t len = (uint8_t)strlen(alpn_list[i]);
    *p++ = len;
    memcpy(p, alpn_list[i], len);
    p += len;
  }
  GPR_ASSERT(SSL_CTX_set_alpn_protos(ctx, alpn_protos, alpn_protos_len) == 0);

  // Try and connect to server. We allow a bounded number of retries as we might
  // be racing with the server setup on its separate thread.
  int retries = 10;
  int sock = -1;
  while (sock == -1 && retries-- > 0) {
    sock = create_socket(port);
    if (sock < 0) {
      sleep(1);
    }
  }
  GPR_ASSERT(sock > 0);
  gpr_log(GPR_INFO, "Connected to server on port %d", port);

  // Establish a SSL* and connect at SSL layer.
  SSL *ssl = SSL_new(ctx);
  GPR_ASSERT(ssl);
  SSL_set_fd(ssl, sock);
  if (SSL_connect(ssl) <= 0) {
    ERR_print_errors_fp(stderr);
    gpr_log(GPR_ERROR, "Handshake failed.");
    success = false;
  } else {
    gpr_log(GPR_INFO, "Handshake successful.");
    // Validate ALPN preferred by server matches alpn_expected.
    const unsigned char *alpn_selected;
    unsigned int alpn_selected_len;
    SSL_get0_alpn_selected(ssl, &alpn_selected, &alpn_selected_len);
    if (strlen(alpn_expected) != alpn_selected_len ||
        strncmp((const char *)alpn_selected, alpn_expected,
                alpn_selected_len) != 0) {
      gpr_log(GPR_ERROR, "Unexpected ALPN protocol preference");
      success = false;
    }
  }
  gpr_event_set(&client_handshake_complete, &client_handshake_complete);

  SSL_free(ssl);
  gpr_free(alpn_protos);
  SSL_CTX_free(ctx);
  EVP_cleanup();
  close(sock);

  gpr_thd_join(thdid);

  grpc_shutdown();

  return success;
}