Blame tests/eagain-auto-auth.c

Packit aea12f
/*
Packit aea12f
 * Copyright (C) 2008-2012 Free Software Foundation, Inc.
Packit aea12f
 * Copyright (C) 2018 Red Hat, Inc.
Packit aea12f
 *
Packit aea12f
 * Author: Simon Josefsson, Nikos Mavrogiannopoulos
Packit aea12f
 *
Packit aea12f
 * This file is part of GnuTLS.
Packit aea12f
 *
Packit aea12f
 * GnuTLS is free software; you can redistribute it and/or modify it
Packit aea12f
 * under the terms of the GNU General Public License as published by
Packit aea12f
 * the Free Software Foundation; either version 3 of the License, or
Packit aea12f
 * (at your option) any later version.
Packit aea12f
 *
Packit aea12f
 * GnuTLS is distributed in the hope that it will be useful, but
Packit aea12f
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit aea12f
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit aea12f
 * General Public License for more details.
Packit aea12f
 *
Packit aea12f
 * You should have received a copy of the GNU Lesser General Public License
Packit aea12f
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
Packit aea12f
 */
Packit aea12f
Packit aea12f
#ifdef HAVE_CONFIG_H
Packit aea12f
#include <config.h>
Packit aea12f
#endif
Packit aea12f
Packit aea12f
#include <stdio.h>
Packit aea12f
#include <stdlib.h>
Packit aea12f
#include <string.h>
Packit aea12f
#include <errno.h>
Packit aea12f
#include <gnutls/gnutls.h>
Packit aea12f
#include <gnutls/crypto.h>
Packit aea12f
#include <gnutls/abstract.h>
Packit aea12f
Packit aea12f
#define RANDOMIZE
Packit aea12f
#include "cert-common.h"
Packit aea12f
#include "cmocka-common.h"
Packit aea12f
Packit aea12f
/* This tests operation under non-blocking mode in TLS1.2/TLS1.3
Packit aea12f
 * rekey/rehandshake.
Packit aea12f
 */
Packit aea12f
static void tls_log_func(int level, const char *str)
Packit aea12f
{
Packit aea12f
	fprintf(stderr, "<%d>| %s", level, str);
Packit aea12f
}
Packit aea12f
Packit aea12f
#define MAX_BUF 1024
Packit aea12f
#define MSG "Hello TLS, and hi and how are you and more data here... and more... and even more and even more more data..."
Packit aea12f
Packit aea12f
static unsigned int cert_asked = 0;
Packit aea12f
Packit aea12f
static int cert_callback(gnutls_session_t session,
Packit aea12f
			 const gnutls_datum_t * req_ca_rdn, int nreqs,
Packit aea12f
			 const gnutls_pk_algorithm_t * sign_algos,
Packit aea12f
			 int sign_algos_length, gnutls_pcert_st ** pcert,
Packit aea12f
			 unsigned int *pcert_length, gnutls_privkey_t * pkey)
Packit aea12f
{
Packit aea12f
	cert_asked = 1;
Packit aea12f
	*pcert_length = 0;
Packit aea12f
	*pcert = NULL;
Packit aea12f
	*pkey = NULL;
Packit aea12f
Packit aea12f
	return 0;
Packit aea12f
}
Packit aea12f
Packit aea12f
static void async_handshake(void **glob_state, const char *prio, unsigned rehsk)
Packit aea12f
{
Packit aea12f
	/* Server stuff. */
Packit aea12f
	gnutls_certificate_credentials_t serverx509cred;
Packit aea12f
	gnutls_session_t server;
Packit aea12f
	int sret, cret;
Packit aea12f
	/* Client stuff. */
Packit aea12f
	gnutls_certificate_credentials_t clientx509cred;
Packit aea12f
	gnutls_session_t client;
Packit aea12f
	/* Need to enable anonymous KX specifically. */
Packit aea12f
	char buffer[MAX_BUF + 1];
Packit aea12f
	int ret, transferred = 0, msglen;
Packit aea12f
Packit aea12f
	/* General init. */
Packit aea12f
	reset_buffers();
Packit aea12f
	cert_asked = 0;
Packit aea12f
	gnutls_global_init();
Packit aea12f
	gnutls_global_set_log_function(tls_log_func);
Packit aea12f
Packit aea12f
	/* Init server */
Packit aea12f
	assert_return_code(gnutls_certificate_allocate_credentials(&serverx509cred), 0);
Packit aea12f
	assert_return_code(gnutls_certificate_set_x509_key_mem(serverx509cred,
Packit aea12f
					    &server_cert, &server_key,
Packit aea12f
					    GNUTLS_X509_FMT_PEM), 0);
Packit aea12f
	ret = gnutls_init(&server, GNUTLS_SERVER|GNUTLS_POST_HANDSHAKE_AUTH);
Packit aea12f
	assert_return_code(ret, 0);
Packit aea12f
Packit aea12f
	ret =
Packit aea12f
	    gnutls_priority_set_direct(server,
Packit aea12f
					prio,
Packit aea12f
					NULL);
Packit aea12f
	assert_return_code(ret, 0);
Packit aea12f
Packit aea12f
Packit aea12f
	ret = gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, serverx509cred);
Packit aea12f
	assert_return_code(ret, 0);
Packit aea12f
Packit aea12f
	gnutls_transport_set_push_function(server, server_push);
Packit aea12f
	gnutls_transport_set_pull_function(server, server_pull);
Packit aea12f
	gnutls_transport_set_ptr(server, server);
Packit aea12f
Packit aea12f
	/* Init client */
Packit aea12f
Packit aea12f
	ret = gnutls_certificate_allocate_credentials(&clientx509cred);
Packit aea12f
	assert_return_code(ret, 0);
Packit aea12f
Packit aea12f
	gnutls_certificate_set_retrieve_function2(clientx509cred, cert_callback);
Packit aea12f
Packit aea12f
	ret = gnutls_init(&client, GNUTLS_CLIENT|GNUTLS_AUTO_REAUTH|GNUTLS_POST_HANDSHAKE_AUTH);
Packit aea12f
	ret =
Packit aea12f
	    gnutls_priority_set_direct(client,
Packit aea12f
					prio,
Packit aea12f
					NULL);
Packit aea12f
	assert_return_code(ret, 0);
Packit aea12f
Packit aea12f
	ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred);
Packit aea12f
	assert_return_code(ret, 0);
Packit aea12f
Packit aea12f
	gnutls_transport_set_push_function(client, client_push);
Packit aea12f
	gnutls_transport_set_pull_function(client, client_pull);
Packit aea12f
	gnutls_transport_set_ptr(client, client);
Packit aea12f
Packit aea12f
	HANDSHAKE(client, server);
Packit aea12f
Packit aea12f
	if (rehsk == 1) {
Packit aea12f
		char b[1];
Packit aea12f
		unsigned hstarted = 0;
Packit aea12f
Packit aea12f
		do {
Packit aea12f
			sret = gnutls_rehandshake(server);
Packit aea12f
		} while (sret == GNUTLS_E_AGAIN || sret == GNUTLS_E_INTERRUPTED);
Packit aea12f
		assert_true(sret == 0);
Packit aea12f
		assert_true(gnutls_record_get_direction(server)==1);
Packit aea12f
Packit aea12f
		sret = cret = GNUTLS_E_AGAIN;
Packit aea12f
		do {
Packit aea12f
			if (!hstarted) {
Packit aea12f
				sret = gnutls_record_recv(server, b, 1);
Packit aea12f
				if (sret == GNUTLS_E_INTERRUPTED) sret = GNUTLS_E_AGAIN;
Packit aea12f
Packit aea12f
				if (sret == GNUTLS_E_REHANDSHAKE) {
Packit aea12f
					hstarted = 1;
Packit aea12f
					sret = GNUTLS_E_AGAIN;
Packit aea12f
				}
Packit aea12f
				assert_true(sret == GNUTLS_E_AGAIN);
Packit aea12f
			}
Packit aea12f
Packit aea12f
			if (sret == GNUTLS_E_AGAIN && hstarted) {
Packit aea12f
				sret = gnutls_handshake (server);
Packit aea12f
				if (sret == GNUTLS_E_INTERRUPTED) sret = GNUTLS_E_AGAIN;
Packit aea12f
				assert_true(sret == GNUTLS_E_AGAIN || sret == 0);
Packit aea12f
			}
Packit aea12f
Packit aea12f
			/* we are done in client side */
Packit aea12f
			if (hstarted && gnutls_record_get_direction(client) == 0 && to_client_len == 0)
Packit aea12f
				cret = 0;
Packit aea12f
Packit aea12f
			if (cret == GNUTLS_E_AGAIN) {
Packit aea12f
				cret = gnutls_record_recv(client, b, 1);
Packit aea12f
				if (cret == GNUTLS_E_INTERRUPTED) cret = GNUTLS_E_AGAIN;
Packit aea12f
			}
Packit aea12f
			assert_true(cret == GNUTLS_E_AGAIN || cret >= 0);
Packit aea12f
Packit aea12f
		} while (cret == GNUTLS_E_AGAIN || sret == GNUTLS_E_AGAIN);
Packit aea12f
		assert_true(hstarted != 0);
Packit aea12f
	} else {
Packit aea12f
		char b[1];
Packit aea12f
Packit aea12f
		gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUEST);
Packit aea12f
Packit aea12f
		do {
Packit aea12f
			sret = gnutls_reauth(server, 0);
Packit aea12f
		} while (sret == GNUTLS_E_INTERRUPTED);
Packit aea12f
Packit aea12f
		assert_true(sret == GNUTLS_E_AGAIN || sret >= 0);
Packit aea12f
Packit aea12f
		cret = GNUTLS_E_AGAIN;
Packit aea12f
		do {
Packit aea12f
			if (cret == GNUTLS_E_AGAIN) {
Packit aea12f
				cret = gnutls_record_recv(client, b, 1);
Packit aea12f
				if (cret == GNUTLS_E_INTERRUPTED) cret = GNUTLS_E_AGAIN;
Packit aea12f
			}
Packit aea12f
Packit aea12f
			if (sret == GNUTLS_E_AGAIN) {
Packit aea12f
				sret = gnutls_reauth(server, 0);
Packit aea12f
				if (sret == GNUTLS_E_INTERRUPTED) sret = GNUTLS_E_AGAIN;
Packit aea12f
			}
Packit aea12f
Packit aea12f
			/* we are done in client side */
Packit aea12f
			if (gnutls_record_get_direction(client) == 0 && to_client_len == 0)
Packit aea12f
				cret = 0;
Packit aea12f
		} while (cret == GNUTLS_E_AGAIN || sret == GNUTLS_E_AGAIN);
Packit aea12f
	}
Packit aea12f
	assert_return_code(cret, 0);
Packit aea12f
	assert_return_code(sret, 0);
Packit aea12f
	assert_return_code(cert_asked, 1);
Packit aea12f
Packit aea12f
	msglen = strlen(MSG);
Packit aea12f
	TRANSFER(client, server, MSG, msglen, buffer, MAX_BUF);
Packit aea12f
Packit aea12f
	assert_true(gnutls_bye(client, GNUTLS_SHUT_WR)>=0);
Packit aea12f
	assert_true(gnutls_bye(server, GNUTLS_SHUT_WR)>=0);
Packit aea12f
Packit aea12f
	gnutls_deinit(client);
Packit aea12f
	gnutls_deinit(server);
Packit aea12f
Packit aea12f
	gnutls_certificate_free_credentials(serverx509cred);
Packit aea12f
	gnutls_certificate_free_credentials(clientx509cred);
Packit aea12f
Packit aea12f
	gnutls_global_deinit();
Packit aea12f
}
Packit aea12f
Packit aea12f
static void tls12_async_handshake(void **glob_state)
Packit aea12f
{
Packit aea12f
	async_handshake(glob_state, "NORMAL:-VERS-ALL:+VERS-TLS1.2", 1);
Packit aea12f
}
Packit aea12f
Packit aea12f
static void tls13_async_handshake(void **glob_state)
Packit aea12f
{
Packit aea12f
	async_handshake(glob_state, "NORMAL:-VERS-ALL:+VERS-TLS1.3", 0);
Packit aea12f
}
Packit aea12f
Packit aea12f
int main(void)
Packit aea12f
{
Packit aea12f
	const struct CMUnitTest tests[] = {
Packit aea12f
		cmocka_unit_test(tls12_async_handshake),
Packit aea12f
		cmocka_unit_test(tls13_async_handshake),
Packit aea12f
	};
Packit aea12f
	return cmocka_run_group_tests(tests, NULL, NULL);
Packit aea12f
}