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