From f12770079bcf21a3fc3e493504443ea203c95004 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 29 Feb 2008 14:51:37 +0100 Subject: Pure cosmetics, trying to get my group policy diff smaller. Gunther (This used to be commit d7346e9360ffa97e44fa781293d32c707436193b) --- source3/libgpo/gpo_fetch.c | 35 ++++++++++++----------------------- source3/libgpo/gpo_filesync.c | 4 ++-- source3/libgpo/gpo_ini.c | 4 ++-- source3/libgpo/gpo_ldap.c | 12 ++++++------ source3/libgpo/gpo_sec.c | 8 ++++---- 5 files changed, 26 insertions(+), 37 deletions(-) diff --git a/source3/libgpo/gpo_fetch.c b/source3/libgpo/gpo_fetch.c index 916db2b3d3..2ec066425b 100644 --- a/source3/libgpo/gpo_fetch.c +++ b/source3/libgpo/gpo_fetch.c @@ -44,15 +44,18 @@ NTSTATUS gpo_explode_filesyspath(TALLOC_CTX *mem_ctx, if (!next_token_talloc(mem_ctx, &file_sys_path, server, "\\")) { return NT_STATUS_INVALID_PARAMETER; } + NT_STATUS_HAVE_NO_MEMORY(*server); if (!next_token_talloc(mem_ctx, &file_sys_path, service, "\\")) { return NT_STATUS_INVALID_PARAMETER; } + NT_STATUS_HAVE_NO_MEMORY(*service); if ((*nt_path = talloc_asprintf(mem_ctx, "\\%s", file_sys_path)) == NULL) { return NT_STATUS_NO_MEMORY; } + NT_STATUS_HAVE_NO_MEMORY(*nt_path); if ((path = talloc_asprintf(mem_ctx, "%s/%s", @@ -65,9 +68,8 @@ NTSTATUS gpo_explode_filesyspath(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - if ((*unix_path = talloc_strdup(mem_ctx, path)) == NULL) { - return NT_STATUS_NO_MEMORY; - } + *unix_path = talloc_strdup(mem_ctx, path); + NT_STATUS_HAVE_NO_MEMORY(*unix_path); TALLOC_FREE(path); return NT_STATUS_OK; @@ -124,36 +126,23 @@ NTSTATUS gpo_fetch_files(TALLOC_CTX *mem_ctx, result = gpo_explode_filesyspath(mem_ctx, gpo->file_sys_path, &server, &service, &nt_path, &unix_path); - if (!NT_STATUS_IS_OK(result)) { - goto out; - } + NT_STATUS_NOT_OK_RETURN(result); result = gpo_prepare_local_store(mem_ctx, unix_path); - if (!NT_STATUS_IS_OK(result)) { - goto out; - } + NT_STATUS_NOT_OK_RETURN(result); unix_ini_path = talloc_asprintf(mem_ctx, "%s/%s", unix_path, GPT_INI); nt_ini_path = talloc_asprintf(mem_ctx, "%s\\%s", nt_path, GPT_INI); - if (!unix_path || !nt_ini_path) { - result = NT_STATUS_NO_MEMORY; - goto out; - } + NT_STATUS_HAVE_NO_MEMORY(unix_ini_path); + NT_STATUS_HAVE_NO_MEMORY(nt_ini_path); result = gpo_copy_file(mem_ctx, cli, nt_ini_path, unix_ini_path); - if (!NT_STATUS_IS_OK(result)) { - goto out; - } + NT_STATUS_NOT_OK_RETURN(result); result = gpo_sync_directories(mem_ctx, cli, nt_path, unix_path); - if (!NT_STATUS_IS_OK(result)) { - goto out; - } + NT_STATUS_NOT_OK_RETURN(result); - result = NT_STATUS_OK; - - out: - return result; + return NT_STATUS_OK; } /**************************************************************** diff --git a/source3/libgpo/gpo_filesync.c b/source3/libgpo/gpo_filesync.c index 03d5286fae..6d64d7b968 100644 --- a/source3/libgpo/gpo_filesync.c +++ b/source3/libgpo/gpo_filesync.c @@ -117,10 +117,10 @@ static bool gpo_sync_files(struct sync_context *ctx) ctx) == -1) { DEBUG(1,("listing [%s] failed with error: %s\n", ctx->mask, cli_errstr(ctx->cli))); - return False; + return false; } - return True; + return true; } /**************************************************************** diff --git a/source3/libgpo/gpo_ini.c b/source3/libgpo/gpo_ini.c index 306d6f9bec..d8f14b609f 100644 --- a/source3/libgpo/gpo_ini.c +++ b/source3/libgpo/gpo_ini.c @@ -174,7 +174,7 @@ static NTSTATUS convert_file_from_ucs2(TALLOC_CTX *mem_ctx, failed: - DEBUG(1,("gp_inifile_init_context failed: %s\n", + DEBUG(1,("gp_inifile_init_context failed: %s\n", nt_errstr(status))); TALLOC_FREE(ctx); @@ -237,7 +237,7 @@ NTSTATUS parse_gpt_ini(TALLOC_CTX *mem_ctx, result = NT_STATUS_OK; out: - if (dict) { + if (dict) { iniparser_freedict(dict); } diff --git a/source3/libgpo/gpo_ldap.c b/source3/libgpo/gpo_ldap.c index a34e6861a5..477832abc5 100644 --- a/source3/libgpo/gpo_ldap.c +++ b/source3/libgpo/gpo_ldap.c @@ -27,7 +27,7 @@ bool ads_parse_gp_ext(TALLOC_CTX *mem_ctx, const char *extension_raw, struct GP_EXT **gp_ext) { - bool ret = False; + bool ret = false; struct GP_EXT *ext = NULL; char **ext_list = NULL; char **ext_strings = NULL; @@ -134,7 +134,7 @@ bool ads_parse_gp_ext(TALLOC_CTX *mem_ctx, *gp_ext = ext; - ret = True; + ret = true; parse_error: TALLOC_FREE(ext_list); @@ -659,7 +659,7 @@ ADS_STATUS ads_get_sid_token(ADS_STRUCT *ads, } } - new_token = create_local_nt_token(mem_ctx, &object_sid, False, + new_token = create_local_nt_token(mem_ctx, &object_sid, false, num_token_sids, token_sids); ADS_ERROR_HAVE_NO_MEMORY(new_token); @@ -713,7 +713,7 @@ ADS_STATUS ads_get_gpo_list(ADS_STRUCT *ads, ADS_STATUS status; struct GP_LINK gp_link; const char *parent_dn, *site_dn, *tmp_dn; - bool add_only_forced_gpos = False; + bool add_only_forced_gpos = false; ZERO_STRUCTP(gpo_list); @@ -793,7 +793,7 @@ ADS_STATUS ads_get_gpo_list(ADS_STRUCT *ads, /* block inheritance from now on */ if (gp_link.gp_opts & GPOPTIONS_BLOCK_INHERITANCE) { - add_only_forced_gpos = True; + add_only_forced_gpos = true; } status = add_gplink_to_gpo_list(ads, @@ -839,7 +839,7 @@ ADS_STATUS ads_get_gpo_list(ADS_STRUCT *ads, /* block inheritance from now on */ if (gp_link.gp_opts & GPOPTIONS_BLOCK_INHERITANCE) { - add_only_forced_gpos = True; + add_only_forced_gpos = true; } status = add_gplink_to_gpo_list(ads, diff --git a/source3/libgpo/gpo_sec.c b/source3/libgpo/gpo_sec.c index 7f8324b994..42ab72a99b 100644 --- a/source3/libgpo/gpo_sec.c +++ b/source3/libgpo/gpo_sec.c @@ -28,13 +28,13 @@ static bool gpo_sd_check_agp_object_guid(const struct security_ace_object *objec NTSTATUS status; if (!object) { - return False; + return false; } status = GUID_from_string(ADS_EXTENDED_RIGHT_APPLY_GROUP_POLICY, &ext_right_apg_guid); if (!NT_STATUS_IS_OK(status)) { - return False; + return false; } switch (object->flags) { @@ -52,7 +52,7 @@ static bool gpo_sd_check_agp_object_guid(const struct security_ace_object *objec break; } - return False; + return false; } /**************************************************************** @@ -61,7 +61,7 @@ static bool gpo_sd_check_agp_object_guid(const struct security_ace_object *objec static bool gpo_sd_check_agp_object(const SEC_ACE *ace) { if (!sec_ace_object(ace->type)) { - return False; + return false; } return gpo_sd_check_agp_object_guid(&ace->object.object); -- cgit From b50eb31bb4369e2ae22c43ad9f0fa2d9e2385d25 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 29 Feb 2008 15:13:02 +0100 Subject: Fix warnings (This used to be commit 9a966e5593ae4474014aec5d8c68c489ac8ce0c9) --- source3/client/client.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source3/client/client.c b/source3/client/client.c index 1410fc2f33..c97f6223a7 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -979,11 +979,10 @@ static int do_get(const char *rname, const char *lname_in, bool reget) int handle = 0, fnum; bool newhandle = false; struct timeval tp_start; - int read_size = io_bufsize; uint16 attr; SMB_OFF_T size; off_t start = 0; - off_t nread = 0; + ssize_t nread = 0; int rc = 0; struct cli_state *targetcli = NULL; char *targetname = NULL; -- cgit From c613bd5d4e34caff88deed13cf82608f894e083c Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 29 Feb 2008 15:46:14 +0100 Subject: Add infrastructure for reading/storing Group Policy state and control data in the registry. Guenther (This used to be commit f673bbd300d972dd7ae2d092b3b1e642ed29cfd2) --- source3/Makefile.in | 3 +- source3/include/gpo.h | 60 ++- source3/include/reg_objects.h | 7 + source3/libgpo/gpo_reg.c | 1058 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1126 insertions(+), 2 deletions(-) create mode 100644 source3/libgpo/gpo_reg.c diff --git a/source3/Makefile.in b/source3/Makefile.in index c6815e91e6..baa917724d 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -377,7 +377,8 @@ LIBWBCLIENT_OBJ0 = nsswitch/libwbclient/wbclient.o \ LIBWBCLIENT_OBJ = $(LIBWBCLIENT_OBJ0) $(WBCOMMON_OBJ) @LIBTALLOC_STATIC@ $(LIBREPLACE_OBJ) LIBGPO_OBJ0 = libgpo/gpo_ldap.o libgpo/gpo_ini.o libgpo/gpo_util.o \ - libgpo/gpo_fetch.o libgpo/gpo_filesync.o libgpo/gpo_sec.o + libgpo/gpo_fetch.o libgpo/gpo_filesync.o libgpo/gpo_sec.o \ + libgpo/gpo_reg.o LIBGPO_OBJ = $(LIBGPO_OBJ0) LIBADS_OBJ = libads/ldap.o libads/ldap_printer.o \ diff --git a/source3/include/gpo.h b/source3/include/gpo.h index 9b1a672640..d8d9e8e597 100644 --- a/source3/include/gpo.h +++ b/source3/include/gpo.h @@ -22,7 +22,8 @@ enum GPO_LINK_TYPE { GP_LINK_MACHINE = 1, GP_LINK_SITE = 2, GP_LINK_DOMAIN = 3, - GP_LINK_OU = 4 + GP_LINK_OU = 4, + GP_LINK_LOCAL = 5 /* for convenience */ }; /* GPO_OPTIONS */ @@ -33,6 +34,17 @@ enum GPO_LINK_TYPE { #define GPO_LIST_FLAG_MACHINE 0x00000001 #define GPO_LIST_FLAG_SITEONLY 0x00000002 +/* following flags from http://support.microsoft.com/kb/312164/EN-US/ */ +#define GPO_INFO_FLAG_MACHINE 0x00000001 +#define GPO_INFO_FLAG_BACKGROUND 0x00000010 +#define GPO_INFO_FLAG_SLOWLINK 0x00000020 +#define GPO_INFO_FLAG_VERBOSE 0x00000040 +#define GPO_INFO_FLAG_NOCHANGES 0x00000080 +#define GPO_INFO_FLAG_LINKTRANSITION 0x00000100 +#define GPO_INFO_FLAG_LOGRSOP_TRANSITION 0x00000200 +#define GPO_INFO_FLAG_FORCED_REFRESH 0x00000400 +#define GPO_INFO_FLAG_SAFEMODE_BOOT 0x00000800 + #define GPO_VERSION_USER(x) (x >> 16) #define GPO_VERSION_MACHINE(x) (x & 0xffff) @@ -88,10 +100,56 @@ struct GP_EXT { char **extensions_guid; char **snapins; char **snapins_guid; + struct GP_EXT *next, *prev; }; #define GPO_CACHE_DIR "gpo_cache" #define GPT_INI "GPT.INI" +#define GPO_REFRESH_INTERVAL 60*90 + +#define GPO_REG_STATE_MACHINE "State\\Machine" + +enum gp_reg_action { + GP_REG_ACTION_NONE = 0, + GP_REG_ACTION_ADD_VALUE = 1, + GP_REG_ACTION_ADD_KEY = 2, + GP_REG_ACTION_DEL_VALUES = 3, + GP_REG_ACTION_DEL_VALUE = 4, + GP_REG_ACTION_DEL_ALL_VALUES = 5, + GP_REG_ACTION_DEL_KEYS = 6, + GP_REG_ACTION_SEC_KEY_SET = 7, + GP_REG_ACTION_SEC_KEY_RESET = 8 +}; + +struct gp_registry_entry { + enum gp_reg_action action; + const char *key; + const char *value; + struct registry_value *data; +}; + +struct gp_registry_value { + const char *value; + struct registry_value *data; +}; + +struct gp_registry_entry2 { + enum gp_reg_action action; + const char *key; + size_t num_values; + struct gp_registry_value **values; +}; + +struct gp_registry_entries { + size_t num_entries; + struct gp_registry_entry **entries; +}; + +struct gp_registry_context { + const struct nt_user_token *token; + const char *path; + struct registry_key *curr_key; +}; #define GP_EXT_GUID_SECURITY "827D319E-6EAC-11D2-A4EA-00C04F79F83A" #define GP_EXT_GUID_REGISTRY "35378EAC-683F-11D2-A89A-00C04FBBCFA2" diff --git a/source3/include/reg_objects.h b/source3/include/reg_objects.h index 3df701f61c..1d0d0d4996 100644 --- a/source3/include/reg_objects.h +++ b/source3/include/reg_objects.h @@ -105,9 +105,16 @@ typedef struct { #define KEY_CURRENT_VERSION "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion" #define KEY_PERFLIB "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib" #define KEY_PERFLIB_009 "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009" +#define KEY_GROUP_POLICY "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Group Policy" +#define KEY_WINLOGON "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon" #define KEY_SMBCONF "HKLM\\SOFTWARE\\Samba\\smbconf" +#define KEY_SAMBA_GROUP_POLICY "HKLM\\SOFTWARE\\Samba\\Group Policy" #define KEY_TREE_ROOT "" +#define KEY_GP_MACHINE_POLICY "HKLM\\Software\\Policies" +#define KEY_GP_MACHINE_WIN_POLICY "HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies" +#define KEY_GP_USER_POLICY "HKCU\\Software\\Policies" +#define KEY_GP_USER_WIN_POLICY "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies" /* * Registry key types * Most keys are going to be GENERIC -- may need a better name? diff --git a/source3/libgpo/gpo_reg.c b/source3/libgpo/gpo_reg.c new file mode 100644 index 0000000000..2a27a7ed93 --- /dev/null +++ b/source3/libgpo/gpo_reg.c @@ -0,0 +1,1058 @@ +/* + * 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" + + +extern REGISTRY_OPS regdb_ops; + +static int gp_reg_fetch_keys(const char *key, REGSUBKEY_CTR *subkey_ctr) +{ + return regdb_ops.fetch_subkeys(key, subkey_ctr); +} + +static bool gp_reg_store_keys(const char *key, REGSUBKEY_CTR *subkeys) +{ + return regdb_ops.store_subkeys(key, subkeys); +} + +static int gp_reg_fetch_values(const char *key, REGVAL_CTR *val) +{ + return regdb_ops.fetch_values(key, val); +} + +static bool gp_reg_store_values(const char *key, REGVAL_CTR *val) +{ + return regdb_ops.store_values(key, val); +} + +static WERROR gp_reg_get_secdesc(TALLOC_CTX *mem_ctx, const char *key, + struct security_descriptor **psecdesc) +{ + return regdb_ops.get_secdesc(mem_ctx, key, psecdesc); +} + +static WERROR gp_reg_set_secdesc(const char *key, + struct security_descriptor *secdesc) +{ + return regdb_ops.set_secdesc(key, secdesc); +} + +/**************************************************************** +****************************************************************/ + +static REGISTRY_OPS gp_reg_ops = { + .fetch_subkeys = gp_reg_fetch_keys, + .fetch_values = gp_reg_fetch_values, + .store_subkeys = gp_reg_store_keys, + .store_values = gp_reg_store_values, +/* .reg_access_check = gp_reg_reg_access_check, */ + .get_secdesc = gp_reg_get_secdesc, + .set_secdesc = gp_reg_set_secdesc +}; + +/**************************************************************** +****************************************************************/ + +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; + static REGISTRY_HOOK gp_reg_hook; + WERROR werr; + + if (!reg_ctx) { + return WERR_INVALID_PARAM; + } + + if (!regdb_init()) { + return WERR_CAN_NOT_COMPLETE; + } + + gp_reg_hook.keyname = initial_path; /* KEY_SAMBA_GROUP_POLICY */ + gp_reg_hook.ops = &gp_reg_ops; + + /* not sure about the cache hook */ + reghook_cache_init(); + + if (!reghook_cache_add(&gp_reg_hook)) { + return WERR_CAN_NOT_COMPLETE; + } + + 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; + } + + 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, KEY_GROUP_POLICY, + &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, + const char *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 gp_reg_set_secdesc(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\n", (int)val->v.dword)); + break; + case REG_QWORD: + DEBUG(lvl,("%d\n", (int)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, + entry->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; +} + -- cgit