hdb: dereference principal aliases in all KDC lookups (#452)

e11abf41 added support in libhdb for always dereferencing principal aliases
during an AS-REQ (where dereferencing refers to enabling alias lookups, and
rewriting the returned entry with the alias name unless canonicalization was
enabled).

Due to the KDC setting HDB_F_FOR_AS_REQ for all lookups from the AS, this
allowed aliases on the TGS itself to be dereferenced during an AS-REQ; however,
on presenting the TGT, the TGS would fail to resolve. Creating an explicit TGS
principal for the aliased realm would work (at least prior to c555ed6a), but
this could be confusing to deploy.

This commit changes enables alias dereferencing when HDB_F_GET_ANY is set,
which essentially means dereference whenever the request is coming from the KDC
(as opposed to, say, kadmin).

We also backout c555ed6a, which changed the TGS to always canonicalize the
server realm, as this breaks serving multiple realms from a single KDC, where
server principals in different realms share a single canonical entry.
HDB_F_CANON is now passed to the backend as a hint only, and per RFC 6806 the
principal name is never changed in TGS replies. (However, for Samba interop,
backends can override this by setting the force-canonicalize HDB flag.)
This commit is contained in:
Luke Howard
2019-01-05 12:36:28 +11:00
parent c6d00f2502
commit 6bb8eaca20
3 changed files with 22 additions and 13 deletions

View File

@@ -1559,10 +1559,14 @@ tgs_build_reply(krb5_context context,
s = b->sname; s = b->sname;
r = b->realm; r = b->realm;
/* /*
* Always to do CANON, see comment below about returned server principal (rsp). * The canonicalize KDC option is passed as a hint to the backend, but
* can typically be ignored. Per RFC 6806, names are not canonicalized
* in response to a TGS request (although we make an exception, see
* force-canonicalize below).
*/ */
flags |= HDB_F_CANON; if (b->kdc_options.canonicalize)
flags |= HDB_F_CANON;
if(b->kdc_options.enc_tkt_in_skey){ if(b->kdc_options.enc_tkt_in_skey){
Ticket *t; Ticket *t;
@@ -1749,18 +1753,18 @@ server_lookup:
goto out; goto out;
} }
/* the name returned to the client depend on what was asked for, /*
* return canonical name if kdc_options.canonicalize was set, the * RFC 6806 notes that names MUST NOT be changed in the response to
* client wants the true name of the principal, if not it just * a TGS request. Hence we ignore the setting of the canonicalize
* wants the name its asked for. * KDC option. However, for legacy interoperability we do allow the
* backend to override this by setting the force-canonicalize HDB
* flag in the server entry.
*/ */
if (server->entry.flags.force_canonicalize)
if (b->kdc_options.canonicalize)
rsp = server->entry.principal; rsp = server->entry.principal;
else else
rsp = sp; rsp = sp;
/* /*
* Select enctype, return key and kvno. * Select enctype, return key and kvno.
*/ */

View File

@@ -130,7 +130,8 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
if(ret) if(ret)
return ret; return ret;
ret = hdb_value2entry(context, &value, &entry->entry); ret = hdb_value2entry(context, &value, &entry->entry);
if (ret == ASN1_BAD_ID && (flags & (HDB_F_CANON|HDB_F_FOR_AS_REQ)) == 0) { /* HDB_F_GET_ANY indicates request originated from KDC (not kadmin) */
if (ret == ASN1_BAD_ID && (flags & (HDB_F_CANON|HDB_F_GET_ANY)) == 0) {
krb5_data_free(&value); krb5_data_free(&value);
return HDB_ERR_NOENTRY; return HDB_ERR_NOENTRY;
} else if (ret == ASN1_BAD_ID) { } else if (ret == ASN1_BAD_ID) {
@@ -155,7 +156,7 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
return ret; return ret;
} }
if ((flags & HDB_F_FOR_AS_REQ) && (flags & HDB_F_CANON) == 0) { if ((flags & HDB_F_GET_ANY) && (flags & HDB_F_CANON) == 0) {
krb5_principal tmp; krb5_principal tmp;
/* "hard" alias: return the principal the client asked for */ /* "hard" alias: return the principal the client asked for */
@@ -333,7 +334,8 @@ _hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
krb5_data key, value; krb5_data key, value;
int code; int code;
if (entry->entry.flags.do_not_store) if (entry->entry.flags.do_not_store ||
entry->entry.flags.force_canonicalize)
return HDB_ERR_MISUSE; return HDB_ERR_MISUSE;
/* check if new aliases already is used */ /* check if new aliases already is used */
code = hdb_check_aliases(context, db, entry); code = hdb_check_aliases(context, db, entry);

View File

@@ -49,6 +49,9 @@ HDBFlags ::= BIT STRING {
locked-out(17), -- Account is locked out, locked-out(17), -- Account is locked out,
-- authentication will be denied -- authentication will be denied
require-pwchange(18), -- require a passwd change require-pwchange(18), -- require a passwd change
force-canonicalize(30), -- force the KDC to return the canonical
-- principal irrespective of the setting
-- of the canonicalize KDC option
do-not-store(31) -- Not to be modified and stored in HDB do-not-store(31) -- Not to be modified and stored in HDB
} }