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
main()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