Blame tests/mini-dtls-record.c

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