From a4c1e9ad257342717a7eb5d1b3fbc6a4fcc82c0e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 13 May 2014 17:47:03 +1200 Subject: [PATCH] passdb: Do not routinely clear the global memory returned by get_global_sam_sid() This avoids use-after-free errors and tdb database churn. Andrew Bartlett Change-Id: If7ab2e24556d9dffc7ad22c0489d665dd75a0cab Signed-off-by: Andrew Bartlett Reviewed-by: Kamen Mazdrashki (cherry picked from commit cda32d4e47aa3efb040eb60f1a0332ea8dd58417) The last 9 patches address bug #10701 - backport dsdb related crash fixes and build fixes. --- source3/passdb/machine_account_secrets.c | 10 ++++--- source3/passdb/pdb_samba_dsdb.c | 46 +++++++++++++++++++++++--------- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c index 5758efe819c..4e35a726382 100644 --- a/source3/passdb/machine_account_secrets.c +++ b/source3/passdb/machine_account_secrets.c @@ -29,6 +29,7 @@ #include "dbwrap/dbwrap.h" #include "../librpc/ndr/libndr.h" #include "util_tdb.h" +#include "libcli/security/security.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_PASSDB @@ -106,9 +107,12 @@ bool secrets_store_domain_sid(const char *domain, const struct dom_sid *sid) ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid )); - /* Force a re-query, in case we modified our domain */ - if (ret) - reset_global_sam_sid(); + /* Force a re-query, in the case where we modified our domain */ + if (ret) { + if (dom_sid_equal(get_global_sam_sid(), sid) == false) { + reset_global_sam_sid(); + } + } return ret; } diff --git a/source3/passdb/pdb_samba_dsdb.c b/source3/passdb/pdb_samba_dsdb.c index 3fc266c4e26..cbeb3327686 100644 --- a/source3/passdb/pdb_samba_dsdb.c +++ b/source3/passdb/pdb_samba_dsdb.c @@ -2193,6 +2193,10 @@ static void free_private_data(void **vp) static NTSTATUS pdb_samba_dsdb_init_secrets(struct pdb_methods *m) { struct pdb_domain_info *dom_info; + struct dom_sid stored_sid; + struct GUID stored_guid; + bool sid_exists_and_matches = false; + bool guid_exists_and_matches = false; bool ret; dom_info = pdb_samba_dsdb_get_domain_info(m, m); @@ -2200,20 +2204,38 @@ static NTSTATUS pdb_samba_dsdb_init_secrets(struct pdb_methods *m) return NT_STATUS_UNSUCCESSFUL; } - secrets_clear_domain_protection(dom_info->name); - ret = secrets_store_domain_sid(dom_info->name, - &dom_info->sid); - if (!ret) { - goto done; + ret = secrets_fetch_domain_sid(dom_info->name, &stored_sid); + if (ret) { + if (dom_sid_equal(&stored_sid, &dom_info->sid)) { + sid_exists_and_matches = true; + } } - ret = secrets_store_domain_guid(dom_info->name, - &dom_info->guid); - if (!ret) { - goto done; + + if (sid_exists_and_matches == false) { + secrets_clear_domain_protection(dom_info->name); + ret = secrets_store_domain_sid(dom_info->name, + &dom_info->sid); + ret &= secrets_mark_domain_protected(dom_info->name); + if (!ret) { + goto done; + } } - ret = secrets_mark_domain_protected(dom_info->name); - if (!ret) { - goto done; + + ret = secrets_fetch_domain_guid(dom_info->name, &stored_guid); + if (ret) { + if (GUID_equal(&stored_guid, &dom_info->guid)) { + guid_exists_and_matches = true; + } + } + + if (guid_exists_and_matches == false) { + secrets_clear_domain_protection(dom_info->name); + ret = secrets_store_domain_guid(dom_info->name, + &dom_info->guid); + ret &= secrets_mark_domain_protected(dom_info->name); + if (!ret) { + goto done; + } } done: -- 2.11.4.GIT