summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/dsdb/samdb/ldb_modules/operational.c56
1 files changed, 55 insertions, 1 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/operational.c b/source4/dsdb/samdb/ldb_modules/operational.c
index c2968a4b802..c99adb1dcd7 100644
--- a/source4/dsdb/samdb/ldb_modules/operational.c
+++ b/source4/dsdb/samdb/ldb_modules/operational.c
@@ -982,6 +982,43 @@ static bool pso_is_supported(struct ldb_context *ldb, struct ldb_message *msg)
}
/*
+ * Returns the number of PSO objects that exist in the DB
+ */
+static int get_pso_count(struct ldb_module *module, TALLOC_CTX *mem_ctx,
+ struct ldb_request *parent, int *pso_count)
+{
+ static const char * const attrs[] = { NULL };
+ int ret;
+ struct ldb_dn *domain_dn = NULL;
+ struct ldb_dn *psc_dn = NULL;
+ struct ldb_result *res = NULL;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+
+ domain_dn = ldb_get_default_basedn(ldb);
+ psc_dn = ldb_dn_new_fmt(mem_ctx, ldb,
+ "CN=Password Settings Container,CN=System,%s",
+ ldb_dn_get_linearized(domain_dn));
+ if (psc_dn == NULL) {
+ return ldb_oom(ldb);
+ }
+
+ /* get the number of PSO children */
+ ret = dsdb_module_search(module, mem_ctx, &res, psc_dn,
+ LDB_SCOPE_ONELEVEL, attrs,
+ DSDB_FLAG_NEXT_MODULE, parent,
+ "(objectClass=msDS-PasswordSettings)");
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ *pso_count = res->count;
+ talloc_free(res);
+ talloc_free(psc_dn);
+
+ return LDB_SUCCESS;
+}
+
+/*
* Compares two PSO objects returned by a search, to work out the better PSO.
* The PSO with the lowest precedence is better, otherwise (if the precedence
* is equal) the PSO with the lower GUID wins.
@@ -1111,6 +1148,7 @@ static int get_pso_for_user(struct ldb_module *module,
int ret;
struct ldb_message_element *el = NULL;
TALLOC_CTX *tmp_ctx = NULL;
+ int pso_count = 0;
*pso_msg = NULL;
@@ -1150,8 +1188,24 @@ static int get_pso_for_user(struct ldb_module *module,
/*
* If no valid PSO applies directly to the user, then try its groups.
- * Work out the SIDs of any account groups the user is a member of
+ * The group expansion is expensive, so check there are actually
+ * PSOs in the DB first (which is a quick search). Note in the above
+ * case we could tell that a PSO applied to the user, based on info
+ * already retrieved by the user search.
*/
+ ret = get_pso_count(module, tmp_ctx, parent, &pso_count);
+ if (ret != LDB_SUCCESS) {
+ DBG_ERR("Error %d determining PSOs in system\n", ret);
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ if (pso_count == 0) {
+ talloc_free(tmp_ctx);
+ return LDB_SUCCESS;
+ }
+
+ /* Work out the SIDs of any account groups the user is a member of */
ret = get_group_sids(ldb, tmp_ctx, user_msg,
"msDS-ResultantPSO", ACCOUNT_GROUPS,
&groupSIDs, &num_groupSIDs);