Add tests for GSSAPI sequence number processing
authorGreg Hudson <ghudson@mit.edu>
Wed, 12 Mar 2014 15:03:48 +0000 (11:03 -0400)
committerGreg Hudson <ghudson@mit.edu>
Tue, 18 Mar 2014 15:55:39 +0000 (11:55 -0400)
ticket: 7872

.gitignore
src/lib/gssapi/generic/Makefile.in
src/lib/gssapi/generic/deps
src/lib/gssapi/generic/t_seqstate.c [new file with mode: 0644]

index 828a504c034fd52cf1109f5ffe27087d1e117322..012175218c7084e75a9cd5d056dec4b4d3e636be 100644 (file)
@@ -168,6 +168,7 @@ testlog
 /src/lib/gssapi/generic/errmap.h
 /src/lib/gssapi/generic/gssapi.h
 /src/lib/gssapi/generic/gssapi_err_generic.[ch]
+/src/lib/gssapi/generic/t_seqstate
 
 /src/lib/gssapi/krb5/error_map.h
 /src/lib/gssapi/krb5/gssapi_err_krb5.[ch]
index c34cba4593c5fe05a3e42ad143ac1fde3a989e8e..04049a655d9f7874872feb5c368c7006684e5d09 100644 (file)
@@ -71,6 +71,8 @@ SRCS = \
        $(srcdir)/util_token.c \
        gssapi_err_generic.c
 
+EXTRADEPSRCS = t_seqstate.c
+
 OBJS = \
        $(OUTPRE)disp_com_err_status.$(OBJEXT) \
        $(OUTPRE)disp_major_status.$(OBJEXT) \
@@ -138,11 +140,18 @@ win-create-ehdrdir:
 clean-unix:: clean-libobjs
        $(RM) $(ETHDRS) $(ETSRCS) $(HDRS) $(EXPORTED_BUILT_HEADERS) \
                $(EHDRDIR)$(S)timestamp errmap.h maptest.h
+       $(RM) t_seqstate.o t_seqstate
 
 clean-windows::
        $(RM) $(HDRS) maptest.h
        -if exist $(EHDRDIR)\nul rmdir $(EHDRDIR)
 
+t_seqstate: t_seqstate.o util_ordering.o
+       $(CC_LINK) $(ALL_CFLAGS) -o $@ t_seqstate.o util_ordering.o
+
+check-unix:: t_seqstate
+       $(RUN_SETUP) $(VALGRIND) ./t_seqstate
+
 generate-files-mac: gssapi.h errmap.h
 
 # Krb5InstallHeaders($(EXPORTED_HEADERS), $(KRB5_INCDIR)/krb5)
index 9d5a0733d6ff4783d64d14a60d730c5763a16fe4..41a967bcac45aaee98ce79821255ceb8ec6a8960 100644 (file)
@@ -87,3 +87,10 @@ util_token.so util_token.po $(OUTPRE)util_token.$(OBJEXT): \
   util_token.c
 gssapi_err_generic.so gssapi_err_generic.po $(OUTPRE)gssapi_err_generic.$(OBJEXT): \
   $(COM_ERR_DEPS) gssapi_err_generic.c
+t_seqstate.so t_seqstate.po $(OUTPRE)t_seqstate.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(COM_ERR_DEPS) \
+  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \
+  $(top_srcdir)/include/k5-thread.h gssapiP_generic.h \
+  gssapi_err_generic.h gssapi_ext.h gssapi_generic.h \
+  t_seqstate.c
diff --git a/src/lib/gssapi/generic/t_seqstate.c b/src/lib/gssapi/generic/t_seqstate.c
new file mode 100644 (file)
index 0000000..6be4b2e
--- /dev/null
@@ -0,0 +1,188 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/gssapi/generic/t_seqstate.c - Test program for sequence number state */
+/*
+ * Copyright (C) 2014 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gssapiP_generic.h"
+
+enum resultcode {
+    NOERR = GSS_S_COMPLETE,
+    GAP = GSS_S_GAP_TOKEN,
+    UNSEQ = GSS_S_UNSEQ_TOKEN,
+    OLD = GSS_S_OLD_TOKEN,
+    REPLAY = GSS_S_DUPLICATE_TOKEN
+};
+
+enum replayflag { NO_REPLAY = 0, DO_REPLAY = 1 };
+enum sequenceflag { NO_SEQUENCE = 0, DO_SEQUENCE = 1 };
+enum width { NARROW = 0, WIDE = 1, BOTH = 2 };
+
+struct test {
+    uint64_t initial;
+    enum replayflag do_replay;
+    enum sequenceflag do_sequence;
+    enum width wide_seqnums;
+    size_t nseqs;
+    struct {
+        uint64_t seqnum;
+        enum resultcode result;
+    } seqs[10];
+} tests[] = {
+    /* No replay or sequence checking. */
+    {
+        10, NO_REPLAY, NO_SEQUENCE, BOTH,
+        4, { { 11, NOERR }, { 10, NOERR }, { 10, NOERR }, { 9, NOERR } }
+    },
+
+    /* Basic sequence checking, no wraparound. */
+    {
+        100, NO_REPLAY, DO_SEQUENCE, BOTH,
+        4, { { 100, NOERR }, { 102, GAP }, { 103, NOERR }, { 101, UNSEQ } }
+    },
+
+    /* Initial gap sequence checking, no wraparound. */
+    {
+        200, NO_REPLAY, DO_SEQUENCE, BOTH,
+        4, { { 201, GAP }, { 202, NOERR }, { 200, UNSEQ }, { 203, NOERR } }
+    },
+
+    /* Sequence checking with wraparound. */
+    {
+        UINT32_MAX - 1, NO_REPLAY, DO_SEQUENCE, NARROW,
+        4, { { UINT32_MAX - 1, NOERR }, { UINT32_MAX, NOERR }, { 0, NOERR },
+             { 1, NOERR } }
+    },
+    {
+        UINT32_MAX - 1, NO_REPLAY, DO_SEQUENCE, NARROW,
+        4, { { UINT32_MAX - 1, NOERR }, { 0, GAP }, { UINT32_MAX, UNSEQ },
+             { 1, NOERR } }
+    },
+    {
+        UINT64_MAX - 1, NO_REPLAY, DO_SEQUENCE, WIDE,
+        4, { { UINT64_MAX - 1, NOERR }, { UINT64_MAX, NOERR }, { 0, NOERR },
+             { 1, NOERR } }
+    },
+    {
+        UINT64_MAX - 1, NO_REPLAY, DO_SEQUENCE, WIDE,
+        4, { { UINT64_MAX - 1, NOERR }, { 0, GAP }, { UINT64_MAX, UNSEQ },
+             { 1, NOERR } }
+    },
+
+    /* 64-bit sequence checking beyond 32-bit range */
+    {
+        UINT32_MAX - 1, NO_REPLAY, DO_SEQUENCE, WIDE,
+        4, { { UINT32_MAX - 1, NOERR },
+             { UINT32_MAX, NOERR },
+             { (uint64_t)UINT32_MAX + 1, NOERR },
+             { (uint64_t)UINT32_MAX + 2, NOERR } }
+    },
+    {
+        UINT32_MAX - 1, NO_REPLAY, DO_SEQUENCE, WIDE,
+        4, { { UINT32_MAX - 1, NOERR },
+             { (uint64_t)UINT32_MAX + 1, GAP },
+             { UINT32_MAX, UNSEQ },
+             { (uint64_t)UINT32_MAX + 2, NOERR } }
+    },
+    {
+        UINT32_MAX - 1, NO_REPLAY, DO_SEQUENCE, WIDE,
+        3, { { UINT32_MAX - 1, NOERR }, { UINT32_MAX, NOERR }, { 0, GAP } }
+    },
+
+    /* Replay without the replay flag set.  Current code reports a replay
+     * anyway. */
+    {
+        250, NO_REPLAY, DO_SEQUENCE, BOTH,
+        2, { { 250, NOERR }, { 250, REPLAY } }
+    },
+
+    /* Basic replay detection with and without sequence checking. */
+    {
+        0, DO_REPLAY, DO_SEQUENCE, BOTH,
+        10, { { 5, GAP }, { 3, UNSEQ }, { 8, GAP }, { 3, REPLAY },
+              { 0, UNSEQ }, { 0, REPLAY }, { 5, REPLAY }, { 3, REPLAY },
+              { 8, REPLAY }, { 9, NOERR } }
+    },
+    {
+        0, DO_REPLAY, NO_SEQUENCE, BOTH,
+        10, { { 5, NOERR }, { 3, NOERR }, { 8, NOERR }, { 3, REPLAY },
+              { 0, NOERR }, { 0, REPLAY }, { 5, REPLAY }, { 3, REPLAY },
+              { 8, REPLAY }, { 9, NOERR } }
+    },
+
+    /* Replay and sequence detection with wraparound.  The last seqnum produces
+     * GAP because it is before the initial sequence number. */
+    {
+        UINT64_MAX - 5, DO_REPLAY, DO_SEQUENCE, WIDE,
+        10, { { UINT64_MAX, GAP }, { UINT64_MAX - 2, UNSEQ }, { 0, NOERR },
+              { UINT64_MAX, REPLAY }, { UINT64_MAX, REPLAY },
+              { 2, GAP }, { 0, REPLAY }, { 1, UNSEQ },
+              { UINT64_MAX - 2, REPLAY }, { UINT64_MAX - 6, GAP } }
+    },
+    {
+        UINT32_MAX - 5, DO_REPLAY, DO_SEQUENCE, NARROW,
+        10, { { UINT32_MAX, GAP }, { UINT32_MAX - 2, UNSEQ }, { 0, NOERR },
+              { UINT32_MAX, REPLAY }, { UINT32_MAX, REPLAY },
+              { 2, GAP }, { 0, REPLAY }, { 1, UNSEQ },
+              { UINT32_MAX - 2, REPLAY }, { UINT32_MAX - 6, GAP } }
+    },
+};
+
+int
+main()
+{
+    size_t i, j;
+    enum width w;
+    struct test *t;
+    void *seqstate;
+    OM_uint32 status;
+
+    for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
+        t = &tests[i];
+        /* Try both widths if t->wide_seqnums is both, otherwise just one. */
+        for (w = NARROW; w <= WIDE; w++) {
+            if (t->wide_seqnums != BOTH && t->wide_seqnums != w)
+                continue;
+            if (g_order_init(&seqstate, t->initial, t->do_replay,
+                             t->do_sequence, w))
+                abort();
+            for (j = 0; j < t->nseqs; j++) {
+                status = g_order_check(&seqstate, t->seqs[j].seqnum);
+                if (status != t->seqs[j].result) {
+                    fprintf(stderr, "Test %d seq %d failed: %d != %d\n",
+                            (int)i, (int)j, status, t->seqs[j].result);
+                    return 1;
+                }
+            }
+            g_order_free(&seqstate);
+        }
+    }
+
+    return 0;
+}