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