2
* Unix SMB/CIFS implementation.
4
* Copyright (C) Guenther Deschner 2007-2008
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.
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.
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/>.
22
#define GP_EXT_NAME "registry"
24
/* more info can be found at:
25
* http://msdn2.microsoft.com/en-us/library/aa374407.aspx */
27
#define GP_REGPOL_FILE "Registry.pol"
29
#define GP_REGPOL_FILE_SIGNATURE 0x67655250 /* 'PReg' */
30
#define GP_REGPOL_FILE_VERSION 1
32
static TALLOC_CTX *ctx = NULL;
34
struct gp_registry_file_header {
39
struct gp_registry_file_entry {
42
enum winreg_Type type;
47
struct gp_registry_file {
48
struct gp_registry_file_header header;
50
struct gp_registry_entry *entries;
53
/****************************************************************
54
****************************************************************/
56
static bool reg_parse_header(const char *desc,
57
struct gp_registry_file_header *header,
64
prs_debug(ps, depth, desc, "reg_parse_header");
67
if (!prs_uint32("signature", ps, depth, &header->signature))
70
if (!prs_uint32("version", ps, depth, &header->version))
76
/****************************************************************
77
****************************************************************/
79
static bool reg_parse_and_verify_ucs2_char(const char *desc,
86
if (!prs_uint16(desc, ps, depth, &tmp))
89
if (tmp != UCS2_CHAR(character))
95
/****************************************************************
96
****************************************************************/
98
static bool reg_parse_init(prs_struct *ps, int depth)
100
return reg_parse_and_verify_ucs2_char("initiator '['", '[',
104
/****************************************************************
105
****************************************************************/
107
static bool reg_parse_sep(prs_struct *ps, int depth)
109
return reg_parse_and_verify_ucs2_char("separator ';'", ';',
113
/****************************************************************
114
****************************************************************/
116
static bool reg_parse_term(prs_struct *ps, int depth)
118
return reg_parse_and_verify_ucs2_char("terminator ']'", ']',
123
/****************************************************************
124
* [key;value;type;size;data]
125
****************************************************************/
127
static bool reg_parse_entry(TALLOC_CTX *mem_ctx,
129
struct gp_registry_file_entry *entry,
138
prs_debug(ps, depth, desc, "reg_parse_entry");
143
if (!reg_parse_init(ps, depth))
146
if (!prs_unistr("key", ps, depth, &entry->key))
149
if (!reg_parse_sep(ps, depth))
152
if (!prs_unistr("value", ps, depth, &entry->value))
155
if (!reg_parse_sep(ps, depth))
158
if (!prs_uint32("type", ps, depth, &entry->type))
161
if (!reg_parse_sep(ps, depth))
164
if (!prs_uint32("size", ps, depth, &size))
169
if (!reg_parse_sep(ps, depth))
173
entry->data = TALLOC_ZERO_ARRAY(mem_ctx, uint8, entry->size);
178
if (!prs_uint8s(false, "data", ps, depth, entry->data, entry->size))
181
if (!reg_parse_term(ps, depth))
187
/****************************************************************
188
****************************************************************/
190
static bool reg_parse_value(TALLOC_CTX *mem_ctx,
192
enum gp_reg_action *action)
195
*action = GP_REG_ACTION_ADD_KEY;
199
if (strncmp(*value, "**", 2) != 0) {
200
*action = GP_REG_ACTION_ADD_VALUE;
204
if (strnequal(*value, "**DelVals.", 10)) {
205
*action = GP_REG_ACTION_DEL_ALL_VALUES;
209
if (strnequal(*value, "**Del.", 6)) {
210
*value = talloc_strdup(mem_ctx, *value + 6);
211
*action = GP_REG_ACTION_DEL_VALUE;
215
if (strnequal(*value, "**SecureKey", 11)) {
216
if (strnequal(*value, "**SecureKey=1", 13)) {
217
*action = GP_REG_ACTION_SEC_KEY_SET;
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;
227
DEBUG(0,("unknown: SecureKey: %s\n", *value));
228
smb_panic("not supported SecureKey method");
232
if (strnequal(*value, "**DeleteValues", strlen("**DeleteValues"))) {
233
smb_panic("not supported: **DeleteValues");
234
*action = GP_REG_ACTION_DEL_VALUES;
238
if (strnequal(*value, "**DeleteKeys", strlen("**DeleteKeys"))) {
239
smb_panic("not supported: **DeleteKeys");
240
*action = GP_REG_ACTION_DEL_KEYS;
244
DEBUG(0,("unknown value: %s\n", *value));
249
/****************************************************************
250
****************************************************************/
252
static bool gp_reg_entry_from_file_entry(TALLOC_CTX *mem_ctx,
253
struct gp_registry_file_entry *file_entry,
254
struct gp_registry_entry **reg_entry)
256
struct registry_value *data = NULL;
257
struct gp_registry_entry *entry = NULL;
260
enum gp_reg_action action = GP_REG_ACTION_NONE;
261
size_t converted_size;
263
ZERO_STRUCTP(*reg_entry);
265
data = TALLOC_ZERO_P(mem_ctx, struct registry_value);
269
if (strlen_w((const smb_ucs2_t *)file_entry->key.buffer) <= 0)
272
if (!pull_ucs2_talloc(mem_ctx, &key, file_entry->key.buffer,
278
if (strlen_w((const smb_ucs2_t *)file_entry->value.buffer) > 0 &&
279
!pull_ucs2_talloc(mem_ctx, &value, file_entry->value.buffer,
285
if (!reg_parse_value(mem_ctx, &value, &action))
288
data->type = file_entry->type;
290
switch (data->type) {
292
data->v.dword = atoi((char *)file_entry->data);
295
data->v.binary = data_blob_talloc(mem_ctx,
302
if (!pull_ucs2_talloc(mem_ctx, &data->v.sz.str,
310
case REG_DWORD_BIG_ENDIAN:
315
/* case REG_DWORD_LITTLE_ENDIAN: */
316
/* case REG_QWORD_LITTLE_ENDIAN: */
317
printf("not yet implemented: %d\n", data->type);
320
printf("invalid reg type defined: %d\n", data->type);
325
entry = TALLOC_ZERO_P(mem_ctx, struct gp_registry_entry);
330
entry->value = value;
332
entry->action = action;
339
/****************************************************************
340
* [key;value;type;size;data][key;value;type;size;data]...
341
****************************************************************/
343
static bool reg_parse_entries(TALLOC_CTX *mem_ctx,
345
struct gp_registry_entry **entries,
351
if (!entries || !num_entries)
354
prs_debug(ps, depth, desc, "reg_parse_entries");
360
while (ps->buffer_size > ps->data_offset) {
362
struct gp_registry_file_entry f_entry;
363
struct gp_registry_entry *r_entry = NULL;
365
if (!reg_parse_entry(mem_ctx, desc, &f_entry,
369
if (!gp_reg_entry_from_file_entry(mem_ctx,
374
if (!add_gp_registry_entry_to_array(mem_ctx,
384
/****************************************************************
385
****************************************************************/
387
static NTSTATUS reg_parse_registry(TALLOC_CTX *mem_ctx,
389
const char *filename,
390
struct gp_registry_entry **entries,
393
uint16_t *buf = NULL;
397
struct gp_registry_file *reg_file;
398
const char *real_filename = NULL;
400
reg_file = TALLOC_ZERO_P(mem_ctx, struct gp_registry_file);
401
NT_STATUS_HAVE_NO_MEMORY(reg_file);
403
status = gp_find_file(mem_ctx,
408
if (!NT_STATUS_IS_OK(status)) {
409
TALLOC_FREE(reg_file);
413
buf = (uint16 *)file_load(real_filename, &n, 0, NULL);
415
TALLOC_FREE(reg_file);
416
return NT_STATUS_CANNOT_LOAD_REGISTRY_FILE;
419
if (!prs_init(&ps, n, mem_ctx, UNMARSHALL)) {
420
status = NT_STATUS_NO_MEMORY;
424
if (!prs_copy_data_in(&ps, (char *)buf, n)) {
425
status = NT_STATUS_NO_MEMORY;
429
prs_set_offset(&ps, 0);
431
if (!reg_parse_header("header", ®_file->header, &ps, 0)) {
432
status = NT_STATUS_REGISTRY_IO_FAILED;
436
if (reg_file->header.signature != GP_REGPOL_FILE_SIGNATURE) {
437
status = NT_STATUS_INVALID_PARAMETER;
441
if (reg_file->header.version != GP_REGPOL_FILE_VERSION) {
442
status = NT_STATUS_INVALID_PARAMETER;
446
if (!reg_parse_entries(mem_ctx, "entries", ®_file->entries,
447
®_file->num_entries, &ps, 0)) {
448
status = NT_STATUS_REGISTRY_IO_FAILED;
452
*entries = reg_file->entries;
453
*num_entries = reg_file->num_entries;
455
status = NT_STATUS_OK;
464
/****************************************************************
465
****************************************************************/
467
static WERROR reg_apply_registry(TALLOC_CTX *mem_ctx,
468
const struct nt_user_token *token,
469
struct registry_key *root_key,
471
struct gp_registry_entry *entries,
474
struct gp_registry_context *reg_ctx = NULL;
478
if (num_entries == 0) {
483
if (flags & GPO_LIST_FLAG_MACHINE) {
484
werr = gp_init_reg_ctx(mem_ctx, KEY_HKLM, REG_KEY_WRITE,
488
werr = gp_init_reg_ctx(mem_ctx, KEY_HKCU, REG_KEY_WRITE,
492
W_ERROR_NOT_OK_RETURN(werr);
494
for (i=0; i<num_entries; i++) {
496
/* FIXME: maybe we should check here if we attempt to go beyond
497
* the 4 allowed reg keys */
499
werr = reg_apply_registry_entry(mem_ctx, root_key,
503
if (!W_ERROR_IS_OK(werr)) {
504
DEBUG(0,("failed to apply registry: %s\n",
511
gp_free_reg_ctx(reg_ctx);
516
/****************************************************************
517
****************************************************************/
519
static NTSTATUS registry_process_group_policy(ADS_STRUCT *ads,
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)
530
struct gp_registry_entry *entries = NULL;
531
size_t num_entries = 0;
532
char *unix_path = NULL;
534
debug_gpext_header(0, "registry_process_group_policy", flags, gpo,
535
extension_guid, snapin_guid);
537
status = gpo_get_unix_path(mem_ctx, gpo, &unix_path);
538
NT_STATUS_NOT_OK_RETURN(status);
540
status = reg_parse_registry(mem_ctx,
545
if (!NT_STATUS_IS_OK(status)) {
546
DEBUG(0,("failed to parse registry: %s\n",
551
dump_reg_entries(flags, "READ", entries, num_entries);
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",
558
return werror_to_ntstatus(werr);
564
/****************************************************************
565
****************************************************************/
567
static NTSTATUS registry_get_reg_config(TALLOC_CTX *mem_ctx,
568
struct gp_extension_reg_info **reg_info)
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 }
577
info = TALLOC_ZERO_P(mem_ctx, struct gp_extension_reg_info);
578
NT_STATUS_HAVE_NO_MEMORY(info);
580
status = gp_ext_info_add_entry(mem_ctx, GP_EXT_NAME,
581
GP_EXT_GUID_REGISTRY,
583
NT_STATUS_NOT_OK_RETURN(status);
590
/****************************************************************
591
****************************************************************/
593
static NTSTATUS registry_initialize(TALLOC_CTX *mem_ctx)
598
/****************************************************************
599
****************************************************************/
601
static NTSTATUS registry_shutdown(void)
605
status = unregister_gp_extension(GP_EXT_NAME);
606
if (NT_STATUS_IS_OK(status)) {
615
/****************************************************************
616
****************************************************************/
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
625
/****************************************************************
626
****************************************************************/
628
NTSTATUS gpext_registry_init(void)
632
ctx = talloc_init("gpext_registry_init");
633
NT_STATUS_HAVE_NO_MEMORY(ctx);
635
status = register_gp_extension(ctx, SMB_GPEXT_INTERFACE_VERSION,
636
GP_EXT_NAME, GP_EXT_GUID_REGISTRY,
638
if (!NT_STATUS_IS_OK(status)) {