r25068: Older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for every opcode on the
[Samba.git] / source / registry / reg_api.c
blob9147becf9b718b841967bd86d7b39c7f0c67e44c
1 /*
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 */
23 #include "includes.h"
25 static WERROR fill_value_cache(struct registry_key *key)
27 if (key->values != NULL) {
28 return WERR_OK;
31 if (!(key->values = TALLOC_ZERO_P(key, REGVAL_CTR))) {
32 return WERR_NOMEM;
34 if (fetch_reg_values(key->key, key->values) == -1) {
35 TALLOC_FREE(key->values);
36 return WERR_BADFILE;
39 return WERR_OK;
42 static WERROR fill_subkey_cache(struct registry_key *key)
44 if (key->subkeys != NULL) {
45 return WERR_OK;
48 if (!(key->subkeys = TALLOC_ZERO_P(key, REGSUBKEY_CTR))) {
49 return WERR_NOMEM;
52 if (fetch_reg_keys(key->key, key->subkeys) == -1) {
53 TALLOC_FREE(key->subkeys);
54 return WERR_NO_MORE_ITEMS;
57 return WERR_OK;
60 static int regkey_destructor(REGISTRY_KEY *key)
62 return regdb_close();
65 static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx,
66 struct registry_key *parent,
67 const char *name,
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;
74 REGISTRY_KEY *key;
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))) {
84 result = WERR_NOMEM;
85 goto done;
88 if ( !(W_ERROR_IS_OK(result = regdb_open())) ) {
89 goto done;
92 key = regkey->key;
93 talloc_set_destructor(key, regkey_destructor);
95 /* initialization */
97 key->type = REG_KEY_GENERIC;
99 if (name[0] == '\0') {
101 * Open a copy of the parent key
103 if (!parent) {
104 result = WERR_BADFILE;
105 goto done;
107 key->name = talloc_strdup(key, parent->key->name);
109 else {
111 * Normal subkey open
113 key->name = talloc_asprintf(key, "%s%s%s",
114 parent ? parent->key->name : "",
115 parent ? "\\": "",
116 name);
119 if (key->name == NULL) {
120 result = WERR_NOMEM;
121 goto done;
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;
135 goto done;
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 )) ) {
142 result = WERR_NOMEM;
143 goto done;
146 if ( fetch_reg_keys( key, subkeys ) == -1 ) {
147 result = WERR_BADFILE;
148 goto done;
151 TALLOC_FREE( subkeys );
153 if ( !regkey_access_check( key, access_desired, &key->access_granted,
154 token ) ) {
155 result = WERR_ACCESS_DENIED;
156 goto done;
159 *pregkey = regkey;
160 result = WERR_OK;
162 done:
163 if ( !W_ERROR_IS_OK(result) ) {
164 TALLOC_FREE(regkey);
167 return 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,
180 pkey);
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;
188 WERROR err;
189 char *p, *path, *to_free;
190 size_t len;
192 if (!(path = SMB_STRDUP(name))) {
193 return WERR_NOMEM;
195 to_free = path;
197 len = strlen(path);
199 if ((len > 0) && (path[len-1] == '\\')) {
200 path[len-1] = '\0';
203 while ((p = strchr(path, '\\')) != NULL) {
204 char *name_component;
205 struct registry_key *tmp;
207 if (!(name_component = SMB_STRNDUP(path, (p - path)))) {
208 err = WERR_NOMEM;
209 goto error;
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)) {
218 goto error;
220 if (direct_parent != parent) {
221 TALLOC_FREE(direct_parent);
224 direct_parent = tmp;
225 path = p+1;
228 err = regkey_open_onelevel(mem_ctx, direct_parent, path, parent->token,
229 desired_access, pkey);
230 error:
231 if (direct_parent != parent) {
232 TALLOC_FREE(direct_parent);
234 SAFE_FREE(to_free);
235 return err;
238 WERROR reg_enumkey(TALLOC_CTX *mem_ctx, struct registry_key *key,
239 uint32 idx, char **name, NTTIME *last_write_time)
241 WERROR err;
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))) {
248 return err;
251 if (idx >= key->subkeys->num_subkeys) {
252 return WERR_NO_MORE_ITEMS;
255 if (!(*name = talloc_strdup(mem_ctx, key->subkeys->subkeys[idx]))) {
256 return WERR_NOMEM;
259 if (last_write_time) {
260 *last_write_time = 0;
263 return WERR_OK;
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;
270 WERROR err;
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)))) {
277 return err;
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)) {
290 return err;
293 if (pname
294 && !(*pname = talloc_strdup(
295 mem_ctx, key->values->values[idx]->valuename))) {
296 SAFE_FREE(val);
297 return WERR_NOMEM;
300 *pval = val;
301 return WERR_OK;
304 WERROR reg_queryvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
305 const char *name, struct registry_value **pval)
307 WERROR err;
308 uint32 i;
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)))) {
315 return err;
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);
324 return WERR_BADFILE;
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)
333 uint32 i, max_size;
334 size_t max_len;
335 TALLOC_CTX *mem_ctx;
336 WERROR err;
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))) {
345 return WERR_BADFILE;
348 max_len = 0;
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? */
357 max_len = 0;
358 max_size = 0;
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))) {
370 return WERR_NOMEM;
373 err = regkey_get_secdesc(mem_ctx, key->key, &secdesc);
374 if (!W_ERROR_IS_OK(err)) {
375 TALLOC_FREE(mem_ctx);
376 return err;
379 *secdescsize = sec_desc_size(secdesc);
380 TALLOC_FREE(mem_ctx);
382 *last_changed_time = 0;
384 return WERR_OK;
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;
394 TALLOC_CTX *mem_ctx;
395 char *path, *end;
396 WERROR err;
397 REGSUBKEY_CTR *subkeys;
399 if (!(mem_ctx = talloc_new(ctx))) return WERR_NOMEM;
401 if (!(path = talloc_strdup(mem_ctx, subkeypath))) {
402 err = WERR_NOMEM;
403 goto done;
406 while ((end = strchr(path, '\\')) != NULL) {
407 struct registry_key *tmp;
408 enum winreg_CreateAction action;
410 *end = '\0';
412 err = reg_createkey(mem_ctx, key, path,
413 SEC_RIGHTS_ENUM_SUBKEYS, &tmp, &action);
414 if (!W_ERROR_IS_OK(err)) {
415 goto done;
418 if (key != parent) {
419 TALLOC_FREE(key);
422 key = tmp;
423 path = end+1;
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;
436 goto done;
439 if (!W_ERROR_EQUAL(err, WERR_BADFILE)) {
441 * Something but "notfound" has happened, so bail out
443 goto done;
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,
452 &create_parent);
453 if (!W_ERROR_IS_OK(err)) {
454 goto done;
458 * Actually create the subkey
461 if (!(subkeys = TALLOC_ZERO_P(mem_ctx, REGSUBKEY_CTR))) {
462 err = WERR_NOMEM;
463 goto done;
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;
475 goto done;
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;
487 done:
488 TALLOC_FREE(mem_ctx);
489 return err;
493 WERROR reg_deletekey(struct registry_key *parent, const char *path)
495 WERROR err;
496 TALLOC_CTX *mem_ctx;
497 char *name, *end;
498 int num_subkeys;
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))) {
504 err = WERR_NOMEM;
505 goto error;
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)) {
511 goto error;
513 if (!W_ERROR_IS_OK(err = fill_subkey_cache(tmp_key))) {
514 goto error;
516 if (tmp_key->subkeys->num_subkeys > 0) {
517 err = WERR_ACCESS_DENIED;
518 goto error;
521 /* no subkeys - proceed with delete */
522 if ((end = strrchr(name, '\\')) != NULL) {
523 *end = '\0';
525 err = reg_openkey(mem_ctx, parent, name,
526 SEC_RIGHTS_CREATE_SUBKEY, &tmp_key);
527 if (!W_ERROR_IS_OK(err)) {
528 goto error;
531 parent = tmp_key;
532 name = end+1;
535 if (name[0] == '\0') {
536 err = WERR_INVALID_PARAM;
537 goto error;
540 if (!W_ERROR_IS_OK(err = fill_subkey_cache(parent))) {
541 goto error;
544 num_subkeys = parent->subkeys->num_subkeys;
546 if (regsubkey_ctr_delkey(parent->subkeys, name) == num_subkeys) {
547 err = WERR_BADFILE;
548 goto error;
551 if (!store_reg_keys(parent->key, parent->subkeys)) {
552 TALLOC_FREE(parent->subkeys);
553 err = WERR_REG_IO_FAILURE;
554 goto error;
557 err = WERR_OK;
558 error:
559 TALLOC_FREE(mem_ctx);
560 return err;
563 WERROR reg_setvalue(struct registry_key *key, const char *name,
564 const struct registry_value *val)
566 WERROR err;
567 DATA_BLOB value_data;
568 int res;
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))) {
575 return err;
578 err = registry_push_value(key, val, &value_data);
579 if (!W_ERROR_IS_OK(err)) {
580 return 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);
587 if (res == 0) {
588 TALLOC_FREE(key->values);
589 return WERR_NOMEM;
592 if (!store_reg_values(key->key, key->values)) {
593 TALLOC_FREE(key->values);
594 return WERR_REG_IO_FAILURE;
597 return WERR_OK;
600 WERROR reg_deletevalue(struct registry_key *key, const char *name)
602 WERROR err;
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))) {
609 return err;
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;
619 return WERR_OK;
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;
634 char *path, *p;
635 WERROR err;
637 if (!(path = SMB_STRDUP(orig_path))) {
638 return WERR_NOMEM;
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,
649 &hive);
650 if (!W_ERROR_IS_OK(err)) {
651 SAFE_FREE(path);
652 return err;
654 SAFE_FREE(path);
655 *pkey = hive;
656 return WERR_OK;
659 *p = '\0';
661 err = reg_openhive(mem_ctx, path, SEC_RIGHTS_ENUM_SUBKEYS, token,
662 &hive);
663 if (!W_ERROR_IS_OK(err)) {
664 SAFE_FREE(path);
665 return err;
668 err = reg_openkey(mem_ctx, hive, p+1, desired_access, &key);
670 TALLOC_FREE(hive);
671 SAFE_FREE(path);
673 if (!W_ERROR_IS_OK(err)) {
674 return err;
677 *pkey = key;
678 return WERR_OK;
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,
689 const char *path)
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) {
698 werr = WERR_NOMEM;
699 goto done;
702 /* recurse through subkeys first */
703 werr = reg_openkey(mem_ctx, parent, path, REG_KEY_WRITE, &key);
704 if (!W_ERROR_IS_OK(werr)) {
705 goto done;
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)) {
713 goto done;
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)));
719 goto done;
722 /* now delete the actual key */
723 werr = reg_deletekey(parent, path);
725 done:
726 TALLOC_FREE(mem_ctx);
727 return werr;