~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/heimdal/lib/gssapi/krb5/sequence.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

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