/* * Unix SMB/CIFS implementation. * Group Policy Object Support * Copyright (C) Guenther Deschner 2007-2008 * * 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 . */ #include "includes.h" /**************************************************************** ****************************************************************/ struct nt_user_token *registry_create_system_token(TALLOC_CTX *mem_ctx) { struct nt_user_token *token = NULL; token = TALLOC_ZERO_P(mem_ctx, struct nt_user_token); if (!token) { DEBUG(1,("talloc failed\n")); return NULL; } token->privileges = se_priv_all; if (!NT_STATUS_IS_OK(add_sid_to_array(token, &global_sid_System, &token->user_sids, &token->num_sids))) { DEBUG(1,("Error adding nt-authority system sid to token\n")); return NULL; } return token; } /**************************************************************** ****************************************************************/ WERROR gp_init_reg_ctx(TALLOC_CTX *mem_ctx, const char *initial_path, uint32_t desired_access, const struct nt_user_token *token, struct gp_registry_context **reg_ctx) { struct gp_registry_context *tmp_ctx; WERROR werr; if (!reg_ctx) { return WERR_INVALID_PARAM; } werr = registry_init_basic(); if (!W_ERROR_IS_OK(werr)) { return werr; } tmp_ctx = TALLOC_ZERO_P(mem_ctx, struct gp_registry_context); W_ERROR_HAVE_NO_MEMORY(tmp_ctx); if (token) { tmp_ctx->token = token; } else { tmp_ctx->token = registry_create_system_token(mem_ctx); } if (!tmp_ctx->token) { TALLOC_FREE(tmp_ctx); return WERR_NOMEM; } werr = regdb_open(); if (!W_ERROR_IS_OK(werr)) { return werr; } if (initial_path) { tmp_ctx->path = talloc_strdup(mem_ctx, initial_path); if (!tmp_ctx->path) { TALLOC_FREE(tmp_ctx); return WERR_NOMEM; } werr = reg_open_path(mem_ctx, tmp_ctx->path, desired_access, tmp_ctx->token, &tmp_ctx->curr_key); if (!W_ERROR_IS_OK(werr)) { TALLOC_FREE(tmp_ctx); return werr; } } *reg_ctx = tmp_ctx; return WERR_OK; } /**************************************************************** ****************************************************************/ void gp_free_reg_ctx(struct gp_registry_context *reg_ctx) { TALLOC_FREE(reg_ctx); } /**************************************************************** ****************************************************************/ WERROR gp_store_reg_subkey(TALLOC_CTX *mem_ctx, const char *subkeyname, struct registry_key *curr_key, struct registry_key **new_key) { enum winreg_CreateAction action = REG_ACTION_NONE; WERROR werr; werr = reg_createkey(mem_ctx, curr_key, subkeyname, REG_KEY_WRITE, new_key, &action); if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) { return WERR_OK; } return werr; } /**************************************************************** ****************************************************************/ WERROR gp_read_reg_subkey(TALLOC_CTX *mem_ctx, struct gp_registry_context *reg_ctx, const char *subkeyname, struct registry_key **key) { const char *tmp = NULL; if (!reg_ctx || !subkeyname || !key) { return WERR_INVALID_PARAM; } tmp = talloc_asprintf(mem_ctx, "%s\\%s", reg_ctx->path, subkeyname); W_ERROR_HAVE_NO_MEMORY(tmp); return reg_open_path(mem_ctx, tmp, REG_KEY_READ, reg_ctx->token, key); } /**************************************************************** ****************************************************************/ WERROR gp_store_reg_val_sz(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *val_name, const char *val) { struct registry_value reg_val; ZERO_STRUCT(reg_val); /* FIXME: hack */ val = val ? val : " "; reg_val.type = REG_SZ; reg_val.v.sz.len = strlen(val); reg_val.v.sz.str = talloc_strdup(mem_ctx, val); W_ERROR_HAVE_NO_MEMORY(reg_val.v.sz.str); return reg_setvalue(key, val_name, ®_val); } /**************************************************************** ****************************************************************/ static WERROR gp_store_reg_val_dword(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *val_name, uint32_t val) { struct registry_value reg_val; ZERO_STRUCT(reg_val); reg_val.type = REG_DWORD; reg_val.v.dword = val; return reg_setvalue(key, val_name, ®_val); } /**************************************************************** ****************************************************************/ WERROR gp_read_reg_val_sz(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *val_name, const char **val) { WERROR werr; struct registry_value *reg_val = NULL; werr = reg_queryvalue(mem_ctx, key, val_name, ®_val); W_ERROR_NOT_OK_RETURN(werr); if (reg_val->type != REG_SZ) { return WERR_INVALID_DATATYPE; } *val = talloc_strdup(mem_ctx, reg_val->v.sz.str); W_ERROR_HAVE_NO_MEMORY(*val); return WERR_OK; } /**************************************************************** ****************************************************************/ static WERROR gp_read_reg_val_dword(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *val_name, uint32_t *val) { WERROR werr; struct registry_value *reg_val = NULL; werr = reg_queryvalue(mem_ctx, key, val_name, ®_val); W_ERROR_NOT_OK_RETURN(werr); if (reg_val->type != REG_DWORD) { return WERR_INVALID_DATATYPE; } *val = reg_val->v.dword; return WERR_OK; } /**************************************************************** ****************************************************************/ static WERROR gp_store_reg_gpovals(TALLOC_CTX *mem_ctx, struct registry_key *key, struct GROUP_POLICY_OBJECT *gpo) { WERROR werr; if (!key || !gpo) { return WERR_INVALID_PARAM; } werr = gp_store_reg_val_dword(mem_ctx, key, "Version", gpo->version); W_ERROR_NOT_OK_RETURN(werr); werr = gp_store_reg_val_dword(mem_ctx, key, "WQLFilterPass", true); /* fake */ W_ERROR_NOT_OK_RETURN(werr); werr = gp_store_reg_val_dword(mem_ctx, key, "AccessDenied", false); /* fake */ W_ERROR_NOT_OK_RETURN(werr); werr = gp_store_reg_val_dword(mem_ctx, key, "GPO-Disabled", (gpo->options & GPO_FLAG_DISABLE)); W_ERROR_NOT_OK_RETURN(werr); werr = gp_store_reg_val_dword(mem_ctx, key, "Options", gpo->options); W_ERROR_NOT_OK_RETURN(werr); werr = gp_store_reg_val_sz(mem_ctx, key, "GPOID", gpo->name); W_ERROR_NOT_OK_RETURN(werr); werr = gp_store_reg_val_sz(mem_ctx, key, "SOM", gpo->link); W_ERROR_NOT_OK_RETURN(werr); werr = gp_store_reg_val_sz(mem_ctx, key, "DisplayName", gpo->display_name); W_ERROR_NOT_OK_RETURN(werr); werr = gp_store_reg_val_sz(mem_ctx, key, "WQL-Id", NULL); W_ERROR_NOT_OK_RETURN(werr); return werr; } /**************************************************************** ****************************************************************/ static const char *gp_reg_groupmembership_path(TALLOC_CTX *mem_ctx, const DOM_SID *sid, uint32_t flags) { if (flags & GPO_LIST_FLAG_MACHINE) { return "GroupMembership"; } return talloc_asprintf(mem_ctx, "%s\\%s", sid_string_tos(sid), "GroupMembership"); } /**************************************************************** ****************************************************************/ static WERROR gp_reg_del_groupmembership(TALLOC_CTX *mem_ctx, struct registry_key *key, const struct nt_user_token *token, uint32_t flags) { const char *path = NULL; path = gp_reg_groupmembership_path(mem_ctx, &token->user_sids[0], flags); W_ERROR_HAVE_NO_MEMORY(path); return reg_deletekey_recursive(mem_ctx, key, path); } /**************************************************************** ****************************************************************/ static WERROR gp_reg_store_groupmembership(TALLOC_CTX *mem_ctx, struct gp_registry_context *reg_ctx, const struct nt_user_token *token, uint32_t flags) { struct registry_key *key = NULL; WERROR werr; int i = 0; const char *valname = NULL; const char *path = NULL; const char *val = NULL; int count = 0; path = gp_reg_groupmembership_path(mem_ctx, &token->user_sids[0], flags); W_ERROR_HAVE_NO_MEMORY(path); gp_reg_del_groupmembership(mem_ctx, reg_ctx->curr_key, token, flags); werr = gp_store_reg_subkey(mem_ctx, path, reg_ctx->curr_key, &key); W_ERROR_NOT_OK_RETURN(werr); for (i=0; inum_sids; i++) { valname = talloc_asprintf(mem_ctx, "Group%d", count++); W_ERROR_HAVE_NO_MEMORY(valname); val = sid_string_talloc(mem_ctx, &token->user_sids[i]); W_ERROR_HAVE_NO_MEMORY(val); werr = gp_store_reg_val_sz(mem_ctx, key, valname, val); W_ERROR_NOT_OK_RETURN(werr); } werr = gp_store_reg_val_dword(mem_ctx, key, "Count", count); W_ERROR_NOT_OK_RETURN(werr); return WERR_OK; } /**************************************************************** ****************************************************************/ #if 0 /* not used yet */ static WERROR gp_reg_read_groupmembership(TALLOC_CTX *mem_ctx, struct gp_registry_context *reg_ctx, const DOM_SID *object_sid, struct nt_user_token **token, uint32_t flags) { struct registry_key *key = NULL; WERROR werr; int i = 0; const char *valname = NULL; const char *val = NULL; const char *path = NULL; uint32_t count = 0; int num_token_sids = 0; struct nt_user_token *tmp_token = NULL; tmp_token = TALLOC_ZERO_P(mem_ctx, struct nt_user_token); W_ERROR_HAVE_NO_MEMORY(tmp_token); path = gp_reg_groupmembership_path(mem_ctx, object_sid, flags); W_ERROR_HAVE_NO_MEMORY(path); werr = gp_read_reg_subkey(mem_ctx, reg_ctx, path, &key); W_ERROR_NOT_OK_RETURN(werr); werr = gp_read_reg_val_dword(mem_ctx, key, "Count", &count); W_ERROR_NOT_OK_RETURN(werr); for (i=0; iuser_sids[num_token_sids++], val)) { return WERR_INSUFFICIENT_BUFFER; } } tmp_token->num_sids = num_token_sids; *token = tmp_token; return WERR_OK; } #endif /**************************************************************** ****************************************************************/ static const char *gp_req_state_path(TALLOC_CTX *mem_ctx, const DOM_SID *sid, uint32_t flags) { if (flags & GPO_LIST_FLAG_MACHINE) { return GPO_REG_STATE_MACHINE; } return talloc_asprintf(mem_ctx, "%s\\%s", "State", sid_string_tos(sid)); } /**************************************************************** ****************************************************************/ static WERROR gp_del_reg_state(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *path) { return reg_deletesubkeys_recursive(mem_ctx, key, path); } /**************************************************************** ****************************************************************/ WERROR gp_reg_state_store(TALLOC_CTX *mem_ctx, uint32_t flags, const char *dn, const struct nt_user_token *token, struct GROUP_POLICY_OBJECT *gpo_list) { struct gp_registry_context *reg_ctx = NULL; WERROR werr = WERR_GENERAL_FAILURE; const char *subkeyname = NULL; struct GROUP_POLICY_OBJECT *gpo; int count = 0; struct registry_key *key; werr = gp_init_reg_ctx(mem_ctx, KEY_GROUP_POLICY, REG_KEY_WRITE, token, ®_ctx); W_ERROR_NOT_OK_RETURN(werr); werr = gp_secure_key(mem_ctx, flags, reg_ctx->curr_key, &token->user_sids[0]); if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("failed to secure key: %s\n", dos_errstr(werr))); goto done; } werr = gp_reg_store_groupmembership(mem_ctx, reg_ctx, token, flags); if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("failed to store group membership: %s\n", dos_errstr(werr))); goto done; } subkeyname = gp_req_state_path(mem_ctx, &token->user_sids[0], flags); if (!subkeyname) { werr = WERR_NOMEM; goto done; } werr = gp_del_reg_state(mem_ctx, reg_ctx->curr_key, subkeyname); if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("failed to delete old state: %s\n", dos_errstr(werr))); /* goto done; */ } werr = gp_store_reg_subkey(mem_ctx, subkeyname, reg_ctx->curr_key, ®_ctx->curr_key); if (!W_ERROR_IS_OK(werr)) { goto done; } werr = gp_store_reg_val_sz(mem_ctx, reg_ctx->curr_key, "Distinguished-Name", dn); if (!W_ERROR_IS_OK(werr)) { goto done; } /* store link list */ werr = gp_store_reg_subkey(mem_ctx, "GPLink-List", reg_ctx->curr_key, &key); if (!W_ERROR_IS_OK(werr)) { goto done; } /* store gpo list */ werr = gp_store_reg_subkey(mem_ctx, "GPO-List", reg_ctx->curr_key, ®_ctx->curr_key); if (!W_ERROR_IS_OK(werr)) { goto done; } for (gpo = gpo_list; gpo; gpo = gpo->next) { subkeyname = talloc_asprintf(mem_ctx, "%d", count++); if (!subkeyname) { werr = WERR_NOMEM; goto done; } werr = gp_store_reg_subkey(mem_ctx, subkeyname, reg_ctx->curr_key, &key); if (!W_ERROR_IS_OK(werr)) { goto done; } werr = gp_store_reg_gpovals(mem_ctx, key, gpo); if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("gp_reg_state_store: " "gpo_store_reg_gpovals failed for %s: %s\n", gpo->display_name, dos_errstr(werr))); goto done; } } done: gp_free_reg_ctx(reg_ctx); return werr; } /**************************************************************** ****************************************************************/ static WERROR gp_read_reg_gpovals(TALLOC_CTX *mem_ctx, struct registry_key *key, struct GROUP_POLICY_OBJECT *gpo) { WERROR werr; if (!key || !gpo) { return WERR_INVALID_PARAM; } werr = gp_read_reg_val_dword(mem_ctx, key, "Version", &gpo->version); W_ERROR_NOT_OK_RETURN(werr); werr = gp_read_reg_val_dword(mem_ctx, key, "Options", &gpo->options); W_ERROR_NOT_OK_RETURN(werr); werr = gp_read_reg_val_sz(mem_ctx, key, "GPOID", &gpo->name); W_ERROR_NOT_OK_RETURN(werr); werr = gp_read_reg_val_sz(mem_ctx, key, "SOM", &gpo->link); W_ERROR_NOT_OK_RETURN(werr); werr = gp_read_reg_val_sz(mem_ctx, key, "DisplayName", &gpo->display_name); W_ERROR_NOT_OK_RETURN(werr); return werr; } /**************************************************************** ****************************************************************/ static WERROR gp_read_reg_gpo(TALLOC_CTX *mem_ctx, struct registry_key *key, struct GROUP_POLICY_OBJECT **gpo_ret) { struct GROUP_POLICY_OBJECT *gpo = NULL; WERROR werr; if (!gpo_ret || !key) { return WERR_INVALID_PARAM; } gpo = TALLOC_ZERO_P(mem_ctx, struct GROUP_POLICY_OBJECT); W_ERROR_HAVE_NO_MEMORY(gpo); werr = gp_read_reg_gpovals(mem_ctx, key, gpo); W_ERROR_NOT_OK_RETURN(werr); *gpo_ret = gpo; return werr; } /**************************************************************** ****************************************************************/ WERROR gp_reg_state_read(TALLOC_CTX *mem_ctx, uint32_t flags, const DOM_SID *sid, struct GROUP_POLICY_OBJECT **gpo_list) { struct gp_registry_context *reg_ctx = NULL; WERROR werr = WERR_GENERAL_FAILURE; const char *subkeyname = NULL; struct GROUP_POLICY_OBJECT *gpo = NULL; int count = 0; struct registry_key *key = NULL; const char *path = NULL; const char *gp_state_path = NULL; if (!gpo_list) { return WERR_INVALID_PARAM; } ZERO_STRUCTP(gpo_list); gp_state_path = gp_req_state_path(mem_ctx, sid, flags); if (!gp_state_path) { werr = WERR_NOMEM; goto done; } path = talloc_asprintf(mem_ctx, "%s\\%s\\%s", KEY_GROUP_POLICY, gp_state_path, "GPO-List"); if (!path) { werr = WERR_NOMEM; goto done; } werr = gp_init_reg_ctx(mem_ctx, path, REG_KEY_READ, NULL, ®_ctx); if (!W_ERROR_IS_OK(werr)) { goto done; } while (1) { subkeyname = talloc_asprintf(mem_ctx, "%d", count++); if (!subkeyname) { werr = WERR_NOMEM; goto done; } werr = gp_read_reg_subkey(mem_ctx, reg_ctx, subkeyname, &key); if (W_ERROR_EQUAL(werr, WERR_BADFILE)) { werr = WERR_OK; break; } if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("gp_reg_state_read: " "gp_read_reg_subkey gave: %s\n", dos_errstr(werr))); goto done; } werr = gp_read_reg_gpo(mem_ctx, key, &gpo); if (!W_ERROR_IS_OK(werr)) { goto done; } DLIST_ADD(*gpo_list, gpo); } done: gp_free_reg_ctx(reg_ctx); return werr; } /**************************************************************** ****************************************************************/ static WERROR gp_reg_generate_sd(TALLOC_CTX *mem_ctx, const DOM_SID *sid, struct security_descriptor **sd, size_t *sd_size) { SEC_ACE ace[6]; SEC_ACCESS mask; SEC_ACL *acl = NULL; uint8_t inherit_flags; init_sec_access(&mask, REG_KEY_ALL); init_sec_ace(&ace[0], &global_sid_System, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); init_sec_access(&mask, REG_KEY_ALL); init_sec_ace(&ace[1], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); init_sec_access(&mask, REG_KEY_READ); init_sec_ace(&ace[2], sid ? sid : &global_sid_Authenticated_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); inherit_flags = SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_CONTAINER_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY; init_sec_access(&mask, REG_KEY_ALL); init_sec_ace(&ace[3], &global_sid_System, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, inherit_flags); init_sec_access(&mask, REG_KEY_ALL); init_sec_ace(&ace[4], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, inherit_flags); init_sec_access(&mask, REG_KEY_READ); init_sec_ace(&ace[5], sid ? sid : &global_sid_Authenticated_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, inherit_flags); acl = make_sec_acl(mem_ctx, NT4_ACL_REVISION, 6, ace); W_ERROR_HAVE_NO_MEMORY(acl); *sd = make_sec_desc(mem_ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE | SEC_DESC_DACL_AUTO_INHERITED | /* really ? */ SEC_DESC_DACL_AUTO_INHERIT_REQ, /* really ? */ NULL, NULL, NULL, acl, sd_size); W_ERROR_HAVE_NO_MEMORY(*sd); return WERR_OK; } /**************************************************************** ****************************************************************/ WERROR gp_secure_key(TALLOC_CTX *mem_ctx, uint32_t flags, struct registry_key *key, const DOM_SID *sid) { struct security_descriptor *sd = NULL; size_t sd_size = 0; const DOM_SID *sd_sid = NULL; WERROR werr; if (!(flags & GPO_LIST_FLAG_MACHINE)) { sd_sid = sid; } werr = gp_reg_generate_sd(mem_ctx, sd_sid, &sd, &sd_size); W_ERROR_NOT_OK_RETURN(werr); return reg_setkeysecurity(key, sd); } /**************************************************************** ****************************************************************/ void dump_reg_val(int lvl, const char *direction, const char *key, const char *subkey, struct registry_value *val) { int i = 0; const char *type_str = NULL; if (!val) { DEBUG(lvl,("no val!\n")); return; } type_str = reg_type_lookup(val->type); DEBUG(lvl,("\tdump_reg_val: %s '%s' '%s' %s: ", direction, key, subkey, type_str)); switch (val->type) { case REG_DWORD: DEBUG(lvl,("%d (0x%08x)\n", (int)val->v.dword, val->v.dword)); break; case REG_QWORD: DEBUG(lvl,("%d (0x%016lx)\n", (int)val->v.qword, val->v.qword)); break; case REG_SZ: DEBUG(lvl,("%s (length: %d)\n", val->v.sz.str, (int)val->v.sz.len)); break; case REG_MULTI_SZ: DEBUG(lvl,("(num_strings: %d)\n", val->v.multi_sz.num_strings)); for (i=0; i < val->v.multi_sz.num_strings; i++) { DEBUGADD(lvl,("\t%s\n", val->v.multi_sz.strings[i])); } break; case REG_NONE: DEBUG(lvl,("\n")); break; case REG_BINARY: dump_data(lvl, val->v.binary.data, val->v.binary.length); break; default: DEBUG(lvl,("unsupported type: %d\n", val->type)); break; } } /**************************************************************** ****************************************************************/ void dump_reg_entry(uint32_t flags, const char *dir, struct gp_registry_entry *entry) { if (!(flags & GPO_INFO_FLAG_VERBOSE)) return; dump_reg_val(1, dir, entry->key, entry->value, entry->data); } /**************************************************************** ****************************************************************/ void dump_reg_entries(uint32_t flags, const char *dir, struct gp_registry_entry *entries, size_t num_entries) { size_t i; if (!(flags & GPO_INFO_FLAG_VERBOSE)) return; for (i=0; i < num_entries; i++) { dump_reg_entry(flags, dir, &entries[i]); } } /**************************************************************** ****************************************************************/ bool add_gp_registry_entry_to_array(TALLOC_CTX *mem_ctx, struct gp_registry_entry *entry, struct gp_registry_entry **entries, size_t *num) { *entries = TALLOC_REALLOC_ARRAY(mem_ctx, *entries, struct gp_registry_entry, (*num)+1); if (*entries == NULL) { *num = 0; return false; } (*entries)[*num].action = entry->action; (*entries)[*num].key = entry->key; (*entries)[*num].value = entry->value; (*entries)[*num].data = entry->data; *num += 1; return true; } /**************************************************************** ****************************************************************/ static const char *gp_reg_action_str(enum gp_reg_action action) { switch (action) { case GP_REG_ACTION_NONE: return "GP_REG_ACTION_NONE"; case GP_REG_ACTION_ADD_VALUE: return "GP_REG_ACTION_ADD_VALUE"; case GP_REG_ACTION_ADD_KEY: return "GP_REG_ACTION_ADD_KEY"; case GP_REG_ACTION_DEL_VALUES: return "GP_REG_ACTION_DEL_VALUES"; case GP_REG_ACTION_DEL_VALUE: return "GP_REG_ACTION_DEL_VALUE"; case GP_REG_ACTION_DEL_ALL_VALUES: return "GP_REG_ACTION_DEL_ALL_VALUES"; case GP_REG_ACTION_DEL_KEYS: return "GP_REG_ACTION_DEL_KEYS"; case GP_REG_ACTION_SEC_KEY_SET: return "GP_REG_ACTION_SEC_KEY_SET"; case GP_REG_ACTION_SEC_KEY_RESET: return "GP_REG_ACTION_SEC_KEY_RESET"; default: return "unknown"; } } /**************************************************************** ****************************************************************/ WERROR reg_apply_registry_entry(TALLOC_CTX *mem_ctx, struct registry_key *root_key, struct gp_registry_context *reg_ctx, struct gp_registry_entry *entry, const struct nt_user_token *token, uint32_t flags) { WERROR werr; struct registry_key *key = NULL; if (flags & GPO_INFO_FLAG_VERBOSE) { printf("about to store key: [%s]\n", entry->key); printf(" value: [%s]\n", entry->value); printf(" data: [%s]\n", reg_type_lookup(entry->data->type)); printf(" action: [%s]\n", gp_reg_action_str(entry->action)); } werr = gp_store_reg_subkey(mem_ctx, entry->key, root_key, &key); /* reg_ctx->curr_key, &key); */ if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("gp_store_reg_subkey failed: %s\n", dos_errstr(werr))); return werr; } switch (entry->action) { case GP_REG_ACTION_NONE: case GP_REG_ACTION_ADD_KEY: return WERR_OK; case GP_REG_ACTION_SEC_KEY_SET: werr = gp_secure_key(mem_ctx, flags, key, &token->user_sids[0]); if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("reg_apply_registry_entry: " "gp_secure_key failed: %s\n", dos_errstr(werr))); return werr; } break; case GP_REG_ACTION_ADD_VALUE: werr = reg_setvalue(key, entry->value, entry->data); if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("reg_apply_registry_entry: " "reg_setvalue failed: %s\n", dos_errstr(werr))); dump_reg_entry(flags, "STORE", entry); return werr; } break; case GP_REG_ACTION_DEL_VALUE: werr = reg_deletevalue(key, entry->value); if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("reg_apply_registry_entry: " "reg_deletevalue failed: %s\n", dos_errstr(werr))); dump_reg_entry(flags, "STORE", entry); return werr; } break; case GP_REG_ACTION_DEL_ALL_VALUES: werr = reg_deleteallvalues(key); if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("reg_apply_registry_entry: " "reg_deleteallvalues failed: %s\n", dos_errstr(werr))); dump_reg_entry(flags, "STORE", entry); return werr; } break; case GP_REG_ACTION_DEL_VALUES: case GP_REG_ACTION_DEL_KEYS: case GP_REG_ACTION_SEC_KEY_RESET: DEBUG(0,("reg_apply_registry_entry: " "not yet supported: %s (%d)\n", gp_reg_action_str(entry->action), entry->action)); return WERR_NOT_SUPPORTED; default: DEBUG(0,("invalid action: %d\n", entry->action)); return WERR_INVALID_PARAM; } return werr; }