Path: blob/main/crypto/heimdal/lib/gssapi/krb5/sequence.c
34923 views
/*1* Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan2* (Royal Institute of Technology, Stockholm, Sweden).3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8*9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11*12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* 3. Neither the name of the Institute nor the names of its contributors17* may be used to endorse or promote products derived from this software18* without specific prior written permission.19*20* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND21* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE23* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE24* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL25* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS26* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)27* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT28* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY29* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF30* SUCH DAMAGE.31*/3233#include "gsskrb5_locl.h"3435#define DEFAULT_JITTER_WINDOW 203637struct gss_msg_order {38OM_uint32 flags;39OM_uint32 start;40OM_uint32 length;41OM_uint32 jitter_window;42OM_uint32 first_seq;43OM_uint32 elem[1];44};454647/*48*49*/5051static OM_uint3252msg_order_alloc(OM_uint32 *minor_status,53struct gss_msg_order **o,54OM_uint32 jitter_window)55{56size_t len;5758len = jitter_window * sizeof((*o)->elem[0]);59len += sizeof(**o);60len -= sizeof((*o)->elem[0]);6162*o = calloc(1, len);63if (*o == NULL) {64*minor_status = ENOMEM;65return GSS_S_FAILURE;66}6768*minor_status = 0;69return GSS_S_COMPLETE;70}7172/*73*74*/7576OM_uint3277_gssapi_msg_order_create(OM_uint32 *minor_status,78struct gss_msg_order **o,79OM_uint32 flags,80OM_uint32 seq_num,81OM_uint32 jitter_window,82int use_64)83{84OM_uint32 ret;8586if (jitter_window == 0)87jitter_window = DEFAULT_JITTER_WINDOW;8889ret = msg_order_alloc(minor_status, o, jitter_window);90if(ret != GSS_S_COMPLETE)91return ret;9293(*o)->flags = flags;94(*o)->length = 0;95(*o)->first_seq = seq_num;96(*o)->jitter_window = jitter_window;97(*o)->elem[0] = seq_num - 1;9899*minor_status = 0;100return GSS_S_COMPLETE;101}102103OM_uint32104_gssapi_msg_order_destroy(struct gss_msg_order **m)105{106free(*m);107*m = NULL;108return GSS_S_COMPLETE;109}110111static void112elem_set(struct gss_msg_order *o, unsigned int slot, OM_uint32 val)113{114o->elem[slot % o->jitter_window] = val;115}116117static void118elem_insert(struct gss_msg_order *o,119unsigned int after_slot,120OM_uint32 seq_num)121{122assert(o->jitter_window > after_slot);123124if (o->length > after_slot)125memmove(&o->elem[after_slot + 1], &o->elem[after_slot],126(o->length - after_slot - 1) * sizeof(o->elem[0]));127128elem_set(o, after_slot, seq_num);129130if (o->length < o->jitter_window)131o->length++;132}133134/* rule 1: expected sequence number */135/* rule 2: > expected sequence number */136/* rule 3: seqnum < seqnum(first) */137/* rule 4+5: seqnum in [seqnum(first),seqnum(last)] */138139OM_uint32140_gssapi_msg_order_check(struct gss_msg_order *o, OM_uint32 seq_num)141{142OM_uint32 r;143size_t i;144145if (o == NULL)146return GSS_S_COMPLETE;147148if ((o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) == 0)149return GSS_S_COMPLETE;150151/* check if the packet is the next in order */152if (o->elem[0] == seq_num - 1) {153elem_insert(o, 0, seq_num);154return GSS_S_COMPLETE;155}156157r = (o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG))==GSS_C_REPLAY_FLAG;158159/* sequence number larger then largest sequence number160* or smaller then the first sequence number */161if (seq_num > o->elem[0]162|| seq_num < o->first_seq163|| o->length == 0)164{165elem_insert(o, 0, seq_num);166if (r) {167return GSS_S_COMPLETE;168} else {169return GSS_S_GAP_TOKEN;170}171}172173assert(o->length > 0);174175/* sequence number smaller the first sequence number */176if (seq_num < o->elem[o->length - 1]) {177if (r)178return(GSS_S_OLD_TOKEN);179else180return(GSS_S_UNSEQ_TOKEN);181}182183if (seq_num == o->elem[o->length - 1]) {184return GSS_S_DUPLICATE_TOKEN;185}186187for (i = 0; i < o->length - 1; i++) {188if (o->elem[i] == seq_num)189return GSS_S_DUPLICATE_TOKEN;190if (o->elem[i + 1] < seq_num && o->elem[i] < seq_num) {191elem_insert(o, i, seq_num);192if (r)193return GSS_S_COMPLETE;194else195return GSS_S_UNSEQ_TOKEN;196}197}198199return GSS_S_FAILURE;200}201202OM_uint32203_gssapi_msg_order_f(OM_uint32 flags)204{205return flags & (GSS_C_SEQUENCE_FLAG|GSS_C_REPLAY_FLAG);206}207208/*209* Translate `o` into inter-process format and export in to `sp'.210*/211212krb5_error_code213_gssapi_msg_order_export(krb5_storage *sp, struct gss_msg_order *o)214{215krb5_error_code kret;216OM_uint32 i;217218kret = krb5_store_int32(sp, o->flags);219if (kret)220return kret;221kret = krb5_store_int32(sp, o->start);222if (kret)223return kret;224kret = krb5_store_int32(sp, o->length);225if (kret)226return kret;227kret = krb5_store_int32(sp, o->jitter_window);228if (kret)229return kret;230kret = krb5_store_int32(sp, o->first_seq);231if (kret)232return kret;233234for (i = 0; i < o->jitter_window; i++) {235kret = krb5_store_int32(sp, o->elem[i]);236if (kret)237return kret;238}239240return 0;241}242243OM_uint32244_gssapi_msg_order_import(OM_uint32 *minor_status,245krb5_storage *sp,246struct gss_msg_order **o)247{248OM_uint32 ret;249krb5_error_code kret;250int32_t i, flags, start, length, jitter_window, first_seq;251252kret = krb5_ret_int32(sp, &flags);253if (kret)254goto failed;255kret = krb5_ret_int32(sp, &start);256if (kret)257goto failed;258kret = krb5_ret_int32(sp, &length);259if (kret)260goto failed;261kret = krb5_ret_int32(sp, &jitter_window);262if (kret)263goto failed;264kret = krb5_ret_int32(sp, &first_seq);265if (kret)266goto failed;267268ret = msg_order_alloc(minor_status, o, jitter_window);269if (ret != GSS_S_COMPLETE)270return ret;271272(*o)->flags = flags;273(*o)->start = start;274(*o)->length = length;275(*o)->jitter_window = jitter_window;276(*o)->first_seq = first_seq;277278for( i = 0; i < jitter_window; i++ ) {279kret = krb5_ret_int32(sp, (int32_t*)&((*o)->elem[i]));280if (kret)281goto failed;282}283284*minor_status = 0;285return GSS_S_COMPLETE;286287failed:288_gssapi_msg_order_destroy(o);289*minor_status = kret;290return GSS_S_FAILURE;291}292293294