diff --git a/kdc/kerberos5.c b/kdc/kerberos5.c index 2c385df7d..21530787f 100644 --- a/kdc/kerberos5.c +++ b/kdc/kerberos5.c @@ -1959,6 +1959,23 @@ add_enc_pa_rep(astgs_request_t r) KRB5_PADATA_FX_FAST, NULL, 0); } +/* + * Add an authorization data element indicating that a synthetic + * principal was used, so that the TGS does not accidentally + * synthesize a non-synthetic principal that has since been deleted. + */ +static krb5_error_code +add_synthetic_princ_ad(astgs_request_t r) +{ + krb5_data data; + + krb5_data_zero(&data); + + return _kdc_tkt_add_if_relevant_ad(r->context, &r->et, + KRB5_AUTHDATA_SYNTHETIC_PRINC_USED, + &data); +} + static krb5_error_code get_local_tgs(krb5_context context, krb5_kdc_configuration *config, @@ -2615,6 +2632,12 @@ _kdc_as_rep(astgs_request_t r) generate_pac(r, skey, krbtgt_key); } + if (r->client->entry.flags.synthetic) { + ret = add_synthetic_princ_ad(r); + if (ret) + goto out; + } + _kdc_log_timestamp(r, "AS-REQ", r->et.authtime, r->et.starttime, r->et.endtime, r->et.renew_till); diff --git a/kdc/krb5tgs.c b/kdc/krb5tgs.c index 7d33c830f..2881da38f 100644 --- a/kdc/krb5tgs.c +++ b/kdc/krb5tgs.c @@ -47,6 +47,30 @@ get_krbtgt_realm(const PrincipalName *p) return NULL; } +/* + * return TRUE if client was a synthetic principal, as indicated by + * authorization data + */ +krb5_boolean +_kdc_synthetic_princ_used_p(krb5_context context, krb5_ticket *ticket) +{ + krb5_data synthetic_princ_used; + krb5_error_code ret; + + ret = krb5_ticket_get_authorization_data_type(context, ticket, + KRB5_AUTHDATA_SYNTHETIC_PRINC_USED, + &synthetic_princ_used); + if (ret == ENOENT) + ret = krb5_ticket_get_authorization_data_type(context, ticket, + KRB5_AUTHDATA_INITIAL_VERIFIED_CAS, + &synthetic_princ_used); + + if (ret == 0) + krb5_data_free(&synthetic_princ_used); + + return ret == 0; +} + /* * */ @@ -1902,25 +1926,9 @@ server_lookup: goto out; } - { - krb5_data verified_cas; + if (_kdc_synthetic_princ_used_p(context, ticket)) + flags |= HDB_F_SYNTHETIC_OK; - /* - * If the client doesn't exist in the HDB but has a TGT and it's - * obtained with PKINIT then we assume it's a synthetic client -- that - * is, a client whose name was vouched for by a CA using a PKINIT SAN, - * but which doesn't exist in the HDB proper. We'll allow such a - * client to do TGT requests even though normally we'd reject all - * clients that don't exist in the HDB. - */ - ret = krb5_ticket_get_authorization_data_type(context, ticket, - KRB5_AUTHDATA_INITIAL_VERIFIED_CAS, - &verified_cas); - if (ret == 0) { - krb5_data_free(&verified_cas); - flags |= HDB_F_SYNTHETIC_OK; - } - } ret = db_fetch_client(context, config, flags, cp, cpn, our_realm, &clientdb, &client); if (ret) diff --git a/lib/asn1/krb5.asn1 b/lib/asn1/krb5.asn1 index 1d7f73172..61c207c2c 100644 --- a/lib/asn1/krb5.asn1 +++ b/lib/asn1/krb5.asn1 @@ -215,6 +215,7 @@ AUTHDATA-TYPE ::= INTEGER { KRB5-AUTHDATA-SIGNTICKET-OLDER(-17), KRB5-AUTHDATA-SIGNTICKET-OLD(142), KRB5-AUTHDATA-SIGNTICKET(512), + KRB5-AUTHDATA-SYNTHETIC-PRINC-USED(513), -- principal was synthetised KRB5-AUTHDATA-AP-OPTIONS(143), -- N.B. these assignments have not been confirmed yet. --