kdc: support for PAC_ATTRIBUTES_INFO

Add PAC_ATTRIBUTES_INFO to the PAC. This info buffer indicates whether the user
explicitly requested a PAC be present or absent.

Note: this changes the windc plugin ABI.
This commit is contained in:
Luke Howard
2021-12-20 15:31:33 +11:00
parent e50033aec2
commit f7964251ff
12 changed files with 268 additions and 95 deletions

View File

@@ -848,7 +848,7 @@ _kdc_fast_check_armor_pac(astgs_request_t r)
armor_client, r->armor_server,
r->armor_server, r->armor_server,
&r->armor_key->key, &r->armor_key->key,
&r->armor_ticket->ticket, &ad_kdc_issued, &mspac, NULL);
&r->armor_ticket->ticket, &ad_kdc_issued, &mspac, NULL, NULL);
if (ret) {
const char *msg = krb5_get_error_message(r->context, ret);

View File

@@ -109,6 +109,8 @@ struct astgs_request_desc {
Key *armor_key;
KDCFastState fast;
uint64_t pac_attributes;
};
typedef struct kx509_req_context_desc {

View File

@@ -1783,34 +1783,33 @@ _kdc_check_anon_policy(astgs_request_t r)
}
/*
*
* Determine whether the client requested a PAC be included
* or excluded explictly, or whether it doesn't care.
*/
static krb5_error_code
check_pa_pac_request(krb5_context context,
KDC_REQ *req,
krb5_boolean *include_pac)
static uint64_t
get_pac_attributes(krb5_context context, KDC_REQ *req)
{
krb5_error_code ret;
PA_PAC_REQUEST pacreq;
const PA_DATA *pa;
int i = 0;
*include_pac = TRUE;
uint32_t pac_attributes;
pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
if (pa == NULL)
return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
return KRB5_PAC_WAS_GIVEN_IMPLICITLY;
ret = decode_PA_PAC_REQUEST(pa->padata_value.data,
pa->padata_value.length,
&pacreq,
NULL);
if (ret)
return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
*include_pac = pacreq.include_pac;
return KRB5_PAC_WAS_GIVEN_IMPLICITLY;
pac_attributes = pacreq.include_pac ? KRB5_PAC_WAS_REQUESTED : 0;
free_PA_PAC_REQUEST(&pacreq);
return 0;
return pac_attributes;
}
/*
@@ -1825,11 +1824,9 @@ generate_pac(astgs_request_t r, const Key *skey, const Key *tkey)
krb5_data data;
uint16_t rodc_id;
krb5_principal client;
krb5_boolean client_sent_pac_req, pac_request;
krb5_const_principal canon_princ = NULL;
client_sent_pac_req =
(check_pa_pac_request(r->context, &r->req, &pac_request) == 0);
r->pac_attributes = get_pac_attributes(r->context, &r->req);
/*
* When a PA mech replaces the reply key, the PAC may include the
@@ -1841,7 +1838,7 @@ generate_pac(astgs_request_t r, const Key *skey, const Key *tkey)
r->client,
r->server,
r->replaced_reply_key ? &r->reply_key : NULL,
client_sent_pac_req ? &pac_request : NULL,
r->pac_attributes,
&p);
if (ret) {
_kdc_r_log(r, 4, "PAC generation failed for -- %s",
@@ -1885,6 +1882,7 @@ generate_pac(astgs_request_t r, const Key *skey, const Key *tkey)
rodc_id,
NULL, /* UPN */
canon_princ,
&r->pac_attributes,
&data);
krb5_free_principal(r->context, client);
krb5_pac_free(r->context, p);

View File

@@ -89,7 +89,8 @@ _kdc_check_pac(krb5_context context,
EncTicketPart *tkt,
krb5_boolean *kdc_issued,
krb5_pac *ppac,
krb5_principal *pac_canon_name)
krb5_principal *pac_canon_name,
uint64_t *pac_attributes)
{
krb5_pac pac = NULL;
krb5_error_code ret;
@@ -129,6 +130,8 @@ _kdc_check_pac(krb5_context context,
return ret;
}
}
if (pac_attributes)
_krb5_pac_get_attributes_info(context, pac, pac_attributes);
} else if (ret == KRB5_PLUGIN_NO_HANDLE) {
/*
* We can't verify the KDC signatures if the ticket was issued by
@@ -150,6 +153,8 @@ _kdc_check_pac(krb5_context context,
krb5_pac_free(context, pac);
return ret;
}
if (pac_attributes)
_krb5_pac_get_attributes_info(context, pac, pac_attributes);
}
/* Discard the PAC if the plugin didn't handle it */
@@ -818,8 +823,8 @@ tgs_make_reply(astgs_request_t r,
/* The PAC should be the last change to the ticket. */
ret = _krb5_kdc_pac_sign_ticket(r->context, mspac, tgt_name, serverkey,
krbtgtkey, rodc_id, add_ticket_sig, &et,
NULL, r->client_princ);
krbtgtkey, rodc_id, NULL, r->client_princ,
add_ticket_sig, &et, &r->pac_attributes);
if (ret)
goto out;
}
@@ -1842,7 +1847,7 @@ server_lookup:
ret = _kdc_check_pac(context, config, user2user_princ, NULL,
user2user_client, user2user_krbtgt, user2user_krbtgt, user2user_krbtgt,
&uukey->key, &priv->ticket_key->key, &adtkt,
&user2user_kdc_issued, &user2user_pac, NULL);
&user2user_kdc_issued, &user2user_pac, NULL, NULL);
_kdc_free_ent(context, user2user_client);
if (ret) {
const char *msg = krb5_get_error_message(context, ret);
@@ -1970,7 +1975,7 @@ server_lookup:
ret = _kdc_check_pac(context, config, cp, NULL, client, server, krbtgt, krbtgt,
&priv->ticket_key->key, &priv->ticket_key->key, tgt,
&kdc_issued, &mspac, &priv->client_princ);
&kdc_issued, &mspac, &priv->client_princ, &priv->pac_attributes);
if (ret) {
const char *msg = krb5_get_error_message(context, ret);
_kdc_audit_addreason((kdc_request_t)priv, "PAC check failed");
@@ -2131,7 +2136,7 @@ server_lookup:
s4u2self_impersonated_client,
server,
NULL,
NULL,
KRB5_PAC_WAS_GIVEN_IMPLICITLY,
&mspac);
if (ret) {
kdc_log(context, config, 4, "PAC generation failed for -- %s", tpn);
@@ -2302,7 +2307,7 @@ server_lookup:
*/
ret = _kdc_check_pac(context, config, tp, dp, adclient, server, krbtgt, client,
&clientkey->key, &priv->ticket_key->key, &adtkt,
&ad_kdc_issued, &mspac, &priv->client_princ);
&ad_kdc_issued, &mspac, &priv->client_princ, &priv->pac_attributes);
if (adclient)
_kdc_free_ent(context, adclient);
if (ret) {

View File

@@ -73,8 +73,8 @@ struct generate_uc {
hdb_entry_ex *client;
hdb_entry_ex *server;
const krb5_keyblock *reply_key;
uint64_t pac_attributes;
krb5_pac *pac;
const krb5_boolean *pac_request;
};
static krb5_error_code KRB5_LIB_CALL
@@ -90,7 +90,7 @@ generate(krb5_context context, const void *plug, void *plugctx, void *userctx)
uc->client,
uc->server,
uc->reply_key,
uc->pac_request,
uc->pac_attributes,
uc->pac);
}
@@ -100,7 +100,7 @@ _kdc_pac_generate(krb5_context context,
hdb_entry_ex *client,
hdb_entry_ex *server,
const krb5_keyblock *reply_key,
const krb5_boolean *pac_request,
uint64_t pac_attributes,
krb5_pac *pac)
{
krb5_error_code ret = 0;
@@ -118,7 +118,7 @@ _kdc_pac_generate(krb5_context context,
uc.server = server;
uc.reply_key = reply_key;
uc.pac = pac;
uc.pac_request = pac_request;
uc.pac_attributes = pac_attributes;
ret = _krb5_plugin_run_f(context, &windc_plugin_data,
0, &uc, generate);

View File

@@ -57,7 +57,7 @@ typedef krb5_error_code
struct hdb_entry_ex *, /* client */
struct hdb_entry_ex *, /* server */
const krb5_keyblock *, /* pk_replykey */
const krb5_boolean *, /* pac_request */
uint64_t, /* pac_attributes */
krb5_pac *);
typedef krb5_error_code