summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2012-02-08 21:54:00 +0100
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2012-02-08 21:54:00 +0100
commit44eeb40c0fddff712223c62440f7320566061380 (patch)
tree094b176a3893918de0f606d7d27c7baefdd3972e /tests
parent128a3bafc38ebb69e67cd0f4d4951ea00652bbb3 (diff)
downloadgnutls-44eeb40c0fddff712223c62440f7320566061380.tar.gz
mini-loss2 is more robust.
Diffstat (limited to 'tests')
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/loss-common.h215
-rw-r--r--tests/mini-loss.c396
-rw-r--r--tests/mini-loss2.c365
4 files changed, 336 insertions, 642 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e1b6cf63e9..99532d3ca2 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -66,7 +66,7 @@ ctests = mini-deflate simple gc set_pkcs12_cred certder certuniqueid \
crq_apis init_roundtrip pkcs12_s2k_pem dn2 mini-eagain \
nul-in-x509-names x509_altname pkcs12_encode mini-x509 \
mini-x509-rehandshake rng-fork mini-eagain-dtls mini-loss \
- x509cert x509cert-tl infoaccess rsa-encrypt-decrypt mini-loss2
+ x509cert x509cert-tl infoaccess rsa-encrypt-decrypt
if ENABLE_OCSP
ctests += ocsp
diff --git a/tests/loss-common.h b/tests/loss-common.h
deleted file mode 100644
index 28432736cc..0000000000
--- a/tests/loss-common.h
+++ /dev/null
@@ -1,215 +0,0 @@
-#define min(x,y) ((x)<(y)?(x):(y))
-
-char tmpbuf[128];
-extern const char* prefix;
-
-#define HANDSHAKE_EXPECT(c, s, clierr, serverr) \
- sret = cret = GNUTLS_E_AGAIN; \
- do \
- { \
- if (cret == GNUTLS_E_AGAIN) \
- { \
- prefix = "client"; \
- cret = gnutls_handshake (c); \
- } \
- else if (cret >= 0) \
- { \
- prefix = "client"; \
- ret = gnutls_record_recv(c, tmpbuf, sizeof(tmpbuf)); \
- } \
- if (sret == GNUTLS_E_AGAIN) \
- { \
- prefix = "server"; \
- sret = gnutls_handshake (s); \
- } \
- else if (sret >= 0) \
- { \
- prefix = "server"; \
- ret = gnutls_record_recv(s, tmpbuf, sizeof(tmpbuf)); \
- } \
- } \
- while ((cret == GNUTLS_E_AGAIN || (cret == 0 && sret == GNUTLS_E_AGAIN)) && (sret == GNUTLS_E_AGAIN || (sret == 0 && cret == GNUTLS_E_AGAIN))); \
- if (cret != clierr || sret != serverr) \
- { \
- fprintf(stderr, "client: %s\n", gnutls_strerror(cret)); \
- fprintf(stderr, "server: %s\n", gnutls_strerror(sret)); \
- fail("Handshake failed\n"); \
- exit(1); \
- }
-
-#define HANDSHAKE(c, s) \
- HANDSHAKE_EXPECT(c,s,0,0)
-
-#define TRANSFER(c, s, msg, msglen, buf, buflen) \
- sret = cret = GNUTLS_E_AGAIN; \
- do \
- { \
- if (cret == GNUTLS_E_AGAIN) \
- { \
- prefix = "client"; \
- cret = gnutls_record_send (c, msg, msglen); \
- } \
- if (sret == GNUTLS_E_AGAIN) \
- { \
- prefix = "server"; \
- sret = gnutls_record_recv (s, buf, buflen); \
- } \
- } \
- while ((cret == GNUTLS_E_AGAIN || (cret >= 0 && sret == GNUTLS_E_AGAIN)) && (sret == GNUTLS_E_AGAIN || (sret >= 0 && cret == GNUTLS_E_AGAIN))); \
- \
- if (cret < 0) fail ("client send error: %s\n", gnutls_strerror (ret)); \
- if (sret < 0) fail ("server send error: %s\n", gnutls_strerror (ret))
-
-static char to_server[64*1024];
-static size_t to_server_len = 0;
-
-static char to_client[64*1024];
-static size_t to_client_len = 0;
-
-extern int counter;
-extern int packet_to_lose;
-
-#ifdef LOSS_DEBUG
-# define RETURN_RND_LOSS(session, len) { \
- if (counter++ == packet_to_lose) \
- { \
- int t = gnutls_handshake_get_last_out(session); \
- fprintf(stderr, "Discarding packet (%d) with seq %d\n", \
- t, counter); \
- return len; \
- } \
- }
-#else
-# define RETURN_RND_LOSS(session, len) { \
- if (counter++ == packet_to_lose) \
- { \
- return len; \
- } \
- }
-#endif
-
-static void reset_counters(void)
-{
- to_client_len = to_server_len = 0;
-}
-
-static ssize_t
-client_push (gnutls_transport_ptr_t tr, const void *data, size_t len)
-{
- size_t newlen;
-
- len = min(len, sizeof(to_server)-to_server_len);
-// RETURN_RND_LOSS(tr, len);
-
- newlen = to_server_len + len;
- memcpy (to_server + to_server_len, data, len);
- to_server_len = newlen;
-#ifdef LOSS_DEBUG
- fprintf(stderr, "loss: pushed %d bytes to server (avail: %d)\n", (int)len, (int)to_server_len);
-#endif
- return len;
-}
-
-static ssize_t
-client_pull (gnutls_transport_ptr_t tr, void *data, size_t len)
-{
- if (to_client_len == 0)
- {
-#ifdef LOSS_DEBUG2
- fprintf(stderr, "loss: Not enough data by server (asked for: %d, have: %d)\n", (int)len, (int)to_client_len);
-#endif
- return -1;
- }
-
- len = min(len, to_client_len);
-
- memcpy (data, to_client, len);
- memmove (to_client, to_client + len, to_client_len - len);
- to_client_len -= len;
-#ifdef LOSS_DEBUG
- fprintf(stderr, "loss: pulled %d bytes by client (avail: %d)\n", (int)len, (int)to_client_len);
-#endif
- return len;
-}
-
-static ssize_t
-server_pull (gnutls_transport_ptr_t tr, void *data, size_t len)
-{
- if (to_server_len == 0)
- {
-#ifdef LOSS_DEBUG2
- fprintf(stderr, "loss: Not enough data by client (asked for: %d, have: %d)\n", (int)len, (int)to_server_len);
-#endif
- return -1;
- }
-
- len = min(len, to_server_len);
-#ifdef LOSS_DEBUG
- fprintf(stderr, "loss: pulled %d bytes by server (avail: %d)\n", (int)len, (int)to_server_len);
-#endif
- memcpy (data, to_server, len);
-
- memmove (to_server, to_server + len, to_server_len - len);
- to_server_len -= len;
-
- return len;
-}
-
-static ssize_t
-server_push (gnutls_transport_ptr_t tr, const void *data, size_t len)
-{
- size_t newlen;
-
-// hexprint (data, len);
-
- len = min(len, sizeof(to_client)-to_client_len);
- RETURN_RND_LOSS(tr, len);
-
- newlen = to_client_len + len;
- memcpy (to_client + to_client_len, data, len);
- to_client_len = newlen;
-#ifdef LOSS_DEBUG
- fprintf(stderr, "loss: pushed %d bytes to client (avail: %d)\n", (int)len, (int)to_client_len);
-#endif
-
- return len;
-}
-
-/* inline is used to avoid a gcc warning if used in mini-loss */
-inline static int server_pull_timeout_func(gnutls_transport_ptr_t ptr, unsigned int ms)
-{
-int ret;
-
- if (to_server_len > 0)
- ret = 1; /* available data */
- else
- ret = 0; /* timeout */
-
-#ifdef LOSS_DEBUG
- fprintf(stderr, "loss: server_pull_timeout: %d\n", ret);
-#endif
-
- return ret;
-}
-
-inline static int client_pull_timeout_func(gnutls_transport_ptr_t ptr, unsigned int ms)
-{
-int ret;
-
- if (to_client_len > 0)
- ret = 1;
- else
- ret = 0;
-
-#ifdef LOSS_DEBUG
- fprintf(stderr, "loss: client_pull_timeout: %d\n", ret);
-#endif
-
- return ret;
-}
-
-inline static void reset_buffers(void)
-{
- to_server_len = 0;
- to_client_len = 0;
-}
diff --git a/tests/mini-loss.c b/tests/mini-loss.c
index 21e013224b..78a91f531a 100644
--- a/tests/mini-loss.c
+++ b/tests/mini-loss.c
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2008-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2012 Free Software Foundation, Inc.
*
- * Author: Simon Josefsson, Nikos Mavrogiannopoulos
+ * Author: Nikos Mavrogiannopoulos
*
* This file is part of GnuTLS.
*
@@ -27,94 +27,368 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#if !defined(_WIN32)
+#include <sys/wait.h>
+#include <arpa/inet.h>
+#endif
+#include <unistd.h>
#include <gnutls/gnutls.h>
-#include <gnutls/crypto.h>
+#include <gnutls/dtls.h>
+
#include "utils.h"
-#include "loss-common.h"
-const char * prefix = NULL;
-int counter;
-int packet_to_lose;
+/* This program simulates packet loss in DTLS datagrams using
+ * the blocking functions
+ */
+
+static void print_type(const unsigned char* buf, int size)
+{
+ if (buf[0] == 22 && size >= 13) {
+ if (buf[13] == 1)
+ fprintf(stderr, "Client Hello\n");
+ else if (buf[13] == 2)
+ fprintf(stderr, "Server Hello\n");
+ else if (buf[13] == 12)
+ fprintf(stderr, "Server Key exchange\n");
+ else if (buf[13] == 14)
+ fprintf(stderr, "Server Hello Done\n");
+ else if (buf[13] == 11)
+ fprintf(stderr, "Certificate\n");
+ else if (buf[13] == 16)
+ fprintf(stderr, "Client Key Exchange\n");
+ else if (buf[4] == 1)
+ fprintf(stderr, "Finished\n");
+ else if (buf[13] == 11)
+ fprintf(stderr, "Server Hello Done\n");
+ else
+ fprintf(stderr, "Unknown handshake\n");
+ } else if (buf[0] == 20) {
+ fprintf(stderr, "Change Cipher Spec\n");
+ } else
+ fprintf(stderr, "Unknown\n");
+}
static void
-tls_log_func (int level, const char *str)
+server_log_func (int level, const char *str)
{
- fprintf (stderr, "%s|<%d>| %s", prefix, level, str);
+ fprintf (stderr, "server|<%d>| %s", level, str);
}
-static gnutls_anon_server_credentials_t s_anoncred;
-static gnutls_anon_client_credentials_t c_anoncred;
+static void
+client_log_func (int level, const char *str)
+{
+ fprintf (stderr, "client|<%d>| %s", level, str);
+}
+
+/* A very basic TLS client, with anonymous authentication.
+ */
+
+#define MAX_BUF 1024
+#define MSG "Hello TLS"
+
+static int counter;
+static int packet_to_lose;
+gnutls_session_t session;
+
+static ssize_t
+push (gnutls_transport_ptr_t tr, const void *data, size_t len)
+{
+int fd = (long int)tr;
+
+ counter++;
+
+ if (packet_to_lose != -1 && packet_to_lose == counter) {
+ if (debug)
+ {
+ fprintf(stderr, "Discarding packet %d: ", counter);
+ print_type(data, len);
+ }
+ return len;
+ }
+ return send(fd, data, len, 0);
+}
-static void try1 (int packet)
+static void
+client (int fd, int packet)
{
- /* Server stuff. */
- gnutls_session_t server;
- int sret, cret;
- /* Client stuff. */
- gnutls_session_t client;
+ int ret, ii;
+ char buffer[MAX_BUF + 1];
+ gnutls_anon_client_credentials_t anoncred;
/* Need to enable anonymous KX specifically. */
- int ret;
+
+ gnutls_global_init ();
+
+ if (debug)
+ {
+ gnutls_global_set_log_function (client_log_func);
+ gnutls_global_set_log_level (4711);
+ }
+
+ gnutls_anon_allocate_client_credentials (&anoncred);
+
+ /* Initialize TLS session
+ */
+ gnutls_init (&session, GNUTLS_CLIENT|GNUTLS_DATAGRAM);
+ gnutls_dtls_set_mtu( session, 1500);
+
+ /* Use default priorities */
+ gnutls_priority_set_direct (session, "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL", NULL);
+
+ /* put the anonymous credentials to the current session
+ */
+ gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
counter = 0;
packet_to_lose = packet;
- reset_counters();
-
- gnutls_init (&server, GNUTLS_SERVER|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK);
- ret = gnutls_priority_set_direct (server, "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL", NULL);
+
+ gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) fd);
+ gnutls_transport_set_push_function (session, push);
+
+ /* Perform the TLS handshake
+ */
+ do
+ {
+ ret = gnutls_handshake (session);
+ }
+ while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
+
if (ret < 0)
- exit(1);
- gnutls_credentials_set (server, GNUTLS_CRD_ANON, s_anoncred);
- gnutls_transport_set_push_function (server, server_push);
- gnutls_transport_set_pull_function (server, server_pull);
- gnutls_transport_set_pull_timeout_function (server, server_pull_timeout_func);
- gnutls_transport_set_ptr (server, (gnutls_transport_ptr_t)server);
-
- /* Init client */
- gnutls_init (&client, GNUTLS_CLIENT|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK);
- cret = gnutls_priority_set_direct (client, "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL", NULL);
- if (cret < 0)
- exit(1);
- gnutls_credentials_set (client, GNUTLS_CRD_ANON, c_anoncred);
- gnutls_transport_set_push_function (client, client_push);
- gnutls_transport_set_pull_function (client, client_pull);
- gnutls_transport_set_pull_timeout_function (client, client_pull_timeout_func);
- gnutls_transport_set_ptr (client, (gnutls_transport_ptr_t)client);
-
- HANDSHAKE(client, server);
+ {
+ fail ("client: Handshake failed\n");
+ gnutls_perror (ret);
+ exit(1);
+ }
+ else
+ {
+ if (debug)
+ success ("client: Handshake was completed\n");
+ }
if (debug)
- success ("Handshake established\n");
+ success ("client: TLS version is: %s\n",
+ gnutls_protocol_get_name (gnutls_protocol_get_version
+ (session)));
- gnutls_bye (client, GNUTLS_SHUT_WR);
- gnutls_bye (server, GNUTLS_SHUT_WR);
+ do {
+ ret = gnutls_record_send (session, MSG, strlen (MSG));
+ } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
- gnutls_deinit (client);
- gnutls_deinit (server);
+ do {
+ ret = gnutls_record_recv (session, buffer, MAX_BUF);
+ } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
+
+ if (ret == 0)
+ {
+ if (debug)
+ success ("client: Peer has closed the TLS connection\n");
+ goto end;
+ }
+ else if (ret < 0)
+ {
+ fail ("client: Error: %s\n", gnutls_strerror (ret));
+ exit(1);
+ }
+
+ if (debug)
+ {
+ printf ("- Received %d bytes: ", ret);
+ for (ii = 0; ii < ret; ii++)
+ {
+ fputc (buffer[ii], stdout);
+ }
+ fputs ("\n", stdout);
+ }
+
+ gnutls_bye (session, GNUTLS_SHUT_RDWR);
+
+end:
+
+ close (fd);
+
+ gnutls_deinit (session);
+
+ gnutls_anon_free_client_credentials (anoncred);
+
+ gnutls_global_deinit ();
}
-void
-doit (void)
+
+/* These are global */
+gnutls_anon_server_credentials_t anoncred;
+pid_t child;
+
+static gnutls_session_t
+initialize_tls_session (void)
+{
+ gnutls_session_t session;
+
+ gnutls_init (&session, GNUTLS_SERVER|GNUTLS_DATAGRAM);
+ gnutls_dtls_set_mtu( session, 1500);
+
+ /* avoid calling all the priority functions, since the defaults
+ * are adequate.
+ */
+ gnutls_priority_set_direct (session, "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL", NULL);
+
+ gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
+
+ return session;
+}
+
+static void terminate(void)
{
- /* General init. */
+int status;
+
+ kill(child, SIGTERM);
+ wait(&status);
+ exit(1);
+}
+
+static void
+server (int fd, int packet)
+{
+int ret;
+char buffer[MAX_BUF + 1];
+ /* this must be called once in the program
+ */
gnutls_global_init ();
+
if (debug)
{
- gnutls_global_set_log_function (tls_log_func);
- gnutls_global_set_log_level (9);
+ gnutls_global_set_log_function (server_log_func);
+ gnutls_global_set_log_level (4711);
+ }
+
+ gnutls_anon_allocate_server_credentials (&anoncred);
+
+ session = initialize_tls_session ();
+
+ counter = 0;
+ packet_to_lose = packet;
+
+ gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) fd);
+ gnutls_transport_set_push_function (session, push);
+
+ do
+ {
+ ret = gnutls_handshake (session);
}
+ while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
+ if (ret < 0)
+ {
+ close (fd);
+ gnutls_deinit (session);
+ fail ("server: Handshake has failed (%s)\n\n", gnutls_strerror (ret));
+ terminate();
+ }
+ if (debug)
+ success ("server: Handshake was completed\n");
- gnutls_anon_allocate_server_credentials (&s_anoncred);
- gnutls_anon_allocate_client_credentials (&c_anoncred);
+ if (debug)
+ success ("server: TLS version is: %s\n",
+ gnutls_protocol_get_name (gnutls_protocol_get_version
+ (session)));
- try1(1);
- try1(2);
- try1(3);
- try1(4);
- try1(5);
+ /* see the Getting peer's information example */
+ /* print_info(session); */
- gnutls_anon_free_client_credentials (c_anoncred);
- gnutls_anon_free_server_credentials (s_anoncred);
+ for (;;)
+ {
+ memset (buffer, 0, MAX_BUF + 1);
+
+ do {
+ ret = gnutls_record_recv (session, buffer, MAX_BUF);
+ } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
+
+ if (ret == 0)
+ {
+ if (debug)
+ success ("server: Peer has closed the GnuTLS connection\n");
+ break;
+ }
+ else if (ret < 0)
+ {
+ fail ("server: Received corrupted data(%d). Closing...\n", ret);
+ terminate();
+ }
+ else if (ret > 0)
+ {
+ /* echo data back to the client
+ */
+ do {
+ ret = gnutls_record_send (session, buffer, strlen (buffer));
+ } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
+ }
+ }
+ /* do not wait for the peer to close the connection.
+ */
+ gnutls_bye (session, GNUTLS_SHUT_WR);
+
+ close (fd);
+ gnutls_deinit (session);
+
+ gnutls_anon_free_server_credentials (anoncred);
gnutls_global_deinit ();
+
+ if (debug)
+ success ("server: finished\n");
+}
+
+static void start (int server_packet, int client_packet)
+{
+ int fd[2];
+ int ret;
+
+ if (debug)
+ fprintf(stderr, "\nWill discard %s packet %d\n",
+ (client_packet!=-1)?"client":"server", (client_packet!=-1)?client_packet:server_packet);
+
+ ret = socketpair(AF_LOCAL, SOCK_DGRAM, 0, fd);
+ if (ret < 0)
+ {
+ perror("socketpair");
+ exit(1);
+ }
+
+ child = fork ();
+ if (child < 0)
+ {
+ perror ("fork");
+ fail ("fork");
+ exit(1);
+ }
+
+ if (child)
+ {
+ int status;
+ /* parent */
+ server (fd[0], server_packet);
+ wait (&status);
+ if (WEXITSTATUS(status) != 0)
+ fail("Child died with status %d\n", WEXITSTATUS(status));
+ }
+ else
+ {
+ client (fd[1], client_packet);
+ exit(0);
+ }
+}
+
+void
+doit (void)
+{
+ start(-1, 1);
+ start(-1, 2);
+ start(-1, 3);
+ start(-1, 4);
+
+ start(1, -1);
+ start(2, -1);
+ start(3, -1);
+ start(4, -1);
+ start(5, -1);
}
diff --git a/tests/mini-loss2.c b/tests/mini-loss2.c
deleted file mode 100644
index a0c0aa58fd..0000000000
--- a/tests/mini-loss2.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) 2012 Free Software Foundation, Inc.
- *
- * Author: Nikos Mavrogiannopoulos
- *
- * This file is part of GnuTLS.
- *
- * GnuTLS is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * GnuTLS is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GnuTLS; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#if !defined(_WIN32)
-#include <sys/wait.h>
-#include <arpa/inet.h>
-#endif
-#include <unistd.h>
-#include <gnutls/gnutls.h>
-#include <gnutls/dtls.h>
-
-#include "utils.h"
-
-/* This program simulates packet loss in DTLS datagrams using
- * the blocking functions
- */
-
-static void
-server_log_func (int level, const char *str)
-{
- fprintf (stderr, "server|<%d>| %s", level, str);
-}
-
-static void
-client_log_func (int level, const char *str)
-{
- fprintf (stderr, "client|<%d>| %s", level, str);
-}
-
-/* A very basic TLS client, with anonymous authentication.
- */
-
-#define MAX_BUF 1024
-#define MSG "Hello TLS"
-
-static int counter;
-static int packet_to_lose;
-gnutls_session_t session;
-
-static ssize_t
-push (gnutls_transport_ptr_t tr, const void *data, size_t len)
-{
-int fd = (long int)tr;
-
- counter++;
- if (packet_to_lose != -1 && packet_to_lose == counter) {
- if (debug)
- {
- int type = gnutls_handshake_get_last_out(session);
-
- fprintf(stderr, "Discarding packet %d (%d)\n", counter, type);
- }
- return len;
- }
- return send(fd, data, len, 0);
-}
-
-static void
-client (int fd, int packet)
-{
- int ret, ii;
- char buffer[MAX_BUF + 1];
- gnutls_anon_client_credentials_t anoncred;
- /* Need to enable anonymous KX specifically. */
-
- gnutls_global_init ();
-
- if (debug)
- {
- gnutls_global_set_log_function (client_log_func);
- gnutls_global_set_log_level (4711);
- }
-
- gnutls_anon_allocate_client_credentials (&anoncred);
-
- /* Initialize TLS session
- */
- gnutls_init (&session, GNUTLS_CLIENT|GNUTLS_DATAGRAM);
- gnutls_dtls_set_mtu( session, 1500);
-
- /* Use default priorities */
- gnutls_priority_set_direct (session, "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL", NULL);
-
- /* put the anonymous credentials to the current session
- */
- gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
-
- counter = 0;
- packet_to_lose = packet;
-
- gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) fd);
- gnutls_transport_set_push_function (session, push);
-
- /* Perform the TLS handshake
- */
- do
- {
- ret = gnutls_handshake (session);
- }
- while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
-
- if (ret < 0)
- {
- fail ("client: Handshake failed\n");
- gnutls_perror (ret);
- exit(1);
- }
- else
- {
- if (debug)
- success ("client: Handshake was completed\n");
- }
-
- if (debug)
- success ("client: TLS version is: %s\n",
- gnutls_protocol_get_name (gnutls_protocol_get_version
- (session)));
-
- do {
- ret = gnutls_record_send (session, MSG, strlen (MSG));
- } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
-
- do {
- ret = gnutls_record_recv (session, buffer, MAX_BUF);
- } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
-
- if (ret == 0)
- {
- if (debug)
- success ("client: Peer has closed the TLS connection\n");
- goto end;
- }
- else if (ret < 0)
- {
- fail ("client: Error: %s\n", gnutls_strerror (ret));
- exit(1);
- }
-
- if (debug)
- {
- printf ("- Received %d bytes: ", ret);
- for (ii = 0; ii < ret; ii++)
- {
- fputc (buffer[ii], stdout);
- }
- fputs ("\n", stdout);
- }
-
- gnutls_bye (session, GNUTLS_SHUT_RDWR);
-
-end:
-
- close (fd);
-
- gnutls_deinit (session);
-
- gnutls_anon_free_client_credentials (anoncred);
-
- gnutls_global_deinit ();
-}
-
-
-/* These are global */
-gnutls_anon_server_credentials_t anoncred;
-pid_t child;
-
-static gnutls_session_t
-initialize_tls_session (void)
-{
- gnutls_session_t session;
-
- gnutls_init (&session, GNUTLS_SERVER|GNUTLS_DATAGRAM);
- gnutls_dtls_set_mtu( session, 1500);
-
- /* avoid calling all the priority functions, since the defaults
- * are adequate.
- */
- gnutls_priority_set_direct (session, "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL", NULL);
-
- gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
-
- return session;
-}
-
-static void terminate(void)
-{
-int status;
-
- kill(child, SIGTERM);
- wait(&status);
- exit(1);
-}
-
-static void
-server (int fd, int packet)
-{
-int ret;
-char buffer[MAX_BUF + 1];
- /* this must be called once in the program
- */
- gnutls_global_init ();
-
- if (debug)
- {
- gnutls_global_set_log_function (server_log_func);
- gnutls_global_set_log_level (4711);
- }
-
- gnutls_anon_allocate_server_credentials (&anoncred);
-
- session = initialize_tls_session ();
-
- counter = 0;
- packet_to_lose = packet;
-
- gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) fd);
- gnutls_transport_set_push_function (session, push);
-
- do
- {
- ret = gnutls_handshake (session);
- }
- while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
- if (ret < 0)
- {
- close (fd);
- gnutls_deinit (session);
- fail ("server: Handshake has failed (%s)\n\n", gnutls_strerror (ret));
- terminate();
- }
- if (debug)
- success ("server: Handshake was completed\n");
-
- if (debug)
- success ("server: TLS version is: %s\n",
- gnutls_protocol_get_name (gnutls_protocol_get_version
- (session)));
-
- /* see the Getting peer's information example */
- /* print_info(session); */
-
- for (;;)
- {
- memset (buffer, 0, MAX_BUF + 1);
-
- do {
- ret = gnutls_record_recv (session, buffer, MAX_BUF);
- } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
-
- if (ret == 0)
- {
- if (debug)
- success ("server: Peer has closed the GnuTLS connection\n");
- break;
- }
- else if (ret < 0)
- {
- fail ("server: Received corrupted data(%d). Closing...\n", ret);
- terminate();
- }
- else if (ret > 0)
- {
- /* echo data back to the client
- */
- do {
- ret = gnutls_record_send (session, buffer, strlen (buffer));
- } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
- }
- }
- /* do not wait for the peer to close the connection.
- */
- gnutls_bye (session, GNUTLS_SHUT_WR);
-
- close (fd);
- gnutls_deinit (session);
-
- gnutls_anon_free_server_credentials (anoncred);
-
- gnutls_global_deinit ();
-
- if (debug)
- success ("server: finished\n");
-}
-
-static void start (int server_packet, int client_packet)
-{
- int fd[2];
- int ret;
-
- if (debug)
- fprintf(stderr, "\nWill discard %s packet %d\n",
- (client_packet!=-1)?"client":"server", (client_packet!=-1)?client_packet:server_packet);
-
- ret = socketpair(AF_LOCAL, SOCK_DGRAM, 0, fd);
- if (ret < 0)
- {
- perror("socketpair");
- exit(1);
- }
-
- child = fork ();
- if (child < 0)
- {
- perror ("fork");
- fail ("fork");
- exit(1);
- }
-
- if (child)
- {
- int status;
- /* parent */
- server (fd[0], server_packet);
- wait (&status);
- if (WEXITSTATUS(status) != 0)
- fail("Child died with status %d\n", WEXITSTATUS(status));
- }
- else
- {
- client (fd[1], client_packet);
- exit(0);
- }
-}
-
-void
-doit (void)
-{
- start(-1, 1);
- start(-1, 2);
- start(-1, 3);
- start(-1, 4);
-
- start(1, -1);
- start(2, -1);
- start(3, -1);
-}