diff options
-rw-r--r-- | source4/kdc/db-glue.c | 65 | ||||
-rw-r--r-- | source4/kdc/db-glue.h | 1 | ||||
-rw-r--r-- | source4/kdc/hdb-samba4.c | 9 | ||||
-rw-r--r-- | source4/kdc/kdc.c | 1 | ||||
-rw-r--r-- | source4/kdc/mit_samba.c | 2 | ||||
-rw-r--r-- | source4/kdc/wdc-samba4.c | 42 |
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); |