kdc: correctly generate PAC TGS signature
When generating an AS-REQ, the TGS signature was incorrectly generated using the server key, which would fail to validate if the server was not also the TGS. Fix this. Patch from Isaac Bourkis <iboukris@gmail.com>.
This commit is contained in:
@@ -1815,7 +1815,7 @@ send_pac_p(krb5_context context, KDC_REQ *req)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static krb5_error_code
|
static krb5_error_code
|
||||||
generate_pac(astgs_request_t r, Key *skey)
|
generate_pac(astgs_request_t r, const Key *skey, const Key *tkey)
|
||||||
{
|
{
|
||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
krb5_pac p = NULL;
|
krb5_pac p = NULL;
|
||||||
@@ -1845,7 +1845,7 @@ generate_pac(astgs_request_t r, Key *skey)
|
|||||||
ret = _krb5_pac_sign(r->context, p, r->et.authtime,
|
ret = _krb5_pac_sign(r->context, p, r->et.authtime,
|
||||||
client,
|
client,
|
||||||
&skey->key, /* Server key */
|
&skey->key, /* Server key */
|
||||||
&skey->key, /* FIXME: should be krbtgt key */
|
&tkey->key, /* TGS key */
|
||||||
rodc_id,
|
rodc_id,
|
||||||
&data);
|
&data);
|
||||||
krb5_free_principal(r->context, client);
|
krb5_free_principal(r->context, client);
|
||||||
@@ -1941,6 +1941,33 @@ add_enc_pa_rep(astgs_request_t r)
|
|||||||
KRB5_PADATA_FX_FAST, NULL, 0);
|
KRB5_PADATA_FX_FAST, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static krb5_error_code
|
||||||
|
get_local_tgs(krb5_context context,
|
||||||
|
krb5_kdc_configuration *config,
|
||||||
|
krb5_const_realm realm,
|
||||||
|
hdb_entry_ex **krbtgt)
|
||||||
|
{
|
||||||
|
krb5_error_code ret;
|
||||||
|
krb5_principal tgs_name;
|
||||||
|
|
||||||
|
*krbtgt = NULL;
|
||||||
|
|
||||||
|
ret = krb5_make_principal(context,
|
||||||
|
&tgs_name,
|
||||||
|
realm,
|
||||||
|
KRB5_TGS_NAME,
|
||||||
|
realm,
|
||||||
|
NULL);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = _kdc_db_fetch(context, config, tgs_name,
|
||||||
|
HDB_F_GET_KRBTGT, NULL, NULL, krbtgt);
|
||||||
|
krb5_free_principal(context, tgs_name);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -1964,6 +1991,8 @@ _kdc_as_rep(astgs_request_t r)
|
|||||||
const PA_DATA *pa;
|
const PA_DATA *pa;
|
||||||
krb5_boolean is_tgs;
|
krb5_boolean is_tgs;
|
||||||
const char *msg;
|
const char *msg;
|
||||||
|
hdb_entry_ex *krbtgt = NULL;
|
||||||
|
Key *krbtgt_key;
|
||||||
|
|
||||||
memset(&rep, 0, sizeof(rep));
|
memset(&rep, 0, sizeof(rep));
|
||||||
error_method.len = 0;
|
error_method.len = 0;
|
||||||
@@ -2248,6 +2277,22 @@ _kdc_as_rep(astgs_request_t r)
|
|||||||
if(ret)
|
if(ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
/* If server is not krbtgt, fetch local krbtgt key for signing authdata */
|
||||||
|
if (is_tgs) {
|
||||||
|
krbtgt_key = skey;
|
||||||
|
} else {
|
||||||
|
ret = get_local_tgs(context, config, r->server_princ->realm,
|
||||||
|
&krbtgt);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = _kdc_get_preferred_key(context, config, krbtgt,
|
||||||
|
r->server_princ->realm,
|
||||||
|
NULL, &krbtgt_key);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey) {
|
if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey) {
|
||||||
ret = KRB5KDC_ERR_BADOPTION;
|
ret = KRB5KDC_ERR_BADOPTION;
|
||||||
_kdc_set_e_text(r, "Bad KDC options");
|
_kdc_set_e_text(r, "Bad KDC options");
|
||||||
@@ -2516,7 +2561,7 @@ _kdc_as_rep(astgs_request_t r)
|
|||||||
|
|
||||||
/* Add the PAC */
|
/* Add the PAC */
|
||||||
if (send_pac_p(context, req) && !r->et.flags.anonymous) {
|
if (send_pac_p(context, req) && !r->et.flags.anonymous) {
|
||||||
generate_pac(r, skey);
|
generate_pac(r, skey, krbtgt_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
_kdc_log_timestamp(r, "AS-REQ", r->et.authtime,
|
_kdc_log_timestamp(r, "AS-REQ", r->et.authtime,
|
||||||
@@ -2611,6 +2656,8 @@ out:
|
|||||||
_kdc_free_ent(context, r->client);
|
_kdc_free_ent(context, r->client);
|
||||||
if (r->server)
|
if (r->server)
|
||||||
_kdc_free_ent(context, r->server);
|
_kdc_free_ent(context, r->server);
|
||||||
|
if (krbtgt)
|
||||||
|
_kdc_free_ent(context, krbtgt);
|
||||||
if (r->armor_crypto) {
|
if (r->armor_crypto) {
|
||||||
krb5_crypto_destroy(r->context, r->armor_crypto);
|
krb5_crypto_destroy(r->context, r->armor_crypto);
|
||||||
r->armor_crypto = NULL;
|
r->armor_crypto = NULL;
|
||||||
|
Reference in New Issue
Block a user