xref: /minix3/crypto/external/bsd/heimdal/dist/lib/gssapi/krb5/sequence.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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