root/source3/libgpo/gpext/scripts.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. scripts_get_reg_config
  2. generate_gp_registry_entry
  3. scripts_parse_ini_section
  4. scripts_store_reg_gpovals
  5. scripts_apply
  6. scripts_process_group_policy
  7. scripts_initialize
  8. scripts_shutdown
  9. gpext_scripts_init

   1 /*
   2  *  Unix SMB/CIFS implementation.
   3  *  Group Policy Support
   4  *  Copyright (C) Guenther Deschner 2007
   5  *
   6  *  This program is free software; you can redistribute it and/or modify
   7  *  it under the terms of the GNU General Public License as published by
   8  *  the Free Software Foundation; either version 3 of the License, or
   9  *  (at your option) any later version.
  10  *
  11  *  This program is distributed in the hope that it will be useful,
  12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14  *  GNU General Public License for more details.
  15  *
  16  *  You should have received a copy of the GNU General Public License
  17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  18  */
  19 
  20 #include "includes.h"
  21 #include "libgpo/gpo_ini.h"
  22 
  23 #define GP_EXT_NAME "scripts"
  24 
  25 #define KEY_GP_SCRIPTS "Software\\Policies\\Microsoft\\Windows\\System\\Scripts"
  26 
  27 #define GP_SCRIPTS_INI "Scripts/scripts.ini"
  28 
  29 #define GP_SCRIPTS_INI_STARTUP "Startup"
  30 #define GP_SCRIPTS_INI_SHUTDOWN "Shutdown"
  31 #define GP_SCRIPTS_INI_LOGON "Logon"
  32 #define GP_SCRIPTS_INI_LOGOFF "Logoff"
  33 
  34 #define GP_SCRIPTS_SECTION_CMDLINE "cmdline"
  35 #define GP_SCRIPTS_SECTION_PARAMETERS "parameters"
  36 
  37 #define GP_SCRIPTS_REG_VAL_SCRIPT "Script"
  38 #define GP_SCRIPTS_REG_VAL_PARAMETERS "Parameters"
  39 #define GP_SCRIPTS_REG_VAL_EXECTIME "ExecTime"
  40 
  41 static TALLOC_CTX *ctx = NULL;
  42 
  43 /****************************************************************
  44 ****************************************************************/
  45 
  46 static NTSTATUS scripts_get_reg_config(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  47                                        struct gp_extension_reg_info **reg_info)
  48 {
  49         NTSTATUS status;
  50         struct gp_extension_reg_info *info = NULL;
  51 
  52         struct gp_extension_reg_table table[] = {
  53                 { "ProcessGroupPolicy", REG_SZ, "scripts_process_group_policy" },
  54                 { "NoGPOListChanges", REG_DWORD, "1" },
  55                 { "NoSlowLink", REG_DWORD, "1" },
  56                 { "NotifyLinkTransition", REG_DWORD, "1" },
  57                 { NULL, REG_NONE, NULL },
  58         };
  59 
  60         info = TALLOC_ZERO_P(mem_ctx, struct gp_extension_reg_info);
  61         NT_STATUS_HAVE_NO_MEMORY(info);
  62 
  63         status = gp_ext_info_add_entry(mem_ctx, GP_EXT_NAME,
  64                                        GP_EXT_GUID_SCRIPTS,
  65                                        table, info);
  66         NT_STATUS_NOT_OK_RETURN(status);
  67 
  68         *reg_info = info;
  69 
  70         return NT_STATUS_OK;
  71 }
  72 
  73 /****************************************************************
  74 ****************************************************************/
  75 
  76 static NTSTATUS generate_gp_registry_entry(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  77                                            const char *key,
  78                                            const char *value,
  79                                            uint32_t data_type,
  80                                            const void *data_p,
  81                                            enum gp_reg_action action,
  82                                            struct gp_registry_entry **entry_out)
  83 {
  84         struct gp_registry_entry *entry = NULL;
  85         struct registry_value *data = NULL;
  86 
  87         entry = TALLOC_ZERO_P(mem_ctx, struct gp_registry_entry);
  88         NT_STATUS_HAVE_NO_MEMORY(entry);
  89 
  90         data = TALLOC_ZERO_P(mem_ctx, struct registry_value);
  91         NT_STATUS_HAVE_NO_MEMORY(data);
  92 
  93         data->type = data_type;
  94         switch (data->type) {
  95                 case REG_QWORD:
  96                         data->v.qword = *(uint64_t *)data_p;
  97                         break;
  98                 case REG_SZ:
  99                         data->v.sz.str = talloc_strdup(mem_ctx, (char *)data_p);
 100                         data->v.sz.len = strlen(data->v.sz.str);
 101                         break;
 102                 default:
 103                         return NT_STATUS_NOT_SUPPORTED;
 104         }
 105 
 106         entry->key = key;
 107         entry->data = data;
 108         entry->action = action;
 109         entry->value = talloc_strdup(mem_ctx, value);
 110         NT_STATUS_HAVE_NO_MEMORY(entry->value);
 111 
 112         *entry_out = entry;
 113 
 114         return NT_STATUS_OK;
 115 }
 116 
 117 /****************************************************************
 118 ****************************************************************/
 119 
 120 static NTSTATUS scripts_parse_ini_section(struct gp_inifile_context *ini_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 121                                           uint32_t flags,
 122                                           const char *section,
 123                                           struct gp_registry_entry **entries,
 124                                           size_t *num_entries)
 125 {
 126         NTSTATUS status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
 127         int i = 0;
 128 
 129         while (1) {
 130 
 131                 const char *key = NULL;
 132                 const char *script = NULL;
 133                 const char *count = NULL;
 134                 const char *parameters = NULL;
 135 
 136                 count = talloc_asprintf(ini_ctx->mem_ctx, "%d", i);
 137                 NT_STATUS_HAVE_NO_MEMORY(count);
 138 
 139                 key = talloc_asprintf(ini_ctx->mem_ctx, "%s:%s%s",
 140                                       section, count,
 141                                       GP_SCRIPTS_SECTION_CMDLINE);
 142                 NT_STATUS_HAVE_NO_MEMORY(key);
 143 
 144                 script = iniparser_getstring(ini_ctx->dict, key, NULL);
 145                 if (!script) {
 146                         break;
 147                 }
 148 
 149                 key = talloc_asprintf(ini_ctx->mem_ctx, "%s:%s%s",
 150                                       section, count,
 151                                       GP_SCRIPTS_SECTION_PARAMETERS);
 152                 NT_STATUS_HAVE_NO_MEMORY(key);
 153 
 154                 parameters = iniparser_getstring(ini_ctx->dict, key, NULL);
 155 
 156                 {
 157                         struct gp_registry_entry *entry = NULL;
 158                         status = generate_gp_registry_entry(ini_ctx->mem_ctx,
 159                                                             count,
 160                                                             GP_SCRIPTS_REG_VAL_SCRIPT,
 161                                                             REG_SZ,
 162                                                             script,
 163                                                             GP_REG_ACTION_ADD_VALUE,
 164                                                             &entry);
 165                         NT_STATUS_NOT_OK_RETURN(status);
 166                         if (!add_gp_registry_entry_to_array(ini_ctx->mem_ctx,
 167                                                             entry,
 168                                                             entries,
 169                                                             num_entries)) {
 170                                 return NT_STATUS_NO_MEMORY;
 171                         }
 172                 }
 173                 {
 174                         struct gp_registry_entry *entry = NULL;
 175                         status = generate_gp_registry_entry(ini_ctx->mem_ctx,
 176                                                             count,
 177                                                             GP_SCRIPTS_REG_VAL_PARAMETERS,
 178                                                             REG_SZ,
 179                                                             parameters,
 180                                                             GP_REG_ACTION_ADD_VALUE,
 181                                                             &entry);
 182                         NT_STATUS_NOT_OK_RETURN(status);
 183                         if (!add_gp_registry_entry_to_array(ini_ctx->mem_ctx,
 184                                                             entry,
 185                                                             entries,
 186                                                             num_entries)) {
 187                                 return NT_STATUS_NO_MEMORY;
 188                         }
 189                 }
 190                 {
 191                         struct gp_registry_entry *entry = NULL;
 192                         status = generate_gp_registry_entry(ini_ctx->mem_ctx,
 193                                                             count,
 194                                                             GP_SCRIPTS_REG_VAL_EXECTIME,
 195                                                             REG_QWORD,
 196                                                             0,
 197                                                             GP_REG_ACTION_ADD_VALUE,
 198                                                             &entry);
 199                         NT_STATUS_NOT_OK_RETURN(status);
 200                         if (!add_gp_registry_entry_to_array(ini_ctx->mem_ctx,
 201                                                             entry,
 202                                                             entries,
 203                                                             num_entries)) {
 204                                 return NT_STATUS_NO_MEMORY;
 205                         }
 206                 }
 207                 status = NT_STATUS_OK;
 208                 i++;
 209         }
 210 
 211         return status;
 212 }
 213 
 214 /****************************************************************
 215 ****************************************************************/
 216 
 217 static WERROR scripts_store_reg_gpovals(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 218                                         struct registry_key *key,
 219                                         struct GROUP_POLICY_OBJECT *gpo)
 220 {
 221         WERROR werr;
 222 
 223         if (!key || !gpo) {
 224                 return WERR_INVALID_PARAM;
 225         }
 226 
 227         werr = gp_store_reg_val_sz(mem_ctx, key, "DisplayName",
 228                 gpo->display_name);
 229         W_ERROR_NOT_OK_RETURN(werr);
 230 
 231         werr = gp_store_reg_val_sz(mem_ctx, key, "FileSysPath",
 232                 gpo->file_sys_path);
 233         W_ERROR_NOT_OK_RETURN(werr);
 234 
 235         werr = gp_store_reg_val_sz(mem_ctx, key, "GPO-ID",
 236                 gpo->ds_path);
 237         W_ERROR_NOT_OK_RETURN(werr);
 238 
 239         werr = gp_store_reg_val_sz(mem_ctx, key, "GPOName",
 240                 gpo->name);
 241         W_ERROR_NOT_OK_RETURN(werr);
 242 
 243         werr = gp_store_reg_val_sz(mem_ctx, key, "SOM-ID",
 244                 gpo->link);
 245         W_ERROR_NOT_OK_RETURN(werr);
 246 
 247         return werr;
 248 }
 249 
 250 /****************************************************************
 251 ****************************************************************/
 252 
 253 static WERROR scripts_apply(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 254                             const struct nt_user_token *token,
 255                             struct registry_key *root_key,
 256                             uint32_t flags,
 257                             const char *section,
 258                             struct GROUP_POLICY_OBJECT *gpo,
 259                             struct gp_registry_entry *entries,
 260                             size_t num_entries)
 261 {
 262         struct gp_registry_context *reg_ctx = NULL;
 263         WERROR werr;
 264         size_t i;
 265         const char *keystr = NULL;
 266         int count = 0;
 267 
 268         if (num_entries == 0) {
 269                 return WERR_OK;
 270         }
 271 
 272 #if 0
 273         if (flags & GPO_INFO_FLAG_MACHINE) {
 274                 struct nt_user_token *tmp_token;
 275 
 276                 tmp_token = registry_create_system_token(mem_ctx);
 277                 W_ERROR_HAVE_NO_MEMORY(tmp_token);
 278 
 279                 werr = gp_init_reg_ctx(mem_ctx, KEY_HKLM, REG_KEY_WRITE,
 280                                        tmp_token,
 281                                        &reg_ctx);
 282         } else {
 283                 werr = gp_init_reg_ctx(mem_ctx, KEY_HKCU, REG_KEY_WRITE,
 284                                        token,
 285                                        &reg_ctx);
 286         }
 287         W_ERROR_NOT_OK_RETURN(werr);
 288 #endif
 289 
 290         keystr = talloc_asprintf(mem_ctx, "%s\\%s\\%d", KEY_GP_SCRIPTS,
 291                                  section, count++);
 292         W_ERROR_HAVE_NO_MEMORY(keystr);
 293 
 294         reg_deletekey_recursive(mem_ctx, root_key, keystr);
 295 
 296         werr = gp_store_reg_subkey(mem_ctx, keystr,
 297                                    root_key, &root_key);
 298         if (!W_ERROR_IS_OK(werr)) {
 299                 goto done;
 300         }
 301 
 302         werr = scripts_store_reg_gpovals(mem_ctx, root_key, gpo);
 303         if (!W_ERROR_IS_OK(werr)) {
 304                 goto done;
 305         }
 306 
 307         for (i=0; i<num_entries; i++) {
 308 
 309                 werr = reg_apply_registry_entry(mem_ctx, root_key, reg_ctx,
 310                                                 &(entries)[i],
 311                                                 token, flags);
 312                 if (!W_ERROR_IS_OK(werr)) {
 313                         DEBUG(0,("failed to apply registry: %s\n",
 314                                 win_errstr(werr)));
 315                         goto done;
 316                 }
 317         }
 318 
 319  done:
 320         gp_free_reg_ctx(reg_ctx);
 321         return werr;
 322 }
 323 
 324 /****************************************************************
 325 ****************************************************************/
 326 
 327 static NTSTATUS scripts_process_group_policy(ADS_STRUCT *ads,
     /* [<][>][^][v][top][bottom][index][help] */
 328                                              TALLOC_CTX *mem_ctx,
 329                                              uint32_t flags,
 330                                              struct registry_key *root_key,
 331                                              const struct nt_user_token *token,
 332                                              struct GROUP_POLICY_OBJECT *gpo,
 333                                              const char *extension_guid,
 334                                              const char *snapin_guid)
 335 {
 336         NTSTATUS status;
 337         WERROR werr;
 338         int i = 0;
 339         char *unix_path = NULL;
 340         struct gp_inifile_context *ini_ctx = NULL;
 341         struct gp_registry_entry *entries = NULL;
 342         size_t num_entries = 0;
 343         const char *list[] = {
 344                 GP_SCRIPTS_INI_STARTUP,
 345                 GP_SCRIPTS_INI_SHUTDOWN,
 346                 GP_SCRIPTS_INI_LOGON,
 347                 GP_SCRIPTS_INI_LOGOFF
 348         };
 349 
 350         debug_gpext_header(0, "scripts_process_group_policy", flags, gpo,
 351                            extension_guid, snapin_guid);
 352 
 353         status = gpo_get_unix_path(mem_ctx, gpo, &unix_path);
 354         NT_STATUS_NOT_OK_RETURN(status);
 355 
 356         status = gp_inifile_init_context(mem_ctx, flags, unix_path,
 357                                          GP_SCRIPTS_INI, &ini_ctx);
 358         NT_STATUS_NOT_OK_RETURN(status);
 359 
 360         for (i = 0; i < ARRAY_SIZE(list); i++) {
 361 
 362                 TALLOC_FREE(entries);
 363                 num_entries = 0;
 364 
 365                 status = scripts_parse_ini_section(ini_ctx, flags, list[i],
 366                                                    &entries, &num_entries);
 367                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
 368                         continue;
 369                 }
 370 
 371                 if (!NT_STATUS_IS_OK(status)) {
 372                         return status;
 373                 }
 374 
 375                 dump_reg_entries(flags, "READ", entries, num_entries);
 376 
 377                 werr = scripts_apply(ini_ctx->mem_ctx, token, root_key,
 378                                      flags, list[i], gpo, entries, num_entries);
 379                 if (!W_ERROR_IS_OK(werr)) {
 380                         continue; /* FIXME: finally fix storing emtpy strings and REG_QWORD! */
 381                         TALLOC_FREE(ini_ctx);
 382                         return werror_to_ntstatus(werr);
 383                 }
 384         }
 385 
 386         TALLOC_FREE(ini_ctx);
 387         return NT_STATUS_OK;
 388 }
 389 
 390 /****************************************************************
 391 ****************************************************************/
 392 
 393 static NTSTATUS scripts_initialize(TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 394 {
 395         return NT_STATUS_OK;
 396 }
 397 
 398 /****************************************************************
 399 ****************************************************************/
 400 
 401 static NTSTATUS scripts_shutdown(void)
     /* [<][>][^][v][top][bottom][index][help] */
 402 {
 403         NTSTATUS status;
 404 
 405         status = unregister_gp_extension(GP_EXT_NAME);
 406         if (NT_STATUS_IS_OK(status)) {
 407                 return status;
 408         }
 409 
 410         TALLOC_FREE(ctx);
 411 
 412         return NT_STATUS_OK;
 413 }
 414 
 415 /****************************************************************
 416 ****************************************************************/
 417 
 418 static struct gp_extension_methods scripts_methods = {
 419         .initialize             = scripts_initialize,
 420         .process_group_policy   = scripts_process_group_policy,
 421         .get_reg_config         = scripts_get_reg_config,
 422         .shutdown               = scripts_shutdown
 423 };
 424 
 425 /****************************************************************
 426 ****************************************************************/
 427 
 428 NTSTATUS gpext_scripts_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 429 {
 430         NTSTATUS status;
 431 
 432         ctx = talloc_init("gpext_scripts_init");
 433         NT_STATUS_HAVE_NO_MEMORY(ctx);
 434 
 435         status = register_gp_extension(ctx, SMB_GPEXT_INTERFACE_VERSION,
 436                                        GP_EXT_NAME, GP_EXT_GUID_SCRIPTS,
 437                                        &scripts_methods);
 438         if (!NT_STATUS_IS_OK(status)) {
 439                 TALLOC_FREE(ctx);
 440         }
 441 
 442         return status;
 443 }

/* [<][>][^][v][top][bottom][index][help] */