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 }