diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
commit | 8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch) | |
tree | 4099e8021376c7d8c05bdf8503093d80e9c7bad0 /source3/libgpo/gpext | |
parent | Initial commit. (diff) | |
download | samba-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 'source3/libgpo/gpext')
-rw-r--r-- | source3/libgpo/gpext/registry.c | 440 | ||||
-rw-r--r-- | source3/libgpo/gpext/scripts.c | 487 | ||||
-rw-r--r-- | source3/libgpo/gpext/security.c | 297 | ||||
-rw-r--r-- | source3/libgpo/gpext/wscript_build | 23 |
4 files changed, 1247 insertions, 0 deletions
diff --git a/source3/libgpo/gpext/registry.c b/source3/libgpo/gpext/registry.c new file mode 100644 index 0000000..ffa1d02 --- /dev/null +++ b/source3/libgpo/gpext/registry.c @@ -0,0 +1,440 @@ +/* + * Unix SMB/CIFS implementation. + * Group Policy Support + * Copyright (C) Guenther Deschner 2007-2008,2010 + * + * 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_ini.h" +#include "../libgpo/gpo.h" +#include "libgpo/gpo_proto.h" +#include "registry.h" +#include "../librpc/gen_ndr/ndr_preg.h" +#include "libgpo/gpext/gpext.h" + +#define GP_EXT_NAME "registry" + +/* more info can be found at: + * http://msdn2.microsoft.com/en-us/library/aa374407.aspx */ + +#define GP_REGPOL_FILE "Registry.pol" + +#define GP_REGPOL_FILE_SIGNATURE 0x67655250 /* 'PReg' */ +#define GP_REGPOL_FILE_VERSION 1 + +static TALLOC_CTX *ctx = NULL; + +NTSTATUS gpext_registry_init(TALLOC_CTX *mem_ctx); + +/**************************************************************** +****************************************************************/ + +static bool reg_parse_value(TALLOC_CTX *mem_ctx, + const char **value, + enum gp_reg_action *action) +{ + if (!*value) { + *action = GP_REG_ACTION_ADD_KEY; + return true; + } + + if (strncmp(*value, "**", 2) != 0) { + *action = GP_REG_ACTION_ADD_VALUE; + return true; + } + + if (strnequal(*value, "**DelVals.", 10)) { + *action = GP_REG_ACTION_DEL_ALL_VALUES; + return true; + } + + if (strnequal(*value, "**Del.", 6)) { + *value = talloc_strdup(mem_ctx, *value + 6); + *action = GP_REG_ACTION_DEL_VALUE; + return true; + } + + if (strnequal(*value, "**SecureKey", 11)) { + if (strnequal(*value, "**SecureKey=1", 13)) { + *action = GP_REG_ACTION_SEC_KEY_SET; + return true; + } + + /*************** not tested from here on ***************/ + if (strnequal(*value, "**SecureKey=0", 13)) { + smb_panic("not supported: **SecureKey=0"); + *action = GP_REG_ACTION_SEC_KEY_RESET; + return true; + } + DEBUG(0,("unknown: SecureKey: %s\n", *value)); + smb_panic("not supported SecureKey method"); + return false; + } + + if (strnequal(*value, "**DeleteValues", strlen("**DeleteValues"))) { + smb_panic("not supported: **DeleteValues"); + *action = GP_REG_ACTION_DEL_VALUES; + return false; + } + + if (strnequal(*value, "**DeleteKeys", strlen("**DeleteKeys"))) { + smb_panic("not supported: **DeleteKeys"); + *action = GP_REG_ACTION_DEL_KEYS; + return false; + } + + DEBUG(0,("unknown value: %s\n", *value)); + smb_panic(*value); + return false; +} + +/**************************************************************** +****************************************************************/ + +static bool gp_reg_entry_from_file_entry(TALLOC_CTX *mem_ctx, + struct preg_entry *r, + struct gp_registry_entry **reg_entry) +{ + struct registry_value *data = NULL; + struct gp_registry_entry *entry = NULL; + enum gp_reg_action action = GP_REG_ACTION_NONE; + enum ndr_err_code ndr_err; + + ZERO_STRUCTP(*reg_entry); + + data = talloc_zero(mem_ctx, struct registry_value); + if (!data) + return false; + + data->type = r->type; + + ndr_err = ndr_push_union_blob( + &data->data, + mem_ctx, + &r->data, + r->type, + (ndr_push_flags_fn_t)ndr_push_winreg_Data); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DBG_WARNING("ndr_push_winreg_Data failed: %s\n", + ndr_errstr(ndr_err)); + return false; + } + + entry = talloc_zero(mem_ctx, struct gp_registry_entry); + if (!entry) + return false; + + if (!reg_parse_value(mem_ctx, &r->valuename, &action)) + return false; + + entry->key = talloc_strdup(entry, r->keyname); + entry->value = talloc_strdup(entry, r->valuename); + entry->data = data; + entry->action = action; + + *reg_entry = entry; + + return true; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS reg_parse_registry(TALLOC_CTX *mem_ctx, + uint32_t flags, + const char *filename, + struct gp_registry_entry **entries_p, + size_t *num_entries_p) +{ + DATA_BLOB blob; + NTSTATUS status; + enum ndr_err_code ndr_err; + const char *real_filename = NULL; + struct preg_file r; + struct gp_registry_entry *entries = NULL; + size_t num_entries = 0; + int i; + + status = gp_find_file(mem_ctx, + flags, + filename, + GP_REGPOL_FILE, + &real_filename); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + blob.data = (uint8_t *)file_load(real_filename, &blob.length, 0, NULL); + if (!blob.data) { + return NT_STATUS_CANNOT_LOAD_REGISTRY_FILE; + } + + ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r, + (ndr_pull_flags_fn_t)ndr_pull_preg_file); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = ndr_map_error2ntstatus(ndr_err); + goto out; + } + + if (flags & GPO_INFO_FLAG_VERBOSE) { + NDR_PRINT_DEBUG(preg_file, &r); + } + + if (!strequal(r.header.signature, "PReg")) { + status = NT_STATUS_INVALID_PARAMETER; + goto out; + } + + if (r.header.version != GP_REGPOL_FILE_VERSION) { + status = NT_STATUS_INVALID_PARAMETER; + goto out; + } + + for (i=0; i < r.num_entries; i++) { + + struct gp_registry_entry *r_entry = NULL; + + if (!gp_reg_entry_from_file_entry(mem_ctx, + &r.entries[i], + &r_entry)) { + status = NT_STATUS_NO_MEMORY; + goto out; + } + + if (!add_gp_registry_entry_to_array(mem_ctx, + r_entry, + &entries, + &num_entries)) { + status = NT_STATUS_NO_MEMORY; + goto out; + } + } + + *entries_p = entries; + *num_entries_p = num_entries; + + status = NT_STATUS_OK; + + out: + data_blob_free(&blob); + return status; +} + +/**************************************************************** +****************************************************************/ + +static WERROR reg_apply_registry(TALLOC_CTX *mem_ctx, + const struct security_token *token, + struct registry_key *root_key, + uint32_t flags, + struct gp_registry_entry *entries, + size_t num_entries) +{ + struct gp_registry_context *reg_ctx = NULL; + WERROR werr; + size_t i; + + if (num_entries == 0) { + return WERR_OK; + } + +#if 0 + if (flags & GPO_LIST_FLAG_MACHINE) { + werr = gp_init_reg_ctx(mem_ctx, KEY_HKLM, REG_KEY_WRITE, + get_system_token(), + ®_ctx); + } else { + werr = gp_init_reg_ctx(mem_ctx, KEY_HKCU, REG_KEY_WRITE, + token, + ®_ctx); + } + W_ERROR_NOT_OK_RETURN(werr); +#endif + for (i=0; i<num_entries; i++) { + + /* FIXME: maybe we should check here if we attempt to go beyond + * the 4 allowed reg keys */ + + werr = reg_apply_registry_entry(mem_ctx, root_key, + reg_ctx, + &(entries)[i], + token, flags); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0,("failed to apply registry: %s\n", + win_errstr(werr))); + goto done; + } + } + +done: + gp_free_reg_ctx(reg_ctx); + return werr; +} + + +/**************************************************************** +****************************************************************/ + +static NTSTATUS registry_process_group_policy(TALLOC_CTX *mem_ctx, + uint32_t flags, + struct registry_key *root_key, + const struct security_token *token, + const struct GROUP_POLICY_OBJECT *deleted_gpo_list, + const struct GROUP_POLICY_OBJECT *changed_gpo_list) +{ + NTSTATUS status; + WERROR werr; + struct gp_registry_entry *entries = NULL; + size_t num_entries = 0; + char *unix_path = NULL; + const struct GROUP_POLICY_OBJECT *gpo; + char *gpo_cache_path = cache_path(talloc_tos(), GPO_CACHE_DIR); + if (gpo_cache_path == NULL) { + return NT_STATUS_NO_MEMORY; + } + + /* implementation of the policy callback function, see + * http://msdn.microsoft.com/en-us/library/aa373494%28v=vs.85%29.aspx + * for details - gd */ + + /* for now do not process the list of deleted group policies + + for (gpo = deleted_gpo_list; gpo; gpo = gpo->next) { + } + + */ + + for (gpo = changed_gpo_list; gpo; gpo = gpo->next) { + + gpext_debug_header(0, "registry_process_group_policy", flags, + gpo, GP_EXT_GUID_REGISTRY, NULL); + + status = gpo_get_unix_path(mem_ctx, gpo_cache_path, + gpo, &unix_path); + if (!NT_STATUS_IS_OK(status)) { + goto err_cache_path_free; + } + + status = reg_parse_registry(mem_ctx, + flags, + unix_path, + &entries, + &num_entries); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("failed to parse registry: %s\n", + nt_errstr(status))); + goto err_cache_path_free; + } + + dump_reg_entries(flags, "READ", entries, num_entries); + + werr = reg_apply_registry(mem_ctx, token, root_key, flags, + entries, num_entries); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0,("failed to apply registry: %s\n", + win_errstr(werr))); + status = werror_to_ntstatus(werr); + goto err_cache_path_free; + } + } + status = NT_STATUS_OK; + +err_cache_path_free: + talloc_free(gpo_cache_path); + talloc_free(entries); + return status; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS registry_get_reg_config(TALLOC_CTX *mem_ctx, + struct gp_extension_reg_info **reg_info) +{ + NTSTATUS status; + struct gp_extension_reg_info *info = NULL; + struct gp_extension_reg_table table[] = { + { "ProcessGroupPolicy", REG_SZ, "registry_process_group_policy" }, + { NULL, REG_NONE, NULL } + }; + + info = talloc_zero(mem_ctx, struct gp_extension_reg_info); + NT_STATUS_HAVE_NO_MEMORY(info); + + status = gpext_info_add_entry(mem_ctx, GP_EXT_NAME, + GP_EXT_GUID_REGISTRY, + table, info); + NT_STATUS_NOT_OK_RETURN(status); + + *reg_info = info; + + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS registry_initialize(TALLOC_CTX *mem_ctx) +{ + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS registry_shutdown(void) +{ + NTSTATUS status; + + status = gpext_unregister_gp_extension(GP_EXT_NAME); + if (NT_STATUS_IS_OK(status)) { + return status; + } + + TALLOC_FREE(ctx); + + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static struct gp_extension_methods registry_methods = { + .initialize = registry_initialize, + .process_group_policy = registry_process_group_policy, + .get_reg_config = registry_get_reg_config, + .shutdown = registry_shutdown +}; + +/**************************************************************** +****************************************************************/ + +NTSTATUS gpext_registry_init(TALLOC_CTX *mem_ctx) +{ + NTSTATUS status; + + ctx = talloc_init("gpext_registry_init"); + NT_STATUS_HAVE_NO_MEMORY(ctx); + + status = gpext_register_gp_extension(ctx, SMB_GPEXT_INTERFACE_VERSION, + GP_EXT_NAME, GP_EXT_GUID_REGISTRY, + ®istry_methods); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(ctx); + } + + return status; +} diff --git a/source3/libgpo/gpext/scripts.c b/source3/libgpo/gpext/scripts.c new file mode 100644 index 0000000..fe0f139 --- /dev/null +++ b/source3/libgpo/gpext/scripts.c @@ -0,0 +1,487 @@ +/* + * Unix SMB/CIFS implementation. + * Group Policy 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/>. + */ + +#include "includes.h" +#include "../libgpo/gpo_ini.h" +#include "../libgpo/gpo.h" +#include "libgpo/gpo_proto.h" +#include "registry.h" +#include "registry/reg_api.h" +#include "../libcli/registry/util_reg.h" +#include "libgpo/gpext/gpext.h" + +#define GP_EXT_NAME "scripts" + +#define KEY_GP_SCRIPTS "Software\\Policies\\Microsoft\\Windows\\System\\Scripts" + +#define GP_SCRIPTS_INI "Scripts/scripts.ini" + +#define GP_SCRIPTS_INI_STARTUP "Startup" +#define GP_SCRIPTS_INI_SHUTDOWN "Shutdown" +#define GP_SCRIPTS_INI_LOGON "Logon" +#define GP_SCRIPTS_INI_LOGOFF "Logoff" + +#define GP_SCRIPTS_SECTION_CMDLINE "cmdline" +#define GP_SCRIPTS_SECTION_PARAMETERS "parameters" + +#define GP_SCRIPTS_REG_VAL_SCRIPT "Script" +#define GP_SCRIPTS_REG_VAL_PARAMETERS "Parameters" +#define GP_SCRIPTS_REG_VAL_EXECTIME "ExecTime" + +NTSTATUS gpext_scripts_init(TALLOC_CTX *mem_ctx); + +static TALLOC_CTX *ctx = NULL; + +/**************************************************************** +****************************************************************/ + +static NTSTATUS scripts_get_reg_config(TALLOC_CTX *mem_ctx, + struct gp_extension_reg_info **reg_info) +{ + NTSTATUS status; + struct gp_extension_reg_info *info = NULL; + + struct gp_extension_reg_table table[] = { + { "ProcessGroupPolicy", REG_SZ, "scripts_process_group_policy" }, + { "NoGPOListChanges", REG_DWORD, "1" }, + { "NoSlowLink", REG_DWORD, "1" }, + { "NotifyLinkTransition", REG_DWORD, "1" }, + { NULL, REG_NONE, NULL }, + }; + + info = talloc_zero(mem_ctx, struct gp_extension_reg_info); + NT_STATUS_HAVE_NO_MEMORY(info); + + status = gpext_info_add_entry(mem_ctx, GP_EXT_NAME, + GP_EXT_GUID_SCRIPTS, + table, info); + NT_STATUS_NOT_OK_RETURN(status); + + *reg_info = info; + + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS generate_gp_registry_entry(TALLOC_CTX *mem_ctx, + const char *key, + const char *value, + uint32_t data_type, + DATA_BLOB *blob, + enum gp_reg_action action, + struct gp_registry_entry **entry_out) +{ + struct gp_registry_entry *entry = NULL; + struct registry_value *data = NULL; + + entry = talloc_zero(mem_ctx, struct gp_registry_entry); + NT_STATUS_HAVE_NO_MEMORY(entry); + + data = talloc_zero(mem_ctx, struct registry_value); + NT_STATUS_HAVE_NO_MEMORY(data); + + data->type = data_type; + data->data = *blob; + + entry->key = key; + entry->data = data; + entry->action = action; + entry->value = talloc_strdup(mem_ctx, value); + NT_STATUS_HAVE_NO_MEMORY(entry->value); + + *entry_out = entry; + + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS scripts_parse_ini_section(struct gp_inifile_context *ini_ctx, + uint32_t flags, + const char *section, + struct gp_registry_entry **entries, + size_t *num_entries) +{ + NTSTATUS status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + NTSTATUS result; + int i = 0; + + while (1) { + + const char *key = NULL; + const char *script = NULL; + const char *count = NULL; + const char *parameters = NULL; + DATA_BLOB blob; + bool ok; + + count = talloc_asprintf(ini_ctx->mem_ctx, "%d", i); + NT_STATUS_HAVE_NO_MEMORY(count); + + key = talloc_asprintf(ini_ctx->mem_ctx, "%s:%s%s", + section, count, + GP_SCRIPTS_SECTION_CMDLINE); + NT_STATUS_HAVE_NO_MEMORY(key); + + result = gp_inifile_getstring(ini_ctx, key, &script); + if (!NT_STATUS_IS_OK(result)) { + break; + } + + key = talloc_asprintf(ini_ctx->mem_ctx, "%s:%s%s", + section, count, + GP_SCRIPTS_SECTION_PARAMETERS); + NT_STATUS_HAVE_NO_MEMORY(key); + + result = gp_inifile_getstring(ini_ctx, key, ¶meters); + if (!NT_STATUS_IS_OK(result)) { + break; + } + + { + struct gp_registry_entry *entry = NULL; + + ok = push_reg_sz(ini_ctx->mem_ctx, &blob, script); + if (!ok) { + return NT_STATUS_NO_MEMORY; + } + + status = generate_gp_registry_entry(ini_ctx->mem_ctx, + count, + GP_SCRIPTS_REG_VAL_SCRIPT, + REG_SZ, + &blob, + GP_REG_ACTION_ADD_VALUE, + &entry); + NT_STATUS_NOT_OK_RETURN(status); + if (!add_gp_registry_entry_to_array(ini_ctx->mem_ctx, + entry, + entries, + num_entries)) { + return NT_STATUS_NO_MEMORY; + } + } + { + struct gp_registry_entry *entry = NULL; + + ok = push_reg_sz(ini_ctx->mem_ctx, &blob, parameters); + if (!ok) { + return NT_STATUS_NO_MEMORY; + } + + status = generate_gp_registry_entry(ini_ctx->mem_ctx, + count, + GP_SCRIPTS_REG_VAL_PARAMETERS, + REG_SZ, + &blob, + GP_REG_ACTION_ADD_VALUE, + &entry); + NT_STATUS_NOT_OK_RETURN(status); + if (!add_gp_registry_entry_to_array(ini_ctx->mem_ctx, + entry, + entries, + num_entries)) { + return NT_STATUS_NO_MEMORY; + } + } + { + struct gp_registry_entry *entry = NULL; + + blob = data_blob_talloc_zero(ini_ctx->mem_ctx, 8); + + status = generate_gp_registry_entry(ini_ctx->mem_ctx, + count, + GP_SCRIPTS_REG_VAL_EXECTIME, + REG_QWORD, + &blob, + GP_REG_ACTION_ADD_VALUE, + &entry); + NT_STATUS_NOT_OK_RETURN(status); + if (!add_gp_registry_entry_to_array(ini_ctx->mem_ctx, + entry, + entries, + num_entries)) { + return NT_STATUS_NO_MEMORY; + } + } + status = NT_STATUS_OK; + i++; + } + + return status; +} + +/**************************************************************** +****************************************************************/ + +static WERROR scripts_store_reg_gpovals(TALLOC_CTX *mem_ctx, + struct registry_key *key, + const struct GROUP_POLICY_OBJECT *gpo) +{ + WERROR werr; + + if (!key || !gpo) { + return WERR_INVALID_PARAMETER; + } + + 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, "FileSysPath", + gpo->file_sys_path); + W_ERROR_NOT_OK_RETURN(werr); + + werr = gp_store_reg_val_sz(mem_ctx, key, "GPO-ID", + gpo->ds_path); + W_ERROR_NOT_OK_RETURN(werr); + + werr = gp_store_reg_val_sz(mem_ctx, key, "GPOName", + gpo->name); + W_ERROR_NOT_OK_RETURN(werr); + + werr = gp_store_reg_val_sz(mem_ctx, key, "SOM-ID", + gpo->link); + W_ERROR_NOT_OK_RETURN(werr); + + return werr; +} + +/**************************************************************** +****************************************************************/ + +static WERROR scripts_apply(TALLOC_CTX *mem_ctx, + const struct security_token *token, + struct registry_key *root_key, + uint32_t flags, + const char *section, + const struct GROUP_POLICY_OBJECT *gpo, + struct gp_registry_entry *entries, + size_t num_entries) +{ + struct gp_registry_context *reg_ctx = NULL; + WERROR werr; + size_t i; + const char *keystr = NULL; + int count = 0; + + if (num_entries == 0) { + return WERR_OK; + } + +#if 0 + if (flags & GPO_INFO_FLAG_MACHINE) { + struct security_token *tmp_token; + + tmp_token = registry_create_system_token(mem_ctx); + W_ERROR_HAVE_NO_MEMORY(tmp_token); + + werr = gp_init_reg_ctx(mem_ctx, KEY_HKLM, REG_KEY_WRITE, + tmp_token, + ®_ctx); + } else { + werr = gp_init_reg_ctx(mem_ctx, KEY_HKCU, REG_KEY_WRITE, + token, + ®_ctx); + } + W_ERROR_NOT_OK_RETURN(werr); +#endif + + keystr = talloc_asprintf(mem_ctx, "%s\\%s\\%d", KEY_GP_SCRIPTS, + section, count++); + W_ERROR_HAVE_NO_MEMORY(keystr); + + reg_deletekey_recursive(root_key, keystr); + + werr = gp_store_reg_subkey(mem_ctx, keystr, + root_key, &root_key); + if (!W_ERROR_IS_OK(werr)) { + goto done; + } + + werr = scripts_store_reg_gpovals(mem_ctx, root_key, gpo); + if (!W_ERROR_IS_OK(werr)) { + goto done; + } + + for (i=0; i<num_entries; i++) { + + werr = reg_apply_registry_entry(mem_ctx, root_key, reg_ctx, + &(entries)[i], + token, flags); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0,("failed to apply registry: %s\n", + win_errstr(werr))); + goto done; + } + } + + done: + gp_free_reg_ctx(reg_ctx); + return werr; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS scripts_process_group_policy(TALLOC_CTX *mem_ctx, + uint32_t flags, + struct registry_key *root_key, + const struct security_token *token, + const struct GROUP_POLICY_OBJECT *deleted_gpo_list, + const struct GROUP_POLICY_OBJECT *changed_gpo_list) +{ + NTSTATUS status; + WERROR werr; + int i = 0; + char *unix_path = NULL; + struct gp_inifile_context *ini_ctx = NULL; + struct gp_registry_entry *entries = NULL; + size_t num_entries = 0; + const char *list[] = { + GP_SCRIPTS_INI_STARTUP, + GP_SCRIPTS_INI_SHUTDOWN, + GP_SCRIPTS_INI_LOGON, + GP_SCRIPTS_INI_LOGOFF + }; + const struct GROUP_POLICY_OBJECT *gpo; + char *gpo_cache_path = cache_path(talloc_tos(), GPO_CACHE_DIR); + if (gpo_cache_path == NULL) { + return NT_STATUS_NO_MEMORY; + } + + /* implementation of the policy callback function, see + * http://msdn.microsoft.com/en-us/library/aa373494%28v=vs.85%29.aspx + * for details - gd */ + + /* for now do not process the list of deleted group policies + + for (gpo = deleted_gpo_list; gpo; gpo = gpo->next) { + } + + */ + + for (gpo = changed_gpo_list; gpo; gpo = gpo->next) { + + gpext_debug_header(0, "scripts_process_group_policy", flags, + gpo, GP_EXT_GUID_SCRIPTS, NULL); + + status = gpo_get_unix_path(mem_ctx, gpo_cache_path, + gpo, &unix_path); + if (!NT_STATUS_IS_OK(status)) { + goto err_cache_path_free; + } + + status = gp_inifile_init_context(mem_ctx, flags, unix_path, + GP_SCRIPTS_INI, &ini_ctx); + if (!NT_STATUS_IS_OK(status)) { + goto err_cache_path_free; + } + + for (i = 0; i < ARRAY_SIZE(list); i++) { + + TALLOC_FREE(entries); + num_entries = 0; + + status = scripts_parse_ini_section(ini_ctx, flags, list[i], + &entries, &num_entries); + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + continue; + } + + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(ini_ctx); + goto err_cache_path_free; + } + + dump_reg_entries(flags, "READ", entries, num_entries); + + werr = scripts_apply(ini_ctx->mem_ctx, token, root_key, + flags, list[i], gpo, entries, num_entries); + if (!W_ERROR_IS_OK(werr)) { + continue; /* FIXME: finally fix storing empty strings and REG_QWORD! */ + } + } + + TALLOC_FREE(ini_ctx); + } + status = NT_STATUS_OK; + +err_cache_path_free: + talloc_free(gpo_cache_path); + return status; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS scripts_initialize(TALLOC_CTX *mem_ctx) +{ + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS scripts_shutdown(void) +{ + NTSTATUS status; + + status = gpext_unregister_gp_extension(GP_EXT_NAME); + if (NT_STATUS_IS_OK(status)) { + return status; + } + + TALLOC_FREE(ctx); + + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static struct gp_extension_methods scripts_methods = { + .initialize = scripts_initialize, + .process_group_policy = scripts_process_group_policy, + .get_reg_config = scripts_get_reg_config, + .shutdown = scripts_shutdown +}; + +/**************************************************************** +****************************************************************/ + +NTSTATUS gpext_scripts_init(TALLOC_CTX *mem_ctx) +{ + NTSTATUS status; + + ctx = talloc_init("gpext_scripts_init"); + NT_STATUS_HAVE_NO_MEMORY(ctx); + + status = gpext_register_gp_extension(ctx, SMB_GPEXT_INTERFACE_VERSION, + GP_EXT_NAME, GP_EXT_GUID_SCRIPTS, + &scripts_methods); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(ctx); + } + + return status; +} diff --git a/source3/libgpo/gpext/security.c b/source3/libgpo/gpext/security.c new file mode 100644 index 0000000..a915eec --- /dev/null +++ b/source3/libgpo/gpext/security.c @@ -0,0 +1,297 @@ +/* + * Unix SMB/CIFS implementation. + * Group Policy Support + * Copyright (C) Guenther Deschner 2005-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_ini.h" +#include "../libgpo/gpo.h" +#include "libgpo/gpo_proto.h" +#include "libgpo/gpext/gpext.h" + +#define GP_EXT_NAME "security" + +#define GPTTMPL_UNIX_PATH "Microsoft/Windows NT/SecEdit/GptTmpl.inf" + +#define GPTTMPL_SECTION_UNICODE "Unicode" +#define GPTTMPL_SECTION_VERSION "Version" + +#define GPTTMPL_SECTION_REGISTRY_VALUES "Registry Values" +#define GPTTMPL_SECTION_SYSTEM_ACCESS "System Access" +#define GPTTMPL_SECTION_KERBEROS_POLICY "Kerberos Policy" +#define GPTTMPL_SECTION_EVENT_AUDIT "Event Audit" +#define GPTTMPL_SECTION_PRIVILEGE_RIGHTS "Privilege Rights" +#define GPTTMPL_SECTION_APPLICATION_LOG "Application Log" +#define GPTTMPL_SECTION_SECURITY_LOG "Security Log" +#define GPTTMPL_SECTION_SYSTEM_LOG "System Log" +#define GPTTMPL_SECTION_GROUP_MEMBERSHIP "Group Membership" +#define GPTTMPL_SECTION_FILE_SECURITY "File Security" +#define GPTTMPL_SECTION_SERVICE_GENERAL_SETTING "Service General Setting" + +NTSTATUS gpext_security_init(TALLOC_CTX *mem_ctx); + +static TALLOC_CTX *ctx = NULL; + +struct gpttmpl_table { + const char *section; + const char *parameter; + enum winreg_Type type; +}; + +/**************************************************************** + parse the Version section from gpttmpl file +****************************************************************/ + +#define GPTTMPL_PARAMETER_REVISION "Revision" +#define GPTTMPL_PARAMETER_SIGNATURE "signature" +#define GPTTMPL_VALUE_CHICAGO "\"$CHICAGO$\"" /* whatever this is good for... */ +#define GPTTMPL_PARAMETER_UNICODE "Unicode" + +static NTSTATUS gpttmpl_parse_header(struct gp_inifile_context *ini_ctx, + uint32_t *version_out) +{ + const char *signature = NULL; + NTSTATUS result; + int version; + bool is_unicode = false; + + if (!ini_ctx) { + return NT_STATUS_INVALID_PARAMETER; + } + + result = gp_inifile_getstring(ini_ctx, GPTTMPL_SECTION_VERSION + ":"GPTTMPL_PARAMETER_SIGNATURE, &signature); + if (!NT_STATUS_IS_OK(result)) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + if (!strequal(signature, GPTTMPL_VALUE_CHICAGO)) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + result = gp_inifile_getint(ini_ctx, GPTTMPL_SECTION_VERSION + ":"GPTTMPL_PARAMETER_REVISION, &version); + if (!NT_STATUS_IS_OK(result)) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + if (version_out) { + *version_out = version; + } + + result = gp_inifile_getbool(ini_ctx, GPTTMPL_SECTION_UNICODE + ":"GPTTMPL_PARAMETER_UNICODE, &is_unicode); + if (!NT_STATUS_IS_OK(result) || !is_unicode) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS gpttmpl_init_context(TALLOC_CTX *mem_ctx, + uint32_t flags, + const char *unix_path, + struct gp_inifile_context **ini_ctx) +{ + NTSTATUS status; + uint32_t version; + struct gp_inifile_context *tmp_ctx = NULL; + + status = gp_inifile_init_context(mem_ctx, flags, unix_path, + GPTTMPL_UNIX_PATH, &tmp_ctx); + NT_STATUS_NOT_OK_RETURN(status); + + status = gpttmpl_parse_header(tmp_ctx, &version); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1,("gpttmpl_init_context: failed: %s\n", + nt_errstr(status))); + TALLOC_FREE(tmp_ctx); + return status; + } + + *ini_ctx = tmp_ctx; + + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS gpttmpl_process(struct gp_inifile_context *ini_ctx, + struct registry_key *root_key, + uint32_t flags) +{ + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS security_process_group_policy(TALLOC_CTX *mem_ctx, + uint32_t flags, + struct registry_key *root_key, + const struct security_token *token, + const struct GROUP_POLICY_OBJECT *deleted_gpo_list, + const struct GROUP_POLICY_OBJECT *changed_gpo_list) +{ + NTSTATUS status = NT_STATUS_OK; + char *unix_path = NULL; + struct gp_inifile_context *ini_ctx = NULL; + const struct GROUP_POLICY_OBJECT *gpo; + char *gpo_cache_path = cache_path(talloc_tos(), GPO_CACHE_DIR); + if (gpo_cache_path == NULL) { + return NT_STATUS_NO_MEMORY; + } + + /* implementation of the policy callback function, see + * http://msdn.microsoft.com/en-us/library/aa373494%28v=vs.85%29.aspx + * for details - gd */ + + /* for now do not process the list of deleted group policies + + for (gpo = deleted_gpo_list; gpo; gpo = gpo->next) { + } + + */ + + for (gpo = changed_gpo_list; gpo; gpo = gpo->next) { + + gpext_debug_header(0, "security_process_group_policy", flags, + gpo, GP_EXT_GUID_SECURITY, NULL); + + /* this handler processes the gpttmpl files and merge output to the + * registry */ + + status = gpo_get_unix_path(mem_ctx, gpo_cache_path, + gpo, &unix_path); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } + + status = gpttmpl_init_context(mem_ctx, flags, unix_path, + &ini_ctx); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } + + status = gpttmpl_process(ini_ctx, root_key, flags); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } + + TALLOC_FREE(ini_ctx); + } + + out: + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("security_process_group_policy: %s\n", + nt_errstr(status))); + } + TALLOC_FREE(ini_ctx); + talloc_free(gpo_cache_path); + + return status; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS security_get_reg_config(TALLOC_CTX *mem_ctx, + struct gp_extension_reg_info **reg_info) +{ + NTSTATUS status; + struct gp_extension_reg_info *info = NULL; + + struct gp_extension_reg_table table[] = { + /* FIXME: how can we store the "(Default)" value ??? */ + /* { "", REG_SZ, "Security" }, */ + { "ProcessGroupPolicy", REG_SZ, "security_process_group_policy" }, + { "NoUserPolicy", REG_DWORD, "1" }, + { "ExtensionDebugLevel", REG_DWORD, "1" }, + { NULL, REG_NONE, NULL } + }; + + info = talloc_zero(mem_ctx, struct gp_extension_reg_info); + NT_STATUS_HAVE_NO_MEMORY(info); + + status = gpext_info_add_entry(mem_ctx, GP_EXT_NAME, + GP_EXT_GUID_SECURITY, + table, info); + NT_STATUS_NOT_OK_RETURN(status); + + *reg_info = info; + + return NT_STATUS_OK; +} + + +/**************************************************************** +****************************************************************/ + +static NTSTATUS security_initialize(TALLOC_CTX *mem_ctx) +{ + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS security_shutdown(void) +{ + NTSTATUS status; + + status = gpext_unregister_gp_extension(GP_EXT_NAME); + if (NT_STATUS_IS_OK(status)) { + return status; + } + + TALLOC_FREE(ctx); + + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static struct gp_extension_methods security_methods = { + .initialize = security_initialize, + .process_group_policy = security_process_group_policy, + .get_reg_config = security_get_reg_config, + .shutdown = security_shutdown +}; + +/**************************************************************** +****************************************************************/ + +NTSTATUS gpext_security_init(TALLOC_CTX *mem_ctx) +{ + NTSTATUS status; + + ctx = talloc_init("gpext_security_init"); + NT_STATUS_HAVE_NO_MEMORY(ctx); + + status = gpext_register_gp_extension(ctx, SMB_GPEXT_INTERFACE_VERSION, + GP_EXT_NAME, GP_EXT_GUID_SECURITY, + &security_methods); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(ctx); + } + + return status; +} diff --git a/source3/libgpo/gpext/wscript_build b/source3/libgpo/gpext/wscript_build new file mode 100644 index 0000000..365b420 --- /dev/null +++ b/source3/libgpo/gpext/wscript_build @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +bld.SAMBA3_MODULE('gpext_registry', + subsystem='gpext', + source='registry.c', + deps='NDR_PREG', + init_function='', + internal_module=bld.SAMBA3_IS_STATIC_MODULE('gpext_registry'), + enabled=bld.SAMBA3_IS_ENABLED_MODULE('gpext_registry')) + +bld.SAMBA3_MODULE('gpext_scripts', + subsystem='gpext', + source='scripts.c', + init_function='', + internal_module=bld.SAMBA3_IS_STATIC_MODULE('gpext_scripts'), + enabled=bld.SAMBA3_IS_ENABLED_MODULE('gpext_scripts')) + +bld.SAMBA3_MODULE('gpext_security', + subsystem='gpext', + source='security.c', + init_function='', + internal_module=bld.SAMBA3_IS_STATIC_MODULE('gpext_security'), + enabled=bld.SAMBA3_IS_ENABLED_MODULE('gpext_security')) |