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/>.
21 #include "../libgpo/gpo_ini.h"
23 #define GP_EXT_NAME "registry"
25 /* more info can be found at:
26 * http://msdn2.microsoft.com/en-us/library/aa374407.aspx */
28 #define GP_REGPOL_FILE "Registry.pol"
30 #define GP_REGPOL_FILE_SIGNATURE 0x67655250 /* 'PReg' */
31 #define GP_REGPOL_FILE_VERSION 1
33 static TALLOC_CTX
*ctx
= NULL
;
35 struct gp_registry_file_header
{
40 struct gp_registry_file_entry
{
43 enum winreg_Type type
;
48 struct gp_registry_file
{
49 struct gp_registry_file_header header
;
51 struct gp_registry_entry
*entries
;
54 /****************************************************************
55 ****************************************************************/
57 static bool reg_parse_header(const char *desc
,
58 struct gp_registry_file_header
*header
,
65 prs_debug(ps
, depth
, desc
, "reg_parse_header");
68 if (!prs_uint32("signature", ps
, depth
, &header
->signature
))
71 if (!prs_uint32("version", ps
, depth
, &header
->version
))
77 /****************************************************************
78 ****************************************************************/
80 static bool reg_parse_and_verify_ucs2_char(const char *desc
,
87 if (!prs_uint16(desc
, ps
, depth
, &tmp
))
90 if (tmp
!= UCS2_CHAR(character
))
96 /****************************************************************
97 ****************************************************************/
99 static bool reg_parse_init(prs_struct
*ps
, int depth
)
101 return reg_parse_and_verify_ucs2_char("initiator '['", '[',
105 /****************************************************************
106 ****************************************************************/
108 static bool reg_parse_sep(prs_struct
*ps
, int depth
)
110 return reg_parse_and_verify_ucs2_char("separator ';'", ';',
114 /****************************************************************
115 ****************************************************************/
117 static bool reg_parse_term(prs_struct
*ps
, int depth
)
119 return reg_parse_and_verify_ucs2_char("terminator ']'", ']',
124 /****************************************************************
125 * [key;value;type;size;data]
126 ****************************************************************/
128 static bool reg_parse_entry(TALLOC_CTX
*mem_ctx
,
130 struct gp_registry_file_entry
*entry
,
139 prs_debug(ps
, depth
, desc
, "reg_parse_entry");
144 if (!reg_parse_init(ps
, depth
))
147 if (!prs_unistr("key", ps
, depth
, &entry
->key
))
150 if (!reg_parse_sep(ps
, depth
))
153 if (!prs_unistr("value", ps
, depth
, &entry
->value
))
156 if (!reg_parse_sep(ps
, depth
))
159 if (!prs_uint32("type", ps
, depth
, &entry
->type
))
162 if (!reg_parse_sep(ps
, depth
))
165 if (!prs_uint32("size", ps
, depth
, &size
))
170 if (!reg_parse_sep(ps
, depth
))
174 entry
->data
= TALLOC_ZERO_ARRAY(mem_ctx
, uint8
, entry
->size
);
179 if (!prs_uint8s(false, "data", ps
, depth
, entry
->data
, entry
->size
))
182 if (!reg_parse_term(ps
, depth
))
188 /****************************************************************
189 ****************************************************************/
191 static bool reg_parse_value(TALLOC_CTX
*mem_ctx
,
193 enum gp_reg_action
*action
)
196 *action
= GP_REG_ACTION_ADD_KEY
;
200 if (strncmp(*value
, "**", 2) != 0) {
201 *action
= GP_REG_ACTION_ADD_VALUE
;
205 if (strnequal(*value
, "**DelVals.", 10)) {
206 *action
= GP_REG_ACTION_DEL_ALL_VALUES
;
210 if (strnequal(*value
, "**Del.", 6)) {
211 *value
= talloc_strdup(mem_ctx
, *value
+ 6);
212 *action
= GP_REG_ACTION_DEL_VALUE
;
216 if (strnequal(*value
, "**SecureKey", 11)) {
217 if (strnequal(*value
, "**SecureKey=1", 13)) {
218 *action
= GP_REG_ACTION_SEC_KEY_SET
;
222 /*************** not tested from here on ***************/
223 if (strnequal(*value
, "**SecureKey=0", 13)) {
224 smb_panic("not supported: **SecureKey=0");
225 *action
= GP_REG_ACTION_SEC_KEY_RESET
;
228 DEBUG(0,("unknown: SecureKey: %s\n", *value
));
229 smb_panic("not supported SecureKey method");
233 if (strnequal(*value
, "**DeleteValues", strlen("**DeleteValues"))) {
234 smb_panic("not supported: **DeleteValues");
235 *action
= GP_REG_ACTION_DEL_VALUES
;
239 if (strnequal(*value
, "**DeleteKeys", strlen("**DeleteKeys"))) {
240 smb_panic("not supported: **DeleteKeys");
241 *action
= GP_REG_ACTION_DEL_KEYS
;
245 DEBUG(0,("unknown value: %s\n", *value
));
250 /****************************************************************
251 ****************************************************************/
253 static bool gp_reg_entry_from_file_entry(TALLOC_CTX
*mem_ctx
,
254 struct gp_registry_file_entry
*file_entry
,
255 struct gp_registry_entry
**reg_entry
)
257 struct registry_value
*data
= NULL
;
258 struct gp_registry_entry
*entry
= NULL
;
261 enum gp_reg_action action
= GP_REG_ACTION_NONE
;
262 size_t converted_size
;
264 ZERO_STRUCTP(*reg_entry
);
266 data
= TALLOC_ZERO_P(mem_ctx
, struct registry_value
);
270 if (strlen_w((const smb_ucs2_t
*)file_entry
->key
.buffer
) <= 0)
273 if (!pull_ucs2_talloc(mem_ctx
, &key
, file_entry
->key
.buffer
,
279 if (strlen_w((const smb_ucs2_t
*)file_entry
->value
.buffer
) > 0 &&
280 !pull_ucs2_talloc(mem_ctx
, &value
, file_entry
->value
.buffer
,
286 if (!reg_parse_value(mem_ctx
, &value
, &action
))
289 data
->type
= file_entry
->type
;
291 switch (data
->type
) {
293 data
->v
.dword
= atoi((char *)file_entry
->data
);
296 data
->v
.binary
= data_blob_talloc(mem_ctx
,
303 if (!pull_ucs2_talloc(mem_ctx
, &data
->v
.sz
.str
,
311 case REG_DWORD_BIG_ENDIAN
:
316 /* case REG_DWORD_LITTLE_ENDIAN: */
317 /* case REG_QWORD_LITTLE_ENDIAN: */
318 printf("not yet implemented: %d\n", data
->type
);
321 printf("invalid reg type defined: %d\n", data
->type
);
326 entry
= TALLOC_ZERO_P(mem_ctx
, struct gp_registry_entry
);
331 entry
->value
= value
;
333 entry
->action
= action
;
340 /****************************************************************
341 * [key;value;type;size;data][key;value;type;size;data]...
342 ****************************************************************/
344 static bool reg_parse_entries(TALLOC_CTX
*mem_ctx
,
346 struct gp_registry_entry
**entries
,
352 if (!entries
|| !num_entries
)
355 prs_debug(ps
, depth
, desc
, "reg_parse_entries");
361 while (ps
->buffer_size
> ps
->data_offset
) {
363 struct gp_registry_file_entry f_entry
;
364 struct gp_registry_entry
*r_entry
= NULL
;
366 if (!reg_parse_entry(mem_ctx
, desc
, &f_entry
,
370 if (!gp_reg_entry_from_file_entry(mem_ctx
,
375 if (!add_gp_registry_entry_to_array(mem_ctx
,
385 /****************************************************************
386 ****************************************************************/
388 static NTSTATUS
reg_parse_registry(TALLOC_CTX
*mem_ctx
,
390 const char *filename
,
391 struct gp_registry_entry
**entries
,
394 uint16_t *buf
= NULL
;
398 struct gp_registry_file
*reg_file
;
399 const char *real_filename
= NULL
;
401 reg_file
= TALLOC_ZERO_P(mem_ctx
, struct gp_registry_file
);
402 NT_STATUS_HAVE_NO_MEMORY(reg_file
);
404 status
= gp_find_file(mem_ctx
,
409 if (!NT_STATUS_IS_OK(status
)) {
410 TALLOC_FREE(reg_file
);
414 buf
= (uint16
*)file_load(real_filename
, &n
, 0, NULL
);
416 TALLOC_FREE(reg_file
);
417 return NT_STATUS_CANNOT_LOAD_REGISTRY_FILE
;
420 if (!prs_init(&ps
, n
, mem_ctx
, UNMARSHALL
)) {
421 status
= NT_STATUS_NO_MEMORY
;
425 if (!prs_copy_data_in(&ps
, (char *)buf
, n
)) {
426 status
= NT_STATUS_NO_MEMORY
;
430 prs_set_offset(&ps
, 0);
432 if (!reg_parse_header("header", ®_file
->header
, &ps
, 0)) {
433 status
= NT_STATUS_REGISTRY_IO_FAILED
;
437 if (reg_file
->header
.signature
!= GP_REGPOL_FILE_SIGNATURE
) {
438 status
= NT_STATUS_INVALID_PARAMETER
;
442 if (reg_file
->header
.version
!= GP_REGPOL_FILE_VERSION
) {
443 status
= NT_STATUS_INVALID_PARAMETER
;
447 if (!reg_parse_entries(mem_ctx
, "entries", ®_file
->entries
,
448 ®_file
->num_entries
, &ps
, 0)) {
449 status
= NT_STATUS_REGISTRY_IO_FAILED
;
453 *entries
= reg_file
->entries
;
454 *num_entries
= reg_file
->num_entries
;
456 status
= NT_STATUS_OK
;
465 /****************************************************************
466 ****************************************************************/
468 static WERROR
reg_apply_registry(TALLOC_CTX
*mem_ctx
,
469 const struct nt_user_token
*token
,
470 struct registry_key
*root_key
,
472 struct gp_registry_entry
*entries
,
475 struct gp_registry_context
*reg_ctx
= NULL
;
479 if (num_entries
== 0) {
484 if (flags
& GPO_LIST_FLAG_MACHINE
) {
485 werr
= gp_init_reg_ctx(mem_ctx
, KEY_HKLM
, REG_KEY_WRITE
,
489 werr
= gp_init_reg_ctx(mem_ctx
, KEY_HKCU
, REG_KEY_WRITE
,
493 W_ERROR_NOT_OK_RETURN(werr
);
495 for (i
=0; i
<num_entries
; i
++) {
497 /* FIXME: maybe we should check here if we attempt to go beyond
498 * the 4 allowed reg keys */
500 werr
= reg_apply_registry_entry(mem_ctx
, root_key
,
504 if (!W_ERROR_IS_OK(werr
)) {
505 DEBUG(0,("failed to apply registry: %s\n",
512 gp_free_reg_ctx(reg_ctx
);
517 /****************************************************************
518 ****************************************************************/
520 static NTSTATUS
registry_process_group_policy(ADS_STRUCT
*ads
,
523 struct registry_key
*root_key
,
524 const struct nt_user_token
*token
,
525 struct GROUP_POLICY_OBJECT
*gpo
,
526 const char *extension_guid
,
527 const char *snapin_guid
)
531 struct gp_registry_entry
*entries
= NULL
;
532 size_t num_entries
= 0;
533 char *unix_path
= NULL
;
535 debug_gpext_header(0, "registry_process_group_policy", flags
, gpo
,
536 extension_guid
, snapin_guid
);
538 status
= gpo_get_unix_path(mem_ctx
, cache_path(GPO_CACHE_DIR
), gpo
, &unix_path
);
539 NT_STATUS_NOT_OK_RETURN(status
);
541 status
= reg_parse_registry(mem_ctx
,
546 if (!NT_STATUS_IS_OK(status
)) {
547 DEBUG(0,("failed to parse registry: %s\n",
552 dump_reg_entries(flags
, "READ", entries
, num_entries
);
554 werr
= reg_apply_registry(mem_ctx
, token
, root_key
, flags
,
555 entries
, num_entries
);
556 if (!W_ERROR_IS_OK(werr
)) {
557 DEBUG(0,("failed to apply registry: %s\n",
559 return werror_to_ntstatus(werr
);
565 /****************************************************************
566 ****************************************************************/
568 static NTSTATUS
registry_get_reg_config(TALLOC_CTX
*mem_ctx
,
569 struct gp_extension_reg_info
**reg_info
)
572 struct gp_extension_reg_info
*info
= NULL
;
573 struct gp_extension_reg_table table
[] = {
574 { "ProcessGroupPolicy", REG_SZ
, "registry_process_group_policy" },
575 { NULL
, REG_NONE
, NULL
}
578 info
= TALLOC_ZERO_P(mem_ctx
, struct gp_extension_reg_info
);
579 NT_STATUS_HAVE_NO_MEMORY(info
);
581 status
= gp_ext_info_add_entry(mem_ctx
, GP_EXT_NAME
,
582 GP_EXT_GUID_REGISTRY
,
584 NT_STATUS_NOT_OK_RETURN(status
);
591 /****************************************************************
592 ****************************************************************/
594 static NTSTATUS
registry_initialize(TALLOC_CTX
*mem_ctx
)
599 /****************************************************************
600 ****************************************************************/
602 static NTSTATUS
registry_shutdown(void)
606 status
= unregister_gp_extension(GP_EXT_NAME
);
607 if (NT_STATUS_IS_OK(status
)) {
616 /****************************************************************
617 ****************************************************************/
619 static struct gp_extension_methods registry_methods
= {
620 .initialize
= registry_initialize
,
621 .process_group_policy
= registry_process_group_policy
,
622 .get_reg_config
= registry_get_reg_config
,
623 .shutdown
= registry_shutdown
626 /****************************************************************
627 ****************************************************************/
629 NTSTATUS
gpext_registry_init(void)
633 ctx
= talloc_init("gpext_registry_init");
634 NT_STATUS_HAVE_NO_MEMORY(ctx
);
636 status
= register_gp_extension(ctx
, SMB_GPEXT_INTERFACE_VERSION
,
637 GP_EXT_NAME
, GP_EXT_GUID_REGISTRY
,
639 if (!NT_STATUS_IS_OK(status
)) {