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