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