1178825Sdfr/* 2233294Sstas * Copyright (c) 2003 - 2006 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9178825Sdfr * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 20178825Sdfr * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34233294Sstas#include "gsskrb5_locl.h" 35178825Sdfr 36178825Sdfr#define DEFAULT_JITTER_WINDOW 20 37178825Sdfr 38178825Sdfrstruct gss_msg_order { 39178825Sdfr OM_uint32 flags; 40178825Sdfr OM_uint32 start; 41178825Sdfr OM_uint32 length; 42178825Sdfr OM_uint32 jitter_window; 43178825Sdfr OM_uint32 first_seq; 44178825Sdfr OM_uint32 elem[1]; 45178825Sdfr}; 46178825Sdfr 47178825Sdfr 48178825Sdfr/* 49178825Sdfr * 50178825Sdfr */ 51178825Sdfr 52178825Sdfrstatic OM_uint32 53178825Sdfrmsg_order_alloc(OM_uint32 *minor_status, 54178825Sdfr struct gss_msg_order **o, 55178825Sdfr OM_uint32 jitter_window) 56178825Sdfr{ 57178825Sdfr size_t len; 58233294Sstas 59178825Sdfr len = jitter_window * sizeof((*o)->elem[0]); 60178825Sdfr len += sizeof(**o); 61178825Sdfr len -= sizeof((*o)->elem[0]); 62233294Sstas 63178825Sdfr *o = calloc(1, len); 64178825Sdfr if (*o == NULL) { 65178825Sdfr *minor_status = ENOMEM; 66178825Sdfr return GSS_S_FAILURE; 67233294Sstas } 68233294Sstas 69178825Sdfr *minor_status = 0; 70233294Sstas return GSS_S_COMPLETE; 71178825Sdfr} 72178825Sdfr 73178825Sdfr/* 74178825Sdfr * 75178825Sdfr */ 76178825Sdfr 77178825SdfrOM_uint32 78178825Sdfr_gssapi_msg_order_create(OM_uint32 *minor_status, 79233294Sstas struct gss_msg_order **o, 80233294Sstas OM_uint32 flags, 81233294Sstas OM_uint32 seq_num, 82178825Sdfr OM_uint32 jitter_window, 83178825Sdfr int use_64) 84178825Sdfr{ 85178825Sdfr OM_uint32 ret; 86178825Sdfr 87178825Sdfr if (jitter_window == 0) 88178825Sdfr jitter_window = DEFAULT_JITTER_WINDOW; 89178825Sdfr 90178825Sdfr ret = msg_order_alloc(minor_status, o, jitter_window); 91178825Sdfr if(ret != GSS_S_COMPLETE) 92178825Sdfr return ret; 93178825Sdfr 94178825Sdfr (*o)->flags = flags; 95178825Sdfr (*o)->length = 0; 96178825Sdfr (*o)->first_seq = seq_num; 97178825Sdfr (*o)->jitter_window = jitter_window; 98178825Sdfr (*o)->elem[0] = seq_num - 1; 99178825Sdfr 100178825Sdfr *minor_status = 0; 101178825Sdfr return GSS_S_COMPLETE; 102178825Sdfr} 103178825Sdfr 104178825SdfrOM_uint32 105178825Sdfr_gssapi_msg_order_destroy(struct gss_msg_order **m) 106178825Sdfr{ 107178825Sdfr free(*m); 108178825Sdfr *m = NULL; 109178825Sdfr return GSS_S_COMPLETE; 110178825Sdfr} 111178825Sdfr 112178825Sdfrstatic void 113178825Sdfrelem_set(struct gss_msg_order *o, unsigned int slot, OM_uint32 val) 114178825Sdfr{ 115178825Sdfr o->elem[slot % o->jitter_window] = val; 116178825Sdfr} 117178825Sdfr 118178825Sdfrstatic void 119233294Sstaselem_insert(struct gss_msg_order *o, 120178825Sdfr unsigned int after_slot, 121178825Sdfr OM_uint32 seq_num) 122178825Sdfr{ 123178825Sdfr assert(o->jitter_window > after_slot); 124178825Sdfr 125178825Sdfr if (o->length > after_slot) 126178825Sdfr memmove(&o->elem[after_slot + 1], &o->elem[after_slot], 127178825Sdfr (o->length - after_slot - 1) * sizeof(o->elem[0])); 128178825Sdfr 129178825Sdfr elem_set(o, after_slot, seq_num); 130178825Sdfr 131178825Sdfr if (o->length < o->jitter_window) 132178825Sdfr o->length++; 133178825Sdfr} 134178825Sdfr 135178825Sdfr/* rule 1: expected sequence number */ 136178825Sdfr/* rule 2: > expected sequence number */ 137178825Sdfr/* rule 3: seqnum < seqnum(first) */ 138178825Sdfr/* rule 4+5: seqnum in [seqnum(first),seqnum(last)] */ 139178825Sdfr 140178825SdfrOM_uint32 141178825Sdfr_gssapi_msg_order_check(struct gss_msg_order *o, OM_uint32 seq_num) 142178825Sdfr{ 143178825Sdfr OM_uint32 r; 144233294Sstas size_t i; 145178825Sdfr 146178825Sdfr if (o == NULL) 147178825Sdfr return GSS_S_COMPLETE; 148178825Sdfr 149178825Sdfr if ((o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) == 0) 150178825Sdfr return GSS_S_COMPLETE; 151178825Sdfr 152178825Sdfr /* check if the packet is the next in order */ 153178825Sdfr if (o->elem[0] == seq_num - 1) { 154178825Sdfr elem_insert(o, 0, seq_num); 155178825Sdfr return GSS_S_COMPLETE; 156178825Sdfr } 157178825Sdfr 158178825Sdfr r = (o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG))==GSS_C_REPLAY_FLAG; 159178825Sdfr 160233294Sstas /* sequence number larger then largest sequence number 161178825Sdfr * or smaller then the first sequence number */ 162178825Sdfr if (seq_num > o->elem[0] 163178825Sdfr || seq_num < o->first_seq 164233294Sstas || o->length == 0) 165178825Sdfr { 166178825Sdfr elem_insert(o, 0, seq_num); 167178825Sdfr if (r) { 168178825Sdfr return GSS_S_COMPLETE; 169178825Sdfr } else { 170178825Sdfr return GSS_S_GAP_TOKEN; 171178825Sdfr } 172178825Sdfr } 173178825Sdfr 174178825Sdfr assert(o->length > 0); 175178825Sdfr 176178825Sdfr /* sequence number smaller the first sequence number */ 177178825Sdfr if (seq_num < o->elem[o->length - 1]) { 178178825Sdfr if (r) 179178825Sdfr return(GSS_S_OLD_TOKEN); 180178825Sdfr else 181178825Sdfr return(GSS_S_UNSEQ_TOKEN); 182178825Sdfr } 183178825Sdfr 184178825Sdfr if (seq_num == o->elem[o->length - 1]) { 185178825Sdfr return GSS_S_DUPLICATE_TOKEN; 186178825Sdfr } 187178825Sdfr 188178825Sdfr for (i = 0; i < o->length - 1; i++) { 189178825Sdfr if (o->elem[i] == seq_num) 190178825Sdfr return GSS_S_DUPLICATE_TOKEN; 191178825Sdfr if (o->elem[i + 1] < seq_num && o->elem[i] < seq_num) { 192178825Sdfr elem_insert(o, i, seq_num); 193178825Sdfr if (r) 194178825Sdfr return GSS_S_COMPLETE; 195178825Sdfr else 196178825Sdfr return GSS_S_UNSEQ_TOKEN; 197178825Sdfr } 198178825Sdfr } 199178825Sdfr 200178825Sdfr return GSS_S_FAILURE; 201178825Sdfr} 202178825Sdfr 203178825SdfrOM_uint32 204178825Sdfr_gssapi_msg_order_f(OM_uint32 flags) 205178825Sdfr{ 206178825Sdfr return flags & (GSS_C_SEQUENCE_FLAG|GSS_C_REPLAY_FLAG); 207178825Sdfr} 208178825Sdfr 209178825Sdfr/* 210178825Sdfr * Translate `o` into inter-process format and export in to `sp'. 211178825Sdfr */ 212178825Sdfr 213178825Sdfrkrb5_error_code 214178825Sdfr_gssapi_msg_order_export(krb5_storage *sp, struct gss_msg_order *o) 215178825Sdfr{ 216178825Sdfr krb5_error_code kret; 217178825Sdfr OM_uint32 i; 218233294Sstas 219178825Sdfr kret = krb5_store_int32(sp, o->flags); 220178825Sdfr if (kret) 221178825Sdfr return kret; 222178825Sdfr kret = krb5_store_int32(sp, o->start); 223178825Sdfr if (kret) 224178825Sdfr return kret; 225178825Sdfr kret = krb5_store_int32(sp, o->length); 226178825Sdfr if (kret) 227178825Sdfr return kret; 228178825Sdfr kret = krb5_store_int32(sp, o->jitter_window); 229178825Sdfr if (kret) 230178825Sdfr return kret; 231178825Sdfr kret = krb5_store_int32(sp, o->first_seq); 232178825Sdfr if (kret) 233178825Sdfr return kret; 234233294Sstas 235178825Sdfr for (i = 0; i < o->jitter_window; i++) { 236178825Sdfr kret = krb5_store_int32(sp, o->elem[i]); 237178825Sdfr if (kret) 238178825Sdfr return kret; 239178825Sdfr } 240233294Sstas 241178825Sdfr return 0; 242178825Sdfr} 243178825Sdfr 244178825SdfrOM_uint32 245178825Sdfr_gssapi_msg_order_import(OM_uint32 *minor_status, 246233294Sstas krb5_storage *sp, 247178825Sdfr struct gss_msg_order **o) 248178825Sdfr{ 249178825Sdfr OM_uint32 ret; 250178825Sdfr krb5_error_code kret; 251178825Sdfr int32_t i, flags, start, length, jitter_window, first_seq; 252233294Sstas 253178825Sdfr kret = krb5_ret_int32(sp, &flags); 254178825Sdfr if (kret) 255178825Sdfr goto failed; 256233294Sstas kret = krb5_ret_int32(sp, &start); 257178825Sdfr if (kret) 258178825Sdfr goto failed; 259233294Sstas kret = krb5_ret_int32(sp, &length); 260178825Sdfr if (kret) 261178825Sdfr goto failed; 262233294Sstas kret = krb5_ret_int32(sp, &jitter_window); 263178825Sdfr if (kret) 264178825Sdfr goto failed; 265233294Sstas kret = krb5_ret_int32(sp, &first_seq); 266178825Sdfr if (kret) 267178825Sdfr goto failed; 268233294Sstas 269178825Sdfr ret = msg_order_alloc(minor_status, o, jitter_window); 270178825Sdfr if (ret != GSS_S_COMPLETE) 271178825Sdfr return ret; 272233294Sstas 273178825Sdfr (*o)->flags = flags; 274178825Sdfr (*o)->start = start; 275178825Sdfr (*o)->length = length; 276178825Sdfr (*o)->jitter_window = jitter_window; 277178825Sdfr (*o)->first_seq = first_seq; 278233294Sstas 279178825Sdfr for( i = 0; i < jitter_window; i++ ) { 280178825Sdfr kret = krb5_ret_int32(sp, (int32_t*)&((*o)->elem[i])); 281178825Sdfr if (kret) 282178825Sdfr goto failed; 283178825Sdfr } 284178825Sdfr 285178825Sdfr *minor_status = 0; 286178825Sdfr return GSS_S_COMPLETE; 287178825Sdfr 288178825Sdfrfailed: 289178825Sdfr _gssapi_msg_order_destroy(o); 290178825Sdfr *minor_status = kret; 291178825Sdfr return GSS_S_FAILURE; 292178825Sdfr} 293