diff options
| author | Cy Schubert <cy@FreeBSD.org> | 2017-07-07 17:03:42 +0000 | 
|---|---|---|
| committer | Cy Schubert <cy@FreeBSD.org> | 2017-07-07 17:03:42 +0000 | 
| commit | 33a9b234e7087f573ef08cd7318c6497ba08b439 (patch) | |
| tree | d0ea40ad3bf5463a3c55795977c71bcb7d781b4b /src/lib/gssapi/generic/util_seqstate.c | |
Diffstat (limited to 'src/lib/gssapi/generic/util_seqstate.c')
| -rw-r--r-- | src/lib/gssapi/generic/util_seqstate.c | 163 | 
1 files changed, 163 insertions, 0 deletions
| diff --git a/src/lib/gssapi/generic/util_seqstate.c b/src/lib/gssapi/generic/util_seqstate.c new file mode 100644 index 000000000000..a0bc2cc1c1d4 --- /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; +} | 
