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