svn commit: samba r2353 - in trunk/source: include libads utils

gd at samba.org gd at samba.org
Wed Sep 15 17:03:06 GMT 2004


Author: gd
Date: 2004-09-15 17:03:05 +0000 (Wed, 15 Sep 2004)
New Revision: 2353

WebSVN: http://websvn.samba.org/websvn/changeset.php?rep=samba&path=/trunk/source&rev=2353&nolog=1

Log:
Use the default locations for creating users/groups and machine
accounts in Active Directory by querying for their well known guid and
do not blindly default to cn=Users or cn=Computers.

This way we match default containers moved by redircmp.exe and
redirusr.exe in Windows 2003.

Also, do not enforce to define cryptic location paths when rejoining an
existing computer-account to ADS (use the original dn instead).

Guenther



Modified:
   trunk/source/include/ads.h
   trunk/source/libads/ldap.c
   trunk/source/utils/net.c
   trunk/source/utils/net_ads.c


Changeset:
Modified: trunk/source/include/ads.h
===================================================================
--- trunk/source/include/ads.h	2004-09-15 15:13:03 UTC (rev 2352)
+++ trunk/source/include/ads.h	2004-09-15 17:03:05 UTC (rev 2353)
@@ -224,3 +224,8 @@
 #ifndef HAVE_AP_OPTS_USE_SUBKEY
 #define AP_OPTS_USE_SUBKEY 0
 #endif
+
+#define WELL_KNOWN_GUID_COMPUTERS		"AA312825768811D1ADED00C04FD8D5CD" /* 252831aa-8876-d111-aded-00c04fd8d5cd */
+#define WELL_KNOWN_GUID_USERS			"A9D1CA15768811D1ADED00C04FD8D5CD" /* 15cad1a9-8876-d111-aded-00c04fd8d5cd */
+#define WELL_KNOWN_GUID_DOMAIN_CONTROLLERS	"A361B2FFFFD211D1AA4B00C04FD7D83A" /* ffb261a3-d2ff-d111-aa4b-00c04fd7d83a */
+#define WELL_KNOWN_GUID_SYSTEM			"AB1D30F3768811D1ADED00C04FD8D5CD" /* f3301dab-8876-d111-aded-00c04fd8d5cd */

Modified: trunk/source/libads/ldap.c
===================================================================
--- trunk/source/libads/ldap.c	2004-09-15 15:13:03 UTC (rev 2352)
+++ trunk/source/libads/ldap.c	2004-09-15 17:03:05 UTC (rev 2353)
@@ -993,22 +993,82 @@
 
 /**
  * Build an org unit string
- *  if org unit is Computers or blank then assume a container, otherwise
+ *  if org unit is empty we get the default container from ads, 
+ *  if org unit is Computers we return cn=Computers, otherwise 
  *  assume a \ separated list of organisational units
+ * @param ads connection to ads server
  * @param org_unit Organizational unit
  * @return org unit string - caller must free
  **/
-char *ads_ou_string(const char *org_unit)
-{	
-	if (!org_unit || !*org_unit || strequal(org_unit, "Computers")) {
+char *ads_ou_string(ADS_STRUCT *ads, const char *org_unit)
+{
+	if (!org_unit || !*org_unit)
+		return ads_default_ou_string(ads, WELL_KNOWN_GUID_COMPUTERS);
+
+	if (strequal(org_unit, "Computers"))
 		return strdup("cn=Computers");
-	}
 
 	return ads_build_path(org_unit, "\\/", "ou=", 1);
 }
 
+/**
+ * Get an org unit string for a well-known GUID
+ * @param ads connection to ads server
+ * @param wknguid Well known GUID
+ * @return org unit string - caller must free
+ **/
+char *ads_default_ou_string(ADS_STRUCT *ads, const char *wknguid)
+{
+	ADS_STATUS status;
+	void *res;
+	char *base, *wkn_dn, *ret, **wkn_dn_exp, **bind_dn_exp;
+	const char *attrs[] = {"distinguishedName", NULL};
+	int wkn_ln, bind_ln, i;
 
+	if (asprintf(&base, "<WKGUID=%s,%s>", wknguid, ads->config.bind_path ) == -1) {
+		DEBUG(1, ("asprintf failed!\n"));
+		return NULL;
+	}
 
+	status = ads_search_dn(ads, &res, base, attrs);
+	if (!ADS_ERR_OK(status)) {
+		DEBUG(1,("Failed while searching for: %s\n", base));
+		return NULL;
+	}
+	free(base);
+
+	if (ads_count_replies(ads, res) != 1)
+		return NULL;
+
+	/* compare ads->config.bind-path and the result from the 
+	   well-known-guid-search to return the correct default 
+	   container (which might consist of several ou's)
+	*/
+
+	wkn_dn = ads_get_dn(ads, res);
+	wkn_dn_exp = ldap_explode_dn(wkn_dn, 0);
+	bind_dn_exp = ldap_explode_dn(ads->config.bind_path, 0);
+
+	for (wkn_ln=0; wkn_dn_exp[wkn_ln]; wkn_ln++)
+		;
+	for (bind_ln=0; bind_dn_exp[bind_ln]; bind_ln++)
+		;
+
+	if (wkn_ln - bind_ln < 1)
+		return NULL;
+
+	ret = wkn_dn_exp[0];
+
+	for (i=1; i < wkn_ln - bind_ln; i++) {
+		char *s;
+		asprintf(&s, "%s,%s", ret, wkn_dn_exp[i]);
+		ret = strdup(s);
+		free(s);
+	}
+
+	return ret;
+}
+
 /*
   add a machine account to the ADS server
 */
@@ -1017,7 +1077,7 @@
 				       const char *org_unit)
 {
 	ADS_STATUS ret, status;
-	char *host_spn, *host_upn, *new_dn, *samAccountName, *controlstr;
+	char *host_spn, *host_upn, *new_dn, *old_dn, *samAccountName, *controlstr;
 	char *ou_str;
 	TALLOC_CTX *ctx;
 	ADS_MODLIST mods;
@@ -1032,6 +1092,7 @@
 	status = ads_find_machine_acct(ads, (void **)&res, hostname);
 	if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) {
 		DEBUG(0, ("Host account for %s already exists - modifying old account\n", hostname));
+		old_dn = ads_get_dn(ads, res);
 		exists=1;
 	}
 
@@ -1044,7 +1105,7 @@
 		goto done;
 	if (!(host_upn = talloc_asprintf(ctx, "%s@%s", host_spn, ads->config.realm)))
 		goto done;
-	ou_str = ads_ou_string(org_unit);
+	ou_str = ads_ou_string(ads,org_unit);
 	if (!ou_str) {
 		DEBUG(1, ("ads_ou_string returned NULL (malloc failure?)\n"));
 		goto done;
@@ -1097,7 +1158,7 @@
 	if (!exists) 
 		ret = ads_gen_add(ads, new_dn, mods);
 	else
-		ret = ads_gen_mod(ads, new_dn, mods);
+		ret = ads_gen_mod(ads, old_dn, mods);
 
 	if (!ADS_ERR_OK(ret))
 		goto done;

Modified: trunk/source/utils/net.c
===================================================================
--- trunk/source/utils/net.c	2004-09-15 15:13:03 UTC (rev 2352)
+++ trunk/source/utils/net.c	2004-09-15 17:03:05 UTC (rev 2353)
@@ -69,7 +69,7 @@
 int opt_verbose = 0;
 int opt_maxusers = -1;
 const char *opt_comment = "";
-const char *opt_container = "cn=Users";
+const char *opt_container = "";
 int opt_flags = -1;
 int opt_timeout = 0;
 const char *opt_target_workgroup = NULL;

Modified: trunk/source/utils/net_ads.c
===================================================================
--- trunk/source/utils/net_ads.c	2004-09-15 15:13:03 UTC (rev 2352)
+++ trunk/source/utils/net_ads.c	2004-09-15 17:03:05 UTC (rev 2353)
@@ -291,6 +291,7 @@
 		goto done;
 	}
 
+	opt_container = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS);
 	status = ads_add_user_acct(ads, argv[0], opt_container, opt_comment);
 
 	if (!ADS_ERR_OK(status)) {
@@ -474,6 +475,7 @@
 		goto done;
 	}
 
+	opt_container = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS);
 	status = ads_add_group_acct(ads, argv[0], opt_container, opt_comment);
 
 	if (ADS_ERR_OK(status)) {
@@ -652,7 +654,7 @@
 	char *password;
 	char *machine_account = NULL;
 	char *tmp_password;
-	const char *org_unit = "Computers";
+	const char *org_unit = NULL;
 	char *dn;
 	void *res;
 	DOM_SID dom_sid;
@@ -684,8 +686,12 @@
 		return -1;
 	}
 
-	ou_str = ads_ou_string(org_unit);
+	ou_str = ads_ou_string(ads, org_unit);
 	asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path);
+	if (ou_str == NULL) {
+		d_printf("could not find any reasonable container for the machine account\n");
+		return -1;
+	}
 	free(ou_str);
 
 	rc = ads_search_dn(ads, &res, dn, NULL);



More information about the samba-cvs mailing list