2 * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
34 #include "krb5_locl.h"
38 hdb_principal2key(krb5_context context
, krb5_const_principal p
, krb5_data
*key
)
44 ret
= copy_Principal(p
, &new);
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");
57 hdb_key2principal(krb5_context context
, krb5_data
*key
, krb5_principal p
)
59 return decode_Principal(key
->data
, key
->length
, p
, NULL
);
63 hdb_entry2value(krb5_context context
, const hdb_entry
*ent
, krb5_data
*value
)
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");
75 hdb_value2entry(krb5_context context
, krb5_data
*value
, hdb_entry
*ent
)
77 return decode_HDB_entry(value
->data
, value
->length
, ent
, NULL
);
81 hdb_entry_alias2value(krb5_context context
,
82 const hdb_entry_alias
*alias
,
88 ASN1_MALLOC_ENCODE(HDB_entry_alias
, value
->data
, value
->length
,
90 if (ret
== 0 && value
->length
!= len
)
91 krb5_abortx(context
, "internal asn.1 encoder error");
96 hdb_value2entry_alias(krb5_context context
, krb5_data
*value
,
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
108 static krb5_error_code
109 add_default_salts(krb5_context context
, HDB
*db
, hdb_entry
*entry
)
115 ret
= krb5_get_pw_salt(context
, entry
->principal
, &pwsalt
);
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
))
126 key
->salt
= calloc(1, sizeof(*key
->salt
));
127 if (key
->salt
== NULL
) {
128 ret
= krb5_enomem(context
);
132 key
->salt
->type
= KRB5_PADATA_PW_SALT
;
134 ret
= krb5_data_copy(&key
->salt
->salt
,
135 pwsalt
.saltvalue
.data
,
136 pwsalt
.saltvalue
.length
);
141 krb5_free_salt(context
, pwsalt
);
146 static krb5_error_code
147 fetch_entry_or_alias(krb5_context context
,
149 krb5_const_principal principal
,
153 HDB_EntryOrAlias eoa
;
154 krb5_principal enterprise_principal
= NULL
;
155 krb5_data 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
);
170 ret
= krb5_parse_name(context
, principal
->name
.name_string
.val
[0],
171 &enterprise_principal
);
174 principal
= enterprise_principal
;
177 ret
= hdb_principal2key(context
, principal
, &key
);
179 ret
= db
->hdb__get(context
, db
, key
, &value
);
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
;
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
);
189 krb5_data_free(&value
);
190 ret
= db
->hdb__get(context
, db
, key
, &value
);
193 /* No alias chaining */
194 ret
= hdb_value2entry(context
, &value
, entry
);
195 krb5_free_principal(context
, eoa
.u
.alias
.principal
);
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;
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
;
219 krb5_free_principal(context
, enterprise_principal
);
220 krb5_data_free(&value
);
221 krb5_data_free(&key
);
222 principal
= enterprise_principal
= NULL
;
227 * We have only one type of aliases in our HDB entries, but we really need two:
230 * Hard aliases should be treated as if they were distinct principals with the
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.
242 is_soft_alias_p(krb5_context context
,
243 krb5_const_principal principal
,
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),
253 strcmp(krb5_principal_get_comp_string(context
, h
->principal
, 2),
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)
267 /* All other cases are hard aliases */
272 _hdb_fetch_kvno(krb5_context context
, HDB
*db
, krb5_const_principal principal
,
273 unsigned flags
, krb5_kvno kvno
, hdb_entry
*entry
)
276 int soft_aliased
= 0;
279 ret
= fetch_entry_or_alias(context
, db
, principal
, flags
, entry
);
283 if ((flags
& HDB_F_DECRYPT
) && (flags
& HDB_F_ALL_KVNOS
)) {
284 /* Decrypt the current keys */
285 ret
= hdb_unseal_keys(context
, db
, entry
);
287 hdb_free_entry(context
, db
, entry
);
290 /* Decrypt the key history too */
291 ret
= hdb_unseal_keys_kvno(context
, db
, 0, flags
, entry
);
293 hdb_free_entry(context
, db
, entry
);
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
);
301 hdb_free_entry(context
, db
, entry
);
305 if ((flags
& HDB_F_ALL_KVNOS
))
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
);
313 hdb_free_entry(context
, db
, entry
);
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
);
327 hdb_free_entry(context
, db
, entry
);
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
))
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
348 * Except, we allow for disabling this for same-realm aliases, mainly
352 krb5_config_get_bool_default(context
, NULL
, FALSE
, "hdb",
353 "same_realm_aliases_are_soft", NULL
))
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
);
361 hdb_free_entry(context
, db
, entry
);
368 /* Same realm -> not a referral, therefore this is a hard alias */
371 /* Soft alias to the same realm?! No. */
372 hdb_free_entry(context
, db
, entry
);
373 return HDB_ERR_NOENTRY
;
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
;
391 code
= db
->hdb__get(context
, db
, *key
, &value
);
392 if (code
== HDB_ERR_NOENTRY
)
397 code
= hdb_value2entry(context
, &value
, &oldentry
);
398 krb5_data_free(&value
);
402 code
= hdb_entry_get_aliases(&oldentry
, &aliases
);
403 if (code
|| aliases
== NULL
) {
404 free_HDB_entry(&oldentry
);
407 for (i
= 0; i
< aliases
->aliases
.len
; i
++) {
410 code
= hdb_principal2key(context
, &aliases
->aliases
.val
[i
], &akey
);
412 code
= db
->hdb__del(context
, db
, akey
);
413 krb5_data_free(&akey
);
414 if (code
== HDB_ERR_NOENTRY
)
418 free_HDB_entry(&oldentry
);
422 free_HDB_entry(&oldentry
);
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
;
435 code
= hdb_entry_get_aliases(entry
, &aliases
);
436 if (code
|| aliases
== NULL
)
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
);
447 code
= hdb_principal2key(context
, &aliases
->aliases
.val
[i
], &key
);
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.
458 krb5_data_free(&value
);
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
;
475 memset(&eoa
, 0, sizeof(eoa
));
476 krb5_data_zero(&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
);
483 ret
= db
->hdb__get(context
, db
, akey
, &value
);
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
)
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
,
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 */
501 free_HDB_EntryOrAlias(&eoa
);
502 krb5_data_free(&value
);
503 krb5_data_free(&akey
);
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.
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
;
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
;
538 if (e
->etypes
!= NULL
) {
539 free(e
->etypes
->val
);
542 } else if ((e
->etypes
= calloc(1, sizeof(e
->etypes
[0]))) == NULL
) {
543 ret
= krb5_enomem(context
);
546 (e
->etypes
->val
= calloc(netypes
, sizeof(e
->etypes
->val
[0]))) == NULL
)
547 ret
= krb5_enomem(context
);
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
;
558 for (k
= 0; i
== 0 && k
< base_keys
->len
; k
++) {
559 if (!base_keys
->val
[k
].keys
.len
)
561 for (; i
< base_keys
->val
[k
].keys
.len
; i
++)
562 e
->etypes
->val
[i
] = base_keys
->val
[k
].keys
.val
[i
].key
.keytype
;
568 _hdb_store(krb5_context context
, HDB
*db
, unsigned flags
, hdb_entry
*entry
)
570 krb5_data key
, value
;
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
);
581 if ((flags
& HDB_F_PRECHECK
) && (flags
& HDB_F_REPLACE
))
584 if ((flags
& HDB_F_PRECHECK
)) {
585 code
= hdb_principal2key(context
, entry
->principal
, &key
);
588 code
= db
->hdb__get(context
, db
, key
, &value
);
589 krb5_data_free(&key
);
591 krb5_data_free(&value
);
592 if (code
== HDB_ERR_NOENTRY
)
594 return code
? code
: HDB_ERR_EXISTS
;
597 if ((entry
->etypes
== NULL
|| entry
->etypes
->len
== 0) &&
598 (code
= hdb_derive_etypes(context
, entry
, NULL
)))
601 if (entry
->generation
== NULL
) {
603 entry
->generation
= malloc(sizeof(*entry
->generation
));
604 if(entry
->generation
== NULL
) {
605 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
608 gettimeofday(&t
, NULL
);
609 entry
->generation
->time
= t
.tv_sec
;
610 entry
->generation
->usec
= t
.tv_usec
;
611 entry
->generation
->gen
= 0;
613 entry
->generation
->gen
++;
615 code
= hdb_seal_keys(context
, db
, entry
);
619 code
= hdb_principal2key(context
, entry
->principal
, &key
);
624 code
= hdb_remove_aliases(context
, db
, &key
);
626 krb5_data_free(&key
);
629 code
= hdb_entry2value(context
, entry
, &value
);
631 code
= db
->hdb__put(context
, db
, flags
& HDB_F_REPLACE
, key
, value
);
632 krb5_data_free(&value
);
633 krb5_data_free(&key
);
637 code
= hdb_add_aliases(context
, db
, flags
, entry
);
643 _hdb_remove(krb5_context context
, HDB
*db
,
644 unsigned flags
, krb5_const_principal principal
)
646 krb5_data key
, value
;
647 HDB_EntryOrAlias eoa
;
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
);
662 code
= db
->hdb__get(context
, db
, key
, &value
);
664 code
= decode_HDB_EntryOrAlias(value
.data
, value
.length
, &eoa
, NULL
);
665 krb5_data_free(&value
);
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
);
681 code
= hdb_remove_aliases(context
, db
, &key
);
683 code
= db
->hdb__del(context
, db
, key
);
684 krb5_data_free(&key
);
688 /* PRF+(K_base, pad, keylen(etype)) */
689 static krb5_error_code
690 derive_Key1(krb5_context context
,
697 krb5_crypto crypto
= NULL
;
704 ret
= krb5_enctype_keysize(context
, base
->keytype
, &len
);
706 ret
= krb5_crypto_init(context
, base
, 0, &crypto
);
708 ret
= krb5_crypto_prfplus(context
, crypto
, pad
, len
, &out
);
710 krb5_crypto_destroy(context
, crypto
);
712 ret
= krb5_random_to_key(context
, etype
, out
.data
, out
.length
, nk
);
713 krb5_data_free(&out
);
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
,
727 krb5_error_code ret
= 0;
728 EncryptionKey intermediate
;
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;
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
);
747 base
= &intermediate
;
748 } /* else `base' is already an intermediate key for the desired princ */
750 /* Derive final key for `kvno' from intermediate key */
753 pad
.length
= sizeof(kvno
);
755 ret
= derive_Key1(context
, &pad
, base
, etype
, &nk
->key
);
756 free_EncryptionKey(&intermediate
);
761 * PRF+(PRF+(K_base, princ, keylen(etype)), kvno, keylen(etype)) for one
764 static krb5_error_code
765 derive_Keys(krb5_context context
,
773 krb5_error_code ret
= 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
)
787 ret
= derive_Key(context
, princ
, kvno
, &base
->val
[0].key
,
788 base
->val
[i
].key
.keytype
, &nk
);
791 ret
= add_Keys(dk
, &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...
810 /* Helper for derive_keys_for_kr() */
811 static krb5_error_code
812 derive_keyset(krb5_context context
,
813 const Keys
*base_keys
,
817 KerberosTime set_time
, /* "now" */
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
,
833 HDB_Ext_KeySet
*base_keys
,
834 int is_current_keyset
,
835 int rotation_period_offset
,
838 krb5uint32 kvno_wanted
,
840 struct KeyRotation
*krp
)
844 KerberosTime set_time
, n
;
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
896 if (left
> krp
->period
>> 2)
897 h
->pw_end
[0] = set_time
+ krp
->period
- (krp
->period
>> 2);
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)))
923 for (i
= 0; i
< base_keys
->len
; i
++) {
924 if (base_keys
->val
[i
].kvno
== krp
->base_key_kvno
)
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
);
938 ret
= derive_keyset(context
, &base_keys
->val
[i
].keys
, princ
, etype
, kvno
,
941 ret
= hdb_install_keyset(context
, h
, is_current_keyset
, &dks
);
943 free_HDB_keyset(&dks
);
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
,
951 HDB_Ext_KeySet
*base_keys
,
955 krb5uint32 kvno_wanted
,
957 struct KeyRotation
*krp
,
958 KerberosTime future_epoch
)
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
))
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.
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)
996 ret
= derive_keys_for_kr(context
, h
, base_keys
, 0, 1, princ
, etype
,
997 kvno_wanted
, t
, krp
);
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).
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
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.
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
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.
1049 * - KR metadata is sane because sanity is checked for when storing HDB
1051 * - KRs are sorted by epoch in descending order; KR #0's epoch is the most
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
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
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
1074 * Note that the last time period in any older KR can be partial.
1078 * .......|--+--+...+--|---+---+---+...+--|----+...
1079 * T20 T10 T11 RT12 T1n T01
1081 * | | | T22 T2n | | ^
1083 * princ | | epoch of | epoch of
1084 * did | | middle KR | newest epoch
1086 * exist! | start of Note that T1n
1087 * | second kvno is shown as shorter
1088 * | in 1st epoch than preceding periods
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
,
1108 krb5_const_principal princ
,
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
;
1122 if (!h_is_namespace
&& !h
->flags
.virtual_keys
)
1124 h
->flags
.virtual = 1;
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
);
1136 ret
= copy_HDB_Ext_KeyRotation(ckr
, &kr
);
1139 /* Get the base keys from the entry, and remove them */
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
);
1156 /* The principal name will be used in key derivation and error messages */
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
);
1165 current_kr
= future_kr
= past_kr
= kr
.len
;
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
1175 * ...|---------|--------|------>
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
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
;
1203 if (!kr
.val
[i
].period
) {
1204 future_kr
= past_kr
= kr
.len
;
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
)
1220 /* This KR is in the future of `t', a candidate for next KR */
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
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
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
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
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
);
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
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
1325 * Naturally, this applies only to concrete principals with concrete keys.
1327 static krb5_error_code
1328 pick_kvno(krb5_context context
,
1336 HDB_Ext_KeySet keys
;
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)
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
);
1355 /* Assume the current keyset is the best to start with */
1356 (void) hdb_entry_get_pw_change_time(h
, ¤t
);
1357 if (current
== 0 && h
->modified_by
)
1358 current
= h
->modified_by
->time
;
1360 current
= h
->created_by
.time
;
1362 /* Current keyset starts out as best */
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
)
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)
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
))
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
)
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
,
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
;
1433 if (comp0
== NULL
|| comp1
== NULL
)
1435 if (strcmp(comp0
, "krbtgt") == 0)
1438 for (i
= 0; svcs
&& svcs
[i
]; i
++) {
1439 if (strcmp(comp0
, svcs
[i
]) == 0) {
1444 if (!svcs
|| !svcs
[i
])
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
);
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 */
1461 is_namespace_princ_p(krb5_context context
,
1462 krb5_const_principal princ
)
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;
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
,
1480 const char *ns_host_part
, *wanted_host_part
, *found_host_part
;
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
;
1507 krb5_principal_get_comp_string(context
, found_ns_princ
, 3);
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
1519 static krb5_error_code
1520 fix_princ_name(krb5_context context
,
1521 krb5_const_principal princ
,
1522 krb5_const_principal nsprinc
,
1525 krb5_error_code ret
= 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
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 */
1578 ret
= rewrite_hostname(context
, princ
, nsprinc
, h
->principal
, &s
);
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
,
1593 /* Wrapper around db->hdb_fetch_kvno() that implements virtual princs/keys */
1594 static krb5_error_code
1595 fetch_it(krb5_context context
,
1597 krb5_const_principal princ
,
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);
1610 size_t mindots
= db
->virtual_hostbased_princ_ndots
;
1611 size_t maxdots
= db
->virtual_hostbased_princ_maxdots
;
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) {
1622 if ((host
= strdup(comp1
)) == NULL
)
1623 return krb5_enomem(context
);
1625 /* Strip out any :port */
1626 htmp
= strchr(host
, ':');
1628 if (strchr(htmp
+ 1, ':')) {
1629 /* Extra ':'s? No virtualization for you! */
1636 /* Count dots in `host' */
1637 for (hdots
= 0, htmp
= host
; htmp
&& *htmp
; htmp
++)
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
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
||
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 */
1691 ret
= HDB_ERR_NOENTRY
;
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 */
1704 ret2
= krb5_principal_set_comp_string(context
, nsprinc
, 3, tmp
);
1709 /* Strip off left-most label for the next go-around */
1710 if ((tmp
= strchr(tmp
, '.')))
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 */
1728 ret
= derive_keys(context
, flags
, princ
, !!nsprinc
, t
, etype
, kvno
,
1730 /* Pick the best kvno for this principal at the given time */
1732 ret
= pick_kvno(context
, db
, flags
, t
, kvno
, ent
);
1738 if (ret
!= 0 && ret
!= HDB_ERR_WRONG_REALM
)
1739 hdb_free_entry(context
, db
, ent
);
1740 krb5_free_principal(context
, nsprinc
);
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
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
1757 * @param context Context
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.
1769 hdb_fetch_kvno(krb5_context context
,
1771 krb5_const_principal principal
,
1778 krb5_error_code ret
;
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");
1801 length_hdb_keyset(HDB_keyset
*data
)
1803 return length_HDB_keyset(data
);
1807 length_hdb_entry(HDB_entry
*data
)
1809 return length_HDB_entry(data
);
1813 length_hdb_entry_alias(HDB_entry_alias
*data
)
1815 return length_HDB_entry_alias(data
);
1819 free_hdb_keyset(HDB_keyset
*data
)
1821 free_HDB_keyset(data
);
1825 free_hdb_entry(HDB_entry
*data
)
1827 free_HDB_entry(data
);
1831 free_hdb_entry_alias(HDB_entry_alias
*data
)
1833 free_HDB_entry_alias(data
);
1837 copy_hdb_keyset(const HDB_keyset
*from
, HDB_keyset
*to
)
1839 return copy_HDB_keyset(from
, to
);
1843 copy_hdb_entry(const HDB_entry
*from
, HDB_entry
*to
)
1845 return copy_HDB_entry(from
, to
);
1849 copy_hdb_entry_alias(const HDB_entry_alias
*from
, HDB_entry_alias
*to
)
1851 return copy_HDB_entry_alias(from
, to
);
1855 decode_hdb_keyset(const unsigned char *p
,
1860 return decode_HDB_keyset(p
, len
, data
, size
);
1864 decode_hdb_entry(const unsigned char *p
,
1869 return decode_HDB_entry(p
, len
, data
, size
);
1873 decode_hdb_entry_alias(const unsigned char *p
,
1875 HDB_entry_alias
*data
,
1878 return decode_HDB_entry_alias(p
, len
, data
, size
);
1882 encode_hdb_keyset(unsigned char *p
,
1884 const HDB_keyset
*data
,
1887 return encode_HDB_keyset(p
, len
, data
, size
);
1891 encode_hdb_entry(unsigned char *p
,
1893 const HDB_entry
*data
,
1896 return encode_HDB_entry(p
, len
, data
, size
);
1900 encode_hdb_entry_alias(unsigned char *p
,
1902 const HDB_entry_alias
*data
,
1905 return encode_HDB_entry_alias(p
, len
, data
, size
);