+2003-10-28 Ken Raeburn <raeburn@mit.edu>
+
+ * gssapiP_generic.h: Include k5-platform.h.
+ (gssint_uint64): New typedef.
+ (g_order_init, g_order_check): Update decls.
+ * util_ordering.c (struct _queue): Change sequence number fields
+ to gssint_uint64. Add mask field.
+ (queue_insert): Change sequence number to gssint_uint64.
+ (g_order_init): Change sequence numbers to gssint_uint64. Add
+ "wide_nums" argument; initialize the queue mask field based on
+ it. Store a -1 as the first element.
+ (g_order_check): Store and check elements as offsets from
+ firstnum. Mask to 32 bits if desired.
+
2003-07-17 Ken Raeburn <raeburn@mit.edu>
* Makefile.in (LIBNAME) [##WIN16##]: Don't define.
#include "gssapi_err_generic.h"
#include <errno.h>
+#include "k5-platform.h"
+typedef UINT64_TYPE gssint_uint64;
+
/** helper macros **/
#define g_OID_equal(o1,o2) \
OM_uint32 status_value,
gss_buffer_t status_string);
-gss_int32 g_order_init (void **queue, OM_uint32 seqnum,
- int do_replay, int do_sequence);
+gss_int32 g_order_init (void **queue, gssint_uint64 seqnum,
+ int do_replay, int do_sequence, int wide);
-gss_int32 g_order_check (void **queue, OM_uint32 seqnum);
+gss_int32 g_order_check (void **queue, gssint_uint64 seqnum);
void g_order_free (void **queue);
int do_sequence;
int start;
int length;
- unsigned int firstnum;
- unsigned int elem[QUEUE_LENGTH];
+ gssint_uint64 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. */
+ gssint_uint64 elem[QUEUE_LENGTH];
+ /* All ones for 64-bit sequence numbers; 32 ones for 32-bit
+ sequence numbers. */
+ gssint_uint64 mask;
} queue;
/* rep invariant:
#define QELEM(q,i) ((q)->elem[(i)%QSIZE(q)])
static void
-queue_insert(queue *q, int after, unsigned int seqnum)
+queue_insert(queue *q, int after, gssint_uint64 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 */
q->length++;
}
}
-
+
gss_int32
-g_order_init(void **vqueue, OM_uint32 seqnum,
- int do_replay, int do_sequence)
+g_order_init(void **vqueue, gssint_uint64 seqnum,
+ int do_replay, int do_sequence, int wide_nums)
{
queue *q;
q->do_replay = do_replay;
q->do_sequence = do_sequence;
+ q->mask = wide_nums ? ~(gssint_uint64)0 : 0xffffffffUL;
q->start = 0;
q->length = 1;
q->firstnum = seqnum;
- q->elem[q->start] = seqnum-1;
+ q->elem[q->start] = ((gssint_uint64)0 - 1) & q->mask;
*vqueue = (void *) q;
return(0);
}
gss_int32
-g_order_check(void **vqueue, OM_uint32 seqnum)
+g_order_check(void **vqueue, gssint_uint64 seqnum)
{
queue *q;
int i;
-
+ gssint_uint64 expected;
+
q = (queue *) (*vqueue);
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 */
- if (seqnum == QELEM(q,q->start+q->length-1)+1) {
+ 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 > QELEM(q,q->start+q->length-1)+1) ||
- (seqnum < q->firstnum)) {
+ if ((seqnum > expected)) {
queue_insert(q, q->start+q->length-1, seqnum);
if (q->do_replay && !q->do_sequence)
return(GSS_S_COMPLETE);
/* rule 3: seqnum < seqnum(first) */
if ((seqnum < QELEM(q,q->start)) &&
- (seqnum >= q->firstnum)) {
+ /* 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