r22728: Patch from Danilo Almeida <dalmeida@centeris.com>:
authorGerald Carter <jerry@samba.org>
Sun, 6 May 2007 21:45:53 +0000 (21:45 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:21:51 +0000 (12:21 -0500)
When asked to create a machine account in an OU as part
of "net ads join" and the account already exists in another
OU, simply move the machine object to the requested OU.
(This used to be commit 3004cc6e593e6659a618de66f659f579e71c07f7)

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

index 5a34385c32a3c96c061b4e76b64a527126908020..af4347c1474405b22f8baa939ba4527b584707d2 100644 (file)
@@ -1688,6 +1688,76 @@ done:
        return ret;
 }
 
+/**
+ * move a machine account to another OU on the ADS server
+ * @param ads - An intialized ADS_STRUCT
+ * @param machine_name - the NetBIOS machine name of this account.
+ * @param org_unit - The LDAP path in which to place this account
+ * @param moved - whether we moved the machine account (optional)
+ * @return 0 upon success, or non-zero otherwise
+**/
+
+ADS_STATUS ads_move_machine_acct(ADS_STRUCT *ads, const char *machine_name, 
+                                 const char *org_unit, BOOL *moved)
+{
+       ADS_STATUS rc;
+       int ldap_status;
+       LDAPMessage *res = NULL;
+       char *filter = NULL;
+       char *computer_dn = NULL;
+       char *parent_dn;
+       char *computer_rdn = NULL;
+       BOOL need_move = False;
+
+       if (asprintf(&filter, "(samAccountName=%s$)", machine_name) == -1) {
+               rc = ADS_ERROR(LDAP_NO_MEMORY);
+               goto done;
+       }
+
+       /* Find pre-existing machine */
+       rc = ads_search(ads, &res, filter, NULL);
+       if (!ADS_ERR_OK(rc)) {
+               goto done;
+       }
+
+       computer_dn = ads_get_dn(ads, res);
+       if (!computer_dn) {
+               rc = ADS_ERROR(LDAP_NO_MEMORY);
+               goto done;
+       }
+
+       parent_dn = ads_parent_dn(computer_dn);
+       if (strequal(parent_dn, org_unit)) {
+               goto done;
+       }
+
+       need_move = True;
+
+       if (asprintf(&computer_rdn, "CN=%s", machine_name) == -1) {
+               rc = ADS_ERROR(LDAP_NO_MEMORY);
+               goto done;
+       }
+
+       ldap_status = ldap_rename2_s(ads->ld, computer_dn, computer_rdn, org_unit, 1);
+       rc = ADS_ERROR(ldap_status);
+
+done:
+       ads_msgfree(ads, res);
+       SAFE_FREE(filter);
+       SAFE_FREE(computer_dn);
+       SAFE_FREE(computer_rdn);
+
+       if (!ADS_ERR_OK(rc)) {
+               need_move = False;
+       }
+
+       if (moved) {
+               *moved = need_move;
+       }
+
+       return rc;
+}
+
 /*
   dump a binary result from ldap
 */
index 37ede28a9767bf225924f9c4b3131c955baa0646..030c5762f3ec2b059a0935414c73f6f1b61d1eed 100644 (file)
@@ -1190,28 +1190,50 @@ done:
 static ADS_STATUS net_precreate_machine_acct( ADS_STRUCT *ads, const char *ou )
 {
        ADS_STATUS rc = ADS_ERROR(LDAP_SERVER_DOWN);
-       char *dn, *ou_str;
+       char *ou_str = NULL;
+       char *dn = NULL;
        LDAPMessage *res = NULL;
+       BOOL moved;
 
        ou_str = ads_ou_string(ads, ou);
-       if ((asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path)) == -1) {
-               SAFE_FREE(ou_str);
-               return ADS_ERROR(LDAP_NO_MEMORY);
+       if (asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path) == -1) {
+               rc = ADS_ERROR(LDAP_NO_MEMORY);
+               goto done;
        }
 
        rc = ads_search_dn(ads, &res, dn, NULL);
-       ads_msgfree(ads, res);
+       if (!ADS_ERR_OK(rc)) {
+               d_fprintf(stderr, "The specified OU does not exist.\n");
+               goto done;
+       }
 
-       if (ADS_ERR_OK(rc)) {
                /* Attempt to create the machine account and bail if this fails.
                   Assume that the admin wants exactly what they requested */
 
                rc = ads_create_machine_acct( ads, global_myname(), dn );
-               if ( rc.error_type == ENUM_ADS_ERROR_LDAP && rc.err.rc == LDAP_ALREADY_EXISTS ) {
-                       rc = ADS_SUCCESS;
+       if (ADS_ERR_OK(rc)) {
+               DEBUG(1, ("machine account created\n"));
+               goto done;
                }
+       if ( !(rc.error_type == ENUM_ADS_ERROR_LDAP && rc.err.rc == LDAP_ALREADY_EXISTS) ) {
+               DEBUG(1, ("machine account creation failed\n"));
+               goto done;
+       }
+
+       rc = ads_move_machine_acct(ads, global_myname(), dn, &moved);
+       if (!ADS_ERR_OK(rc)) {
+               DEBUG(1, ("failure to locate/move pre-existing machine account\n"));
+               goto done;
        }
 
+       if (moved) {
+               d_printf("The machine account was moved into the specified OU.\n");
+       } else {
+               d_printf("The machine account already exists in the specified OU.\n");
+       }
+
+done:
+       ads_msgfree(ads, res);
        SAFE_FREE( ou_str );
        SAFE_FREE( dn );
 
@@ -1528,7 +1550,7 @@ int net_ads_join(int argc, const char **argv)
                status = net_precreate_machine_acct( ads, create_in_ou );
                if ( !ADS_ERR_OK(status) ) {
                        d_fprintf( stderr, "Failed to pre-create the machine object "
-                               "in OU %s.\n", argv[0]);
+                               "in OU %s.\n", create_in_ou);
                        DEBUG(1, ("error calling net_precreate_machine_acct: %s\n", 
                                  ads_errstr(status)));
                        nt_status = ads_ntstatus(status);