mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
heimdal Add support for extracting a particular KVNO from the database
This should allow master key rollover. (but the real reason is to allow multiple krbtgt accounts, as used by Active Directory to implement RODC support) Andrew Bartlett
This commit is contained in:
parent
3021af2777
commit
9b5e304cce
@ -988,7 +988,8 @@ _kdc_as_rep(krb5_context context,
|
||||
*/
|
||||
|
||||
ret = _kdc_db_fetch(context, config, client_princ,
|
||||
HDB_F_GET_CLIENT | flags, &clientdb, &client);
|
||||
HDB_F_GET_CLIENT | flags, 0,
|
||||
&clientdb, &client);
|
||||
if(ret){
|
||||
const char *msg = krb5_get_error_message(context, ret);
|
||||
kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name, msg);
|
||||
@ -999,7 +1000,7 @@ _kdc_as_rep(krb5_context context,
|
||||
|
||||
ret = _kdc_db_fetch(context, config, server_princ,
|
||||
HDB_F_GET_SERVER|HDB_F_GET_KRBTGT,
|
||||
NULL, &server);
|
||||
0, NULL, &server);
|
||||
if(ret){
|
||||
const char *msg = krb5_get_error_message(context, ret);
|
||||
kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name, msg);
|
||||
|
@ -281,8 +281,10 @@ check_PAC(krb5_context context,
|
||||
const krb5_principal client_principal,
|
||||
hdb_entry_ex *client,
|
||||
hdb_entry_ex *server,
|
||||
hdb_entry_ex *krbtgt,
|
||||
const EncryptionKey *server_key,
|
||||
const EncryptionKey *krbtgt_key,
|
||||
const EncryptionKey *krbtgt_check_key,
|
||||
const EncryptionKey *krbtgt_sign_key,
|
||||
EncTicketPart *tkt,
|
||||
krb5_data *rspac,
|
||||
int *signedpath)
|
||||
@ -325,14 +327,14 @@ check_PAC(krb5_context context,
|
||||
|
||||
ret = krb5_pac_verify(context, pac, tkt->authtime,
|
||||
client_principal,
|
||||
krbtgt_key, NULL);
|
||||
krbtgt_check_key, NULL);
|
||||
if (ret) {
|
||||
krb5_pac_free(context, pac);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = _kdc_pac_verify(context, client_principal,
|
||||
client, server, &pac);
|
||||
client, server, krbtgt, &pac);
|
||||
if (ret) {
|
||||
krb5_pac_free(context, pac);
|
||||
return ret;
|
||||
@ -341,7 +343,7 @@ check_PAC(krb5_context context,
|
||||
|
||||
ret = _krb5_pac_sign(context, pac, tkt->authtime,
|
||||
client_principal,
|
||||
server_key, krbtgt_key, rspac);
|
||||
server_key, krbtgt_sign_key, rspac);
|
||||
|
||||
krb5_pac_free(context, pac);
|
||||
|
||||
@ -1156,7 +1158,7 @@ tgs_parse_request(krb5_context context,
|
||||
ap_req.ticket.sname,
|
||||
ap_req.ticket.realm);
|
||||
|
||||
ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, NULL, krbtgt);
|
||||
ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, ap_req.ticket.enc_part.kvno, NULL, krbtgt);
|
||||
|
||||
if(ret) {
|
||||
const char *msg = krb5_get_error_message(context, ret);
|
||||
@ -1454,6 +1456,8 @@ tgs_build_reply(krb5_context context,
|
||||
krb5_kvno kvno;
|
||||
krb5_data rspac;
|
||||
|
||||
hdb_entry_ex *krbtgt_out = NULL;
|
||||
|
||||
METHOD_DATA enc_pa_data;
|
||||
|
||||
PrincipalName *s;
|
||||
@ -1463,7 +1467,8 @@ tgs_build_reply(krb5_context context,
|
||||
char opt_str[128];
|
||||
int signedpath = 0;
|
||||
|
||||
Key *tkey;
|
||||
Key *tkey_check;
|
||||
Key *tkey_sign;
|
||||
|
||||
memset(&sessionkey, 0, sizeof(sessionkey));
|
||||
memset(&adtkt, 0, sizeof(adtkt));
|
||||
@ -1495,7 +1500,7 @@ tgs_build_reply(krb5_context context,
|
||||
}
|
||||
_krb5_principalname2krb5_principal(context, &p, t->sname, t->realm);
|
||||
ret = _kdc_db_fetch(context, config, p,
|
||||
HDB_F_GET_CLIENT|HDB_F_GET_SERVER,
|
||||
HDB_F_GET_KRBTGT, t->enc_part.kvno,
|
||||
NULL, &uu);
|
||||
krb5_free_principal(context, p);
|
||||
if(ret){
|
||||
@ -1548,7 +1553,7 @@ tgs_build_reply(krb5_context context,
|
||||
|
||||
server_lookup:
|
||||
ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER | HDB_F_CANON,
|
||||
NULL, &server);
|
||||
0, NULL, &server);
|
||||
|
||||
if(ret){
|
||||
const char *new_rlm, *msg;
|
||||
@ -1609,7 +1614,7 @@ server_lookup:
|
||||
}
|
||||
|
||||
ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | HDB_F_CANON,
|
||||
&clientdb, &client);
|
||||
0, &clientdb, &client);
|
||||
if(ret) {
|
||||
const char *krbtgt_realm, *msg;
|
||||
|
||||
@ -1704,15 +1709,31 @@ server_lookup:
|
||||
*/
|
||||
|
||||
ret = hdb_enctype2key(context, &krbtgt->entry,
|
||||
krbtgt_etype, &tkey);
|
||||
krbtgt_etype, &tkey_check);
|
||||
if(ret) {
|
||||
kdc_log(context, config, 0,
|
||||
"Failed to find key for krbtgt PAC check");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Now refetch the krbtgt, but get the current kvno (the sign check may have been on an old kvno) */
|
||||
ret = _kdc_db_fetch(context, config, krbtgt->entry.principal, HDB_F_GET_KRBTGT, NULL, NULL, &krbtgt_out);
|
||||
if (ret) {
|
||||
kdc_log(context, config, 0,
|
||||
"Failed to find krbtgt in DB for krbtgt PAC signature");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = hdb_enctype2key(context, &krbtgt_out->entry,
|
||||
krbtgt_etype, &tkey_sign);
|
||||
if(ret) {
|
||||
kdc_log(context, config, 0,
|
||||
"Failed to find key for krbtgt PAC signature");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = check_PAC(context, config, cp,
|
||||
client, server, ekey, &tkey->key,
|
||||
client, server, krbtgt, ekey, &tkey_check->key, &tkey_sign->key,
|
||||
tgt, &rspac, &signedpath);
|
||||
if (ret) {
|
||||
const char *msg = krb5_get_error_message(context, ret);
|
||||
@ -1814,7 +1835,7 @@ server_lookup:
|
||||
krb5_pac p = NULL;
|
||||
krb5_data_free(&rspac);
|
||||
ret = _kdc_db_fetch(context, config, client_principal, HDB_F_GET_CLIENT | HDB_F_CANON,
|
||||
&s4u2self_impersonated_clientdb, &s4u2self_impersonated_client);
|
||||
0, &s4u2self_impersonated_clientdb, &s4u2self_impersonated_client);
|
||||
if (ret) {
|
||||
const char *msg;
|
||||
|
||||
@ -1840,7 +1861,7 @@ server_lookup:
|
||||
if (p != NULL) {
|
||||
ret = _krb5_pac_sign(context, p, ticket->ticket.authtime,
|
||||
s4u2self_impersonated_client->entry.principal,
|
||||
ekey, &tkey->key,
|
||||
ekey, &tkey_sign->key,
|
||||
&rspac);
|
||||
krb5_pac_free(context, p);
|
||||
if (ret) {
|
||||
@ -2070,7 +2091,7 @@ server_lookup:
|
||||
spn,
|
||||
client,
|
||||
cp,
|
||||
krbtgt,
|
||||
krbtgt_out,
|
||||
krbtgt_etype,
|
||||
spp,
|
||||
&rspac,
|
||||
@ -2084,6 +2105,8 @@ out:
|
||||
|
||||
krb5_data_free(&rspac);
|
||||
krb5_free_keyblock_contents(context, &sessionkey);
|
||||
if(krbtgt_out)
|
||||
_kdc_free_ent(context, krbtgt_out);
|
||||
if(server)
|
||||
_kdc_free_ent(context, server);
|
||||
if(client)
|
||||
|
@ -40,12 +40,19 @@ _kdc_db_fetch(krb5_context context,
|
||||
krb5_kdc_configuration *config,
|
||||
krb5_const_principal principal,
|
||||
unsigned flags,
|
||||
krb5int32 *kvno_ptr,
|
||||
HDB **db,
|
||||
hdb_entry_ex **h)
|
||||
{
|
||||
hdb_entry_ex *ent;
|
||||
krb5_error_code ret;
|
||||
int i;
|
||||
unsigned kvno;
|
||||
|
||||
if (kvno_ptr) {
|
||||
kvno = *kvno_ptr;
|
||||
flags |= HDB_F_KVNO_SPECIFIED;
|
||||
}
|
||||
|
||||
ent = calloc (1, sizeof (*ent));
|
||||
if (ent == NULL) {
|
||||
@ -88,6 +95,7 @@ _kdc_db_fetch(krb5_context context,
|
||||
config->db[i],
|
||||
principal,
|
||||
flags | HDB_F_DECRYPT,
|
||||
kvno,
|
||||
ent);
|
||||
krb5_free_principal(context, enterprise_principal);
|
||||
|
||||
|
@ -86,6 +86,7 @@ _kdc_pac_verify(krb5_context context,
|
||||
const krb5_principal client_principal,
|
||||
hdb_entry_ex *client,
|
||||
hdb_entry_ex *server,
|
||||
hdb_entry_ex *krbtgt,
|
||||
krb5_pac *pac)
|
||||
{
|
||||
if (windcft == NULL) {
|
||||
@ -93,7 +94,7 @@ _kdc_pac_verify(krb5_context context,
|
||||
return EINVAL;
|
||||
}
|
||||
return (windcft->pac_verify)(windcctx, context,
|
||||
client_principal, client, server, pac);
|
||||
client_principal, client, server, krbtgt, pac);
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
|
@ -60,6 +60,7 @@ typedef krb5_error_code
|
||||
const krb5_principal,
|
||||
struct hdb_entry_ex *,
|
||||
struct hdb_entry_ex *,
|
||||
struct hdb_entry_ex *,
|
||||
krb5_pac *);
|
||||
|
||||
typedef krb5_error_code
|
||||
|
@ -54,6 +54,7 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK };
|
||||
#define HDB_F_GET_ANY 28 /* fetch any of client,server,krbtgt */
|
||||
#define HDB_F_CANON 32 /* want canonicalition */
|
||||
#define HDB_F_ADMIN_DATA 64 /* want data that kdc don't use */
|
||||
#define HDB_F_KVNO_SPECIFIED 128 /* we want a particular KVNO */
|
||||
|
||||
/* hdb_capability_flags */
|
||||
#define HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL 1
|
||||
@ -122,7 +123,7 @@ typedef struct HDB{
|
||||
* should be fetch: client, server, krbtgt.
|
||||
*/
|
||||
krb5_error_code (*hdb_fetch)(krb5_context, struct HDB*,
|
||||
krb5_const_principal, unsigned,
|
||||
krb5_const_principal, unsigned, unsigned,
|
||||
hdb_entry_ex*);
|
||||
/**
|
||||
* Store an entry to database
|
||||
|
@ -213,7 +213,7 @@ hdb_get_entry(krb5_context context,
|
||||
ret = (*db->hdb_fetch)(context, db, principal,
|
||||
HDB_F_DECRYPT|
|
||||
HDB_F_GET_CLIENT|HDB_F_GET_SERVER|HDB_F_GET_KRBTGT,
|
||||
&ent);
|
||||
0, &ent);
|
||||
|
||||
if(ret == HDB_ERR_NOENTRY) {
|
||||
ret = KRB5_KT_NOTFOUND;
|
||||
|
Loading…
Reference in New Issue
Block a user