much better support for organisational units in ADS join
authorAndrew Tridgell <tridge@samba.org>
Wed, 16 Jan 2002 02:22:30 +0000 (02:22 +0000)
committerAndrew Tridgell <tridge@samba.org>
Wed, 16 Jan 2002 02:22:30 +0000 (02:22 +0000)
(This used to be commit 7e876057d5e392f85e6fdb0f2c233b0fe76df688)

source3/libads/ads_struct.c
source3/libads/ldap.c
source3/utils/net_ads.c

index 013491eaed132969210604e3f8fc52c7d5eb9d24..476152f2c2d5e3f7a88266c541c8269a53ac6b94 100644 (file)
 
 #include "includes.h"
 
-/* return a dn of the form "dc=AA,dc=BB,dc=CC" from a 
-   realm of the form AA.BB.CC 
+/* return a ldap dn path from a string, given separators and field name
    caller must free
 */
-char *ads_build_dn(const char *realm)
+char *ads_build_path(const char *realm, const char *sep, const char *field, int reverse)
 {
        char *p, *r;
-       int numdots = 0;
+       int numbits = 0;
        char *ret;
        int len;
        
@@ -38,19 +37,25 @@ char *ads_build_dn(const char *realm)
        if (!r || !*r) return r;
 
        for (p=r; *p; p++) {
-               if (*p == '.') numdots++;
+               if (strchr(sep, *p)) numbits++;
        }
 
-       len = (numdots+1)*4 + strlen(r) + 1;
+       len = (numbits+1)*(strlen(field)+1) + strlen(r) + 1;
 
        ret = malloc(len);
-       strlcpy(ret,"dc=", len);
-       p=strtok(r,"."); 
+       strlcpy(ret,field, len);
+       p=strtok(r,sep); 
        strlcat(ret, p, len);
 
-       while ((p=strtok(NULL,"."))) {
-               strlcat(ret,",dc=", len);
-               strlcat(ret, p, len);
+       while ((p=strtok(NULL,sep))) {
+               char *s;
+               if (reverse) {
+                       asprintf(&s, "%s%s,%s", field, p, ret);
+               } else {
+                       asprintf(&s, "%s,%s%s", ret, field, p);
+               }
+               free(ret);
+               ret = s;
        }
 
        free(r);
@@ -58,6 +63,15 @@ char *ads_build_dn(const char *realm)
        return ret;
 }
 
+/* return a dn of the form "dc=AA,dc=BB,dc=CC" from a 
+   realm of the form AA.BB.CC 
+   caller must free
+*/
+char *ads_build_dn(const char *realm)
+{
+       return ads_build_path(realm, ".", "dc=", 0);
+}
+
 
 #ifdef HAVE_LDAP
 /*
index 2e93e11603a61bcd15c1b1edb492a9841965e1bd..d922e4c7c566732f45e450b09f88d9000d4b559b 100644 (file)
@@ -172,6 +172,23 @@ ADS_STATUS ads_gen_add(ADS_STRUCT *ads, const char *new_dn, ...)
        return ADS_ERROR(ret);
 }
 
+/*
+  build an org unit string
+  if org unit is Computers or blank then assume a container, otherwise
+  assume a \ separated list of organisational units
+  caller must free
+*/
+char *ads_ou_string(const char *org_unit)
+{      
+       if (!org_unit || !*org_unit || strcasecmp(org_unit, "Computers") == 0) {
+               return strdup("cn=Computers");
+       }
+
+       return ads_build_path(org_unit, "\\/", "ou=", 1);
+}
+
+
+
 /*
   add a machine account to the ADS server
 */
@@ -180,10 +197,13 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname,
 {
        ADS_STATUS ret;
        char *host_spn, *host_upn, *new_dn, *samAccountName, *controlstr;
+       char *ou_str;
 
        asprintf(&host_spn, "HOST/%s", hostname);
        asprintf(&host_upn, "%s@%s", host_spn, ads->realm);
-       asprintf(&new_dn, "cn=%s,cn=%s,%s", hostname, org_unit, ads->bind_path);
+       ou_str = ads_ou_string(org_unit);
+       asprintf(&new_dn, "cn=%s,%s,%s", hostname, ou_str, ads->bind_path);
+       free(ou_str);
        asprintf(&samAccountName, "%s$", hostname);
        asprintf(&controlstr, "%u", 
                UF_DONT_EXPIRE_PASSWD | UF_WORKSTATION_TRUST_ACCOUNT | 
index 7baa29723054cdda389b2973686c49ebff3708ec..fec31c6ea3f8e07cc3257080b47366158397eee2 100644 (file)
@@ -211,6 +211,7 @@ static int net_ads_join(int argc, const char **argv)
        char *dn;
        void *res;
        DOM_SID dom_sid;
+       char *ou_str;
 
        if (argc > 0) org_unit = argv[0];
 
@@ -224,16 +225,19 @@ static int net_ads_join(int argc, const char **argv)
 
        if (!(ads = ads_startup())) return -1;
 
-       asprintf(&dn, "cn=%s,%s", org_unit, ads->bind_path);
+       ou_str = ads_ou_string(org_unit);
+       asprintf(&dn, "%s,%s", ou_str, ads->bind_path);
+       free(ou_str);
 
        rc = ads_search_dn(ads, &res, dn, NULL);
-       free(dn);
        ads_msgfree(ads, res);
 
        if (rc.error_type == ADS_ERROR_LDAP && rc.rc == LDAP_NO_SUCH_OBJECT) {
-               d_printf("ads_join_realm: organisational unit %s does not exist\n", org_unit);
+               d_printf("ads_join_realm: organisational unit %s does not exist (dn:%s)\n", 
+                        org_unit, dn);
                return -1;
        }
+       free(dn);
 
        if (!ADS_ERR_OK(rc)) {
                d_printf("ads_join_realm: %s\n", ads_errstr(rc));