r4132: - Bunch of rather large fixes in the registry
[samba.git] / source4 / lib / registry / common / reg_interface.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Transparent registry backend handling
4    Copyright (C) Jelmer Vernooij                        2003-2004.
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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "dlinklist.h"
23 #include "registry.h"
24
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_REGISTRY
27
28 /* List of available backends */
29 static struct reg_init_function_entry *backends = NULL;
30
31 static struct reg_init_function_entry *reg_find_backend_entry(const char *name);
32
33 /* Register new backend */
34 NTSTATUS registry_register(const void *_hive_ops)  
35 {
36         const struct hive_operations *hive_ops = _hive_ops;
37         struct reg_init_function_entry *entry = backends;
38
39         DEBUG(5,("Attempting to register registry backend %s\n", hive_ops->name));
40
41         /* Check for duplicates */
42         if (reg_find_backend_entry(hive_ops->name)) {
43                 DEBUG(0,("There already is a registry backend registered with the name %s!\n", hive_ops->name));
44                 return NT_STATUS_OBJECT_NAME_COLLISION;
45         }
46
47         entry = talloc_p(NULL, struct reg_init_function_entry);
48         entry->hive_functions = hive_ops;
49
50         DLIST_ADD(backends, entry);
51         DEBUG(5,("Successfully added registry backend '%s'\n", hive_ops->name));
52         return NT_STATUS_OK;
53 }
54
55 /* Find a backend in the list of available backends */
56 static struct reg_init_function_entry *reg_find_backend_entry(const char *name)
57 {
58         struct reg_init_function_entry *entry;
59
60         entry = backends;
61
62         while(entry) {
63                 if (strcmp(entry->hive_functions->name, name) == 0) return entry;
64                 entry = entry->next;
65         }
66
67         return NULL;
68 }
69
70 /* Check whether a certain backend is present */
71 BOOL reg_has_backend(const char *backend)
72 {
73         return reg_find_backend_entry(backend) != NULL?True:False;
74 }
75
76 static struct {
77         uint32 hkey;
78         const char *name;
79 } hkey_names[] = 
80 {
81         {HKEY_CLASSES_ROOT,"HKEY_CLASSES_ROOT" },
82         {HKEY_CURRENT_USER,"HKEY_CURRENT_USER" },
83         {HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE" },
84         {HKEY_PERFORMANCE_DATA, "HKEY_PERFORMANCE_DATA" },
85         {HKEY_USERS, "HKEY_USERS" },
86         {HKEY_CURRENT_CONFIG, "HKEY_CURRENT_CONFIG" },
87         {HKEY_DYN_DATA, "HKEY_DYN_DATA" },
88         {HKEY_PT, "HKEY_PT" },
89         {HKEY_PN, "HKEY_PN" },
90         { 0, NULL }
91 };
92
93 int reg_list_hives(TALLOC_CTX *mem_ctx, char ***hives, uint32_t **hkeys)
94 {
95         int i;
96         *hives = talloc_array_p(mem_ctx, char *, ARRAY_SIZE(hkey_names));
97         *hkeys = talloc_array_p(mem_ctx, uint32_t, ARRAY_SIZE(hkey_names));
98
99         for (i = 0; hkey_names[i].name; i++) {
100                 (*hives)[i] = talloc_strdup(mem_ctx, hkey_names[i].name);
101                 (*hkeys)[i] = hkey_names[i].hkey;
102         }
103
104         return i;
105 }
106
107 const char *reg_get_hkey_name(uint32_t hkey)
108 {
109         int i;
110         for (i = 0; hkey_names[i].name; i++) {
111                 if (hkey_names[i].hkey == hkey) return hkey_names[i].name;
112         }
113
114         return NULL;
115 }
116
117 WERROR reg_get_hive_by_name(struct registry_context *ctx, const char *name, struct registry_key **key)
118 {
119         int i;
120         
121         for (i = 0; hkey_names[i].name; i++) {
122                 if (!strcmp(hkey_names[i].name, name)) return reg_get_hive(ctx, hkey_names[i].hkey, key);
123         }
124
125         DEBUG(1, ("No hive with name '%s'\n", name));
126         
127         return WERR_BADFILE;
128 }
129
130 WERROR reg_close (struct registry_context *ctx)
131 {
132         talloc_destroy(ctx);
133
134         return WERR_OK;
135 }
136
137 WERROR reg_get_hive(struct registry_context *ctx, uint32_t hkey, struct registry_key **key)
138 {
139         WERROR ret = ctx->get_hive(ctx, hkey, key);
140
141         if (W_ERROR_IS_OK(ret)) {
142                 (*key)->name = talloc_strdup(*key, reg_get_hkey_name(hkey));
143                 (*key)->path = ""; 
144         }
145
146         return ret;
147 }
148
149 /* Open a registry file/host/etc */
150 WERROR reg_open_hive(struct registry_context *parent_ctx, const char *backend, const char *location, const char *credentials, struct registry_key **root)
151 {
152         struct registry_hive *ret;
153         struct reg_init_function_entry *entry;
154         WERROR werr;
155
156         entry = reg_find_backend_entry(backend);
157         
158         if (!entry) {
159                 DEBUG(0, ("No such registry backend '%s' loaded!\n", backend));
160                 return WERR_GENERAL_FAILURE;
161         }
162
163         if(!entry->hive_functions || !entry->hive_functions->open_hive) {
164                 return WERR_NOT_SUPPORTED;
165         }
166         
167         ret = talloc_p(parent_ctx, struct registry_hive);
168         ret->location = location?talloc_strdup(ret, location):NULL;
169         ret->functions = entry->hive_functions;
170         ret->backend_data = NULL;
171         ret->reg_ctx = parent_ctx;
172
173         werr = entry->hive_functions->open_hive(ret, &ret->root);
174
175         if(!W_ERROR_IS_OK(werr)) {
176                 return werr;
177         }
178         
179         if(!ret->root) {
180                 DEBUG(0, ("Backend %s didn't provide root key!\n", backend));
181                 return WERR_GENERAL_FAILURE;
182         }
183
184         ret->root->hive = ret;
185         ret->root->name = NULL;
186         ret->root->path = talloc_strdup(ret, "");
187         
188         *root = ret->root;
189
190         return WERR_OK;
191 }
192
193 /* Open a key by name (including the hive name!) */
194 WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result)
195 {
196         struct registry_key *hive;
197         WERROR error;
198         int hivelength;
199         char *hivename;
200
201         if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name;
202         else hivelength = strlen(name);
203
204         hivename = strndup(name, hivelength);
205         error = reg_get_hive_by_name(handle, hivename, &hive);
206         SAFE_FREE(hivename);
207
208         if(!W_ERROR_IS_OK(error)) {
209                 return error;
210         }
211
212         return reg_open_key(mem_ctx, hive, name, result);
213 }
214
215 /* Open a key 
216  * First tries to use the open_key function from the backend
217  * then falls back to get_subkey_by_name and later get_subkey_by_index 
218  */
219 WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, struct registry_key **result)
220 {
221         char *fullname;
222         WERROR error;
223
224         if(!parent) {
225                 DEBUG(0, ("Invalid parent key specified"));
226                 return WERR_INVALID_PARAM;
227         }
228
229         if(!parent->hive->functions->open_key && 
230            (parent->hive->functions->get_subkey_by_name || 
231            parent->hive->functions->get_subkey_by_index)) {
232                 char *orig = strdup(name), 
233                          *curbegin = orig, 
234                          *curend = strchr(orig, '\\');
235                 struct registry_key *curkey = parent;
236
237                 while(curbegin && *curbegin) {
238                         if(curend)*curend = '\0';
239                         error = reg_key_get_subkey_by_name(mem_ctx, curkey, curbegin, &curkey);
240                         if(!W_ERROR_IS_OK(error)) {
241                                 SAFE_FREE(orig);
242                                 return error;
243                         }
244                         if(!curend) break;
245                         curbegin = curend + 1;
246                         curend = strchr(curbegin, '\\');
247                 }
248                 SAFE_FREE(orig);
249
250                 *result = curkey;
251                 
252                 return WERR_OK;
253         }
254
255         if(!parent->hive->functions->open_key) {
256                 DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n"));
257                 return WERR_NOT_SUPPORTED;
258         }
259
260
261         fullname = ((parent->hive->root == parent)?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name));
262
263         error = parent->hive->functions->open_key(mem_ctx, parent->hive, fullname, result);
264
265         if(!W_ERROR_IS_OK(error)) return error;
266                 
267         (*result)->hive = parent->hive;
268         (*result)->path = fullname;
269         (*result)->hive = parent->hive;
270
271         return WERR_OK;
272 }
273
274 WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_value **val)
275 {
276         if(!key) return WERR_INVALID_PARAM;
277
278         if(key->hive->functions->get_value_by_index) {
279                 WERROR status = key->hive->functions->get_value_by_index(mem_ctx, key, idx, val);
280                 if(!W_ERROR_IS_OK(status)) 
281                         return status;
282         } else {
283                 return WERR_NOT_SUPPORTED;
284         }
285         
286         (*val)->parent = key;
287         (*val)->hive = key->hive;
288         return WERR_OK;
289 }
290
291 WERROR reg_key_num_subkeys(struct registry_key *key, int *count)
292 {
293         if(!key) return WERR_INVALID_PARAM;
294         
295         if(key->hive->functions->num_subkeys) {
296                 return key->hive->functions->num_subkeys(key, count);
297         }
298
299         if(key->hive->functions->get_subkey_by_index) {
300                 int i;
301                 WERROR error;
302                 struct registry_key *dest;
303                 TALLOC_CTX *mem_ctx = talloc_init("num_subkeys");
304                 
305                 for(i = 0; W_ERROR_IS_OK(error = key->hive->functions->get_subkey_by_index(mem_ctx, key, i, &dest)); i++);
306                 talloc_destroy(mem_ctx);
307
308                 *count = i;
309                 if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK;
310                 return error;
311         }
312
313         return WERR_NOT_SUPPORTED;
314 }
315
316 WERROR reg_key_num_values(struct registry_key *key, int *count)
317 {
318         
319         if(!key) return WERR_INVALID_PARAM;
320
321         if (key->hive->functions->num_values) {
322                 return key->hive->functions->num_values(key, count);
323         }
324
325         if(key->hive->functions->get_value_by_index) {
326                 int i;
327                 WERROR error;
328                 struct registry_value *dest;
329                 TALLOC_CTX *mem_ctx = talloc_init("num_subkeys");
330                 
331                 for(i = 0; W_ERROR_IS_OK(error = key->hive->functions->get_value_by_index(mem_ctx, key, i, &dest)); i++);
332                 talloc_destroy(mem_ctx);
333
334                 *count = i;
335                 if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK;
336                 return error;
337         }
338
339         return WERR_NOT_SUPPORTED;
340 }
341
342 WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_key **subkey)
343 {
344         if(!key) return WERR_INVALID_PARAM;
345
346         if(key->hive->functions->get_subkey_by_index) {
347                 WERROR status = key->hive->functions->get_subkey_by_index(mem_ctx, key, idx, subkey);
348                 if(!NT_STATUS_IS_OK(status)) return status;
349         } else {
350                 return WERR_NOT_SUPPORTED;
351         }
352
353         if(key->hive->root == key) 
354                 (*subkey)->path = talloc_strdup(mem_ctx, (*subkey)->name);
355         else 
356                 (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name);
357
358         (*subkey)->hive = key->hive;
359         return WERR_OK;;
360 }
361
362 WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *name, struct registry_key **subkey)
363 {
364         int i;
365         WERROR error = WERR_OK;
366
367         if(!key) return WERR_INVALID_PARAM;
368
369         if(key->hive->functions->get_subkey_by_name) {
370                 error = key->hive->functions->get_subkey_by_name(mem_ctx, key,name,subkey);
371         } else if(key->hive->functions->open_key) {
372                 error = key->hive->functions->open_key(mem_ctx, key->hive, talloc_asprintf(mem_ctx, "%s\\%s", key->path, name), subkey);
373         } else if(key->hive->functions->get_subkey_by_index) {
374                 for(i = 0; W_ERROR_IS_OK(error); i++) {
375                         error = reg_key_get_subkey_by_index(mem_ctx, key, i, subkey);
376                         if(W_ERROR_IS_OK(error) && !strcmp((*subkey)->name, name)) {
377                                 return error;
378                         }
379                 }
380         } else {
381                 return WERR_NOT_SUPPORTED;
382         }
383
384         if(!W_ERROR_IS_OK(error)) return error;
385
386         (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name);
387         (*subkey)->hive = key->hive;
388
389         return WERR_OK; 
390 }
391
392 WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *name, struct registry_value **val)
393 {
394         int i;
395         WERROR error = WERR_OK;
396
397         if(!key) return WERR_INVALID_PARAM;
398
399         if(key->hive->functions->get_value_by_name) {
400                 error = key->hive->functions->get_value_by_name(mem_ctx, key,name, val);
401         } else {
402                 for(i = 0; W_ERROR_IS_OK(error); i++) {
403                         error = reg_key_get_value_by_index(mem_ctx, key, i, val);
404                         if(W_ERROR_IS_OK(error) && StrCaseCmp((*val)->name, name)) {
405                                 break;
406                         }
407                 }
408         }
409
410         if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
411                 return error;
412         
413         (*val)->parent = key;
414         (*val)->hive = key->hive;
415         
416         return WERR_OK;
417 }
418
419 WERROR reg_key_del(struct registry_key *key)
420 {
421         WERROR error;
422         if(!key) return WERR_INVALID_PARAM;
423         
424         
425         if(!key->hive->functions->del_key)
426                 return WERR_NOT_SUPPORTED;
427         
428         error = key->hive->functions->del_key(key);
429         if(!W_ERROR_IS_OK(error)) return error;
430
431         return WERR_OK;
432 }
433
434 WERROR reg_key_del_recursive(struct registry_key *key)
435 {
436         WERROR error = WERR_OK;
437         int i;
438
439         TALLOC_CTX *mem_ctx = talloc_init("del_recursive");
440         
441         /* Delete all values for specified key */
442         for(i = 0; W_ERROR_IS_OK(error); i++) {
443                 struct registry_value *val;
444                 error = reg_key_get_value_by_index(mem_ctx, key, i, &val);
445                 if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) 
446                 {
447                         talloc_destroy(mem_ctx);                        
448                         return error;
449                 }
450
451                 if(W_ERROR_IS_OK(error)) {
452                         error = reg_del_value(val);
453                         if(!W_ERROR_IS_OK(error)) {
454                                 talloc_destroy(mem_ctx);
455                                 return error;
456                         }
457                 }
458         }
459
460         error = WERR_OK;
461
462         /* Delete all keys below this one */
463         for(i = 0; W_ERROR_IS_OK(error); i++) {
464                 struct registry_key *subkey;
465
466                 error = reg_key_get_subkey_by_index(mem_ctx, key, i, &subkey);
467                 if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; }
468
469                 error = reg_key_del_recursive(subkey);
470                 if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; }
471         }
472
473         talloc_destroy(mem_ctx);
474         return reg_key_del(key);
475 }
476
477 WERROR reg_key_add_name_recursive_abs(struct registry_context *handle, const char *name)
478 {
479         struct registry_key *hive;
480         WERROR error;
481         int hivelength;
482         char *hivename;
483
484         if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name;
485         else hivelength = strlen(name);
486
487         hivename = strndup(name, hivelength);
488         error = reg_get_hive_by_name(handle, hivename, &hive);
489         SAFE_FREE(hivename);
490
491         if(!W_ERROR_IS_OK(error)) return error;
492
493         return reg_key_add_name_recursive(hive, name);
494 }
495
496 WERROR reg_key_add_name_recursive(struct registry_key *parent, const char *path)
497 {
498         struct registry_key *cur, *prevcur = parent;
499         WERROR error = WERR_OK;
500         char *dups, *begin, *end;
501         TALLOC_CTX *mem_ctx = talloc_init("add_recursive");
502
503         begin = dups = strdup(path);
504
505         while(1) { 
506                 end = strchr(begin, '\\');
507                 if(end) *end = '\0';
508                 
509                 error = reg_key_get_subkey_by_name(mem_ctx, prevcur, begin, &cur);
510
511                 /* Key is not there, add it */
512                 if(W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) {
513                         error = reg_key_add_name(mem_ctx, prevcur, begin, 0, NULL, &cur);
514                         if(!W_ERROR_IS_OK(error)) break;
515                 }
516
517                 if(!W_ERROR_IS_OK(error)) {
518                         if(end) *end = '\\';
519                         break;
520                 }
521                 
522                 if(!end) { 
523                         error = WERR_OK; 
524                         break; 
525                 }
526
527                 *end = '\\';
528                 begin = end+1;
529                 prevcur = cur;
530         }
531         SAFE_FREE(dups);
532         talloc_destroy(mem_ctx);
533         return error;
534 }
535
536 WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, struct registry_key **newkey)
537 {
538         WERROR error;
539         
540         if (!parent) return WERR_INVALID_PARAM;
541         
542         if (!parent->hive->functions->add_key) {
543                 DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->hive->functions->name));
544                 return WERR_NOT_SUPPORTED;
545         }
546
547         error = parent->hive->functions->add_key(mem_ctx, parent, name, access_mask, desc, newkey);
548
549         if(!W_ERROR_IS_OK(error)) return error;
550         
551         (*newkey)->hive = parent->hive;
552         (*newkey)->backend_data = talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name);
553
554         return WERR_OK;
555 }
556
557 WERROR reg_val_set(struct registry_key *key, const char *value, int type, void *data, int len)
558 {
559         /* A 'real' set function has preference */
560         if (key->hive->functions->set_value) 
561                 return key->hive->functions->set_value(key, value, type, data, len);
562
563         DEBUG(1, ("Backend '%s' doesn't support method set_value\n", key->hive->functions->name));
564         return WERR_NOT_SUPPORTED;
565 }
566
567
568
569 WERROR reg_del_value(struct registry_value *val)
570 {
571         WERROR ret = WERR_OK;
572         if(!val->hive->functions->del_value)
573                 return WERR_NOT_SUPPORTED;
574
575         ret = val->hive->functions->del_value(val);
576
577         if(!W_ERROR_IS_OK(ret)) return ret;
578
579         return ret;
580 }
581
582 WERROR reg_save (struct registry_context *ctx, const char *location)
583 {
584         return WERR_NOT_SUPPORTED;
585 }
586
587 WERROR reg_key_get_parent(TALLOC_CTX *mem_ctx, struct registry_key *key, struct registry_key **parent)
588 {
589         char *parent_name;
590         char *last;
591         struct registry_key *root = NULL;
592         WERROR error;
593
594         parent_name = strdup(key->path);
595         last = strrchr(parent_name, '\\');
596
597         if(!last) {
598                 SAFE_FREE(parent_name);
599                 return WERR_FOOBAR;
600         }
601         *last = '\0';
602
603         error = reg_open_key(mem_ctx, root, parent_name, parent);
604         SAFE_FREE(parent_name);
605         return error;
606 }
607
608 WERROR reg_key_flush(struct registry_key *key)
609 {
610         if (!key) {
611                 return WERR_INVALID_PARAM;
612         }
613         
614         if (key->hive->functions->flush_key) {
615                 return key->hive->functions->flush_key(key);
616         }
617         
618         /* No need for flushing, apparently */
619         return WERR_OK;
620 }
621
622 WERROR reg_key_subkeysizes(struct registry_key *key, uint32 *max_subkeylen, uint32 *max_subkeysize)
623 {
624         int i = 0; 
625         struct registry_key *subkey;
626         WERROR error;
627         TALLOC_CTX *mem_ctx = talloc_init("subkeysize");
628
629         *max_subkeylen = *max_subkeysize = 0;
630
631         do {
632                 error = reg_key_get_subkey_by_index(mem_ctx, key, i, &subkey);
633
634                 if (W_ERROR_IS_OK(error)) {
635                         *max_subkeysize = MAX(*max_subkeysize, 0xFF);
636                         *max_subkeylen = MAX(*max_subkeylen, strlen(subkey->name));
637                 }
638
639                 i++;
640         } while (W_ERROR_IS_OK(error));
641
642         talloc_destroy(mem_ctx);
643
644         return WERR_OK;
645 }
646
647 WERROR reg_key_valuesizes(struct registry_key *key, uint32 *max_valnamelen, uint32 *max_valbufsize)
648 {
649         int i = 0; 
650         struct registry_value *value;
651         WERROR error;
652         TALLOC_CTX *mem_ctx = talloc_init("subkeysize");
653
654         *max_valnamelen = *max_valbufsize = 0;
655
656         do {
657                 error = reg_key_get_value_by_index(mem_ctx, key, i, &value);
658
659                 if (W_ERROR_IS_OK(error)) {
660                         if (value->name) {
661                                 *max_valnamelen = MAX(*max_valnamelen, strlen(value->name));
662                         }
663                         *max_valbufsize = MAX(*max_valbufsize, value->data_len);
664                 }
665
666                 i++;
667         } while (W_ERROR_IS_OK(error));
668
669         talloc_destroy(mem_ctx);
670
671         return WERR_OK;
672 }