diff options
author | Günther Deschner <gd@samba.org> | 2008-04-13 17:52:11 +0200 |
---|---|---|
committer | Günther Deschner <gd@samba.org> | 2008-04-13 17:52:11 +0200 |
commit | de013be0b6875e3febc526ecc6c8a67dfc8876cb (patch) | |
tree | 19ae20199afe95aec17c27866c6e149dc49399e8 /source3/libgpo/gpext | |
parent | e39f02217a8ec0eeee4a4179ab5b39d35e0575c6 (diff) | |
download | samba-de013be0b6875e3febc526ecc6c8a67dfc8876cb.tar.gz samba-de013be0b6875e3febc526ecc6c8a67dfc8876cb.tar.bz2 samba-de013be0b6875e3febc526ecc6c8a67dfc8876cb.zip |
gpo: add scripts plugin.
Guenther
(This used to be commit cd6388f04041a667bf0909d81e8af5f7b3bdc4af)
Diffstat (limited to 'source3/libgpo/gpext')
-rw-r--r-- | source3/libgpo/gpext/scripts.c | 443 |
1 files changed, 443 insertions, 0 deletions
diff --git a/source3/libgpo/gpext/scripts.c b/source3/libgpo/gpext/scripts.c new file mode 100644 index 0000000000..c07407c3f0 --- /dev/null +++ b/source3/libgpo/gpext/scripts.c @@ -0,0 +1,443 @@ +/* + * 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" + +#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" + +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_P(mem_ctx, struct gp_extension_reg_info); + NT_STATUS_HAVE_NO_MEMORY(info); + + status = gp_ext_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, + const void *data_p, + 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_P(mem_ctx, struct gp_registry_entry); + NT_STATUS_HAVE_NO_MEMORY(entry); + + data = TALLOC_ZERO_P(mem_ctx, struct registry_value); + NT_STATUS_HAVE_NO_MEMORY(data); + + data->type = data_type; + switch (data->type) { + case REG_QWORD: + data->v.qword = (uint64_t)data_p; + break; + case REG_SZ: + data->v.sz.str = talloc_strdup(mem_ctx, (char *)data_p); + data->v.sz.len = strlen(data->v.sz.str); + break; + default: + return NT_STATUS_NOT_SUPPORTED; + } + + 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; + int i = 0; + + while (1) { + + const char *key = NULL; + const char *script = NULL; + const char *count = NULL; + const char *parameters = NULL; + + 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); + + script = iniparser_getstring(ini_ctx->dict, key, NULL); + if (!script) { + break; + } + + key = talloc_asprintf(ini_ctx->mem_ctx, "%s:%s%s", + section, count, + GP_SCRIPTS_SECTION_PARAMETERS); + NT_STATUS_HAVE_NO_MEMORY(key); + + parameters = iniparser_getstring(ini_ctx->dict, key, NULL); + + { + struct gp_registry_entry *entry = NULL; + status = generate_gp_registry_entry(ini_ctx->mem_ctx, + count, + GP_SCRIPTS_REG_VAL_SCRIPT, + REG_SZ, + script, + 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; + status = generate_gp_registry_entry(ini_ctx->mem_ctx, + count, + GP_SCRIPTS_REG_VAL_PARAMETERS, + REG_SZ, + parameters, + 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; + status = generate_gp_registry_entry(ini_ctx->mem_ctx, + count, + GP_SCRIPTS_REG_VAL_EXECTIME, + REG_QWORD, + 0, + 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, + struct GROUP_POLICY_OBJECT *gpo) +{ + WERROR werr; + + if (!key || !gpo) { + return WERR_INVALID_PARAM; + } + + 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 nt_user_token *token, + struct registry_key *root_key, + uint32_t flags, + const char *section, + 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 nt_user_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(mem_ctx, 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", + dos_errstr(werr))); + goto done; + } + } + + done: + gp_free_reg_ctx(reg_ctx); + return werr; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS scripts_process_group_policy(ADS_STRUCT *ads, + TALLOC_CTX *mem_ctx, + uint32_t flags, + struct registry_key *root_key, + const struct nt_user_token *token, + struct GROUP_POLICY_OBJECT *gpo, + const char *extension_guid, + const char *snapin_guid) +{ + 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 + }; + + debug_gpext_header(0, "scripts_process_group_policy", flags, gpo, + extension_guid, snapin_guid); + + status = gpo_get_unix_path(mem_ctx, gpo, &unix_path); + NT_STATUS_NOT_OK_RETURN(status); + + status = gp_inifile_init_context(mem_ctx, flags, unix_path, + GP_SCRIPTS_INI, &ini_ctx); + NT_STATUS_NOT_OK_RETURN(status); + + 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)) { + return status; + } + + 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 emtpy strings and REG_QWORD! */ + TALLOC_FREE(ini_ctx); + return werror_to_ntstatus(werr); + } + } + + TALLOC_FREE(ini_ctx); + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS scripts_initialize(TALLOC_CTX *mem_ctx) +{ + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS scripts_shutdown(void) +{ + NTSTATUS status; + + status = 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(void) +{ + NTSTATUS status; + + ctx = talloc_init("gpext_scripts_init"); + NT_STATUS_HAVE_NO_MEMORY(ctx); + + status = 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; +} |