summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2014-03-12 12:13:08 -0400
committerGreg Hudson <ghudson@mit.edu>2014-03-18 11:59:11 -0400
commitcb3db58b1942998a5e2c4d46c21ca0554e769a8c (patch)
tree205cfad4498d8aa5003167b5617cca9a9e3d22a9
parent23a378046bd8122839e501b3e47bb807b66e1c03 (diff)
downloadkrb5-cb3db58b1942998a5e2c4d46c21ca0554e769a8c.tar.gz
krb5-cb3db58b1942998a5e2c4d46c21ca0554e769a8c.tar.xz
krb5-cb3db58b1942998a5e2c4d46c21ca0554e769a8c.zip
Rewrite GSS sequence state tracking code
Replace util_ordering.c with a new file util_seqstate.c, implemented using a bitmap of previously received sequence numbers instead of a 20-element circular queue. This approach has slightly different limitations--it can check for replays for values within 64 of the expected next number, where the old code could check within the range of the last 20 received numbers regardless of how far apart they are. The new approach should work as well or better for any realistic packet reordering scenario. ticket: 7879 (new)
-rw-r--r--src/lib/gssapi/generic/Makefile.in10
-rw-r--r--src/lib/gssapi/generic/deps8
-rw-r--r--src/lib/gssapi/generic/t_seqstate.c15
-rw-r--r--src/lib/gssapi/generic/util_ordering.c259
-rw-r--r--src/lib/gssapi/generic/util_seqstate.c163
-rw-r--r--src/util/gss-kernel-lib/Makefile.in8
-rw-r--r--src/util/gss-kernel-lib/deps4
7 files changed, 190 insertions, 277 deletions
diff --git a/src/lib/gssapi/generic/Makefile.in b/src/lib/gssapi/generic/Makefile.in
index 04049a655..530a0a96e 100644
--- a/src/lib/gssapi/generic/Makefile.in
+++ b/src/lib/gssapi/generic/Makefile.in
@@ -66,8 +66,8 @@ SRCS = \
$(srcdir)/util_buffer.c \
$(srcdir)/util_buffer_set.c \
$(srcdir)/util_errmap.c \
- $(srcdir)/util_ordering.c \
$(srcdir)/util_set.c \
+ $(srcdir)/util_seqstate.c \
$(srcdir)/util_token.c \
gssapi_err_generic.c
@@ -83,8 +83,8 @@ OBJS = \
$(OUTPRE)util_buffer.$(OBJEXT) \
$(OUTPRE)util_buffer_set.$(OBJEXT) \
$(OUTPRE)util_errmap.$(OBJEXT) \
- $(OUTPRE)util_ordering.$(OBJEXT) \
$(OUTPRE)util_set.$(OBJEXT) \
+ $(OUTPRE)util_seqstate.$(OBJEXT) \
$(OUTPRE)util_token.$(OBJEXT) \
$(OUTPRE)gssapi_err_generic.$(OBJEXT)
@@ -98,8 +98,8 @@ STLIBOBJS = \
util_buffer.o \
util_buffer_set.o \
util_errmap.o \
- util_ordering.o \
util_set.o \
+ util_seqstate.o \
util_token.o \
gssapi_err_generic.o
@@ -146,8 +146,8 @@ 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
+t_seqstate: t_seqstate.o util_seqstate.o
+ $(CC_LINK) $(ALL_CFLAGS) -o $@ t_seqstate.o util_seqstate.o
check-unix:: t_seqstate
$(RUN_SETUP) $(VALGRIND) ./t_seqstate
diff --git a/src/lib/gssapi/generic/deps b/src/lib/gssapi/generic/deps
index 41a967bca..5b80e7f38 100644
--- a/src/lib/gssapi/generic/deps
+++ b/src/lib/gssapi/generic/deps
@@ -64,20 +64,20 @@ util_errmap.so util_errmap.po $(OUTPRE)util_errmap.$(OBJEXT): \
$(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \
errmap.h gssapiP_generic.h gssapi_err_generic.h gssapi_ext.h \
gssapi_generic.h util_errmap.c
-util_ordering.so util_ordering.po $(OUTPRE)util_ordering.$(OBJEXT): \
+util_set.so util_set.po $(OUTPRE)util_set.$(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 \
- util_ordering.c
-util_set.so util_set.po $(OUTPRE)util_set.$(OBJEXT): \
+ util_set.c
+util_seqstate.so util_seqstate.po $(OUTPRE)util_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 \
- util_set.c
+ util_seqstate.c
util_token.so util_token.po $(OUTPRE)util_token.$(OBJEXT): \
$(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
$(BUILDTOP)/include/gssapi/gssapi_alloc.h $(COM_ERR_DEPS) \
diff --git a/src/lib/gssapi/generic/t_seqstate.c b/src/lib/gssapi/generic/t_seqstate.c
index c7250b9ad..8f44fcf3e 100644
--- a/src/lib/gssapi/generic/t_seqstate.c
+++ b/src/lib/gssapi/generic/t_seqstate.c
@@ -115,11 +115,10 @@ struct test {
3, { { UINT32_MAX - 1, NOERR }, { UINT32_MAX, NOERR }, { 0, GAP } }
},
- /* Replay without the replay flag set. Current code reports a replay
- * anyway. */
+ /* Replay without the replay flag set. */
{
250, NO_REPLAY, DO_SEQUENCE, BOTH,
- 2, { { 250, NOERR }, { 250, REPLAY } }
+ 2, { { 250, NOERR }, { 250, UNSEQ } }
},
/* Basic replay detection with and without sequence checking. */
@@ -152,6 +151,16 @@ struct test {
{ 2, GAP }, { 0, REPLAY }, { 1, UNSEQ },
{ UINT32_MAX - 2, REPLAY }, { UINT32_MAX - 6, GAP } }
},
+
+ /* Old token edge cases. The current code can detect replays up to 64
+ * numbers behind the expected sequence number (1164 in this case). */
+ {
+ 1000, DO_REPLAY, NO_SEQUENCE, BOTH,
+ 10, { { 1163, NOERR }, { 1100, NOERR }, { 1100, REPLAY },
+ { 1163, REPLAY }, { 1099, OLD }, { 1100, REPLAY },
+ { 1150, NOERR }, { 1150, REPLAY }, { 1000, OLD },
+ { 999, NOERR } }
+ },
};
int
diff --git a/src/lib/gssapi/generic/util_ordering.c b/src/lib/gssapi/generic/util_ordering.c
deleted file mode 100644
index d6feed10d..000000000
--- a/src/lib/gssapi/generic/util_ordering.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- * Copyright 1993 by OpenVision Technologies, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appears in all copies and
- * that both that copyright notice and this permission notice appear in
- * supporting documentation, and that the name of OpenVision not be used
- * in advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission. OpenVision makes no
- * representations about the suitability of this software for any
- * purpose. It is provided "as is" without express or implied warranty.
- *
- * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
- * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
- * $Id$
- */
-
-/*
- * functions to check sequence numbers for replay and sequencing
- */
-
-#include "gssapiP_generic.h"
-#include <string.h>
-
-#define QUEUE_LENGTH 20
-
-typedef struct g_seqnum_state_st {
- int do_replay;
- int do_sequence;
- int start;
- int length;
- uint64_t firstnum;
- /* Stored as deltas from firstnum. This way, the high bit won't
- overflow unless we've actually gone through 2**n messages, or
- gotten something *way* out of sequence. */
- uint64_t elem[QUEUE_LENGTH];
- /* All ones for 64-bit sequence numbers; 32 ones for 32-bit
- sequence numbers. */
- uint64_t mask;
-} queue;
-
-/* rep invariant:
- * - the queue is a circular queue. The first element (q->elem[q->start])
- * is the oldest. The last element is the newest.
- */
-
-#define QSIZE(q) (sizeof((q)->elem)/sizeof((q)->elem[0]))
-#define QELEM(q,i) ((q)->elem[(i)%QSIZE(q)])
-
-static void
-queue_insert(queue *q, int after, uint64_t seqnum)
-{
- /* insert. this is not the fastest way, but it's easy, and it's
- optimized for insert at end, which is the common case */
- int i;
-
- /* common case: at end, after == q->start+q->length-1 */
-
- /* move all the elements (after,last] up one slot */
-
- for (i=q->start+q->length-1; i>after; i--)
- QELEM(q,i+1) = QELEM(q,i);
-
- /* fill in slot after+1 */
-
- QELEM(q,after+1) = seqnum;
-
- /* Either increase the length by one, or move the starting point up
- one (deleting the first element, which got bashed above), as
- appropriate. */
-
- if (q->length == QSIZE(q)) {
- q->start++;
- if (q->start == QSIZE(q))
- q->start = 0;
- } else {
- q->length++;
- }
-}
-
-long
-g_seqstate_init(g_seqnum_state *state_out, uint64_t seqnum,
- int do_replay, int do_sequence, int wide_nums)
-{
- queue *q;
-
- if ((q = (queue *) malloc(sizeof(queue))) == NULL)
- return(ENOMEM);
-
- /* This stops valgrind from complaining about writing uninitialized
- data if the caller exports the context and writes it to a file.
- We don't actually use those bytes at all, but valgrind still
- complains. */
- memset(q, 0xfe, sizeof(*q));
-
- q->do_replay = do_replay;
- q->do_sequence = do_sequence;
- q->mask = wide_nums ? ~(uint64_t)0 : 0xffffffffUL;
-
- q->start = 0;
- q->length = 1;
- q->firstnum = seqnum;
- q->elem[q->start] = ((uint64_t)0 - 1) & q->mask;
-
- *state_out = q;
- return(0);
-}
-
-OM_uint32
-g_seqstate_check(g_seqnum_state q, uint64_t seqnum)
-{
- int i;
- uint64_t expected;
-
- if (!q->do_replay && !q->do_sequence)
- return(GSS_S_COMPLETE);
-
- /* All checks are done relative to the initial sequence number, to
- avoid (or at least put off) the pain of wrapping. */
- seqnum -= q->firstnum;
- /* If we're only doing 32-bit values, adjust for that again.
-
- Note that this will probably be the wrong thing to if we get
- 2**32 messages sent with 32-bit sequence numbers. */
- seqnum &= q->mask;
-
- /* rule 1: expected sequence number */
-
- expected = (QELEM(q,q->start+q->length-1)+1) & q->mask;
- if (seqnum == expected) {
- queue_insert(q, q->start+q->length-1, seqnum);
- return(GSS_S_COMPLETE);
- }
-
- /* rule 2: > expected sequence number */
-
- if ((seqnum > expected)) {
- queue_insert(q, q->start+q->length-1, seqnum);
- if (q->do_replay && !q->do_sequence)
- return(GSS_S_COMPLETE);
- else
- return(GSS_S_GAP_TOKEN);
- }
-
- /* rule 3: seqnum < seqnum(first) */
-
- if ((seqnum < QELEM(q,q->start)) &&
- /* Is top bit of whatever width we're using set?
-
- We used to check for greater than or equal to firstnum, but
- (1) we've since switched to compute values relative to
- firstnum, so the lowest we can have is 0, and (2) the effect
- of the original scheme was highly dependent on whether
- firstnum was close to either side of 0. (Consider
- firstnum==0xFFFFFFFE and we miss three packets; the next
- packet is *new* but would look old.)
-
- This check should give us 2**31 or 2**63 messages "new", and
- just as many "old". That's not quite right either. */
- (seqnum & (1 + (q->mask >> 1)))
- ) {
- if (q->do_replay && !q->do_sequence)
- return(GSS_S_OLD_TOKEN);
- else
- return(GSS_S_UNSEQ_TOKEN);
- }
-
- /* rule 4+5: seqnum in [seqnum(first),seqnum(last)] */
-
- else {
- if (seqnum == QELEM(q,q->start+q->length-1))
- return(GSS_S_DUPLICATE_TOKEN);
-
- for (i=q->start; i<q->start+q->length-1; i++) {
- if (seqnum == QELEM(q,i))
- return(GSS_S_DUPLICATE_TOKEN);
- if ((seqnum > QELEM(q,i)) && (seqnum < QELEM(q,i+1))) {
- queue_insert(q, i, seqnum);
- if (q->do_replay && !q->do_sequence)
- return(GSS_S_COMPLETE);
- else
- return(GSS_S_UNSEQ_TOKEN);
- }
- }
- /*
- * Exception: if first token arrived out-of-order.
- * In that case first two elements in queue are 0xFFFFFFFF and some k,
- * where k > seqnum. We need to insert seqnum before k.
- * We check this after the for-loop, because this should be rare.
- */
- if ((QELEM(q, q->start) == (((uint64_t)0 - 1) & q->mask)) &&
- ((QELEM(q, q->start + 1) > seqnum))) {
- queue_insert(q, q->start, seqnum);
- if (q->do_replay && !q->do_sequence)
- return(GSS_S_COMPLETE);
- else
- return(GSS_S_UNSEQ_TOKEN);
-
- }
- }
-
- /* this should never happen */
- return(GSS_S_FAILURE);
-}
-
-void
-g_seqstate_free(g_seqnum_state q)
-{
- free(q);
-}
-
-/*
- * These support functions are for the serialization routines
- */
-void
-g_seqstate_size(g_seqnum_state q, size_t *sizep)
-{
- *sizep += sizeof(*q);
-}
-
-long
-g_seqstate_externalize(g_seqnum_state q, unsigned char **buf,
- size_t *lenremain)
-{
- if (*lenremain < sizeof(*q))
- return ENOMEM;
- memcpy(*buf, q, sizeof(*q));
- *buf += sizeof(*q);
- *lenremain -= sizeof(*q);
-
- return 0;
-}
-
-long
-g_seqstate_internalize(g_seqnum_state *state_out, unsigned char **buf,
- size_t *lenremain)
-{
- queue *q;
-
- if (*lenremain < sizeof(*q))
- return EINVAL;
- if ((q = malloc(sizeof(*q))) == 0)
- return ENOMEM;
- memcpy(q, *buf, sizeof(*q));
- *buf += sizeof(*q);
- *lenremain -= sizeof(*q);
- *state_out = q;
- return 0;
-}
diff --git a/src/lib/gssapi/generic/util_seqstate.c b/src/lib/gssapi/generic/util_seqstate.c
new file mode 100644
index 000000000..a0bc2cc1c
--- /dev/null
+++ b/src/lib/gssapi/generic/util_seqstate.c
@@ -0,0 +1,163 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/gssapi/generic/util_seqstate.c - sequence number checking */
+/*
+ * 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"
+#include <string.h>
+
+struct g_seqnum_state_st {
+ /* Flags to indicate whether we are supposed to check for replays or
+ * enforce strict sequencing. */
+ int do_replay;
+ int do_sequence;
+
+ /* UINT32_MAX for 32-bit sequence numbers, UINT64_MAX for 64-bit. Mask
+ * against this after arithmetic to stay within the correct range. */
+ uint64_t seqmask;
+
+ /* The initial sequence number for this context. This value will be
+ * subtracted from all received sequence numbers to simplify wraparound. */
+ uint64_t base;
+
+ /* The expected next sequence number (one more than the highest previously
+ * seen sequence number), relative to base. */
+ uint64_t next;
+
+ /*
+ * A bitmap for the 64 sequence numbers prior to next. If the 1<<(i-1) bit
+ * is set, then we have seen seqnum next-i relative to base. The least
+ * significant bit is always set if we have received any sequence numbers,
+ * and indicates the highest sequence number we have seen (next-1). When
+ * we advance next, we shift recvmap to the left.
+ */
+ uint64_t recvmap;
+};
+
+long
+g_seqstate_init(g_seqnum_state *state_out, uint64_t seqnum, int do_replay,
+ int do_sequence, int wide)
+{
+ g_seqnum_state state;
+
+ *state_out = NULL;
+ state = malloc(sizeof(*state));
+ if (state == NULL)
+ return ENOMEM;
+ state->do_replay = do_replay;
+ state->do_sequence = do_sequence;
+ state->seqmask = wide ? UINT64_MAX : UINT32_MAX;
+ state->base = seqnum;
+ state->next = state->recvmap = 0;
+ *state_out = state;
+ return 0;
+}
+
+OM_uint32
+g_seqstate_check(g_seqnum_state state, uint64_t seqnum)
+{
+ uint64_t rel_seqnum, offset, bit;
+
+ if (!state->do_replay && !state->do_sequence)
+ return GSS_S_COMPLETE;
+
+ /* Use the difference from the base seqnum, to simplify wraparound. */
+ rel_seqnum = (seqnum - state->base) & state->seqmask;
+
+ if (rel_seqnum >= state->next) {
+ /* seqnum is the expected sequence number or in the future. Update the
+ * received bitmap and expected next sequence number. */
+ offset = rel_seqnum - state->next;
+ state->recvmap = (state->recvmap << (offset + 1)) | 1;
+ state->next = (rel_seqnum + 1) & state->seqmask;
+
+ return (offset > 0 && state->do_sequence) ? GSS_S_GAP_TOKEN :
+ GSS_S_COMPLETE;
+ }
+
+ /* seqnum is in the past. Check if it's too old for replay detection. */
+ offset = state->next - rel_seqnum;
+ if (offset > 64)
+ return state->do_sequence ? GSS_S_UNSEQ_TOKEN : GSS_S_OLD_TOKEN;
+
+ /* Check for replay and mark as received. */
+ bit = (uint64_t)1 << (offset - 1);
+ if (state->do_replay && (state->recvmap & bit))
+ return GSS_S_DUPLICATE_TOKEN;
+ state->recvmap |= bit;
+
+ return state->do_sequence ? GSS_S_UNSEQ_TOKEN : GSS_S_COMPLETE;
+}
+
+void
+g_seqstate_free(g_seqnum_state state)
+{
+ free(state);
+}
+
+/*
+ * These support functions are for the serialization routines
+ */
+void
+g_seqstate_size(g_seqnum_state state, size_t *sizep)
+{
+ *sizep += sizeof(*state);
+}
+
+long
+g_seqstate_externalize(g_seqnum_state state, unsigned char **buf,
+ size_t *lenremain)
+{
+ if (*lenremain < sizeof(*state))
+ return ENOMEM;
+ memcpy(*buf, state, sizeof(*state));
+ *buf += sizeof(*state);
+ *lenremain -= sizeof(*state);
+ return 0;
+}
+
+long
+g_seqstate_internalize(g_seqnum_state *state_out, unsigned char **buf,
+ size_t *lenremain)
+{
+ g_seqnum_state state;
+
+ *state_out = NULL;
+ if (*lenremain < sizeof(*state))
+ return EINVAL;
+ state = malloc(sizeof(*state));
+ if (state == NULL)
+ return ENOMEM;
+ memcpy(state, *buf, sizeof(*state));
+ *buf += sizeof(*state);
+ *lenremain -= sizeof(*state);
+ *state_out = state;
+ return 0;
+}
diff --git a/src/util/gss-kernel-lib/Makefile.in b/src/util/gss-kernel-lib/Makefile.in
index dc017d370..f70f3c655 100644
--- a/src/util/gss-kernel-lib/Makefile.in
+++ b/src/util/gss-kernel-lib/Makefile.in
@@ -22,7 +22,7 @@ SRCS= \
util_seed.c \
util_token.c \
util_set.c \
- util_ordering.c
+ util_seqstate.c
EXTRADEPSRCS= kernel_gss.c t_kgss_common.c t_kgss_user.c t_kgss_kernel.c
@@ -40,7 +40,7 @@ OBJS= \
util_seed.o \
util_token.o \
util_set.o \
- util_ordering.o
+ util_seqstate.o
# COM_ERR_DEPS is COM_ERR_DEPS-k5 when we use the bundled com_err, and
# empty otherwise. Normally COM_ERR_DEPS-k5 is from the central
@@ -138,8 +138,8 @@ util_token.c: $(GSS_GENERIC)/util_token.c
$(CP) $(GSS_GENERIC)/util_token.c $@
util_set.c: $(GSS_GENERIC)/util_set.c
$(CP) $(GSS_GENERIC)/util_set.c $@
-util_ordering.c: $(GSS_GENERIC)/util_ordering.c
- $(CP) $(GSS_GENERIC)/util_ordering.c $@
+util_seqstate.c: $(GSS_GENERIC)/util_seqstate.c
+ $(CP) $(GSS_GENERIC)/util_seqstate.c $@
# Rules to copy headers from their real homes in the source or build tree.
gssapi.h: $(INCLUDE)/gssapi.h
diff --git a/src/util/gss-kernel-lib/deps b/src/util/gss-kernel-lib/deps
index 94c60ba0a..a263ba2cb 100644
--- a/src/util/gss-kernel-lib/deps
+++ b/src/util/gss-kernel-lib/deps
@@ -89,10 +89,10 @@ $(OUTPRE)util_set.$(OBJEXT): $(COM_ERR_DEPS) autoconf.h \
gssapi/gssapi.h gssapi/gssapi_alloc.h gssapi/gssapi_ext.h \
gssapiP_generic.h gssapi_err_generic.h gssapi_generic.h \
k5-buf.h k5-platform.h k5-thread.h util_set.c
-$(OUTPRE)util_ordering.$(OBJEXT): $(COM_ERR_DEPS) autoconf.h \
+$(OUTPRE)util_seqstate.$(OBJEXT): $(COM_ERR_DEPS) autoconf.h \
gssapi/gssapi.h gssapi/gssapi_alloc.h gssapi/gssapi_ext.h \
gssapiP_generic.h gssapi_err_generic.h gssapi_generic.h \
- k5-buf.h k5-platform.h k5-thread.h util_ordering.c
+ k5-buf.h k5-platform.h k5-thread.h util_seqstate.c
$(OUTPRE)kernel_gss.$(OBJEXT): $(COM_ERR_DEPS) autoconf.h \
gssapi/gssapi.h gssapi/gssapi_alloc.h gssapi/gssapi_ext.h \
gssapi/gssapi_krb5.h gssapiP_generic.h gssapiP_krb5.h \