summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2010-09-28 13:13:28 +1000
committerAndrew Bartlett <abartlet@samba.org>2010-09-29 04:23:07 +1000
commit89ee9e6518f5bd398bb44e0cd47454e2d69f469e (patch)
tree97c294dd0fd053b4ec9078fcd84e6bbf83efcaf6
parent9d33929d76d0969917c1d42e1097d75af3401008 (diff)
downloadsamba-89ee9e6518f5bd398bb44e0cd47454e2d69f469e.tar.gz
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
-rw-r--r--source4/kdc/db-glue.c65
-rw-r--r--source4/kdc/db-glue.h1
-rw-r--r--source4/kdc/hdb-samba4.c9
-rw-r--r--source4/kdc/kdc.c1
-rw-r--r--source4/kdc/mit_samba.c2
-rw-r--r--source4/kdc/wdc-samba4.c42
6 files changed, 83 insertions, 37 deletions
diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c
index 2cda04bca8..ecb160caf3 100644
--- a/source4/kdc/db-glue.c
+++ b/source4/kdc/db-glue.c
@@ -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;
}
diff --git a/source4/kdc/db-glue.h b/source4/kdc/db-glue.h
index 5f9c39dfb6..9738fbc769 100644
--- a/source4/kdc/db-glue.h
+++ b/source4/kdc/db-glue.h
@@ -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,
diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c
index cbc00df0ae..53b1abee94 100644
--- a/source4/kdc/hdb-samba4.c
+++ b/source4/kdc/hdb-samba4.c
@@ -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,
diff --git a/source4/kdc/kdc.c b/source4/kdc/kdc.c
index 5adb0709cf..4dd2113dff 100644
--- a/source4/kdc/kdc.c
+++ b/source4/kdc/kdc.c
@@ -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) {
diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c
index 217f0983ae..14ad7be414 100644
--- a/source4/kdc/mit_samba.c
+++ b/source4/kdc/mit_samba.c
@@ -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);
diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c
index 0ebc4e7c2b..8926594698 100644
--- a/source4/kdc/wdc-samba4.c
+++ b/source4/kdc/wdc-samba4.c
@@ -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);