~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/heimdal/lib/krb5/store.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) 1997-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_locl.h"
 
35
#include "store-int.h"
 
36
 
 
37
RCSID("$Id$");
 
38
 
 
39
#define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V))
 
40
#define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE)
 
41
#define BYTEORDER_IS_BE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_BE)
 
42
#define BYTEORDER_IS_HOST(SP) (BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_HOST) || \
 
43
                               krb5_storage_is_flags((SP), KRB5_STORAGE_HOST_BYTEORDER))
 
44
 
 
45
void KRB5_LIB_FUNCTION
 
46
krb5_storage_set_flags(krb5_storage *sp, krb5_flags flags)
 
47
{
 
48
    sp->flags |= flags;
 
49
}
 
50
 
 
51
void KRB5_LIB_FUNCTION
 
52
krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags)
 
53
{
 
54
    sp->flags &= ~flags;
 
55
}
 
56
 
 
57
krb5_boolean KRB5_LIB_FUNCTION
 
58
krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags)
 
59
{
 
60
    return (sp->flags & flags) == flags;
 
61
}
 
62
 
 
63
void KRB5_LIB_FUNCTION
 
64
krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder)
 
65
{
 
66
    sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK;
 
67
    sp->flags |= byteorder;
 
68
}
 
69
 
 
70
krb5_flags KRB5_LIB_FUNCTION
 
71
krb5_storage_get_byteorder(krb5_storage *sp, krb5_flags byteorder)
 
72
{
 
73
    return sp->flags & KRB5_STORAGE_BYTEORDER_MASK;
 
74
}
 
75
 
 
76
off_t KRB5_LIB_FUNCTION
 
77
krb5_storage_seek(krb5_storage *sp, off_t offset, int whence)
 
78
{
 
79
    return (*sp->seek)(sp, offset, whence);
 
80
}
 
81
 
 
82
krb5_ssize_t KRB5_LIB_FUNCTION
 
83
krb5_storage_read(krb5_storage *sp, void *buf, size_t len)
 
84
{
 
85
    return sp->fetch(sp, buf, len);
 
86
}
 
87
 
 
88
krb5_ssize_t KRB5_LIB_FUNCTION
 
89
krb5_storage_write(krb5_storage *sp, const void *buf, size_t len)
 
90
{
 
91
    return sp->store(sp, buf, len);
 
92
}
 
93
 
 
94
void KRB5_LIB_FUNCTION
 
95
krb5_storage_set_eof_code(krb5_storage *sp, int code)
 
96
{
 
97
    sp->eof_code = code;
 
98
}
 
99
 
 
100
krb5_ssize_t KRB5_LIB_FUNCTION
 
101
_krb5_put_int(void *buffer, unsigned long value, size_t size)
 
102
{
 
103
    unsigned char *p = buffer;
 
104
    int i;
 
105
    for (i = size - 1; i >= 0; i--) {
 
106
        p[i] = value & 0xff;
 
107
        value >>= 8;
 
108
    }
 
109
    return size;
 
110
}
 
111
 
 
112
krb5_ssize_t KRB5_LIB_FUNCTION
 
113
_krb5_get_int(void *buffer, unsigned long *value, size_t size)
 
114
{
 
115
    unsigned char *p = buffer;
 
116
    unsigned long v = 0;
 
117
    int i;
 
118
    for (i = 0; i < size; i++)
 
119
        v = (v << 8) + p[i];
 
120
    *value = v;
 
121
    return size;
 
122
}
 
123
 
 
124
krb5_error_code KRB5_LIB_FUNCTION
 
125
krb5_storage_free(krb5_storage *sp)
 
126
{
 
127
    if(sp->free)
 
128
        (*sp->free)(sp);
 
129
    free(sp->data);
 
130
    free(sp);
 
131
    return 0;
 
132
}
 
133
 
 
134
krb5_error_code KRB5_LIB_FUNCTION
 
135
krb5_storage_to_data(krb5_storage *sp, krb5_data *data)
 
136
{
 
137
    off_t pos;
 
138
    size_t size;
 
139
    krb5_error_code ret;
 
140
 
 
141
    pos = sp->seek(sp, 0, SEEK_CUR);
 
142
    size = (size_t)sp->seek(sp, 0, SEEK_END);
 
143
    ret = krb5_data_alloc (data, size);
 
144
    if (ret) {
 
145
        sp->seek(sp, pos, SEEK_SET);
 
146
        return ret;
 
147
    }
 
148
    if (size) {
 
149
        sp->seek(sp, 0, SEEK_SET);
 
150
        sp->fetch(sp, data->data, data->length);
 
151
        sp->seek(sp, pos, SEEK_SET);
 
152
    }
 
153
    return 0;
 
154
}
 
155
 
 
156
static krb5_error_code
 
157
krb5_store_int(krb5_storage *sp,
 
158
               int32_t value,
 
159
               size_t len)
 
160
{
 
161
    int ret;
 
162
    unsigned char v[16];
 
163
 
 
164
    if(len > sizeof(v))
 
165
        return EINVAL;
 
166
    _krb5_put_int(v, value, len);
 
167
    ret = sp->store(sp, v, len);
 
168
    if (ret != len)
 
169
        return (ret<0)?errno:sp->eof_code;
 
170
    return 0;
 
171
}
 
172
 
 
173
krb5_error_code KRB5_LIB_FUNCTION
 
174
krb5_store_int32(krb5_storage *sp,
 
175
                 int32_t value)
 
176
{
 
177
    if(BYTEORDER_IS_HOST(sp))
 
178
        value = htonl(value);
 
179
    else if(BYTEORDER_IS_LE(sp))
 
180
        value = bswap32(value);
 
181
    return krb5_store_int(sp, value, 4);
 
182
}
 
183
 
 
184
krb5_error_code KRB5_LIB_FUNCTION
 
185
krb5_store_uint32(krb5_storage *sp,
 
186
                  uint32_t value)
 
187
{
 
188
    return krb5_store_int32(sp, (int32_t)value);
 
189
}
 
190
 
 
191
static krb5_error_code
 
192
krb5_ret_int(krb5_storage *sp,
 
193
             int32_t *value,
 
194
             size_t len)
 
195
{
 
196
    int ret;
 
197
    unsigned char v[4];
 
198
    unsigned long w;
 
199
    ret = sp->fetch(sp, v, len);
 
200
    if(ret != len)
 
201
        return (ret<0)?errno:sp->eof_code;
 
202
    _krb5_get_int(v, &w, len);
 
203
    *value = w;
 
204
    return 0;
 
205
}
 
206
 
 
207
krb5_error_code KRB5_LIB_FUNCTION
 
208
krb5_ret_int32(krb5_storage *sp,
 
209
               int32_t *value)
 
210
{
 
211
    krb5_error_code ret = krb5_ret_int(sp, value, 4);
 
212
    if(ret)
 
213
        return ret;
 
214
    if(BYTEORDER_IS_HOST(sp))
 
215
        *value = htonl(*value);
 
216
    else if(BYTEORDER_IS_LE(sp))
 
217
        *value = bswap32(*value);
 
218
    return 0;
 
219
}
 
220
 
 
221
krb5_error_code KRB5_LIB_FUNCTION
 
222
krb5_ret_uint32(krb5_storage *sp,
 
223
                uint32_t *value)
 
224
{
 
225
    krb5_error_code ret;
 
226
    int32_t v;
 
227
 
 
228
    ret = krb5_ret_int32(sp, &v);
 
229
    if (ret == 0)
 
230
        *value = (uint32_t)v;
 
231
 
 
232
    return ret;
 
233
}
 
234
 
 
235
krb5_error_code KRB5_LIB_FUNCTION
 
236
krb5_store_int16(krb5_storage *sp,
 
237
                 int16_t value)
 
238
{
 
239
    if(BYTEORDER_IS_HOST(sp))
 
240
        value = htons(value);
 
241
    else if(BYTEORDER_IS_LE(sp))
 
242
        value = bswap16(value);
 
243
    return krb5_store_int(sp, value, 2);
 
244
}
 
245
 
 
246
krb5_error_code KRB5_LIB_FUNCTION
 
247
krb5_store_uint16(krb5_storage *sp,
 
248
                  uint16_t value)
 
249
{
 
250
    return krb5_store_int16(sp, (int16_t)value);
 
251
}
 
252
 
 
253
krb5_error_code KRB5_LIB_FUNCTION
 
254
krb5_ret_int16(krb5_storage *sp,
 
255
               int16_t *value)
 
256
{
 
257
    int32_t v;
 
258
    int ret;
 
259
    ret = krb5_ret_int(sp, &v, 2);
 
260
    if(ret)
 
261
        return ret;
 
262
    *value = v;
 
263
    if(BYTEORDER_IS_HOST(sp))
 
264
        *value = htons(*value);
 
265
    else if(BYTEORDER_IS_LE(sp))
 
266
        *value = bswap16(*value);
 
267
    return 0;
 
268
}
 
269
 
 
270
krb5_error_code KRB5_LIB_FUNCTION
 
271
krb5_ret_uint16(krb5_storage *sp,
 
272
                uint16_t *value)
 
273
{
 
274
    krb5_error_code ret;
 
275
    int16_t v;
 
276
 
 
277
    ret = krb5_ret_int16(sp, &v);
 
278
    if (ret == 0)
 
279
        *value = (uint16_t)v;
 
280
 
 
281
    return ret;
 
282
}
 
283
 
 
284
krb5_error_code KRB5_LIB_FUNCTION
 
285
krb5_store_int8(krb5_storage *sp,
 
286
                int8_t value)
 
287
{
 
288
    int ret;
 
289
 
 
290
    ret = sp->store(sp, &value, sizeof(value));
 
291
    if (ret != sizeof(value))
 
292
        return (ret<0)?errno:sp->eof_code;
 
293
    return 0;
 
294
}
 
295
 
 
296
krb5_error_code KRB5_LIB_FUNCTION
 
297
krb5_store_uint8(krb5_storage *sp,
 
298
                 uint8_t value)
 
299
{
 
300
    return krb5_store_int8(sp, (int8_t)value);
 
301
}
 
302
 
 
303
krb5_error_code KRB5_LIB_FUNCTION
 
304
krb5_ret_int8(krb5_storage *sp,
 
305
              int8_t *value)
 
306
{
 
307
    int ret;
 
308
 
 
309
    ret = sp->fetch(sp, value, sizeof(*value));
 
310
    if (ret != sizeof(*value))
 
311
        return (ret<0)?errno:sp->eof_code;
 
312
    return 0;
 
313
}
 
314
 
 
315
krb5_error_code KRB5_LIB_FUNCTION
 
316
krb5_ret_uint8(krb5_storage *sp,
 
317
               uint8_t *value)
 
318
{
 
319
    krb5_error_code ret;
 
320
    int8_t v;
 
321
 
 
322
    ret = krb5_ret_int8(sp, &v);
 
323
    if (ret == 0)
 
324
        *value = (uint8_t)v;
 
325
 
 
326
    return ret;
 
327
}
 
328
 
 
329
krb5_error_code KRB5_LIB_FUNCTION
 
330
krb5_store_data(krb5_storage *sp,
 
331
                krb5_data data)
 
332
{
 
333
    int ret;
 
334
    ret = krb5_store_int32(sp, data.length);
 
335
    if(ret < 0)
 
336
        return ret;
 
337
    ret = sp->store(sp, data.data, data.length);
 
338
    if(ret != data.length){
 
339
        if(ret < 0)
 
340
            return errno;
 
341
        return sp->eof_code;
 
342
    }
 
343
    return 0;
 
344
}
 
345
 
 
346
krb5_error_code KRB5_LIB_FUNCTION
 
347
krb5_ret_data(krb5_storage *sp,
 
348
              krb5_data *data)
 
349
{
 
350
    int ret;
 
351
    int32_t size;
 
352
 
 
353
    ret = krb5_ret_int32(sp, &size);
 
354
    if(ret)
 
355
        return ret;
 
356
    ret = krb5_data_alloc (data, size);
 
357
    if (ret)
 
358
        return ret;
 
359
    if (size) {
 
360
        ret = sp->fetch(sp, data->data, size);
 
361
        if(ret != size)
 
362
            return (ret < 0)? errno : sp->eof_code;
 
363
    }
 
364
    return 0;
 
365
}
 
366
 
 
367
krb5_error_code KRB5_LIB_FUNCTION
 
368
krb5_store_string(krb5_storage *sp, const char *s)
 
369
{
 
370
    krb5_data data;
 
371
    data.length = strlen(s);
 
372
    data.data = rk_UNCONST(s);
 
373
    return krb5_store_data(sp, data);
 
374
}
 
375
 
 
376
krb5_error_code KRB5_LIB_FUNCTION
 
377
krb5_ret_string(krb5_storage *sp,
 
378
                char **string)
 
379
{
 
380
    int ret;
 
381
    krb5_data data;
 
382
    ret = krb5_ret_data(sp, &data);
 
383
    if(ret)
 
384
        return ret;
 
385
    *string = realloc(data.data, data.length + 1);
 
386
    if(*string == NULL){
 
387
        free(data.data);
 
388
        return ENOMEM;
 
389
    }
 
390
    (*string)[data.length] = 0;
 
391
    return 0;
 
392
}
 
393
 
 
394
krb5_error_code KRB5_LIB_FUNCTION
 
395
krb5_store_stringz(krb5_storage *sp, const char *s)
 
396
{
 
397
    size_t len = strlen(s) + 1;
 
398
    ssize_t ret;
 
399
 
 
400
    ret = sp->store(sp, s, len);
 
401
    if(ret != len) {
 
402
        if(ret < 0)
 
403
            return ret;
 
404
        else
 
405
            return sp->eof_code;
 
406
    }
 
407
    return 0;
 
408
}
 
409
 
 
410
krb5_error_code KRB5_LIB_FUNCTION
 
411
krb5_ret_stringz(krb5_storage *sp,
 
412
                char **string)
 
413
{
 
414
    char c;
 
415
    char *s = NULL;
 
416
    size_t len = 0;
 
417
    ssize_t ret;
 
418
 
 
419
    while((ret = sp->fetch(sp, &c, 1)) == 1){
 
420
        char *tmp;
 
421
 
 
422
        len++;
 
423
        tmp = realloc (s, len);
 
424
        if (tmp == NULL) {
 
425
            free (s);
 
426
            return ENOMEM;
 
427
        }
 
428
        s = tmp;
 
429
        s[len - 1] = c;
 
430
        if(c == 0)
 
431
            break;
 
432
    }
 
433
    if(ret != 1){
 
434
        free(s);
 
435
        if(ret == 0)
 
436
            return sp->eof_code;
 
437
        return ret;
 
438
    }
 
439
    *string = s;
 
440
    return 0;
 
441
}
 
442
 
 
443
krb5_error_code KRB5_LIB_FUNCTION
 
444
krb5_store_stringnl(krb5_storage *sp, const char *s)
 
445
{
 
446
    size_t len = strlen(s);
 
447
    ssize_t ret;
 
448
 
 
449
    ret = sp->store(sp, s, len);
 
450
    if(ret != len) {
 
451
        if(ret < 0)
 
452
            return ret;
 
453
        else
 
454
            return sp->eof_code;
 
455
    }
 
456
    ret = sp->store(sp, "\n", 1);
 
457
    if(ret != 1) {
 
458
        if(ret < 0)
 
459
            return ret;
 
460
        else
 
461
            return sp->eof_code;
 
462
    }
 
463
 
 
464
    return 0;
 
465
 
 
466
}
 
467
 
 
468
krb5_error_code KRB5_LIB_FUNCTION
 
469
krb5_ret_stringnl(krb5_storage *sp,
 
470
                  char **string)
 
471
{
 
472
    int expect_nl = 0;
 
473
    char c;
 
474
    char *s = NULL;
 
475
    size_t len = 0;
 
476
    ssize_t ret;
 
477
 
 
478
    while((ret = sp->fetch(sp, &c, 1)) == 1){
 
479
        char *tmp;
 
480
 
 
481
        if (c == '\r') {
 
482
            expect_nl = 1;
 
483
            continue;
 
484
        }
 
485
        if (expect_nl && c != '\n') {
 
486
            free(s);
 
487
            return KRB5_BADMSGTYPE;
 
488
        }
 
489
 
 
490
        len++;
 
491
        tmp = realloc (s, len);
 
492
        if (tmp == NULL) {
 
493
            free (s);
 
494
            return ENOMEM;
 
495
        }
 
496
        s = tmp;
 
497
        if(c == '\n') {
 
498
            s[len - 1] = '\0';
 
499
            break;
 
500
        }
 
501
        s[len - 1] = c;
 
502
    }
 
503
    if(ret != 1){
 
504
        free(s);
 
505
        if(ret == 0)
 
506
            return sp->eof_code;
 
507
        return ret;
 
508
    }
 
509
    *string = s;
 
510
    return 0;
 
511
}
 
512
 
 
513
 
 
514
krb5_error_code KRB5_LIB_FUNCTION
 
515
krb5_store_principal(krb5_storage *sp,
 
516
                     krb5_const_principal p)
 
517
{
 
518
    int i;
 
519
    int ret;
 
520
 
 
521
    if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) {
 
522
        ret = krb5_store_int32(sp, p->name.name_type);
 
523
        if(ret) return ret;
 
524
    }
 
525
    if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
 
526
        ret = krb5_store_int32(sp, p->name.name_string.len + 1);
 
527
    else
 
528
        ret = krb5_store_int32(sp, p->name.name_string.len);
 
529
 
 
530
    if(ret) return ret;
 
531
    ret = krb5_store_string(sp, p->realm);
 
532
    if(ret) return ret;
 
533
    for(i = 0; i < p->name.name_string.len; i++){
 
534
        ret = krb5_store_string(sp, p->name.name_string.val[i]);
 
535
        if(ret) return ret;
 
536
    }
 
537
    return 0;
 
538
}
 
539
 
 
540
krb5_error_code KRB5_LIB_FUNCTION
 
541
krb5_ret_principal(krb5_storage *sp,
 
542
                   krb5_principal *princ)
 
543
{
 
544
    int i;
 
545
    int ret;
 
546
    krb5_principal p;
 
547
    int32_t type;
 
548
    int32_t ncomp;
 
549
 
 
550
    p = calloc(1, sizeof(*p));
 
551
    if(p == NULL)
 
552
        return ENOMEM;
 
553
 
 
554
    if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE))
 
555
        type = KRB5_NT_UNKNOWN;
 
556
    else if((ret = krb5_ret_int32(sp, &type))){
 
557
        free(p);
 
558
        return ret;
 
559
    }
 
560
    if((ret = krb5_ret_int32(sp, &ncomp))){
 
561
        free(p);
 
562
        return ret;
 
563
    }
 
564
    if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
 
565
        ncomp--;
 
566
    if (ncomp < 0) {
 
567
        free(p);
 
568
        return EINVAL;
 
569
    }
 
570
    p->name.name_type = type;
 
571
    p->name.name_string.len = ncomp;
 
572
    ret = krb5_ret_string(sp, &p->realm);
 
573
    if(ret) {
 
574
        free(p);
 
575
        return ret;
 
576
    }
 
577
    p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val));
 
578
    if(p->name.name_string.val == NULL && ncomp != 0){
 
579
        free(p->realm);
 
580
        free(p);
 
581
        return ENOMEM;
 
582
    }
 
583
    for(i = 0; i < ncomp; i++){
 
584
        ret = krb5_ret_string(sp, &p->name.name_string.val[i]);
 
585
        if(ret) {
 
586
            while (i >= 0)
 
587
                free(p->name.name_string.val[i--]);
 
588
            free(p->realm);
 
589
            free(p);
 
590
            return ret;
 
591
        }
 
592
    }
 
593
    *princ = p;
 
594
    return 0;
 
595
}
 
596
 
 
597
krb5_error_code KRB5_LIB_FUNCTION
 
598
krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
 
599
{
 
600
    int ret;
 
601
    ret = krb5_store_int16(sp, p.keytype);
 
602
    if(ret) return ret;
 
603
 
 
604
    if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
 
605
        /* this should really be enctype, but it is the same as
 
606
           keytype nowadays */
 
607
    ret = krb5_store_int16(sp, p.keytype);
 
608
    if(ret) return ret;
 
609
    }
 
610
 
 
611
    ret = krb5_store_data(sp, p.keyvalue);
 
612
    return ret;
 
613
}
 
614
 
 
615
krb5_error_code KRB5_LIB_FUNCTION
 
616
krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
 
617
{
 
618
    int ret;
 
619
    int16_t tmp;
 
620
 
 
621
    ret = krb5_ret_int16(sp, &tmp);
 
622
    if(ret) return ret;
 
623
    p->keytype = tmp;
 
624
 
 
625
    if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
 
626
    ret = krb5_ret_int16(sp, &tmp);
 
627
    if(ret) return ret;
 
628
    }
 
629
 
 
630
    ret = krb5_ret_data(sp, &p->keyvalue);
 
631
    return ret;
 
632
}
 
633
 
 
634
krb5_error_code KRB5_LIB_FUNCTION
 
635
krb5_store_times(krb5_storage *sp, krb5_times times)
 
636
{
 
637
    int ret;
 
638
    ret = krb5_store_int32(sp, times.authtime);
 
639
    if(ret) return ret;
 
640
    ret = krb5_store_int32(sp, times.starttime);
 
641
    if(ret) return ret;
 
642
    ret = krb5_store_int32(sp, times.endtime);
 
643
    if(ret) return ret;
 
644
    ret = krb5_store_int32(sp, times.renew_till);
 
645
    return ret;
 
646
}
 
647
 
 
648
krb5_error_code KRB5_LIB_FUNCTION
 
649
krb5_ret_times(krb5_storage *sp, krb5_times *times)
 
650
{
 
651
    int ret;
 
652
    int32_t tmp;
 
653
    ret = krb5_ret_int32(sp, &tmp);
 
654
    times->authtime = tmp;
 
655
    if(ret) return ret;
 
656
    ret = krb5_ret_int32(sp, &tmp);
 
657
    times->starttime = tmp;
 
658
    if(ret) return ret;
 
659
    ret = krb5_ret_int32(sp, &tmp);
 
660
    times->endtime = tmp;
 
661
    if(ret) return ret;
 
662
    ret = krb5_ret_int32(sp, &tmp);
 
663
    times->renew_till = tmp;
 
664
    return ret;
 
665
}
 
666
 
 
667
krb5_error_code KRB5_LIB_FUNCTION
 
668
krb5_store_address(krb5_storage *sp, krb5_address p)
 
669
{
 
670
    int ret;
 
671
    ret = krb5_store_int16(sp, p.addr_type);
 
672
    if(ret) return ret;
 
673
    ret = krb5_store_data(sp, p.address);
 
674
    return ret;
 
675
}
 
676
 
 
677
krb5_error_code KRB5_LIB_FUNCTION
 
678
krb5_ret_address(krb5_storage *sp, krb5_address *adr)
 
679
{
 
680
    int16_t t;
 
681
    int ret;
 
682
    ret = krb5_ret_int16(sp, &t);
 
683
    if(ret) return ret;
 
684
    adr->addr_type = t;
 
685
    ret = krb5_ret_data(sp, &adr->address);
 
686
    return ret;
 
687
}
 
688
 
 
689
krb5_error_code KRB5_LIB_FUNCTION
 
690
krb5_store_addrs(krb5_storage *sp, krb5_addresses p)
 
691
{
 
692
    int i;
 
693
    int ret;
 
694
    ret = krb5_store_int32(sp, p.len);
 
695
    if(ret) return ret;
 
696
    for(i = 0; i<p.len; i++){
 
697
        ret = krb5_store_address(sp, p.val[i]);
 
698
        if(ret) break;
 
699
    }
 
700
    return ret;
 
701
}
 
702
 
 
703
krb5_error_code KRB5_LIB_FUNCTION
 
704
krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr)
 
705
{
 
706
    int i;
 
707
    int ret;
 
708
    int32_t tmp;
 
709
 
 
710
    ret = krb5_ret_int32(sp, &tmp);
 
711
    if(ret) return ret;
 
712
    adr->len = tmp;
 
713
    ALLOC(adr->val, adr->len);
 
714
    if (adr->val == NULL && adr->len != 0)
 
715
        return ENOMEM;
 
716
    for(i = 0; i < adr->len; i++){
 
717
        ret = krb5_ret_address(sp, &adr->val[i]);
 
718
        if(ret) break;
 
719
    }
 
720
    return ret;
 
721
}
 
722
 
 
723
krb5_error_code KRB5_LIB_FUNCTION
 
724
krb5_store_authdata(krb5_storage *sp, krb5_authdata auth)
 
725
{
 
726
    krb5_error_code ret;
 
727
    int i;
 
728
    ret = krb5_store_int32(sp, auth.len);
 
729
    if(ret) return ret;
 
730
    for(i = 0; i < auth.len; i++){
 
731
        ret = krb5_store_int16(sp, auth.val[i].ad_type);
 
732
        if(ret) break;
 
733
        ret = krb5_store_data(sp, auth.val[i].ad_data);
 
734
        if(ret) break;
 
735
    }
 
736
    return 0;
 
737
}
 
738
 
 
739
krb5_error_code KRB5_LIB_FUNCTION
 
740
krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth)
 
741
{
 
742
    krb5_error_code ret;
 
743
    int32_t tmp;
 
744
    int16_t tmp2;
 
745
    int i;
 
746
    ret = krb5_ret_int32(sp, &tmp);
 
747
    if(ret) return ret;
 
748
    ALLOC_SEQ(auth, tmp);
 
749
    if (auth->val == NULL && tmp != 0)
 
750
        return ENOMEM;
 
751
    for(i = 0; i < tmp; i++){
 
752
        ret = krb5_ret_int16(sp, &tmp2);
 
753
        if(ret) break;
 
754
        auth->val[i].ad_type = tmp2;
 
755
        ret = krb5_ret_data(sp, &auth->val[i].ad_data);
 
756
        if(ret) break;
 
757
    }
 
758
    return ret;
 
759
}
 
760
 
 
761
static int32_t
 
762
bitswap32(int32_t b)
 
763
{
 
764
    int32_t r = 0;
 
765
    int i;
 
766
    for (i = 0; i < 32; i++) {
 
767
        r = r << 1 | (b & 1);
 
768
        b = b >> 1;
 
769
    }
 
770
    return r;
 
771
}
 
772
 
 
773
 
 
774
/*
 
775
 *
 
776
 */
 
777
 
 
778
krb5_error_code KRB5_LIB_FUNCTION
 
779
krb5_store_creds(krb5_storage *sp, krb5_creds *creds)
 
780
{
 
781
    int ret;
 
782
 
 
783
    ret = krb5_store_principal(sp, creds->client);
 
784
    if(ret)
 
785
        return ret;
 
786
    ret = krb5_store_principal(sp, creds->server);
 
787
    if(ret)
 
788
        return ret;
 
789
    ret = krb5_store_keyblock(sp, creds->session);
 
790
    if(ret)
 
791
        return ret;
 
792
    ret = krb5_store_times(sp, creds->times);
 
793
    if(ret)
 
794
        return ret;
 
795
    ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
 
796
    if(ret)
 
797
        return ret;
 
798
 
 
799
    if(krb5_storage_is_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER))
 
800
        ret = krb5_store_int32(sp, creds->flags.i);
 
801
    else
 
802
        ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
 
803
    if(ret)
 
804
        return ret;
 
805
 
 
806
    ret = krb5_store_addrs(sp, creds->addresses);
 
807
    if(ret)
 
808
        return ret;
 
809
    ret = krb5_store_authdata(sp, creds->authdata);
 
810
    if(ret)
 
811
        return ret;
 
812
    ret = krb5_store_data(sp, creds->ticket);
 
813
    if(ret)
 
814
        return ret;
 
815
    ret = krb5_store_data(sp, creds->second_ticket);
 
816
    return ret;
 
817
}
 
818
 
 
819
krb5_error_code KRB5_LIB_FUNCTION
 
820
krb5_ret_creds(krb5_storage *sp, krb5_creds *creds)
 
821
{
 
822
    krb5_error_code ret;
 
823
    int8_t dummy8;
 
824
    int32_t dummy32;
 
825
 
 
826
    memset(creds, 0, sizeof(*creds));
 
827
    ret = krb5_ret_principal (sp,  &creds->client);
 
828
    if(ret) goto cleanup;
 
829
    ret = krb5_ret_principal (sp,  &creds->server);
 
830
    if(ret) goto cleanup;
 
831
    ret = krb5_ret_keyblock (sp,  &creds->session);
 
832
    if(ret) goto cleanup;
 
833
    ret = krb5_ret_times (sp,  &creds->times);
 
834
    if(ret) goto cleanup;
 
835
    ret = krb5_ret_int8 (sp,  &dummy8);
 
836
    if(ret) goto cleanup;
 
837
    ret = krb5_ret_int32 (sp,  &dummy32);
 
838
    if(ret) goto cleanup;
 
839
    /*
 
840
     * Runtime detect the what is the higher bits of the bitfield. If
 
841
     * any of the higher bits are set in the input data, it's either a
 
842
     * new ticket flag (and this code need to be removed), or it's a
 
843
     * MIT cache (or new Heimdal cache), lets change it to our current
 
844
     * format.
 
845
     */
 
846
    {
 
847
        uint32_t mask = 0xffff0000;
 
848
        creds->flags.i = 0;
 
849
        creds->flags.b.anonymous = 1;
 
850
        if (creds->flags.i & mask)
 
851
            mask = ~mask;
 
852
        if (dummy32 & mask)
 
853
            dummy32 = bitswap32(dummy32);
 
854
    }
 
855
    creds->flags.i = dummy32;
 
856
    ret = krb5_ret_addrs (sp,  &creds->addresses);
 
857
    if(ret) goto cleanup;
 
858
    ret = krb5_ret_authdata (sp,  &creds->authdata);
 
859
    if(ret) goto cleanup;
 
860
    ret = krb5_ret_data (sp,  &creds->ticket);
 
861
    if(ret) goto cleanup;
 
862
    ret = krb5_ret_data (sp,  &creds->second_ticket);
 
863
cleanup:
 
864
    if(ret) {
 
865
#if 0   
 
866
        krb5_free_cred_contents(context, creds); /* XXX */
 
867
#endif
 
868
    }
 
869
    return ret;
 
870
}
 
871
 
 
872
#define SC_CLIENT_PRINCIPAL         0x0001
 
873
#define SC_SERVER_PRINCIPAL         0x0002
 
874
#define SC_SESSION_KEY              0x0004
 
875
#define SC_TICKET                   0x0008
 
876
#define SC_SECOND_TICKET            0x0010
 
877
#define SC_AUTHDATA                 0x0020
 
878
#define SC_ADDRESSES                0x0040
 
879
 
 
880
/*
 
881
 *
 
882
 */
 
883
 
 
884
krb5_error_code KRB5_LIB_FUNCTION
 
885
krb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds)
 
886
{
 
887
    int ret;
 
888
    int32_t header = 0;
 
889
 
 
890
    if (creds->client)
 
891
        header |= SC_CLIENT_PRINCIPAL;
 
892
    if (creds->server)
 
893
        header |= SC_SERVER_PRINCIPAL;
 
894
    if (creds->session.keytype != ETYPE_NULL)
 
895
        header |= SC_SESSION_KEY;
 
896
    if (creds->ticket.data)
 
897
        header |= SC_TICKET;
 
898
    if (creds->second_ticket.length)
 
899
        header |= SC_SECOND_TICKET;
 
900
    if (creds->authdata.len)
 
901
        header |= SC_AUTHDATA;
 
902
    if (creds->addresses.len)
 
903
        header |= SC_ADDRESSES;
 
904
 
 
905
    ret = krb5_store_int32(sp, header);
 
906
 
 
907
    if (creds->client) {
 
908
        ret = krb5_store_principal(sp, creds->client);
 
909
        if(ret)
 
910
            return ret;
 
911
    }
 
912
 
 
913
    if (creds->server) {
 
914
        ret = krb5_store_principal(sp, creds->server);
 
915
        if(ret)
 
916
            return ret;
 
917
    }
 
918
 
 
919
    if (creds->session.keytype != ETYPE_NULL) {
 
920
        ret = krb5_store_keyblock(sp, creds->session);
 
921
        if(ret)
 
922
            return ret;
 
923
    }
 
924
 
 
925
    ret = krb5_store_times(sp, creds->times);
 
926
    if(ret)
 
927
        return ret;
 
928
    ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
 
929
    if(ret)
 
930
        return ret;
 
931
 
 
932
    ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
 
933
    if(ret)
 
934
        return ret;
 
935
 
 
936
    if (creds->addresses.len) {
 
937
        ret = krb5_store_addrs(sp, creds->addresses);
 
938
        if(ret)
 
939
            return ret;
 
940
    }
 
941
 
 
942
    if (creds->authdata.len) {
 
943
        ret = krb5_store_authdata(sp, creds->authdata);
 
944
        if(ret)
 
945
            return ret;
 
946
    }
 
947
 
 
948
    if (creds->ticket.data) {
 
949
        ret = krb5_store_data(sp, creds->ticket);
 
950
        if(ret)
 
951
            return ret;
 
952
    }
 
953
 
 
954
    if (creds->second_ticket.data) {
 
955
        ret = krb5_store_data(sp, creds->second_ticket);
 
956
        if (ret)
 
957
            return ret;
 
958
    }
 
959
 
 
960
    return ret;
 
961
}
 
962
 
 
963
krb5_error_code KRB5_LIB_FUNCTION
 
964
krb5_ret_creds_tag(krb5_storage *sp,
 
965
                   krb5_creds *creds)
 
966
{
 
967
    krb5_error_code ret;
 
968
    int8_t dummy8;
 
969
    int32_t dummy32, header;
 
970
 
 
971
    memset(creds, 0, sizeof(*creds));
 
972
 
 
973
    ret = krb5_ret_int32 (sp, &header);
 
974
    if (ret) goto cleanup;
 
975
 
 
976
    if (header & SC_CLIENT_PRINCIPAL) {
 
977
        ret = krb5_ret_principal (sp,  &creds->client);
 
978
        if(ret) goto cleanup;
 
979
    }
 
980
    if (header & SC_SERVER_PRINCIPAL) {
 
981
        ret = krb5_ret_principal (sp,  &creds->server);
 
982
        if(ret) goto cleanup;
 
983
    }
 
984
    if (header & SC_SESSION_KEY) {
 
985
        ret = krb5_ret_keyblock (sp,  &creds->session);
 
986
        if(ret) goto cleanup;
 
987
    }
 
988
    ret = krb5_ret_times (sp,  &creds->times);
 
989
    if(ret) goto cleanup;
 
990
    ret = krb5_ret_int8 (sp,  &dummy8);
 
991
    if(ret) goto cleanup;
 
992
    ret = krb5_ret_int32 (sp,  &dummy32);
 
993
    if(ret) goto cleanup;
 
994
    /*
 
995
     * Runtime detect the what is the higher bits of the bitfield. If
 
996
     * any of the higher bits are set in the input data, it's either a
 
997
     * new ticket flag (and this code need to be removed), or it's a
 
998
     * MIT cache (or new Heimdal cache), lets change it to our current
 
999
     * format.
 
1000
     */
 
1001
    {
 
1002
        uint32_t mask = 0xffff0000;
 
1003
        creds->flags.i = 0;
 
1004
        creds->flags.b.anonymous = 1;
 
1005
        if (creds->flags.i & mask)
 
1006
            mask = ~mask;
 
1007
        if (dummy32 & mask)
 
1008
            dummy32 = bitswap32(dummy32);
 
1009
    }
 
1010
    creds->flags.i = dummy32;
 
1011
    if (header & SC_ADDRESSES) {
 
1012
        ret = krb5_ret_addrs (sp,  &creds->addresses);
 
1013
        if(ret) goto cleanup;
 
1014
    }
 
1015
    if (header & SC_AUTHDATA) {
 
1016
        ret = krb5_ret_authdata (sp,  &creds->authdata);
 
1017
        if(ret) goto cleanup;
 
1018
    }
 
1019
    if (header & SC_TICKET) {
 
1020
        ret = krb5_ret_data (sp,  &creds->ticket);
 
1021
        if(ret) goto cleanup;
 
1022
    }
 
1023
    if (header & SC_SECOND_TICKET) {
 
1024
        ret = krb5_ret_data (sp,  &creds->second_ticket);
 
1025
        if(ret) goto cleanup;
 
1026
    }
 
1027
 
 
1028
cleanup:
 
1029
    if(ret) {
 
1030
#if 0   
 
1031
        krb5_free_cred_contents(context, creds); /* XXX */
 
1032
#endif
 
1033
    }
 
1034
    return ret;
 
1035
}