r25417: Use DBGC_REGISTRY class.
[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 = sec_desc_size(secdesc);
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;
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, &tmp_key);
512         if (!W_ERROR_IS_OK(err)) {
513                 goto error;
514         }
515         if (!W_ERROR_IS_OK(err = fill_subkey_cache(tmp_key))) {
516                 goto error;
517         }
518         if (tmp_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         err = WERR_OK;
560  error:
561         TALLOC_FREE(mem_ctx);
562         return err;
563 }
564
565 WERROR reg_setvalue(struct registry_key *key, const char *name,
566                     const struct registry_value *val)
567 {
568         WERROR err;
569         DATA_BLOB value_data;
570         int res;
571
572         if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
573                 return WERR_ACCESS_DENIED;
574         }
575
576         if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
577                 return err;
578         }
579
580         err = registry_push_value(key, val, &value_data);
581         if (!W_ERROR_IS_OK(err)) {
582                 return err;
583         }
584
585         res = regval_ctr_addvalue(key->values, name, val->type,
586                                   (char *)value_data.data, value_data.length);
587         TALLOC_FREE(value_data.data);
588
589         if (res == 0) {
590                 TALLOC_FREE(key->values);
591                 return WERR_NOMEM;
592         }
593
594         if (!store_reg_values(key->key, key->values)) {
595                 TALLOC_FREE(key->values);
596                 return WERR_REG_IO_FAILURE;
597         }
598
599         return WERR_OK;
600 }
601
602 WERROR reg_deletevalue(struct registry_key *key, const char *name)
603 {
604         WERROR err;
605
606         if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
607                 return WERR_ACCESS_DENIED;
608         }
609
610         if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
611                 return err;
612         }
613
614         regval_ctr_delvalue(key->values, name);
615
616         if (!store_reg_values(key->key, key->values)) {
617                 TALLOC_FREE(key->values);
618                 return WERR_REG_IO_FAILURE;
619         }
620
621         return WERR_OK;
622 }
623
624 WERROR reg_deleteallvalues(struct registry_key *key)
625 {
626         WERROR err;
627         int i;
628
629         if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
630                 return WERR_ACCESS_DENIED;
631         }
632
633         if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
634                 return err;
635         }
636
637         for (i=0; i<key->values->num_values; i++) {
638                 regval_ctr_delvalue(key->values, key->values->values[i]->valuename);
639         }
640
641         if (!store_reg_values(key->key, key->values)) {
642                 TALLOC_FREE(key->values);
643                 return WERR_REG_IO_FAILURE;
644         }
645
646         return WERR_OK;
647 }
648
649 /*
650  * Utility function to open a complete registry path including the hive
651  * prefix. This should become the replacement function for
652  * regkey_open_internal.
653  */
654
655 WERROR reg_open_path(TALLOC_CTX *mem_ctx, const char *orig_path,
656                      uint32 desired_access, const struct nt_user_token *token,
657                      struct registry_key **pkey)
658 {
659         struct registry_key *hive, *key;
660         char *path, *p;
661         WERROR err;
662
663         if (!(path = SMB_STRDUP(orig_path))) {
664                 return WERR_NOMEM;
665         }
666
667         p = strchr(path, '\\');
668
669         if ((p == NULL) || (p[1] == '\0')) {
670                 /*
671                  * No key behind the hive, just return the hive
672                  */
673
674                 err = reg_openhive(mem_ctx, path, desired_access, token,
675                                    &hive);
676                 if (!W_ERROR_IS_OK(err)) {
677                         SAFE_FREE(path);
678                         return err;
679                 }
680                 SAFE_FREE(path);
681                 *pkey = hive;
682                 return WERR_OK;
683         }
684
685         *p = '\0';
686
687         err = reg_openhive(mem_ctx, path, SEC_RIGHTS_ENUM_SUBKEYS, token,
688                            &hive);
689         if (!W_ERROR_IS_OK(err)) {
690                 SAFE_FREE(path);
691                 return err;
692         }
693
694         err = reg_openkey(mem_ctx, hive, p+1, desired_access, &key);
695
696         TALLOC_FREE(hive);
697         SAFE_FREE(path);
698
699         if (!W_ERROR_IS_OK(err)) {
700                 return err;
701         }
702
703         *pkey = key;
704         return WERR_OK;
705 }
706
707 /*
708  * Utility function to delete a registry key with all its subkeys. 
709  * Note that reg_deletekey returns ACCESS_DENIED when called on a 
710  * key that has subkeys.
711  */
712 WERROR reg_deletekey_recursive_internal(TALLOC_CTX *ctx,
713                                         struct registry_key *parent,
714                                         const char *path,
715                                         BOOL del_key)
716 {
717         TALLOC_CTX *mem_ctx = NULL;
718         WERROR werr = WERR_OK;
719         struct registry_key *key;
720         char *subkey_name = NULL;
721
722         mem_ctx = talloc_new(ctx);
723         if (mem_ctx == NULL) {
724                 werr = WERR_NOMEM;
725                 goto done;
726         }
727
728         /* recurse through subkeys first */
729         werr = reg_openkey(mem_ctx, parent, path, REG_KEY_WRITE, &key);
730         if (!W_ERROR_IS_OK(werr)) {
731                 goto done;
732         }
733
734         while (W_ERROR_IS_OK(werr = reg_enumkey(mem_ctx, key, 0,
735                                                 &subkey_name, NULL))) 
736         {
737                 werr = reg_deletekey_recursive_internal(mem_ctx, key,
738                                                         subkey_name,
739                                                         True);
740                 if (!W_ERROR_IS_OK(werr)) {
741                         goto done;
742                 }
743         }
744         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
745                 DEBUG(1, ("reg_deletekey_recursive_internal: "
746                           "Error enumerating subkeys: %s\n",
747                           dos_errstr(werr)));
748                 goto done;
749         }
750
751         werr = WERR_OK;
752
753         if (del_key) {
754                 /* now delete the actual key */
755                 werr = reg_deletekey(parent, path);
756         }
757
758 done:
759         TALLOC_FREE(mem_ctx);
760         return werr;
761 }
762
763 WERROR reg_deletekey_recursive(TALLOC_CTX *ctx,
764                                struct registry_key *parent,
765                                const char *path)
766 {
767         return reg_deletekey_recursive_internal(ctx, parent, path, True);
768 }
769
770 WERROR reg_deletesubkeys_recursive(TALLOC_CTX *ctx,
771                                    struct registry_key *parent,
772                                    const char *path)
773 {
774         return reg_deletekey_recursive_internal(ctx, parent, path, False);
775 }