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