kdc: move more name canonicalization logic to KDC

Enterprise principal client names in AS-REQs should always be canonicalized
irrespective of the setting the canonicalize KDC option. Perform this check in
the KDC rather than HDB.

Do not set the HDB_F_GET_KRBTGT flag unless the client actually requested a TGS
principal.
This commit is contained in:
Luke Howard
2019-01-05 15:36:50 +11:00
parent c6232299c3
commit 1b7e196e66
2 changed files with 25 additions and 14 deletions

View File

@@ -1654,7 +1654,7 @@ _kdc_as_rep(kdc_request_t r,
krb5_error_code ret = 0; krb5_error_code ret = 0;
Key *skey; Key *skey;
int found_pa = 0; int found_pa = 0;
int i, flags = HDB_F_FOR_AS_REQ; int i, cflags, sflags;
METHOD_DATA error_method; METHOD_DATA error_method;
const PA_DATA *pa; const PA_DATA *pa;
@@ -1674,9 +1674,6 @@ _kdc_as_rep(kdc_request_t r,
b = &req->req_body; b = &req->req_body;
f = b->kdc_options; f = b->kdc_options;
if (f.canonicalize)
flags |= HDB_F_CANON;
if(b->sname == NULL){ if(b->sname == NULL){
ret = KRB5KRB_ERR_GENERIC; ret = KRB5KRB_ERR_GENERIC;
_kdc_set_e_text(r, "No server in request"); _kdc_set_e_text(r, "No server in request");
@@ -1715,6 +1712,19 @@ _kdc_as_rep(kdc_request_t r,
kdc_log(context, config, 0, "AS-REQ %s from %s for %s", kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
r->client_name, from, r->server_name); r->client_name, from, r->server_name);
/* Client enterprise principal names are always canonicalized */
cflags = HDB_F_FOR_AS_REQ | HDB_F_GET_CLIENT;
if (f.canonicalize ||
r->client_princ->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL)
cflags |= HDB_F_CANON;
sflags = HDB_F_FOR_AS_REQ | HDB_F_GET_SERVER;
if (f.canonicalize)
sflags |= HDB_F_CANON;
/* Only set HDB_F_GET_KRBTGT if we are resolving a TGS */
if (krb5_principal_is_krbtgt(context, r->server_princ))
sflags |= HDB_F_GET_KRBTGT;
/* /*
* *
*/ */
@@ -1737,9 +1747,8 @@ _kdc_as_rep(kdc_request_t r,
* *
*/ */
ret = _kdc_db_fetch(context, config, r->client_princ, ret = _kdc_db_fetch(context, config, r->client_princ, cflags,
HDB_F_GET_CLIENT | flags, NULL, NULL, &r->clientdb, &r->client);
&r->clientdb, &r->client);
if(ret == HDB_ERR_NOT_FOUND_HERE) { if(ret == HDB_ERR_NOT_FOUND_HERE) {
kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy", kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
r->client_name); r->client_name);
@@ -1776,8 +1785,7 @@ _kdc_as_rep(kdc_request_t r,
ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
goto out; goto out;
} }
ret = _kdc_db_fetch(context, config, r->server_princ, ret = _kdc_db_fetch(context, config, r->server_princ, sflags,
HDB_F_GET_SERVER|HDB_F_GET_KRBTGT | flags,
NULL, NULL, &r->server); NULL, NULL, &r->server);
if(ret == HDB_ERR_NOT_FOUND_HERE) { if(ret == HDB_ERR_NOT_FOUND_HERE) {
kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy",
@@ -1953,16 +1961,18 @@ _kdc_as_rep(kdc_request_t r,
rep.pvno = 5; rep.pvno = 5;
rep.msg_type = krb_as_rep; rep.msg_type = krb_as_rep;
if (r->client->entry.flags.force_canonicalize)
cflags |= HDB_F_CANON;
if (_kdc_is_anonymous(context, r->client_princ)) { if (_kdc_is_anonymous(context, r->client_princ)) {
Realm anon_realm=KRB5_ANON_REALM; Realm anon_realm=KRB5_ANON_REALM;
ret = copy_Realm(&anon_realm, &rep.crealm); ret = copy_Realm(&anon_realm, &rep.crealm);
} else if (f.canonicalize || r->client->entry.flags.force_canonicalize) } else if (cflags & HDB_F_CANON)
ret = copy_Realm(&r->client->entry.principal->realm, &rep.crealm); ret = copy_Realm(&r->client->entry.principal->realm, &rep.crealm);
else else
ret = copy_Realm(&r->client_princ->realm, &rep.crealm); ret = copy_Realm(&r->client_princ->realm, &rep.crealm);
if (ret) if (ret)
goto out; goto out;
if (f.canonicalize || r->client->entry.flags.force_canonicalize) if (cflags & HDB_F_CANON)
ret = _krb5_principal2principalname(&rep.cname, r->client->entry.principal); ret = _krb5_principal2principalname(&rep.cname, r->client->entry.principal);
else else
ret = _krb5_principal2principalname(&rep.cname, r->client_princ); ret = _krb5_principal2principalname(&rep.cname, r->client_princ);
@@ -1970,13 +1980,15 @@ _kdc_as_rep(kdc_request_t r,
goto out; goto out;
rep.ticket.tkt_vno = 5; rep.ticket.tkt_vno = 5;
if (f.canonicalize || r->server->entry.flags.force_canonicalize) if (r->server->entry.flags.force_canonicalize)
sflags |= HDB_F_CANON;
if (sflags & HDB_F_CANON)
ret = copy_Realm(&r->server->entry.principal->realm, &rep.ticket.realm); ret = copy_Realm(&r->server->entry.principal->realm, &rep.ticket.realm);
else else
ret = copy_Realm(&r->server_princ->realm, &rep.ticket.realm); ret = copy_Realm(&r->server_princ->realm, &rep.ticket.realm);
if (ret) if (ret)
goto out; goto out;
if (f.canonicalize || r->server->entry.flags.force_canonicalize) if (sflags & HDB_F_CANON)
_krb5_principal2principalname(&rep.ticket.sname, _krb5_principal2principalname(&rep.ticket.sname,
r->server->entry.principal); r->server->entry.principal);
else else

View File

@@ -119,7 +119,6 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
if (ret) if (ret)
return ret; return ret;
principal = enterprise_principal; principal = enterprise_principal;
flags |= HDB_F_CANON; /* enterprise implies canonicalization */
} }
hdb_principal2key(context, principal, &key); hdb_principal2key(context, principal, &key);