int main()

in Tools/TlsClient/TlsClient.cpp [27:198]


int main(int argc, char* argv[])
{
	BOOL useChain;
	char dir[128], deviceCertChain[128], aliasKey[128], serverCA[128], aliasCert[128];;
	
	if (argc == 1) return Usage();
	if (argc > 3)return Usage();

	if (strcmp(argv[1], "B") == 0)
	{
		useChain = FALSE;
	}
	else
		if (strcmp(argv[1], "C")==0)
		{
			useChain = TRUE;
		}
		else
			return Usage();

	if (argc == 3) 
	{
		strcpy(dir, argv[2]);
	}
	else
	{
		strcpy(dir, ".");
	}

	//strcat(dir, "/");

	strcpy(aliasKey, dir);			strcat(aliasKey, "AliasKey.PEM");
	strcpy(deviceCertChain, dir);	strcat(deviceCertChain, "DeviceCertChainIncAlias.PEM");
	strcpy(serverCA, dir);			strcat(serverCA, "ServerCA.PEM");
	strcpy(aliasCert, dir);			strcat(aliasCert, "AliasCert.PEM");

	printf("Attempting to establish a TLS connection on localhost\n");


	long res = 1;
	int ret = 1;
	unsigned long ssl_err = 0;

	SSL_CTX* ctx = NULL;
	BIO *web = NULL, *out = NULL;
	SSL *ssl = NULL;

	do {
		// for interactive debugging
		Sleep(3000);

		init_openssl_library();
		const SSL_METHOD* method = SSLv23_method();
		CheckIsNotNull((void*) method, "SSLv23_method");

		ctx = SSL_CTX_new(method);
		CheckIsNotNull((void*)ctx, "SSL_CTX_new");

		SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);
		SSL_CTX_set_verify_depth(ctx, 10);


		/* Remove the most egregious. Because SSLv2 and SSLv3 have been      */
		/* removed, a TLSv1.0 handshake is used. The client accepts TLSv1.0  */
		/* and above. An added benefit of TLS 1.0 and above are TLS          */
		/* extensions like Server Name Indicatior (SNI).                     */
		const long flags = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
		long old_opts = SSL_CTX_set_options(ctx, flags);
		UNUSED(old_opts);

		// <PAUL> - the following three setup lines are the only substantive changes to the 
		// OSSL sample code
		res = SSL_CTX_use_PrivateKey_file(ctx, aliasKey, SSL_FILETYPE_PEM);
		CheckIsOne(res, "SSL_CTX_use_PrivateKey_file");
		if (useChain) 
		{
			res = SSL_CTX_use_certificate_chain_file(ctx, deviceCertChain);
			CheckIsOne(res, "SSL_CTX_use_certificate_chain_file");
		}
		else
		{
			res = SSL_CTX_use_certificate_chain_file(ctx, aliasCert);
			CheckIsOne(res, "SSL_CTX_use_certificate_chain_file");
		}
		res = SSL_CTX_load_verify_locations(ctx, serverCA, NULL);
		CheckIsOne(res, "SSL_CTX_load_verify_locations");
		// </PAUL>


		web = BIO_new_ssl_connect(ctx);
		CheckIsNotNull((void*)web, "BIO_new_ssl_connect");
		res = BIO_set_conn_hostname(web, "localhost:5556");
		CheckIsOne(res, "BIO_set_conn_hostname");
		BIO_get_ssl(web, &ssl);
		res = SSL_set_cipher_list(ssl, PREFERRED_CIPHERS);
		CheckIsOne(res, "SSL_set_cipher_list");
		res = SSL_set_tlsext_host_name(ssl, HOST_NAME);
		CheckIsOne(res, "SSL_set_tlsext_host_name");
		res = BIO_do_connect(web);
		CheckIsOne(res, "BIO_do_connect");
		res = BIO_do_handshake(web);
		CheckIsOne(res, "BIO_do_handshake");


		X509* cert = SSL_get_peer_certificate(ssl);
		if (cert) { X509_free(cert); } /* Free immediately */
		CheckIsNotNull(cert, "SSL_get_peer_certificate");
		/* Error codes: http://www.openssl.org/docs/apps/verify.html  */
		res = SSL_get_verify_result(ssl);

		ASSERT(X509_V_OK == res);
		if (!(X509_V_OK == res))
		{
			/* Hack a code into print_error_string. */
			print_error_string((unsigned long)res, "SSL_get_verify_results");
			break; /* failed */
		}



		/* Step 3: hostname verifcation.   */
		/* An exercise left to the reader. */

		/**************************************************************************************/
		/**************************************************************************************/
		/* Now, we can finally start reading and writing to the BIO...                        */
		/**************************************************************************************/
		/**************************************************************************************/

		printf("Connection was successful.  Terminating");


		BIO_puts(web, "GET " HOST_RESOURCE " HTTP/1.1\r\nHost: " HOST_NAME "\r\nConnection: close\r\n\r\n");
		BIO_puts(out, "\nFetching: " HOST_RESOURCE "\n\n");

#ifdef USE_CONNECTION
		int len = 0;
		do {
			char buff[1536] = {};

			/* https://www.openssl.org/docs/crypto/BIO_read.html */
			len = BIO_read(web, buff, sizeof(buff));

			if (len > 0)
				BIO_write(out, buff, len);

			/* BIO_should_retry returns TRUE unless there's an  */
			/* error. We expect an error when the server        */
			/* provides the response and closes the connection. */

		} while (len > 0 || BIO_should_retry(web));
#endif

		ret = 0;

	} while (0);

	if (out)
		BIO_free(out);

	if (web != NULL)
		BIO_free_all(web);

	if (NULL != ctx)
		SSL_CTX_free(ctx);

	// for interactive debugging
	Sleep(3000);


	return ret;
}