~ubuntu-branches/ubuntu/maverick/krb5/maverick

« back to all changes in this revision

Viewing changes to src/lib/kdb/kdb_default.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hartman
  • Date: 2009-05-07 16:16:34 UTC
  • mfrom: (13.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20090507161634-xqyk0s9na0le4flj
Tags: 1.7dfsg~beta1-4
When  decrypting the TGS response fails with the subkey, try with the
session key to work around Heimdal bug, Closes: #527353 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * lib/kdb/kdb_helper.c
3
3
 *
4
 
 * Copyright 1995 by the Massachusetts Institute of Technology. 
 
4
 * Copyright 1995, 2009 by the Massachusetts Institute of Technology. 
5
5
 * All Rights Reserved.
6
6
 *
7
7
 * Export of this software from the United States of America may
25
25
 * 
26
26
 */
27
27
 
 
28
/*
 
29
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 
30
 * Use is subject to license terms.
 
31
 */
 
32
 
28
33
#include "k5-int.h"
29
34
#include "kdb.h"
30
35
#include <string.h>
31
36
#include <stdio.h>
32
37
#include <errno.h>
 
38
#include <arpa/inet.h>
33
39
 
34
40
 
35
41
/*
132
138
#endif
133
139
 
134
140
krb5_error_code
135
 
krb5_def_store_mkey(context, keyfile, mname, key, master_pwd)
136
 
    krb5_context context;
137
 
    char *keyfile;
138
 
    krb5_principal mname;
139
 
    krb5_keyblock *key;
140
 
    char *master_pwd;
 
141
krb5_def_store_mkey_list(krb5_context       context,
 
142
                         char               *keyfile,
 
143
                         krb5_principal     mname,
 
144
                         krb5_keylist_node  *keylist,
 
145
                         char               *master_pwd)
141
146
{
142
 
    FILE *kf;
143
147
    krb5_error_code retval = 0;
144
 
    krb5_ui_2 enctype;
145
148
    char defkeyfile[MAXPATHLEN+1];
 
149
    char *tmp_ktname = NULL, *tmp_ktpath;
146
150
    krb5_data *realm = krb5_princ_realm(context, mname);
147
 
#if HAVE_UMASK
148
 
    mode_t oumask;
149
 
#endif
 
151
    krb5_keytab kt = NULL;
 
152
    krb5_keytab_entry new_entry;
 
153
    struct stat stb;
 
154
    int statrc;
150
155
 
151
156
    if (!keyfile) {
152
 
        (void) strcpy(defkeyfile, DEFAULT_KEYFILE_STUB);
153
 
        (void) strncat(defkeyfile, realm->data,
154
 
                       min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1,
155
 
                           realm->length));
156
 
        defkeyfile[sizeof(defkeyfile) - 1] = '\0';
157
 
        keyfile = defkeyfile;
158
 
    }
159
 
 
160
 
#if HAVE_UMASK
161
 
    oumask = umask(077);
162
 
#endif
163
 
#ifdef ANSI_STDIO
164
 
    if (!(kf = fopen(keyfile, "wb")))
165
 
#else
166
 
    if (!(kf = fopen(keyfile, "w")))
167
 
#endif
168
 
    {
169
 
        int e = errno;
170
 
#if HAVE_UMASK
171
 
        (void) umask(oumask);
172
 
#endif
173
 
        krb5_set_error_message (context, e,
174
 
                                "%s accessing file '%s'",
175
 
                                error_message (e), keyfile);
176
 
        return e;
177
 
    }
178
 
    enctype = key->enctype;
179
 
    if ((fwrite((krb5_pointer) &enctype,
180
 
                2, 1, kf) != 1) ||
181
 
        (fwrite((krb5_pointer) &key->length,
182
 
                sizeof(key->length), 1, kf) != 1) ||
183
 
        (fwrite((krb5_pointer) key->contents,
184
 
                sizeof(key->contents[0]), (unsigned) key->length, 
185
 
                kf) != key->length)) {
186
 
        retval = errno;
187
 
        (void) fclose(kf);
188
 
    } else if (fclose(kf) == EOF)
189
 
        retval = errno;
190
 
#if HAVE_UMASK
191
 
    (void) umask(oumask);
192
 
#endif
 
157
        (void) snprintf(defkeyfile, sizeof(defkeyfile), "%s%s",
 
158
                        DEFAULT_KEYFILE_STUB, realm->data);
 
159
        keyfile = defkeyfile;
 
160
    }
 
161
 
 
162
    /*
 
163
     * XXX making the assumption that the keyfile is in a dir that requires root
 
164
     * privilege to write to thus making timing attacks unlikely.
 
165
     */
 
166
    if ((statrc = stat(keyfile, &stb)) >= 0) {
 
167
        /* if keyfile exists it better be a regular file */
 
168
        if (!S_ISREG(stb.st_mode)) {
 
169
            retval = EINVAL;
 
170
            krb5_set_error_message (context, retval,
 
171
                "keyfile (%s) is not a regular file: %s",
 
172
                keyfile, error_message(retval));
 
173
            goto out;
 
174
        }
 
175
    }
 
176
 
 
177
    /* Use temp keytab file name in case creation of keytab fails */
 
178
 
 
179
    /* create temp file template for use by mktemp() */
 
180
    if ((retval = asprintf(&tmp_ktname, "WRFILE:%s_XXXXXX", keyfile)) < 0) {
 
181
        krb5_set_error_message (context, retval,
 
182
            "Could not create temp keytab file name.");
 
183
        goto out;
 
184
    }
 
185
 
 
186
    /*
 
187
     * Set tmp_ktpath to point to the keyfile path (skip WRFILE:).  Subtracting
 
188
     * 1 to account for NULL terminator in sizeof calculation of a string
 
189
     * constant.  Used further down.
 
190
     */
 
191
    tmp_ktpath = tmp_ktname + (sizeof("WRFILE:") - 1);
 
192
 
 
193
    if (mktemp(tmp_ktpath) == NULL) {
 
194
        retval = errno;
 
195
        krb5_set_error_message (context, retval,
 
196
            "Could not create temp stash file: %s",
 
197
            error_message(errno));
 
198
        goto out;
 
199
    }
 
200
 
 
201
    /* create new stash keytab using temp file name */
 
202
    retval = krb5_kt_resolve(context, tmp_ktname, &kt);
 
203
    if (retval != 0)
 
204
        goto out;
 
205
 
 
206
    while (keylist && !retval) {
 
207
        memset((char *) &new_entry, 0, sizeof(new_entry));
 
208
        new_entry.principal = mname;
 
209
        new_entry.key = keylist->keyblock;
 
210
        new_entry.vno = keylist->kvno;
 
211
 
 
212
        retval = krb5_kt_add_entry(context, kt, &new_entry);
 
213
        keylist = keylist->next;
 
214
    }
 
215
    krb5_kt_close(context, kt);
 
216
 
 
217
    if (retval != 0) {
 
218
        /* delete tmp keyfile if it exists and an error occurrs */
 
219
        if (stat(keyfile, &stb) >= 0)
 
220
            (void) unlink(tmp_ktpath);
 
221
    } else {
 
222
        /* rename original keyfile to original filename */
 
223
        if (rename(tmp_ktpath, keyfile) < 0) {
 
224
            retval = errno;
 
225
            krb5_set_error_message (context, retval,
 
226
                "rename of temporary keyfile (%s) to (%s) failed: %s",
 
227
                tmp_ktpath, keyfile, error_message(errno));
 
228
        }
 
229
    }
 
230
 
 
231
out:
 
232
    if (tmp_ktname != NULL)
 
233
        free(tmp_ktname);
 
234
 
193
235
    return retval;
194
236
}
195
237
 
196
 
 
197
238
krb5_error_code
198
 
krb5_db_def_fetch_mkey( krb5_context   context,
199
 
                        krb5_principal mname,
200
 
                        krb5_keyblock *key,
201
 
                        int           *kvno,
202
 
                        char          *db_args)
203
 
{
204
 
    krb5_error_code retval;
 
239
krb5_def_store_mkey(krb5_context   context,
 
240
                    char           *keyfile,
 
241
                    krb5_principal mname,
 
242
                    krb5_kvno      kvno,
 
243
                    krb5_keyblock  *key,
 
244
                    char           *master_pwd)
 
245
{
 
246
    krb5_keylist_node list;
 
247
 
 
248
    list.kvno = kvno;
 
249
    list.keyblock = *key;
 
250
    list.next = NULL;
 
251
    return krb5_def_store_mkey_list(context, keyfile, mname, &list,
 
252
                                    master_pwd);
 
253
}
 
254
 
 
255
static krb5_error_code
 
256
krb5_db_def_fetch_mkey_stash(krb5_context   context,
 
257
                             const char *keyfile,
 
258
                             krb5_keyblock *key,
 
259
                             krb5_kvno     *kvno)
 
260
{
 
261
    krb5_error_code retval = 0;
205
262
    krb5_ui_2 enctype;
206
 
    char defkeyfile[MAXPATHLEN+1];
207
 
    krb5_data *realm = krb5_princ_realm(context, mname);
 
263
    krb5_ui_4 keylength;
208
264
    FILE *kf = NULL;
209
265
 
210
 
    retval = 0;
211
 
    key->magic = KV5M_KEYBLOCK;
212
 
    (void) strcpy(defkeyfile, DEFAULT_KEYFILE_STUB);
213
 
    (void) strncat(defkeyfile, realm->data,
214
 
                   min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1,
215
 
                       realm->length));
216
 
    defkeyfile[sizeof(defkeyfile) - 1] = '\0';
217
 
        
218
266
#ifdef ANSI_STDIO
219
 
    if (!(kf = fopen((db_args) ? db_args : defkeyfile, "rb")))
 
267
    if (!(kf = fopen(keyfile, "rb")))
220
268
#else
221
 
    if (!(kf = fopen((db_args) ? db_args : defkeyfile, "r")))
 
269
    if (!(kf = fopen(keyfile, "r")))
222
270
#endif
223
271
        return KRB5_KDB_CANTREAD_STORED;
 
272
    set_cloexec_file(kf);
224
273
 
225
274
    if (fread((krb5_pointer) &enctype, 2, 1, kf) != 1) {
226
275
        retval = KRB5_KDB_CANTREAD_STORED;
227
276
        goto errout;
228
277
    }
229
278
 
 
279
#if BIG_ENDIAN_MASTER_KEY
 
280
    enctype = ntohs((uint16_t) enctype);
 
281
#endif
 
282
 
230
283
    if (key->enctype == ENCTYPE_UNKNOWN)
231
284
        key->enctype = enctype;
232
285
    else if (enctype != key->enctype) {
234
287
        goto errout;
235
288
    }
236
289
 
237
 
    if (fread((krb5_pointer) &key->length,
238
 
              sizeof(key->length), 1, kf) != 1) {
 
290
    if (fread((krb5_pointer) &keylength,
 
291
              sizeof(keylength), 1, kf) != 1) {
239
292
        retval = KRB5_KDB_CANTREAD_STORED;
240
293
        goto errout;
241
294
    }
242
295
 
 
296
#if BIG_ENDIAN_MASTER_KEY
 
297
    key->length = ntohl((uint32_t) keylength);
 
298
#else
 
299
    key->length = keylength;
 
300
#endif
 
301
 
243
302
    if (!key->length || ((int) key->length) < 0) {
244
303
        retval = KRB5_KDB_BADSTORED_MKEY;
245
304
        goto errout;
250
309
        goto errout;
251
310
    }
252
311
 
253
 
    if (fread((krb5_pointer) key->contents,
254
 
              sizeof(key->contents[0]), key->length, kf) 
255
 
        != key->length) {
 
312
    if (fread((krb5_pointer) key->contents, sizeof(key->contents[0]),
 
313
                                            key->length, kf) != key->length) {
256
314
        retval = KRB5_KDB_CANTREAD_STORED;
257
 
        memset(key->contents, 0,  key->length);
 
315
        zap(key->contents, key->length);
258
316
        free(key->contents);
259
317
        key->contents = 0;
260
318
    } else
261
319
        retval = 0;
262
320
 
263
 
    *kvno = 0;
 
321
    /*
 
322
     * Note, the old stash format did not store the kvno and at this point it
 
323
     * can be assumed to be 1 as is the case for the mkey princ.  If the kvno is
 
324
     * passed in and isn't ignore_vno just leave it alone as this could cause
 
325
     * verifcation trouble if the mkey princ is using a kvno other than 1.
 
326
     */
 
327
    if (kvno && *kvno == IGNORE_VNO)
 
328
        *kvno = 1;
264
329
 
265
330
 errout:
266
331
    (void) fclose(kf);
267
332
    return retval;
268
 
 
269
 
}
270
 
 
271
 
 
272
 
krb5_error_code
273
 
krb5_def_verify_master_key(context, mprinc, mkey)
274
 
    krb5_context context;
275
 
    krb5_principal mprinc;
276
 
    krb5_keyblock *mkey;
 
333
}
 
334
 
 
335
static krb5_error_code
 
336
krb5_db_def_fetch_mkey_keytab(krb5_context   context,
 
337
                              const char     *keyfile,
 
338
                              krb5_principal mname,
 
339
                              krb5_keyblock  *key,
 
340
                              krb5_kvno      *kvno)
 
341
{
 
342
    krb5_error_code retval = 0;
 
343
    krb5_keytab kt = NULL;
 
344
    krb5_keytab_entry kt_ent;
 
345
    krb5_enctype enctype = IGNORE_ENCTYPE;
 
346
 
 
347
    if ((retval = krb5_kt_resolve(context, keyfile, &kt)) != 0)
 
348
        goto errout;
 
349
 
 
350
    /* override default */
 
351
    if (key->enctype != ENCTYPE_UNKNOWN)
 
352
        enctype = key->enctype;
 
353
 
 
354
    if ((retval = krb5_kt_get_entry(context, kt, mname,
 
355
                                    kvno ? *kvno : IGNORE_VNO,
 
356
                                    enctype,
 
357
                                    &kt_ent)) == 0) {
 
358
 
 
359
        if (key->enctype == ENCTYPE_UNKNOWN)
 
360
            key->enctype = kt_ent.key.enctype;
 
361
 
 
362
        if (((int) kt_ent.key.length) < 0) {
 
363
            retval = KRB5_KDB_BADSTORED_MKEY;
 
364
            krb5_kt_free_entry(context, &kt_ent);
 
365
            goto errout;
 
366
        }
 
367
 
 
368
        key->length = kt_ent.key.length;
 
369
 
 
370
        /*
 
371
         * If a kvno pointer was passed in and it dereferences the
 
372
         * IGNORE_VNO value then it should be assigned the value of the kvno
 
373
         * found in the keytab otherwise the KNVO specified should be the
 
374
         * same as the one returned from the keytab.
 
375
         */
 
376
        if (kvno != NULL && *kvno == IGNORE_VNO)
 
377
            *kvno = kt_ent.vno;
 
378
 
 
379
        /*
 
380
         * kt_ent will be free'd so need to allocate and copy key contents for
 
381
         * output to caller.
 
382
         */
 
383
        if (!(key->contents = (krb5_octet *)malloc(key->length))) {
 
384
            retval = ENOMEM;
 
385
            krb5_kt_free_entry(context, &kt_ent);
 
386
            goto errout;
 
387
        }
 
388
        memcpy(key->contents, kt_ent.key.contents, kt_ent.key.length);
 
389
        krb5_kt_free_entry(context, &kt_ent);
 
390
    }
 
391
 
 
392
errout:
 
393
    if (kt)
 
394
        krb5_kt_close(context, kt);
 
395
 
 
396
    return retval;
 
397
}
 
398
 
 
399
krb5_error_code
 
400
krb5_db_def_fetch_mkey(krb5_context   context,
 
401
                       krb5_principal mname,
 
402
                       krb5_keyblock *key,
 
403
                       krb5_kvno     *kvno,
 
404
                       char          *db_args)
 
405
{
 
406
    krb5_error_code retval_ofs = 0, retval_kt = 0;
 
407
    char keyfile[MAXPATHLEN+1];
 
408
    krb5_data *realm = krb5_princ_realm(context, mname);
 
409
 
 
410
    key->magic = KV5M_KEYBLOCK;
 
411
 
 
412
    if (db_args != NULL) {
 
413
        (void) strncpy(keyfile, db_args, sizeof(keyfile));
 
414
    } else {
 
415
        (void) snprintf(keyfile, sizeof(keyfile), "%s%s",
 
416
                        DEFAULT_KEYFILE_STUB, realm->data);
 
417
    }
 
418
    /* null terminate no matter what */
 
419
    keyfile[sizeof(keyfile) - 1] = '\0';
 
420
 
 
421
    /* assume the master key is in a keytab */
 
422
    retval_kt = krb5_db_def_fetch_mkey_keytab(context, keyfile, mname, key, kvno);
 
423
    if (retval_kt != 0) {
 
424
        /*
 
425
         * If it's not in a keytab, fall back and try getting the mkey from the
 
426
         * older stash file format.
 
427
         */
 
428
        retval_ofs = krb5_db_def_fetch_mkey_stash(context, keyfile, key, kvno);
 
429
    }
 
430
 
 
431
    if (retval_kt != 0 && retval_ofs != 0) {
 
432
        /*
 
433
         * Error, not able to get mkey from either file format.  Note, in order
 
434
         * to try to return a more correct error, the logic below is assuming
 
435
         * that if either of the stash reading functions returned
 
436
         * KRB5_KDB_BADSTORED_MKEY then this is probably the real error.
 
437
         */
 
438
        krb5_set_error_message (context, KRB5_KDB_CANTREAD_STORED,
 
439
            "Can not fetch master key either from keytab (error: %s) or old "
 
440
            "format (error %s).", error_message(retval_kt),
 
441
            error_message(retval_ofs));
 
442
        return KRB5_KDB_CANTREAD_STORED;
 
443
    } else {
 
444
        return 0;
 
445
    }
 
446
}
 
447
 
 
448
/*
 
449
 * Note, this verifies that the input mkey is currently protecting all the mkeys
 
450
 */
 
451
krb5_error_code
 
452
krb5_def_verify_master_key(krb5_context    context,
 
453
                           krb5_principal  mprinc,
 
454
                           krb5_kvno       kvno,
 
455
                           krb5_keyblock   *mkey)
277
456
{
278
457
    krb5_error_code retval;
279
458
    krb5_db_entry master_entry;
308
487
        retval = KRB5_KDB_BADMASTERKEY;
309
488
    }
310
489
 
311
 
    memset((char *)tempkey.contents, 0, tempkey.length);
312
 
    krb5_xfree(tempkey.contents);
 
490
    if (kvno != IGNORE_VNO &&
 
491
        kvno != (krb5_kvno) master_entry.key_data->key_data_kvno) {
 
492
        retval = KRB5_KDB_BADMASTERKEY;
 
493
        krb5_set_error_message (context, retval,
 
494
            "User specified mkeyVNO (%u) does not match master key princ's KVNO (%u)",
 
495
            kvno, master_entry.key_data->key_data_kvno);
 
496
    }
 
497
 
 
498
    zap((char *)tempkey.contents, tempkey.length);
 
499
    free(tempkey.contents);
313
500
    krb5_db_free_principal(context, &master_entry, nprinc);
314
501
    
315
502
    return retval;
316
503
}
317
504
 
 
505
krb5_error_code
 
506
krb5_def_fetch_mkey_list(krb5_context        context,
 
507
                       krb5_principal        mprinc,
 
508
                       const krb5_keyblock  *mkey,
 
509
                       krb5_kvno             mkvno,
 
510
                       krb5_keylist_node  **mkeys_list)
 
511
{
 
512
    krb5_error_code retval;
 
513
    krb5_db_entry master_entry;
 
514
    int nprinc;
 
515
    krb5_boolean more, found_key = FALSE;
 
516
    krb5_keyblock cur_mkey;
 
517
    krb5_keylist_node *mkey_list_head = NULL, **mkey_list_node;
 
518
    krb5_key_data *key_data;
 
519
    krb5_mkey_aux_node  *mkey_aux_data_list = NULL, *aux_data_entry;
 
520
    int i;
 
521
 
 
522
    if (mkeys_list == NULL)
 
523
        return (EINVAL);
 
524
 
 
525
    memset(&cur_mkey, 0, sizeof(cur_mkey));
 
526
    memset(&master_entry, 0, sizeof(master_entry));
 
527
 
 
528
    nprinc = 1;
 
529
    if ((retval = krb5_db_get_principal(context, mprinc,
 
530
                                        &master_entry, &nprinc, &more)))
 
531
        return (retval);
 
532
 
 
533
    if (nprinc != 1) {
 
534
        if (nprinc)
 
535
            krb5_db_free_principal(context, &master_entry, nprinc);
 
536
        return(KRB5_KDB_NOMASTERKEY);
 
537
    } else if (more) {
 
538
        krb5_db_free_principal(context, &master_entry, nprinc);
 
539
        return (KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
 
540
    }
 
541
 
 
542
    /*
 
543
     * Check if the input mkey is the latest key and if it isn't then find the
 
544
     * latest mkey.
 
545
     */
 
546
 
 
547
    if (mkey->enctype == master_entry.key_data[0].key_data_type[0]) {
 
548
        if (krb5_dbekd_decrypt_key_data(context, mkey,
 
549
                                        &master_entry.key_data[0],
 
550
                                        &cur_mkey, NULL) == 0) {
 
551
            found_key = TRUE;
 
552
        }
 
553
    }
 
554
 
 
555
    if (!found_key) {
 
556
        /*
 
557
         * Note the mkvno may provide a hint as to which mkey_aux tuple to
 
558
         * decrypt.
 
559
         */
 
560
        if ((retval = krb5_dbe_lookup_mkey_aux(context, &master_entry,
 
561
                                               &mkey_aux_data_list)))
 
562
            goto clean_n_exit;
 
563
 
 
564
        /* mkvno may be 0 in some cases like keyboard and should be ignored */
 
565
        if (mkvno != 0) {
 
566
            /* for performance sake, try decrypting with matching kvno */
 
567
            for (aux_data_entry = mkey_aux_data_list; aux_data_entry != NULL;
 
568
                 aux_data_entry = aux_data_entry->next) {
 
569
 
 
570
                if (aux_data_entry->mkey_kvno == mkvno) {
 
571
                    if (krb5_dbekd_decrypt_key_data(context, mkey,
 
572
                                                    &aux_data_entry->latest_mkey,
 
573
                                                    &cur_mkey, NULL) == 0) {
 
574
                        found_key = TRUE;
 
575
                        break;
 
576
                    }
 
577
                }
 
578
            }
 
579
        }
 
580
        if (!found_key) {
 
581
            /* given the importance of acquiring the latest mkey, try brute force */
 
582
            for (aux_data_entry = mkey_aux_data_list; aux_data_entry != NULL;
 
583
                 aux_data_entry = aux_data_entry->next) {
 
584
 
 
585
                if (mkey->enctype == aux_data_entry->latest_mkey.key_data_type[0] &&
 
586
                    (krb5_dbekd_decrypt_key_data(context, mkey,
 
587
                                                 &aux_data_entry->latest_mkey,
 
588
                                                 &cur_mkey, NULL) == 0)) {
 
589
                    found_key = TRUE;
 
590
                    break;
 
591
                }
 
592
            }
 
593
            if (found_key != TRUE) {
 
594
                krb5_set_error_message (context, KRB5_KDB_BADMASTERKEY,
 
595
                    "Unable to decrypt latest master key with the provided master key\n");
 
596
                retval = KRB5_KDB_BADMASTERKEY;
 
597
                goto clean_n_exit;
 
598
            }
 
599
        }
 
600
    }
 
601
 
 
602
    /*
 
603
     * Extract all the mkeys from master_entry using the most current mkey and
 
604
     * create a mkey list for the mkeys field in kdc_realm_t. 
 
605
     */
 
606
 
 
607
    mkey_list_head = (krb5_keylist_node *) malloc(sizeof(krb5_keylist_node));
 
608
    if (mkey_list_head == NULL) {
 
609
        retval = ENOMEM;
 
610
        goto clean_n_exit;
 
611
    }
 
612
 
 
613
    memset(mkey_list_head, 0, sizeof(krb5_keylist_node));
 
614
 
 
615
    /* Set mkey_list_head to the current mkey as an optimization. */
 
616
    /* mkvno may not be latest so ... */
 
617
    mkey_list_head->kvno = master_entry.key_data[0].key_data_kvno;
 
618
    /* this is the latest clear mkey (avoids a redundant decrypt) */
 
619
    mkey_list_head->keyblock = cur_mkey;
 
620
 
 
621
    /* loop through any other master keys creating a list of krb5_keylist_nodes */
 
622
    mkey_list_node = &mkey_list_head->next;
 
623
    for (i = 1; i < master_entry.n_key_data; i++) {
 
624
        if (*mkey_list_node == NULL) {
 
625
            /* *mkey_list_node points to next field of previous node */
 
626
            *mkey_list_node = (krb5_keylist_node *) malloc(sizeof(krb5_keylist_node));
 
627
            if (*mkey_list_node == NULL) {
 
628
                retval = ENOMEM;
 
629
                goto clean_n_exit;
 
630
            }
 
631
            memset(*mkey_list_node, 0, sizeof(krb5_keylist_node));
 
632
        }
 
633
        key_data = &master_entry.key_data[i];
 
634
        retval = krb5_dbekd_decrypt_key_data(context, &cur_mkey,
 
635
                                             key_data,
 
636
                                             &((*mkey_list_node)->keyblock),
 
637
                                             NULL);
 
638
        if (retval)
 
639
            goto clean_n_exit;
 
640
 
 
641
        (*mkey_list_node)->kvno = key_data->key_data_kvno;
 
642
        mkey_list_node = &((*mkey_list_node)->next);
 
643
    }
 
644
 
 
645
    *mkeys_list = mkey_list_head;
 
646
 
 
647
clean_n_exit:
 
648
    krb5_db_free_principal(context, &master_entry, nprinc);
 
649
    krb5_dbe_free_mkey_aux_list(context, mkey_aux_data_list);
 
650
    if (retval != 0)
 
651
        krb5_dbe_free_key_list(context, mkey_list_head);
 
652
    return retval;
 
653
}
318
654
 
319
655
krb5_error_code kdb_def_set_mkey ( krb5_context kcontext,
320
656
                                   char *pwd,
331
667
    return 0;
332
668
}
333
669
 
 
670
krb5_error_code kdb_def_set_mkey_list ( krb5_context kcontext,
 
671
                                        krb5_keylist_node *keylist )
 
672
{
 
673
    /* printf("default set master key\n"); */
 
674
    return 0;
 
675
}
 
676
 
 
677
krb5_error_code kdb_def_get_mkey_list ( krb5_context kcontext,
 
678
                                        krb5_keylist_node **keylist )
 
679
{
 
680
    /* printf("default get master key\n"); */
 
681
    return 0;
 
682
}
 
683
 
334
684
krb5_error_code krb5_def_promote_db (krb5_context kcontext,
335
685
                                     char *s, char **args)
336
686
{