From 41467ffc6d2588bfc9cd112586f6036c185536b2 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 19 Dec 2007 11:02:39 +0100 Subject: Add libnet_Unjoin(), libnet_UnjoinCtx and friends. Guenther (This used to be commit 89e8abb1163984eed358a4da9be4699a8e3a43f9) --- source3/libnet/libnet_join.c | 226 ++++++++++++++++++++++++++++++++++++++++++- source3/libnet/libnet_join.h | 17 ++++ 2 files changed, 239 insertions(+), 4 deletions(-) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index 18421056da..68434bd391 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -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; +} diff --git a/source3/libnet/libnet_join.h b/source3/libnet/libnet_join.h index 9596733cee..46ab27e8b0 100644 --- a/source3/libnet/libnet_join.h +++ b/source3/libnet/libnet_join.h @@ -39,8 +39,25 @@ struct libnet_JoinCtx { char *netbios_domain_name; char *dns_domain_name; char *dn; + struct dom_sid *domain_sid; bool modified_config; + WERROR result; + } out; +}; + +struct libnet_UnjoinCtx { + struct { + const char *server_name; + const char *domain_name; + const char *admin_account; + const char *password; + uint32_t unjoin_flags; + bool modify_config; struct dom_sid *domain_sid; + } in; + + struct { + bool modified_config; WERROR result; } out; }; -- cgit