]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
Don't require "Modify property" perms to unjoin (bug #6481) "net ads leave" stopped...
authorJim McDonough <jmcd@samba.org>
Mon, 29 Jun 2009 13:42:35 +0000 (09:42 -0400)
committerKarolin Seeger <kseeger@samba.org>
Tue, 30 Jun 2009 07:08:50 +0000 (09:08 +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.

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 d15e2e733c25f901d55205ae1ea18e5c56b62a3f..93c2eed8ee173dd0906462edd39f9ff43557f46d 100644 (file)
@@ -207,6 +207,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 1016e9ceaabd68dad73f9e231a436cee3ff220ad..9029d616e914d25205060414a32efac3d45d9dd0 100644 (file)
@@ -1923,6 +1923,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;
@@ -1948,38 +1954,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 ed49062a78cdadbd8a5bc4fc1f84390ad82d50bb..9daf3cd8b247db7d9e33be3ef7bd814da592ab17 100644 (file)
@@ -58,6 +58,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 79fcd16a90ef1ca90a4c911c888ef5d4ce7ddcc9..ba31ea63652e625c3d8a30ddd9643a1894642909 100644 (file)
@@ -89,6 +89,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 c600ea094a8fe8a4da6e13c45de6a552fc4c2342..80429dc2fd8ea7dfbae86d77218fb9dbee74872b 100644 (file)
@@ -53,6 +53,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 d0f7430174a308e5d303c161c8f1ef6df125bf3d..648104718a6305792a7620e26cb5a710670cacce 100644 (file)
@@ -901,8 +901,12 @@ static int net_ads_leave(struct net_context *c, int argc, const char **argv)
        r->in.admin_account     = c->opt_user_name;
        r->in.admin_password    = net_prompt_pass(c, c->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)) {
@@ -912,7 +916,7 @@ static int net_ads_leave(struct net_context *c, 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;
@@ -926,7 +930,10 @@ static int net_ads_leave(struct net_context *c, 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: