root/source4/heimdal/lib/gssapi/krb5/sequence.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. msg_order_alloc
  2. _gssapi_msg_order_create
  3. _gssapi_msg_order_destroy
  4. elem_set
  5. elem_insert
  6. _gssapi_msg_order_check
  7. _gssapi_msg_order_f
  8. _gssapi_msg_order_export
  9. _gssapi_msg_order_import

   1 /*
   2  * Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan
   3  * (Royal Institute of Technology, Stockholm, Sweden).
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  *
  13  * 2. Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in the
  15  *    documentation and/or other materials provided with the distribution.
  16  *
  17  * 3. Neither the name of the Institute nor the names of its contributors
  18  *    may be used to endorse or promote products derived from this software
  19  *    without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31  * SUCH DAMAGE.
  32  */
  33 
  34 #include "krb5/gsskrb5_locl.h"
  35 
  36 RCSID("$Id$");
  37 
  38 #define DEFAULT_JITTER_WINDOW 20
  39 
  40 struct gss_msg_order {
  41     OM_uint32 flags;
  42     OM_uint32 start;
  43     OM_uint32 length;
  44     OM_uint32 jitter_window;
  45     OM_uint32 first_seq;
  46     OM_uint32 elem[1];
  47 };
  48 
  49 
  50 /*
  51  *
  52  */
  53 
  54 static OM_uint32
  55 msg_order_alloc(OM_uint32 *minor_status,
     /* [<][>][^][v][top][bottom][index][help] */
  56                 struct gss_msg_order **o,
  57                 OM_uint32 jitter_window)
  58 {
  59     size_t len;
  60 
  61     len = jitter_window * sizeof((*o)->elem[0]);
  62     len += sizeof(**o);
  63     len -= sizeof((*o)->elem[0]);
  64 
  65     *o = calloc(1, len);
  66     if (*o == NULL) {
  67         *minor_status = ENOMEM;
  68         return GSS_S_FAILURE;
  69     }   
  70 
  71     *minor_status = 0;
  72     return GSS_S_COMPLETE;
  73 }
  74 
  75 /*
  76  *
  77  */
  78 
  79 OM_uint32
  80 _gssapi_msg_order_create(OM_uint32 *minor_status,
     /* [<][>][^][v][top][bottom][index][help] */
  81                          struct gss_msg_order **o,
  82                          OM_uint32 flags,
  83                          OM_uint32 seq_num,
  84                          OM_uint32 jitter_window,
  85                          int use_64)
  86 {
  87     OM_uint32 ret;
  88 
  89     if (jitter_window == 0)
  90         jitter_window = DEFAULT_JITTER_WINDOW;
  91 
  92     ret = msg_order_alloc(minor_status, o, jitter_window);
  93     if(ret != GSS_S_COMPLETE)
  94         return ret;
  95 
  96     (*o)->flags = flags;
  97     (*o)->length = 0;
  98     (*o)->first_seq = seq_num;
  99     (*o)->jitter_window = jitter_window;
 100     (*o)->elem[0] = seq_num - 1;
 101 
 102     *minor_status = 0;
 103     return GSS_S_COMPLETE;
 104 }
 105 
 106 OM_uint32
 107 _gssapi_msg_order_destroy(struct gss_msg_order **m)
     /* [<][>][^][v][top][bottom][index][help] */
 108 {
 109     free(*m);
 110     *m = NULL;
 111     return GSS_S_COMPLETE;
 112 }
 113 
 114 static void
 115 elem_set(struct gss_msg_order *o, unsigned int slot, OM_uint32 val)
     /* [<][>][^][v][top][bottom][index][help] */
 116 {
 117     o->elem[slot % o->jitter_window] = val;
 118 }
 119 
 120 static void
 121 elem_insert(struct gss_msg_order *o,
     /* [<][>][^][v][top][bottom][index][help] */
 122             unsigned int after_slot,
 123             OM_uint32 seq_num)
 124 {
 125     assert(o->jitter_window > after_slot);
 126 
 127     if (o->length > after_slot)
 128         memmove(&o->elem[after_slot + 1], &o->elem[after_slot],
 129                 (o->length - after_slot - 1) * sizeof(o->elem[0]));
 130 
 131     elem_set(o, after_slot, seq_num);
 132 
 133     if (o->length < o->jitter_window)
 134         o->length++;
 135 }
 136 
 137 /* rule 1: expected sequence number */
 138 /* rule 2: > expected sequence number */
 139 /* rule 3: seqnum < seqnum(first) */
 140 /* rule 4+5: seqnum in [seqnum(first),seqnum(last)]  */
 141 
 142 OM_uint32
 143 _gssapi_msg_order_check(struct gss_msg_order *o, OM_uint32 seq_num)
     /* [<][>][^][v][top][bottom][index][help] */
 144 {
 145     OM_uint32 r;
 146     int i;
 147 
 148     if (o == NULL)
 149         return GSS_S_COMPLETE;
 150 
 151     if ((o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) == 0)
 152         return GSS_S_COMPLETE;
 153 
 154     /* check if the packet is the next in order */
 155     if (o->elem[0] == seq_num - 1) {
 156         elem_insert(o, 0, seq_num);
 157         return GSS_S_COMPLETE;
 158     }
 159 
 160     r = (o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG))==GSS_C_REPLAY_FLAG;
 161 
 162     /* sequence number larger then largest sequence number
 163      * or smaller then the first sequence number */
 164     if (seq_num > o->elem[0]
 165         || seq_num < o->first_seq
 166         || o->length == 0)
 167     {
 168         elem_insert(o, 0, seq_num);
 169         if (r) {
 170             return GSS_S_COMPLETE;
 171         } else {
 172             return GSS_S_GAP_TOKEN;
 173         }
 174     }
 175 
 176     assert(o->length > 0);
 177 
 178     /* sequence number smaller the first sequence number */
 179     if (seq_num < o->elem[o->length - 1]) {
 180         if (r)
 181             return(GSS_S_OLD_TOKEN);
 182         else
 183             return(GSS_S_UNSEQ_TOKEN);
 184     }
 185 
 186     if (seq_num == o->elem[o->length - 1]) {
 187         return GSS_S_DUPLICATE_TOKEN;
 188     }
 189 
 190     for (i = 0; i < o->length - 1; i++) {
 191         if (o->elem[i] == seq_num)
 192             return GSS_S_DUPLICATE_TOKEN;
 193         if (o->elem[i + 1] < seq_num && o->elem[i] < seq_num) {
 194             elem_insert(o, i, seq_num);
 195             if (r)
 196                 return GSS_S_COMPLETE;
 197             else
 198                 return GSS_S_UNSEQ_TOKEN;
 199         }
 200     }
 201 
 202     return GSS_S_FAILURE;
 203 }
 204 
 205 OM_uint32
 206 _gssapi_msg_order_f(OM_uint32 flags)
     /* [<][>][^][v][top][bottom][index][help] */
 207 {
 208     return flags & (GSS_C_SEQUENCE_FLAG|GSS_C_REPLAY_FLAG);
 209 }
 210 
 211 /*
 212  * Translate `o` into inter-process format and export in to `sp'.
 213  */
 214 
 215 krb5_error_code
 216 _gssapi_msg_order_export(krb5_storage *sp, struct gss_msg_order *o)
     /* [<][>][^][v][top][bottom][index][help] */
 217 {
 218     krb5_error_code kret;
 219     OM_uint32 i;
 220 
 221     kret = krb5_store_int32(sp, o->flags);
 222     if (kret)
 223         return kret;
 224     kret = krb5_store_int32(sp, o->start);
 225     if (kret)
 226         return kret;
 227     kret = krb5_store_int32(sp, o->length);
 228     if (kret)
 229         return kret;
 230     kret = krb5_store_int32(sp, o->jitter_window);
 231     if (kret)
 232         return kret;
 233     kret = krb5_store_int32(sp, o->first_seq);
 234     if (kret)
 235         return kret;
 236 
 237     for (i = 0; i < o->jitter_window; i++) {
 238         kret = krb5_store_int32(sp, o->elem[i]);
 239         if (kret)
 240             return kret;
 241     }
 242 
 243     return 0;
 244 }
 245 
 246 OM_uint32
 247 _gssapi_msg_order_import(OM_uint32 *minor_status,
     /* [<][>][^][v][top][bottom][index][help] */
 248                          krb5_storage *sp,
 249                          struct gss_msg_order **o)
 250 {
 251     OM_uint32 ret;
 252     krb5_error_code kret;
 253     int32_t i, flags, start, length, jitter_window, first_seq;
 254 
 255     kret = krb5_ret_int32(sp, &flags);
 256     if (kret)
 257         goto failed;
 258     kret = krb5_ret_int32(sp, &start);
 259     if (kret)
 260         goto failed;
 261     kret = krb5_ret_int32(sp, &length);
 262     if (kret)
 263         goto failed;
 264     kret = krb5_ret_int32(sp, &jitter_window);
 265     if (kret)
 266         goto failed;
 267     kret = krb5_ret_int32(sp, &first_seq);
 268     if (kret)
 269         goto failed;
 270 
 271     ret = msg_order_alloc(minor_status, o, jitter_window);
 272     if (ret != GSS_S_COMPLETE)
 273         return ret;
 274 
 275     (*o)->flags = flags;
 276     (*o)->start = start;
 277     (*o)->length = length;
 278     (*o)->jitter_window = jitter_window;
 279     (*o)->first_seq = first_seq;
 280 
 281     for( i = 0; i < jitter_window; i++ ) {
 282         kret = krb5_ret_int32(sp, (int32_t*)&((*o)->elem[i]));
 283         if (kret)
 284             goto failed;
 285     }
 286 
 287     *minor_status = 0;
 288     return GSS_S_COMPLETE;
 289 
 290 failed:
 291     _gssapi_msg_order_destroy(o);
 292     *minor_status = kret;
 293     return GSS_S_FAILURE;
 294 }

/* [<][>][^][v][top][bottom][index][help] */