Blame tests/eagain-auto-auth.c

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