}
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;
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 */
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;
}
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!");
}
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 */
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;
}
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");
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);