kdc: use astgs_request_t for client/server name (TGS)

Store the client and server principal name from the TGT and request
(respectively) in the astgs_request_t rather than using local variables.
This commit is contained in:
Luke Howard
2022-01-10 12:50:37 +11:00
parent 2520c30b28
commit 40e4a4df09
4 changed files with 34 additions and 52 deletions

View File

@@ -49,7 +49,7 @@ static const char *kdc_plugin_deps[] = {
static struct heim_plugin_data kdc_plugin_data = { static struct heim_plugin_data kdc_plugin_data = {
"krb5", "krb5",
"kdc", "kdc",
KRB5_PLUGIN_KDC_VERSION_8, KRB5_PLUGIN_KDC_VERSION_9,
kdc_plugin_deps, kdc_plugin_deps,
kdc_get_instance kdc_get_instance
}; };

View File

@@ -87,10 +87,7 @@ typedef krb5_error_code
* If the function returns KRB5_PLUGIN_NO_HANDLE, the TGS will continue * If the function returns KRB5_PLUGIN_NO_HANDLE, the TGS will continue
* with its default referral handling. * with its default referral handling.
* *
* Note well: the current API contract requires the plugin to NOT free * Note well: the plugin should free priv->server_princ is replacing.
* priv->server_princ if replacing; the KDC will do this. This may change
* in a future release, be sure to consult this file whenever the plugin
* version changes.
*/ */
typedef krb5_error_code typedef krb5_error_code
@@ -118,7 +115,7 @@ typedef krb5_error_code
* Plugins should carefully check API contract notes for changes * Plugins should carefully check API contract notes for changes
* between plugin API versions. * between plugin API versions.
*/ */
#define KRB5_PLUGIN_KDC_VERSION_8 8 #define KRB5_PLUGIN_KDC_VERSION_9 9
typedef struct krb5plugin_kdc_ftable { typedef struct krb5plugin_kdc_ftable {
int minor_version; int minor_version;

View File

@@ -1355,7 +1355,7 @@ tgs_build_reply(astgs_request_t priv,
KDC_REQ_BODY *b = &priv->req.req_body; KDC_REQ_BODY *b = &priv->req.req_body;
const char *from = priv->from; const char *from = priv->from;
krb5_error_code ret, ret2; krb5_error_code ret, ret2;
krb5_principal cp = NULL, sp = NULL, rsp = NULL; krb5_principal rsp = NULL;
krb5_principal krbtgt_out_principal = NULL; krb5_principal krbtgt_out_principal = NULL;
krb5_principal user2user_princ = NULL; krb5_principal user2user_princ = NULL;
char *spn = NULL, *cpn = NULL, *krbtgt_out_n = NULL; char *spn = NULL, *cpn = NULL, *krbtgt_out_n = NULL;
@@ -1413,13 +1413,14 @@ tgs_build_reply(astgs_request_t priv,
goto out; goto out;
} }
_krb5_principalname2krb5_principal(context, &sp, *s, r); _krb5_principalname2krb5_principal(context, &priv->server_princ, *s, r);
ret = krb5_unparse_name(context, sp, &priv->sname); ret = krb5_unparse_name(context, priv->server_princ, &priv->sname);
if (ret) if (ret)
goto out; goto out;
spn = priv->sname; spn = priv->sname;
_krb5_principalname2krb5_principal(context, &cp, tgt->cname, tgt->crealm); _krb5_principalname2krb5_principal(context, &priv->client_princ,
ret = krb5_unparse_name(context, cp, &priv->cname); tgt->cname, tgt->crealm);
ret = krb5_unparse_name(context, priv->client_princ, &priv->cname);
if (ret) if (ret)
goto out; goto out;
cpn = priv->cname; cpn = priv->cname;
@@ -1440,11 +1441,10 @@ tgs_build_reply(astgs_request_t priv,
server_lookup: server_lookup:
priv->server = NULL; priv->server = NULL;
priv->server_princ = sp;
if (server) if (server)
_kdc_free_ent(context, server); _kdc_free_ent(context, server);
server = NULL; server = NULL;
ret = _kdc_db_fetch(context, config, sp, ret = _kdc_db_fetch(context, config, priv->server_princ,
HDB_F_GET_SERVER | HDB_F_DELAY_NEW_KEYS | flags, HDB_F_GET_SERVER | HDB_F_DELAY_NEW_KEYS | flags,
NULL, &serverdb, &server); NULL, &serverdb, &server);
priv->server = server; priv->server = server;
@@ -1464,15 +1464,15 @@ server_lookup:
"Returning a referral to realm %s for " "Returning a referral to realm %s for "
"server %s.", "server %s.",
ref_realm, spn); ref_realm, spn);
krb5_free_principal(context, sp); krb5_free_principal(context, priv->server_princ);
sp = NULL; priv->server_princ = NULL;
ret = krb5_make_principal(context, &sp, r, KRB5_TGS_NAME, ret = krb5_make_principal(context, &priv->server_princ, r, KRB5_TGS_NAME,
ref_realm, NULL); ref_realm, NULL);
if (ret) if (ret)
goto out; goto out;
free(priv->sname); free(priv->sname);
priv->sname = NULL; priv->sname = NULL;
ret = krb5_unparse_name(context, sp, &priv->sname); ret = krb5_unparse_name(context, priv->server_princ, &priv->sname);
if (ret) if (ret)
goto out; goto out;
spn = priv->sname; spn = priv->sname;
@@ -1486,22 +1486,15 @@ server_lookup:
priv->ret = ret; /* advise policy plugin of failure reason */ priv->ret = ret; /* advise policy plugin of failure reason */
ret2 = _kdc_referral_policy(priv); ret2 = _kdc_referral_policy(priv);
if (ret2 == 0) { if (ret2 == 0) {
heim_assert(priv->server_princ != sp,
"Referral policy plugin must update server principal");
krb5_free_principal(context, sp);
sp = priv->server_princ;
krb5_xfree(priv->sname); krb5_xfree(priv->sname);
priv->sname = NULL; priv->sname = NULL;
ret = krb5_unparse_name(context, sp, &priv->sname); ret = krb5_unparse_name(context, priv->server_princ, &priv->sname);
if (ret) if (ret)
goto out; goto out;
spn = priv->sname;
goto server_lookup; goto server_lookup;
} else if (ret2 != KRB5_PLUGIN_NO_HANDLE) { } else if (ret2 != KRB5_PLUGIN_NO_HANDLE) {
ret = ret2; ret = ret2;
} else if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) { } else if ((req_rlm = get_krbtgt_realm(&priv->server_princ->name)) != NULL) {
if (capath == NULL) { if (capath == NULL) {
/* With referalls, hierarchical capaths are always enabled */ /* With referalls, hierarchical capaths are always enabled */
ret2 = _krb5_find_capath(context, tgt->crealm, our_realm, ret2 = _krb5_find_capath(context, tgt->crealm, our_realm,
@@ -1526,31 +1519,31 @@ server_lookup:
goto out; goto out;
} }
krb5_free_principal(context, sp); krb5_free_principal(context, priv->server_princ);
sp = NULL; priv->server_princ = NULL;
krb5_make_principal(context, &sp, r, krb5_make_principal(context, &priv->server_princ, r,
KRB5_TGS_NAME, ref_realm, NULL); KRB5_TGS_NAME, ref_realm, NULL);
free(priv->sname); free(priv->sname);
priv->sname = NULL; priv->sname = NULL;
ret = krb5_unparse_name(context, sp, &priv->sname); ret = krb5_unparse_name(context, priv->server_princ, &priv->sname);
if (ret) if (ret)
goto out; goto out;
spn = priv->sname; spn = priv->sname;
goto server_lookup; goto server_lookup;
} }
} else if (need_referral(context, config, &b->kdc_options, sp, &realms)) { } else if (need_referral(context, config, &b->kdc_options, priv->server_princ, &realms)) {
if (strcmp(realms[0], sp->realm) != 0) { if (strcmp(realms[0], priv->server_princ->realm) != 0) {
kdc_log(context, config, 4, kdc_log(context, config, 4,
"Returning a referral to realm %s for " "Returning a referral to realm %s for "
"server %s that was not found", "server %s that was not found",
realms[0], spn); realms[0], spn);
krb5_free_principal(context, sp); krb5_free_principal(context, priv->server_princ);
sp = NULL; priv->server_princ = NULL;
krb5_make_principal(context, &sp, r, KRB5_TGS_NAME, krb5_make_principal(context, &priv->server_princ, r, KRB5_TGS_NAME,
realms[0], NULL); realms[0], NULL);
free(priv->sname); free(priv->sname);
priv->sname = NULL; priv->sname = NULL;
ret = krb5_unparse_name(context, sp, &priv->sname); ret = krb5_unparse_name(context, priv->server_princ, &priv->sname);
if (ret) { if (ret) {
krb5_free_host_realm(context, realms); krb5_free_host_realm(context, realms);
goto out; goto out;
@@ -1586,9 +1579,7 @@ server_lookup:
if (server->entry.flags.force_canonicalize) if (server->entry.flags.force_canonicalize)
rsp = server->entry.principal; rsp = server->entry.principal;
else else
rsp = sp; rsp = priv->server_princ;
priv->server_princ = sp;
/* /*
* Now refetch the primary krbtgt, and get the current kvno (the * Now refetch the primary krbtgt, and get the current kvno (the
@@ -1816,7 +1807,7 @@ server_lookup:
} else { } else {
Key *skey; Key *skey;
ret = _kdc_find_etype(priv, krb5_principal_is_krbtgt(context, sp) ret = _kdc_find_etype(priv, krb5_principal_is_krbtgt(context, priv->server_princ)
? KFE_IS_TGS : 0, ? KFE_IS_TGS : 0,
b->etype.val, b->etype.len, &etype, NULL, b->etype.val, b->etype.len, &etype, NULL,
NULL); NULL);
@@ -1894,15 +1885,15 @@ server_lookup:
if (_kdc_synthetic_princ_used_p(context, priv->ticket)) if (_kdc_synthetic_princ_used_p(context, priv->ticket))
flags |= HDB_F_SYNTHETIC_OK; flags |= HDB_F_SYNTHETIC_OK;
ret = _kdc_db_fetch_client(context, config, flags, cp, cpn, our_realm, ret = _kdc_db_fetch_client(context, config, flags, priv->client_princ,
&clientdb, &client); cpn, our_realm, &clientdb, &client);
if (ret) if (ret)
goto out; goto out;
flags &= ~HDB_F_SYNTHETIC_OK; flags &= ~HDB_F_SYNTHETIC_OK;
priv->client = client; priv->client = client;
priv->clientdb = clientdb; priv->clientdb = clientdb;
ret = _kdc_check_pac(context, config, cp, NULL, ret = _kdc_check_pac(context, config, priv->client_princ, NULL,
priv->client, priv->server, priv->client, priv->server,
priv->krbtgt, priv->krbtgt, priv->krbtgt, priv->krbtgt,
&priv->ticket_key->key, &priv->ticket_key->key, tgt, &priv->ticket_key->key, &priv->ticket_key->key, tgt,
@@ -1922,9 +1913,6 @@ server_lookup:
* Process request * Process request
*/ */
/* by default the tgt principal matches the client principal */
priv->client_princ = cp;
/* /*
* Services for User: protocol transition and constrained delegation * Services for User: protocol transition and constrained delegation
*/ */
@@ -2048,7 +2036,7 @@ server_lookup:
server, server,
rsp, rsp,
client, client,
cp, priv->client_princ,
tgt_realm, tgt_realm,
rodc_id, rodc_id,
add_ticket_sig); add_ticket_sig);
@@ -2065,9 +2053,6 @@ out:
_kdc_free_ent(context, user2user_krbtgt); _kdc_free_ent(context, user2user_krbtgt);
krb5_free_principal(context, user2user_princ); krb5_free_principal(context, user2user_princ);
if (priv->client_princ != cp)
krb5_free_principal(context, cp); /* else caller frees */
krb5_free_principal(context, sp);
krb5_free_principal(context, krbtgt_out_principal); krb5_free_principal(context, krbtgt_out_principal);
free(ref_realm); free(ref_realm);
@@ -2231,7 +2216,7 @@ out:
krb5_free_principal(r->context, r->client_princ); krb5_free_principal(r->context, r->client_princ);
if (r->server) if (r->server)
_kdc_free_ent(r->context, r->server); _kdc_free_ent(r->context, r->server);
krb5_free_principal(r->context, r->server_princ);
_kdc_free_fast_state(&r->fast); _kdc_free_fast_state(&r->fast);
krb5_pac_free(r->context, r->pac); krb5_pac_free(r->context, r->pac);

View File

@@ -152,7 +152,7 @@ audit(void *ctx, astgs_request_t r)
} }
static krb5plugin_kdc_ftable kdc_plugin = { static krb5plugin_kdc_ftable kdc_plugin = {
KRB5_PLUGIN_KDC_VERSION_8, KRB5_PLUGIN_KDC_VERSION_9,
init, init,
fini, fini,
pac_generate, pac_generate,