From 6bb8eaca2052967bbda194e2c2bc0622b18a4d2f Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sat, 5 Jan 2019 12:36:28 +1100 Subject: [PATCH] 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.) --- kdc/krb5tgs.c | 24 ++++++++++++++---------- lib/hdb/common.c | 8 +++++--- lib/hdb/hdb.asn1 | 3 +++ 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/kdc/krb5tgs.c b/kdc/krb5tgs.c index 4bbfcc60a..aa23cbcd2 100644 --- a/kdc/krb5tgs.c +++ b/kdc/krb5tgs.c @@ -1559,10 +1559,14 @@ tgs_build_reply(krb5_context context, s = b->sname; 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){ Ticket *t; @@ -1749,18 +1753,18 @@ server_lookup: goto out; } - /* the name returned to the client depend on what was asked for, - * return canonical name if kdc_options.canonicalize was set, the - * client wants the true name of the principal, if not it just - * wants the name its asked for. + /* + * RFC 6806 notes that names MUST NOT be changed in the response to + * a TGS request. Hence we ignore the setting of the canonicalize + * 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 (b->kdc_options.canonicalize) + if (server->entry.flags.force_canonicalize) rsp = server->entry.principal; else rsp = sp; - /* * Select enctype, return key and kvno. */ diff --git a/lib/hdb/common.c b/lib/hdb/common.c index 3b9f09f86..f389f8883 100644 --- a/lib/hdb/common.c +++ b/lib/hdb/common.c @@ -130,7 +130,8 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, if(ret) return ret; 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); return HDB_ERR_NOENTRY; } else if (ret == ASN1_BAD_ID) { @@ -155,7 +156,7 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, 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; /* "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; 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; /* check if new aliases already is used */ code = hdb_check_aliases(context, db, entry); diff --git a/lib/hdb/hdb.asn1 b/lib/hdb/hdb.asn1 index 333ccb064..c0024d4b4 100644 --- a/lib/hdb/hdb.asn1 +++ b/lib/hdb/hdb.asn1 @@ -49,6 +49,9 @@ HDBFlags ::= BIT STRING { locked-out(17), -- Account is locked out, -- authentication will be denied 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 }