1c19800e8SDoug Rabson /* 2*ae771770SStanislav Sedov * 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 34*ae771770SStanislav Sedov #include "gsskrb5_locl.h" 35c19800e8SDoug Rabson 36c19800e8SDoug Rabson #define DEFAULT_JITTER_WINDOW 20 37c19800e8SDoug Rabson 38c19800e8SDoug Rabson struct gss_msg_order { 39c19800e8SDoug Rabson OM_uint32 flags; 40c19800e8SDoug Rabson OM_uint32 start; 41c19800e8SDoug Rabson OM_uint32 length; 42c19800e8SDoug Rabson OM_uint32 jitter_window; 43c19800e8SDoug Rabson OM_uint32 first_seq; 44c19800e8SDoug Rabson OM_uint32 elem[1]; 45c19800e8SDoug Rabson }; 46c19800e8SDoug Rabson 47c19800e8SDoug Rabson 48c19800e8SDoug Rabson /* 49c19800e8SDoug Rabson * 50c19800e8SDoug Rabson */ 51c19800e8SDoug Rabson 52c19800e8SDoug Rabson static OM_uint32 53c19800e8SDoug Rabson msg_order_alloc(OM_uint32 *minor_status, 54c19800e8SDoug Rabson struct gss_msg_order **o, 55c19800e8SDoug Rabson OM_uint32 jitter_window) 56c19800e8SDoug Rabson { 57c19800e8SDoug Rabson size_t len; 58c19800e8SDoug Rabson 59c19800e8SDoug Rabson len = jitter_window * sizeof((*o)->elem[0]); 60c19800e8SDoug Rabson len += sizeof(**o); 61c19800e8SDoug Rabson len -= sizeof((*o)->elem[0]); 62c19800e8SDoug Rabson 63c19800e8SDoug Rabson *o = calloc(1, len); 64c19800e8SDoug Rabson if (*o == NULL) { 65c19800e8SDoug Rabson *minor_status = ENOMEM; 66c19800e8SDoug Rabson return GSS_S_FAILURE; 67c19800e8SDoug Rabson } 68c19800e8SDoug Rabson 69c19800e8SDoug Rabson *minor_status = 0; 70c19800e8SDoug Rabson return GSS_S_COMPLETE; 71c19800e8SDoug Rabson } 72c19800e8SDoug Rabson 73c19800e8SDoug Rabson /* 74c19800e8SDoug Rabson * 75c19800e8SDoug Rabson */ 76c19800e8SDoug Rabson 77c19800e8SDoug Rabson OM_uint32 78c19800e8SDoug Rabson _gssapi_msg_order_create(OM_uint32 *minor_status, 79c19800e8SDoug Rabson struct gss_msg_order **o, 80c19800e8SDoug Rabson OM_uint32 flags, 81c19800e8SDoug Rabson OM_uint32 seq_num, 82c19800e8SDoug Rabson OM_uint32 jitter_window, 83c19800e8SDoug Rabson int use_64) 84c19800e8SDoug Rabson { 85c19800e8SDoug Rabson OM_uint32 ret; 86c19800e8SDoug Rabson 87c19800e8SDoug Rabson if (jitter_window == 0) 88c19800e8SDoug Rabson jitter_window = DEFAULT_JITTER_WINDOW; 89c19800e8SDoug Rabson 90c19800e8SDoug Rabson ret = msg_order_alloc(minor_status, o, jitter_window); 91c19800e8SDoug Rabson if(ret != GSS_S_COMPLETE) 92c19800e8SDoug Rabson return ret; 93c19800e8SDoug Rabson 94c19800e8SDoug Rabson (*o)->flags = flags; 95c19800e8SDoug Rabson (*o)->length = 0; 96c19800e8SDoug Rabson (*o)->first_seq = seq_num; 97c19800e8SDoug Rabson (*o)->jitter_window = jitter_window; 98c19800e8SDoug Rabson (*o)->elem[0] = seq_num - 1; 99c19800e8SDoug Rabson 100c19800e8SDoug Rabson *minor_status = 0; 101c19800e8SDoug Rabson return GSS_S_COMPLETE; 102c19800e8SDoug Rabson } 103c19800e8SDoug Rabson 104c19800e8SDoug Rabson OM_uint32 105c19800e8SDoug Rabson _gssapi_msg_order_destroy(struct gss_msg_order **m) 106c19800e8SDoug Rabson { 107c19800e8SDoug Rabson free(*m); 108c19800e8SDoug Rabson *m = NULL; 109c19800e8SDoug Rabson return GSS_S_COMPLETE; 110c19800e8SDoug Rabson } 111c19800e8SDoug Rabson 112c19800e8SDoug Rabson static void 113c19800e8SDoug Rabson elem_set(struct gss_msg_order *o, unsigned int slot, OM_uint32 val) 114c19800e8SDoug Rabson { 115c19800e8SDoug Rabson o->elem[slot % o->jitter_window] = val; 116c19800e8SDoug Rabson } 117c19800e8SDoug Rabson 118c19800e8SDoug Rabson static void 119c19800e8SDoug Rabson elem_insert(struct gss_msg_order *o, 120c19800e8SDoug Rabson unsigned int after_slot, 121c19800e8SDoug Rabson OM_uint32 seq_num) 122c19800e8SDoug Rabson { 123c19800e8SDoug Rabson assert(o->jitter_window > after_slot); 124c19800e8SDoug Rabson 125c19800e8SDoug Rabson if (o->length > after_slot) 126c19800e8SDoug Rabson memmove(&o->elem[after_slot + 1], &o->elem[after_slot], 127c19800e8SDoug Rabson (o->length - after_slot - 1) * sizeof(o->elem[0])); 128c19800e8SDoug Rabson 129c19800e8SDoug Rabson elem_set(o, after_slot, seq_num); 130c19800e8SDoug Rabson 131c19800e8SDoug Rabson if (o->length < o->jitter_window) 132c19800e8SDoug Rabson o->length++; 133c19800e8SDoug Rabson } 134c19800e8SDoug Rabson 135c19800e8SDoug Rabson /* rule 1: expected sequence number */ 136c19800e8SDoug Rabson /* rule 2: > expected sequence number */ 137c19800e8SDoug Rabson /* rule 3: seqnum < seqnum(first) */ 138c19800e8SDoug Rabson /* rule 4+5: seqnum in [seqnum(first),seqnum(last)] */ 139c19800e8SDoug Rabson 140c19800e8SDoug Rabson OM_uint32 141c19800e8SDoug Rabson _gssapi_msg_order_check(struct gss_msg_order *o, OM_uint32 seq_num) 142c19800e8SDoug Rabson { 143c19800e8SDoug Rabson OM_uint32 r; 144*ae771770SStanislav Sedov size_t i; 145c19800e8SDoug Rabson 146c19800e8SDoug Rabson if (o == NULL) 147c19800e8SDoug Rabson return GSS_S_COMPLETE; 148c19800e8SDoug Rabson 149c19800e8SDoug Rabson if ((o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) == 0) 150c19800e8SDoug Rabson return GSS_S_COMPLETE; 151c19800e8SDoug Rabson 152c19800e8SDoug Rabson /* check if the packet is the next in order */ 153c19800e8SDoug Rabson if (o->elem[0] == seq_num - 1) { 154c19800e8SDoug Rabson elem_insert(o, 0, seq_num); 155c19800e8SDoug Rabson return GSS_S_COMPLETE; 156c19800e8SDoug Rabson } 157c19800e8SDoug Rabson 158c19800e8SDoug Rabson r = (o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG))==GSS_C_REPLAY_FLAG; 159c19800e8SDoug Rabson 160c19800e8SDoug Rabson /* sequence number larger then largest sequence number 161c19800e8SDoug Rabson * or smaller then the first sequence number */ 162c19800e8SDoug Rabson if (seq_num > o->elem[0] 163c19800e8SDoug Rabson || seq_num < o->first_seq 164c19800e8SDoug Rabson || o->length == 0) 165c19800e8SDoug Rabson { 166c19800e8SDoug Rabson elem_insert(o, 0, seq_num); 167c19800e8SDoug Rabson if (r) { 168c19800e8SDoug Rabson return GSS_S_COMPLETE; 169c19800e8SDoug Rabson } else { 170c19800e8SDoug Rabson return GSS_S_GAP_TOKEN; 171c19800e8SDoug Rabson } 172c19800e8SDoug Rabson } 173c19800e8SDoug Rabson 174c19800e8SDoug Rabson assert(o->length > 0); 175c19800e8SDoug Rabson 176c19800e8SDoug Rabson /* sequence number smaller the first sequence number */ 177c19800e8SDoug Rabson if (seq_num < o->elem[o->length - 1]) { 178c19800e8SDoug Rabson if (r) 179c19800e8SDoug Rabson return(GSS_S_OLD_TOKEN); 180c19800e8SDoug Rabson else 181c19800e8SDoug Rabson return(GSS_S_UNSEQ_TOKEN); 182c19800e8SDoug Rabson } 183c19800e8SDoug Rabson 184c19800e8SDoug Rabson if (seq_num == o->elem[o->length - 1]) { 185c19800e8SDoug Rabson return GSS_S_DUPLICATE_TOKEN; 186c19800e8SDoug Rabson } 187c19800e8SDoug Rabson 188c19800e8SDoug Rabson for (i = 0; i < o->length - 1; i++) { 189c19800e8SDoug Rabson if (o->elem[i] == seq_num) 190c19800e8SDoug Rabson return GSS_S_DUPLICATE_TOKEN; 191c19800e8SDoug Rabson if (o->elem[i + 1] < seq_num && o->elem[i] < seq_num) { 192c19800e8SDoug Rabson elem_insert(o, i, seq_num); 193c19800e8SDoug Rabson if (r) 194c19800e8SDoug Rabson return GSS_S_COMPLETE; 195c19800e8SDoug Rabson else 196c19800e8SDoug Rabson return GSS_S_UNSEQ_TOKEN; 197c19800e8SDoug Rabson } 198c19800e8SDoug Rabson } 199c19800e8SDoug Rabson 200c19800e8SDoug Rabson return GSS_S_FAILURE; 201c19800e8SDoug Rabson } 202c19800e8SDoug Rabson 203c19800e8SDoug Rabson OM_uint32 204c19800e8SDoug Rabson _gssapi_msg_order_f(OM_uint32 flags) 205c19800e8SDoug Rabson { 206c19800e8SDoug Rabson return flags & (GSS_C_SEQUENCE_FLAG|GSS_C_REPLAY_FLAG); 207c19800e8SDoug Rabson } 208c19800e8SDoug Rabson 209c19800e8SDoug Rabson /* 210c19800e8SDoug Rabson * Translate `o` into inter-process format and export in to `sp'. 211c19800e8SDoug Rabson */ 212c19800e8SDoug Rabson 213c19800e8SDoug Rabson krb5_error_code 214c19800e8SDoug Rabson _gssapi_msg_order_export(krb5_storage *sp, struct gss_msg_order *o) 215c19800e8SDoug Rabson { 216c19800e8SDoug Rabson krb5_error_code kret; 217c19800e8SDoug Rabson OM_uint32 i; 218c19800e8SDoug Rabson 219c19800e8SDoug Rabson kret = krb5_store_int32(sp, o->flags); 220c19800e8SDoug Rabson if (kret) 221c19800e8SDoug Rabson return kret; 222c19800e8SDoug Rabson kret = krb5_store_int32(sp, o->start); 223c19800e8SDoug Rabson if (kret) 224c19800e8SDoug Rabson return kret; 225c19800e8SDoug Rabson kret = krb5_store_int32(sp, o->length); 226c19800e8SDoug Rabson if (kret) 227c19800e8SDoug Rabson return kret; 228c19800e8SDoug Rabson kret = krb5_store_int32(sp, o->jitter_window); 229c19800e8SDoug Rabson if (kret) 230c19800e8SDoug Rabson return kret; 231c19800e8SDoug Rabson kret = krb5_store_int32(sp, o->first_seq); 232c19800e8SDoug Rabson if (kret) 233c19800e8SDoug Rabson return kret; 234c19800e8SDoug Rabson 235c19800e8SDoug Rabson for (i = 0; i < o->jitter_window; i++) { 236c19800e8SDoug Rabson kret = krb5_store_int32(sp, o->elem[i]); 237c19800e8SDoug Rabson if (kret) 238c19800e8SDoug Rabson return kret; 239c19800e8SDoug Rabson } 240c19800e8SDoug Rabson 241c19800e8SDoug Rabson return 0; 242c19800e8SDoug Rabson } 243c19800e8SDoug Rabson 244c19800e8SDoug Rabson OM_uint32 245c19800e8SDoug Rabson _gssapi_msg_order_import(OM_uint32 *minor_status, 246c19800e8SDoug Rabson krb5_storage *sp, 247c19800e8SDoug Rabson struct gss_msg_order **o) 248c19800e8SDoug Rabson { 249c19800e8SDoug Rabson OM_uint32 ret; 250c19800e8SDoug Rabson krb5_error_code kret; 251c19800e8SDoug Rabson int32_t i, flags, start, length, jitter_window, first_seq; 252c19800e8SDoug Rabson 253c19800e8SDoug Rabson kret = krb5_ret_int32(sp, &flags); 254c19800e8SDoug Rabson if (kret) 255c19800e8SDoug Rabson goto failed; 256*ae771770SStanislav Sedov kret = krb5_ret_int32(sp, &start); 257c19800e8SDoug Rabson if (kret) 258c19800e8SDoug Rabson goto failed; 259*ae771770SStanislav Sedov kret = krb5_ret_int32(sp, &length); 260c19800e8SDoug Rabson if (kret) 261c19800e8SDoug Rabson goto failed; 262*ae771770SStanislav Sedov kret = krb5_ret_int32(sp, &jitter_window); 263c19800e8SDoug Rabson if (kret) 264c19800e8SDoug Rabson goto failed; 265*ae771770SStanislav Sedov kret = krb5_ret_int32(sp, &first_seq); 266c19800e8SDoug Rabson if (kret) 267c19800e8SDoug Rabson goto failed; 268c19800e8SDoug Rabson 269c19800e8SDoug Rabson ret = msg_order_alloc(minor_status, o, jitter_window); 270c19800e8SDoug Rabson if (ret != GSS_S_COMPLETE) 271c19800e8SDoug Rabson return ret; 272c19800e8SDoug Rabson 273c19800e8SDoug Rabson (*o)->flags = flags; 274c19800e8SDoug Rabson (*o)->start = start; 275c19800e8SDoug Rabson (*o)->length = length; 276c19800e8SDoug Rabson (*o)->jitter_window = jitter_window; 277c19800e8SDoug Rabson (*o)->first_seq = first_seq; 278c19800e8SDoug Rabson 279c19800e8SDoug Rabson for( i = 0; i < jitter_window; i++ ) { 280c19800e8SDoug Rabson kret = krb5_ret_int32(sp, (int32_t*)&((*o)->elem[i])); 281c19800e8SDoug Rabson if (kret) 282c19800e8SDoug Rabson goto failed; 283c19800e8SDoug Rabson } 284c19800e8SDoug Rabson 285c19800e8SDoug Rabson *minor_status = 0; 286c19800e8SDoug Rabson return GSS_S_COMPLETE; 287c19800e8SDoug Rabson 288c19800e8SDoug Rabson failed: 289c19800e8SDoug Rabson _gssapi_msg_order_destroy(o); 290c19800e8SDoug Rabson *minor_status = kret; 291c19800e8SDoug Rabson return GSS_S_FAILURE; 292c19800e8SDoug Rabson } 293