135
krb5_def_store_mkey(context, keyfile, mname, key, master_pwd)
136
krb5_context context;
138
krb5_principal mname;
141
krb5_def_store_mkey_list(krb5_context context,
143
krb5_principal mname,
144
krb5_keylist_node *keylist,
143
147
krb5_error_code retval = 0;
145
148
char defkeyfile[MAXPATHLEN+1];
149
char *tmp_ktname = NULL, *tmp_ktpath;
146
150
krb5_data *realm = krb5_princ_realm(context, mname);
151
krb5_keytab kt = NULL;
152
krb5_keytab_entry new_entry;
152
(void) strcpy(defkeyfile, DEFAULT_KEYFILE_STUB);
153
(void) strncat(defkeyfile, realm->data,
154
min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1,
156
defkeyfile[sizeof(defkeyfile) - 1] = '\0';
157
keyfile = defkeyfile;
164
if (!(kf = fopen(keyfile, "wb")))
166
if (!(kf = fopen(keyfile, "w")))
171
(void) umask(oumask);
173
krb5_set_error_message (context, e,
174
"%s accessing file '%s'",
175
error_message (e), keyfile);
178
enctype = key->enctype;
179
if ((fwrite((krb5_pointer) &enctype,
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)) {
188
} else if (fclose(kf) == EOF)
191
(void) umask(oumask);
157
(void) snprintf(defkeyfile, sizeof(defkeyfile), "%s%s",
158
DEFAULT_KEYFILE_STUB, realm->data);
159
keyfile = defkeyfile;
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.
166
if ((statrc = stat(keyfile, &stb)) >= 0) {
167
/* if keyfile exists it better be a regular file */
168
if (!S_ISREG(stb.st_mode)) {
170
krb5_set_error_message (context, retval,
171
"keyfile (%s) is not a regular file: %s",
172
keyfile, error_message(retval));
177
/* Use temp keytab file name in case creation of keytab fails */
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.");
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.
191
tmp_ktpath = tmp_ktname + (sizeof("WRFILE:") - 1);
193
if (mktemp(tmp_ktpath) == NULL) {
195
krb5_set_error_message (context, retval,
196
"Could not create temp stash file: %s",
197
error_message(errno));
201
/* create new stash keytab using temp file name */
202
retval = krb5_kt_resolve(context, tmp_ktname, &kt);
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;
212
retval = krb5_kt_add_entry(context, kt, &new_entry);
213
keylist = keylist->next;
215
krb5_kt_close(context, kt);
218
/* delete tmp keyfile if it exists and an error occurrs */
219
if (stat(keyfile, &stb) >= 0)
220
(void) unlink(tmp_ktpath);
222
/* rename original keyfile to original filename */
223
if (rename(tmp_ktpath, keyfile) < 0) {
225
krb5_set_error_message (context, retval,
226
"rename of temporary keyfile (%s) to (%s) failed: %s",
227
tmp_ktpath, keyfile, error_message(errno));
232
if (tmp_ktname != NULL)
198
krb5_db_def_fetch_mkey( krb5_context context,
199
krb5_principal mname,
204
krb5_error_code retval;
239
krb5_def_store_mkey(krb5_context context,
241
krb5_principal mname,
246
krb5_keylist_node list;
249
list.keyblock = *key;
251
return krb5_def_store_mkey_list(context, keyfile, mname, &list,
255
static krb5_error_code
256
krb5_db_def_fetch_mkey_stash(krb5_context context,
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);
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,
216
defkeyfile[sizeof(defkeyfile) - 1] = '\0';
218
266
#ifdef ANSI_STDIO
219
if (!(kf = fopen((db_args) ? db_args : defkeyfile, "rb")))
267
if (!(kf = fopen(keyfile, "rb")))
221
if (!(kf = fopen((db_args) ? db_args : defkeyfile, "r")))
269
if (!(kf = fopen(keyfile, "r")))
223
271
return KRB5_KDB_CANTREAD_STORED;
272
set_cloexec_file(kf);
225
274
if (fread((krb5_pointer) &enctype, 2, 1, kf) != 1) {
226
275
retval = KRB5_KDB_CANTREAD_STORED;
279
#if BIG_ENDIAN_MASTER_KEY
280
enctype = ntohs((uint16_t) enctype);
230
283
if (key->enctype == ENCTYPE_UNKNOWN)
231
284
key->enctype = enctype;
232
285
else if (enctype != key->enctype) {
253
if (fread((krb5_pointer) key->contents,
254
sizeof(key->contents[0]), key->length, kf)
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;
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.
327
if (kvno && *kvno == IGNORE_VNO)
266
331
(void) fclose(kf);
273
krb5_def_verify_master_key(context, mprinc, mkey)
274
krb5_context context;
275
krb5_principal mprinc;
335
static krb5_error_code
336
krb5_db_def_fetch_mkey_keytab(krb5_context context,
338
krb5_principal mname,
342
krb5_error_code retval = 0;
343
krb5_keytab kt = NULL;
344
krb5_keytab_entry kt_ent;
345
krb5_enctype enctype = IGNORE_ENCTYPE;
347
if ((retval = krb5_kt_resolve(context, keyfile, &kt)) != 0)
350
/* override default */
351
if (key->enctype != ENCTYPE_UNKNOWN)
352
enctype = key->enctype;
354
if ((retval = krb5_kt_get_entry(context, kt, mname,
355
kvno ? *kvno : IGNORE_VNO,
359
if (key->enctype == ENCTYPE_UNKNOWN)
360
key->enctype = kt_ent.key.enctype;
362
if (((int) kt_ent.key.length) < 0) {
363
retval = KRB5_KDB_BADSTORED_MKEY;
364
krb5_kt_free_entry(context, &kt_ent);
368
key->length = kt_ent.key.length;
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.
376
if (kvno != NULL && *kvno == IGNORE_VNO)
380
* kt_ent will be free'd so need to allocate and copy key contents for
383
if (!(key->contents = (krb5_octet *)malloc(key->length))) {
385
krb5_kt_free_entry(context, &kt_ent);
388
memcpy(key->contents, kt_ent.key.contents, kt_ent.key.length);
389
krb5_kt_free_entry(context, &kt_ent);
394
krb5_kt_close(context, kt);
400
krb5_db_def_fetch_mkey(krb5_context context,
401
krb5_principal mname,
406
krb5_error_code retval_ofs = 0, retval_kt = 0;
407
char keyfile[MAXPATHLEN+1];
408
krb5_data *realm = krb5_princ_realm(context, mname);
410
key->magic = KV5M_KEYBLOCK;
412
if (db_args != NULL) {
413
(void) strncpy(keyfile, db_args, sizeof(keyfile));
415
(void) snprintf(keyfile, sizeof(keyfile), "%s%s",
416
DEFAULT_KEYFILE_STUB, realm->data);
418
/* null terminate no matter what */
419
keyfile[sizeof(keyfile) - 1] = '\0';
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) {
425
* If it's not in a keytab, fall back and try getting the mkey from the
426
* older stash file format.
428
retval_ofs = krb5_db_def_fetch_mkey_stash(context, keyfile, key, kvno);
431
if (retval_kt != 0 && retval_ofs != 0) {
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.
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;
449
* Note, this verifies that the input mkey is currently protecting all the mkeys
452
krb5_def_verify_master_key(krb5_context context,
453
krb5_principal mprinc,
278
457
krb5_error_code retval;
279
458
krb5_db_entry master_entry;
308
487
retval = KRB5_KDB_BADMASTERKEY;
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);
498
zap((char *)tempkey.contents, tempkey.length);
499
free(tempkey.contents);
313
500
krb5_db_free_principal(context, &master_entry, nprinc);
506
krb5_def_fetch_mkey_list(krb5_context context,
507
krb5_principal mprinc,
508
const krb5_keyblock *mkey,
510
krb5_keylist_node **mkeys_list)
512
krb5_error_code retval;
513
krb5_db_entry master_entry;
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;
522
if (mkeys_list == NULL)
525
memset(&cur_mkey, 0, sizeof(cur_mkey));
526
memset(&master_entry, 0, sizeof(master_entry));
529
if ((retval = krb5_db_get_principal(context, mprinc,
530
&master_entry, &nprinc, &more)))
535
krb5_db_free_principal(context, &master_entry, nprinc);
536
return(KRB5_KDB_NOMASTERKEY);
538
krb5_db_free_principal(context, &master_entry, nprinc);
539
return (KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
543
* Check if the input mkey is the latest key and if it isn't then find the
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) {
557
* Note the mkvno may provide a hint as to which mkey_aux tuple to
560
if ((retval = krb5_dbe_lookup_mkey_aux(context, &master_entry,
561
&mkey_aux_data_list)))
564
/* mkvno may be 0 in some cases like keyboard and should be ignored */
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) {
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) {
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) {
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)) {
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;
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.
607
mkey_list_head = (krb5_keylist_node *) malloc(sizeof(krb5_keylist_node));
608
if (mkey_list_head == NULL) {
613
memset(mkey_list_head, 0, sizeof(krb5_keylist_node));
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;
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) {
631
memset(*mkey_list_node, 0, sizeof(krb5_keylist_node));
633
key_data = &master_entry.key_data[i];
634
retval = krb5_dbekd_decrypt_key_data(context, &cur_mkey,
636
&((*mkey_list_node)->keyblock),
641
(*mkey_list_node)->kvno = key_data->key_data_kvno;
642
mkey_list_node = &((*mkey_list_node)->next);
645
*mkeys_list = mkey_list_head;
648
krb5_db_free_principal(context, &master_entry, nprinc);
649
krb5_dbe_free_mkey_aux_list(context, mkey_aux_data_list);
651
krb5_dbe_free_key_list(context, mkey_list_head);
319
655
krb5_error_code kdb_def_set_mkey ( krb5_context kcontext,