Blame tests/mini-dtls-record.c

Packit Service 4684c1
/*
Packit Service 4684c1
 * Copyright (C) 2012-2013 Free Software Foundation, Inc.
Packit Service 4684c1
 * Copyright (C) 2013 Nikos Mavrogiannopoulos
Packit Service 4684c1
 *
Packit Service 4684c1
 * Author: 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 General Public License
Packit Service 4684c1
 * along with GnuTLS; if not, write to the Free Software Foundation,
Packit Service 4684c1
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
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
Packit Service 4684c1
#if defined(_WIN32)
Packit Service 4684c1
Packit Service 4684c1
int main()
Packit Service 4684c1
{
Packit Service 4684c1
	exit(77);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
#else
Packit Service 4684c1
Packit Service 4684c1
#include <string.h>
Packit Service 4684c1
#include <errno.h>
Packit Service 4684c1
#include <sys/types.h>
Packit Service 4684c1
#include <netinet/in.h>
Packit Service 4684c1
#include <sys/socket.h>
Packit Service 4684c1
#include <sys/wait.h>
Packit Service 4684c1
#include <arpa/inet.h>
Packit Service 4684c1
#include <unistd.h>
Packit Service 4684c1
#include <signal.h>
Packit Service 4684c1
#include <gnutls/gnutls.h>
Packit Service 4684c1
#include <gnutls/dtls.h>
Packit Service 4684c1
Packit Service 4684c1
#include "utils.h"
Packit Service 4684c1
Packit Service 4684c1
static int test_finished = 0;
Packit Service 4684c1
static void terminate(void);
Packit Service 4684c1
Packit Service 4684c1
/* This program tests whether messages in DTLS are received
Packit Service 4684c1
 * with the expected sequence. That is whether the message
Packit Service 4684c1
 * sequence numbers returned correspond to the received messages.
Packit Service 4684c1
 */
Packit Service 4684c1
Packit Service 4684c1
/*
Packit Service 4684c1
static void
Packit Service 4684c1
tls_audit_log_func (gnutls_session_t session, const char *str)
Packit Service 4684c1
{
Packit Service 4684c1
  fprintf (stderr, "|<%p>| %s", session, str);
Packit Service 4684c1
}
Packit Service 4684c1
*/
Packit Service 4684c1
Packit Service 4684c1
static void server_log_func(int level, const char *str)
Packit Service 4684c1
{
Packit Service 4684c1
	fprintf(stderr, "server|<%d>| %s", level, str);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
static void client_log_func(int level, const char *str)
Packit Service 4684c1
{
Packit Service 4684c1
	fprintf(stderr, "client|<%d>| %s", level, str);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* These are global */
Packit Service 4684c1
static pid_t child;
Packit Service 4684c1
Packit Service 4684c1
/* A test client/server app for DTLS duplicate packet detection.
Packit Service 4684c1
 */
Packit Service 4684c1
Packit Service 4684c1
#define MAX_BUF 1024
Packit Service 4684c1
Packit Service 4684c1
#define MAX_SEQ 128
Packit Service 4684c1
Packit Service 4684c1
static int msg_seq[] =
Packit Service 4684c1
    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 16, 5, 32, 11, 11, 11, 11, 12,
Packit Service 4684c1
	10, 13, 14, 15, 16, 17, 19, 20, 18, 22, 24, 23, 25, 26, 27, 29, 28,
Packit Service 4684c1
	29, 29, 30, 31, 32, 33, 34, 35, 37, 36, 38, 39, 42, 37, 40, 41, 41,
Packit Service 4684c1
	-1
Packit Service 4684c1
};
Packit Service 4684c1
Packit Service 4684c1
static unsigned int current = 0;
Packit Service 4684c1
static unsigned int pos = 0;
Packit Service 4684c1
Packit Service 4684c1
unsigned char *stored_messages[MAX_SEQ];
Packit Service 4684c1
unsigned int stored_sizes[MAX_SEQ];
Packit Service 4684c1
Packit Service 4684c1
static ssize_t odd_push(gnutls_transport_ptr_t tr, const void *data, size_t len)
Packit Service 4684c1
{
Packit Service 4684c1
	ssize_t ret;
Packit Service 4684c1
	unsigned i;
Packit Service 4684c1
Packit Service 4684c1
	if (msg_seq[current] == -1 || test_finished != 0) {
Packit Service 4684c1
		test_finished = 1;
Packit Service 4684c1
		return len;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	stored_messages[current] = malloc(len);
Packit Service 4684c1
	memcpy(stored_messages[current], data, len);
Packit Service 4684c1
	stored_sizes[current] = len;
Packit Service 4684c1
Packit Service 4684c1
	if (pos != current) {
Packit Service 4684c1
		for (i = pos; i <= current; i++) {
Packit Service 4684c1
			if (stored_messages[msg_seq[i]] != NULL) {
Packit Service 4684c1
				do {
Packit Service 4684c1
					ret =
Packit Service 4684c1
					    send((long int)tr,
Packit Service 4684c1
						 stored_messages[msg_seq
Packit Service 4684c1
								 [i]],
Packit Service 4684c1
						 stored_sizes[msg_seq[i]], 0);
Packit Service 4684c1
				}
Packit Service 4684c1
				while (ret == -1 && (errno == EAGAIN || errno == EINTR));
Packit Service 4684c1
				pos++;
Packit Service 4684c1
			} else
Packit Service 4684c1
				break;
Packit Service 4684c1
		}
Packit Service 4684c1
	} else if (msg_seq[current] == (int)current) {
Packit Service 4684c1
		do {
Packit Service 4684c1
			ret = send((long int)tr, data, len, 0);
Packit Service 4684c1
		}
Packit Service 4684c1
		while (ret == -1 && (errno == EAGAIN || errno == EINTR));
Packit Service 4684c1
Packit Service 4684c1
		current++;
Packit Service 4684c1
		pos++;
Packit Service 4684c1
Packit Service 4684c1
		return ret;
Packit Service 4684c1
	} else if (stored_messages[msg_seq[current]] != NULL) {
Packit Service 4684c1
		do {
Packit Service 4684c1
			ret =
Packit Service 4684c1
			    send((long int)tr,
Packit Service 4684c1
				 stored_messages[msg_seq[current]],
Packit Service 4684c1
				 stored_sizes[msg_seq[current]], 0);
Packit Service 4684c1
		}
Packit Service 4684c1
		while (ret == -1 && (errno == EAGAIN || errno == EINTR));
Packit Service 4684c1
		current++;
Packit Service 4684c1
		pos++;
Packit Service 4684c1
		return ret;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	current++;
Packit Service 4684c1
Packit Service 4684c1
	return len;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
static ssize_t n_push(gnutls_transport_ptr_t tr, const void *data, size_t len)
Packit Service 4684c1
{
Packit Service 4684c1
	return send((unsigned long)tr, data, len, 0);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* The first five messages are handshake. Thus corresponds to msg_seq+5 */
Packit Service 4684c1
static int recv_msg_seq[] =
Packit Service 4684c1
    { 1, 2, 3, 4, 5, 6, 12, 28, 7, 8, 9, 10, 11, 13, 15, 16, 14, 18, 20,
Packit Service 4684c1
	19, 21, 22, 23, 25, 24, 26, 27, 29, 30, 31, 33, 32, 34, 35, 38, 36, 37,
Packit Service 4684c1
	    -1
Packit Service 4684c1
};
Packit Service 4684c1
Packit Service 4684c1
static void client(int fd)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_session_t session;
Packit Service 4684c1
	int ret;
Packit Service 4684c1
	char buffer[MAX_BUF + 1];
Packit Service 4684c1
	gnutls_anon_client_credentials_t anoncred;
Packit Service 4684c1
	unsigned char seq[8];
Packit Service 4684c1
	uint32_t useq;
Packit Service 4684c1
Packit Service 4684c1
	memset(buffer, 0, sizeof(buffer));
Packit Service 4684c1
Packit Service 4684c1
	/* Need to enable anonymous KX specifically. */
Packit Service 4684c1
Packit Service 4684c1
/*    gnutls_global_set_audit_log_function (tls_audit_log_func); */
Packit Service 4684c1
	global_init();
Packit Service 4684c1
Packit Service 4684c1
	if (debug) {
Packit Service 4684c1
		gnutls_global_set_log_function(client_log_func);
Packit Service 4684c1
		gnutls_global_set_log_level(2);
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	gnutls_anon_allocate_client_credentials(&anoncred);
Packit Service 4684c1
Packit Service 4684c1
	/* Initialize TLS session
Packit Service 4684c1
	 */
Packit Service 4684c1
	gnutls_init(&session, GNUTLS_CLIENT | GNUTLS_DATAGRAM);
Packit Service 4684c1
	gnutls_dtls_set_timeouts(session, 50 * 1000, 600 * 1000);
Packit Service 4684c1
	gnutls_heartbeat_enable(session, GNUTLS_HB_PEER_ALLOWED_TO_SEND);
Packit Service 4684c1
	gnutls_dtls_set_mtu(session, 1500);
Packit Service 4684c1
Packit Service 4684c1
	/* Use default priorities */
Packit Service 4684c1
	gnutls_priority_set_direct(session,
Packit Service 4684c1
				   "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL",
Packit Service 4684c1
				   NULL);
Packit Service 4684c1
Packit Service 4684c1
	/* put the anonymous credentials to the current session
Packit Service 4684c1
	 */
Packit Service 4684c1
	gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);
Packit Service 4684c1
Packit Service 4684c1
	gnutls_transport_set_int(session, fd);
Packit Service 4684c1
Packit Service 4684c1
	/* Perform the TLS handshake
Packit Service 4684c1
	 */
Packit Service 4684c1
	do {
Packit Service 4684c1
		ret = gnutls_handshake(session);
Packit Service 4684c1
	}
Packit Service 4684c1
	while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
Packit Service 4684c1
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		fail("client: Handshake failed\n");
Packit Service 4684c1
		gnutls_perror(ret);
Packit Service 4684c1
		exit(1);
Packit Service 4684c1
	} else {
Packit Service 4684c1
		if (debug)
Packit Service 4684c1
			success("client: Handshake was completed\n");
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	gnutls_record_send(session, buffer, 1);
Packit Service 4684c1
Packit Service 4684c1
	if (debug)
Packit Service 4684c1
		success("client: DTLS version is: %s\n",
Packit Service 4684c1
			gnutls_protocol_get_name
Packit Service 4684c1
			(gnutls_protocol_get_version(session)));
Packit Service 4684c1
	do {
Packit Service 4684c1
		ret =
Packit Service 4684c1
		    gnutls_record_recv_seq(session, buffer, sizeof(buffer),
Packit Service 4684c1
					   seq);
Packit Service 4684c1
Packit Service 4684c1
		if (ret > 0) {
Packit Service 4684c1
			useq =
Packit Service 4684c1
			    seq[7] | (seq[6] << 8) | (seq[5] << 16) |
Packit Service 4684c1
			    (seq[4] << 24);
Packit Service 4684c1
Packit Service 4684c1
			if (debug)
Packit Service 4684c1
				success("received %u\n", (unsigned int)useq);
Packit Service 4684c1
Packit Service 4684c1
			if (recv_msg_seq[current] == -1) {
Packit Service 4684c1
				fail("received message sequence differs\n");
Packit Service 4684c1
				terminate();
Packit Service 4684c1
			}
Packit Service 4684c1
			if (((uint32_t)recv_msg_seq[current]) != useq) {
Packit Service 4684c1
				fail("received message sequence differs (current: %u, got: %u, expected: %u)\n",
Packit Service 4684c1
				     (unsigned)current, (unsigned)useq, (unsigned)recv_msg_seq[current]);
Packit Service 4684c1
				terminate();
Packit Service 4684c1
			}
Packit Service 4684c1
Packit Service 4684c1
			current++;
Packit Service 4684c1
		}
Packit Service 4684c1
	}
Packit Service 4684c1
	while ((ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED
Packit Service 4684c1
		|| ret > 0));
Packit Service 4684c1
Packit Service 4684c1
	gnutls_bye(session, GNUTLS_SHUT_WR);
Packit Service 4684c1
Packit Service 4684c1
	close(fd);
Packit Service 4684c1
Packit Service 4684c1
	gnutls_deinit(session);
Packit Service 4684c1
Packit Service 4684c1
	gnutls_anon_free_client_credentials(anoncred);
Packit Service 4684c1
Packit Service 4684c1
	gnutls_global_deinit();
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
static void terminate(void)
Packit Service 4684c1
{
Packit Service 4684c1
	int status;
Packit Service 4684c1
Packit Service 4684c1
	kill(child, SIGTERM);
Packit Service 4684c1
	wait(&status);
Packit Service 4684c1
	exit(1);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
static void server(int fd)
Packit Service 4684c1
{
Packit Service 4684c1
	int ret;
Packit Service 4684c1
	gnutls_session_t session;
Packit Service 4684c1
	gnutls_anon_server_credentials_t anoncred;
Packit Service 4684c1
	char c;
Packit Service 4684c1
Packit Service 4684c1
	global_init();
Packit Service 4684c1
Packit Service 4684c1
	if (debug) {
Packit Service 4684c1
		gnutls_global_set_log_function(server_log_func);
Packit Service 4684c1
		gnutls_global_set_log_level(2);
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	gnutls_anon_allocate_server_credentials(&anoncred);
Packit Service 4684c1
Packit Service 4684c1
	gnutls_init(&session, GNUTLS_SERVER | GNUTLS_DATAGRAM);
Packit Service 4684c1
	gnutls_dtls_set_timeouts(session, 50 * 1000, 600 * 1000);
Packit Service 4684c1
	gnutls_transport_set_push_function(session, odd_push);
Packit Service 4684c1
	gnutls_heartbeat_enable(session, GNUTLS_HB_PEER_ALLOWED_TO_SEND);
Packit Service 4684c1
	gnutls_dtls_set_mtu(session, 1500);
Packit Service 4684c1
Packit Service 4684c1
	/* avoid calling all the priority functions, since the defaults
Packit Service 4684c1
	 * are adequate.
Packit Service 4684c1
	 */
Packit Service 4684c1
	gnutls_priority_set_direct(session,
Packit Service 4684c1
				   "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL",
Packit Service 4684c1
				   NULL);
Packit Service 4684c1
	gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);
Packit Service 4684c1
Packit Service 4684c1
	gnutls_transport_set_int(session, fd);
Packit Service 4684c1
Packit Service 4684c1
	do {
Packit Service 4684c1
		ret = gnutls_handshake(session);
Packit Service 4684c1
	}
Packit Service 4684c1
	while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		close(fd);
Packit Service 4684c1
		gnutls_deinit(session);
Packit Service 4684c1
		fail("server: Handshake has failed (%s)\n\n",
Packit Service 4684c1
		     gnutls_strerror(ret));
Packit Service 4684c1
		terminate();
Packit Service 4684c1
	}
Packit Service 4684c1
	if (debug)
Packit Service 4684c1
		success("server: Handshake was completed\n");
Packit Service 4684c1
Packit Service 4684c1
	if (debug)
Packit Service 4684c1
		success("server: TLS version is: %s\n",
Packit Service 4684c1
			gnutls_protocol_get_name
Packit Service 4684c1
			(gnutls_protocol_get_version(session)));
Packit Service 4684c1
Packit Service 4684c1
	gnutls_record_recv(session, &c, 1);
Packit Service 4684c1
	do {
Packit Service 4684c1
		do {
Packit Service 4684c1
			ret = gnutls_record_send(session, &c, 1);
Packit Service 4684c1
		}
Packit Service 4684c1
		while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
Packit Service 4684c1
Packit Service 4684c1
		if (ret < 0) {
Packit Service 4684c1
			fail("send: %s\n", gnutls_strerror(ret));
Packit Service 4684c1
			terminate();
Packit Service 4684c1
		}
Packit Service 4684c1
	}
Packit Service 4684c1
	while (test_finished == 0);
Packit Service 4684c1
Packit Service 4684c1
	gnutls_transport_set_push_function(session, n_push);
Packit Service 4684c1
	do {
Packit Service 4684c1
		ret = gnutls_bye(session, GNUTLS_SHUT_WR);
Packit Service 4684c1
	}
Packit Service 4684c1
	while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
Packit Service 4684c1
Packit Service 4684c1
	close(fd);
Packit Service 4684c1
	gnutls_deinit(session);
Packit Service 4684c1
Packit Service 4684c1
	gnutls_anon_free_server_credentials(anoncred);
Packit Service 4684c1
Packit Service 4684c1
	gnutls_global_deinit();
Packit Service 4684c1
Packit Service 4684c1
	if (debug)
Packit Service 4684c1
		success("server: finished\n");
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
static void start(void)
Packit Service 4684c1
{
Packit Service 4684c1
	int fd[2];
Packit Service 4684c1
	int ret;
Packit Service 4684c1
Packit Service 4684c1
	signal(SIGPIPE, SIG_IGN);
Packit Service 4684c1
Packit Service 4684c1
	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		perror("socketpair");
Packit Service 4684c1
		exit(1);
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	child = fork();
Packit Service 4684c1
	if (child < 0) {
Packit Service 4684c1
		perror("fork");
Packit Service 4684c1
		fail("fork");
Packit Service 4684c1
		exit(1);
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	if (child) {
Packit Service 4684c1
		int status;
Packit Service 4684c1
		/* parent */
Packit Service 4684c1
		close(fd[1]);
Packit Service 4684c1
		server(fd[0]);
Packit Service 4684c1
		wait(&status);
Packit Service 4684c1
		check_wait_status(status);
Packit Service 4684c1
	} else {
Packit Service 4684c1
		close(fd[0]);
Packit Service 4684c1
		client(fd[1]);
Packit Service 4684c1
		exit(0);
Packit Service 4684c1
	}
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
void doit(void)
Packit Service 4684c1
{
Packit Service 4684c1
	start();
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
#endif				/* _WIN32 */