Don't require "Modify property" perms to unjoin (bug #6481) "net ads leave" stopped...
authorJim McDonough <jmcd@samba.org>
Mon, 29 Jun 2009 14:06:14 +0000 (10:06 -0400)
committerKarolin Seeger <kseeger@samba.org>
Mon, 10 Aug 2009 15:53:10 +0000 (17:53 +0200)
Libnetapi should not delete machine accounts, as this does not
happen on win32.  The WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE flag
really means "disable" (both in practice and docs).

However, to keep the functionality in "net ads leave", we
will still try to do the delete.  If this fails, we try
to do the disable.

Additionally, it is possible in windows to not disable or
delete the account, but just tell the local machine that it
is no longer in the account.  libnet can now do this as well.

Don't use ads realm name for non-ads case.  #6481

Also check that the connection to ads worked.
(cherry picked from commit 880d1a3f83a0834225d5a7c0f179c236b0e59ef8)

source/lib/netapi/joindomain.c
source/libnet/libnet_join.c
source/librpc/gen_ndr/libnet_join.h
source/librpc/gen_ndr/ndr_libnet_join.c
source/librpc/idl/libnet_join.idl
source/utils/net_ads.c

index 66f7cfb13ff8ee7fbc1cd88051eab1d0fbd318a3..c204a8097162d52eb41c9ba63e09d2aca43e096b 100644 (file)
@@ -209,6 +209,7 @@ WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
 
        u->in.domain_name = domain;
        u->in.unjoin_flags = r->in.unjoin_flags;
+       u->in.delete_machine_account = false;
        u->in.modify_config = true;
        u->in.debug = true;
 
index c13ac9b769e3219c9560f3254f76d2b3cac89237..face9d3a35b369cf37b66138d4c08fea435b0f67 100644 (file)
@@ -1835,6 +1835,12 @@ static WERROR libnet_DomainUnjoin(TALLOC_CTX *mem_ctx,
                W_ERROR_HAVE_NO_MEMORY(r->in.domain_sid);
        }
 
+       if (!(r->in.unjoin_flags & WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE) &&
+           !r->in.delete_machine_account) {
+               libnet_join_unjoindomain_remove_secrets(mem_ctx, r);
+               return WERR_OK;
+       }
+
        if (!r->in.dc_name) {
                struct netr_DsRGetDCNameInfo *info;
                const char *dc;
@@ -1860,38 +1866,55 @@ static WERROR libnet_DomainUnjoin(TALLOC_CTX *mem_ctx,
                W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
        }
 
-       status = libnet_join_unjoindomain_rpc(mem_ctx, r);
-       if (!NT_STATUS_IS_OK(status)) {
-               libnet_unjoin_set_error_string(mem_ctx, r,
-                       "failed to disable machine account via rpc: %s",
-                       get_friendly_nt_error_msg(status));
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
-                       return WERR_SETUP_NOT_JOINED;
-               }
-               return ntstatus_to_werror(status);
-       }
-
-       r->out.disabled_machine_account = true;
-
 #ifdef WITH_ADS
-       if (r->in.unjoin_flags & WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE) {
+       /* for net ads leave, try to delete the account.  If it works,
+          no sense in disabling.  If it fails, we can still try to
+          disable it. jmcd */
+
+       if (r->in.delete_machine_account) {
                ADS_STATUS ads_status;
-               libnet_unjoin_connect_ads(mem_ctx, r);
-               ads_status = libnet_unjoin_remove_machine_acct(mem_ctx, r);
+               ads_status = libnet_unjoin_connect_ads(mem_ctx, r);
+               if (ADS_ERR_OK(ads_status)) {
+                       /* dirty hack */
+                       r->out.dns_domain_name =
+                               talloc_strdup(mem_ctx,
+                                             r->in.ads->server.realm);
+                       ads_status =
+                               libnet_unjoin_remove_machine_acct(mem_ctx, r);
+               }
                if (!ADS_ERR_OK(ads_status)) {
                        libnet_unjoin_set_error_string(mem_ctx, r,
                                "failed to remove machine account from AD: %s",
                                ads_errstr(ads_status));
                } else {
                        r->out.deleted_machine_account = true;
-                       /* dirty hack */
-                       r->out.dns_domain_name = talloc_strdup(mem_ctx,
-                                                              r->in.ads->server.realm);
                        W_ERROR_HAVE_NO_MEMORY(r->out.dns_domain_name);
+                       libnet_join_unjoindomain_remove_secrets(mem_ctx, r);
+                       return WERR_OK;
                }
        }
 #endif /* WITH_ADS */
 
+       /* The WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE flag really means
+          "disable".  */
+       if (r->in.unjoin_flags & WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE) {
+               status = libnet_join_unjoindomain_rpc(mem_ctx, r);
+               if (!NT_STATUS_IS_OK(status)) {
+                       libnet_unjoin_set_error_string(mem_ctx, r,
+                               "failed to disable machine account via rpc: %s",
+                               get_friendly_nt_error_msg(status));
+                       if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
+                               return WERR_SETUP_NOT_JOINED;
+                       }
+                       return ntstatus_to_werror(status);
+               }
+
+               r->out.disabled_machine_account = true;
+       }
+
+       /* If disable succeeded or was not requested at all, we
+          should be getting rid of our end of things */
+
        libnet_join_unjoindomain_remove_secrets(mem_ctx, r);
 
        return WERR_OK;
index e5ec438bb5842234cb9d1b553213e5e27bb7f557..0de71323248319356a5df1ff9580f552060afbcd 100644 (file)
@@ -56,6 +56,7 @@ struct libnet_UnjoinCtx {
                const char * admin_password;
                const char * machine_password;
                uint32_t unjoin_flags;
+               uint8_t delete_machine_account;
                uint8_t modify_config;
                struct dom_sid *domain_sid;/* [ref] */
                struct ads_struct *ads;/* [ref] */
index 753859f0ed7c6793dbe86a95bab9cab06e83b7db..a550cd61104c2f14c271df0a329fe124d2c6444b 100644 (file)
@@ -87,6 +87,7 @@ _PUBLIC_ void ndr_print_libnet_UnjoinCtx(struct ndr_print *ndr, const char *name
                ndr_print_ptr(ndr, "machine_password", r->in.machine_password);
 #endif
                ndr_print_wkssvc_joinflags(ndr, "unjoin_flags", r->in.unjoin_flags);
+               ndr_print_uint8(ndr, "delete_machine_account", r->in.delete_machine_account);
                ndr_print_uint8(ndr, "modify_config", r->in.modify_config);
                ndr_print_ptr(ndr, "domain_sid", r->in.domain_sid);
                ndr->depth++;
index 7f6e3464556bb7fc789a265337a1cb7a455119d8..93b1f0989f79ec52544ea28de5740f4627a5e634 100644 (file)
@@ -51,6 +51,7 @@ interface libnetjoin
                [in] string admin_password,
                [in] string machine_password,
                [in] wkssvc_joinflags unjoin_flags,
+               [in] boolean8 delete_machine_account,
                [in] boolean8 modify_config,
                [in] dom_sid *domain_sid,
                [in] ads_struct *ads,
index a023a11a066171bd301703ca65dfcc29b6c14f24..3c27b4ccb2a8a6d7958507cb90b561a4bd704bf0 100644 (file)
@@ -835,8 +835,12 @@ static int net_ads_leave(int argc, const char **argv)
        r->in.admin_account     = opt_user_name;
        r->in.admin_password    = net_prompt_pass(opt_user_name);
        r->in.modify_config     = lp_config_backend_is_registry();
+
+       /* Try to delete it, but if that fails, disable it.  The
+          WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
        r->in.unjoin_flags      = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
                                  WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
+       r->in.delete_machine_account = true;
 
        werr = libnet_Unjoin(ctx, r);
        if (!W_ERROR_IS_OK(werr)) {
@@ -846,7 +850,7 @@ static int net_ads_leave(int argc, const char **argv)
                goto done;
        }
 
-       if (W_ERROR_IS_OK(werr)) {
+       if (r->out.deleted_machine_account) {
                d_printf("Deleted account for '%s' in realm '%s'\n",
                        r->in.machine_name, r->out.dns_domain_name);
                goto done;
@@ -860,7 +864,10 @@ static int net_ads_leave(int argc, const char **argv)
                goto done;
        }
 
-       d_fprintf(stderr, "Failed to disable machine account for '%s' in realm '%s'\n",
+       /* Based on what we requseted, we shouldn't get here, but if
+          we did, it means the secrets were removed, and therefore
+          we have left the domain */
+       d_fprintf(stderr, "Machine '%s' Left domain '%s'\n",
                  r->in.machine_name, r->out.dns_domain_name);
 
  done: