summaryrefslogtreecommitdiffstats
path: root/libgpo/gpo_reg.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:20:00 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:20:00 +0000
commit8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch)
tree4099e8021376c7d8c05bdf8503093d80e9c7bad0 /libgpo/gpo_reg.c
parentInitial commit. (diff)
downloadsamba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.tar.xz
samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.zip
Adding upstream version 2:4.20.0+dfsg.upstream/2%4.20.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'libgpo/gpo_reg.c')
-rw-r--r--libgpo/gpo_reg.c1047
1 files changed, 1047 insertions, 0 deletions
diff --git a/libgpo/gpo_reg.c b/libgpo/gpo_reg.c
new file mode 100644
index 0000000..a1a8d7d
--- /dev/null
+++ b/libgpo/gpo_reg.c
@@ -0,0 +1,1047 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "../libgpo/gpo.h"
+#include "libgpo/gpo_proto.h"
+#include "registry.h"
+#include "registry/reg_api.h"
+#include "registry/reg_backend_db.h"
+#include "registry/reg_api_util.h"
+#include "registry/reg_init_basic.h"
+#include "../libcli/security/security.h"
+#include "libcli/security/dom_sid.h"
+#include "../libcli/registry/util_reg.h"
+
+
+/****************************************************************
+****************************************************************/
+
+struct security_token *registry_create_system_token(TALLOC_CTX *mem_ctx)
+{
+ const struct security_token *system_token = get_system_token();
+
+ struct security_token *dup_token
+ = security_token_duplicate(mem_ctx, system_token);
+
+ if (dup_token == NULL) {
+ DBG_WARNING("security_token_duplicate() failed\n");
+ return NULL;
+ }
+
+ return dup_token;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR gp_init_reg_ctx(TALLOC_CTX *mem_ctx,
+ const char *initial_path,
+ uint32_t desired_access,
+ const struct security_token *token,
+ struct gp_registry_context **reg_ctx)
+{
+ struct gp_registry_context *tmp_ctx;
+ WERROR werr;
+
+ if (!reg_ctx) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ werr = registry_init_basic();
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ tmp_ctx = talloc_zero(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_NOT_ENOUGH_MEMORY;
+ }
+
+ 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_NOT_ENOUGH_MEMORY;
+ }
+
+ 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_PARAMETER;
+ }
+
+ 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;
+
+ reg_val.type = REG_SZ;
+ if (!push_reg_sz(mem_ctx, &reg_val.data, val)) {
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ return reg_setvalue(key, val_name, &reg_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;
+
+ reg_val.type = REG_DWORD;
+ reg_val.data = data_blob_talloc(mem_ctx, NULL, 4);
+ SIVAL(reg_val.data.data, 0, val);
+
+ return reg_setvalue(key, val_name, &reg_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, &reg_val);
+ W_ERROR_NOT_OK_RETURN(werr);
+
+ if (reg_val->type != REG_SZ) {
+ return WERR_INVALID_DATATYPE;
+ }
+
+ if (!pull_reg_sz(mem_ctx, &reg_val->data, val)) {
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ 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, &reg_val);
+ W_ERROR_NOT_OK_RETURN(werr);
+
+ if (reg_val->type != REG_DWORD) {
+ return WERR_INVALID_DATATYPE;
+ }
+
+ if (reg_val->data.length < 4) {
+ return WERR_INSUFFICIENT_BUFFER;
+ }
+ *val = IVAL(reg_val->data.data, 0);
+
+ 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_PARAMETER;
+ }
+
+ 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 ? 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",
+ "");
+ W_ERROR_NOT_OK_RETURN(werr);
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+static const char *gp_reg_groupmembership_path(TALLOC_CTX *mem_ctx,
+ const struct dom_sid *sid,
+ uint32_t flags)
+{
+ struct dom_sid_buf sidbuf;
+
+ if (flags & GPO_LIST_FLAG_MACHINE) {
+ return "GroupMembership";
+ }
+
+ return talloc_asprintf(
+ mem_ctx,
+ "%s\\%s",
+ dom_sid_str_buf(sid, &sidbuf),
+ "GroupMembership");
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR gp_reg_del_groupmembership(TALLOC_CTX *mem_ctx,
+ struct registry_key *key,
+ const struct security_token *token,
+ uint32_t flags)
+{
+ const char *path = NULL;
+
+ path = gp_reg_groupmembership_path(mem_ctx, &token->sids[PRIMARY_USER_SID_INDEX],
+ flags);
+ W_ERROR_HAVE_NO_MEMORY(path);
+
+ return reg_deletekey_recursive(key, path);
+
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR gp_reg_store_groupmembership(TALLOC_CTX *mem_ctx,
+ struct gp_registry_context *reg_ctx,
+ const struct security_token *token,
+ uint32_t flags)
+{
+ struct registry_key *key = NULL;
+ WERROR werr;
+ uint32_t i = 0;
+ const char *valname = NULL;
+ const char *path = NULL;
+ int count = 0;
+
+ path = gp_reg_groupmembership_path(mem_ctx, &token->sids[PRIMARY_USER_SID_INDEX],
+ 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; i<token->num_sids; i++) {
+ struct dom_sid_buf buf;
+
+ valname = talloc_asprintf(mem_ctx, "Group%d", count++);
+ W_ERROR_HAVE_NO_MEMORY(valname);
+
+ werr = gp_store_reg_val_sz(
+ mem_ctx,
+ key,
+ valname,
+ dom_sid_str_buf(&token->sids[i], &buf));
+ 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 struct dom_sid *object_sid,
+ struct security_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 security_token *tmp_token = NULL;
+
+ tmp_token = talloc_zero(mem_ctx, struct security_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; i<count; i++) {
+
+ valname = talloc_asprintf(mem_ctx, "Group%d", i);
+ W_ERROR_HAVE_NO_MEMORY(valname);
+
+ werr = gp_read_reg_val_sz(mem_ctx, key, valname, &val);
+ W_ERROR_NOT_OK_RETURN(werr);
+
+ if (!string_to_sid(&tmp_token->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 struct dom_sid *sid,
+ uint32_t flags)
+{
+ struct dom_sid_buf sidbuf;
+
+ if (flags & GPO_LIST_FLAG_MACHINE) {
+ return GPO_REG_STATE_MACHINE;
+ }
+
+ return talloc_asprintf(
+ mem_ctx,
+ "%s\\%s",
+ "State",
+ dom_sid_str_buf(sid, &sidbuf));
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR gp_del_reg_state(TALLOC_CTX *mem_ctx,
+ struct registry_key *key,
+ const char *path)
+{
+ return reg_deletesubkeys_recursive(key, path);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR gp_reg_state_store(TALLOC_CTX *mem_ctx,
+ uint32_t flags,
+ const char *dn,
+ const struct security_token *token,
+ struct GROUP_POLICY_OBJECT *gpo_list)
+{
+ struct gp_registry_context *reg_ctx = NULL;
+ WERROR werr = WERR_GEN_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, &reg_ctx);
+ W_ERROR_NOT_OK_RETURN(werr);
+
+ werr = gp_secure_key(mem_ctx, flags, reg_ctx->curr_key,
+ &token->sids[PRIMARY_USER_SID_INDEX]);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(0,("failed to secure key: %s\n", win_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", win_errstr(werr)));
+ goto done;
+ }
+
+ subkeyname = gp_req_state_path(mem_ctx, &token->sids[PRIMARY_USER_SID_INDEX], flags);
+ if (!subkeyname) {
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ 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", win_errstr(werr)));
+ /* goto done; */
+ }
+
+ werr = gp_store_reg_subkey(mem_ctx, subkeyname,
+ reg_ctx->curr_key, &reg_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, &reg_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_NOT_ENOUGH_MEMORY;
+ 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: "
+ "gp_store_reg_gpovals failed for %s: %s\n",
+ gpo->display_name, win_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_PARAMETER;
+ }
+
+ 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_PARAMETER;
+ }
+
+ gpo = talloc_zero(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 struct dom_sid *sid,
+ struct GROUP_POLICY_OBJECT **gpo_list)
+{
+ struct gp_registry_context *reg_ctx = NULL;
+ WERROR werr = WERR_GEN_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_PARAMETER;
+ }
+
+ ZERO_STRUCTP(gpo_list);
+
+ gp_state_path = gp_req_state_path(mem_ctx, sid, flags);
+ if (!gp_state_path) {
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
+ KEY_GROUP_POLICY,
+ gp_state_path,
+ "GPO-List");
+ if (!path) {
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ werr = gp_init_reg_ctx(mem_ctx, path, REG_KEY_READ, NULL, &reg_ctx);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ while (1) {
+
+ subkeyname = talloc_asprintf(mem_ctx, "%d", count++);
+ if (!subkeyname) {
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ werr = gp_read_reg_subkey(mem_ctx, reg_ctx, subkeyname, &key);
+ if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
+ werr = WERR_OK;
+ break;
+ }
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(0,("gp_reg_state_read: "
+ "gp_read_reg_subkey gave: %s\n",
+ win_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 struct dom_sid *sid,
+ struct security_descriptor **sd,
+ size_t *sd_size)
+{
+ struct security_ace ace[6];
+ uint32_t mask;
+
+ struct security_acl *theacl = NULL;
+
+ uint8_t inherit_flags;
+
+ mask = REG_KEY_ALL;
+ init_sec_ace(&ace[0],
+ &global_sid_System,
+ SEC_ACE_TYPE_ACCESS_ALLOWED,
+ mask, 0);
+
+ mask = REG_KEY_ALL;
+ init_sec_ace(&ace[1],
+ &global_sid_Builtin_Administrators,
+ SEC_ACE_TYPE_ACCESS_ALLOWED,
+ mask, 0);
+
+ 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;
+
+ mask = REG_KEY_ALL;
+ init_sec_ace(&ace[3],
+ &global_sid_System,
+ SEC_ACE_TYPE_ACCESS_ALLOWED,
+ mask, inherit_flags);
+
+ mask = REG_KEY_ALL;
+ init_sec_ace(&ace[4],
+ &global_sid_Builtin_Administrators,
+ SEC_ACE_TYPE_ACCESS_ALLOWED,
+ mask, inherit_flags);
+
+ mask = REG_KEY_READ;
+ init_sec_ace(&ace[5],
+ sid ? sid : &global_sid_Authenticated_Users,
+ SEC_ACE_TYPE_ACCESS_ALLOWED,
+ mask, inherit_flags);
+
+ theacl = make_sec_acl(mem_ctx, NT4_ACL_REVISION, 6, ace);
+ W_ERROR_HAVE_NO_MEMORY(theacl);
+
+ *sd = make_sec_desc(mem_ctx, SD_REVISION,
+ SEC_DESC_SELF_RELATIVE |
+ SEC_DESC_DACL_AUTO_INHERITED | /* really ? */
+ SEC_DESC_DACL_AUTO_INHERIT_REQ, /* really ? */
+ NULL, NULL, NULL,
+ theacl, 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 struct dom_sid *sid)
+{
+ struct security_descriptor *sd = NULL;
+ size_t sd_size = 0;
+ const struct 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 = str_regtype(val->type);
+
+ DEBUG(lvl,("\tdump_reg_val:\t%s '%s'\n\t\t\t'%s' %s: ",
+ direction, key, subkey, type_str));
+
+ switch (val->type) {
+ case REG_DWORD: {
+ uint32_t v;
+ if (val->data.length < 4) {
+ break;
+ }
+ v = IVAL(val->data.data, 0);
+ DEBUG(lvl,("%d (0x%08x)\n",
+ (int)v, v));
+ break;
+ }
+ case REG_QWORD: {
+ uint64_t v;
+ if (val->data.length < 8) {
+ break;
+ }
+ v = BVAL(val->data.data, 0);
+ DEBUG(lvl,("%d (0x%016llx)\n",
+ (int)v,
+ (unsigned long long)v));
+ break;
+ }
+ case REG_SZ: {
+ const char *s;
+ if (!pull_reg_sz(talloc_tos(), &val->data, &s)) {
+ break;
+ }
+ DEBUG(lvl,("%s (length: %d)\n",
+ s, (int)strlen_m(s)));
+ break;
+ }
+ case REG_MULTI_SZ: {
+ const char **a;
+ if (!pull_reg_multi_sz(talloc_tos(), &val->data, &a)) {
+ break;
+ }
+ for (i=0; a[i] != NULL; i++) {
+ ;;
+ }
+ DEBUG(lvl,("(num_strings: %d)\n", i));
+ for (i=0; a[i] != NULL; i++) {
+ DEBUGADD(lvl,("\t%s\n", a[i]));
+ }
+ break;
+ }
+ case REG_NONE:
+ DEBUG(lvl,("\n"));
+ break;
+ case REG_BINARY:
+ dump_data(lvl, val->data.data,
+ val->data.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(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 security_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", str_regtype(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", win_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->sids[PRIMARY_USER_SID_INDEX]);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(0,("reg_apply_registry_entry: "
+ "gp_secure_key failed: %s\n",
+ win_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",
+ win_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",
+ win_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",
+ win_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_PARAMETER;
+ }
+
+ return werr;
+}