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);
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
)) {