root/source3/libgpo/gpext/registry.c

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

DEFINITIONS

This source file includes following definitions.
  1. reg_parse_header
  2. reg_parse_and_verify_ucs2_char
  3. reg_parse_init
  4. reg_parse_sep
  5. reg_parse_term
  6. reg_parse_entry
  7. reg_parse_value
  8. gp_reg_entry_from_file_entry
  9. reg_parse_entries
  10. reg_parse_registry
  11. reg_apply_registry
  12. registry_process_group_policy
  13. registry_get_reg_config
  14. registry_initialize
  15. registry_shutdown
  16. gpext_registry_init

   1 /*
   2  *  Unix SMB/CIFS implementation.
   3  *  Group Policy Support
   4  *  Copyright (C) Guenther Deschner 2007-2008
   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 
  22 #define GP_EXT_NAME "registry"
  23 
  24 /* more info can be found at:
  25  * http://msdn2.microsoft.com/en-us/library/aa374407.aspx */
  26 
  27 #define GP_REGPOL_FILE  "Registry.pol"
  28 
  29 #define GP_REGPOL_FILE_SIGNATURE 0x67655250 /* 'PReg' */
  30 #define GP_REGPOL_FILE_VERSION 1
  31 
  32 static TALLOC_CTX *ctx = NULL;
  33 
  34 struct gp_registry_file_header {
  35         uint32_t signature;
  36         uint32_t version;
  37 };
  38 
  39 struct gp_registry_file_entry {
  40         UNISTR key;
  41         UNISTR value;
  42         enum winreg_Type type;
  43         size_t size;
  44         uint8_t *data;
  45 };
  46 
  47 struct gp_registry_file {
  48         struct gp_registry_file_header header;
  49         size_t num_entries;
  50         struct gp_registry_entry *entries;
  51 };
  52 
  53 /****************************************************************
  54 ****************************************************************/
  55 
  56 static bool reg_parse_header(const char *desc,
     /* [<][>][^][v][top][bottom][index][help] */
  57                              struct gp_registry_file_header *header,
  58                              prs_struct *ps,
  59                              int depth)
  60 {
  61         if (!header)
  62                 return false;
  63 
  64         prs_debug(ps, depth, desc, "reg_parse_header");
  65         depth++;
  66 
  67         if (!prs_uint32("signature", ps, depth, &header->signature))
  68                 return false;
  69 
  70         if (!prs_uint32("version", ps, depth, &header->version))
  71                 return false;
  72 
  73         return true;
  74 }
  75 
  76 /****************************************************************
  77 ****************************************************************/
  78 
  79 static bool reg_parse_and_verify_ucs2_char(const char *desc,
     /* [<][>][^][v][top][bottom][index][help] */
  80                                            char character,
  81                                            prs_struct *ps,
  82                                            int depth)
  83 {
  84         uint16_t tmp;
  85 
  86         if (!prs_uint16(desc, ps, depth, &tmp))
  87                 return false;
  88 
  89         if (tmp != UCS2_CHAR(character))
  90                 return false;
  91 
  92         return true;
  93 }
  94 
  95 /****************************************************************
  96 ****************************************************************/
  97 
  98 static bool reg_parse_init(prs_struct *ps, int depth)
     /* [<][>][^][v][top][bottom][index][help] */
  99 {
 100         return reg_parse_and_verify_ucs2_char("initiator '['", '[',
 101                                               ps, depth);
 102 }
 103 
 104 /****************************************************************
 105 ****************************************************************/
 106 
 107 static bool reg_parse_sep(prs_struct *ps, int depth)
     /* [<][>][^][v][top][bottom][index][help] */
 108 {
 109         return reg_parse_and_verify_ucs2_char("separator ';'", ';',
 110                                               ps, depth);
 111 }
 112 
 113 /****************************************************************
 114 ****************************************************************/
 115 
 116 static bool reg_parse_term(prs_struct *ps, int depth)
     /* [<][>][^][v][top][bottom][index][help] */
 117 {
 118         return reg_parse_and_verify_ucs2_char("terminator ']'", ']',
 119                                               ps, depth);
 120 }
 121 
 122 
 123 /****************************************************************
 124 * [key;value;type;size;data]
 125 ****************************************************************/
 126 
 127 static bool reg_parse_entry(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 128                             const char *desc,
 129                             struct gp_registry_file_entry *entry,
 130                             prs_struct *ps,
 131                             int depth)
 132 {
 133         uint32_t size = 0;
 134 
 135         if (!entry)
 136                 return false;
 137 
 138         prs_debug(ps, depth, desc, "reg_parse_entry");
 139         depth++;
 140 
 141         ZERO_STRUCTP(entry);
 142 
 143         if (!reg_parse_init(ps, depth))
 144                 return false;
 145 
 146         if (!prs_unistr("key", ps, depth, &entry->key))
 147                 return false;
 148 
 149         if (!reg_parse_sep(ps, depth))
 150                 return false;
 151 
 152         if (!prs_unistr("value", ps, depth, &entry->value))
 153                 return false;
 154 
 155         if (!reg_parse_sep(ps, depth))
 156                 return false;
 157 
 158         if (!prs_uint32("type", ps, depth, &entry->type))
 159                 return false;
 160 
 161         if (!reg_parse_sep(ps, depth))
 162                 return false;
 163 
 164         if (!prs_uint32("size", ps, depth, &size))
 165                 return false;
 166 
 167         entry->size = size;
 168 
 169         if (!reg_parse_sep(ps, depth))
 170                 return false;
 171 
 172         if (entry->size) {
 173                 entry->data = TALLOC_ZERO_ARRAY(mem_ctx, uint8, entry->size);
 174                 if (!entry->data)
 175                         return false;
 176         }
 177 
 178         if (!prs_uint8s(false, "data", ps, depth, entry->data, entry->size))
 179                 return false;
 180 
 181         if (!reg_parse_term(ps, depth))
 182                 return false;
 183 
 184         return true;
 185 }
 186 
 187 /****************************************************************
 188 ****************************************************************/
 189 
 190 static bool reg_parse_value(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 191                             char **value,
 192                             enum gp_reg_action *action)
 193 {
 194         if (!*value) {
 195                 *action = GP_REG_ACTION_ADD_KEY;
 196                 return true;
 197         }
 198 
 199         if (strncmp(*value, "**", 2) != 0) {
 200                 *action = GP_REG_ACTION_ADD_VALUE;
 201                 return true;
 202         }
 203 
 204         if (strnequal(*value, "**DelVals.", 10)) {
 205                 *action = GP_REG_ACTION_DEL_ALL_VALUES;
 206                 return true;
 207         }
 208 
 209         if (strnequal(*value, "**Del.", 6)) {
 210                 *value = talloc_strdup(mem_ctx, *value + 6);
 211                 *action = GP_REG_ACTION_DEL_VALUE;
 212                 return true;
 213         }
 214 
 215         if (strnequal(*value, "**SecureKey", 11)) {
 216                 if (strnequal(*value, "**SecureKey=1", 13)) {
 217                         *action = GP_REG_ACTION_SEC_KEY_SET;
 218                         return true;
 219                 }
 220 
 221  /*************** not tested from here on ***************/
 222                 if (strnequal(*value, "**SecureKey=0", 13)) {
 223                         smb_panic("not supported: **SecureKey=0");
 224                         *action = GP_REG_ACTION_SEC_KEY_RESET;
 225                         return true;
 226                 }
 227                 DEBUG(0,("unknown: SecureKey: %s\n", *value));
 228                 smb_panic("not supported SecureKey method");
 229                 return false;
 230         }
 231 
 232         if (strnequal(*value, "**DeleteValues", strlen("**DeleteValues"))) {
 233                 smb_panic("not supported: **DeleteValues");
 234                 *action = GP_REG_ACTION_DEL_VALUES;
 235                 return false;
 236         }
 237 
 238         if (strnequal(*value, "**DeleteKeys", strlen("**DeleteKeys"))) {
 239                 smb_panic("not supported: **DeleteKeys");
 240                 *action = GP_REG_ACTION_DEL_KEYS;
 241                 return false;
 242         }
 243 
 244         DEBUG(0,("unknown value: %s\n", *value));
 245         smb_panic(*value);
 246         return false;
 247 }
 248 
 249 /****************************************************************
 250 ****************************************************************/
 251 
 252 static bool gp_reg_entry_from_file_entry(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 253                                          struct gp_registry_file_entry *file_entry,
 254                                          struct gp_registry_entry **reg_entry)
 255 {
 256         struct registry_value *data = NULL;
 257         struct gp_registry_entry *entry = NULL;
 258         char *key = NULL;
 259         char *value = NULL;
 260         enum gp_reg_action action = GP_REG_ACTION_NONE;
 261         size_t converted_size;
 262 
 263         ZERO_STRUCTP(*reg_entry);
 264 
 265         data = TALLOC_ZERO_P(mem_ctx, struct registry_value);
 266         if (!data)
 267                 return false;
 268 
 269         if (strlen_w((const smb_ucs2_t *)file_entry->key.buffer) <= 0)
 270                 return false;
 271 
 272         if (!pull_ucs2_talloc(mem_ctx, &key, file_entry->key.buffer,
 273                               &converted_size))
 274         {
 275                 return false;
 276         }
 277 
 278         if (strlen_w((const smb_ucs2_t *)file_entry->value.buffer) > 0 &&
 279             !pull_ucs2_talloc(mem_ctx, &value, file_entry->value.buffer,
 280                               &converted_size))
 281         {
 282                         return false;
 283         }
 284 
 285         if (!reg_parse_value(mem_ctx, &value, &action))
 286                 return false;
 287 
 288         data->type = file_entry->type;
 289 
 290         switch (data->type) {
 291                 case REG_DWORD:
 292                         data->v.dword = atoi((char *)file_entry->data);
 293                         break;
 294                 case REG_BINARY:
 295                         data->v.binary = data_blob_talloc(mem_ctx,
 296                                                           file_entry->data,
 297                                                           file_entry->size);
 298                         break;
 299                 case REG_NONE:
 300                         break;
 301                 case REG_SZ:
 302                         if (!pull_ucs2_talloc(mem_ctx, &data->v.sz.str,
 303                                               (const smb_ucs2_t *)
 304                                               file_entry->data,
 305                                               &data->v.sz.len)) {
 306                                 data->v.sz.len = -1;
 307                         }
 308 
 309                         break;
 310                 case REG_DWORD_BIG_ENDIAN:
 311                 case REG_EXPAND_SZ:
 312                 case REG_LINK:
 313                 case REG_MULTI_SZ:
 314                 case REG_QWORD:
 315 /*              case REG_DWORD_LITTLE_ENDIAN: */
 316 /*              case REG_QWORD_LITTLE_ENDIAN: */
 317                         printf("not yet implemented: %d\n", data->type);
 318                         return false;
 319                 default:
 320                         printf("invalid reg type defined: %d\n", data->type);
 321                         return false;
 322 
 323         }
 324 
 325         entry = TALLOC_ZERO_P(mem_ctx, struct gp_registry_entry);
 326         if (!entry)
 327                 return false;
 328 
 329         entry->key = key;
 330         entry->value = value;
 331         entry->data = data;
 332         entry->action = action;
 333 
 334         *reg_entry = entry;
 335 
 336         return true;
 337 }
 338 
 339 /****************************************************************
 340 * [key;value;type;size;data][key;value;type;size;data]...
 341 ****************************************************************/
 342 
 343 static bool reg_parse_entries(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 344                               const char *desc,
 345                               struct gp_registry_entry **entries,
 346                               size_t *num_entries,
 347                               prs_struct *ps,
 348                               int depth)
 349 {
 350 
 351         if (!entries || !num_entries)
 352                 return false;
 353 
 354         prs_debug(ps, depth, desc, "reg_parse_entries");
 355         depth++;
 356 
 357         *entries = NULL;
 358         *num_entries = 0;
 359 
 360         while (ps->buffer_size > ps->data_offset) {
 361 
 362                 struct gp_registry_file_entry f_entry;
 363                 struct gp_registry_entry *r_entry = NULL;
 364 
 365                 if (!reg_parse_entry(mem_ctx, desc, &f_entry,
 366                                      ps, depth))
 367                         return false;
 368 
 369                 if (!gp_reg_entry_from_file_entry(mem_ctx,
 370                                                   &f_entry,
 371                                                   &r_entry))
 372                         return false;
 373 
 374                 if (!add_gp_registry_entry_to_array(mem_ctx,
 375                                                     r_entry,
 376                                                     entries,
 377                                                     num_entries))
 378                         return false;
 379         }
 380 
 381         return true;
 382 }
 383 
 384 /****************************************************************
 385 ****************************************************************/
 386 
 387 static NTSTATUS reg_parse_registry(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 388                                    uint32_t flags,
 389                                    const char *filename,
 390                                    struct gp_registry_entry **entries,
 391                                    size_t *num_entries)
 392 {
 393         uint16_t *buf = NULL;
 394         size_t n = 0;
 395         NTSTATUS status;
 396         prs_struct ps;
 397         struct gp_registry_file *reg_file;
 398         const char *real_filename = NULL;
 399 
 400         reg_file = TALLOC_ZERO_P(mem_ctx, struct gp_registry_file);
 401         NT_STATUS_HAVE_NO_MEMORY(reg_file);
 402 
 403         status = gp_find_file(mem_ctx,
 404                               flags,
 405                               filename,
 406                               GP_REGPOL_FILE,
 407                               &real_filename);
 408         if (!NT_STATUS_IS_OK(status)) {
 409                 TALLOC_FREE(reg_file);
 410                 return status;
 411         }
 412 
 413         buf = (uint16 *)file_load(real_filename, &n, 0, NULL);
 414         if (!buf) {
 415                 TALLOC_FREE(reg_file);
 416                 return NT_STATUS_CANNOT_LOAD_REGISTRY_FILE;
 417         }
 418 
 419         if (!prs_init(&ps, n, mem_ctx, UNMARSHALL)) {
 420                 status = NT_STATUS_NO_MEMORY;
 421                 goto out;
 422         }
 423 
 424         if (!prs_copy_data_in(&ps, (char *)buf, n)) {
 425                 status = NT_STATUS_NO_MEMORY;
 426                 goto out;
 427         }
 428 
 429         prs_set_offset(&ps, 0);
 430 
 431         if (!reg_parse_header("header", &reg_file->header, &ps, 0)) {
 432                 status = NT_STATUS_REGISTRY_IO_FAILED;
 433                 goto out;
 434         }
 435 
 436         if (reg_file->header.signature != GP_REGPOL_FILE_SIGNATURE) {
 437                 status = NT_STATUS_INVALID_PARAMETER;
 438                 goto out;
 439         }
 440 
 441         if (reg_file->header.version != GP_REGPOL_FILE_VERSION) {
 442                 status = NT_STATUS_INVALID_PARAMETER;
 443                 goto out;
 444         }
 445 
 446         if (!reg_parse_entries(mem_ctx, "entries", &reg_file->entries,
 447                                &reg_file->num_entries, &ps, 0)) {
 448                 status = NT_STATUS_REGISTRY_IO_FAILED;
 449                 goto out;
 450         }
 451 
 452         *entries = reg_file->entries;
 453         *num_entries = reg_file->num_entries;
 454 
 455         status = NT_STATUS_OK;
 456 
 457  out:
 458         TALLOC_FREE(buf);
 459         prs_mem_free(&ps);
 460 
 461         return status;
 462 }
 463 
 464 /****************************************************************
 465 ****************************************************************/
 466 
 467 static WERROR reg_apply_registry(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 468                                  const struct nt_user_token *token,
 469                                  struct registry_key *root_key,
 470                                  uint32_t flags,
 471                                  struct gp_registry_entry *entries,
 472                                  size_t num_entries)
 473 {
 474         struct gp_registry_context *reg_ctx = NULL;
 475         WERROR werr;
 476         size_t i;
 477 
 478         if (num_entries == 0) {
 479                 return WERR_OK;
 480         }
 481 
 482 #if 0
 483         if (flags & GPO_LIST_FLAG_MACHINE) {
 484                 werr = gp_init_reg_ctx(mem_ctx, KEY_HKLM, REG_KEY_WRITE,
 485                                        get_system_token(),
 486                                        &reg_ctx);
 487         } else {
 488                 werr = gp_init_reg_ctx(mem_ctx, KEY_HKCU, REG_KEY_WRITE,
 489                                        token,
 490                                        &reg_ctx);
 491         }
 492         W_ERROR_NOT_OK_RETURN(werr);
 493 #endif
 494         for (i=0; i<num_entries; i++) {
 495 
 496                 /* FIXME: maybe we should check here if we attempt to go beyond
 497                  * the 4 allowed reg keys */
 498 
 499                 werr = reg_apply_registry_entry(mem_ctx, root_key,
 500                                                 reg_ctx,
 501                                                 &(entries)[i],
 502                                                 token, flags);
 503                 if (!W_ERROR_IS_OK(werr)) {
 504                         DEBUG(0,("failed to apply registry: %s\n",
 505                                 win_errstr(werr)));
 506                         goto done;
 507                 }
 508         }
 509 
 510 done:
 511         gp_free_reg_ctx(reg_ctx);
 512         return werr;
 513 }
 514 
 515 
 516 /****************************************************************
 517 ****************************************************************/
 518 
 519 static NTSTATUS registry_process_group_policy(ADS_STRUCT *ads,
     /* [<][>][^][v][top][bottom][index][help] */
 520                                               TALLOC_CTX *mem_ctx,
 521                                               uint32_t flags,
 522                                               struct registry_key *root_key,
 523                                               const struct nt_user_token *token,
 524                                               struct GROUP_POLICY_OBJECT *gpo,
 525                                               const char *extension_guid,
 526                                               const char *snapin_guid)
 527 {
 528         NTSTATUS status;
 529         WERROR werr;
 530         struct gp_registry_entry *entries = NULL;
 531         size_t num_entries = 0;
 532         char *unix_path = NULL;
 533 
 534         debug_gpext_header(0, "registry_process_group_policy", flags, gpo,
 535                            extension_guid, snapin_guid);
 536 
 537         status = gpo_get_unix_path(mem_ctx, gpo, &unix_path);
 538         NT_STATUS_NOT_OK_RETURN(status);
 539 
 540         status = reg_parse_registry(mem_ctx,
 541                                     flags,
 542                                     unix_path,
 543                                     &entries,
 544                                     &num_entries);
 545         if (!NT_STATUS_IS_OK(status)) {
 546                 DEBUG(0,("failed to parse registry: %s\n",
 547                         nt_errstr(status)));
 548                 return status;
 549         }
 550 
 551         dump_reg_entries(flags, "READ", entries, num_entries);
 552 
 553         werr = reg_apply_registry(mem_ctx, token, root_key, flags,
 554                                   entries, num_entries);
 555         if (!W_ERROR_IS_OK(werr)) {
 556                 DEBUG(0,("failed to apply registry: %s\n",
 557                         win_errstr(werr)));
 558                 return werror_to_ntstatus(werr);
 559         }
 560 
 561         return NT_STATUS_OK;
 562 }
 563 
 564 /****************************************************************
 565 ****************************************************************/
 566 
 567 static NTSTATUS registry_get_reg_config(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 568                                         struct gp_extension_reg_info **reg_info)
 569 {
 570         NTSTATUS status;
 571         struct gp_extension_reg_info *info = NULL;
 572         struct gp_extension_reg_table table[] = {
 573                 { "ProcessGroupPolicy", REG_SZ, "registry_process_group_policy" },
 574                 { NULL, REG_NONE, NULL }
 575         };
 576 
 577         info = TALLOC_ZERO_P(mem_ctx, struct gp_extension_reg_info);
 578         NT_STATUS_HAVE_NO_MEMORY(info);
 579 
 580         status = gp_ext_info_add_entry(mem_ctx, GP_EXT_NAME,
 581                                        GP_EXT_GUID_REGISTRY,
 582                                        table, info);
 583         NT_STATUS_NOT_OK_RETURN(status);
 584 
 585         *reg_info = info;
 586 
 587         return NT_STATUS_OK;
 588 }
 589 
 590 /****************************************************************
 591 ****************************************************************/
 592 
 593 static NTSTATUS registry_initialize(TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 594 {
 595         return NT_STATUS_OK;
 596 }
 597 
 598 /****************************************************************
 599 ****************************************************************/
 600 
 601 static NTSTATUS registry_shutdown(void)
     /* [<][>][^][v][top][bottom][index][help] */
 602 {
 603         NTSTATUS status;
 604 
 605         status = unregister_gp_extension(GP_EXT_NAME);
 606         if (NT_STATUS_IS_OK(status)) {
 607                 return status;
 608         }
 609 
 610         TALLOC_FREE(ctx);
 611 
 612         return NT_STATUS_OK;
 613 }
 614 
 615 /****************************************************************
 616 ****************************************************************/
 617 
 618 static struct gp_extension_methods registry_methods = {
 619         .initialize             = registry_initialize,
 620         .process_group_policy   = registry_process_group_policy,
 621         .get_reg_config         = registry_get_reg_config,
 622         .shutdown               = registry_shutdown
 623 };
 624 
 625 /****************************************************************
 626 ****************************************************************/
 627 
 628 NTSTATUS gpext_registry_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 629 {
 630         NTSTATUS status;
 631 
 632         ctx = talloc_init("gpext_registry_init");
 633         NT_STATUS_HAVE_NO_MEMORY(ctx);
 634 
 635         status = register_gp_extension(ctx, SMB_GPEXT_INTERFACE_VERSION,
 636                                        GP_EXT_NAME, GP_EXT_GUID_REGISTRY,
 637                                        &registry_methods);
 638         if (!NT_STATUS_IS_OK(status)) {
 639                 TALLOC_FREE(ctx);
 640         }
 641 
 642         return status;
 643 }

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