gnutls-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU gnutls branch, master, updated. gnutls-3_0_12-228-gd7eb6b9


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls-3_0_12-228-gd7eb6b9
Date: Tue, 14 Feb 2012 18:08:55 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".

http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=d7eb6b9c4e71f55020f69f279f42b09780f1f48c

The branch, master has been updated
       via  d7eb6b9c4e71f55020f69f279f42b09780f1f48c (commit)
       via  52844e057b1bb1b751beca0fce83cdd60a2504d6 (commit)
       via  ad8b7c2b7aa37460136a24175638f7f97fca40fc (commit)
       via  00ed0bf0e75462f52633cf85884968976162cd7b (commit)
       via  ae7358b70a21324ca4f02365269dea4548a6224c (commit)
      from  67db171a3553875283c118a6ee02edc9acf208b7 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit d7eb6b9c4e71f55020f69f279f42b09780f1f48c
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Tue Feb 14 19:12:53 2012 +0100

    added more tests and updated to compile with gnutls' options

commit 52844e057b1bb1b751beca0fce83cdd60a2504d6
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Tue Feb 14 19:02:40 2012 +0100

    Added DTLS-stress test.
    Contributed by Sean Buckheister.

commit ad8b7c2b7aa37460136a24175638f7f97fca40fc
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Tue Feb 14 19:01:50 2012 +0100

    Added rules to build epub version.

commit 00ed0bf0e75462f52633cf85884968976162cd7b
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Tue Feb 14 17:59:12 2012 +0100

    discard unexpected buffered changecipherspec

commit ae7358b70a21324ca4f02365269dea4548a6224c
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Tue Feb 14 17:29:32 2012 +0100

    simplified sliding window. Now a different window is kept per epoch.

-----------------------------------------------------------------------

Summary of changes:
 .gitignore                                     |    3 +
 configure.ac                                   |    1 +
 doc/Makefile.am                                |    8 +
 doc/{gnutls.texi => epub.texi}                 |   43 +--
 lib/gnutls_buffers.c                           |    9 +-
 lib/gnutls_dtls.c                              |   31 +-
 lib/gnutls_dtls.h                              |    2 +-
 lib/gnutls_int.h                               |   12 +-
 lib/gnutls_record.c                            |    9 +-
 lib/gnutls_state.c                             |    2 -
 tests/Makefile.am                              |    2 +-
 tests/{safe-renegotiation => dtls}/Makefile.am |   30 +-
 tests/{cert-tests/aki => dtls/dtls}            |   22 +-
 tests/dtls/dtls-stress.c                       |  800 ++++++++++++++++++++++++
 14 files changed, 878 insertions(+), 96 deletions(-)
 copy doc/{gnutls.texi => epub.texi} (73%)
 copy tests/{safe-renegotiation => dtls}/Makefile.am (63%)
 copy tests/{cert-tests/aki => dtls/dtls} (57%)
 create mode 100644 tests/dtls/dtls-stress.c

diff --git a/.gitignore b/.gitignore
index c65f537..66c80cb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -587,3 +587,6 @@ gl/tests/test-base64
 tests/mini-loss2
 src/libopts/libopts.la
 tests/mini-loss-time
+tests/dtls/dtls-stress
+doc/gnutls.epub
+doc/gnutls.xml
diff --git a/configure.ac b/configure.ac
index f23c33c..a54988e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -458,6 +458,7 @@ AC_CONFIG_FILES([
   tests/Makefile
   tests/cert-tests/Makefile
   tests/dsa/Makefile
+  tests/dtls/Makefile
   tests/ecdsa/Makefile
   tests/key-id/Makefile
   tests/openpgp-certs/Makefile
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 28c16fa..ea4c37f 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -409,3 +409,11 @@ core.c.texi:
        echo "(Guile not available, documentation not generated.)" > $@
 
 endif !HAVE_GUILE
+
+gnutls.xml: epub.texi
+       makeinfo --docbook $<
+       sed -i 's/\&\#8226;//g' $@
+
+gnutls.epub: gnutls.xml
+       dbtoepub $<
+       epub-fix --delete-unmanifested gnutls.epub
diff --git a/doc/gnutls.texi b/doc/epub.texi
similarity index 73%
copy from doc/gnutls.texi
copy to doc/epub.texi
index 9d98de5..3afe979 100644
--- a/doc/gnutls.texi
+++ b/doc/epub.texi
@@ -2,7 +2,7 @@
 @comment %**start of header
 @setfilename gnutls.info
 @include version.texi
address@hidden GnuTLS @value{VERSION}
address@hidden The GnuTLS Manual
 
 @c don't indent the paragraphs.
 @paragraphindent 0
@@ -12,11 +12,9 @@
 @syncodeindex pg cp
 
 @comment %**end of header
address@hidden
address@hidden
-This manual is last updated @value{UPDATED} for version
address@hidden of GnuTLS.
address@hidden @finalout
 
address@hidden
 Copyright @copyright{} 2001-2012 Free Software Foundation, Inc.
 
 @quotation
@@ -29,34 +27,6 @@ Documentation License''.
 @end quotation
 @end copying
 
address@hidden Software libraries
address@hidden
-* GnuTLS: (gnutls).            GNU Transport Layer Security Library.
address@hidden direntry
-
address@hidden System Administration
address@hidden
-* certtool: (gnutls)Invoking certtool. Manipulate certificates and keys.
-* gnutls-serv: (gnutls)Invoking gnutls-serv.   GnuTLS test server.
-* gnutls-cli: (gnutls)Invoking gnutls-cli.     GnuTLS test client.
-* gnutls-cli-debug: (gnutls)Invoking gnutls-cli-debug. GnuTLS debug client.
-* psktool: (gnutls)Invoking psktool.   Simple TLS-Pre-Shared-Keys manager.
-* srptool: (gnutls)Invoking srptool.   Simple SRP password tool.
address@hidden direntry
-
address@hidden
address@hidden GnuTLS
address@hidden Transport Layer Security Library for the GNU system
address@hidden for version @value{VERSION}, @value{UPDATED}
address@hidden 7
address@hidden @image{gnutls-logo,6cm,6cm}
address@hidden Nikos Mavrogiannopoulos
address@hidden Simon Josefsson (@email{bug-gnutls@@gnu.org})
address@hidden
address@hidden 0pt plus 1filll
address@hidden
address@hidden titlepage
-
 @c reference to an internal function.
 @macro refint {func}
 @code{\func\}
@@ -140,13 +110,6 @@ Documentation License''.
 
 @contents
 
address@hidden
address@hidden Top
address@hidden GnuTLS
-
address@hidden
address@hidden ifnottex
-
 @menu
 * Preface::
 * Introduction to GnuTLS::
diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c
index 80b5b22..83a4232 100644
--- a/lib/gnutls_buffers.c
+++ b/lib/gnutls_buffers.c
@@ -115,7 +115,14 @@ mbuffer_st* bufel;
     return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
 
   if (type != bufel->type)
-    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
+    {
+      if (IS_DTLS(session))
+        _gnutls_audit_log(session, "Discarded unexpected %s (%d) packet 
(expecting: %s (%d))\n",
+                    _gnutls_packet2str(bufel->type), (int)bufel->type,
+                    _gnutls_packet2str(type), (int)type);
+      _mbuffer_head_remove_bytes(&session->internals.record_buffer, msg.size);
+      return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
+    }
 
   if (msg.size <= length)
     length = msg.size;
diff --git a/lib/gnutls_dtls.c b/lib/gnutls_dtls.c
index 62ac934..97f7073 100644
--- a/lib/gnutls_dtls.c
+++ b/lib/gnutls_dtls.c
@@ -420,14 +420,14 @@ int ret;
 }
 
 
-#define window_table session->internals.dtls.record_sw
-#define window_size session->internals.dtls.record_sw_size
+#define window_table rp->record_sw
+#define window_size rp->record_sw_size
 
 /* FIXME: could we modify that code to avoid using
  * uint64_t?
  */
 
-static void rot_window(gnutls_session_t session, int places)
+static void rot_window(struct record_parameters_st * rp, int places)
 {
   window_size -= places;
   memmove(window_table, &window_table[places], 
window_size*sizeof(window_table[0]));
@@ -437,13 +437,12 @@ static void rot_window(gnutls_session_t session, int 
places)
 /* Checks if a sequence number is not replayed. If replayed
  * returns a negative error code, otherwise zero.
  */
-int _dtls_record_check(gnutls_session_t session, uint64 * _seq)
+int _dtls_record_check(struct record_parameters_st *rp, uint64 * _seq)
 {
 uint64_t seq = 0, diff;
 unsigned int i, offset = 0;
 
-  seq |= _seq->i[0] & 0xff;
-  for (i=1;i<8;i++) 
+  for (i=2;i<8;i++)
     {
       seq <<= 8;
       seq |= _seq->i[i] & 0xff;
@@ -463,7 +462,7 @@ unsigned int i, offset = 0;
 
   if (window_size == DTLS_RECORD_WINDOW_SIZE) 
     {
-      rot_window(session, MOVE_SIZE);
+      rot_window(rp, MOVE_SIZE);
     }
 
   if (seq < window_table[window_size-1])
@@ -472,21 +471,9 @@ unsigned int i, offset = 0;
       diff = window_table[window_size-1] - seq;
 
       if (diff >= window_size) 
-        {
-          /* Probably an epoch change. Check if we can fit it */
-          if (window_table[0] == 0 || window_table[0]+1 == seq)
-            {
-              window_table[0] = seq;
-              return 0;
-            }
-          
-          if ((window_size-2)/2 < 2)
-            return -1;
+        return -1;
 
-          offset = 1 + seq % ((window_size-2)/2);
-        }
-      else
-        offset = window_size-1-diff;
+      offset = window_size-1-diff;
 
       if (window_table[offset] == seq)
         return -1;
@@ -517,7 +504,7 @@ unsigned int i, offset = 0;
             }
           else
             {
-              rot_window(session, diff);
+              rot_window(rp, diff);
               offset = diff + window_size-1;
               window_table[offset] = seq;
               window_size = offset + 1;            
diff --git a/lib/gnutls_dtls.h b/lib/gnutls_dtls.h
index 467b3e9..f8b1a72 100644
--- a/lib/gnutls_dtls.h
+++ b/lib/gnutls_dtls.h
@@ -31,7 +31,7 @@
 
 int _dtls_transmit(gnutls_session_t session);
 int _dtls_retransmit(gnutls_session_t session);
-int _dtls_record_check(gnutls_session_t session, uint64 * _seq);
+int _dtls_record_check(struct record_parameters_st *rp, uint64 * _seq);
 
 #define MAX_DTLS_TIMEOUT 60000
 
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 3069eb9..23349dd 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -124,6 +124,9 @@ typedef struct
 #define GNUTLS_MASTER_SIZE 48
 #define GNUTLS_RANDOM_SIZE 32
 
+/* DTLS */
+#define DTLS_RECORD_WINDOW_SIZE 64
+
 /* TLS Extensions */
 /* we can receive up to MAX_EXT_TYPES extensions.
  */
@@ -527,6 +530,10 @@ struct record_parameters_st
   gnutls_mac_algorithm_t mac_algorithm;
   gnutls_compression_method_t compression_algorithm;
 
+  /* for DTLS */
+  uint64_t record_sw[DTLS_RECORD_WINDOW_SIZE];
+  unsigned int record_sw_size;
+
   record_state_st read;
   record_state_st write;
   
@@ -593,8 +600,6 @@ typedef struct
   int free_rsa_params;
 } internal_params_st;
 
-#define DTLS_RECORD_WINDOW_SIZE 64
-
 /* DTLS session state
  */
 typedef struct
@@ -621,9 +626,6 @@ typedef struct
 
   unsigned int hsk_hello_verify_requests;
   
-  uint64_t record_sw[DTLS_RECORD_WINDOW_SIZE];
-  unsigned int record_sw_size;
-
   /* non blocking stuff variables */
   unsigned int blocking:1;
   /* starting time of current handshake */
diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c
index ebe1b1a..6e4406a 100644
--- a/lib/gnutls_record.c
+++ b/lib/gnutls_record.c
@@ -499,6 +499,13 @@ check_buffers (gnutls_session_t session, content_type_t 
type,
       ret = _gnutls_record_buffer_get (type, session, data, data_size, seq);
       if (ret < 0)
         {
+          if (IS_DTLS(session))
+            {
+              if (ret == GNUTLS_E_UNEXPECTED_PACKET)
+                {
+                  ret = GNUTLS_E_AGAIN;
+                }
+            }
           gnutls_assert ();
           return ret;
         }
@@ -1021,7 +1028,7 @@ begin:
    */
   if (IS_DTLS(session)) 
     {
-      ret = _dtls_record_check(session, packet_sequence);
+      ret = _dtls_record_check(record_params, packet_sequence);
       if (ret < 0)
         {
           _gnutls_audit_log(session, "Discarded duplicate message[%u]: %s\n",
diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c
index 3588d2e..354db34 100644
--- a/lib/gnutls_state.c
+++ b/lib/gnutls_state.c
@@ -386,8 +386,6 @@ gnutls_init (gnutls_session_t * session, unsigned int flags)
 
       (*session)->internals.dtls.retrans_timeout_ms = 1000;
       (*session)->internals.dtls.total_timeout_ms = 60000;
-
-      (*session)->internals.dtls.record_sw_size = 0;
     }
   else
     (*session)->internals.transport = GNUTLS_STREAM;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index c168152..b2b637b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -21,7 +21,7 @@
 
 SUBDIRS = . rsa-md5-collision pkcs1-padding pkcs8-decode pkcs12-decode \
        userid cert-tests key-id sha2 safe-renegotiation dsa scripts ecdsa \
-       slow
+       slow dtls
 
 if ENABLE_OPENPGP
 SUBDIRS += openpgp-certs
diff --git a/tests/safe-renegotiation/Makefile.am b/tests/dtls/Makefile.am
similarity index 63%
copy from tests/safe-renegotiation/Makefile.am
copy to tests/dtls/Makefile.am
index 4d084cb..1dda703 100644
--- a/tests/safe-renegotiation/Makefile.am
+++ b/tests/dtls/Makefile.am
@@ -1,5 +1,7 @@
 ## Process this file with automake to produce Makefile.in
-# Copyright (C) 2010, 2012 Free Software Foundation, Inc.
+# Copyright (C) 2012 Free Software Foundation, Inc.
+#
+# Author: Nikos Mavrogiannopoulos
 #
 # This file is part of GnuTLS.
 #
@@ -17,19 +19,29 @@
 # along with this file; if not, write to the Free Software Foundation,
 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
+dist_check_SCRIPTS = dtls
+
 AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS)
 AM_CPPFLAGS = \
+       -I$(top_srcdir)/gl                      \
+       -I$(top_builddir)/gl                    \
        -I$(top_srcdir)/lib/includes            \
-       -I$(top_builddir)/lib/includes
+       -I$(top_builddir)/lib/includes          \
+       -I$(top_srcdir)/extra/includes  \
+       -I$(top_builddir)/extra/includes        \
+       -I$(top_srcdir)/lib                     \
+       -I$(top_srcdir)/doc/examples
 
 AM_LDFLAGS = -no-install
-LDADD = ../libutils.la \
-       ../../lib/libgnutls.la $(LTLIBGCRYPT) $(LIBSOCKET)
+LDADD = ../../lib/libgnutls.la \
+       ../../gl/libgnu.la \
+       $(LIBSOCKET) $(INET_NTOP_LIB) $(INET_PTON_LIB)
+
+if !WINDOWS
 
-ctests = srn0 srn1 srn2 srn3 srn4 srn5
+check_PROGRAMS = dtls-stress
+TESTS = dtls
 
-check_PROGRAMS = $(ctests)
-TESTS = $(ctests)
-TESTS_ENVIRONMENT = $(VALGRIND)
+endif
 
-EXTRA_DIST = README suppressions.valgrind
+TESTS_ENVIRONMENT = EXEEXT=$(EXEEXT)
diff --git a/tests/cert-tests/aki b/tests/dtls/dtls
similarity index 57%
copy from tests/cert-tests/aki
copy to tests/dtls/dtls
index e0722a0..9d45bf6 100755
--- a/tests/cert-tests/aki
+++ b/tests/dtls/dtls
@@ -22,20 +22,14 @@
 
 set -e
 
-srcdir=${srcdir:-.}
-CERTTOOL=${CERTTOOL:-../../src/certtool$EXEEXT}
-
-$CERTTOOL --certificate-info --infile $srcdir/aki-cert.pem \
-         --outfile tmp-aki.pem
-
-diff $srcdir/aki-cert.pem tmp-aki.pem
-rc=$?
-
-rm -f tmp-aki.pem
-
-# We're done.
-if test "$rc" != "0"; then
-  exit $rc
+if test "${WINDIR}" != "";then
+  exit 77
 fi
 
+./dtls-stress -shello 021 -sfinished 01 -cfinished 012 SKeyExchange 
CKeyExchange CFinished >/dev/null 2>&1
+./dtls-stress -shello 012 -sfinished 10 -cfinished 210 SHello SKeyExchange 
SHelloDone  >/dev/null 2>&1
+./dtls-stress -shello 012 -sfinished 01 -cfinished 021 SHello SKeyExchange 
SHelloDone  >/dev/null 2>&1
+./dtls-stress -shello 021 -sfinished 01 -cfinished 201 SHello SHelloDone 
CChangeCipherSpec SChangeCipherSpec SFinished  >/dev/null 2>&1
+./dtls-stress -shello 102 -sfinished 01 -cfinished 120 SHello SHelloDone 
CKeyExchange CFinished SChangeCipherSpec SFinished  >/dev/null 2>&1
+
 exit 0
diff --git a/tests/dtls/dtls-stress.c b/tests/dtls/dtls-stress.c
new file mode 100644
index 0000000..86d8cf7
--- /dev/null
+++ b/tests/dtls/dtls-stress.c
@@ -0,0 +1,800 @@
+/*
+ * Copyright (C) 2012 Sean Buckheister
+ *
+ * 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
+ */
+
+#include <gnutls/gnutls.h>
+#include <gnutls/dtls.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <poll.h>
+#include <time.h>
+#include <wait.h>
+
+enum role {
+       SERVER,
+       CLIENT
+} role;
+
+int debug;
+int nonblock;
+
+int run_id;
+
+static const char* role_to_name(enum role role)
+{
+       if (role == SERVER) {
+               return "server";
+       } else {
+               return "client";
+       }
+}
+
+static void logfn(int level, const char* s)
+{
+       if (debug) {
+               fprintf(stdout, "%i %s|<%i> %s", run_id, role_to_name(role), 
level, s);
+       }
+}
+
+static void auditfn(gnutls_session_t session, const char* s)
+{
+       if (debug) {
+               fprintf(stdout, "%i %s| %s", run_id, role_to_name(role), s);
+       }
+}
+
+static void drop(const char* packet)
+{
+       if (debug) {
+               fprintf(stdout, "%i %s| dropping %s\n", run_id, 
role_to_name(role), packet);
+       }
+}
+
+
+typedef struct {
+       int count;
+} filter_packet_state_t;
+
+filter_packet_state_t state_packet_ServerHello = { 0 };
+filter_packet_state_t state_packet_ServerKeyExchange = { 0 };
+filter_packet_state_t state_packet_ServerHelloDone = { 0 };
+filter_packet_state_t state_packet_ClientKeyExchange = { 0 };
+filter_packet_state_t state_packet_ClientChangeCipherSpec = { 0 };
+filter_packet_state_t state_packet_ClientFinished = { 0 };
+filter_packet_state_t state_packet_ServerChangeCipherSpec = { 0 };
+filter_packet_state_t state_packet_ServerFinished = { 0 };
+
+typedef struct {
+       gnutls_datum_t packets[3];
+       int* order;
+       int count;
+} filter_permute_state_t;
+
+filter_permute_state_t state_permute_ServerHello = { { { 0, 0 }, { 0, 0 }, { 
0, 0 } }, 0, 0 };
+filter_permute_state_t state_permute_ServerFinished = { { { 0, 0 }, { 0, 0 }, 
{ 0, 0 } }, 0, 0 };
+filter_permute_state_t state_permute_ClientFinished = { { { 0, 0 }, { 0, 0 }, 
{ 0, 0 } }, 0, 0 };
+
+typedef void (*filter_fn)(gnutls_transport_ptr_t, const unsigned char*, 
size_t);
+
+filter_fn filter_chain[32];
+int filter_current_idx;
+
+static void filter_clear_state(void)
+{
+int i;
+
+       memset(&state_packet_ServerHello, 0, sizeof(state_packet_ServerHello));
+       memset(&state_packet_ServerKeyExchange, 0, 
sizeof(state_packet_ServerKeyExchange));
+       memset(&state_packet_ServerHelloDone, 0, 
sizeof(state_packet_ServerHelloDone));
+       memset(&state_packet_ClientKeyExchange, 0, 
sizeof(state_packet_ClientKeyExchange));
+       memset(&state_packet_ClientChangeCipherSpec, 0, 
sizeof(state_packet_ClientChangeCipherSpec));
+       memset(&state_packet_ServerChangeCipherSpec, 0, 
sizeof(state_packet_ServerChangeCipherSpec));
+       memset(&state_packet_ServerFinished, 0, 
sizeof(state_packet_ServerFinished));
+
+       for (i = 0; i < 3; i++) {
+               if (state_permute_ServerHello.packets[i].data) {
+                       free(state_permute_ServerHello.packets[i].data);
+               }
+               if (state_permute_ServerFinished.packets[i].data) {
+                       free(state_permute_ServerFinished.packets[i].data);
+               }
+               if (state_permute_ClientFinished.packets[i].data) {
+                       free(state_permute_ClientFinished.packets[i].data);
+               }
+       }
+
+       memset(&state_permute_ServerHello, 0, 
sizeof(state_permute_ServerHello));
+       memset(&state_permute_ServerFinished, 0, 
sizeof(state_permute_ServerFinished));
+       memset(&state_permute_ClientFinished, 0, 
sizeof(state_permute_ClientFinished));
+}
+
+static void filter_run_next(gnutls_transport_ptr_t fd,
+               const unsigned char* buffer, size_t len)
+{
+       filter_fn fn = filter_chain[filter_current_idx];
+       filter_current_idx++;
+       if (fn) {
+               fn(fd, buffer, len);
+       } else {
+               send((long int) fd, buffer, len, 0);
+       }
+}
+
+
+
+static int match_ServerHello(const unsigned char* buffer, size_t len)
+{
+       return role == SERVER && len >= 13 + 1 && buffer[0] == 22 && buffer[13] 
== 2;
+}
+
+static void filter_packet_ServerHello(gnutls_transport_ptr_t fd,
+               const unsigned char* buffer, size_t len)
+{
+       if (match_ServerHello(buffer, len) && state_packet_ServerHello.count++ 
< 3) {
+               drop("Server Hello");
+       } else {
+               filter_run_next(fd, buffer, len);
+       }
+}
+
+static int match_ServerKeyExchange(const unsigned char* buffer, size_t len)
+{
+       return role == SERVER && len >= 13 + 1 && buffer[0] == 22 && buffer[13] 
== 12;
+}
+
+static void filter_packet_ServerKeyExchange(gnutls_transport_ptr_t fd,
+               const unsigned char* buffer, size_t len)
+{
+       if (match_ServerKeyExchange(buffer, len) && 
state_packet_ServerKeyExchange.count++ < 3) {
+               drop("Server Key Exchange");
+       } else {
+               filter_run_next(fd, buffer, len);
+       }
+}
+
+static int match_ServerHelloDone(const unsigned char* buffer, size_t len)
+{
+       return role == SERVER && len >= 13 + 1 && buffer[0] == 22 && buffer[13] 
== 14;
+}
+
+static 
+void filter_packet_ServerHelloDone(gnutls_transport_ptr_t fd,
+               const unsigned char* buffer, size_t len)
+{
+       if (match_ServerHelloDone(buffer, len) && 
state_packet_ServerHelloDone.count++ < 3) {
+               drop("Server Hello Done");
+       } else {
+               filter_run_next(fd, buffer, len);
+       }
+}
+
+static
+int match_ClientKeyExchange(const unsigned char* buffer, size_t len)
+{
+       return role == CLIENT && len >= 13 + 1 && buffer[0] == 22 && buffer[13] 
== 16;
+}
+
+static
+void filter_packet_ClientKeyExchange(gnutls_transport_ptr_t fd,
+               const unsigned char* buffer, size_t len)
+{
+       if (match_ClientKeyExchange(buffer, len) && 
state_packet_ClientKeyExchange.count++ < 3) {
+               drop("Client Key Exchange");
+       } else {
+               filter_run_next(fd, buffer, len);
+       }
+}
+
+static
+int match_ClientChangeCipherSpec(const unsigned char* buffer, size_t len)
+{
+       return role == CLIENT && len >= 13 && buffer[0] == 20;
+}
+
+static
+void filter_packet_ClientChangeCipherSpec(gnutls_transport_ptr_t fd,
+               const unsigned char* buffer, size_t len)
+{
+       if (match_ClientChangeCipherSpec(buffer, len) && 
state_packet_ClientChangeCipherSpec.count++ < 3) {
+               drop("Client Change Cipher Spec");
+       } else {
+               filter_run_next(fd, buffer, len);
+       }
+}
+
+static
+int match_ClientFinished(const unsigned char* buffer, size_t len)
+{
+       return role == CLIENT && len >= 13 && buffer[0] == 22 && buffer[4] == 1;
+}
+
+static
+void filter_packet_ClientFinished(gnutls_transport_ptr_t fd,
+               const unsigned char* buffer, size_t len)
+{
+       if (match_ClientFinished(buffer, len) && 
state_packet_ClientFinished.count++ < 3) {
+               drop("Client Finished");
+       } else {
+               filter_run_next(fd, buffer, len);
+       }
+}
+
+static
+int match_ServerChangeCipherSpec(const unsigned char* buffer, size_t len)
+{
+       return role == SERVER && len >= 13 && buffer[0] == 20;
+}
+
+static
+void filter_packet_ServerChangeCipherSpec(gnutls_transport_ptr_t fd,
+               const unsigned char* buffer, size_t len)
+{
+       if (match_ServerChangeCipherSpec(buffer, len) && 
state_packet_ServerChangeCipherSpec.count++ < 3) {
+               drop("Server Change Cipher Spec");
+       } else {
+               filter_run_next(fd, buffer, len);
+       }
+}
+
+static
+int match_ServerFinished(const unsigned char* buffer, size_t len)
+{
+       return role == SERVER && len >= 13 && buffer[0] == 22 && buffer[4] == 1;
+}
+
+static
+void filter_packet_ServerFinished(gnutls_transport_ptr_t fd,
+               const unsigned char* buffer, size_t len)
+{
+       if (match_ServerFinished(buffer, len) && 
state_packet_ServerFinished.count++ < 3) {
+               drop("Server Finished");
+       } else {
+               filter_run_next(fd, buffer, len);
+       }
+}
+
+static
+void filter_permutete_state_free_buffer(filter_permute_state_t* state)
+{
+       int i;
+
+       for (i = 0; i < 3; i++) {
+               if (state->packets[i].data) {
+                       free(state->packets[i].data);
+               }
+       }
+}
+
+static
+void filter_permute_state_run(filter_permute_state_t* state, int packetCount,
+               gnutls_transport_ptr_t fd, const unsigned char* buffer, size_t 
len)
+{
+       unsigned char* data = malloc(len);
+       int packet = state->order[state->count];
+
+       memcpy(data, buffer, len);
+       state->packets[packet].data = data;
+       state->packets[packet].size = len;
+       state->count++;
+
+       if (state->count == packetCount) {
+               for (packet = 0; packet < packetCount; packet++) {
+                       filter_run_next(fd, state->packets[packet].data,
+                                       state->packets[packet].size);
+               }
+               filter_permutete_state_free_buffer(state);
+               state->count = 0;
+       }
+}
+
+static
+void filter_permute_ServerHello(gnutls_transport_ptr_t fd,
+               const unsigned char* buffer, size_t len)
+{
+       if (match_ServerHello(buffer, len)
+                       || match_ServerKeyExchange(buffer, len)
+                       || match_ServerHelloDone(buffer, len)) {
+               filter_permute_state_run(&state_permute_ServerHello, 3, fd, 
buffer, len);
+       } else {
+               filter_run_next(fd, buffer, len);
+       }
+}
+
+static
+void filter_permute_ServerFinished(gnutls_transport_ptr_t fd,
+               const unsigned char* buffer, size_t len)
+{
+       if (match_ServerChangeCipherSpec(buffer, len)
+                       || match_ServerFinished(buffer, len)) {
+               filter_permute_state_run(&state_permute_ServerFinished, 2, fd, 
buffer, len);
+       } else {
+               filter_run_next(fd, buffer, len);
+       }
+}
+
+static
+void filter_permute_ClientFinished(gnutls_transport_ptr_t fd,
+               const unsigned char* buffer, size_t len)
+{
+       if (match_ClientKeyExchange(buffer, len)
+                       || match_ClientChangeCipherSpec(buffer, len)
+                       || match_ClientFinished(buffer, len)) {
+               filter_permute_state_run(&state_permute_ClientFinished, 3, fd, 
buffer, len);
+       } else {
+               filter_run_next(fd, buffer, len);
+       }
+}
+
+
+static
+ssize_t writefn(gnutls_transport_ptr_t fd, const void* buffer, size_t len)
+{
+       filter_current_idx = 0;
+       filter_run_next(fd, (const unsigned char*) buffer, len);
+       return len;
+}
+
+static
+void await(int fd)
+{
+       if (nonblock) {
+               struct pollfd p = { fd, POLLIN, 0 };
+               poll(&p, 1, 100);
+       }
+}
+
+
+
+
+static
+gnutls_session_t session(int sock, int server)
+{
+       gnutls_session_t r;
+
+       gnutls_init(&r, GNUTLS_DATAGRAM | (server ? GNUTLS_SERVER : 
GNUTLS_CLIENT)
+                       | GNUTLS_NONBLOCK * nonblock);
+       gnutls_priority_set_direct(r, "NORMAL:+ANON-ECDH", 0);
+       gnutls_transport_set_ptr(r, (gnutls_transport_ptr_t) sock);
+
+       if (server) {
+               gnutls_anon_server_credentials_t cred;
+               gnutls_anon_allocate_server_credentials(&cred);
+               gnutls_credentials_set(r, GNUTLS_CRD_ANON, cred);
+       } else {
+               gnutls_anon_client_credentials_t cred;
+               gnutls_anon_allocate_client_credentials(&cred);
+               gnutls_credentials_set(r, GNUTLS_CRD_ANON, cred);
+       }
+
+       gnutls_transport_set_push_function(r, writefn);
+
+       gnutls_dtls_set_mtu(r, 1400);
+       gnutls_dtls_set_timeouts(r, 1000, 60000);
+
+       return r;
+}
+
+static
+int log_error(int code)
+{
+       if (code < 0 && code != GNUTLS_E_AGAIN) {
+               fprintf(stdout, "%i <%s tls> %s", run_id, role_to_name(role), 
gnutls_strerror(code));
+               if (gnutls_error_is_fatal(code)) {
+                       fprintf(stdout, " (fatal)\n");
+                       exit(1);
+               } else {
+                       fprintf(stdout, "\n");
+               }
+       }
+       return code;
+}
+
+timer_t killtimer_tid;
+
+static
+void reset_killtimer(void)
+{
+struct itimerspec tout = { { 0, 0 }, { 120, 0 } };
+
+       if (nonblock) {
+               return;
+       }
+       timer_settime(killtimer_tid, 0, &tout, 0);
+}
+
+static
+void setup_killtimer(void)
+{
+       struct sigevent sig;
+       struct itimerspec tout = { { 0, 0 }, { 240, 0 } };
+
+       memset(&sig, 0, sizeof(sig));
+       sig.sigev_notify = SIGEV_SIGNAL;
+       sig.sigev_signo = 15;
+       timer_create(CLOCK_MONOTONIC, &sig, &killtimer_tid);
+
+       timer_settime(killtimer_tid, 0, &tout, 0);
+}
+
+static
+void log_error_with_time(int err, time_t started)
+{
+       if (err < 0) {
+               if (err != GNUTLS_E_TIMEDOUT || (time(0) - started) >= 60) {
+                       log_error(err);
+               } else {
+                       fprintf(stdout, "{spurious}");
+                       log_error(err);
+               }
+               if (gnutls_error_is_fatal(err)) {
+                       exit(1);
+               }
+       }
+}
+
+static
+void client(int sock)
+{
+       gnutls_session_t s = session(sock, 0);
+       int err = 0;
+       time_t started = time(0);
+       const char* line = "foobar!";
+       char buffer[8192];
+       int len;
+
+       setup_killtimer();
+
+       do {
+               await(sock);
+               err = log_error(gnutls_handshake(s));
+               reset_killtimer();
+       } while (err != 0 && !gnutls_error_is_fatal(err));
+       log_error_with_time(err, started);
+       
+       started = time(0);
+       do {
+               err = gnutls_record_send(s, line, strlen(line));
+               reset_killtimer();
+       } while (err < 0 && !gnutls_error_is_fatal(err));
+       log_error_with_time(err, started);
+       
+       do {
+               await(sock);
+               len = gnutls_record_recv(s, buffer, sizeof(buffer));
+       } while (len < 0 && !gnutls_error_is_fatal(len));
+       if (len > 0 && strcmp(line, buffer) == 0) {
+               exit(0);
+       } else {
+               log_error(len);
+               exit(1);
+       }
+}
+
+static
+void server(int sock)
+{ 
+       gnutls_session_t s = session(sock, 1);
+       int err;
+       time_t started = time(0);
+
+       write(sock, &sock, 1);
+
+       setup_killtimer();
+
+       do {
+               await(sock);
+               err = log_error(gnutls_handshake(s));
+               reset_killtimer();
+       } while (err != 0 && !gnutls_error_is_fatal(err));
+       log_error_with_time(err, started);
+
+       for (;;) {
+               char buffer[8192];
+               int len;
+               do {
+                       await(sock);
+                       len = gnutls_record_recv(s, buffer, sizeof(buffer));
+                       reset_killtimer();
+               } while (len < 0 && !gnutls_error_is_fatal(len));
+               log_error_with_time(len, started);
+
+               gnutls_record_send(s, buffer, len);
+               exit(0);
+       }
+}
+
+#if 0
+static
+void udp_sockpair(int* socks)
+{
+       struct sockaddr_in6 sa = { AF_INET6, htons(30000), 0, in6addr_loopback, 
0 };
+       struct sockaddr_in6 sb = { AF_INET6, htons(20000), 0, in6addr_loopback, 
0 };
+
+       socks[0] = socket(AF_INET6, SOCK_DGRAM, 0);
+       socks[1] = socket(AF_INET6, SOCK_DGRAM, 0);
+
+       bind(socks[0], (struct sockaddr*) &sa, sizeof(sa));
+       bind(socks[1], (struct sockaddr*) &sb, sizeof(sb));
+
+       connect(socks[1], (struct sockaddr*) &sa, sizeof(sa));
+       connect(socks[0], (struct sockaddr*) &sb, sizeof(sb));
+}
+#endif
+
+static
+int run_test(void)
+{
+       int fds[2];
+       int pid1, pid2;
+       int status2;
+
+       socketpair(AF_LOCAL, SOCK_DGRAM, 0, fds);
+
+       if (nonblock) {
+               fcntl(fds[0], F_SETFL, (long) O_NONBLOCK);
+               fcntl(fds[1], F_SETFL, (long) O_NONBLOCK);
+       }
+
+       if (!(pid1 = fork())) {
+               setpgrp();
+               role = SERVER;
+               server(fds[1]);
+       }
+       read(fds[0], &status2, sizeof(status2));
+       if (!(pid2 = fork())) {
+               setpgrp();
+               role = CLIENT;
+               client(fds[0]);
+       }
+       waitpid(pid2, &status2, 0);
+       kill(pid1, 15);
+       waitpid(pid1, 0, 0);
+
+       close(fds[0]);
+       close(fds[1]);
+
+       if (WIFEXITED(status2)) {
+               return !!WEXITSTATUS(status2);
+       } else {
+               return 2;
+       }
+}
+
+static int permutations2[2][2]
+       = { { 0, 1 }, { 1, 0 } };
+static const char* permutations2names[2]
+       = { "01", "10" };
+static int permutations3[6][3]
+       = { { 0, 1, 2 }, { 0, 2, 1 },
+               { 1, 0, 2 }, { 1, 2, 0 },
+               { 2, 0, 1 }, { 2, 1, 0 } };
+static const char* permutations3names[6]
+       = { "012", "021", "102", "120", "201", "210" };
+static filter_fn filters[8]
+       = { filter_packet_ServerHello,
+               filter_packet_ServerKeyExchange,
+               filter_packet_ServerHelloDone,
+               filter_packet_ClientKeyExchange,
+               filter_packet_ClientChangeCipherSpec,
+               filter_packet_ClientFinished,
+               filter_packet_ServerChangeCipherSpec,
+               filter_packet_ServerFinished };
+static const char* filter_names[8]
+       = { "SHello",
+               "SKeyExchange",
+               "SHelloDone",
+               "CKeyExchange",
+               "CChangeCipherSpec",
+               "CFinished",
+               "SChangeCipherSpec",
+               "SFinished" };
+
+static
+int run_one_test(int dropMode, int serverFinishedPermute, int 
serverHelloPermute, int clientFinishedPermute)
+{
+       int fnIdx = 0;
+       int filterIdx, res;
+       run_id = ((dropMode * 2 + serverFinishedPermute) * 6 + 
serverHelloPermute) * 6 + clientFinishedPermute;
+
+       filter_clear_state();
+
+       filter_chain[fnIdx++] = filter_permute_ServerHello;
+       state_permute_ServerHello.order = permutations3[serverHelloPermute];
+
+       filter_chain[fnIdx++] = filter_permute_ServerFinished;
+       state_permute_ServerFinished.order = 
permutations2[serverFinishedPermute];
+       
+       filter_chain[fnIdx++] = filter_permute_ClientFinished;
+       state_permute_ClientFinished.order = 
permutations3[clientFinishedPermute];
+
+       if (dropMode) {
+               for (filterIdx = 0; filterIdx < 8; filterIdx++) {
+                       if (dropMode & (1 << filterIdx)) {
+                               filter_chain[fnIdx++] = filters[filterIdx];
+                       }
+               }
+       }
+       filter_chain[fnIdx++] = NULL;
+
+       res = run_test();
+
+       switch (res) {
+               case 0:
+                       fprintf(stdout, "%i ++ ", run_id);
+                       break;
+               case 1:
+                       fprintf(stdout, "%i -- ", run_id);
+                       break;
+               case 2:
+                       fprintf(stdout, "%i !! ", run_id);
+                       break;
+       }
+
+       fprintf(stdout, "SHello(%s), ", permutations3names[serverHelloPermute]);
+       fprintf(stdout, "SFinished(%s), ", 
permutations2names[serverFinishedPermute]);
+       fprintf(stdout, "CFinished(%s) :- ", 
permutations3names[clientFinishedPermute]);
+       if (dropMode) {
+               for (filterIdx = 0; filterIdx < 8; filterIdx++) {
+                       if (dropMode & (1 << filterIdx)) {
+                               if (dropMode & ((1 << filterIdx) - 1)) {
+                                       fprintf(stdout, ", ");
+                               }
+                               fprintf(stdout, "%s", filter_names[filterIdx]);
+                       }
+               }
+       }
+       fprintf(stdout, "\n");
+
+       if (res && debug) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+static
+void run_tests(int childcount)
+{
+       int children = 0;
+       int dropMode, serverFinishedPermute, serverHelloPermute, 
clientFinishedPermute;
+
+       for (dropMode = 0; dropMode != 1 << 8; dropMode++)
+       for (serverFinishedPermute = 0; serverFinishedPermute < 2; 
serverFinishedPermute++)
+       for (serverHelloPermute = 0; serverHelloPermute < 6; 
serverHelloPermute++)
+       for (clientFinishedPermute = 0; clientFinishedPermute < 6; 
clientFinishedPermute++) {
+               if (!fork()) {
+                       exit(run_one_test(dropMode, serverFinishedPermute, 
serverHelloPermute, clientFinishedPermute));
+               } else {
+                       children++;
+                       while (children >= childcount) {
+                               wait(0);
+                               children--;
+                       }
+               }
+       }
+
+       while (children > 0) {
+               wait(0);
+               children--;
+       }
+}
+
+
+
+int main(int argc, const char* argv[])
+{
+int arg;
+
+       setlinebuf(stdout);
+       gnutls_global_init();
+       gnutls_global_set_log_function(logfn);
+       gnutls_global_set_audit_log_function(auditfn);
+
+       nonblock = 0;
+       debug = 0;
+
+       if (argc == 1) {
+               run_tests(100);
+       } else {
+               int dropMode = 0;
+               int serverFinishedPermute = 0;
+               int serverHelloPermute = 0;
+               int clientFinishedPermute = 0;
+
+               for (arg = 1; arg < argc; arg++) {
+                       if (strcmp("-shello", argv[arg]) == 0) {
+                               arg++;
+                               if (arg >= argc) {
+                                       fprintf(stderr, "No arg to -shello\n");
+                                       exit(1);
+                               }
+                               while (serverHelloPermute < 6) {
+                                       if 
(strcmp(permutations3names[serverHelloPermute], argv[arg]) == 0) {
+                                               break;
+                                       }
+                                       serverHelloPermute++;
+                               }
+                               if (serverHelloPermute == 6) {
+                                       fprintf(stderr, "Unknown permutation 
%s\n", argv[arg]);
+                                       exit(1);
+                               }
+                       } else if (strcmp("-d", argv[arg]) == 0) {
+                               debug++;
+                       } else if (strcmp("-sfinished", argv[arg]) == 0) {
+                               arg++;
+                               if (arg >= argc) {
+                                       fprintf(stderr, "No arg to 
-sfinished\n");
+                                       exit(1);
+                               }
+                               while (serverFinishedPermute < 2) {
+                                       if 
(strcmp(permutations2names[serverFinishedPermute], argv[arg]) == 0) {
+                                               break;
+                                       }
+                                       serverFinishedPermute++;
+                               }
+                               if (serverFinishedPermute == 2) {
+                                       fprintf(stderr, "Unknown permutation 
%s\n", argv[arg]);
+                                       exit(1);
+                               }
+                       } else if (strcmp("-cfinished", argv[arg]) == 0) {
+                               arg++;
+                               if (arg >= argc) {
+                                       fprintf(stderr, "No arg to 
-cfinished\n");
+                                       exit(1);
+                               }
+                               while (clientFinishedPermute < 6) {
+                                       if 
(strcmp(permutations3names[clientFinishedPermute], argv[arg]) == 0) {
+                                               break;
+                                       }
+                                       clientFinishedPermute++;
+                               }
+                               if (clientFinishedPermute == 6) {
+                                       fprintf(stderr, "Unknown permutation 
%s\n", argv[arg]);
+                                       exit(1);
+                               }
+                       } else {
+                               int drop;
+                               for (drop = 0; drop < 8; drop++) {
+                                       if (strcmp(filter_names[drop], 
argv[arg]) == 0) {
+                                               dropMode |= (1 << drop);
+                                               break;
+                                       }
+                               }
+                               if (drop == 8) {
+                                       fprintf(stderr, "Unknown packet %s\n", 
argv[arg]);
+                                       exit(8);
+                               }
+                       }
+               }
+               
+               if (debug)
+                       gnutls_global_set_log_level(99);
+               run_one_test(dropMode, serverFinishedPermute, 
serverHelloPermute, clientFinishedPermute);
+       }
+
+       gnutls_global_deinit();
+}
+


hooks/post-receive
-- 
GNU gnutls



reply via email to

[Prev in Thread] Current Thread [Next in Thread]