diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2012-02-08 21:54:00 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2012-02-08 21:54:00 +0100 |
commit | 44eeb40c0fddff712223c62440f7320566061380 (patch) | |
tree | 094b176a3893918de0f606d7d27c7baefdd3972e /tests | |
parent | 128a3bafc38ebb69e67cd0f4d4951ea00652bbb3 (diff) | |
download | gnutls-44eeb40c0fddff712223c62440f7320566061380.tar.gz |
mini-loss2 is more robust.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/loss-common.h | 215 | ||||
-rw-r--r-- | tests/mini-loss.c | 396 | ||||
-rw-r--r-- | tests/mini-loss2.c | 365 |
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); -} |