diff options
Diffstat (limited to 'source3/libnet')
-rw-r--r-- | source3/libnet/libnet.h | 26 | ||||
-rw-r--r-- | source3/libnet/libnet_conf.c | 195 | ||||
-rw-r--r-- | source3/libnet/libnet_join.c | 583 | ||||
-rw-r--r-- | source3/libnet/libnet_join.h | 65 |
4 files changed, 869 insertions, 0 deletions
diff --git a/source3/libnet/libnet.h b/source3/libnet/libnet.h new file mode 100644 index 0000000000..fa24c3b40a --- /dev/null +++ b/source3/libnet/libnet.h @@ -0,0 +1,26 @@ +/* + * Unix SMB/CIFS implementation. + * libnet Support + * Copyright (C) Guenther Deschner 2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __LIBNET_H__ +#define __LIBNET_H__ + +#include "libnet/libnet_join.h" +#include "libnet/libnet_proto.h" + +#endif diff --git a/source3/libnet/libnet_conf.c b/source3/libnet/libnet_conf.c new file mode 100644 index 0000000000..8bc5161268 --- /dev/null +++ b/source3/libnet/libnet_conf.c @@ -0,0 +1,195 @@ +/* + * Unix SMB/CIFS implementation. + * libnet smbconf registry Support + * Copyright (C) Michael Adam 2007 + * Copyright (C) Guenther Deschner 2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "includes.h" + +/* + * Open a subkey of KEY_SMBCONF (i.e a service) + * - variant without error output (q = quiet)- + */ +WERROR libnet_smbconf_open_path_q(TALLOC_CTX *ctx, const char *subkeyname, + uint32 desired_access, + struct registry_key **key) +{ + WERROR werr = WERR_OK; + char *path = NULL; + NT_USER_TOKEN *token; + + if (!(token = registry_create_admin_token(ctx))) { + DEBUG(1, ("Error creating admin token\n")); + goto done; + } + + if (subkeyname == NULL) { + path = talloc_strdup(ctx, KEY_SMBCONF); + } else { + path = talloc_asprintf(ctx, "%s\\%s", KEY_SMBCONF, subkeyname); + } + + werr = reg_open_path(ctx, path, desired_access, + token, key); + +done: + TALLOC_FREE(path); + return werr; +} + +/* + * check if a subkey of KEY_SMBCONF of a given name exists + */ +bool libnet_smbconf_key_exists(TALLOC_CTX *ctx, const char *subkeyname) +{ + bool ret = False; + WERROR werr = WERR_OK; + TALLOC_CTX *mem_ctx; + struct registry_key *key; + + if (!(mem_ctx = talloc_new(ctx))) { + d_fprintf(stderr, "ERROR: Out of memory...!\n"); + goto done; + } + + werr = libnet_smbconf_open_path_q(mem_ctx, subkeyname, REG_KEY_READ, &key); + if (W_ERROR_IS_OK(werr)) { + ret = True; + } + +done: + TALLOC_FREE(mem_ctx); + return ret; +} + +/* + * Open a subkey of KEY_SMBCONF (i.e a service) + * - variant with error output - + */ +WERROR libnet_smbconf_open_path(TALLOC_CTX *ctx, const char *subkeyname, + uint32 desired_access, + struct registry_key **key) +{ + WERROR werr = WERR_OK; + + werr = libnet_smbconf_open_path_q(ctx, subkeyname, desired_access, key); + if (!W_ERROR_IS_OK(werr)) { + d_fprintf(stderr, "Error opening registry path '%s\\%s': %s\n", + KEY_SMBCONF, + (subkeyname == NULL) ? "" : subkeyname, + dos_errstr(werr)); + } + + return werr; +} + +/* + * open the base key KEY_SMBCONF + */ +WERROR libnet_smbconf_open_basepath(TALLOC_CTX *ctx, uint32 desired_access, + struct registry_key **key) +{ + return libnet_smbconf_open_path(ctx, NULL, desired_access, key); +} + +/* + * create a subkey of KEY_SMBCONF + */ +WERROR libnet_reg_createkey_internal(TALLOC_CTX *ctx, + const char * subkeyname, + struct registry_key **newkey) +{ + WERROR werr = WERR_OK; + struct registry_key *create_parent = NULL; + TALLOC_CTX *create_ctx; + enum winreg_CreateAction action = REG_ACTION_NONE; + + /* create a new talloc ctx for creation. it will hold + * the intermediate parent key (SMBCONF) for creation + * and will be destroyed when leaving this function... */ + if (!(create_ctx = talloc_new(ctx))) { + werr = WERR_NOMEM; + goto done; + } + + werr = libnet_smbconf_open_basepath(create_ctx, REG_KEY_WRITE, &create_parent); + if (!W_ERROR_IS_OK(werr)) { + goto done; + } + + werr = reg_createkey(ctx, create_parent, subkeyname, + REG_KEY_WRITE, newkey, &action); + if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) { + d_fprintf(stderr, "Key '%s' already exists.\n", subkeyname); + werr = WERR_ALREADY_EXISTS; + } + if (!W_ERROR_IS_OK(werr)) { + d_fprintf(stderr, "Error creating key %s: %s\n", + subkeyname, dos_errstr(werr)); + } + +done: + TALLOC_FREE(create_ctx); + return werr; +} + +static WERROR do_modify_val_config(struct registry_key *key, + const char *val_name, + const char *val_data) +{ + struct registry_value val; + + ZERO_STRUCT(val); + + val.type = REG_SZ; + val.v.sz.str = CONST_DISCARD(char *, val_data); + val.v.sz.len = strlen(val_data) + 1; + + return reg_setvalue(key, val_name, &val); +} + +WERROR libnet_smbconf_set_global_param(TALLOC_CTX *mem_ctx, + const char *param, + const char *val) +{ + WERROR werr; + struct registry_key *key = NULL; + + if (!lp_include_registry_globals()) { + return WERR_NOT_SUPPORTED; + } + + 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; + } + + return do_modify_val_config(key, param, val); +} + diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c new file mode 100644 index 0000000000..2994c3f59d --- /dev/null +++ b/source3/libnet/libnet_join.c @@ -0,0 +1,583 @@ +/* + * Unix SMB/CIFS implementation. + * libnet Join Support + * Copyright (C) Gerald (Jerry) Carter 2006 + * Copyright (C) Guenther Deschner 2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "includes.h" +#include "libnet/libnet_join.h" +#include "libnet/libnet_proto.h" + +static NTSTATUS do_DomainJoin(TALLOC_CTX *mem_ctx, + struct libnet_JoinCtx *r) +{ + struct cli_state *cli = NULL; + struct rpc_pipe_client *pipe_hnd = NULL; + const char *password = NULL; + POLICY_HND sam_pol, domain_pol, user_pol, lsa_pol; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + char *acct_name; + const char *const_acct_name; + uint32 user_rid; + uint32 num_rids, *name_types, *user_rids; + uint32 flags = 0x3e8; + uint32 acb_info = ACB_WSTRUST; + uint32 fields_present; + uchar pwbuf[532]; + SAM_USERINFO_CTR ctr; + SAM_USER_INFO_25 p25; + const int infolevel = 25; + struct MD5Context md5ctx; + uchar md5buffer[16]; + DATA_BLOB digested_session_key; + uchar md4_trust_password[16]; + + password = talloc_strdup(mem_ctx, + generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH)); + NT_STATUS_HAVE_NO_MEMORY(password); + + 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_LSARPC, &status); + if (!pipe_hnd) { + goto done; + } + + status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, + SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = rpccli_lsa_query_info_policy2(pipe_hnd, mem_ctx, &lsa_pol, + 12, + &r->out.netbios_domain_name, + &r->out.dns_domain_name, + NULL, + NULL, + &r->out.domain_sid); + + if (!NT_STATUS_IS_OK(status)) { + status = rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx, &lsa_pol, + 5, + &r->out.netbios_domain_name, + &r->out.domain_sid); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + } + + rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol); + cli_rpc_pipe_close(pipe_hnd); + + 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->out.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_create_dom_user(pipe_hnd, mem_ctx, &domain_pol, + acct_name, ACB_WSTRUST, + 0xe005000b, &user_pol, &user_rid); + if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) { + if (!(r->in.join_flags & WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED)) { + goto done; + } + } + + if (NT_STATUS_IS_OK(status)) { + rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol); + } + + 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; + } + + E_md4hash(r->in.password, md4_trust_password); + encode_pw_buffer(pwbuf, r->in.password, STR_UNICODE); + + generate_random_buffer((uint8*)md5buffer, sizeof(md5buffer)); + digested_session_key = data_blob_talloc(mem_ctx, 0, 16); + + MD5Init(&md5ctx); + MD5Update(&md5ctx, md5buffer, sizeof(md5buffer)); + MD5Update(&md5ctx, cli->user_session_key.data, cli->user_session_key.length); + MD5Final(digested_session_key.data, &md5ctx); + + SamOEMhashBlob(pwbuf, sizeof(pwbuf), &digested_session_key); + memcpy(&pwbuf[516], md5buffer, sizeof(md5buffer)); + + acb_info |= ACB_PWNOEXP; +#if 0 + if ( dom_type == ND_TYPE_AD ) { +#if !defined(ENCTYPE_ARCFOUR_HMAC) + acb_info |= ACB_USE_DES_KEY_ONLY; +#endif + ;; + } +#endif + ZERO_STRUCT(ctr); + ZERO_STRUCT(p25); + + fields_present = ACCT_NT_PWD_SET | ACCT_LM_PWD_SET | ACCT_FLAGS; + init_sam_user_info25P(&p25, fields_present, acb_info, (char *)pwbuf); + + ctr.switch_value = infolevel; + ctr.info.id25 = &p25; + + status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol, + infolevel, &cli->user_session_key, + &ctr); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol); + cli_rpc_pipe_close(pipe_hnd); + + if (!secrets_store_domain_sid(r->out.netbios_domain_name, + r->out.domain_sid)) + { + status = NT_STATUS_INTERNAL_DB_ERROR; + goto done; + } + + if (!secrets_store_machine_password(password, + r->out.netbios_domain_name, + SEC_CHAN_WKSTA)) + { + status = NT_STATUS_INTERNAL_DB_ERROR; + goto done; + } + + status = NT_STATUS_OK; + done: + if (cli) { + cli_shutdown(cli); + } + + 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) +{ + struct registry_value val; + + ZERO_STRUCT(val); + + val.type = REG_SZ; + val.v.sz.str = CONST_DISCARD(char *, val_data); + val.v.sz.len = strlen(val_data) + 1; + + return reg_setvalue(key, val_name, &val); +} + +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; + + if (!(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE)) { + + werr = do_modify_val_config(key, "security", "user"); + W_ERROR_NOT_OK_RETURN(werr); + + werr = do_modify_val_config(key, "workgroup", + r->in.domain_name); + return werr; + } + + if (r->out.dns_domain_name) { + is_ad = true; + } + + werr = do_modify_val_config(key, "security", "domain"); + W_ERROR_NOT_OK_RETURN(werr); + + werr = do_modify_val_config(key, "workgroup", + r->out.netbios_domain_name); + W_ERROR_NOT_OK_RETURN(werr); + + if (is_ad) { + werr = do_modify_val_config(key, "security", "ads"); + W_ERROR_NOT_OK_RETURN(werr); + + werr = do_modify_val_config(key, "realm", + r->out.dns_domain_name); + W_ERROR_NOT_OK_RETURN(werr); + } + + return werr; +} + +static WERROR do_unjoin_modify_vals_config(TALLOC_CTX *mem_ctx, + struct libnet_UnjoinCtx *r, + struct registry_key *key) +{ + WERROR werr = WERR_OK; + + 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) +{ + 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_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; + } + + r->out.modified_config = true; + r->out.result = werr; + + return werr; +} + +WERROR libnet_init_JoinCtx(TALLOC_CTX *mem_ctx, + struct libnet_JoinCtx **r) +{ + struct libnet_JoinCtx *ctx; + + ctx = talloc_zero(mem_ctx, struct libnet_JoinCtx); + if (!ctx) { + return WERR_NOMEM; + } + + *r = 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) +{ + WERROR werr; + NTSTATUS status; + + if (!r->in.domain_name) { + return WERR_INVALID_PARAM; + } + + if (r->in.modify_config && !lp_include_registry_globals()) { + return WERR_NOT_SUPPORTED; + } + + if (IS_DC) { + return WERR_SETUP_DOMAIN_CONTROLLER; + } + + if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) { + + status = do_DomainJoin(mem_ctx, r); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) { + return WERR_SETUP_ALREADY_JOINED; + } + return ntstatus_to_werror(status); + } + } + + werr = do_JoinConfig(mem_ctx, r); + if (!W_ERROR_IS_OK(werr)) { + return werr; + } + + return werr; +} + +WERROR libnet_Unjoin(TALLOC_CTX *mem_ctx, + struct libnet_UnjoinCtx *r) +{ + WERROR werr; + NTSTATUS status; + + 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 new file mode 100644 index 0000000000..46ab27e8b0 --- /dev/null +++ b/source3/libnet/libnet_join.h @@ -0,0 +1,65 @@ +/* + * Unix SMB/CIFS implementation. + * libnet Join Support + * Copyright (C) Guenther Deschner 2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __LIBNET_JOIN_H__ +#define __LIBNET_JOIN_H__ + +struct libnet_JoinCtx { + struct { + const char *server_name; + const char *domain_name; + const char *account_ou; + const char *admin_account; + const char *password; + uint32_t join_flags; + const char *os_version; + const char *os_string; + const char *upn; + bool modify_config; + } in; + + struct { + char *account_name; + 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; +}; + +#endif |