From e8bd75ec73a804375753be9eb15d7fc5d9bc18c7 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 18 Mar 2008 21:30:34 +0100 Subject: Bind Group Policy processing closer to the samba registry. Guenther (This used to be commit e9c56250eb7a2dc4e69962c5b48875834941ccfc) --- source3/libgpo/gpo_ldap.c | 2 +- source3/libgpo/gpo_util.c | 202 +++++++++++++++++++++++++++----------- source3/registry/reg_backend_db.c | 8 ++ source3/utils/net_ads_gpo.c | 194 +++++++++++++++++++++++++++++------- 4 files changed, 310 insertions(+), 96 deletions(-) (limited to 'source3') diff --git a/source3/libgpo/gpo_ldap.c b/source3/libgpo/gpo_ldap.c index 477832abc5..0e77f0a856 100644 --- a/source3/libgpo/gpo_ldap.c +++ b/source3/libgpo/gpo_ldap.c @@ -725,7 +725,7 @@ ADS_STATUS ads_get_gpo_list(ADS_STRUCT *ads, /* (L)ocal */ status = add_local_policy_to_gpo_list(mem_ctx, gpo_list, - GP_LINK_UNKOWN); + GP_LINK_LOCAL); if (!ADS_ERR_OK(status)) { return status; } diff --git a/source3/libgpo/gpo_util.c b/source3/libgpo/gpo_util.c index f41bbc1817..7105b21de8 100644 --- a/source3/libgpo/gpo_util.c +++ b/source3/libgpo/gpo_util.c @@ -400,21 +400,34 @@ void dump_gplink(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, struct GP_LINK *gp_link) /**************************************************************** ****************************************************************/ -NTSTATUS process_extension(ADS_STRUCT *ads, - TALLOC_CTX *mem_ctx, - uint32_t flags, - const struct nt_user_token *token, - struct GROUP_POLICY_OBJECT *gpo, - const char *extension_guid, - const char *snapin_guid) +static bool gpo_get_gp_ext_from_gpo(TALLOC_CTX *mem_ctx, + uint32_t flags, + struct GROUP_POLICY_OBJECT *gpo, + struct GP_EXT **gp_ext) { - DEBUG(0,("process_extension: no extension available for:\n")); - DEBUGADD(0,("%s (%s) (snapin: %s)\n", - extension_guid, - cse_gpo_guid_string_to_name(extension_guid), - snapin_guid)); + ZERO_STRUCTP(*gp_ext); + + if (flags & GPO_INFO_FLAG_MACHINE) { + + if (gpo->machine_extensions) { + + if (!ads_parse_gp_ext(mem_ctx, gpo->machine_extensions, + gp_ext)) { + return false; + } + } + } else { - return NT_STATUS_OK; + if (gpo->user_extensions) { + + if (!ads_parse_gp_ext(mem_ctx, gpo->user_extensions, + gp_ext)) { + return false; + } + } + } + + return true; } /**************************************************************** @@ -423,6 +436,7 @@ NTSTATUS process_extension(ADS_STRUCT *ads, ADS_STATUS gpo_process_a_gpo(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const struct nt_user_token *token, + struct registry_key *root_key, struct GROUP_POLICY_OBJECT *gpo, const char *extension_guid_filter, uint32_t flags) @@ -433,36 +447,22 @@ ADS_STATUS gpo_process_a_gpo(ADS_STRUCT *ads, DEBUG(10,("gpo_process_a_gpo: processing gpo %s (%s)\n", gpo->name, gpo->display_name)); if (extension_guid_filter) { - DEBUGADD(10,("gpo_process_a_gpo: using filter %s\n", - extension_guid_filter)); + DEBUGADD(10,("gpo_process_a_gpo: using filter %s (%s)\n", + extension_guid_filter, + cse_gpo_guid_string_to_name(extension_guid_filter))); } - if (flags & GPO_LIST_FLAG_MACHINE) { - - if (gpo->machine_extensions) { - - if (!ads_parse_gp_ext(mem_ctx, gpo->machine_extensions, - &gp_ext)) { - return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } + if (!gpo_get_gp_ext_from_gpo(mem_ctx, flags, gpo, &gp_ext)) { + return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } - } else { - /* nothing to apply */ - return ADS_SUCCESS; - } - - } else { - - if (gpo->user_extensions) { - - if (!ads_parse_gp_ext(mem_ctx, gpo->user_extensions, - &gp_ext)) { - return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - } else { - /* nothing to apply */ - return ADS_SUCCESS; + if (!gp_ext || !gp_ext->num_exts) { + if (flags & GPO_INFO_FLAG_VERBOSE) { + DEBUG(0,("gpo_process_a_gpo: " + "no policies in %s (%s) for this extension\n", + gpo->name, gpo->display_name)); } + return ADS_SUCCESS; } for (i=0; inum_exts; i++) { @@ -475,10 +475,10 @@ ADS_STATUS gpo_process_a_gpo(ADS_STRUCT *ads, continue; } - ntstatus = process_extension(ads, mem_ctx, - flags, token, gpo, - gp_ext->extensions_guid[i], - gp_ext->snapins_guid[i]); + ntstatus = gpext_process_extension(ads, mem_ctx, + flags, token, root_key, gpo, + gp_ext->extensions_guid[i], + gp_ext->snapins_guid[i]); if (!NT_STATUS_IS_OK(ntstatus)) { ADS_ERROR_NT(ntstatus); } @@ -490,37 +490,122 @@ ADS_STATUS gpo_process_a_gpo(ADS_STRUCT *ads, /**************************************************************** ****************************************************************/ -ADS_STATUS gpo_process_gpo_list(ADS_STRUCT *ads, - TALLOC_CTX *mem_ctx, - const struct nt_user_token *token, - struct GROUP_POLICY_OBJECT *gpo_list, - const char *extensions_guid, - uint32_t flags) +static ADS_STATUS gpo_process_gpo_list_by_ext(ADS_STRUCT *ads, + TALLOC_CTX *mem_ctx, + const struct nt_user_token *token, + struct registry_key *root_key, + struct GROUP_POLICY_OBJECT *gpo_list, + const char *extensions_guid, + uint32_t flags) { ADS_STATUS status; struct GROUP_POLICY_OBJECT *gpo; - /* FIXME: ok, this is wrong, windows does process the extensions and - * hands the list of gpos to each extension and not process each gpo - * with all extensions (this is how the extension can store the list - * gplist in the registry) */ - for (gpo = gpo_list; gpo; gpo = gpo->next) { - status = gpo_process_a_gpo(ads, mem_ctx, token, gpo, - extensions_guid, flags); + if (gpo->link_type == GP_LINK_LOCAL) { + continue; + } + + + /* FIXME: we need to pass down the *list* down to the + * extension, otherwise we cannot store the e.g. the *list* of + * logon-scripts correctly (for more then one GPO) */ + + status = gpo_process_a_gpo(ads, mem_ctx, token, root_key, + gpo, extensions_guid, flags); if (!ADS_ERR_OK(status)) { - DEBUG(0,("failed to process gpo: %s\n", + DEBUG(0,("failed to process gpo by ext: %s\n", ads_errstr(status))); return status; } - } return ADS_SUCCESS; } +/**************************************************************** +****************************************************************/ + +ADS_STATUS gpo_process_gpo_list(ADS_STRUCT *ads, + TALLOC_CTX *mem_ctx, + const struct nt_user_token *token, + struct GROUP_POLICY_OBJECT *gpo_list, + const char *extensions_guid_filter, + uint32_t flags) +{ + ADS_STATUS status = ADS_SUCCESS; + struct gp_extension *gp_ext_list = NULL; + struct gp_extension *gp_ext = NULL; + struct registry_key *root_key = NULL; + struct gp_registry_context *reg_ctx = NULL; + WERROR werr; + + status = ADS_ERROR_NT(init_gp_extensions(mem_ctx)); + if (!ADS_ERR_OK(status)) { + return status; + } + + gp_ext_list = get_gp_extension_list(); + if (!gp_ext_list) { + return ADS_ERROR_NT(NT_STATUS_DLL_INIT_FAILED); + } + + /* get the key here */ + 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); + } + if (!W_ERROR_IS_OK(werr)) { + gp_free_reg_ctx(reg_ctx); + return ADS_ERROR_NT(werror_to_ntstatus(werr)); + } + + root_key = reg_ctx->curr_key; + + for (gp_ext = gp_ext_list; gp_ext; gp_ext = gp_ext->next) { + + const char *guid_str = NULL; + + guid_str = GUID_string(mem_ctx, gp_ext->guid); + if (!guid_str) { + status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); + goto done; + } + + if (extensions_guid_filter && + (!strequal(guid_str, extensions_guid_filter))) { + continue; + } + + DEBUG(0,("-------------------------------------------------\n")); + DEBUG(0,("gpo_process_gpo_list: processing ext: %s {%s}\n", + gp_ext->name, guid_str)); + + + status = gpo_process_gpo_list_by_ext(ads, mem_ctx, token, + root_key, gpo_list, + guid_str, flags); + if (!ADS_ERR_OK(status)) { + goto done; + } + } + + done: + gp_free_reg_ctx(reg_ctx); + TALLOC_FREE(root_key); + free_gp_extensions(); + + return status; +} + + /**************************************************************** check wether the version number in a GROUP_POLICY_OBJECT match those of the locally stored version. If not, fetch the required policy via CIFS @@ -621,6 +706,7 @@ NTSTATUS check_refresh_gpo(ADS_STRUCT *ads, gpo->version, GPO_VERSION_USER(gpo->version), GPO_VERSION_MACHINE(gpo->version))); + DEBUGADD(10,("LDAP GPO link:\t\t%s\n", gpo->link)); result = NT_STATUS_OK; diff --git a/source3/registry/reg_backend_db.c b/source3/registry/reg_backend_db.c index 08f74eb583..07aaf68d50 100644 --- a/source3/registry/reg_backend_db.c +++ b/source3/registry/reg_backend_db.c @@ -46,6 +46,14 @@ static const char *builtin_registry_paths[] = { KEY_SMBCONF, KEY_PERFLIB, KEY_PERFLIB_009, + KEY_GROUP_POLICY, + KEY_SAMBA_GROUP_POLICY, + KEY_GP_MACHINE_POLICY, + KEY_GP_MACHINE_WIN_POLICY, + KEY_HKCU, + KEY_GP_USER_POLICY, + KEY_GP_USER_WIN_POLICY, + KEY_WINLOGON_GPEXT_PATH, "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors", KEY_PROD_OPTIONS, "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\DefaultUserConfiguration", diff --git a/source3/utils/net_ads_gpo.c b/source3/utils/net_ads_gpo.c index 5f53982da9..d71fa908e9 100644 --- a/source3/utils/net_ads_gpo.c +++ b/source3/utils/net_ads_gpo.c @@ -1,20 +1,20 @@ -/* - Samba Unix/Linux SMB client library +/* + Samba Unix/Linux SMB client library net ads commands for Group Policy - Copyright (C) 2005 Guenther Deschner (gd@samba.org) + Copyright (C) 2005-2008 Guenther Deschner (gd@samba.org) 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 . + along with this program. If not, see . */ #include "includes.h" @@ -48,6 +48,7 @@ static int net_ads_gpo_refresh(int argc, const char **argv) ADS_STATUS status; const char *dn = NULL; struct GROUP_POLICY_OBJECT *gpo_list = NULL; + struct GROUP_POLICY_OBJECT *read_list = NULL; uint32 uac = 0; uint32 flags = 0; struct GROUP_POLICY_OBJECT *gpo; @@ -66,6 +67,7 @@ static int net_ads_gpo_refresh(int argc, const char **argv) status = ads_startup(False, &ads); if (!ADS_ERR_OK(status)) { + printf("failed to connect AD server: %s\n", ads_errstr(status)); goto out; } @@ -79,27 +81,61 @@ static int net_ads_gpo_refresh(int argc, const char **argv) flags |= GPO_LIST_FLAG_MACHINE; } - printf("\n%s: '%s' has dn: '%s'\n\n", - (uac & UF_WORKSTATION_TRUST_ACCOUNT) ? "machine" : "user", + printf("\n%s: '%s' has dn: '%s'\n\n", + (uac & UF_WORKSTATION_TRUST_ACCOUNT) ? "machine" : "user", argv[0], dn); - status = ads_get_sid_token(ads, mem_ctx, dn, &token); + printf("* fetching token "); + if (uac & UF_WORKSTATION_TRUST_ACCOUNT) { + status = gp_get_machine_token(ads, mem_ctx, dn, &token); + } else { + status = ads_get_sid_token(ads, mem_ctx, dn, &token); + } + if (!ADS_ERR_OK(status)) { + printf("failed: %s\n", ads_errstr(status)); goto out; } + printf("finished\n"); + printf("* fetching GPO List "); status = ads_get_gpo_list(ads, mem_ctx, dn, flags, token, &gpo_list); if (!ADS_ERR_OK(status)) { + printf("failed: %s\n", ads_errstr(status)); goto out; } + printf("finished\n"); - if (!NT_STATUS_IS_OK(result = check_refresh_gpo_list(ads, mem_ctx, flags, gpo_list))) { - printf("failed to refresh GPOs: %s\n", nt_errstr(result)); + printf("* refreshing Group Policy Data "); + if (!NT_STATUS_IS_OK(result = check_refresh_gpo_list(ads, mem_ctx, + flags, + gpo_list))) { + printf("failed: %s\n", nt_errstr(result)); goto out; } + printf("finished\n"); + + printf("* storing GPO list to registry "); - for (gpo = gpo_list; gpo; gpo = gpo->next) { + { + WERROR werr = gp_reg_state_store(mem_ctx, flags, dn, + token, gpo_list); + if (!W_ERROR_IS_OK(werr)) { + printf("failed: %s\n", dos_errstr(werr)); + goto out; + } + } + printf("finished\n"); + + if (opt_verbose) { + + printf("* dumping GPO list\n"); + + for (gpo = gpo_list; gpo; gpo = gpo->next) { + + dump_gpo(ads, mem_ctx, gpo, 0); +#if 0 char *server, *share, *nt_path, *unix_path; printf("--------------------------------------\n"); @@ -110,7 +146,8 @@ static int net_ads_gpo_refresh(int argc, const char **argv) GPO_VERSION_MACHINE(gpo->version)); result = gpo_explode_filesyspath(mem_ctx, gpo->file_sys_path, - &server, &share, &nt_path, &unix_path); + &server, &share, &nt_path, + &unix_path); if (!NT_STATUS_IS_OK(result)) { printf("got: %s\n", nt_errstr(result)); } @@ -118,6 +155,54 @@ static int net_ads_gpo_refresh(int argc, const char **argv) printf("GPO stored on server: %s, share: %s\n", server, share); printf("\tremote path:\t%s\n", nt_path); printf("\tlocal path:\t%s\n", unix_path); +#endif + } + } + + printf("* re-reading GPO list from registry "); + + { + WERROR werr = gp_reg_state_read(mem_ctx, flags, + &token->user_sids[0], + &read_list); + if (!W_ERROR_IS_OK(werr)) { + printf("failed: %s\n", dos_errstr(werr)); + goto out; + } + } + + printf("finished\n"); + + if (opt_verbose) { + + printf("* dumping GPO list from registry\n"); + + for (gpo = read_list; gpo; gpo = gpo->next) { + + dump_gpo(ads, mem_ctx, gpo, 0); + +#if 0 + char *server, *share, *nt_path, *unix_path; + + printf("--------------------------------------\n"); + printf("Name:\t\t\t%s\n", gpo->display_name); + printf("LDAP GPO version:\t%d (user: %d, machine: %d)\n", + gpo->version, + GPO_VERSION_USER(gpo->version), + GPO_VERSION_MACHINE(gpo->version)); + + result = gpo_explode_filesyspath(mem_ctx, gpo->file_sys_path, + &server, &share, &nt_path, + &unix_path); + if (!NT_STATUS_IS_OK(result)) { + printf("got: %s\n", nt_errstr(result)); + } + + printf("GPO stored on server: %s, share: %s\n", server, share); + printf("\tremote path:\t%s\n", nt_path); + printf("\tlocal path:\t%s\n", unix_path); +#endif + } } out: @@ -168,14 +253,16 @@ static int net_ads_gpo_list_all(int argc, const char **argv) if (!ADS_ERR_OK(status)) { d_printf("search failed: %s\n", ads_errstr(status)); goto out; - } + } num_reply = ads_count_replies(ads, res); - + d_printf("Got %d replies\n\n", num_reply); /* dump the results */ - for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { + for (msg = ads_first_entry(ads, res); + msg; + msg = ads_next_entry(ads, msg)) { if ((dn = ads_get_dn(ads, msg)) == NULL) { goto out; @@ -184,10 +271,11 @@ static int net_ads_gpo_list_all(int argc, const char **argv) status = ads_parse_gpo(ads, mem_ctx, msg, dn, &gpo); if (!ADS_ERR_OK(status)) { - d_printf("ads_parse_gpo failed: %s\n", ads_errstr(status)); + d_printf("ads_parse_gpo failed: %s\n", + ads_errstr(status)); ads_memfree(ads, dn); goto out; - } + } dump_gpo(ads, mem_ctx, &gpo, 0); ads_memfree(ads, dn); @@ -198,7 +286,7 @@ out: talloc_destroy(mem_ctx); ads_destroy(&ads); - + return 0; } @@ -238,11 +326,16 @@ static int net_ads_gpo_list(int argc, const char **argv) flags |= GPO_LIST_FLAG_MACHINE; } - printf("%s: '%s' has dn: '%s'\n", - (uac & UF_WORKSTATION_TRUST_ACCOUNT) ? "machine" : "user", + printf("%s: '%s' has dn: '%s'\n", + (uac & UF_WORKSTATION_TRUST_ACCOUNT) ? "machine" : "user", argv[0], dn); - status = ads_get_sid_token(ads, mem_ctx, dn, &token); + if (uac & UF_WORKSTATION_TRUST_ACCOUNT) { + status = gp_get_machine_token(ads, mem_ctx, dn, &token); + } else { + status = ads_get_sid_token(ads, mem_ctx, dn, &token); + } + if (!ADS_ERR_OK(status)) { goto out; } @@ -259,11 +352,11 @@ out: talloc_destroy(mem_ctx); ads_destroy(&ads); - + return 0; } -#if 0 /* not yet */ +#if 0 static int net_ads_gpo_apply(int argc, const char **argv) { TALLOC_CTX *mem_ctx; @@ -273,7 +366,9 @@ static int net_ads_gpo_apply(int argc, const char **argv) struct GROUP_POLICY_OBJECT *gpo_list; uint32 uac = 0; uint32 flags = 0; - + struct nt_user_token *token = NULL; + const char *filter = NULL; + if (argc < 1) { printf("usage: net ads gpo apply \n"); return -1; @@ -284,13 +379,20 @@ static int net_ads_gpo_apply(int argc, const char **argv) goto out; } + if (argc >= 2) { + filter = cse_gpo_name_to_guid_string(argv[1]); + } + status = ads_startup(False, &ads); if (!ADS_ERR_OK(status)) { + printf("got: %s\n", ads_errstr(status)); goto out; } status = ads_find_samaccount(ads, mem_ctx, argv[0], &uac, &dn); if (!ADS_ERR_OK(status)) { + printf("failed to find samaccount for %s: %s\n", + argv[0], ads_errstr(status)); goto out; } @@ -298,18 +400,34 @@ static int net_ads_gpo_apply(int argc, const char **argv) flags |= GPO_LIST_FLAG_MACHINE; } - printf("%s: '%s' has dn: '%s'\n", - (uac & UF_WORKSTATION_TRUST_ACCOUNT) ? "machine" : "user", + if (opt_verbose) { + flags |= GPO_INFO_FLAG_VERBOSE; + } + + printf("%s: '%s' has dn: '%s'\n", + (uac & UF_WORKSTATION_TRUST_ACCOUNT) ? "machine" : "user", argv[0], dn); - status = ads_get_gpo_list(ads, mem_ctx, dn, flags, &gpo_list); + if (uac & UF_WORKSTATION_TRUST_ACCOUNT) { + status = gp_get_machine_token(ads, mem_ctx, dn, &token); + } else { + status = ads_get_sid_token(ads, mem_ctx, dn, &token); + } + if (!ADS_ERR_OK(status)) { goto out; } - /* FIXME: allow to process just a single extension */ - status = gpo_process_gpo_list(ads, mem_ctx, gpo_list, NULL, flags); + status = ads_get_gpo_list(ads, mem_ctx, dn, flags, token, &gpo_list); + if (!ADS_ERR_OK(status)) { + goto out; + } + + status = gpo_process_gpo_list(ads, mem_ctx, token, gpo_list, + filter, flags); if (!ADS_ERR_OK(status)) { + d_printf("failed to process gpo list: %s\n", + ads_errstr(status)); goto out; } @@ -318,7 +436,6 @@ out: talloc_destroy(mem_ctx); return 0; } - #endif static int net_ads_gpo_link_get(int argc, const char **argv) @@ -345,9 +462,10 @@ static int net_ads_gpo_link_get(int argc, const char **argv) status = ads_get_gpo_link(ads, mem_ctx, argv[0], &gp_link); if (!ADS_ERR_OK(status)) { - d_printf("get link for %s failed: %s\n", argv[0], ads_errstr(status)); + d_printf("get link for %s failed: %s\n", argv[0], + ads_errstr(status)); goto out; - } + } dump_gplink(ads, mem_ctx, &gp_link); @@ -367,7 +485,8 @@ static int net_ads_gpo_link_add(int argc, const char **argv) if (argc < 2) { printf("usage: net ads gpo linkadd [options]\n"); - printf("note: DNs must be provided properly escaped.\n See RFC 4514 for details\n"); + printf("note: DNs must be provided properly escaped.\n"); + printf("See RFC 4514 for details\n"); return -1; } @@ -424,7 +543,7 @@ static int net_ads_gpo_link_delete(int argc, const char **argv) if (!ADS_ERR_OK(status)) { d_printf("delete link failed: %s\n", ads_errstr(status)); goto out; - } + } out: talloc_destroy(mem_ctx); @@ -464,9 +583,10 @@ static int net_ads_gpo_get_gpo(int argc, const char **argv) } if (!ADS_ERR_OK(status)) { - d_printf("get gpo for [%s] failed: %s\n", argv[0], ads_errstr(status)); + d_printf("get gpo for [%s] failed: %s\n", argv[0], + ads_errstr(status)); goto out; - } + } dump_gpo(ads, mem_ctx, &gpo, 1); -- cgit