~ubuntu-branches/ubuntu/oneiric/likewise-open/oneiric

« back to all changes in this revision

Viewing changes to krb5/src/plugins/kdb/db2/kdb_xdr.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Salley
  • Date: 2010-11-22 12:06:00 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20101122120600-8lba1fpceot71wlb
Tags: 6.0.0.53010-1
Likewise Open 6.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * lib/kdb/kdb_xdr.c
 
3
 *
 
4
 * Copyright 1995 by the Massachusetts Institute of Technology. 
 
5
 * All Rights Reserved.
 
6
 *
 
7
 * Export of this software from the United States of America may
 
8
 *   require a specific license from the United States Government.
 
9
 *   It is the responsibility of any person or organization contemplating
 
10
 *   export to obtain such a license before exporting.
 
11
 * 
 
12
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
 
13
 * distribute this software and its documentation for any purpose and
 
14
 * without fee is hereby granted, provided that the above copyright
 
15
 * notice appear in all copies and that both that copyright notice and
 
16
 * this permission notice appear in supporting documentation, and that
 
17
 * the name of M.I.T. not be used in advertising or publicity pertaining
 
18
 * to distribution of the software without specific, written prior
 
19
 * permission.  Furthermore if you modify this software you must label
 
20
 * your software as modified software and not distribute it in such a
 
21
 * fashion that it might be confused with the original M.I.T. software.
 
22
 * M.I.T. makes no representations about the suitability of
 
23
 * this software for any purpose.  It is provided "as is" without express
 
24
 * or implied warranty.
 
25
 * 
 
26
 */
 
27
 
 
28
#include "k5-int.h"
 
29
#include <string.h>
 
30
#include <stdio.h>
 
31
#include <errno.h>
 
32
#include "kdb_xdr.h"
 
33
 
 
34
krb5_error_code
 
35
krb5_encode_princ_dbkey(context, key, principal)
 
36
    krb5_context context;
 
37
    krb5_data  *key;
 
38
    krb5_const_principal principal;
 
39
{
 
40
    char *princ_name;
 
41
    krb5_error_code retval;
 
42
 
 
43
    if (!(retval = krb5_unparse_name(context, principal, &princ_name))) {
 
44
        /* need to store the NULL for decoding */
 
45
        key->length = strlen(princ_name)+1;     
 
46
        key->data = princ_name;
 
47
    }
 
48
    return(retval);
 
49
}
 
50
 
 
51
void
 
52
krb5_free_princ_dbkey(context, key)
 
53
    krb5_context context;
 
54
    krb5_data  *key;
 
55
{
 
56
    (void) krb5_free_data_contents(context, key);
 
57
}
 
58
 
 
59
krb5_error_code
 
60
krb5_encode_princ_contents(context, content, entry)
 
61
    krb5_context          context;
 
62
    krb5_data           * content;
 
63
    krb5_db_entry       * entry;
 
64
{
 
65
    int                   i, j;
 
66
    unsigned int          unparse_princ_size;
 
67
    char                * unparse_princ;
 
68
    unsigned char       * nextloc;
 
69
    krb5_tl_data        * tl_data;
 
70
    krb5_error_code       retval;
 
71
    krb5_int16            psize16;
 
72
 
 
73
    /*
 
74
     * Generate one lump of data from the krb5_db_entry.
 
75
     * This data must be independent of byte order of the machine,
 
76
     * compact and extensible.
 
77
     */
 
78
 
 
79
    /* 
 
80
     * First allocate enough space for all the data. 
 
81
     * Need  2 bytes for the length of the base structure
 
82
     * then 36 [ 8 * 4 + 2 * 2] bytes for the base information
 
83
     *         [ attributes, max_life, max_renewable_life, expiration,
 
84
     *           pw_expiration, last_success, last_failed, fail_auth_count ]
 
85
     *         [ n_key_data, n_tl_data ]
 
86
     * then XX bytes [ e_length ] for the extra data [ e_data ]
 
87
     * then XX bytes [ 2 for length + length for string ] for the principal,
 
88
     * then (4 [type + length] + tl_data_length) bytes per tl_data
 
89
     * then (4 + (4 + key_data_length) per key_data_contents) bytes per key_data
 
90
     */
 
91
    content->length = entry->len + entry->e_length;
 
92
 
 
93
    if ((retval = krb5_unparse_name(context, entry->princ, &unparse_princ)))
 
94
        return(retval);
 
95
 
 
96
    unparse_princ_size = strlen(unparse_princ) + 1;
 
97
    content->length += unparse_princ_size;
 
98
    content->length += 2;               
 
99
 
 
100
    i = 0;
 
101
    /* tl_data is a linked list */
 
102
    for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
 
103
        content->length += tl_data->tl_data_length;
 
104
        content->length += 4; /* type, length */
 
105
        i++;
 
106
    }
 
107
 
 
108
    if (i != entry->n_tl_data) {
 
109
        retval = KRB5_KDB_TRUNCATED_RECORD;
 
110
        goto epc_error;
 
111
    }
 
112
 
 
113
    /* key_data is an array */
 
114
    for (i = 0; i < entry->n_key_data; i++) {
 
115
        content->length += 4; /* Version, KVNO */
 
116
        for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
 
117
            content->length += entry->key_data[i].key_data_length[j];
 
118
            content->length += 4; /* type + length */
 
119
        }
 
120
    }
 
121
        
 
122
    if ((content->data = malloc(content->length)) == NULL) {
 
123
        retval = ENOMEM;
 
124
        goto epc_error;
 
125
    }
 
126
 
 
127
    /* 
 
128
     * Now we go through entry again, this time copying data 
 
129
     * These first entries are always saved regardless of version
 
130
     */
 
131
    nextloc = (unsigned char *)content->data;
 
132
 
 
133
        /* Base Length */
 
134
    krb5_kdb_encode_int16(entry->len, nextloc);
 
135
    nextloc += 2;
 
136
 
 
137
        /* Attributes */
 
138
    krb5_kdb_encode_int32(entry->attributes, nextloc);
 
139
    nextloc += 4;
 
140
  
 
141
        /* Max Life */
 
142
    krb5_kdb_encode_int32(entry->max_life, nextloc);
 
143
    nextloc += 4;
 
144
  
 
145
        /* Max Renewable Life */
 
146
    krb5_kdb_encode_int32(entry->max_renewable_life, nextloc);
 
147
    nextloc += 4;
 
148
  
 
149
        /* When the client expires */
 
150
    krb5_kdb_encode_int32(entry->expiration, nextloc);
 
151
    nextloc += 4;
 
152
  
 
153
        /* When its passwd expires */
 
154
    krb5_kdb_encode_int32(entry->pw_expiration, nextloc);
 
155
    nextloc += 4;
 
156
  
 
157
        /* Last successful passwd */
 
158
    krb5_kdb_encode_int32(entry->last_success, nextloc);
 
159
    nextloc += 4;
 
160
  
 
161
        /* Last failed passwd attempt */
 
162
    krb5_kdb_encode_int32(entry->last_failed, nextloc);
 
163
    nextloc += 4;
 
164
  
 
165
        /* # of failed passwd attempt */
 
166
    krb5_kdb_encode_int32(entry->fail_auth_count, nextloc);
 
167
    nextloc += 4;
 
168
 
 
169
        /* # tl_data strutures */
 
170
    krb5_kdb_encode_int16(entry->n_tl_data, nextloc);
 
171
    nextloc += 2;
 
172
  
 
173
        /* # key_data strutures */
 
174
    krb5_kdb_encode_int16(entry->n_key_data, nextloc);
 
175
    nextloc += 2;
 
176
  
 
177
        /* Put extended fields here */
 
178
    if (entry->len != KRB5_KDB_V1_BASE_LENGTH)
 
179
        abort();
 
180
 
 
181
        /* Any extra data that this version doesn't understand. */
 
182
    if (entry->e_length) {
 
183
        memcpy(nextloc, entry->e_data, entry->e_length);
 
184
        nextloc += entry->e_length;
 
185
    }
 
186
  
 
187
        /* 
 
188
         * Now we get to the principal.
 
189
         * To squeze a few extra bytes out it is always assumed to come
 
190
         * after the base type.
 
191
         */
 
192
    psize16 = (krb5_int16) unparse_princ_size;
 
193
    krb5_kdb_encode_int16(psize16, nextloc);
 
194
    nextloc += 2;
 
195
    (void) memcpy(nextloc, unparse_princ, unparse_princ_size);
 
196
    nextloc += unparse_princ_size;
 
197
 
 
198
        /* tl_data is a linked list, of type, legth, contents */
 
199
    for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
 
200
        krb5_kdb_encode_int16(tl_data->tl_data_type, nextloc);
 
201
        nextloc += 2;
 
202
        krb5_kdb_encode_int16(tl_data->tl_data_length, nextloc);
 
203
        nextloc += 2;
 
204
 
 
205
        memcpy(nextloc, tl_data->tl_data_contents, tl_data->tl_data_length);
 
206
        nextloc += tl_data->tl_data_length;
 
207
    }
 
208
 
 
209
        /* key_data is an array */
 
210
    for (i = 0; i < entry->n_key_data; i++) {
 
211
        krb5_kdb_encode_int16(entry->key_data[i].key_data_ver, nextloc);
 
212
        nextloc += 2;
 
213
        krb5_kdb_encode_int16(entry->key_data[i].key_data_kvno, nextloc);
 
214
        nextloc += 2;
 
215
 
 
216
        for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
 
217
            krb5_int16 type = entry->key_data[i].key_data_type[j];
 
218
            krb5_ui_2  length = entry->key_data[i].key_data_length[j];
 
219
 
 
220
            krb5_kdb_encode_int16(type, nextloc);
 
221
            nextloc += 2;
 
222
            krb5_kdb_encode_int16(length, nextloc);
 
223
            nextloc += 2;
 
224
 
 
225
            if (length) {
 
226
                memcpy(nextloc, entry->key_data[i].key_data_contents[j],length);
 
227
                nextloc += length;
 
228
            }
 
229
        }
 
230
    }
 
231
        
 
232
epc_error:;
 
233
    free(unparse_princ);
 
234
    return retval;
 
235
}
 
236
 
 
237
void
 
238
krb5_free_princ_contents(context, contents)
 
239
    krb5_context          context;
 
240
    krb5_data *contents;
 
241
{
 
242
    krb5_free_data_contents(context, contents);
 
243
    return;
 
244
}
 
245
 
 
246
krb5_error_code
 
247
krb5_decode_princ_contents(context, content, entry)
 
248
    krb5_context          context;
 
249
    krb5_data           * content;
 
250
    krb5_db_entry       * entry;
 
251
{
 
252
    int                   sizeleft, i;
 
253
    unsigned char       * nextloc;
 
254
    krb5_tl_data       ** tl_data;
 
255
    krb5_int16            i16;
 
256
 
 
257
    krb5_error_code retval;
 
258
 
 
259
    /* Zero out entry and NULL pointers */
 
260
    memset(entry, 0, sizeof(krb5_db_entry));
 
261
 
 
262
    /*
 
263
     * undo the effects of encode_princ_contents.
 
264
     *
 
265
     * The first part is decoding the base type. If the base type is
 
266
     * bigger than the original base type then the additional fields
 
267
     * need to be filled in. If the base type is larger than any
 
268
     * known base type the additional data goes in e_data.
 
269
     */
 
270
 
 
271
    /* First do the easy stuff */
 
272
    nextloc = (unsigned char *)content->data;
 
273
    sizeleft = content->length;
 
274
    if ((sizeleft -= KRB5_KDB_V1_BASE_LENGTH) < 0) 
 
275
        return KRB5_KDB_TRUNCATED_RECORD;
 
276
 
 
277
        /* Base Length */
 
278
    krb5_kdb_decode_int16(nextloc, entry->len);
 
279
    nextloc += 2;
 
280
 
 
281
        /* Attributes */
 
282
    krb5_kdb_decode_int32(nextloc, entry->attributes);
 
283
    nextloc += 4;
 
284
 
 
285
        /* Max Life */
 
286
    krb5_kdb_decode_int32(nextloc, entry->max_life);
 
287
    nextloc += 4;
 
288
 
 
289
        /* Max Renewable Life */
 
290
    krb5_kdb_decode_int32(nextloc, entry->max_renewable_life);
 
291
    nextloc += 4;
 
292
 
 
293
        /* When the client expires */
 
294
    krb5_kdb_decode_int32(nextloc, entry->expiration);
 
295
    nextloc += 4;
 
296
 
 
297
        /* When its passwd expires */
 
298
    krb5_kdb_decode_int32(nextloc, entry->pw_expiration);
 
299
    nextloc += 4;
 
300
 
 
301
        /* Last successful passwd */
 
302
    krb5_kdb_decode_int32(nextloc, entry->last_success);
 
303
    nextloc += 4;
 
304
 
 
305
        /* Last failed passwd attempt */
 
306
    krb5_kdb_decode_int32(nextloc, entry->last_failed);
 
307
    nextloc += 4;
 
308
 
 
309
        /* # of failed passwd attempt */
 
310
    krb5_kdb_decode_int32(nextloc, entry->fail_auth_count);
 
311
    nextloc += 4;
 
312
 
 
313
        /* # tl_data strutures */
 
314
    krb5_kdb_decode_int16(nextloc, entry->n_tl_data);
 
315
    nextloc += 2;
 
316
 
 
317
    if (entry->n_tl_data < 0)
 
318
        return KRB5_KDB_TRUNCATED_RECORD;
 
319
 
 
320
        /* # key_data strutures */
 
321
    krb5_kdb_decode_int16(nextloc, entry->n_key_data);
 
322
    nextloc += 2;
 
323
 
 
324
    if (entry->n_key_data < 0)
 
325
        return KRB5_KDB_TRUNCATED_RECORD;
 
326
 
 
327
        /* Check for extra data */
 
328
    if (entry->len > KRB5_KDB_V1_BASE_LENGTH) {
 
329
        entry->e_length = entry->len - KRB5_KDB_V1_BASE_LENGTH;
 
330
        if ((entry->e_data = (krb5_octet *)malloc(entry->e_length))) {
 
331
            memcpy(entry->e_data, nextloc, entry->e_length);
 
332
            nextloc += entry->e_length;
 
333
        } else {
 
334
            return ENOMEM;
 
335
        }
 
336
    }
 
337
 
 
338
    /*
 
339
     * Get the principal name for the entry 
 
340
     * (stored as a string which gets unparsed.)
 
341
     */
 
342
    if ((sizeleft -= 2) < 0) {
 
343
        retval = KRB5_KDB_TRUNCATED_RECORD;
 
344
        goto error_out;
 
345
    }
 
346
 
 
347
    i = 0;
 
348
    krb5_kdb_decode_int16(nextloc, i16);
 
349
    i = (int) i16;
 
350
    nextloc += 2;
 
351
 
 
352
    if ((retval = krb5_parse_name(context, (char *)nextloc, &(entry->princ))))
 
353
        goto error_out;
 
354
    if (((size_t) i != (strlen((char *)nextloc) + 1)) || (sizeleft < i)) {
 
355
        retval = KRB5_KDB_TRUNCATED_RECORD;
 
356
        goto error_out;
 
357
    }
 
358
    sizeleft -= i;
 
359
    nextloc += i;
 
360
 
 
361
        /* tl_data is a linked list */
 
362
    tl_data = &entry->tl_data;
 
363
    for (i = 0; i < entry->n_tl_data; i++) {
 
364
        if ((sizeleft -= 4) < 0) {
 
365
            retval = KRB5_KDB_TRUNCATED_RECORD;
 
366
            goto error_out;
 
367
        }
 
368
        if ((*tl_data = (krb5_tl_data *)
 
369
          malloc(sizeof(krb5_tl_data))) == NULL) {
 
370
            retval = ENOMEM;
 
371
            goto error_out;
 
372
        }
 
373
        (*tl_data)->tl_data_next = NULL;
 
374
        (*tl_data)->tl_data_contents = NULL;
 
375
        krb5_kdb_decode_int16(nextloc, (*tl_data)->tl_data_type);
 
376
        nextloc += 2;
 
377
        krb5_kdb_decode_int16(nextloc, (*tl_data)->tl_data_length);
 
378
        nextloc += 2;
 
379
 
 
380
        if ((sizeleft -= (*tl_data)->tl_data_length) < 0) {
 
381
            retval = KRB5_KDB_TRUNCATED_RECORD;
 
382
            goto error_out;
 
383
        }
 
384
        if (((*tl_data)->tl_data_contents = (krb5_octet *)
 
385
          malloc((*tl_data)->tl_data_length)) == NULL) {
 
386
            retval = ENOMEM;
 
387
            goto error_out;
 
388
        }
 
389
        memcpy((*tl_data)->tl_data_contents,nextloc,(*tl_data)->tl_data_length);
 
390
        nextloc += (*tl_data)->tl_data_length;
 
391
        tl_data = &((*tl_data)->tl_data_next);
 
392
    }
 
393
 
 
394
        /* key_data is an array */
 
395
    if (entry->n_key_data && ((entry->key_data = (krb5_key_data *)
 
396
      malloc(sizeof(krb5_key_data) * entry->n_key_data)) == NULL)) {
 
397
        retval = ENOMEM;
 
398
        goto error_out;
 
399
    }
 
400
    for (i = 0; i < entry->n_key_data; i++) {
 
401
        krb5_key_data * key_data;
 
402
        int j;
 
403
 
 
404
        if ((sizeleft -= 4) < 0) {
 
405
            retval = KRB5_KDB_TRUNCATED_RECORD;
 
406
            goto error_out;
 
407
        }
 
408
        key_data = entry->key_data + i;
 
409
        memset(key_data, 0, sizeof(krb5_key_data));
 
410
        krb5_kdb_decode_int16(nextloc, key_data->key_data_ver);
 
411
        nextloc += 2;
 
412
        krb5_kdb_decode_int16(nextloc, key_data->key_data_kvno);
 
413
        nextloc += 2;
 
414
 
 
415
        /* key_data_ver determins number of elements and how to unparse them. */
 
416
        if (key_data->key_data_ver <= KRB5_KDB_V1_KEY_DATA_ARRAY) {
 
417
            for (j = 0; j < key_data->key_data_ver; j++) {
 
418
                if ((sizeleft -= 4) < 0) {
 
419
                    retval = KRB5_KDB_TRUNCATED_RECORD;
 
420
                    goto error_out;
 
421
                }
 
422
                krb5_kdb_decode_int16(nextloc, key_data->key_data_type[j]);
 
423
                nextloc += 2;
 
424
                krb5_kdb_decode_int16(nextloc, key_data->key_data_length[j]);
 
425
                nextloc += 2;
 
426
 
 
427
                if ((sizeleft -= key_data->key_data_length[j]) < 0) {
 
428
                    retval = KRB5_KDB_TRUNCATED_RECORD;
 
429
                    goto error_out;
 
430
                }
 
431
                if (key_data->key_data_length[j]) {
 
432
                    if ((key_data->key_data_contents[j] = (krb5_octet *)
 
433
                      malloc(key_data->key_data_length[j])) == NULL) {
 
434
                        retval = ENOMEM;
 
435
                        goto error_out;
 
436
                    }
 
437
                    memcpy(key_data->key_data_contents[j], nextloc, 
 
438
                           key_data->key_data_length[j]);
 
439
                    nextloc += key_data->key_data_length[j];
 
440
                }
 
441
            }
 
442
        } else {
 
443
            /* This isn't right. I'll fix it later */
 
444
            abort();
 
445
        }
 
446
    }
 
447
    return 0;
 
448
 
 
449
error_out:;
 
450
    krb5_dbe_free_contents(context, entry);
 
451
    return retval;
 
452
}
 
453
            
 
454
void
 
455
krb5_dbe_free_contents(context, entry)
 
456
     krb5_context         context; 
 
457
     krb5_db_entry      * entry;
 
458
{
 
459
    krb5_tl_data        * tl_data_next;
 
460
    krb5_tl_data        * tl_data;
 
461
    int i, j;
 
462
 
 
463
    if (entry->e_data)
 
464
        free(entry->e_data);
 
465
    if (entry->princ)
 
466
        krb5_free_principal(context, entry->princ);
 
467
    for (tl_data = entry->tl_data; tl_data; tl_data = tl_data_next) {
 
468
        tl_data_next = tl_data->tl_data_next;
 
469
        if (tl_data->tl_data_contents)
 
470
            free(tl_data->tl_data_contents);
 
471
        free(tl_data);
 
472
    }
 
473
    if (entry->key_data) {
 
474
        for (i = 0; i < entry->n_key_data; i++) {
 
475
            for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
 
476
                if (entry->key_data[i].key_data_length[j]) {
 
477
                    if (entry->key_data[i].key_data_contents[j]) {
 
478
                        memset(entry->key_data[i].key_data_contents[j], 
 
479
                               0, 
 
480
                               (unsigned) entry->key_data[i].key_data_length[j]);
 
481
                        free (entry->key_data[i].key_data_contents[j]);
 
482
                    }
 
483
                }
 
484
                entry->key_data[i].key_data_contents[j] = NULL;
 
485
                entry->key_data[i].key_data_length[j] = 0;
 
486
                entry->key_data[i].key_data_type[j] = 0;
 
487
            }
 
488
        }
 
489
        free(entry->key_data);
 
490
    }
 
491
    memset(entry, 0, sizeof(*entry));
 
492
    return;
 
493
}