2 * Unix SMB/CIFS implementation.
3 * Virtual Windows Registry Layer
4 * Copyright (C) Volker Lendecke 2006
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 2 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, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 /* Attempt to wrap the existing API in a more winreg.idl-like way */
25 static WERROR
fill_value_cache(struct registry_key
*key
)
27 if (key
->values
!= NULL
) {
31 if (!(key
->values
= TALLOC_ZERO_P(key
, REGVAL_CTR
))) {
34 if (fetch_reg_values(key
->key
, key
->values
) == -1) {
35 TALLOC_FREE(key
->values
);
42 static WERROR
fill_subkey_cache(struct registry_key
*key
)
44 if (key
->subkeys
!= NULL
) {
48 if (!(key
->subkeys
= TALLOC_ZERO_P(key
, REGSUBKEY_CTR
))) {
52 if (fetch_reg_keys(key
->key
, key
->subkeys
) == -1) {
53 TALLOC_FREE(key
->subkeys
);
54 return WERR_NO_MORE_ITEMS
;
60 static int regkey_destructor(REGISTRY_KEY
*key
)
65 static WERROR
regkey_open_onelevel(TALLOC_CTX
*mem_ctx
,
66 struct registry_key
*parent
,
68 const struct nt_user_token
*token
,
69 uint32 access_desired
,
70 struct registry_key
**pregkey
)
72 WERROR result
= WERR_OK
;
73 struct registry_key
*regkey
;
75 REGSUBKEY_CTR
*subkeys
= NULL
;
77 DEBUG(7,("regkey_open_onelevel: name = [%s]\n", name
));
79 SMB_ASSERT(strchr(name
, '\\') == NULL
);
81 if (!(regkey
= TALLOC_ZERO_P(mem_ctx
, struct registry_key
)) ||
82 !(regkey
->token
= dup_nt_token(regkey
, token
)) ||
83 !(regkey
->key
= TALLOC_ZERO_P(regkey
, REGISTRY_KEY
))) {
88 if ( !(W_ERROR_IS_OK(result
= regdb_open())) ) {
93 talloc_set_destructor(key
, regkey_destructor
);
97 key
->type
= REG_KEY_GENERIC
;
99 if (name
[0] == '\0') {
101 * Open a copy of the parent key
104 result
= WERR_BADFILE
;
107 key
->name
= talloc_strdup(key
, parent
->key
->name
);
113 key
->name
= talloc_asprintf(key
, "%s%s%s",
114 parent
? parent
->key
->name
: "",
119 if (key
->name
== NULL
) {
124 /* Tag this as a Performance Counter Key */
126 if( StrnCaseCmp(key
->name
, KEY_HKPD
, strlen(KEY_HKPD
)) == 0 )
127 key
->type
= REG_KEY_HKPD
;
129 /* Look up the table of registry I/O operations */
131 if ( !(key
->hook
= reghook_cache_find( key
->name
)) ) {
132 DEBUG(0,("reg_open_onelevel: Failed to assigned a "
133 "REGISTRY_HOOK to [%s]\n", key
->name
));
134 result
= WERR_BADFILE
;
138 /* check if the path really exists; failed is indicated by -1 */
139 /* if the subkey count failed, bail out */
141 if ( !(subkeys
= TALLOC_ZERO_P( key
, REGSUBKEY_CTR
)) ) {
146 if ( fetch_reg_keys( key
, subkeys
) == -1 ) {
147 result
= WERR_BADFILE
;
151 TALLOC_FREE( subkeys
);
153 if ( !regkey_access_check( key
, access_desired
, &key
->access_granted
,
155 result
= WERR_ACCESS_DENIED
;
163 if ( !W_ERROR_IS_OK(result
) ) {
170 WERROR
reg_openhive(TALLOC_CTX
*mem_ctx
, const char *hive
,
171 uint32 desired_access
,
172 const struct nt_user_token
*token
,
173 struct registry_key
**pkey
)
175 SMB_ASSERT(hive
!= NULL
);
176 SMB_ASSERT(hive
[0] != '\0');
177 SMB_ASSERT(strchr(hive
, '\\') == NULL
);
179 return regkey_open_onelevel(mem_ctx
, NULL
, hive
, token
, desired_access
,
183 WERROR
reg_openkey(TALLOC_CTX
*mem_ctx
, struct registry_key
*parent
,
184 const char *name
, uint32 desired_access
,
185 struct registry_key
**pkey
)
187 struct registry_key
*direct_parent
= parent
;
189 char *p
, *path
, *to_free
;
192 if (!(path
= SMB_STRDUP(name
))) {
199 if ((len
> 0) && (path
[len
-1] == '\\')) {
203 while ((p
= strchr(path
, '\\')) != NULL
) {
204 char *name_component
;
205 struct registry_key
*tmp
;
207 if (!(name_component
= SMB_STRNDUP(path
, (p
- path
)))) {
212 err
= regkey_open_onelevel(mem_ctx
, direct_parent
,
213 name_component
, parent
->token
,
214 SEC_RIGHTS_ENUM_SUBKEYS
, &tmp
);
215 SAFE_FREE(name_component
);
217 if (!W_ERROR_IS_OK(err
)) {
220 if (direct_parent
!= parent
) {
221 TALLOC_FREE(direct_parent
);
228 err
= regkey_open_onelevel(mem_ctx
, direct_parent
, path
, parent
->token
,
229 desired_access
, pkey
);
231 if (direct_parent
!= parent
) {
232 TALLOC_FREE(direct_parent
);
238 WERROR
reg_enumkey(TALLOC_CTX
*mem_ctx
, struct registry_key
*key
,
239 uint32 idx
, char **name
, NTTIME
*last_write_time
)
243 if (!(key
->key
->access_granted
& SEC_RIGHTS_ENUM_SUBKEYS
)) {
244 return WERR_ACCESS_DENIED
;
247 if (!W_ERROR_IS_OK(err
= fill_subkey_cache(key
))) {
251 if (idx
>= key
->subkeys
->num_subkeys
) {
252 return WERR_NO_MORE_ITEMS
;
255 if (!(*name
= talloc_strdup(mem_ctx
, key
->subkeys
->subkeys
[idx
]))) {
259 if (last_write_time
) {
260 *last_write_time
= 0;
266 WERROR
reg_enumvalue(TALLOC_CTX
*mem_ctx
, struct registry_key
*key
,
267 uint32 idx
, char **pname
, struct registry_value
**pval
)
269 struct registry_value
*val
;
272 if (!(key
->key
->access_granted
& SEC_RIGHTS_QUERY_VALUE
)) {
273 return WERR_ACCESS_DENIED
;
276 if (!(W_ERROR_IS_OK(err
= fill_value_cache(key
)))) {
280 if (idx
>= key
->values
->num_values
) {
281 return WERR_NO_MORE_ITEMS
;
284 err
= registry_pull_value(mem_ctx
, &val
,
285 key
->values
->values
[idx
]->type
,
286 key
->values
->values
[idx
]->data_p
,
287 key
->values
->values
[idx
]->size
,
288 key
->values
->values
[idx
]->size
);
289 if (!W_ERROR_IS_OK(err
)) {
294 && !(*pname
= talloc_strdup(
295 mem_ctx
, key
->values
->values
[idx
]->valuename
))) {
304 WERROR
reg_queryvalue(TALLOC_CTX
*mem_ctx
, struct registry_key
*key
,
305 const char *name
, struct registry_value
**pval
)
310 if (!(key
->key
->access_granted
& SEC_RIGHTS_QUERY_VALUE
)) {
311 return WERR_ACCESS_DENIED
;
314 if (!(W_ERROR_IS_OK(err
= fill_value_cache(key
)))) {
318 for (i
=0; i
<key
->values
->num_values
; i
++) {
319 if (strequal(key
->values
->values
[i
]->valuename
, name
)) {
320 return reg_enumvalue(mem_ctx
, key
, i
, NULL
, pval
);
327 WERROR
reg_queryinfokey(struct registry_key
*key
, uint32_t *num_subkeys
,
328 uint32_t *max_subkeylen
, uint32_t *max_subkeysize
,
329 uint32_t *num_values
, uint32_t *max_valnamelen
,
330 uint32_t *max_valbufsize
, uint32_t *secdescsize
,
331 NTTIME
*last_changed_time
)
337 struct security_descriptor
*secdesc
;
339 if (!(key
->key
->access_granted
& SEC_RIGHTS_QUERY_VALUE
)) {
340 return WERR_ACCESS_DENIED
;
343 if (!W_ERROR_IS_OK(fill_subkey_cache(key
)) ||
344 !W_ERROR_IS_OK(fill_value_cache(key
))) {
349 for (i
=0; i
<key
->subkeys
->num_subkeys
; i
++) {
350 max_len
= MAX(max_len
, strlen(key
->subkeys
->subkeys
[i
]));
353 *num_subkeys
= key
->subkeys
->num_subkeys
;
354 *max_subkeylen
= max_len
;
355 *max_subkeysize
= 0; /* Class length? */
359 for (i
=0; i
<key
->values
->num_values
; i
++) {
360 max_len
= MAX(max_len
,
361 strlen(key
->values
->values
[i
]->valuename
));
362 max_size
= MAX(max_size
, key
->values
->values
[i
]->size
);
365 *num_values
= key
->values
->num_values
;
366 *max_valnamelen
= max_len
;
367 *max_valbufsize
= max_size
;
369 if (!(mem_ctx
= talloc_new(key
))) {
373 err
= regkey_get_secdesc(mem_ctx
, key
->key
, &secdesc
);
374 if (!W_ERROR_IS_OK(err
)) {
375 TALLOC_FREE(mem_ctx
);
379 *secdescsize
= sec_desc_size(secdesc
);
380 TALLOC_FREE(mem_ctx
);
382 *last_changed_time
= 0;
387 WERROR
reg_createkey(TALLOC_CTX
*ctx
, struct registry_key
*parent
,
388 const char *subkeypath
, uint32 desired_access
,
389 struct registry_key
**pkey
,
390 enum winreg_CreateAction
*paction
)
392 struct registry_key
*key
= parent
;
393 struct registry_key
*create_parent
;
397 REGSUBKEY_CTR
*subkeys
;
399 if (!(mem_ctx
= talloc_new(ctx
))) return WERR_NOMEM
;
401 if (!(path
= talloc_strdup(mem_ctx
, subkeypath
))) {
406 while ((end
= strchr(path
, '\\')) != NULL
) {
407 struct registry_key
*tmp
;
408 enum winreg_CreateAction action
;
412 err
= reg_createkey(mem_ctx
, key
, path
,
413 SEC_RIGHTS_ENUM_SUBKEYS
, &tmp
, &action
);
414 if (!W_ERROR_IS_OK(err
)) {
427 * At this point, "path" contains the one-element subkey of "key". We
428 * can try to open it.
431 err
= reg_openkey(ctx
, key
, path
, desired_access
, pkey
);
432 if (W_ERROR_IS_OK(err
)) {
433 if (paction
!= NULL
) {
434 *paction
= REG_OPENED_EXISTING_KEY
;
439 if (!W_ERROR_EQUAL(err
, WERR_BADFILE
)) {
441 * Something but "notfound" has happened, so bail out
447 * We have to make a copy of the current key, as we opened it only
448 * with ENUM_SUBKEY access.
451 err
= reg_openkey(mem_ctx
, key
, "", SEC_RIGHTS_CREATE_SUBKEY
,
453 if (!W_ERROR_IS_OK(err
)) {
458 * Actually create the subkey
461 if (!(subkeys
= TALLOC_ZERO_P(mem_ctx
, REGSUBKEY_CTR
))) {
466 err
= fill_subkey_cache(create_parent
);
467 if (!W_ERROR_IS_OK(err
)) goto done
;
469 err
= regsubkey_ctr_addkey(create_parent
->subkeys
, path
);
470 if (!W_ERROR_IS_OK(err
)) goto done
;
472 if (!store_reg_keys(create_parent
->key
, create_parent
->subkeys
)) {
473 TALLOC_FREE(create_parent
->subkeys
);
474 err
= WERR_REG_IO_FAILURE
;
479 * Now open the newly created key
482 err
= reg_openkey(ctx
, create_parent
, path
, desired_access
, pkey
);
483 if (W_ERROR_IS_OK(err
) && (paction
!= NULL
)) {
484 *paction
= REG_CREATED_NEW_KEY
;
488 TALLOC_FREE(mem_ctx
);
493 WERROR
reg_deletekey(struct registry_key
*parent
, const char *path
)
499 struct registry_key
*tmp_key
;
501 if (!(mem_ctx
= talloc_init("reg_createkey"))) return WERR_NOMEM
;
503 if (!(name
= talloc_strdup(mem_ctx
, path
))) {
508 /* check if the key has subkeys */
509 err
= reg_openkey(mem_ctx
, parent
, name
, REG_KEY_READ
, &tmp_key
);
510 if (!W_ERROR_IS_OK(err
)) {
513 if (!W_ERROR_IS_OK(err
= fill_subkey_cache(tmp_key
))) {
516 if (tmp_key
->subkeys
->num_subkeys
> 0) {
517 err
= WERR_ACCESS_DENIED
;
521 /* no subkeys - proceed with delete */
522 if ((end
= strrchr(name
, '\\')) != NULL
) {
525 err
= reg_openkey(mem_ctx
, parent
, name
,
526 SEC_RIGHTS_CREATE_SUBKEY
, &tmp_key
);
527 if (!W_ERROR_IS_OK(err
)) {
535 if (name
[0] == '\0') {
536 err
= WERR_INVALID_PARAM
;
540 if (!W_ERROR_IS_OK(err
= fill_subkey_cache(parent
))) {
544 num_subkeys
= parent
->subkeys
->num_subkeys
;
546 if (regsubkey_ctr_delkey(parent
->subkeys
, name
) == num_subkeys
) {
551 if (!store_reg_keys(parent
->key
, parent
->subkeys
)) {
552 TALLOC_FREE(parent
->subkeys
);
553 err
= WERR_REG_IO_FAILURE
;
559 TALLOC_FREE(mem_ctx
);
563 WERROR
reg_setvalue(struct registry_key
*key
, const char *name
,
564 const struct registry_value
*val
)
567 DATA_BLOB value_data
;
570 if (!(key
->key
->access_granted
& SEC_RIGHTS_SET_VALUE
)) {
571 return WERR_ACCESS_DENIED
;
574 if (!W_ERROR_IS_OK(err
= fill_value_cache(key
))) {
578 err
= registry_push_value(key
, val
, &value_data
);
579 if (!W_ERROR_IS_OK(err
)) {
583 res
= regval_ctr_addvalue(key
->values
, name
, val
->type
,
584 (char *)value_data
.data
, value_data
.length
);
585 TALLOC_FREE(value_data
.data
);
588 TALLOC_FREE(key
->values
);
592 if (!store_reg_values(key
->key
, key
->values
)) {
593 TALLOC_FREE(key
->values
);
594 return WERR_REG_IO_FAILURE
;
600 WERROR
reg_deletevalue(struct registry_key
*key
, const char *name
)
604 if (!(key
->key
->access_granted
& SEC_RIGHTS_SET_VALUE
)) {
605 return WERR_ACCESS_DENIED
;
608 if (!W_ERROR_IS_OK(err
= fill_value_cache(key
))) {
612 regval_ctr_delvalue(key
->values
, name
);
614 if (!store_reg_values(key
->key
, key
->values
)) {
615 TALLOC_FREE(key
->values
);
616 return WERR_REG_IO_FAILURE
;
624 * Utility function to open a complete registry path including the hive
625 * prefix. This should become the replacement function for
626 * regkey_open_internal.
629 WERROR
reg_open_path(TALLOC_CTX
*mem_ctx
, const char *orig_path
,
630 uint32 desired_access
, const struct nt_user_token
*token
,
631 struct registry_key
**pkey
)
633 struct registry_key
*hive
, *key
;
637 if (!(path
= SMB_STRDUP(orig_path
))) {
641 p
= strchr(path
, '\\');
643 if ((p
== NULL
) || (p
[1] == '\0')) {
645 * No key behind the hive, just return the hive
648 err
= reg_openhive(mem_ctx
, path
, desired_access
, token
,
650 if (!W_ERROR_IS_OK(err
)) {
661 err
= reg_openhive(mem_ctx
, path
, SEC_RIGHTS_ENUM_SUBKEYS
, token
,
663 if (!W_ERROR_IS_OK(err
)) {
668 err
= reg_openkey(mem_ctx
, hive
, p
+1, desired_access
, &key
);
673 if (!W_ERROR_IS_OK(err
)) {
683 * Utility function to delete a registry key with all its subkeys.
684 * Note that reg_deletekey returns ACCESS_DENIED when called on a
685 * key that has subkeys.
687 WERROR
reg_deletekey_recursive(TALLOC_CTX
*ctx
,
688 struct registry_key
*parent
,
691 TALLOC_CTX
*mem_ctx
= NULL
;
692 WERROR werr
= WERR_OK
;
693 struct registry_key
*key
;
694 char *subkey_name
= NULL
;
696 mem_ctx
= talloc_new(ctx
);
697 if (mem_ctx
== NULL
) {
702 /* recurse through subkeys first */
703 werr
= reg_openkey(mem_ctx
, parent
, path
, REG_KEY_WRITE
, &key
);
704 if (!W_ERROR_IS_OK(werr
)) {
708 while (W_ERROR_IS_OK(werr
= reg_enumkey(mem_ctx
, key
, 0,
709 &subkey_name
, NULL
)))
711 werr
= reg_deletekey_recursive(mem_ctx
, key
, subkey_name
);
712 if (!W_ERROR_IS_OK(werr
)) {
716 if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS
, werr
)) {
717 DEBUG(1, ("reg_deletekey_recursive: Error enumerating "
718 "subkeys: %s\n", dos_errstr(werr
)));
722 /* now delete the actual key */
723 werr
= reg_deletekey(parent
, path
);
726 TALLOC_FREE(mem_ctx
);