Fix spelling
[heimdal.git] / lib / hdb / common.c
blobe2d12823dab8449ca39b4e078110d6e7cce6d9bd
1 /*
2 * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
34 #include "krb5_locl.h"
35 #include "hdb_locl.h"
37 int
38 hdb_principal2key(krb5_context context, krb5_const_principal p, krb5_data *key)
40 Principal new;
41 size_t len = 0;
42 int ret;
44 ret = copy_Principal(p, &new);
45 if(ret)
46 return ret;
47 new.name.name_type = 0;
49 ASN1_MALLOC_ENCODE(Principal, key->data, key->length, &new, &len, ret);
50 if (ret == 0 && key->length != len)
51 krb5_abortx(context, "internal asn.1 encoder error");
52 free_Principal(&new);
53 return ret;
56 int
57 hdb_key2principal(krb5_context context, krb5_data *key, krb5_principal p)
59 return decode_Principal(key->data, key->length, p, NULL);
62 int
63 hdb_entry2value(krb5_context context, const hdb_entry *ent, krb5_data *value)
65 size_t len = 0;
66 int ret;
68 ASN1_MALLOC_ENCODE(HDB_entry, value->data, value->length, ent, &len, ret);
69 if (ret == 0 && value->length != len)
70 krb5_abortx(context, "internal asn.1 encoder error");
71 return ret;
74 int
75 hdb_value2entry(krb5_context context, krb5_data *value, hdb_entry *ent)
77 return decode_HDB_entry(value->data, value->length, ent, NULL);
80 int
81 hdb_entry_alias2value(krb5_context context,
82 const hdb_entry_alias *alias,
83 krb5_data *value)
85 size_t len = 0;
86 int ret;
88 ASN1_MALLOC_ENCODE(HDB_entry_alias, value->data, value->length,
89 alias, &len, ret);
90 if (ret == 0 && value->length != len)
91 krb5_abortx(context, "internal asn.1 encoder error");
92 return ret;
95 int
96 hdb_value2entry_alias(krb5_context context, krb5_data *value,
97 hdb_entry_alias *ent)
99 return decode_HDB_entry_alias(value->data, value->length, ent, NULL);
103 * Some old databases may not have stored the salt with each key, which will
104 * break clients when aliases or canonicalization are used. Generate a
105 * default salt based on the real principal name in the entry to handle
106 * this case.
108 static krb5_error_code
109 add_default_salts(krb5_context context, HDB *db, hdb_entry *entry)
111 krb5_error_code ret;
112 size_t i;
113 krb5_salt pwsalt;
115 ret = krb5_get_pw_salt(context, entry->principal, &pwsalt);
116 if (ret)
117 return ret;
119 for (i = 0; i < entry->keys.len; i++) {
120 Key *key = &entry->keys.val[i];
122 if (key->salt != NULL ||
123 _krb5_enctype_requires_random_salt(context, key->key.keytype))
124 continue;
126 key->salt = calloc(1, sizeof(*key->salt));
127 if (key->salt == NULL) {
128 ret = krb5_enomem(context);
129 break;
132 key->salt->type = KRB5_PADATA_PW_SALT;
134 ret = krb5_data_copy(&key->salt->salt,
135 pwsalt.saltvalue.data,
136 pwsalt.saltvalue.length);
137 if (ret)
138 break;
141 krb5_free_salt(context, pwsalt);
143 return ret;
146 static krb5_error_code
147 fetch_entry_or_alias(krb5_context context,
148 HDB *db,
149 krb5_const_principal principal,
150 unsigned flags,
151 hdb_entry *entry)
153 HDB_EntryOrAlias eoa;
154 krb5_principal enterprise_principal = NULL;
155 krb5_data key, value;
156 krb5_error_code ret;
158 value.length = 0;
159 value.data = 0;
160 key = value;
162 if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
163 if (principal->name.name_string.len != 1) {
164 ret = KRB5_PARSE_MALFORMED;
165 krb5_set_error_message(context, ret, "malformed principal: "
166 "enterprise name with %d name components",
167 principal->name.name_string.len);
168 return ret;
170 ret = krb5_parse_name(context, principal->name.name_string.val[0],
171 &enterprise_principal);
172 if (ret)
173 return ret;
174 principal = enterprise_principal;
177 ret = hdb_principal2key(context, principal, &key);
178 if (ret == 0)
179 ret = db->hdb__get(context, db, key, &value);
180 if (ret == 0)
181 ret = decode_HDB_EntryOrAlias(value.data, value.length, &eoa, NULL);
182 if (ret == 0 && eoa.element == choice_HDB_EntryOrAlias_entry) {
183 *entry = eoa.u.entry;
184 entry->aliased = 0;
185 } else if (ret == 0 && eoa.element == choice_HDB_EntryOrAlias_alias) {
186 krb5_data_free(&key);
187 ret = hdb_principal2key(context, eoa.u.alias.principal, &key);
188 if (ret == 0) {
189 krb5_data_free(&value);
190 ret = db->hdb__get(context, db, key, &value);
192 if (ret == 0)
193 /* No alias chaining */
194 ret = hdb_value2entry(context, &value, entry);
195 krb5_free_principal(context, eoa.u.alias.principal);
196 entry->aliased = 1;
197 } else if (ret == 0)
198 ret = ENOTSUP;
199 if (ret == 0 && enterprise_principal) {
201 * Whilst Windows does not canonicalize enterprise principal names if
202 * the canonicalize flag is unset, the original specification in
203 * draft-ietf-krb-wg-kerberos-referrals-03.txt says we should.
205 entry->flags.force_canonicalize = 1;
208 #if 0
209 /* HDB_F_GET_ANY indicates request originated from KDC (not kadmin) */
210 if (ret == 0 && eoa.element == choice_HDB_EntryOrAlias_alias &&
211 (flags & (HDB_F_CANON|HDB_F_GET_ANY)) == 0) {
213 /* `principal' was alias but canon not req'd */
214 free_HDB_entry(entry);
215 ret = HDB_ERR_NOENTRY;
217 #endif
219 krb5_free_principal(context, enterprise_principal);
220 krb5_data_free(&value);
221 krb5_data_free(&key);
222 principal = enterprise_principal = NULL;
223 return ret;
227 * We have only one type of aliases in our HDB entries, but we really need two:
228 * hard and soft.
230 * Hard aliases should be treated as if they were distinct principals with the
231 * same keys.
233 * Soft aliases should be treated as configuration to issue referrals, and they
234 * can only result in referrals to other realms.
236 * Rather than add a type of aliases, we'll use a convention where the form of
237 * the target of the alias indicates whether the alias is hard or soft.
239 * TODO We could also use an attribute of the aliased entry.
241 static int
242 is_soft_alias_p(krb5_context context,
243 krb5_const_principal principal,
244 unsigned int flags,
245 hdb_entry *h)
247 /* Target is a WELLKNOWN/REFERRALS/TARGET/... -> soft alias */
248 if (krb5_principal_get_num_comp(context, h->principal) >= 3 &&
249 strcmp(krb5_principal_get_comp_string(context, h->principal, 0),
250 KRB5_WELLKNOWN_NAME) == 0 &&
251 strcmp(krb5_principal_get_comp_string(context, h->principal, 1),
252 "REFERRALS") == 0 &&
253 strcmp(krb5_principal_get_comp_string(context, h->principal, 2),
254 "TARGET") == 0)
255 return 1;
258 * Pre-8.0 we had only soft aliases for a while, and one site used aliases
259 * of referrals-targetNN@TARGET-REALM.
261 if (krb5_principal_get_num_comp(context, h->principal) == 1 &&
262 strncmp("referrals-target",
263 krb5_principal_get_comp_string(context, h->principal, 0),
264 sizeof("referrals-target") - 1) == 0)
265 return 1;
267 /* All other cases are hard aliases */
268 return 0;
271 krb5_error_code
272 _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
273 unsigned flags, krb5_kvno kvno, hdb_entry *entry)
275 krb5_error_code ret;
276 int soft_aliased = 0;
277 int same_realm;
279 ret = fetch_entry_or_alias(context, db, principal, flags, entry);
280 if (ret)
281 return ret;
283 if ((flags & HDB_F_DECRYPT) && (flags & HDB_F_ALL_KVNOS)) {
284 /* Decrypt the current keys */
285 ret = hdb_unseal_keys(context, db, entry);
286 if (ret) {
287 hdb_free_entry(context, db, entry);
288 return ret;
290 /* Decrypt the key history too */
291 ret = hdb_unseal_keys_kvno(context, db, 0, flags, entry);
292 if (ret) {
293 hdb_free_entry(context, db, entry);
294 return ret;
296 } else if ((flags & HDB_F_DECRYPT)) {
297 if ((flags & HDB_F_KVNO_SPECIFIED) == 0 || kvno == entry->kvno) {
298 /* Decrypt the current keys */
299 ret = hdb_unseal_keys(context, db, entry);
300 if (ret) {
301 hdb_free_entry(context, db, entry);
302 return ret;
304 } else {
305 if ((flags & HDB_F_ALL_KVNOS))
306 kvno = 0;
308 * Find and decrypt the keys from the history that we want,
309 * and swap them with the current keys
311 ret = hdb_unseal_keys_kvno(context, db, kvno, flags, entry);
312 if (ret) {
313 hdb_free_entry(context, db, entry);
314 return ret;
318 if ((flags & HDB_F_FOR_AS_REQ) && (flags & HDB_F_GET_CLIENT)) {
320 * Generate default salt for any principals missing one; note such
321 * principals could include those for which a random (non-password)
322 * key was generated, but given the salt will be ignored by a keytab
323 * client it doesn't hurt to include the default salt.
325 ret = add_default_salts(context, db, entry);
326 if (ret) {
327 hdb_free_entry(context, db, entry);
328 return ret;
332 if (!entry->aliased)
333 return 0;
335 soft_aliased = is_soft_alias_p(context, principal, flags, entry);
337 /* Never return HDB_ERR_WRONG_REALM to kadm5 or other non-KDC callers */
338 if ((flags & HDB_F_ADMIN_DATA))
339 return 0;
341 same_realm = krb5_realm_compare(context, principal, entry->principal);
343 if (entry->aliased && !soft_aliased) {
345 * This is a hard alias. We'll make the entry's name be the same as
346 * the alias.
348 * Except, we allow for disabling this for same-realm aliases, mainly
349 * for our tests.
351 if (same_realm &&
352 krb5_config_get_bool_default(context, NULL, FALSE, "hdb",
353 "same_realm_aliases_are_soft", NULL))
354 return 0;
356 /* EPNs are always soft */
357 if (principal->name.name_type != KRB5_NT_ENTERPRISE_PRINCIPAL) {
358 krb5_free_principal(context, entry->principal);
359 ret = krb5_copy_principal(context, principal, &entry->principal);
360 if (ret) {
361 hdb_free_entry(context, db, entry);
362 return ret;
365 return 0;
368 /* Same realm -> not a referral, therefore this is a hard alias */
369 if (same_realm) {
370 if (soft_aliased) {
371 /* Soft alias to the same realm?! No. */
372 hdb_free_entry(context, db, entry);
373 return HDB_ERR_NOENTRY;
375 return 0;
378 /* Not same realm && not hard alias */
379 return HDB_ERR_WRONG_REALM;
382 static krb5_error_code
383 hdb_remove_aliases(krb5_context context, HDB *db, krb5_data *key)
385 const HDB_Ext_Aliases *aliases;
386 krb5_error_code code;
387 hdb_entry oldentry;
388 krb5_data value;
389 size_t i;
391 code = db->hdb__get(context, db, *key, &value);
392 if (code == HDB_ERR_NOENTRY)
393 return 0;
394 else if (code)
395 return code;
397 code = hdb_value2entry(context, &value, &oldentry);
398 krb5_data_free(&value);
399 if (code)
400 return code;
402 code = hdb_entry_get_aliases(&oldentry, &aliases);
403 if (code || aliases == NULL) {
404 free_HDB_entry(&oldentry);
405 return code;
407 for (i = 0; i < aliases->aliases.len; i++) {
408 krb5_data akey;
410 code = hdb_principal2key(context, &aliases->aliases.val[i], &akey);
411 if (code == 0) {
412 code = db->hdb__del(context, db, akey);
413 krb5_data_free(&akey);
414 if (code == HDB_ERR_NOENTRY)
415 code = 0;
417 if (code) {
418 free_HDB_entry(&oldentry);
419 return code;
422 free_HDB_entry(&oldentry);
423 return 0;
426 static krb5_error_code
427 hdb_add_aliases(krb5_context context, HDB *db,
428 unsigned flags, hdb_entry *entry)
430 const HDB_Ext_Aliases *aliases;
431 krb5_error_code code;
432 krb5_data key, value;
433 size_t i;
435 code = hdb_entry_get_aliases(entry, &aliases);
436 if (code || aliases == NULL)
437 return code;
439 for (i = 0; i < aliases->aliases.len; i++) {
440 hdb_entry_alias entryalias;
441 entryalias.principal = entry->principal;
443 code = hdb_entry_alias2value(context, &entryalias, &value);
444 if (code)
445 return code;
447 code = hdb_principal2key(context, &aliases->aliases.val[i], &key);
448 if (code == 0) {
449 code = db->hdb__put(context, db, flags, key, value);
450 krb5_data_free(&key);
451 if (code == HDB_ERR_EXISTS)
453 * Assuming hdb_check_aliases() was called, this must be a
454 * duplicate in the alias list.
456 code = 0;
458 krb5_data_free(&value);
459 if (code)
460 return code;
462 return 0;
465 /* Check if new aliases are already used for other entries */
466 static krb5_error_code
467 hdb_check_aliases(krb5_context context, HDB *db, hdb_entry *entry)
469 const HDB_Ext_Aliases *aliases = NULL;
470 HDB_EntryOrAlias eoa;
471 krb5_data akey, value;
472 size_t i;
473 int ret;
475 memset(&eoa, 0, sizeof(eoa));
476 krb5_data_zero(&value);
477 akey = value;
479 ret = hdb_entry_get_aliases(entry, &aliases);
480 for (i = 0; ret == 0 && aliases && i < aliases->aliases.len; i++) {
481 ret = hdb_principal2key(context, &aliases->aliases.val[i], &akey);
482 if (ret == 0)
483 ret = db->hdb__get(context, db, akey, &value);
484 if (ret == 0)
485 ret = decode_HDB_EntryOrAlias(value.data, value.length, &eoa, NULL);
486 if (ret == 0 && eoa.element != choice_HDB_EntryOrAlias_entry &&
487 eoa.element != choice_HDB_EntryOrAlias_alias)
488 ret = ENOTSUP;
489 if (ret == 0 && eoa.element == choice_HDB_EntryOrAlias_entry)
490 /* New alias names an existing non-alias entry in the HDB */
491 ret = HDB_ERR_EXISTS;
492 if (ret == 0 && eoa.element == choice_HDB_EntryOrAlias_alias &&
493 !krb5_principal_compare(context, eoa.u.alias.principal,
494 entry->principal))
495 /* New alias names an existing alias of a different entry */
496 ret = HDB_ERR_EXISTS;
497 if (ret == HDB_ERR_NOENTRY) /* from db->hdb__get */
498 /* New alias is a name that doesn't exist in the HDB */
499 ret = 0;
501 free_HDB_EntryOrAlias(&eoa);
502 krb5_data_free(&value);
503 krb5_data_free(&akey);
505 return ret;
509 * Many HDB entries don't have `etypes' setup. Historically we use the
510 * enctypes of the selected keyset as the entry's supported enctypes, but that
511 * is problematic. By doing this at store time and, if need be, at fetch time,
512 * we can make sure to stop deriving supported etypes from keys in the long
513 * run. We also need kadm5/kadmin support for etypes. We'll use this function
514 * there to derive etypes when using a kadm5_principal_ent_t that lacks the new
515 * TL data for etypes.
517 krb5_error_code
518 hdb_derive_etypes(krb5_context context, hdb_entry *e, HDB_Ext_KeySet *base_keys)
520 krb5_error_code ret = 0;
521 size_t i, k, netypes;
522 HDB_extension *ext;
524 if (!base_keys &&
525 (ext = hdb_find_extension(e, choice_HDB_extension_data_hist_keys)))
526 base_keys = &ext->data.u.hist_keys;
528 netypes = e->keys.len;
529 if (netypes == 0 && base_keys) {
530 /* There's no way that base_keys->val[i].keys.len == 0, but hey */
531 for (i = 0; netypes == 0 && i < base_keys->len; i++)
532 netypes = base_keys->val[i].keys.len;
535 if (netypes == 0)
536 return 0;
538 if (e->etypes != NULL) {
539 free(e->etypes->val);
540 e->etypes->len = 0;
541 e->etypes->val = 0;
542 } else if ((e->etypes = calloc(1, sizeof(e->etypes[0]))) == NULL) {
543 ret = krb5_enomem(context);
545 if (ret == 0 &&
546 (e->etypes->val = calloc(netypes, sizeof(e->etypes->val[0]))) == NULL)
547 ret = krb5_enomem(context);
548 if (ret) {
549 free(e->etypes);
550 e->etypes = 0;
551 return ret;
553 e->etypes->len = netypes;
554 for (i = 0; i < e->keys.len && i < netypes; i++)
555 e->etypes->val[i] = e->keys.val[i].key.keytype;
556 if (!base_keys || i)
557 return 0;
558 for (k = 0; i == 0 && k < base_keys->len; k++) {
559 if (!base_keys->val[k].keys.len)
560 continue;
561 for (; i < base_keys->val[k].keys.len; i++)
562 e->etypes->val[i] = base_keys->val[k].keys.val[i].key.keytype;
564 return 0;
567 krb5_error_code
568 _hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
570 krb5_data key, value;
571 int code;
573 if (entry->flags.do_not_store ||
574 entry->flags.force_canonicalize)
575 return HDB_ERR_MISUSE;
576 /* check if new aliases already is used */
577 code = hdb_check_aliases(context, db, entry);
578 if (code)
579 return code;
581 if ((flags & HDB_F_PRECHECK) && (flags & HDB_F_REPLACE))
582 return 0;
584 if ((flags & HDB_F_PRECHECK)) {
585 code = hdb_principal2key(context, entry->principal, &key);
586 if (code)
587 return code;
588 code = db->hdb__get(context, db, key, &value);
589 krb5_data_free(&key);
590 if (code == 0)
591 krb5_data_free(&value);
592 if (code == HDB_ERR_NOENTRY)
593 return 0;
594 return code ? code : HDB_ERR_EXISTS;
597 if ((entry->etypes == NULL || entry->etypes->len == 0) &&
598 (code = hdb_derive_etypes(context, entry, NULL)))
599 return code;
601 if (entry->generation == NULL) {
602 struct timeval t;
603 entry->generation = malloc(sizeof(*entry->generation));
604 if(entry->generation == NULL) {
605 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
606 return ENOMEM;
608 gettimeofday(&t, NULL);
609 entry->generation->time = t.tv_sec;
610 entry->generation->usec = t.tv_usec;
611 entry->generation->gen = 0;
612 } else
613 entry->generation->gen++;
615 code = hdb_seal_keys(context, db, entry);
616 if (code)
617 return code;
619 code = hdb_principal2key(context, entry->principal, &key);
620 if (code)
621 return code;
623 /* remove aliases */
624 code = hdb_remove_aliases(context, db, &key);
625 if (code) {
626 krb5_data_free(&key);
627 return code;
629 code = hdb_entry2value(context, entry, &value);
630 if (code == 0)
631 code = db->hdb__put(context, db, flags & HDB_F_REPLACE, key, value);
632 krb5_data_free(&value);
633 krb5_data_free(&key);
634 if (code)
635 return code;
637 code = hdb_add_aliases(context, db, flags, entry);
639 return code;
642 krb5_error_code
643 _hdb_remove(krb5_context context, HDB *db,
644 unsigned flags, krb5_const_principal principal)
646 krb5_data key, value;
647 HDB_EntryOrAlias eoa;
648 int is_alias = -1;
649 int code;
652 * We only allow deletion of entries by canonical name. To remove an
653 * alias use kadm5_modify_principal().
655 * We need to determine if this is an alias. We decode as a
656 * HDB_EntryOrAlias, which is expensive -- we could decode as a
657 * HDB_entry_alias instead and assume it's an entry if decoding fails...
660 code = hdb_principal2key(context, principal, &key);
661 if (code == 0)
662 code = db->hdb__get(context, db, key, &value);
663 if (code == 0) {
664 code = decode_HDB_EntryOrAlias(value.data, value.length, &eoa, NULL);
665 krb5_data_free(&value);
667 if (code == 0) {
668 is_alias = eoa.element == choice_HDB_EntryOrAlias_entry ? 0 : 1;
669 free_HDB_EntryOrAlias(&eoa);
672 if ((flags & HDB_F_PRECHECK)) {
673 if (code == 0 && is_alias)
674 krb5_set_error_message(context, code = HDB_ERR_NOENTRY,
675 "Cannot delete alias of principal");
676 krb5_data_free(&key);
677 return code;
680 if (code == 0)
681 code = hdb_remove_aliases(context, db, &key);
682 if (code == 0)
683 code = db->hdb__del(context, db, key);
684 krb5_data_free(&key);
685 return code;
688 /* PRF+(K_base, pad, keylen(etype)) */
689 static krb5_error_code
690 derive_Key1(krb5_context context,
691 krb5_data *pad,
692 EncryptionKey *base,
693 krb5int32 etype,
694 EncryptionKey *nk)
696 krb5_error_code ret;
697 krb5_crypto crypto = NULL;
698 krb5_data out;
699 size_t len;
701 out.data = 0;
702 out.length = 0;
704 ret = krb5_enctype_keysize(context, base->keytype, &len);
705 if (ret == 0)
706 ret = krb5_crypto_init(context, base, 0, &crypto);
707 if (ret == 0)
708 ret = krb5_crypto_prfplus(context, crypto, pad, len, &out);
709 if (crypto)
710 krb5_crypto_destroy(context, crypto);
711 if (ret == 0)
712 ret = krb5_random_to_key(context, etype, out.data, out.length, nk);
713 krb5_data_free(&out);
714 return ret;
717 /* PRF+(PRF+(K_base, princ, keylen(etype)), kvno, keylen(etype)) */
718 /* XXX Make it PRF+(PRF+(K_base, princ, keylen(K_base.etype)), and lift it, kvno, keylen(etype)) */
719 static krb5_error_code
720 derive_Key(krb5_context context,
721 const char *princ,
722 krb5uint32 kvno,
723 EncryptionKey *base,
724 krb5int32 etype,
725 Key *nk)
727 krb5_error_code ret = 0;
728 EncryptionKey intermediate;
729 krb5_data pad;
731 nk->salt = NULL;
732 nk->mkvno = NULL;
733 nk->key.keytype = 0;
734 nk->key.keyvalue.data = 0;
735 nk->key.keyvalue.length = 0;
737 intermediate.keytype = 0;
738 intermediate.keyvalue.data = 0;
739 intermediate.keyvalue.length = 0;
740 if (princ) {
741 /* Derive intermediate key for the given principal */
742 /* XXX Lift to optimize? */
743 pad.data = (void *)(uintptr_t)princ;
744 pad.length = strlen(princ);
745 ret = derive_Key1(context, &pad, base, etype, &intermediate);
746 if (ret == 0)
747 base = &intermediate;
748 } /* else `base' is already an intermediate key for the desired princ */
750 /* Derive final key for `kvno' from intermediate key */
751 kvno = htonl(kvno);
752 pad.data = &kvno;
753 pad.length = sizeof(kvno);
754 if (ret == 0)
755 ret = derive_Key1(context, &pad, base, etype, &nk->key);
756 free_EncryptionKey(&intermediate);
757 return ret;
761 * PRF+(PRF+(K_base, princ, keylen(etype)), kvno, keylen(etype)) for one
762 * enctype.
764 static krb5_error_code
765 derive_Keys(krb5_context context,
766 const char *princ,
767 krb5uint32 kvno,
768 krb5int32 etype,
769 const Keys *base,
770 Keys *dk)
773 krb5_error_code ret = 0;
774 size_t i;
775 Key nk;
777 dk->len = 0;
778 dk->val = 0;
781 * The enctypes of the base keys is the list of enctypes to derive keys
782 * for. Still, we derive all keys from the first base key.
784 for (i = 0; ret == 0 && i < base->len; i++) {
785 if (etype != KRB5_ENCTYPE_NULL && etype != base->val[i].key.keytype)
786 continue;
787 ret = derive_Key(context, princ, kvno, &base->val[0].key,
788 base->val[i].key.keytype, &nk);
789 if (ret)
790 break;
791 ret = add_Keys(dk, &nk);
792 free_Key(&nk);
794 * FIXME We need to finish kdc/kadm5/kadmin support for the `etypes' so
795 * we can reduce the number of keys in keytabs to just those in current
796 * use and only of *one* enctype.
798 * What we could do is derive *one* key and for the others output a
799 * one-byte key of the intended enctype (which will never work).
801 * We'll never need any keys but the first one...
805 if (ret)
806 free_Keys(dk);
807 return ret;
810 /* Helper for derive_keys_for_kr() */
811 static krb5_error_code
812 derive_keyset(krb5_context context,
813 const Keys *base_keys,
814 const char *princ,
815 krb5int32 etype,
816 krb5uint32 kvno,
817 KerberosTime set_time, /* "now" */
818 hdb_keyset *dks)
820 dks->kvno = kvno;
821 dks->keys.val = 0;
822 dks->set_time = malloc(sizeof(*(dks->set_time)));
823 if (dks->set_time == NULL)
824 return krb5_enomem(context);
825 *dks->set_time = set_time;
826 return derive_Keys(context, princ, kvno, etype, base_keys, &dks->keys);
829 /* Possibly derive and install in `h' a keyset identified by `t' */
830 static krb5_error_code
831 derive_keys_for_kr(krb5_context context,
832 hdb_entry *h,
833 HDB_Ext_KeySet *base_keys,
834 int is_current_keyset,
835 int rotation_period_offset,
836 const char *princ,
837 krb5int32 etype,
838 krb5uint32 kvno_wanted,
839 KerberosTime t,
840 struct KeyRotation *krp)
842 krb5_error_code ret;
843 hdb_keyset dks;
844 KerberosTime set_time, n;
845 krb5uint32 kvno;
846 size_t i;
848 if (rotation_period_offset < -1 || rotation_period_offset > 1)
849 return EINVAL; /* wat */
852 * Compute `kvno' and `set_time' given `t' and `krp'.
854 * There be signed 32-bit time_t dragons here.
856 * (t - krp->epoch < 0) is better than (krp->epoch < t), making us more
857 * tolerant of signed 32-bit time_t here near 2038. Of course, we have
858 * signed 32-bit time_t dragons elsewhere.
860 * We don't need to check for n == 0 && rotation_period_offset < 0 because
861 * only derive_keys_for_current_kr() calls us with non-zero rotation period
862 * offsets, and it will never call us in that case.
864 if (t - krp->epoch < 0)
865 return 0; /* This KR is not relevant yet */
866 n = (t - krp->epoch) / krp->period;
867 n += rotation_period_offset;
868 set_time = krp->epoch + krp->period * n;
869 kvno = krp->base_kvno + n;
872 * Since this principal is virtual, or has virtual keys, we're going to
873 * derive a "password expiration time" for it in order to help httpkadmind
874 * and other tools figure out when to request keys again.
876 * The kadm5 representation of principals does not include the set_time of
877 * keys/keysets, so we can't have httpkadmind derive a Cache-Control from
878 * that without adding yet another "TL data". Since adding TL data is a
879 * huge pain, we'll just use the `pw_end' field of `HDB_entry' to
880 * communicate when this principal's keys will change next.
882 if (h->pw_end[0] == 0) {
883 KerberosTime used = (t - krp->epoch) % krp->period;
884 KerberosTime left = krp->period - used;
887 * If `h->pw_end[0]' == 0 then this must be the current period of the
888 * current KR we're deriving keys for. See upstairs.
890 * If there's more than a quarter of this time period left, then we'll
891 * set `h->pw_end[0]' to one quarter before the end of this time
892 * period. Else we'll set it to 1/4 after (we'll be including the next
893 * set of derived keys, so there's no harm in waiting that long to
894 * refetch).
896 if (left > krp->period >> 2)
897 h->pw_end[0] = set_time + krp->period - (krp->period >> 2);
898 else
899 h->pw_end[0] = set_time + krp->period + (krp->period >> 2);
904 * Do not waste cycles computing keys not wanted or needed.
905 * A past kvno is too old if its set_time + rotation period is in the past
906 * by more than half a rotation period, since then no service ticket
907 * encrypted with keys of that kvno can still be extant.
909 * A future kvno is not coming up soon enough if we're more than a quarter
910 * of the rotation period away from it.
912 * Recall: the assumption for virtually-keyed principals is that services
913 * fetch their future keys frequently enough that they'll never miss having
914 * the keys they need.
916 if (!is_current_keyset || rotation_period_offset != 0) {
917 if ((kvno_wanted && kvno != kvno_wanted) ||
918 t - (set_time + krp->period + (krp->period >> 1)) > 0 ||
919 (set_time - t > 0 && (set_time - t) > (krp->period >> 2)))
920 return 0;
923 for (i = 0; i < base_keys->len; i++) {
924 if (base_keys->val[i].kvno == krp->base_key_kvno)
925 break;
927 if (i == base_keys->len) {
928 /* Base key not found! */
929 if (kvno_wanted || is_current_keyset) {
930 krb5_set_error_message(context, ret = HDB_ERR_KVNO_NOT_FOUND,
931 "Base key version %u not found for %s",
932 krp->base_key_kvno, princ);
933 return ret;
935 return 0;
938 ret = derive_keyset(context, &base_keys->val[i].keys, princ, etype, kvno,
939 set_time, &dks);
940 if (ret == 0)
941 ret = hdb_install_keyset(context, h, is_current_keyset, &dks);
943 free_HDB_keyset(&dks);
944 return ret;
947 /* Derive and install current keys, and possibly preceding or next keys */
948 static krb5_error_code
949 derive_keys_for_current_kr(krb5_context context,
950 hdb_entry *h,
951 HDB_Ext_KeySet *base_keys,
952 const char *princ,
953 unsigned int flags,
954 krb5int32 etype,
955 krb5uint32 kvno_wanted,
956 KerberosTime t,
957 struct KeyRotation *krp,
958 KerberosTime future_epoch)
960 krb5_error_code ret;
962 /* derive_keys_for_kr() for current kvno and install as the current keys */
963 ret = derive_keys_for_kr(context, h, base_keys, 1, 0, princ, etype,
964 kvno_wanted, t, krp);
965 if (!(flags & HDB_F_ALL_KVNOS))
966 return ret;
968 /* */
972 * derive_keys_for_kr() for prev kvno if still needed -- it can only be
973 * needed if the prev kvno's start time is within this KR's epoch.
975 * Note that derive_keys_for_kr() can return without doing anything if this
976 * is isn't the current keyset. So these conditions need not be
977 * sufficiently narrow.
979 if (ret == 0 && t - krp->epoch >= krp->period)
980 ret = derive_keys_for_kr(context, h, base_keys, 0, -1, princ, etype,
981 kvno_wanted, t, krp);
983 * derive_keys_for_kr() for next kvno if near enough, but only if it
984 * doesn't start after the next KR's epoch.
986 if (future_epoch &&
987 t - krp->epoch >= 0 /* We know! Hint to the compiler */) {
988 KerberosTime next_kvno_start, n;
990 n = (t - krp->epoch) / krp->period;
991 next_kvno_start = krp->epoch + krp->period * (n + 1);
992 if (future_epoch - next_kvno_start <= 0)
993 return ret;
995 if (ret == 0)
996 ret = derive_keys_for_kr(context, h, base_keys, 0, 1, princ, etype,
997 kvno_wanted, t, krp);
998 return ret;
1002 * Derive and install all keysets in `h' that `princ' needs at time `now'.
1004 * This mutates the entry `h' to
1006 * a) not have base keys,
1007 * b) have keys derived from the base keys according to
1008 * c) the key rotation periods for the base principal (possibly the same
1009 * principal if it's a concrete principal with virtual keys), and the
1010 * requested time, enctype, and kvno (all of which are optional, with zero
1011 * implying some default).
1013 * Arguments:
1015 * - `flags' is the flags passed to `hdb_fetch_kvno()'
1016 * - `princ' is the name of the principal we'll end up with in `entry'
1017 * - `h_is_namespace' indicates whether `h' is for a namespace or a concrete
1018 * principal (that might nonetheless have virtual/derived keys)
1019 * - `t' is the time such that the derived keys are for kvnos needed at `t'
1020 * - `etype' indicates what enctype to derive keys for (0 for all enctypes in
1021 * `entry->etypes')
1022 * - `kvno' requests a particular kvno, or all if zero
1024 * The caller doesn't know if the principal needs key derivation -- we make
1025 * that determination in this function.
1027 * Note that this function is fully deterministic for any given set of
1028 * arguments and HDB contents.
1030 * Definitions:
1032 * - A keyset is a set of keys for a single kvno.
1033 * - A keyset is relevant IFF:
1034 * - it is the keyset for a time period identified by `t' in a
1035 * corresponding KR
1036 * - it is a keyset for a past time period for which there may be extant,
1037 * not-yet-expired tickets that a service may need to decrypt
1038 * - it is a keyset for an upcoming time period that a service will need to
1039 * fetch before that time period becomes current, that way the service
1040 * can have keytab entries for those keys in time for when the KDC starts
1041 * encrypting service tickets to those keys
1043 * This function derives the keyset(s) for the current KR first. The idea is
1044 * to optimize the order of resulting keytabs so that the most likely keys to
1045 * be used come first.
1047 * Invariants:
1049 * - KR metadata is sane because sanity is checked for when storing HDB
1050 * entries
1051 * - KRs are sorted by epoch in descending order; KR #0's epoch is the most
1052 * recent
1053 * - KR periods are non-zero (we divide by period)
1054 * - kvnos are numerically ordered and correspond to time periods
1055 * - within each KR, the kvnos for larger times are larger than (or equal
1056 * to) the kvnos of earlier times
1057 * - at KR boundaries, the first kvno of the newer boundary is larger than
1058 * the kvno of the last time period of the previous KR
1059 * - the time `t' must fall into exactly one KR period
1060 * - the time `t' must fall into exactly one period within a KR period
1061 * - at most two kvnos will be relevant from the KR that `t' falls into
1062 * (the current kvno for `t', and possibly either the preceding, or the
1063 * next)
1064 * - at most one kvno from non-current KRs will be derived: possibly one for a
1065 * preceding KR, and possibly one from an upcoming KR
1067 * There can be:
1069 * - no KR extension (not a namespace principal, and no virtual keys)
1070 * - 1, 2, or 3 KRs (see above)
1071 * - the newest KR may have the `deleted' flag, meaning "does not exist after
1072 * this epoch"
1074 * Note that the last time period in any older KR can be partial.
1076 * Timeline diagram:
1078 * .......|--+--+...+--|---+---+---+...+--|----+...
1079 * T20 T10 T11 RT12 T1n T01
1080 * ^ ^ ^ ^ ^ ^ ^ T00
1081 * | | | T22 T2n | | ^
1082 * ^ | T21 | | |
1083 * princ | | epoch of | epoch of
1084 * did | | middle KR | newest epoch
1085 * not | | |
1086 * exist! | start of Note that T1n
1087 * | second kvno is shown as shorter
1088 * | in 1st epoch than preceding periods
1091 * first KR's
1092 * epoch, and start
1093 * of its first kvno
1095 * Tmn == the start of the Mth KR's Nth time period.
1096 * (higher M -> older KR; lower M -> newer KR)
1097 * (N is the reverse: lower N -> older time period in KR)
1098 * T20 == start of oldest KR -- no keys before this time will be derived.
1099 * T2n == last time period in oldest KR
1100 * T10 == start of middle KR
1101 * T1n == last time period in middle KR
1102 * T00 == start of newest KR
1103 * T0n == current time period in newest KR for wall clock time
1105 static krb5_error_code
1106 derive_keys(krb5_context context,
1107 unsigned flags,
1108 krb5_const_principal princ,
1109 int h_is_namespace,
1110 krb5_timestamp t,
1111 krb5int32 etype,
1112 krb5uint32 kvno,
1113 hdb_entry *h)
1115 HDB_Ext_KeyRotation kr;
1116 HDB_Ext_KeySet base_keys;
1117 krb5_error_code ret = 0;
1118 size_t current_kr, future_kr, past_kr, i;
1119 char *p = NULL;
1120 int valid = 1;
1122 if (!h_is_namespace && !h->flags.virtual_keys)
1123 return 0;
1124 h->flags.virtual = 1;
1126 kr.len = 0;
1127 kr.val = 0;
1128 if (ret == 0) {
1129 const HDB_Ext_KeyRotation *ckr;
1131 /* Installing keys invalidates `ckr', so we copy it */
1132 ret = hdb_entry_get_key_rotation(context, h, &ckr);
1133 if (!ckr)
1134 return ret;
1135 if (ret == 0)
1136 ret = copy_HDB_Ext_KeyRotation(ckr, &kr);
1139 /* Get the base keys from the entry, and remove them */
1140 base_keys.val = 0;
1141 base_keys.len = 0;
1142 if (ret == 0)
1143 ret = _hdb_remove_base_keys(context, h, &base_keys, &kr);
1145 /* Make sure we have h->etypes */
1146 if (ret == 0 && !h->etypes)
1147 ret = hdb_derive_etypes(context, h, &base_keys);
1149 /* Keys not desired? Don't derive them! */
1150 if (ret || !(flags & HDB_F_DECRYPT)) {
1151 free_HDB_Ext_KeyRotation(&kr);
1152 free_HDB_Ext_KeySet(&base_keys);
1153 return ret;
1156 /* The principal name will be used in key derivation and error messages */
1157 if (ret == 0)
1158 ret = krb5_unparse_name(context, princ, &p);
1160 /* Sanity check key rotations, determine current & last kr */
1161 if (ret == 0 && kr.len < 1)
1162 krb5_set_error_message(context, ret = HDB_ERR_NOENTRY,
1163 "no key rotation periods for %s", p);
1164 if (ret == 0)
1165 current_kr = future_kr = past_kr = kr.len;
1166 else
1167 current_kr = future_kr = past_kr = 1;
1170 * Identify a current, next, and previous KRs if there are any.
1172 * There can be up to three KRs, ordered by epoch, descending, making up a
1173 * timeline like:
1175 * ...|---------|--------|------>
1176 * ^ | | |
1177 * | | | |
1178 * | | | Newest KR (kr.val[0])
1179 * | | Middle KR (kr.val[1])
1180 * | Oldest (last) KR (kr.val[2])
1182 * Before the begging of time for this namespace
1184 * We step through these from future towards past looking for the best
1185 * future, current, and past KRs. The best current KR is one that has its
1186 * epoch nearest to `t' but in the past of `t'.
1188 * We validate KRs before storing HDB entries with the KR extension, so we
1189 * can assume they are valid here. However, we do some validity checking,
1190 * and if they're not valid, we pick the best current KR and ignore the
1191 * others.
1193 * In principle there cannot be two future KRs, but this function is
1194 * deterministic and takes a time value, so it should not enforce this just
1195 * so we can test. Enforcement of such rules should be done at store time.
1197 for (i = 0; ret == 0 && i < kr.len; i++) {
1198 /* Minimal validation: order and period */
1199 if (i && kr.val[i - 1].epoch - kr.val[i].epoch <= 0) {
1200 future_kr = past_kr = kr.len;
1201 valid = 0;
1203 if (!kr.val[i].period) {
1204 future_kr = past_kr = kr.len;
1205 valid = 0;
1206 continue;
1208 if (t - kr.val[i].epoch >= 0) {
1210 * `t' is in the future of this KR's epoch, so it's a candidate for
1211 * either current or past KR.
1213 if (current_kr == kr.len)
1214 current_kr = i; /* First curr KR candidate; should be best */
1215 else if (kr.val[current_kr].epoch - kr.val[i].epoch < 0)
1216 current_kr = i; /* Invalid KRs, but better curr KR cand. */
1217 else if (valid && past_kr == kr.len)
1218 past_kr = i;
1219 } else if (valid) {
1220 /* This KR is in the future of `t', a candidate for next KR */
1221 future_kr = i;
1224 if (ret == 0 && current_kr == kr.len)
1225 /* No current KR -> too soon */
1226 krb5_set_error_message(context, ret = HDB_ERR_NOENTRY,
1227 "Too soon for virtual principal to exist");
1229 /* Check that the principal has not been marked deleted */
1230 if (ret == 0 && current_kr < kr.len && kr.val[current_kr].flags.deleted)
1231 krb5_set_error_message(context, ret = HDB_ERR_NOENTRY,
1232 "virtual principal %s does not exist "
1233 "because last key rotation period "
1234 "marks deletion", p);
1236 /* See `derive_keys_for_kr()' */
1237 if (h->pw_end == NULL &&
1238 (h->pw_end = calloc(1, sizeof(h->pw_end[0]))) == NULL)
1239 ret = krb5_enomem(context);
1242 * Derive and set in `h' its current kvno and current keys.
1244 * This will set h->kvno as well.
1246 * This may set up to TWO keysets for the current key rotation period:
1247 * - current keys (h->keys and h->kvno)
1248 * - possibly one future
1249 * OR
1250 * possibly one past keyset in hist_keys for the current_kr
1252 if (ret == 0 && current_kr < kr.len)
1253 ret = derive_keys_for_current_kr(context, h, &base_keys, p, flags,
1254 etype, kvno, t, &kr.val[current_kr],
1255 current_kr ? kr.val[0].epoch : 0);
1258 * Derive and set in `h' its future keys for next KR if it is soon to be
1259 * current.
1261 * We want to derive keys for the first kvno of the next (future) KR if
1262 * it's sufficiently close to `t', meaning within 1 period of the current
1263 * KR, but we want these keys to be available sooner, so 1.5 of the current
1264 * period.
1266 if (ret == 0 && future_kr < kr.len && (flags & HDB_F_ALL_KVNOS))
1267 ret = derive_keys_for_kr(context, h, &base_keys, 0, 0, p, etype, kvno,
1268 kr.val[future_kr].epoch, &kr.val[future_kr]);
1271 * Derive and set in `h' its past keys for the previous KR if its last time
1272 * period could still have extant, unexpired service tickets encrypted in
1273 * its keys.
1275 if (ret == 0 && past_kr < kr.len && (flags & HDB_F_ALL_KVNOS))
1276 ret = derive_keys_for_kr(context, h, &base_keys, 0, 0, p, etype, kvno,
1277 kr.val[current_kr].epoch - 1, &kr.val[past_kr]);
1280 * Impose a bound on h->max_life so that [when the KDC is the caller]
1281 * the KDC won't issue tickets longer lived than this.
1283 if (ret == 0 && !h->max_life &&
1284 (h->max_life = calloc(1, sizeof(h->max_life[0]))) == NULL)
1285 ret = krb5_enomem(context);
1286 if (ret == 0 && *h->max_life > kr.val[current_kr].period >> 1)
1287 *h->max_life = kr.val[current_kr].period >> 1;
1289 if (ret == 0 && h->pw_end[0] == 0)
1290 /* Shouldn't happen */
1291 h->pw_end[0] = kr.val[current_kr].epoch +
1292 kr.val[current_kr].period *
1293 (1 + (t - kr.val[current_kr].epoch) / kr.val[current_kr].period);
1295 free_HDB_Ext_KeyRotation(&kr);
1296 free_HDB_Ext_KeySet(&base_keys);
1297 free(p);
1298 return ret;
1302 * Pick a best kvno for the given principal at the given time.
1304 * Implements the [hdb] new_service_key_delay configuration parameter.
1306 * In order for disparate keytab provisioning systems such as OSKT and our own
1307 * kadmin ext_keytab and httpkadmind's get-keys to coexist, we need to be able
1308 * to force keys set by the former to not become current keys until users of
1309 * the latter have had a chance to fetch those keys into their keytabs. To do
1310 * this we have to search the list of keys in the entry looking for the newest
1311 * keys older than `now - db->new_service_key_delay'.
1313 * The context is that OSKT's krb5_keytab is very happy to change keys in a way
1314 * that requires all members of a cluster to rekey together. If one also
1315 * wishes to have cluster members that opt out of this and just fetch current,
1316 * past, and future keys periodically, then the keys set by OSKT must not come
1317 * into effect until all the opt-out members have had a chance to fetch the new
1318 * keys.
1320 * The assumption is that services will fetch new keys periodically, say, every
1321 * four hours. Then one can set `[hdb] new_service_key_delay = 8h' in the
1322 * configuration and new keys set by OSKT will not be used until 8h after they
1323 * are set.
1325 * Naturally, this applies only to concrete principals with concrete keys.
1327 static krb5_error_code
1328 pick_kvno(krb5_context context,
1329 HDB *db,
1330 unsigned flags,
1331 krb5_timestamp now,
1332 krb5uint32 kvno,
1333 hdb_entry *h)
1335 HDB_extension *ext;
1336 HDB_Ext_KeySet keys;
1337 time_t current = 0;
1338 time_t best;
1339 size_t i;
1342 * If we want a specific kvno, or if the caller doesn't want new keys
1343 * delayed, or if there's no new-key delay configured, or we're not
1344 * fetching for use as a service principal, then we're out.
1346 if (!(flags & HDB_F_DELAY_NEW_KEYS) || kvno || h->flags.virtual ||
1347 h->flags.virtual_keys || db->new_service_key_delay <= 0)
1348 return 0;
1350 /* No history -> current keyset is the only one and therefore the best */
1351 ext = hdb_find_extension(h, choice_HDB_extension_data_hist_keys);
1352 if (!ext)
1353 return 0;
1355 /* Assume the current keyset is the best to start with */
1356 (void) hdb_entry_get_pw_change_time(h, &current);
1357 if (current == 0 && h->modified_by)
1358 current = h->modified_by->time;
1359 if (current == 0)
1360 current = h->created_by.time;
1362 /* Current keyset starts out as best */
1363 best = current;
1364 kvno = h->kvno;
1366 /* Look for a better keyset in the history */
1367 keys = ext->data.u.hist_keys;
1368 for (i = 0; i < keys.len; i++) {
1369 /* No set_time? Ignore. Too new? Ignore */
1370 if (!keys.val[i].set_time ||
1371 keys.val[i].set_time[0] + db->new_service_key_delay > now)
1372 continue;
1375 * Ignore the keyset with kvno 1 when the entry has better kvnos
1376 * because kadmin's `ank -r' command immediately changes the keys.
1378 if (kvno > 1 && keys.val[i].kvno == 1)
1379 continue;
1382 * This keyset's set_time older than the previous best? Ignore.
1383 * However, if the current best is the entry's current and that one
1384 * is too new, then don't ignore this one.
1386 if (keys.val[i].set_time[0] < best &&
1387 (best != current || current + db->new_service_key_delay < now))
1388 continue;
1391 * If two good enough keysets have the same set_time, take the keyset
1392 * with the highest kvno.
1394 if (keys.val[i].set_time[0] == best && keys.val[i].kvno <= kvno)
1395 continue;
1398 * This keyset is clearly more current than the previous best keyset
1399 * but still old enough to use for encrypting tickets with.
1401 best = keys.val[i].set_time[0];
1402 kvno = keys.val[i].kvno;
1404 return hdb_change_kvno(context, kvno, h);
1408 * Make a WELLKNOWN/HOSTBASED-NAMESPACE/${svc}/${hostname} or
1409 * WELLKNOWN/HOSTBASED-NAMESPACE/${svc}/${hostname}/${domainname} principal
1410 * object, with the service and hostname components take from `wanted', but if
1411 * the service name is not in the list `db->virtual_hostbased_princ_svcs[]'
1412 * then use "_" (wildcard) instead. This way we can have different attributes
1413 * for different services in the same namespaces.
1415 * For example, virtual hostbased service names for the "host" service might
1416 * have ok-as-delegate set, but ones for the "HTTP" service might not.
1418 static krb5_error_code
1419 make_namespace_princ(krb5_context context,
1420 HDB *db,
1421 krb5_const_principal wanted,
1422 krb5_principal *namespace)
1424 krb5_error_code ret = 0;
1425 const char *realm = krb5_principal_get_realm(context, wanted);
1426 const char *comp0 = krb5_principal_get_comp_string(context, wanted, 0);
1427 const char *comp1 = krb5_principal_get_comp_string(context, wanted, 1);
1428 const char *comp2 = krb5_principal_get_comp_string(context, wanted, 2);
1429 char * const *svcs = db->virtual_hostbased_princ_svcs;
1430 size_t i;
1432 *namespace = NULL;
1433 if (comp0 == NULL || comp1 == NULL)
1434 return EINVAL;
1435 if (strcmp(comp0, "krbtgt") == 0)
1436 return 0;
1438 for (i = 0; svcs && svcs[i]; i++) {
1439 if (strcmp(comp0, svcs[i]) == 0) {
1440 comp0 = svcs[i];
1441 break;
1444 if (!svcs || !svcs[i])
1445 comp0 = "_";
1447 /* First go around, need a namespace princ. Make it! */
1448 ret = krb5_build_principal(context, namespace, strlen(realm),
1449 realm, KRB5_WELLKNOWN_NAME,
1450 HDB_WK_NAMESPACE, comp0, NULL);
1451 if (ret == 0)
1452 ret = krb5_principal_set_comp_string(context, *namespace, 3, comp1);
1453 if (ret == 0 && comp2)
1454 /* Support domain-based names */
1455 ret = krb5_principal_set_comp_string(context, *namespace, 4, comp2);
1456 /* Caller frees `*namespace' on error */
1457 return ret;
1460 static int
1461 is_namespace_princ_p(krb5_context context,
1462 krb5_const_principal princ)
1464 return
1465 krb5_principal_get_num_comp(context, princ) >= 4
1466 && strcmp(krb5_principal_get_comp_string(context, princ, 0),
1467 KRB5_WELLKNOWN_NAME) == 0
1468 && strcmp(krb5_principal_get_comp_string(context, princ, 1),
1469 HDB_WK_NAMESPACE) == 0;
1472 /* See call site */
1473 static krb5_error_code
1474 rewrite_hostname(krb5_context context,
1475 krb5_const_principal wanted_princ,
1476 krb5_const_principal ns_princ,
1477 krb5_const_principal found_ns_princ,
1478 char **s)
1480 const char *ns_host_part, *wanted_host_part, *found_host_part;
1481 const char *p, *r;
1482 size_t ns_host_part_len, wanted_host_part_len;
1484 wanted_host_part = krb5_principal_get_comp_string(context, wanted_princ, 1);
1485 wanted_host_part_len = strlen(wanted_host_part);
1486 if (wanted_host_part_len > 256) {
1487 krb5_set_error_message(context, HDB_ERR_NOENTRY,
1488 "Aliases of host-based principals longer than "
1489 "256 bytes not supported");
1490 return HDB_ERR_NOENTRY;
1493 ns_host_part = krb5_principal_get_comp_string(context, ns_princ, 3);
1494 ns_host_part_len = strlen(ns_host_part);
1496 /* Find `ns_host_part' as the tail of `wanted_host_part' */
1497 for (r = p = strstr(wanted_host_part, ns_host_part);
1498 r && strnlen(r, ns_host_part_len + 1) > ns_host_part_len;
1499 p = (r = strstr(r, ns_host_part)) ? r : p)
1501 if (!p || strnlen(p, ns_host_part_len + 1) != ns_host_part_len)
1502 return HDB_ERR_NOENTRY; /* Can't happen */
1503 if (p == wanted_host_part || p[-1] != '.')
1504 return HDB_ERR_NOENTRY;
1506 found_host_part =
1507 krb5_principal_get_comp_string(context, found_ns_princ, 3);
1508 return
1509 asprintf(s, "%.*s%s", (int)(p - wanted_host_part), wanted_host_part,
1510 found_host_part) < 0 ||
1511 *s == NULL ? krb5_enomem(context) : 0;
1515 * Fix `h->principal' to match the desired `princ' in the namespace
1516 * `nsprinc' (which is either the same as `h->principal' or an alias
1517 * of it).
1519 static krb5_error_code
1520 fix_princ_name(krb5_context context,
1521 krb5_const_principal princ,
1522 krb5_const_principal nsprinc,
1523 hdb_entry *h)
1525 krb5_error_code ret = 0;
1526 char *s = NULL;
1528 if (!nsprinc)
1529 return 0;
1530 if (krb5_principal_get_num_comp(context, princ) < 2)
1531 return HDB_ERR_NOENTRY;
1533 /* `nsprinc' must be a namespace principal */
1535 if (krb5_principal_compare(context, nsprinc, h->principal)) {
1537 * `h' is the HDB entry for `nsprinc', and `nsprinc' is its canonical
1538 * name.
1540 * Set the entry's principal name to the desired name. The keys will
1541 * be fixed next (upstairs, but don't forget to!).
1543 free_Principal(h->principal);
1544 return copy_Principal(princ, h->principal);
1547 if (!is_namespace_princ_p(context, h->principal)) {
1549 * The alias is a namespace, but the canonical name is not. WAT.
1551 * Well, the KDC will just issue a referral anyways, so we can leave
1552 * `h->principal' as is...
1554 * Remove all of `h's keys just in case, and leave
1555 * `h->principal' as-is.
1557 free_Keys(&h->keys);
1558 (void) hdb_entry_clear_password(context, h);
1559 return hdb_clear_extension(context, h,
1560 choice_HDB_extension_data_hist_keys);
1564 * A namespace alias of a namespace entry.
1566 * We'll want to rewrite the original principal accordingly.
1568 * E.g., if the caller wanted host/foo.ns.test.h5l.se and we
1569 * found WELLKNOWN/HOSTBASED-NAMESPACE/ns.test.h5l.se is an
1570 * alias of WELLKNOWN/HOSTBASED-NAMESPACE/ns.example.org, then
1571 * we'll want to treat host/foo.ns.test.h5l.se as an alias of
1572 * host/foo.ns.example.org.
1574 if (krb5_principal_get_num_comp(context, h->principal) !=
1575 2 + krb5_principal_get_num_comp(context, princ))
1576 ret = HDB_ERR_NOENTRY; /* Only host-based services for now */
1577 if (ret == 0)
1578 ret = rewrite_hostname(context, princ, nsprinc, h->principal, &s);
1579 if (ret == 0) {
1580 krb5_free_principal(context, h->principal);
1581 h->principal = NULL;
1582 ret = krb5_make_principal(context, &h->principal,
1583 krb5_principal_get_realm(context, princ),
1584 krb5_principal_get_comp_string(context,
1585 princ, 0),
1587 NULL);
1589 free(s);
1590 return ret;
1593 /* Wrapper around db->hdb_fetch_kvno() that implements virtual princs/keys */
1594 static krb5_error_code
1595 fetch_it(krb5_context context,
1596 HDB *db,
1597 krb5_const_principal princ,
1598 unsigned flags,
1599 krb5_timestamp t,
1600 krb5int32 etype,
1601 krb5uint32 kvno,
1602 hdb_entry *ent)
1604 krb5_const_principal tmpprinc = princ;
1605 krb5_principal nsprinc = NULL;
1606 krb5_error_code ret = 0;
1607 const char *comp0 = krb5_principal_get_comp_string(context, princ, 0);
1608 const char *comp1 = krb5_principal_get_comp_string(context, princ, 1);
1609 const char *tmp;
1610 size_t mindots = db->virtual_hostbased_princ_ndots;
1611 size_t maxdots = db->virtual_hostbased_princ_maxdots;
1612 size_t hdots = 0;
1613 char *host = NULL;
1614 int do_search = 0;
1616 if (!db->enable_virtual_hostbased_princs)
1617 maxdots = mindots = 0;
1618 if (db->enable_virtual_hostbased_princs && comp1 &&
1619 strcmp("krbtgt", comp0) != 0 && strcmp(KRB5_WELLKNOWN_NAME, comp0) != 0) {
1620 char *htmp;
1622 if ((host = strdup(comp1)) == NULL)
1623 return krb5_enomem(context);
1625 /* Strip out any :port */
1626 htmp = strchr(host, ':');
1627 if (htmp) {
1628 if (strchr(htmp + 1, ':')) {
1629 /* Extra ':'s? No virtualization for you! */
1630 free(host);
1631 host = NULL;
1632 } else {
1633 *htmp = '\0';
1636 /* Count dots in `host' */
1637 for (hdots = 0, htmp = host; htmp && *htmp; htmp++)
1638 if (*htmp == '.')
1639 hdots++;
1641 do_search = 1;
1644 tmp = host ? host : comp1;
1645 for (ret = HDB_ERR_NOENTRY; ret == HDB_ERR_NOENTRY; tmpprinc = nsprinc) {
1646 krb5_error_code ret2 = 0;
1649 * We break out of this loop with ret == 0 only if we found the HDB
1650 * entry we were looking for or the HDB entry for a matching namespace.
1652 * Otherwise we break out with ret != 0, typically HDB_ERR_NOENTRY.
1654 * First time through we lookup the principal as given.
1656 * Next we lookup a namespace principal, stripping off hostname labels
1657 * from the left until we find one or get tired of looking or run out
1658 * of labels.
1660 ret = db->hdb_fetch_kvno(context, db, tmpprinc, flags, kvno, ent);
1661 if (ret == 0 && nsprinc && ent->flags.invalid) {
1662 free_HDB_entry(ent);
1663 ret = HDB_ERR_NOENTRY;
1665 if (ret != HDB_ERR_NOENTRY || hdots == 0 || hdots < mindots || !tmp ||
1666 !do_search)
1667 break;
1670 * Breadcrumb:
1672 * - if we found a concrete principal, but it's been marked
1673 * as now-virtual, then we must keep going
1675 * But this will be coded in the future.
1677 * Maybe we can take attributes from the concrete principal...
1681 * The namespace's hostname will not have more labels than maxdots + 1.
1682 * Thus we truncate immediately down to maxdots + 1 if we haven't yet.
1684 * Example: with maxdots == 3,
1685 * foo.bar.baz.app.blah.example -> baz.app.blah.example
1687 while (maxdots && hdots > maxdots && tmp) {
1688 tmp = strchr(tmp, '.');
1689 /* tmp != NULL because maxdots > 0; we check to quiet linters */
1690 if (tmp == NULL) {
1691 ret = HDB_ERR_NOENTRY;
1692 goto out;
1694 tmp++;
1695 hdots--;
1698 if (nsprinc == NULL)
1699 /* First go around, need a namespace princ. Make it! */
1700 ret2 = make_namespace_princ(context, db, tmpprinc, &nsprinc);
1702 /* Update the hostname component of the namespace principal */
1703 if (ret2 == 0)
1704 ret2 = krb5_principal_set_comp_string(context, nsprinc, 3, tmp);
1705 if (ret2)
1706 ret = ret2;
1708 if (tmp) {
1709 /* Strip off left-most label for the next go-around */
1710 if ((tmp = strchr(tmp, '.')))
1711 tmp++;
1712 hdots--;
1713 } /* else we'll break out after the next db->hdb_fetch_kvno() call */
1717 * If unencrypted keys were requested, derive them. There may not be any
1718 * key derivation to do, but that's decided in derive_keys().
1720 if (ret == 0 || ret == HDB_ERR_WRONG_REALM) {
1721 krb5_error_code save_ret = ret;
1723 /* Fix the principal name if namespaced */
1724 ret = fix_princ_name(context, princ, nsprinc, ent);
1726 /* Derive keys if namespaced or virtual */
1727 if (ret == 0)
1728 ret = derive_keys(context, flags, princ, !!nsprinc, t, etype, kvno,
1729 ent);
1730 /* Pick the best kvno for this principal at the given time */
1731 if (ret == 0)
1732 ret = pick_kvno(context, db, flags, t, kvno, ent);
1733 if (ret == 0)
1734 ret = save_ret;
1737 out:
1738 if (ret != 0 && ret != HDB_ERR_WRONG_REALM)
1739 hdb_free_entry(context, db, ent);
1740 krb5_free_principal(context, nsprinc);
1741 free(host);
1742 return ret;
1746 * Fetch a principal's HDB entry, possibly generating virtual keys from base
1747 * keys according to strict key rotation schedules. If a time is given, other
1748 * than HDB I/O, this function is pure, thus usable for testing.
1750 * HDB writers should use `db->hdb_fetch_kvno()' to avoid materializing virtual
1751 * principals.
1753 * HDB readers should use this function rather than `db->hdb_fetch_kvno()'
1754 * unless they only want to see concrete principals and not bother generating
1755 * any virtual keys.
1757 * @param context Context
1758 * @param db HDB
1759 * @param principal Principal name
1760 * @param flags Fetch flags
1761 * @param t For virtual keys, use this as the point in time (use zero to mean "now")
1762 * @param etype Key enctype (use KRB5_ENCTYPE_NULL to mean "preferred")
1763 * @param kvno Key version number (use zero to mean "current")
1764 * @param h Output HDB entry
1766 * @return Zero or HDB_ERR_WRONG_REALM on success, an error code otherwise.
1768 krb5_error_code
1769 hdb_fetch_kvno(krb5_context context,
1770 HDB *db,
1771 krb5_const_principal principal,
1772 unsigned int flags,
1773 krb5_timestamp t,
1774 krb5int32 etype,
1775 krb5uint32 kvno,
1776 hdb_entry *h)
1778 krb5_error_code ret;
1779 krb5_timestamp now;
1781 krb5_timeofday(context, &now);
1783 flags |= kvno ? HDB_F_KVNO_SPECIFIED : 0; /* XXX is this needed */
1784 ret = fetch_it(context, db, principal, flags, t ? t : now, etype, kvno, h);
1785 if (ret == 0 && t == 0 && h->flags.virtual &&
1786 h->pw_end && h->pw_end[0] < now) {
1788 * This shouldn't happen!
1790 * Do not allow h->pw_end[0] to be in the past for virtual principals
1791 * outside testing. This is just to prevent the AS/TGS from failing.
1793 h->pw_end[0] = now + 3600;
1795 if (ret == HDB_ERR_NOENTRY)
1796 krb5_set_error_message(context, ret, "no such entry found in hdb");
1797 return ret;
1800 size_t ASN1CALL
1801 length_hdb_keyset(HDB_keyset *data)
1803 return length_HDB_keyset(data);
1806 size_t ASN1CALL
1807 length_hdb_entry(HDB_entry *data)
1809 return length_HDB_entry(data);
1812 size_t ASN1CALL
1813 length_hdb_entry_alias(HDB_entry_alias *data)
1815 return length_HDB_entry_alias(data);
1818 void ASN1CALL
1819 free_hdb_keyset(HDB_keyset *data)
1821 free_HDB_keyset(data);
1824 void ASN1CALL
1825 free_hdb_entry(HDB_entry *data)
1827 free_HDB_entry(data);
1830 void ASN1CALL
1831 free_hdb_entry_alias(HDB_entry_alias *data)
1833 free_HDB_entry_alias(data);
1836 size_t ASN1CALL
1837 copy_hdb_keyset(const HDB_keyset *from, HDB_keyset *to)
1839 return copy_HDB_keyset(from, to);
1842 size_t ASN1CALL
1843 copy_hdb_entry(const HDB_entry *from, HDB_entry *to)
1845 return copy_HDB_entry(from, to);
1848 size_t ASN1CALL
1849 copy_hdb_entry_alias(const HDB_entry_alias *from, HDB_entry_alias *to)
1851 return copy_HDB_entry_alias(from, to);
1854 int ASN1CALL
1855 decode_hdb_keyset(const unsigned char *p,
1856 size_t len,
1857 HDB_keyset *data,
1858 size_t *size)
1860 return decode_HDB_keyset(p, len, data, size);
1863 int ASN1CALL
1864 decode_hdb_entry(const unsigned char *p,
1865 size_t len,
1866 HDB_entry *data,
1867 size_t *size)
1869 return decode_HDB_entry(p, len, data, size);
1872 int ASN1CALL
1873 decode_hdb_entry_alias(const unsigned char *p,
1874 size_t len,
1875 HDB_entry_alias *data,
1876 size_t *size)
1878 return decode_HDB_entry_alias(p, len, data, size);
1881 int ASN1CALL
1882 encode_hdb_keyset(unsigned char *p,
1883 size_t len,
1884 const HDB_keyset *data,
1885 size_t *size)
1887 return encode_HDB_keyset(p, len, data, size);
1890 int ASN1CALL
1891 encode_hdb_entry(unsigned char *p,
1892 size_t len,
1893 const HDB_entry *data,
1894 size_t *size)
1896 return encode_HDB_entry(p, len, data, size);
1899 int ASN1CALL
1900 encode_hdb_entry_alias(unsigned char *p,
1901 size_t len,
1902 const HDB_entry_alias *data,
1903 size_t *size)
1905 return encode_HDB_entry_alias(p, len, data, size);