svn commit: samba r25940 - in branches/SAMBA_4_0/source: dsdb/samdb dsdb/samdb/ldb_modules rpc_server/drsuapi scripting/libjs setup

abartlet at samba.org abartlet at samba.org
Tue Nov 13 22:38:55 GMT 2007


Author: abartlet
Date: 2007-11-13 22:38:55 +0000 (Tue, 13 Nov 2007)
New Revision: 25940

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=25940

Log:
Rework the samldb and templates handling.

Templates just don't belong in the sam.ldb, as they don't obey any of
the other rules.  This moves them to a seperate templates.ldb.

In samldb, this patch reworks the duplicate SID and Name detection
code, to use ldb_search_exp_fmt() rather than gendb_search.  This
returns far more useful errors, which we now handle and report better.

The call to samdb_search_for_parent_domain() has been moved in samldb,
to allow both the account and SID uniqueness checks to be in the same
domain.  This function also returns better errors.

dcesrv_drsuapi.c is updated for the new prototype of
samdb_search_for_parent_domain()

Andrew Bartlett

Modified:
   branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules/samldb.c
   branches/SAMBA_4_0/source/dsdb/samdb/samdb.c
   branches/SAMBA_4_0/source/rpc_server/drsuapi/dcesrv_drsuapi.c
   branches/SAMBA_4_0/source/scripting/libjs/provision.js
   branches/SAMBA_4_0/source/setup/provision_templates.ldif


Changeset:
Modified: branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules/samldb.c
===================================================================
--- branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules/samldb.c	2007-11-13 22:30:33 UTC (rev 25939)
+++ branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules/samldb.c	2007-11-13 22:38:55 UTC (rev 25940)
@@ -190,24 +190,16 @@
 */
 static int samldb_get_new_sid(struct ldb_module *module, 
 			      TALLOC_CTX *mem_ctx, struct ldb_dn *obj_dn,
+			      struct ldb_dn *dom_dn, 
 			      struct dom_sid **sid)
 {
 	const char * const attrs[2] = { "objectSid", NULL };
 	struct ldb_result *res = NULL;
-	struct ldb_dn *dom_dn;
 	int ret;
 	struct dom_sid *dom_sid;
 
 	/* get the domain component part of the provided dn */
 
-	dom_dn = samdb_search_for_parent_domain(module->ldb, mem_ctx, obj_dn);
-	if (dom_dn == NULL) {
-		ldb_asprintf_errstring(module->ldb,
-					"Invalid dn (%s) not child of a domain object!\n",
-					ldb_dn_get_linearized(obj_dn));
-		return LDB_ERR_CONSTRAINT_VIOLATION;
-	}
-
 	/* find the domain sid */
 
 	ret = ldb_search(module->ldb, dom_dn, LDB_SCOPE_BASE, "objectSid=*", attrs, &res);
@@ -338,13 +330,14 @@
 }
 
 static int samldb_handle_sid(struct ldb_module *module, 
-					 TALLOC_CTX *mem_ctx, struct ldb_message *msg2)
+			     TALLOC_CTX *mem_ctx, struct ldb_message *msg2,
+			     struct ldb_dn *parent_dn)
 {
 	int ret;
 	
 	struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, msg2, "objectSid");
 	if (sid == NULL) { 
-		ret = samldb_get_new_sid(module, msg2, msg2->dn, &sid);
+		ret = samldb_get_new_sid(module, msg2, msg2->dn, parent_dn, &sid);
 		if (ret != 0) {
 			return ret;
 		}
@@ -361,31 +354,35 @@
 	return ret;
 }
 
-static char *samldb_generate_samAccountName(struct ldb_module *module, TALLOC_CTX *mem_ctx) 
+static int samldb_generate_samAccountName(struct ldb_module *module, TALLOC_CTX *mem_ctx, 
+					  struct ldb_dn *dom_dn, char **name) 
 {
-	char *name;
 	const char *attrs[] = { NULL };
-	struct ldb_message **msgs;
+	struct ldb_result *res;
 	int ret;
 	
 	/* Format: $000000-000000000000 */
 	
 	do {
-		name = talloc_asprintf(mem_ctx, "$%.6X-%.6X%.6X", (unsigned int)random(), (unsigned int)random(), (unsigned int)random());
+		*name = talloc_asprintf(mem_ctx, "$%.6X-%.6X%.6X", (unsigned int)random(), (unsigned int)random(), (unsigned int)random());
 		/* TODO: Figure out exactly what this is meant to conflict with */
-		ret = gendb_search(module->ldb,
-				   mem_ctx, NULL, &msgs, attrs,
-				   "samAccountName=%s",
-				   ldb_binary_encode_string(mem_ctx, name));
-		if (ret == 0) {
+		ret = ldb_search_exp_fmt(module->ldb,
+					 mem_ctx, &res, dom_dn, LDB_SCOPE_SUBTREE, attrs,
+					 "samAccountName=%s",
+					 ldb_binary_encode_string(mem_ctx, *name));
+		if (ret != LDB_SUCCESS) {
+			ldb_asprintf_errstring(module->ldb, "samldb: Failure searching to determine if samAccountName %s is unique: %s",
+					       *name, ldb_errstring(module->ldb));
+			return ret;
+		}
+
+		if (res->count == 0) {
+			talloc_free(res);
 			/* Great. There are no conflicting users/groups/etc */
-			return name;
-		} else if (ret == -1) {
-			/* Bugger, there is a problem, and we don't know what it is until gendb_search improves */
-			return NULL;
+			return LDB_SUCCESS;
 		} else {
-			talloc_free(name);
-                        /* gah, there are conflicting sids, lets move around the loop again... */
+			talloc_free(*name);
+                        /* gah, there is a conflicting name, lets move around the loop again... */
 		}
 	} while (1);
 }
@@ -394,8 +391,9 @@
 						    struct ldb_message **ret_msg)
 {
 	int ret;
-	const char *name;
+	char *name;
 	struct ldb_message *msg2;
+	struct ldb_dn *dom_dn;
 	const char *rdn_name;
 	TALLOC_CTX *mem_ctx = talloc_new(msg);
 	const char *errstr;
@@ -428,12 +426,19 @@
 		return LDB_ERR_CONSTRAINT_VIOLATION;
 	}
 
+	ret = samdb_search_for_parent_domain(module->ldb, mem_ctx, msg2->dn, &dom_dn, &errstr);
+	if (ret != LDB_SUCCESS) {
+		ldb_asprintf_errstring(module->ldb,
+				       "samldb_fill_group_object: %s", errstr);
+		return ret;
+	}
+
 	/* Generate a random name, if no samAccountName was supplied */
 	if (ldb_msg_find_element(msg2, "samAccountName") == NULL) {
-		name = samldb_generate_samAccountName(module, mem_ctx);
-		if (!name) {
+		ret = samldb_generate_samAccountName(module, mem_ctx, dom_dn, &name);
+		if (ret != LDB_SUCCESS) {
 			talloc_free(mem_ctx);
-			return LDB_ERR_OPERATIONS_ERROR;
+			return ret;
 		}
 		ret = samdb_find_or_add_attribute(module->ldb, msg2, "sAMAccountName", name);
 		if (ret) {
@@ -443,7 +448,7 @@
 	}
 	
 	/* Manage SID allocation, conflicts etc */
-	ret = samldb_handle_sid(module, mem_ctx, msg2); 
+	ret = samldb_handle_sid(module, mem_ctx, msg2, dom_dn); 
 
 	if (ret == LDB_SUCCESS) {
 		talloc_steal(msg, msg2);
@@ -459,6 +464,7 @@
 	int ret;
 	char *name;
 	struct ldb_message *msg2;
+	struct ldb_dn *dom_dn;
 	const char *rdn_name;
 	TALLOC_CTX *mem_ctx = talloc_new(msg);
 	const char *errstr;
@@ -514,11 +520,18 @@
 		return LDB_ERR_CONSTRAINT_VIOLATION;
 	}
 
+	ret = samdb_search_for_parent_domain(module->ldb, mem_ctx, msg2->dn, &dom_dn, &errstr);
+	if (ret != LDB_SUCCESS) {
+		ldb_asprintf_errstring(module->ldb,
+				       "samldb_fill_group_object: %s", errstr);
+		return ret;
+	}
+
 	if (ldb_msg_find_element(msg2, "samAccountName") == NULL) {
-		name = samldb_generate_samAccountName(module, mem_ctx);
-		if (!name) {
+		ret = samldb_generate_samAccountName(module, mem_ctx, dom_dn, &name);
+		if (ret != LDB_SUCCESS) {
 			talloc_free(mem_ctx);
-			return LDB_ERR_OPERATIONS_ERROR;
+			return ret;
 		}
 		ret = samdb_find_or_add_attribute(module->ldb, msg2, "sAMAccountName", name);
 		if (ret) {
@@ -532,7 +545,7 @@
 	*/
 
 	/* Manage SID allocation, conflicts etc */
-	ret = samldb_handle_sid(module, mem_ctx, msg2); 
+	ret = samldb_handle_sid(module, mem_ctx, msg2, dom_dn); 
 
 	/* TODO: objectCategory, userAccountControl, badPwdCount, codePage, countryCode, badPasswordTime, lastLogoff, lastLogon, pwdLastSet, primaryGroupID, accountExpires, logonCount */
 

Modified: branches/SAMBA_4_0/source/dsdb/samdb/samdb.c
===================================================================
--- branches/SAMBA_4_0/source/dsdb/samdb/samdb.c	2007-11-13 22:30:33 UTC (rev 25939)
+++ branches/SAMBA_4_0/source/dsdb/samdb/samdb.c	2007-11-13 22:38:55 UTC (rev 25940)
@@ -37,6 +37,34 @@
 #include "dsdb/common/flags.h"
 #include "param/param.h"
 
+char *samdb_relative_path(struct ldb_context *ldb,
+				 TALLOC_CTX *mem_ctx, 
+				 const char *name) 
+{
+	const char *base_url = 
+		(const char *)ldb_get_opaque(ldb, "ldb_url");
+	char *path, *p, *full_name;
+	if (name == NULL) {
+		return NULL;
+	}
+	if (name[0] == 0 || name[0] == '/' || strstr(name, ":/")) {
+		return talloc_strdup(mem_ctx, name);
+	}
+	path = talloc_strdup(mem_ctx, base_url);
+	if (path == NULL) {
+		return NULL;
+	}
+	if ( (p = strrchr(path, '/')) != NULL) {
+		p[0] = '\0';
+		full_name = talloc_asprintf(mem_ctx, "%s/%s", path, name);
+	} else {
+		full_name = talloc_asprintf(mem_ctx, "./%s", name);
+	}
+	talloc_free(path);
+	return full_name;
+}
+
+
 /*
   connect to the SAM database
   return an opaque context pointer on success, or NULL on failure
@@ -682,21 +710,49 @@
 	struct ldb_result *res;
 	struct ldb_message *t;
 	int ret, i, j;
-	struct ldb_dn *basedn = ldb_dn_new(ldb, ldb, "cn=Templates");
+	struct ldb_context *templates_ldb;
+	char *templates_ldb_path; 
+	struct ldb_dn *basedn;
 
+	templates_ldb = talloc_get_type(ldb_get_opaque(ldb, "templates_ldb"), struct ldb_context);
+
+	if (!templates_ldb) {
+		templates_ldb_path = samdb_relative_path(ldb, 
+							msg, 
+							"templates.ldb");
+		if (!templates_ldb_path) {
+			*errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: Failed to contruct path for template db");
+			return LDB_ERR_OPERATIONS_ERROR;
+		}
+
+		templates_ldb = ldb_wrap_connect(ldb, global_loadparm, 
+						templates_ldb_path, NULL,
+						NULL, 0, NULL);
+		talloc_free(templates_ldb_path);
+		if (!templates_ldb) {
+			return LDB_ERR_OPERATIONS_ERROR;
+		}
+		
+		ret = ldb_set_opaque(ldb, "templates_ldb", templates_ldb);
+		if (ret != LDB_SUCCESS) {
+			return ret;
+		}
+	}
 	*errstring = NULL;	
 
+	basedn = ldb_dn_new(templates_ldb, ldb, "cn=Templates");
 	if (!ldb_dn_add_child_fmt(basedn, "CN=Template%s", name)) {
+		talloc_free(basedn);
 		*errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: Failed to contruct DN for template '%s'", 
 					     name);
 		return LDB_ERR_OPERATIONS_ERROR;
 	}
 	
 	/* pull the template record */
-	ret = ldb_search(ldb, basedn, LDB_SCOPE_BASE, "cn=*", NULL, &res);
+	ret = ldb_search(templates_ldb, basedn, LDB_SCOPE_BASE, "(dn=*)", NULL, &res);	
 	talloc_free(basedn);
 	if (ret != LDB_SUCCESS) {
-		*errstring = talloc_steal(msg, ldb_errstring(ldb));
+		*errstring = talloc_steal(msg, ldb_errstring(templates_ldb));
 		return ret;
 	}
 	if (res->count != 1) {
@@ -1439,7 +1495,8 @@
 
 
 /* Find a domain object in the parents of a particular DN.  */
-struct ldb_dn *samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn)
+int samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
+				   struct ldb_dn **parent_dn, const char **errstring)
 {
 	TALLOC_CTX *local_ctx;
 	struct ldb_dn *sdn = dn;
@@ -1448,7 +1505,7 @@
 	const char *attrs[] = { NULL };
 
 	local_ctx = talloc_new(mem_ctx);
-	if (local_ctx == NULL) return NULL;
+	if (local_ctx == NULL) return LDB_ERR_OPERATIONS_ERROR;
 	
 	while ((sdn = ldb_dn_get_parent(local_ctx, sdn))) {
 		ret = ldb_search(ldb, sdn, LDB_SCOPE_BASE, 
@@ -1458,18 +1515,28 @@
 			if (res->count == 1) {
 				break;
 			}
+		} else {
+			break;
 		}
 	}
 
-	if (ret != LDB_SUCCESS || res->count != 1) {
+	if (ret != LDB_SUCCESS) {
+		*errstring = talloc_asprintf(mem_ctx, "Error searching for parent domain of %s: %s",
+					      ldb_dn_get_linearized(sdn),
+					      ldb_errstring(ldb));
 		talloc_free(local_ctx);
-		return NULL;
+		return ret;
 	}
+	if (res->count != 1) {
+		*errstring = talloc_asprintf(mem_ctx, "Invalid dn (%s), not child of a domain object",
+					     ldb_dn_get_linearized(sdn));
+		talloc_free(local_ctx);
+		return LDB_ERR_CONSTRAINT_VIOLATION;
+	}
 
-	talloc_steal(mem_ctx, sdn);
+	*parent_dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
 	talloc_free(local_ctx);
-
-	return sdn;
+	return ret;
 }
 
 /*

Modified: branches/SAMBA_4_0/source/rpc_server/drsuapi/dcesrv_drsuapi.c
===================================================================
--- branches/SAMBA_4_0/source/rpc_server/drsuapi/dcesrv_drsuapi.c	2007-11-13 22:30:33 UTC (rev 25939)
+++ branches/SAMBA_4_0/source/rpc_server/drsuapi/dcesrv_drsuapi.c	2007-11-13 22:38:55 UTC (rev 25940)
@@ -570,6 +570,7 @@
 			ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_account, ref_dn, 
 						 LDB_SCOPE_BASE, attrs_account_1, "objectClass=computer");
 			if (ret == LDB_SUCCESS && res_account->count == 1) {
+				const char *errstr;
 				ctr1->array[i].dns_name
 					= ldb_msg_find_attr_as_string(res_account->msgs[0], "dNSHostName", NULL);
 				ctr1->array[i].netbios_name
@@ -578,10 +579,11 @@
 					= ldb_dn_get_linearized(res_account->msgs[0]->dn);
 
 				/* Determine if this is the PDC */
-				domain_dn = samdb_search_for_parent_domain(b_state->sam_ctx, 
-									   mem_ctx, res_account->msgs[0]->dn);
+				ret = samdb_search_for_parent_domain(b_state->sam_ctx, 
+								     mem_ctx, res_account->msgs[0]->dn,
+								     &domain_dn, &errstr);
 				
-				if (domain_dn) {
+				if (ret == LDB_SUCCESS) {
 					ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn, 
 								 LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s",
 								 ldb_dn_get_linearized(ntds_dn));
@@ -664,6 +666,7 @@
 			ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_account, ref_dn, 
 						 LDB_SCOPE_BASE, attrs_account_2, "objectClass=computer");
 			if (ret == LDB_SUCCESS && res_account->count == 1) {
+				const char *errstr;
 				ctr2->array[i].dns_name
 					= ldb_msg_find_attr_as_string(res_account->msgs[0], "dNSHostName", NULL);
 				ctr2->array[i].netbios_name
@@ -673,10 +676,11 @@
 					= samdb_result_guid(res_account->msgs[0], "objectGUID");
 
 				/* Determine if this is the PDC */
-				domain_dn = samdb_search_for_parent_domain(b_state->sam_ctx, 
-									   mem_ctx, res_account->msgs[0]->dn);
+				ret = samdb_search_for_parent_domain(b_state->sam_ctx, 
+								     mem_ctx, res_account->msgs[0]->dn,
+								     &domain_dn, &errstr);
 				
-				if (domain_dn) {
+				if (ret == LDB_SUCCESS) {
 					ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn, 
 								 LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s",
 								 ldb_dn_get_linearized(ntds_dn));

Modified: branches/SAMBA_4_0/source/scripting/libjs/provision.js
===================================================================
--- branches/SAMBA_4_0/source/scripting/libjs/provision.js	2007-11-13 22:30:33 UTC (rev 25939)
+++ branches/SAMBA_4_0/source/scripting/libjs/provision.js	2007-11-13 22:38:55 UTC (rev 25940)
@@ -383,6 +383,7 @@
 	paths.shareconf = lp.get("private dir") + "/" + "share.ldb";
 	paths.samdb = lp.get("sam database");
 	paths.secrets = lp.get("secrets database");
+	paths.templates = lp.get("private dir") + "/" + "templates.ldb";
 	paths.keytab = "secrets.keytab";
 	paths.dns_keytab = "dns.keytab";
 	paths.dns_keytab_abs = lp.get("private dir") + "/" + paths.dns_keytab;
@@ -528,6 +529,9 @@
 	info.message = message;
 	info.session_info = session_info;
 
+	message("Setting up teplates into " + paths.templates + "\n");
+	setup_ldb("provision_templates.ldif", info, paths.templates);
+
 	/* Also wipes the database */
 	message("Setting up " + paths.samdb + " partitions\n");
 	setup_ldb("provision_partitions.ldif", info, paths.samdb);
@@ -548,9 +552,6 @@
 	message("Setting up " + paths.samdb + " indexes\n");
 	setup_add_ldif("provision_index.ldif", info, samdb, false);
 
-	message("Setting up " + paths.samdb + " templates\n");
-	setup_add_ldif("provision_templates.ldif", info, samdb, false);
-
 	ok = samdb.transaction_commit();
 	assert(ok);
 
@@ -623,6 +624,9 @@
 	var reg = reg_open();
 	reg.apply_patchfile(lp.get("setup directory") + "/provision.reg")
 
+	message("Setting up teplates into " + paths.templates + "\n");
+	setup_ldb("provision_templates.ldif", info, paths.templates);
+
 	message("Setting up sam.ldb partitions\n");
 	/* Also wipes the database */
 	setup_ldb("provision_partitions.ldif", info, paths.samdb);
@@ -707,8 +711,6 @@
 
 	message("Setting up display specifiers\n");
 	setup_add_ldif("display_specifiers.ldif", info, samdb, false);
-	message("Setting up sam.ldb templates\n");
-	setup_add_ldif("provision_templates.ldif", info, samdb, false);
 
 	message("Adding users container (permitted to fail)\n");
 	var add_ok = setup_add_ldif("provision_users_add.ldif", info, samdb, true);

Modified: branches/SAMBA_4_0/source/setup/provision_templates.ldif
===================================================================
--- branches/SAMBA_4_0/source/setup/provision_templates.ldif	2007-11-13 22:30:33 UTC (rev 25939)
+++ branches/SAMBA_4_0/source/setup/provision_templates.ldif	2007-11-13 22:38:55 UTC (rev 25940)
@@ -1,3 +1,17 @@
+###
+# Templates to be put in templates.ldb.  Not part of main samdb any more.
+###
+
+dn: @OPTIONS
+checkBaseOnSearch: TRUE
+
+dn: @INDEXLIST
+ at IDXATTR: cn
+
+dn: @ATTRIBUTES
+cn: CASE_INSENSITIVE
+dn: CASE_INSENSITIVE
+
 dn: CN=Templates
 objectClass: top
 objectClass: container
@@ -2,11 +16,3 @@
 description: Container for SAM account templates
-showInAdvancedViewOnly: TRUE
-systemFlags: 2348810240
-isCriticalSystemObject: TRUE
 
-###
-# note! the template users must not match normal searches. Be careful
-# with what classes you put them in
-###
-
 dn: CN=TemplateUser,CN=Templates



More information about the samba-cvs mailing list