Add libnet_Unjoin(), libnet_UnjoinCtx and friends.
[ira/wip.git] / source3 / libnet / libnet_join.c
index 18421056daf845c4d1e66ee17c005a7f38259cc8..68434bd39140b9e6b13fd0b5bbffe9e40127b5ed 100644 (file)
@@ -218,6 +218,119 @@ static NTSTATUS do_DomainJoin(TALLOC_CTX *mem_ctx,
        return status;
 }
 
+static NTSTATUS do_DomainUnjoin(TALLOC_CTX *mem_ctx,
+                               struct libnet_UnjoinCtx *r)
+{
+       struct cli_state *cli = NULL;
+       struct rpc_pipe_client *pipe_hnd = NULL;
+       POLICY_HND sam_pol, domain_pol, user_pol;
+       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       char *acct_name;
+       uint32 flags = 0x3e8;
+       const char *const_acct_name;
+       uint32 user_rid;
+       uint32 num_rids, *name_types, *user_rids;
+       SAM_USERINFO_CTR ctr, *qctr = NULL;
+       SAM_USER_INFO_16 p16;
+
+       status = cli_full_connection(&cli, NULL, r->in.server_name,
+                                    NULL, 0,
+                                    "IPC$", "IPC",
+                                    r->in.admin_account,
+                                    NULL, //r->in.domain_name,
+                                    r->in.password,
+                                    0, Undefined, NULL);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+
+       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &status);
+       if (!pipe_hnd) {
+               goto done;
+       }
+
+       status = rpccli_samr_connect(pipe_hnd, mem_ctx,
+                                    SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+
+       status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &sam_pol,
+                                        SEC_RIGHTS_MAXIMUM_ALLOWED,
+                                        r->in.domain_sid,
+                                        &domain_pol);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+
+       acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname());
+       strlower_m(acct_name);
+       const_acct_name = acct_name;
+
+       status = rpccli_samr_lookup_names(pipe_hnd, mem_ctx,
+                                         &domain_pol, flags, 1,
+                                         &const_acct_name,
+                                         &num_rids, &user_rids, &name_types);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+
+       if (name_types[0] != SID_NAME_USER) {
+               status = NT_STATUS_INVALID_WORKSTATION;
+               goto done;
+       }
+
+       user_rid = user_rids[0];
+
+       status = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
+                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
+                                      user_rid, &user_pol);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+
+       status = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx,
+                                           &user_pol, 16, &qctr);
+       if (!NT_STATUS_IS_OK(status)) {
+               rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
+               goto done;
+       }
+
+       ZERO_STRUCT(ctr);
+       ctr.switch_value = 16;
+       ctr.info.id16 = &p16;
+
+       p16.acb_info = qctr->info.id16->acb_info | ACB_DISABLED;
+
+       status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol, 16,
+                                          &cli->user_session_key, &ctr);
+
+       rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
+
+       if (!secrets_delete_machine_password_ex(lp_workgroup())) {
+               status = NT_STATUS_INTERNAL_DB_ERROR;
+               goto done;
+       }
+
+       if (!secrets_delete_domain_sid(lp_workgroup())) {
+               status = NT_STATUS_INTERNAL_DB_ERROR;
+               goto done;
+       }
+
+done:
+       rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
+       rpccli_samr_close(pipe_hnd, mem_ctx, &sam_pol);
+
+       cli_rpc_pipe_close(pipe_hnd);
+
+       if (cli) {
+               cli_shutdown(cli);
+       }
+
+       return status;
+}
+
 static WERROR do_modify_val_config(struct registry_key *key,
                                   const char *val_name,
                                   const char *val_data)
@@ -233,9 +346,9 @@ static WERROR do_modify_val_config(struct registry_key *key,
        return reg_setvalue(key, val_name, &val);
 }
 
-static WERROR do_modify_vals_config(TALLOC_CTX *mem_ctx,
-                                   struct libnet_JoinCtx *r,
-                                   struct registry_key *key)
+static WERROR do_join_modify_vals_config(TALLOC_CTX *mem_ctx,
+                                        struct libnet_JoinCtx *r,
+                                        struct registry_key *key)
 {
        WERROR werr;
        bool is_ad = false;
@@ -273,6 +386,24 @@ static WERROR do_modify_vals_config(TALLOC_CTX *mem_ctx,
        return werr;
 }
 
+static WERROR do_unjoin_modify_vals_config(TALLOC_CTX *mem_ctx,
+                                          struct libnet_UnjoinCtx *r,
+                                          struct registry_key *key)
+{
+       WERROR werr;
+
+       if (r->in.unjoin_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
+
+               werr = do_modify_val_config(key, "security", "user");
+               W_ERROR_NOT_OK_RETURN(werr);
+       }
+
+       reg_deletevalue(key, "realm");
+
+       return werr;
+}
+
+
 static WERROR do_JoinConfig(TALLOC_CTX *mem_ctx,
                            struct libnet_JoinCtx *r)
 {
@@ -303,7 +434,48 @@ static WERROR do_JoinConfig(TALLOC_CTX *mem_ctx,
                return werr;
        }
 
-       werr = do_modify_vals_config(mem_ctx, r, key);
+       werr = do_join_modify_vals_config(mem_ctx, r, key);
+       if (!W_ERROR_IS_OK(werr)) {
+               return werr;
+       }
+
+       r->out.modified_config = true;
+       r->out.result = werr;
+
+       return werr;
+}
+
+static WERROR do_UnjoinConfig(TALLOC_CTX *mem_ctx,
+                             struct libnet_UnjoinCtx *r)
+{
+       WERROR werr;
+       struct registry_key *key = NULL;
+
+       if (!W_ERROR_IS_OK(r->out.result)) {
+               return r->out.result;
+       }
+
+       if (!r->in.modify_config) {
+               return WERR_OK;
+       }
+
+       if (!registry_init_regdb()) {
+               return WERR_REG_IO_FAILURE;
+       }
+
+       if (!libnet_smbconf_key_exists(mem_ctx, GLOBAL_NAME)) {
+               werr = libnet_reg_createkey_internal(mem_ctx,
+                                                    GLOBAL_NAME, &key);
+       } else {
+               werr = libnet_smbconf_open_path(mem_ctx,
+                                               GLOBAL_NAME,
+                                               REG_KEY_WRITE, &key);
+       }
+       if (!W_ERROR_IS_OK(werr)) {
+               return werr;
+       }
+
+       werr = do_unjoin_modify_vals_config(mem_ctx, r, key);
        if (!W_ERROR_IS_OK(werr)) {
                return werr;
        }
@@ -329,6 +501,21 @@ WERROR libnet_init_JoinCtx(TALLOC_CTX *mem_ctx,
        return WERR_OK;
 }
 
+WERROR libnet_init_UnjoinCtx(TALLOC_CTX *mem_ctx,
+                            struct libnet_UnjoinCtx **r)
+{
+       struct libnet_UnjoinCtx *ctx;
+
+       ctx = talloc_zero(mem_ctx, struct libnet_UnjoinCtx);
+       if (!ctx) {
+               return WERR_NOMEM;
+       }
+
+       *r = ctx;
+
+       return WERR_OK;
+}
+
 WERROR libnet_Join(TALLOC_CTX *mem_ctx,
                   struct libnet_JoinCtx *r)
 {
@@ -361,3 +548,34 @@ WERROR libnet_Join(TALLOC_CTX *mem_ctx,
 
        return werr;
 }
+
+WERROR libnet_Unjoin(TALLOC_CTX *mem_ctx,
+                    struct libnet_UnjoinCtx *r)
+{
+       WERROR werr;
+       NTSTATUS status;
+
+       printf("libnet_Unjoin\n");
+
+       if (r->in.modify_config && !lp_include_registry_globals()) {
+               return WERR_NOT_SUPPORTED;
+       }
+
+       if (r->in.unjoin_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
+
+               status = do_DomainUnjoin(mem_ctx, r);
+               if (!NT_STATUS_IS_OK(status)) {
+                       if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
+                               return WERR_SETUP_NOT_JOINED;
+                       }
+                       return ntstatus_to_werror(status);
+               }
+       }
+
+       werr = do_UnjoinConfig(mem_ctx, r);
+       if (!W_ERROR_IS_OK(werr)) {
+               return werr;
+       }
+
+       return werr;
+}