r24418: Adding reg_deleteallvalues().
[obnox/samba-ctdb.git] / source3 / registry / reg_api.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Virtual Windows Registry Layer
4  *  Copyright (C) Volker Lendecke 2006
5  *
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.
10  *  
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.
15  *  
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/>.
18  */
19
20 /* Attempt to wrap the existing API in a more winreg.idl-like way */
21
22 #include "includes.h"
23
24 static WERROR fill_value_cache(struct registry_key *key)
25 {
26         if (key->values != NULL) {
27                 return WERR_OK;
28         }
29
30         if (!(key->values = TALLOC_ZERO_P(key, REGVAL_CTR))) {
31                 return WERR_NOMEM;
32         }
33         if (fetch_reg_values(key->key, key->values) == -1) {
34                 TALLOC_FREE(key->values);
35                 return WERR_BADFILE;
36         }
37
38         return WERR_OK;
39 }
40
41 static WERROR fill_subkey_cache(struct registry_key *key)
42 {
43         if (key->subkeys != NULL) {
44                 return WERR_OK;
45         }
46
47         if (!(key->subkeys = TALLOC_ZERO_P(key, REGSUBKEY_CTR))) {
48                 return WERR_NOMEM;
49         }
50
51         if (fetch_reg_keys(key->key, key->subkeys) == -1) {
52                 TALLOC_FREE(key->subkeys);
53                 return WERR_NO_MORE_ITEMS;
54         }
55
56         return WERR_OK;
57 }
58
59 static int regkey_destructor(REGISTRY_KEY *key)
60 {
61         return regdb_close();
62 }
63
64 static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx, 
65                                    struct registry_key *parent,
66                                    const char *name,
67                                    const struct nt_user_token *token,
68                                    uint32 access_desired,
69                                    struct registry_key **pregkey)
70 {
71         WERROR          result = WERR_OK;
72         struct registry_key *regkey;
73         REGISTRY_KEY *key;
74         REGSUBKEY_CTR   *subkeys = NULL;
75
76         DEBUG(7,("regkey_open_onelevel: name = [%s]\n", name));
77
78         SMB_ASSERT(strchr(name, '\\') == NULL);
79
80         if (!(regkey = TALLOC_ZERO_P(mem_ctx, struct registry_key)) ||
81             !(regkey->token = dup_nt_token(regkey, token)) ||
82             !(regkey->key = TALLOC_ZERO_P(regkey, REGISTRY_KEY))) {
83                 result = WERR_NOMEM;
84                 goto done;
85         }
86
87         if ( !(W_ERROR_IS_OK(result = regdb_open())) ) {
88                 goto done;
89         }
90
91         key = regkey->key;
92         talloc_set_destructor(key, regkey_destructor);
93                 
94         /* initialization */
95         
96         key->type = REG_KEY_GENERIC;
97
98         if (name[0] == '\0') {
99                 /*
100                  * Open a copy of the parent key
101                  */
102                 if (!parent) {
103                         result = WERR_BADFILE;
104                         goto done;
105                 }
106                 key->name = talloc_strdup(key, parent->key->name);
107         }
108         else {
109                 /*
110                  * Normal subkey open
111                  */
112                 key->name = talloc_asprintf(key, "%s%s%s",
113                                             parent ? parent->key->name : "",
114                                             parent ? "\\": "",
115                                             name);
116         }
117
118         if (key->name == NULL) {
119                 result = WERR_NOMEM;
120                 goto done;
121         }
122
123         /* Tag this as a Performance Counter Key */
124
125         if( StrnCaseCmp(key->name, KEY_HKPD, strlen(KEY_HKPD)) == 0 )
126                 key->type = REG_KEY_HKPD;
127         
128         /* Look up the table of registry I/O operations */
129
130         if ( !(key->hook = reghook_cache_find( key->name )) ) {
131                 DEBUG(0,("reg_open_onelevel: Failed to assigned a "
132                          "REGISTRY_HOOK to [%s]\n", key->name ));
133                 result = WERR_BADFILE;
134                 goto done;
135         }
136         
137         /* check if the path really exists; failed is indicated by -1 */
138         /* if the subkey count failed, bail out */
139
140         if ( !(subkeys = TALLOC_ZERO_P( key, REGSUBKEY_CTR )) ) {
141                 result = WERR_NOMEM;
142                 goto done;
143         }
144
145         if ( fetch_reg_keys( key, subkeys ) == -1 )  {
146                 result = WERR_BADFILE;
147                 goto done;
148         }
149         
150         TALLOC_FREE( subkeys );
151
152         if ( !regkey_access_check( key, access_desired, &key->access_granted,
153                                    token ) ) {
154                 result = WERR_ACCESS_DENIED;
155                 goto done;
156         }
157
158         *pregkey = regkey;
159         result = WERR_OK;
160         
161 done:
162         if ( !W_ERROR_IS_OK(result) ) {
163                 TALLOC_FREE(regkey);
164         }
165
166         return result;
167 }
168
169 WERROR reg_openhive(TALLOC_CTX *mem_ctx, const char *hive,
170                     uint32 desired_access,
171                     const struct nt_user_token *token,
172                     struct registry_key **pkey)
173 {
174         SMB_ASSERT(hive != NULL);
175         SMB_ASSERT(hive[0] != '\0');
176         SMB_ASSERT(strchr(hive, '\\') == NULL);
177
178         return regkey_open_onelevel(mem_ctx, NULL, hive, token, desired_access,
179                                     pkey);
180 }
181
182 WERROR reg_openkey(TALLOC_CTX *mem_ctx, struct registry_key *parent,
183                    const char *name, uint32 desired_access,
184                    struct registry_key **pkey)
185 {
186         struct registry_key *direct_parent = parent;
187         WERROR err;
188         char *p, *path, *to_free;
189         size_t len;
190
191         if (!(path = SMB_STRDUP(name))) {
192                 return WERR_NOMEM;
193         }
194         to_free = path;
195
196         len = strlen(path);
197
198         if ((len > 0) && (path[len-1] == '\\')) {
199                 path[len-1] = '\0';
200         }
201
202         while ((p = strchr(path, '\\')) != NULL) {
203                 char *name_component;
204                 struct registry_key *tmp;
205
206                 if (!(name_component = SMB_STRNDUP(path, (p - path)))) {
207                         err = WERR_NOMEM;
208                         goto error;
209                 }
210
211                 err = regkey_open_onelevel(mem_ctx, direct_parent,
212                                            name_component, parent->token,
213                                            SEC_RIGHTS_ENUM_SUBKEYS, &tmp);
214                 SAFE_FREE(name_component);
215
216                 if (!W_ERROR_IS_OK(err)) {
217                         goto error;
218                 }
219                 if (direct_parent != parent) {
220                         TALLOC_FREE(direct_parent);
221                 }
222
223                 direct_parent = tmp;
224                 path = p+1;
225         }
226
227         err = regkey_open_onelevel(mem_ctx, direct_parent, path, parent->token,
228                                    desired_access, pkey);
229  error:
230         if (direct_parent != parent) {
231                 TALLOC_FREE(direct_parent);
232         }
233         SAFE_FREE(to_free);
234         return err;
235 }
236
237 WERROR reg_enumkey(TALLOC_CTX *mem_ctx, struct registry_key *key,
238                    uint32 idx, char **name, NTTIME *last_write_time)
239 {
240         WERROR err;
241
242         if (!(key->key->access_granted & SEC_RIGHTS_ENUM_SUBKEYS)) {
243                 return WERR_ACCESS_DENIED;
244         }
245
246         if (!W_ERROR_IS_OK(err = fill_subkey_cache(key))) {
247                 return err;
248         }
249
250         if (idx >= key->subkeys->num_subkeys) {
251                 return WERR_NO_MORE_ITEMS;
252         }
253
254         if (!(*name = talloc_strdup(mem_ctx, key->subkeys->subkeys[idx]))) {
255                 return WERR_NOMEM;
256         }
257
258         if (last_write_time) {
259                 *last_write_time = 0;
260         }
261
262         return WERR_OK;
263 }
264
265 WERROR reg_enumvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
266                      uint32 idx, char **pname, struct registry_value **pval)
267 {
268         struct registry_value *val;
269         WERROR err;
270
271         if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
272                 return WERR_ACCESS_DENIED;
273         }
274
275         if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
276                 return err;
277         }
278
279         if (idx >= key->values->num_values) {
280                 return WERR_NO_MORE_ITEMS;
281         }
282
283         err = registry_pull_value(mem_ctx, &val,
284                                   key->values->values[idx]->type,
285                                   key->values->values[idx]->data_p,
286                                   key->values->values[idx]->size,
287                                   key->values->values[idx]->size);
288         if (!W_ERROR_IS_OK(err)) {
289                 return err;
290         }
291
292         if (pname
293             && !(*pname = talloc_strdup(
294                          mem_ctx, key->values->values[idx]->valuename))) {
295                 SAFE_FREE(val);
296                 return WERR_NOMEM;
297         }
298                 
299         *pval = val;
300         return WERR_OK;
301 }
302
303 WERROR reg_queryvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
304                       const char *name, struct registry_value **pval)
305 {
306         WERROR err;
307         uint32 i;
308
309         if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
310                 return WERR_ACCESS_DENIED;
311         }
312
313         if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
314                 return err;
315         }
316
317         for (i=0; i<key->values->num_values; i++) {
318                 if (strequal(key->values->values[i]->valuename, name)) {
319                         return reg_enumvalue(mem_ctx, key, i, NULL, pval);
320                 }
321         }
322
323         return WERR_BADFILE;
324 }
325
326 WERROR reg_queryinfokey(struct registry_key *key, uint32_t *num_subkeys,
327                         uint32_t *max_subkeylen, uint32_t *max_subkeysize, 
328                         uint32_t *num_values, uint32_t *max_valnamelen, 
329                         uint32_t *max_valbufsize, uint32_t *secdescsize,
330                         NTTIME *last_changed_time)
331 {
332         uint32 i, max_size;
333         size_t max_len;
334         TALLOC_CTX *mem_ctx;
335         WERROR err;
336         struct security_descriptor *secdesc;
337
338         if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
339                 return WERR_ACCESS_DENIED;
340         }
341
342         if (!W_ERROR_IS_OK(fill_subkey_cache(key)) ||
343             !W_ERROR_IS_OK(fill_value_cache(key))) {
344                 return WERR_BADFILE;
345         }
346
347         max_len = 0;
348         for (i=0; i<key->subkeys->num_subkeys; i++) {
349                 max_len = MAX(max_len, strlen(key->subkeys->subkeys[i]));
350         }
351
352         *num_subkeys = key->subkeys->num_subkeys;
353         *max_subkeylen = max_len;
354         *max_subkeysize = 0;    /* Class length? */
355
356         max_len = 0;
357         max_size = 0;
358         for (i=0; i<key->values->num_values; i++) {
359                 max_len = MAX(max_len,
360                               strlen(key->values->values[i]->valuename));
361                 max_size = MAX(max_size, key->values->values[i]->size);
362         }
363
364         *num_values = key->values->num_values;
365         *max_valnamelen = max_len;
366         *max_valbufsize = max_size;
367
368         if (!(mem_ctx = talloc_new(key))) {
369                 return WERR_NOMEM;
370         }
371
372         err = regkey_get_secdesc(mem_ctx, key->key, &secdesc);
373         if (!W_ERROR_IS_OK(err)) {
374                 TALLOC_FREE(mem_ctx);
375                 return err;
376         }
377
378         *secdescsize = sec_desc_size(secdesc);
379         TALLOC_FREE(mem_ctx);
380
381         *last_changed_time = 0;
382
383         return WERR_OK;
384 }
385
386 WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
387                      const char *subkeypath, uint32 desired_access,
388                      struct registry_key **pkey,
389                      enum winreg_CreateAction *paction)
390 {
391         struct registry_key *key = parent;
392         struct registry_key *create_parent;
393         TALLOC_CTX *mem_ctx;
394         char *path, *end;
395         WERROR err;
396         REGSUBKEY_CTR *subkeys;
397
398         if (!(mem_ctx = talloc_new(ctx))) return WERR_NOMEM;
399
400         if (!(path = talloc_strdup(mem_ctx, subkeypath))) {
401                 err = WERR_NOMEM;
402                 goto done;
403         }
404
405         while ((end = strchr(path, '\\')) != NULL) {
406                 struct registry_key *tmp;
407                 enum winreg_CreateAction action;
408
409                 *end = '\0';
410
411                 err = reg_createkey(mem_ctx, key, path,
412                                     SEC_RIGHTS_ENUM_SUBKEYS, &tmp, &action);
413                 if (!W_ERROR_IS_OK(err)) {
414                         goto done;
415                 }
416
417                 if (key != parent) {
418                         TALLOC_FREE(key);
419                 }
420
421                 key = tmp;
422                 path = end+1;
423         }
424
425         /*
426          * At this point, "path" contains the one-element subkey of "key". We
427          * can try to open it.
428          */
429
430         err = reg_openkey(ctx, key, path, desired_access, pkey);
431         if (W_ERROR_IS_OK(err)) {
432                 if (paction != NULL) {
433                         *paction = REG_OPENED_EXISTING_KEY;
434                 }
435                 goto done;
436         }
437
438         if (!W_ERROR_EQUAL(err, WERR_BADFILE)) {
439                 /*
440                  * Something but "notfound" has happened, so bail out
441                  */
442                 goto done;
443         }
444
445         /*
446          * We have to make a copy of the current key, as we opened it only
447          * with ENUM_SUBKEY access.
448          */
449
450         err = reg_openkey(mem_ctx, key, "", SEC_RIGHTS_CREATE_SUBKEY,
451                           &create_parent);
452         if (!W_ERROR_IS_OK(err)) {
453                 goto done;
454         }
455
456         /*
457          * Actually create the subkey
458          */
459
460         if (!(subkeys = TALLOC_ZERO_P(mem_ctx, REGSUBKEY_CTR))) {
461                 err = WERR_NOMEM;
462                 goto done;
463         }
464
465         err = fill_subkey_cache(create_parent);
466         if (!W_ERROR_IS_OK(err)) goto done;
467
468         err = regsubkey_ctr_addkey(create_parent->subkeys, path);
469         if (!W_ERROR_IS_OK(err)) goto done;
470
471         if (!store_reg_keys(create_parent->key, create_parent->subkeys)) {
472                 TALLOC_FREE(create_parent->subkeys);
473                 err = WERR_REG_IO_FAILURE;
474                 goto done;
475         }
476
477         /*
478          * Now open the newly created key
479          */
480
481         err = reg_openkey(ctx, create_parent, path, desired_access, pkey);
482         if (W_ERROR_IS_OK(err) && (paction != NULL)) {
483                 *paction = REG_CREATED_NEW_KEY;
484         }
485
486  done:
487         TALLOC_FREE(mem_ctx);
488         return err;
489 }
490                      
491
492 WERROR reg_deletekey(struct registry_key *parent, const char *path)
493 {
494         WERROR err;
495         TALLOC_CTX *mem_ctx;
496         char *name, *end;
497         int num_subkeys;
498         struct registry_key *tmp_key;
499
500         if (!(mem_ctx = talloc_init("reg_createkey"))) return WERR_NOMEM;
501
502         if (!(name = talloc_strdup(mem_ctx, path))) {
503                 err = WERR_NOMEM;
504                 goto error;
505         }
506
507         /* check if the key has subkeys */
508         err = reg_openkey(mem_ctx, parent, name, REG_KEY_READ, &tmp_key);
509         if (!W_ERROR_IS_OK(err)) {
510                 goto error;
511         }
512         if (!W_ERROR_IS_OK(err = fill_subkey_cache(tmp_key))) {
513                 goto error;
514         }
515         if (tmp_key->subkeys->num_subkeys > 0) {
516                 err = WERR_ACCESS_DENIED;
517                 goto error;
518         }
519
520         /* no subkeys - proceed with delete */
521         if ((end = strrchr(name, '\\')) != NULL) {
522                 *end = '\0';
523
524                 err = reg_openkey(mem_ctx, parent, name,
525                                   SEC_RIGHTS_CREATE_SUBKEY, &tmp_key);
526                 if (!W_ERROR_IS_OK(err)) {
527                         goto error;
528                 }
529
530                 parent = tmp_key;
531                 name = end+1;
532         }
533
534         if (name[0] == '\0') {
535                 err = WERR_INVALID_PARAM;
536                 goto error;
537         }
538
539         if (!W_ERROR_IS_OK(err = fill_subkey_cache(parent))) {
540                 goto error;
541         }
542
543         num_subkeys = parent->subkeys->num_subkeys;
544
545         if (regsubkey_ctr_delkey(parent->subkeys, name) == num_subkeys) {
546                 err = WERR_BADFILE;
547                 goto error;
548         }
549
550         if (!store_reg_keys(parent->key, parent->subkeys)) {
551                 TALLOC_FREE(parent->subkeys);
552                 err = WERR_REG_IO_FAILURE;
553                 goto error;
554         }
555
556         err = WERR_OK;
557  error:
558         TALLOC_FREE(mem_ctx);
559         return err;
560 }
561
562 WERROR reg_setvalue(struct registry_key *key, const char *name,
563                     const struct registry_value *val)
564 {
565         WERROR err;
566         DATA_BLOB value_data;
567         int res;
568
569         if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
570                 return WERR_ACCESS_DENIED;
571         }
572
573         if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
574                 return err;
575         }
576
577         err = registry_push_value(key, val, &value_data);
578         if (!W_ERROR_IS_OK(err)) {
579                 return err;
580         }
581
582         res = regval_ctr_addvalue(key->values, name, val->type,
583                                   (char *)value_data.data, value_data.length);
584         TALLOC_FREE(value_data.data);
585
586         if (res == 0) {
587                 TALLOC_FREE(key->values);
588                 return WERR_NOMEM;
589         }
590
591         if (!store_reg_values(key->key, key->values)) {
592                 TALLOC_FREE(key->values);
593                 return WERR_REG_IO_FAILURE;
594         }
595
596         return WERR_OK;
597 }
598
599 WERROR reg_deletevalue(struct registry_key *key, const char *name)
600 {
601         WERROR err;
602
603         if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
604                 return WERR_ACCESS_DENIED;
605         }
606
607         if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
608                 return err;
609         }
610
611         regval_ctr_delvalue(key->values, name);
612
613         if (!store_reg_values(key->key, key->values)) {
614                 TALLOC_FREE(key->values);
615                 return WERR_REG_IO_FAILURE;
616         }
617
618         return WERR_OK;
619 }
620
621 WERROR reg_deleteallvalues(struct registry_key *key)
622 {
623         WERROR err;
624         int i;
625
626         if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
627                 return WERR_ACCESS_DENIED;
628         }
629
630         if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
631                 return err;
632         }
633
634         for (i=0; i<key->values->num_values; i++) {
635                 regval_ctr_delvalue(key->values, key->values->values[i]->valuename);
636         }
637
638         if (!store_reg_values(key->key, key->values)) {
639                 TALLOC_FREE(key->values);
640                 return WERR_REG_IO_FAILURE;
641         }
642
643         return WERR_OK;
644 }
645
646 /*
647  * Utility function to open a complete registry path including the hive
648  * prefix. This should become the replacement function for
649  * regkey_open_internal.
650  */
651
652 WERROR reg_open_path(TALLOC_CTX *mem_ctx, const char *orig_path,
653                      uint32 desired_access, const struct nt_user_token *token,
654                      struct registry_key **pkey)
655 {
656         struct registry_key *hive, *key;
657         char *path, *p;
658         WERROR err;
659
660         if (!(path = SMB_STRDUP(orig_path))) {
661                 return WERR_NOMEM;
662         }
663
664         p = strchr(path, '\\');
665
666         if ((p == NULL) || (p[1] == '\0')) {
667                 /*
668                  * No key behind the hive, just return the hive
669                  */
670
671                 err = reg_openhive(mem_ctx, path, desired_access, token,
672                                    &hive);
673                 if (!W_ERROR_IS_OK(err)) {
674                         SAFE_FREE(path);
675                         return err;
676                 }
677                 SAFE_FREE(path);
678                 *pkey = hive;
679                 return WERR_OK;
680         }
681
682         *p = '\0';
683
684         err = reg_openhive(mem_ctx, path, SEC_RIGHTS_ENUM_SUBKEYS, token,
685                            &hive);
686         if (!W_ERROR_IS_OK(err)) {
687                 SAFE_FREE(path);
688                 return err;
689         }
690
691         err = reg_openkey(mem_ctx, hive, p+1, desired_access, &key);
692
693         TALLOC_FREE(hive);
694         SAFE_FREE(path);
695
696         if (!W_ERROR_IS_OK(err)) {
697                 return err;
698         }
699
700         *pkey = key;
701         return WERR_OK;
702 }
703
704
705 /*
706  * Utility function to delete a registry key with all its subkeys. 
707  * Note that reg_deletekey returns ACCESS_DENIED when called on a 
708  * key that has subkeys.
709  */
710 WERROR reg_deletekey_recursive(TALLOC_CTX *ctx,
711                                struct registry_key *parent, 
712                                const char *path)
713 {
714         TALLOC_CTX *mem_ctx = NULL;
715         WERROR werr = WERR_OK;
716         struct registry_key *key;
717         char *subkey_name = NULL;
718
719         mem_ctx = talloc_new(ctx);
720         if (mem_ctx == NULL) {
721                 werr = WERR_NOMEM;
722                 goto done;
723         }
724
725         /* recurse through subkeys first */
726         werr = reg_openkey(mem_ctx, parent, path, REG_KEY_WRITE, &key);
727         if (!W_ERROR_IS_OK(werr)) {
728                 goto done;
729         }
730
731         while (W_ERROR_IS_OK(werr = reg_enumkey(mem_ctx, key, 0,
732                                                 &subkey_name, NULL))) 
733         {
734                 werr = reg_deletekey_recursive(mem_ctx, key, subkey_name);
735                 if (!W_ERROR_IS_OK(werr)) {
736                         goto done;
737                 }
738         }
739         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
740                 DEBUG(1, ("reg_deletekey_recursive: Error enumerating "
741                           "subkeys: %s\n", dos_errstr(werr)));
742                 goto done;
743         }
744
745         /* now delete the actual key */
746         werr = reg_deletekey(parent, path);
747         
748 done:
749         TALLOC_FREE(mem_ctx);
750         return werr;
751 }