1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* lib/gssapi/generic/t_seqstate.c - Test program for sequence number state */ 3 /* 4 * Copyright (C) 2014 by the Massachusetts Institute of Technology. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 30 * OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include "gssapiP_generic.h" 34 35 enum resultcode { 36 NOERR = GSS_S_COMPLETE, 37 GAP = GSS_S_GAP_TOKEN, 38 UNSEQ = GSS_S_UNSEQ_TOKEN, 39 OLD = GSS_S_OLD_TOKEN, 40 REPLAY = GSS_S_DUPLICATE_TOKEN 41 }; 42 43 enum replayflag { NO_REPLAY = 0, DO_REPLAY = 1 }; 44 enum sequenceflag { NO_SEQUENCE = 0, DO_SEQUENCE = 1 }; 45 enum width { NARROW = 0, WIDE = 1, BOTH = 2 }; 46 47 struct test { 48 uint64_t initial; 49 enum replayflag do_replay; 50 enum sequenceflag do_sequence; 51 enum width wide_seqnums; 52 size_t nseqs; 53 struct { 54 uint64_t seqnum; 55 enum resultcode result; 56 } seqs[10]; 57 } tests[] = { 58 /* No replay or sequence checking. */ 59 { 60 10, NO_REPLAY, NO_SEQUENCE, BOTH, 61 4, { { 11, NOERR }, { 10, NOERR }, { 10, NOERR }, { 9, NOERR } } 62 }, 63 64 /* Basic sequence checking, no wraparound. */ 65 { 66 100, NO_REPLAY, DO_SEQUENCE, BOTH, 67 4, { { 100, NOERR }, { 102, GAP }, { 103, NOERR }, { 101, UNSEQ } } 68 }, 69 70 /* Initial gap sequence checking, no wraparound. */ 71 { 72 200, NO_REPLAY, DO_SEQUENCE, BOTH, 73 4, { { 201, GAP }, { 202, NOERR }, { 200, UNSEQ }, { 203, NOERR } } 74 }, 75 76 /* Sequence checking with wraparound. */ 77 { 78 UINT32_MAX - 1, NO_REPLAY, DO_SEQUENCE, NARROW, 79 4, { { UINT32_MAX - 1, NOERR }, { UINT32_MAX, NOERR }, { 0, NOERR }, 80 { 1, NOERR } } 81 }, 82 { 83 UINT32_MAX - 1, NO_REPLAY, DO_SEQUENCE, NARROW, 84 4, { { UINT32_MAX - 1, NOERR }, { 0, GAP }, { UINT32_MAX, UNSEQ }, 85 { 1, NOERR } } 86 }, 87 { 88 UINT64_MAX - 1, NO_REPLAY, DO_SEQUENCE, WIDE, 89 4, { { UINT64_MAX - 1, NOERR }, { UINT64_MAX, NOERR }, { 0, NOERR }, 90 { 1, NOERR } } 91 }, 92 { 93 UINT64_MAX - 1, NO_REPLAY, DO_SEQUENCE, WIDE, 94 4, { { UINT64_MAX - 1, NOERR }, { 0, GAP }, { UINT64_MAX, UNSEQ }, 95 { 1, NOERR } } 96 }, 97 98 /* 64-bit sequence checking beyond 32-bit range */ 99 { 100 UINT32_MAX - 1, NO_REPLAY, DO_SEQUENCE, WIDE, 101 4, { { UINT32_MAX - 1, NOERR }, 102 { UINT32_MAX, NOERR }, 103 { (uint64_t)UINT32_MAX + 1, NOERR }, 104 { (uint64_t)UINT32_MAX + 2, NOERR } } 105 }, 106 { 107 UINT32_MAX - 1, NO_REPLAY, DO_SEQUENCE, WIDE, 108 4, { { UINT32_MAX - 1, NOERR }, 109 { (uint64_t)UINT32_MAX + 1, GAP }, 110 { UINT32_MAX, UNSEQ }, 111 { (uint64_t)UINT32_MAX + 2, NOERR } } 112 }, 113 { 114 UINT32_MAX - 1, NO_REPLAY, DO_SEQUENCE, WIDE, 115 3, { { UINT32_MAX - 1, NOERR }, { UINT32_MAX, NOERR }, { 0, GAP } } 116 }, 117 118 /* Replay without the replay flag set. */ 119 { 120 250, NO_REPLAY, DO_SEQUENCE, BOTH, 121 2, { { 250, NOERR }, { 250, UNSEQ } } 122 }, 123 124 /* Basic replay detection with and without sequence checking. */ 125 { 126 0, DO_REPLAY, DO_SEQUENCE, BOTH, 127 10, { { 5, GAP }, { 3, UNSEQ }, { 8, GAP }, { 3, REPLAY }, 128 { 0, UNSEQ }, { 0, REPLAY }, { 5, REPLAY }, { 3, REPLAY }, 129 { 8, REPLAY }, { 9, NOERR } } 130 }, 131 { 132 0, DO_REPLAY, NO_SEQUENCE, BOTH, 133 10, { { 5, NOERR }, { 3, NOERR }, { 8, NOERR }, { 3, REPLAY }, 134 { 0, NOERR }, { 0, REPLAY }, { 5, REPLAY }, { 3, REPLAY }, 135 { 8, REPLAY }, { 9, NOERR } } 136 }, 137 138 /* Replay and sequence detection with wraparound. The last seqnum produces 139 * GAP because it is before the initial sequence number. */ 140 { 141 UINT64_MAX - 5, DO_REPLAY, DO_SEQUENCE, WIDE, 142 10, { { UINT64_MAX, GAP }, { UINT64_MAX - 2, UNSEQ }, { 0, NOERR }, 143 { UINT64_MAX, REPLAY }, { UINT64_MAX, REPLAY }, 144 { 2, GAP }, { 0, REPLAY }, { 1, UNSEQ }, 145 { UINT64_MAX - 2, REPLAY }, { UINT64_MAX - 6, GAP } } 146 }, 147 { 148 UINT32_MAX - 5, DO_REPLAY, DO_SEQUENCE, NARROW, 149 10, { { UINT32_MAX, GAP }, { UINT32_MAX - 2, UNSEQ }, { 0, NOERR }, 150 { UINT32_MAX, REPLAY }, { UINT32_MAX, REPLAY }, 151 { 2, GAP }, { 0, REPLAY }, { 1, UNSEQ }, 152 { UINT32_MAX - 2, REPLAY }, { UINT32_MAX - 6, GAP } } 153 }, 154 155 /* Old token edge cases. The current code can detect replays up to 64 156 * numbers behind the expected sequence number (1164 in this case). */ 157 { 158 1000, DO_REPLAY, NO_SEQUENCE, BOTH, 159 10, { { 1163, NOERR }, { 1100, NOERR }, { 1100, REPLAY }, 160 { 1163, REPLAY }, { 1099, OLD }, { 1100, REPLAY }, 161 { 1150, NOERR }, { 1150, REPLAY }, { 1000, OLD }, 162 { 999, NOERR } } 163 }, 164 }; 165 166 int 167 main() 168 { 169 size_t i, j; 170 enum width w; 171 struct test *t; 172 g_seqnum_state seqstate; 173 OM_uint32 status; 174 175 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { 176 t = &tests[i]; 177 /* Try both widths if t->wide_seqnums is both, otherwise just one. */ 178 for (w = NARROW; w <= WIDE; w++) { 179 if (t->wide_seqnums != BOTH && t->wide_seqnums != w) 180 continue; 181 if (g_seqstate_init(&seqstate, t->initial, t->do_replay, 182 t->do_sequence, w)) 183 abort(); 184 for (j = 0; j < t->nseqs; j++) { 185 status = g_seqstate_check(seqstate, t->seqs[j].seqnum); 186 if (status != t->seqs[j].result) { 187 fprintf(stderr, "Test %d seq %d failed: %d != %d\n", 188 (int)i, (int)j, status, t->seqs[j].result); 189 return 1; 190 } 191 } 192 g_seqstate_free(seqstate); 193 } 194 } 195 196 return 0; 197 } 198