mirror of
https://github.com/samba-team/samba.git
synced 2025-03-27 22:50:26 +03:00
s4-kdc Handle the case where we may be given a ticket from an RODC in db layer
This includes rewriting the PAC if the original krbtgt isn't to be trusted, and reading different entries from the DB for the krbtgt depending on the krbtgt number. Andrew Bartlett
This commit is contained in:
parent
9d33929d76
commit
89ee9e6518
@ -1049,10 +1049,11 @@ static krb5_error_code samba_kdc_fetch_client(krb5_context context,
|
||||
}
|
||||
|
||||
static krb5_error_code samba_kdc_fetch_krbtgt(krb5_context context,
|
||||
struct samba_kdc_db_context *kdc_db_ctx,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
krb5_const_principal principal,
|
||||
hdb_entry_ex *entry_ex)
|
||||
struct samba_kdc_db_context *kdc_db_ctx,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
krb5_const_principal principal,
|
||||
uint32_t krbtgt_number,
|
||||
hdb_entry_ex *entry_ex)
|
||||
{
|
||||
struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx;
|
||||
krb5_error_code ret;
|
||||
@ -1070,7 +1071,7 @@ static krb5_error_code samba_kdc_fetch_krbtgt(krb5_context context,
|
||||
|
||||
if (lpcfg_is_my_domain_or_realm(lp_ctx, principal->realm)
|
||||
&& lpcfg_is_my_domain_or_realm(lp_ctx, principal->name.name_string.val[1])) {
|
||||
/* us */
|
||||
/* us, or someone quite like us */
|
||||
/* Cludge, cludge cludge. If the realm part of krbtgt/realm,
|
||||
* is in our db, then direct the caller at our primary
|
||||
* krbtgt */
|
||||
@ -1078,18 +1079,35 @@ static krb5_error_code samba_kdc_fetch_krbtgt(krb5_context context,
|
||||
int lret;
|
||||
char *realm_fixed;
|
||||
|
||||
lret = dsdb_search_one(kdc_db_ctx->samdb, mem_ctx,
|
||||
&msg, realm_dn, LDB_SCOPE_SUBTREE,
|
||||
krbtgt_attrs,
|
||||
DSDB_SEARCH_SHOW_EXTENDED_DN,
|
||||
"(&(objectClass=user)(samAccountName=krbtgt))");
|
||||
if (krbtgt_number == kdc_db_ctx->my_krbtgt_number) {
|
||||
lret = dsdb_search_one(kdc_db_ctx->samdb, mem_ctx,
|
||||
&msg, kdc_db_ctx->krbtgt_dn, LDB_SCOPE_BASE,
|
||||
krbtgt_attrs, 0,
|
||||
"(objectClass=user)");
|
||||
} else {
|
||||
/* We need to look up an RODC krbtgt (perhaps
|
||||
* ours, if we are an RODC, perhaps another
|
||||
* RODC if we are a read-write DC */
|
||||
lret = dsdb_search_one(kdc_db_ctx->samdb, mem_ctx,
|
||||
&msg, realm_dn, LDB_SCOPE_SUBTREE,
|
||||
krbtgt_attrs,
|
||||
DSDB_SEARCH_SHOW_EXTENDED_DN,
|
||||
"(&(objectClass=user)(msDS-SecondaryKrbTgtNumber=%u))", (unsigned)(krbtgt_number));
|
||||
}
|
||||
|
||||
if (lret == LDB_ERR_NO_SUCH_OBJECT) {
|
||||
krb5_warnx(context, "samba_kdc_fetch: could not find own KRBTGT in DB!");
|
||||
krb5_set_error_message(context, HDB_ERR_NOENTRY, "samba_kdc_fetch: could not find own KRBTGT in DB!");
|
||||
krb5_warnx(context, "samba_kdc_fetch: could not find KRBTGT number %u in DB!",
|
||||
(unsigned)(krbtgt_number));
|
||||
krb5_set_error_message(context, HDB_ERR_NOENTRY,
|
||||
"samba_kdc_fetch: could not find KRBTGT number %u in DB!",
|
||||
(unsigned)(krbtgt_number));
|
||||
return HDB_ERR_NOENTRY;
|
||||
} else if (lret != LDB_SUCCESS) {
|
||||
krb5_warnx(context, "samba_kdc_fetch: could not find own KRBTGT in DB: %s", ldb_errstring(kdc_db_ctx->samdb));
|
||||
krb5_set_error_message(context, HDB_ERR_NOENTRY, "samba_kdc_fetch: could not find own KRBTGT in DB: %s", ldb_errstring(kdc_db_ctx->samdb));
|
||||
krb5_warnx(context, "samba_kdc_fetch: could not find KRBTGT number %u in DB!",
|
||||
(unsigned)(krbtgt_number));
|
||||
krb5_set_error_message(context, HDB_ERR_NOENTRY,
|
||||
"samba_kdc_fetch: could not find KRBTGT number %u in DB!",
|
||||
(unsigned)(krbtgt_number));
|
||||
return HDB_ERR_NOENTRY;
|
||||
}
|
||||
|
||||
@ -1281,11 +1299,24 @@ krb5_error_code samba_kdc_fetch(krb5_context context,
|
||||
struct samba_kdc_db_context *kdc_db_ctx,
|
||||
krb5_const_principal principal,
|
||||
unsigned flags,
|
||||
unsigned kvno,
|
||||
hdb_entry_ex *entry_ex)
|
||||
{
|
||||
krb5_error_code ret = HDB_ERR_NOENTRY;
|
||||
TALLOC_CTX *mem_ctx = talloc_named(kdc_db_ctx, 0, "samba_kdc_fetch context");
|
||||
TALLOC_CTX *mem_ctx;
|
||||
unsigned int krbtgt_number;
|
||||
if (flags & HDB_F_KVNO_SPECIFIED) {
|
||||
krbtgt_number = kvno >> 16;
|
||||
if (kdc_db_ctx->rodc) {
|
||||
if (krbtgt_number != kdc_db_ctx->my_krbtgt_number) {
|
||||
return HDB_ERR_NOT_FOUND_HERE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
krbtgt_number = kdc_db_ctx->my_krbtgt_number;
|
||||
}
|
||||
|
||||
mem_ctx = talloc_named(kdc_db_ctx, 0, "samba_kdc_fetch context");
|
||||
if (!mem_ctx) {
|
||||
ret = ENOMEM;
|
||||
krb5_set_error_message(context, ret, "samba_kdc_fetch: talloc_named() failed!");
|
||||
@ -1298,7 +1329,7 @@ krb5_error_code samba_kdc_fetch(krb5_context context,
|
||||
}
|
||||
if (flags & HDB_F_GET_SERVER) {
|
||||
/* krbtgt fits into this situation for trusted realms, and for resolving different versions of our own realm name */
|
||||
ret = samba_kdc_fetch_krbtgt(context, kdc_db_ctx, mem_ctx, principal, entry_ex);
|
||||
ret = samba_kdc_fetch_krbtgt(context, kdc_db_ctx, mem_ctx, principal, krbtgt_number, entry_ex);
|
||||
if (ret != HDB_ERR_NOENTRY) goto done;
|
||||
|
||||
/* We return 'no entry' if it does not start with krbtgt/, so move to the common case quickly */
|
||||
@ -1306,7 +1337,7 @@ krb5_error_code samba_kdc_fetch(krb5_context context,
|
||||
if (ret != HDB_ERR_NOENTRY) goto done;
|
||||
}
|
||||
if (flags & HDB_F_GET_KRBTGT) {
|
||||
ret = samba_kdc_fetch_krbtgt(context, kdc_db_ctx, mem_ctx, principal, entry_ex);
|
||||
ret = samba_kdc_fetch_krbtgt(context, kdc_db_ctx, mem_ctx, principal, krbtgt_number, entry_ex);
|
||||
if (ret != HDB_ERR_NOENTRY) goto done;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ krb5_error_code samba_kdc_fetch(krb5_context context,
|
||||
struct samba_kdc_db_context *kdc_db_ctx,
|
||||
krb5_const_principal principal,
|
||||
unsigned flags,
|
||||
unsigned kvno,
|
||||
hdb_entry_ex *entry_ex);
|
||||
|
||||
krb5_error_code samba_kdc_firstkey(krb5_context context,
|
||||
|
@ -83,16 +83,17 @@ static krb5_error_code hdb_samba4_remove(krb5_context context, HDB *db, krb5_con
|
||||
}
|
||||
|
||||
static krb5_error_code hdb_samba4_fetch(krb5_context context, HDB *db,
|
||||
krb5_const_principal principal,
|
||||
unsigned flags,
|
||||
hdb_entry_ex *entry_ex)
|
||||
krb5_const_principal principal,
|
||||
unsigned flags,
|
||||
unsigned kvno,
|
||||
hdb_entry_ex *entry_ex)
|
||||
{
|
||||
struct samba_kdc_db_context *kdc_db_ctx;
|
||||
|
||||
kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
|
||||
struct samba_kdc_db_context);
|
||||
|
||||
return samba_kdc_fetch(context, kdc_db_ctx, principal, flags, entry_ex);
|
||||
return samba_kdc_fetch(context, kdc_db_ctx, principal, flags, kvno, entry_ex);
|
||||
}
|
||||
|
||||
static krb5_error_code hdb_samba4_firstkey(krb5_context context, HDB *db, unsigned flags,
|
||||
|
@ -632,6 +632,7 @@ static NTSTATUS kdc_check_generic_kerberos(struct irpc_message *msg,
|
||||
kdc->config->db[0],
|
||||
principal,
|
||||
HDB_F_GET_KRBTGT | HDB_F_DECRYPT,
|
||||
0,
|
||||
&ent);
|
||||
|
||||
if (ret != 0) {
|
||||
|
@ -130,7 +130,7 @@ static int mit_samba_get_principal(struct mit_samba_context *ctx,
|
||||
}
|
||||
|
||||
ret = samba_kdc_fetch(ctx->context, ctx->db_ctx,
|
||||
principal, flags, hentry);
|
||||
principal, flags, 0, hentry);
|
||||
|
||||
krb5_free_principal(ctx->context, principal);
|
||||
|
||||
|
@ -60,7 +60,9 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context,
|
||||
static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
|
||||
const krb5_principal client_principal,
|
||||
struct hdb_entry_ex *client,
|
||||
struct hdb_entry_ex *server, krb5_pac *pac)
|
||||
struct hdb_entry_ex *server,
|
||||
struct hdb_entry_ex *krbtgt,
|
||||
krb5_pac *pac)
|
||||
{
|
||||
struct samba_kdc_entry *p = talloc_get_type(server->ctx, struct samba_kdc_entry);
|
||||
TALLOC_CTX *mem_ctx = talloc_named(p, 0, "samba_kdc_reget_pac context");
|
||||
@ -72,27 +74,37 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
pac_blob = talloc_zero(mem_ctx, DATA_BLOB);
|
||||
if (!pac_blob) {
|
||||
talloc_free(mem_ctx);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
/* The user account may be set not to want the PAC */
|
||||
if (!samba_princ_needs_pac(server)) {
|
||||
talloc_free(mem_ctx);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
nt_status = samba_kdc_update_pac_blob(mem_ctx, context,
|
||||
pac, pac_blob);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
DEBUG(0, ("Building PAC failed: %s\n",
|
||||
nt_errstr(nt_status)));
|
||||
talloc_free(mem_ctx);
|
||||
return EINVAL;
|
||||
}
|
||||
/* If the krbtgt was generated by an RODC, and we are not that
|
||||
* RODC, then we need to regenerate the PAC - we can't trust
|
||||
* it */
|
||||
if (samba_krbtgt_was_untrusted_rodc(krbtgt)) {
|
||||
nt_status = samba_kdc_get_pac_blob(mem_ctx, client, &pac_blob);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return EINVAL;
|
||||
}
|
||||
} else {
|
||||
pac_blob = talloc_zero(mem_ctx, DATA_BLOB);
|
||||
if (!pac_blob) {
|
||||
talloc_free(mem_ctx);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
nt_status = samba_kdc_update_pac_blob(mem_ctx, context,
|
||||
pac, pac_blob);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
DEBUG(0, ("Building PAC failed: %s\n",
|
||||
nt_errstr(nt_status)));
|
||||
talloc_free(mem_ctx);
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
/* We now completely regenerate this pac */
|
||||
krb5_pac_free(context, *pac);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user