summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGünther Deschner <gd@samba.org>2004-10-06 16:21:35 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 10:52:54 -0500
commit132879b285e66bff896c761858311d7f5d43e9b6 (patch)
tree106c6b70d2c93f2c8dbdecae2cc7f60d7da098a5
parent4fd4aa1152732311178f1b1c70880d9efeccbaf6 (diff)
downloadsamba-132879b285e66bff896c761858311d7f5d43e9b6.tar.gz
samba-132879b285e66bff896c761858311d7f5d43e9b6.tar.bz2
samba-132879b285e66bff896c761858311d7f5d43e9b6.zip
r2832: Readd WKGUID-binding to match the correct default-locations of new
User-, Group- and Machine-Accounts in Active Directory (this got lost during the last trunk-merge). This way we match e.g. default containers moved by redircmp.exe and redirusr.exe in Windows 2003 and don't blindly default to cn=Users or cn=Computers. Further wkguids can be examied via "net ads search wellknownobjects=*". This should still keep a samba3-client joining a samba4 dc. Fixes Bugzilla #1343. Guenther (This used to be commit 8836621694c95779475fa9a1acf158e5e0577288)
-rw-r--r--source3/include/ads.h3
-rw-r--r--source3/libads/ldap.c77
-rw-r--r--source3/utils/net.c2
-rw-r--r--source3/utils/net_ads.c12
4 files changed, 87 insertions, 7 deletions
diff --git a/source3/include/ads.h b/source3/include/ads.h
index 4daa65e796..de020f2a3f 100644
--- a/source3/include/ads.h
+++ b/source3/include/ads.h
@@ -224,3 +224,6 @@ typedef void **ADS_MODLIST;
#ifndef HAVE_AP_OPTS_USE_SUBKEY
#define AP_OPTS_USE_SUBKEY 0
#endif
+
+#define WELL_KNOWN_GUID_COMPUTERS "AA312825768811D1ADED00C04FD8D5CD"
+#define WELL_KNOWN_GUID_USERS "A9D1CA15768811D1ADED00C04FD8D5CD"
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index d1539b83da..e5d2dfb8d3 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -995,12 +995,23 @@ ADS_STATUS ads_del_dn(ADS_STRUCT *ads, char *del_dn)
* Build an org unit string
* if org unit is Computers or blank then assume a container, 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)
+{
+ char *ret = NULL;
+
+ if (!org_unit || !*org_unit) {
+
+ ret = ads_default_ou_string(ads, WELL_KNOWN_GUID_COMPUTERS);
+
+ /* samba4 might not yet respond to a wellknownobject-query */
+ return ret ? ret : strdup("cn=Computers");
+ }
+
+ if (strequal(org_unit, "Computers")) {
return strdup("cn=Computers");
}
@@ -1008,6 +1019,64 @@ char *ads_ou_string(const char *org_unit)
}
/**
+ * Get a 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 new_ln, wkn_ln, bind_ln, i;
+
+ if (wknguid == NULL) {
+ return NULL;
+ }
+
+ 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;
+ }
+
+ /* substitute the bind-path from the well-known-guid-search result */
+ 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++)
+ ;
+
+ new_ln = wkn_ln - bind_ln;
+
+ ret = wkn_dn_exp[0];
+
+ for (i=1; i < new_ln; i++) {
+ char *s;
+ asprintf(&s, "%s,%s", ret, wkn_dn_exp[i]);
+ ret = strdup(s);
+ free(s);
+ }
+
+ return ret;
+}
+
+/**
* Adds (appends) an item to an attribute array, rather then
* replacing the whole list
* @param ctx An initialized TALLOC_CTX
@@ -1283,7 +1352,7 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *machine_name
machine_name));
exists=1;
} else {
- char *ou_str = ads_ou_string(org_unit);
+ char *ou_str = ads_ou_string(ads,org_unit);
if (!ou_str) {
DEBUG(1, ("ads_add_machine_acct: ads_ou_string returned NULL (malloc failure?)\n"));
goto done;
diff --git a/source3/utils/net.c b/source3/utils/net.c
index da1339aed1..2bf8ac286d 100644
--- a/source3/utils/net.c
+++ b/source3/utils/net.c
@@ -69,7 +69,7 @@ int opt_port = 0;
int opt_verbose = 0;
int opt_maxusers = -1;
const char *opt_comment = "";
-const char *opt_container = "cn=Users";
+const char *opt_container = NULL;
int opt_flags = -1;
int opt_timeout = 0;
const char *opt_target_workgroup = NULL;
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 70e9e6cea8..8afc42c456 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -297,6 +297,10 @@ static int ads_user_add(int argc, const char **argv)
goto done;
}
+ if (opt_container == NULL) {
+ 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)) {
@@ -498,6 +502,10 @@ static int ads_group_add(int argc, const char **argv)
goto done;
}
+ if (opt_container == NULL) {
+ 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)) {
@@ -690,7 +698,7 @@ int net_ads_join(int argc, const char **argv)
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;
@@ -728,7 +736,7 @@ int net_ads_join(int argc, const char **argv)
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);
free(ou_str);