diff options
-rw-r--r-- | source3/libads/ldap.c | 70 | ||||
-rw-r--r-- | source3/utils/net_ads.c | 40 |
2 files changed, 101 insertions, 9 deletions
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 5a34385c32..af4347c147 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -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 */ diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 37ede28a97..030c5762f3 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -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); |