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