registry: create and use shared libcli/registry/util_reg.h header.
[samba.git] / source3 / lib / smbconf / smbconf_reg.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  libsmbconf - Samba configuration library, registry backend
4  *  Copyright (C) Michael Adam 2008
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "includes.h"
21 #include "lib/smbconf/smbconf_private.h"
22 #include "registry.h"
23 #include "registry/reg_api.h"
24 #include "registry/reg_backend_db.h"
25 #include "registry/reg_util_token.h"
26 #include "registry/reg_api_util.h"
27 #include "registry/reg_init_smbconf.h"
28 #include "lib/smbconf/smbconf_init.h"
29 #include "lib/smbconf/smbconf_reg.h"
30 #include "../libcli/registry/util_reg.h"
31
32 #define INCLUDES_VALNAME "includes"
33
34 struct reg_private_data {
35         struct registry_key *base_key;
36         bool open;              /* did _we_ open the registry? */
37 };
38
39 /**********************************************************************
40  *
41  * helper functions
42  *
43  **********************************************************************/
44
45 /**
46  * a convenience helper to cast the private data structure
47  */
48 static struct reg_private_data *rpd(struct smbconf_ctx *ctx)
49 {
50         return (struct reg_private_data *)(ctx->data);
51 }
52
53 /*
54  * check whether a given value name is forbidden in registry (smbconf)
55  */
56 static bool smbconf_reg_valname_forbidden(const char *valname)
57 {
58         /* hard code the list of forbidden names here for now */
59         const char *forbidden_valnames[] = {
60                 "lock directory",
61                 "lock dir",
62                 "config backend",
63                 "include",
64                 "includes", /* this has a special meaning internally */
65                 NULL
66         };
67         const char **forbidden = NULL;
68
69         for (forbidden = forbidden_valnames; *forbidden != NULL; forbidden++) {
70                 if (strwicmp(valname, *forbidden) == 0) {
71                         return true;
72                 }
73         }
74         return false;
75 }
76
77 static bool smbconf_reg_valname_valid(const char *valname)
78 {
79         return (!smbconf_reg_valname_forbidden(valname) &&
80                 lp_parameter_is_valid(valname));
81 }
82
83 /**
84  * Open a subkey of the base key (i.e a service)
85  */
86 static WERROR smbconf_reg_open_service_key(TALLOC_CTX *mem_ctx,
87                                            struct smbconf_ctx *ctx,
88                                            const char *servicename,
89                                            uint32 desired_access,
90                                            struct registry_key **key)
91 {
92         WERROR werr;
93
94         if (servicename == NULL) {
95                 *key = rpd(ctx)->base_key;
96                 return WERR_OK;
97         }
98         werr = reg_openkey(mem_ctx, rpd(ctx)->base_key, servicename,
99                            desired_access, key);
100
101         if (W_ERROR_EQUAL(werr, WERR_BADFILE)) {
102                 werr = WERR_NO_SUCH_SERVICE;
103         }
104
105         return werr;
106 }
107
108 /**
109  * check if a value exists in a given registry key
110  */
111 static bool smbconf_value_exists(struct registry_key *key, const char *param)
112 {
113         bool ret = false;
114         WERROR werr = WERR_OK;
115         TALLOC_CTX *ctx = talloc_stackframe();
116         struct registry_value *value = NULL;
117
118         werr = reg_queryvalue(ctx, key, param, &value);
119         if (W_ERROR_IS_OK(werr)) {
120                 ret = true;
121         }
122
123         talloc_free(ctx);
124         return ret;
125 }
126
127 /**
128  * create a subkey of the base key (i.e. a service...)
129  */
130 static WERROR smbconf_reg_create_service_key(TALLOC_CTX *mem_ctx,
131                                              struct smbconf_ctx *ctx,
132                                              const char * subkeyname,
133                                              struct registry_key **newkey)
134 {
135         WERROR werr = WERR_OK;
136         TALLOC_CTX *create_ctx;
137         enum winreg_CreateAction action = REG_ACTION_NONE;
138
139         /* create a new talloc ctx for creation. it will hold
140          * the intermediate parent key (SMBCONF) for creation
141          * and will be destroyed when leaving this function... */
142         create_ctx = talloc_stackframe();
143
144         werr = reg_createkey(mem_ctx, rpd(ctx)->base_key, subkeyname,
145                              REG_KEY_WRITE, newkey, &action);
146         if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) {
147                 DEBUG(10, ("Key '%s' already exists.\n", subkeyname));
148                 werr = WERR_FILE_EXISTS;
149         }
150         if (!W_ERROR_IS_OK(werr)) {
151                 DEBUG(5, ("Error creating key %s: %s\n",
152                          subkeyname, win_errstr(werr)));
153         }
154
155         talloc_free(create_ctx);
156         return werr;
157 }
158
159 /**
160  * add a value to a key.
161  */
162 static WERROR smbconf_reg_set_value(struct registry_key *key,
163                                     const char *valname,
164                                     const char *valstr)
165 {
166         struct registry_value val;
167         WERROR werr = WERR_OK;
168         char *subkeyname;
169         const char *canon_valname;
170         const char *canon_valstr;
171
172         if (!lp_canonicalize_parameter_with_value(valname, valstr,
173                                                   &canon_valname,
174                                                   &canon_valstr))
175         {
176                 if (canon_valname == NULL) {
177                         DEBUG(5, ("invalid parameter '%s' given\n",
178                                   valname));
179                 } else {
180                         DEBUG(5, ("invalid value '%s' given for "
181                                   "parameter '%s'\n", valstr, valname));
182                 }
183                 werr = WERR_INVALID_PARAM;
184                 goto done;
185         }
186
187         if (smbconf_reg_valname_forbidden(canon_valname)) {
188                 DEBUG(5, ("Parameter '%s' not allowed in registry.\n",
189                           canon_valname));
190                 werr = WERR_INVALID_PARAM;
191                 goto done;
192         }
193
194         subkeyname = strrchr_m(key->key->name, '\\');
195         if ((subkeyname == NULL) || (*(subkeyname +1) == '\0')) {
196                 DEBUG(5, ("Invalid registry key '%s' given as "
197                           "smbconf section.\n", key->key->name));
198                 werr = WERR_INVALID_PARAM;
199                 goto done;
200         }
201         subkeyname++;
202         if (!strequal(subkeyname, GLOBAL_NAME) &&
203             lp_parameter_is_global(valname))
204         {
205                 DEBUG(5, ("Global parameter '%s' not allowed in "
206                           "service definition ('%s').\n", canon_valname,
207                           subkeyname));
208                 werr = WERR_INVALID_PARAM;
209                 goto done;
210         }
211
212         ZERO_STRUCT(val);
213
214         val.type = REG_SZ;
215         if (!push_reg_sz(talloc_tos(), &val.data, canon_valstr)) {
216                 werr = WERR_NOMEM;
217                 goto done;
218         }
219
220         werr = reg_setvalue(key, canon_valname, &val);
221         if (!W_ERROR_IS_OK(werr)) {
222                 DEBUG(5, ("Error adding value '%s' to "
223                           "key '%s': %s\n",
224                           canon_valname, key->key->name, win_errstr(werr)));
225         }
226
227 done:
228         return werr;
229 }
230
231 static WERROR smbconf_reg_set_multi_sz_value(struct registry_key *key,
232                                              const char *valname,
233                                              const uint32_t num_strings,
234                                              const char **strings)
235 {
236         WERROR werr;
237         struct registry_value *value;
238         uint32_t count;
239         TALLOC_CTX *tmp_ctx = talloc_stackframe();
240         const char **array;
241
242         if (strings == NULL) {
243                 werr = WERR_INVALID_PARAM;
244                 goto done;
245         }
246
247         array = talloc_zero_array(tmp_ctx, const char *, num_strings + 1);
248         if (array == NULL) {
249                 werr = WERR_NOMEM;
250                 goto done;
251         }
252
253         value = TALLOC_ZERO_P(tmp_ctx, struct registry_value);
254         if (value == NULL) {
255                 werr = WERR_NOMEM;
256                 goto done;
257         }
258
259         value->type = REG_MULTI_SZ;
260
261         for (count = 0; count < num_strings; count++) {
262                 array[count] = talloc_strdup(value, strings[count]);
263                 if (array[count] == NULL) {
264                         werr = WERR_NOMEM;
265                         goto done;
266                 }
267         }
268
269         if (!push_reg_multi_sz(value, &value->data, array)) {
270                 werr = WERR_NOMEM;
271                 goto done;
272         }
273
274         werr = reg_setvalue(key, valname, value);
275         if (!W_ERROR_IS_OK(werr)) {
276                 DEBUG(5, ("Error adding value '%s' to key '%s': %s\n",
277                           valname, key->key->name, win_errstr(werr)));
278         }
279
280 done:
281         talloc_free(tmp_ctx);
282         return werr;
283 }
284
285 /**
286  * format a registry_value into a string.
287  *
288  * This is intended to be used for smbconf registry values,
289  * which are ar stored as REG_SZ values, so the incomplete
290  * handling should be ok.
291  */
292 static char *smbconf_format_registry_value(TALLOC_CTX *mem_ctx,
293                                            struct registry_value *value)
294 {
295         char *result = NULL;
296
297         /* alternatively, create a new talloc context? */
298         if (mem_ctx == NULL) {
299                 return result;
300         }
301
302         switch (value->type) {
303         case REG_DWORD:
304                 if (value->data.length >= 4) {
305                         uint32_t v = IVAL(value->data.data, 0);
306                         result = talloc_asprintf(mem_ctx, "%d", v);
307                 }
308                 break;
309         case REG_SZ:
310         case REG_EXPAND_SZ: {
311                 const char *s;
312                 if (!pull_reg_sz(mem_ctx, &value->data, &s)) {
313                         break;
314                 }
315                 result = talloc_strdup(mem_ctx, s);
316                 break;
317         }
318         case REG_MULTI_SZ: {
319                 uint32 j;
320                 const char **a = NULL;
321                 if (!pull_reg_multi_sz(mem_ctx, &value->data, &a)) {
322                         break;
323                 }
324                 for (j = 0; a[j] != NULL; j++) {
325                         result = talloc_asprintf(mem_ctx, "%s\"%s\" ",
326                                                  result ? result : "" ,
327                                                  a[j]);
328                         if (result == NULL) {
329                                 break;
330                         }
331                 }
332                 break;
333         }
334         case REG_BINARY:
335                 result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
336                                          (int)value->data.length);
337                 break;
338         default:
339                 result = talloc_asprintf(mem_ctx, "<unprintable>");
340                 break;
341         }
342         return result;
343 }
344
345 static WERROR smbconf_reg_get_includes_internal(TALLOC_CTX *mem_ctx,
346                                                 struct registry_key *key,
347                                                 uint32_t *num_includes,
348                                                 char ***includes)
349 {
350         WERROR werr;
351         uint32_t count;
352         struct registry_value *value = NULL;
353         char **tmp_includes = NULL;
354         const char **array = NULL;
355         TALLOC_CTX *tmp_ctx = talloc_stackframe();
356
357         if (!smbconf_value_exists(key, INCLUDES_VALNAME)) {
358                 /* no includes */
359                 *num_includes = 0;
360                 *includes = NULL;
361                 werr = WERR_OK;
362                 goto done;
363         }
364
365         werr = reg_queryvalue(tmp_ctx, key, INCLUDES_VALNAME, &value);
366         if (!W_ERROR_IS_OK(werr)) {
367                 goto done;
368         }
369
370         if (value->type != REG_MULTI_SZ) {
371                 /* wrong type -- ignore */
372                 goto done;
373         }
374
375         if (!pull_reg_multi_sz(tmp_ctx, &value->data, &array)) {
376                 werr = WERR_NOMEM;
377                 goto done;
378         }
379
380         for (count = 0; array[count] != NULL; count++) {
381                 werr = smbconf_add_string_to_array(tmp_ctx,
382                                         &tmp_includes,
383                                         count,
384                                         array[count]);
385                 if (!W_ERROR_IS_OK(werr)) {
386                         goto done;
387                 }
388         }
389
390         if (count > 0) {
391                 *includes = talloc_move(mem_ctx, &tmp_includes);
392                 if (*includes == NULL) {
393                         werr = WERR_NOMEM;
394                         goto done;
395                 }
396                 *num_includes = count;
397         } else {
398                 *num_includes = 0;
399                 *includes = NULL;
400         }
401
402 done:
403         talloc_free(tmp_ctx);
404         return werr;
405 }
406
407 /**
408  * Get the values of a key as a list of value names
409  * and a list of value strings (ordered)
410  */
411 static WERROR smbconf_reg_get_values(TALLOC_CTX *mem_ctx,
412                                      struct registry_key *key,
413                                      uint32_t *num_values,
414                                      char ***value_names,
415                                      char ***value_strings)
416 {
417         TALLOC_CTX *tmp_ctx = NULL;
418         WERROR werr = WERR_OK;
419         uint32_t count;
420         struct registry_value *valvalue = NULL;
421         char *valname = NULL;
422         uint32_t tmp_num_values = 0;
423         char **tmp_valnames = NULL;
424         char **tmp_valstrings = NULL;
425         uint32_t num_includes = 0;
426         char **includes = NULL;
427
428         if ((num_values == NULL) || (value_names == NULL) ||
429             (value_strings == NULL))
430         {
431                 werr = WERR_INVALID_PARAM;
432                 goto done;
433         }
434
435         tmp_ctx = talloc_stackframe();
436
437         for (count = 0;
438              werr = reg_enumvalue(tmp_ctx, key, count, &valname, &valvalue),
439              W_ERROR_IS_OK(werr);
440              count++)
441         {
442                 char *valstring;
443
444                 if (!smbconf_reg_valname_valid(valname)) {
445                         continue;
446                 }
447
448                 werr = smbconf_add_string_to_array(tmp_ctx,
449                                                    &tmp_valnames,
450                                                    tmp_num_values, valname);
451                 if (!W_ERROR_IS_OK(werr)) {
452                         goto done;
453                 }
454
455                 valstring = smbconf_format_registry_value(tmp_ctx, valvalue);
456                 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_valstrings,
457                                                    tmp_num_values, valstring);
458                 if (!W_ERROR_IS_OK(werr)) {
459                         goto done;
460                 }
461                 tmp_num_values++;
462         }
463         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
464                 goto done;
465         }
466
467         /* now add the includes at the end */
468         werr = smbconf_reg_get_includes_internal(tmp_ctx, key, &num_includes,
469                                                  &includes);
470         if (!W_ERROR_IS_OK(werr)) {
471                 goto done;
472         }
473         for (count = 0; count < num_includes; count++) {
474                 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_valnames,
475                                                    tmp_num_values, "include");
476                 if (!W_ERROR_IS_OK(werr)) {
477                         goto done;
478                 }
479
480                 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_valstrings,
481                                                    tmp_num_values,
482                                                    includes[count]);
483                 if (!W_ERROR_IS_OK(werr)) {
484                         goto done;
485                 }
486
487                 tmp_num_values++;
488         }
489
490         *num_values = tmp_num_values;
491         if (tmp_num_values > 0) {
492                 *value_names = talloc_move(mem_ctx, &tmp_valnames);
493                 *value_strings = talloc_move(mem_ctx, &tmp_valstrings);
494         } else {
495                 *value_names = NULL;
496                 *value_strings = NULL;
497         }
498
499 done:
500         talloc_free(tmp_ctx);
501         return werr;
502 }
503
504 static bool smbconf_reg_key_has_values(struct registry_key *key)
505 {
506         WERROR werr;
507         uint32_t num_subkeys;
508         uint32_t max_subkeylen;
509         uint32_t max_subkeysize;
510         uint32_t num_values;
511         uint32_t max_valnamelen;
512         uint32_t max_valbufsize;
513         uint32_t secdescsize;
514         NTTIME last_changed_time;
515
516         werr = reg_queryinfokey(key, &num_subkeys, &max_subkeylen,
517                                 &max_subkeysize, &num_values, &max_valnamelen,
518                                 &max_valbufsize, &secdescsize,
519                                 &last_changed_time);
520         if (!W_ERROR_IS_OK(werr)) {
521                 return false;
522         }
523
524         return (num_values != 0);
525 }
526
527 /**
528  * delete all values from a key
529  */
530 static WERROR smbconf_reg_delete_values(struct registry_key *key)
531 {
532         WERROR werr;
533         char *valname;
534         struct registry_value *valvalue;
535         uint32_t count;
536         TALLOC_CTX *mem_ctx = talloc_stackframe();
537
538         for (count = 0;
539              werr = reg_enumvalue(mem_ctx, key, count, &valname, &valvalue),
540              W_ERROR_IS_OK(werr);
541              count++)
542         {
543                 werr = reg_deletevalue(key, valname);
544                 if (!W_ERROR_IS_OK(werr)) {
545                         goto done;
546                 }
547         }
548         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
549                 DEBUG(1, ("smbconf_reg_delete_values: "
550                           "Error enumerating values of %s: %s\n",
551                           key->key->name,
552                           win_errstr(werr)));
553                 goto done;
554         }
555
556         werr = WERR_OK;
557
558 done:
559         talloc_free(mem_ctx);
560         return werr;
561 }
562
563 /**********************************************************************
564  *
565  * smbconf operations: registry implementations
566  *
567  **********************************************************************/
568
569 /**
570  * initialize the registry smbconf backend
571  */
572 static WERROR smbconf_reg_init(struct smbconf_ctx *ctx, const char *path)
573 {
574         WERROR werr = WERR_OK;
575         struct security_token *token;
576
577         if (path == NULL) {
578                 path = KEY_SMBCONF;
579         }
580         ctx->path = talloc_strdup(ctx, path);
581         if (ctx->path == NULL) {
582                 werr = WERR_NOMEM;
583                 goto done;
584         }
585
586         ctx->data = TALLOC_ZERO_P(ctx, struct reg_private_data);
587
588         werr = ntstatus_to_werror(registry_create_admin_token(ctx, &token));
589         if (!W_ERROR_IS_OK(werr)) {
590                 DEBUG(1, ("Error creating admin token\n"));
591                 goto done;
592         }
593         rpd(ctx)->open = false;
594
595         werr = registry_init_smbconf(path);
596         if (!W_ERROR_IS_OK(werr)) {
597                 goto done;
598         }
599
600         werr = ctx->ops->open_conf(ctx);
601         if (!W_ERROR_IS_OK(werr)) {
602                 DEBUG(1, ("Error opening the registry.\n"));
603                 goto done;
604         }
605
606         werr = reg_open_path(ctx, ctx->path,
607                              KEY_ENUMERATE_SUB_KEYS | REG_KEY_WRITE,
608                              token, &rpd(ctx)->base_key);
609         if (!W_ERROR_IS_OK(werr)) {
610                 goto done;
611         }
612
613 done:
614         return werr;
615 }
616
617 static int smbconf_reg_shutdown(struct smbconf_ctx *ctx)
618 {
619         return ctx->ops->close_conf(ctx);
620 }
621
622 static bool smbconf_reg_requires_messaging(struct smbconf_ctx *ctx)
623 {
624 #ifdef CLUSTER_SUPPORT
625         if (lp_clustering() && lp_parm_bool(-1, "ctdb", "registry.tdb", true)) {
626                 return true;
627         }
628 #endif
629         return false;
630 }
631
632 static bool smbconf_reg_is_writeable(struct smbconf_ctx *ctx)
633 {
634         /*
635          * The backend has write support.
636          *
637          *  TODO: add access checks whether the concrete
638          *  config source is really writeable by the calling user.
639          */
640         return true;
641 }
642
643 static WERROR smbconf_reg_open(struct smbconf_ctx *ctx)
644 {
645         WERROR werr;
646
647         if (rpd(ctx)->open) {
648                 return WERR_OK;
649         }
650
651         werr = regdb_open();
652         if (W_ERROR_IS_OK(werr)) {
653                 rpd(ctx)->open = true;
654         }
655         return werr;
656 }
657
658 static int smbconf_reg_close(struct smbconf_ctx *ctx)
659 {
660         int ret;
661
662         if (!rpd(ctx)->open) {
663                 return 0;
664         }
665
666         ret = regdb_close();
667         if (ret == 0) {
668                 rpd(ctx)->open = false;
669         }
670         return ret;
671 }
672
673 /**
674  * Get the change sequence number of the given service/parameter.
675  * service and parameter strings may be NULL.
676  */
677 static void smbconf_reg_get_csn(struct smbconf_ctx *ctx,
678                                 struct smbconf_csn *csn,
679                                 const char *service, const char *param)
680 {
681         if (csn == NULL) {
682                 return;
683         }
684
685         if (!W_ERROR_IS_OK(ctx->ops->open_conf(ctx))) {
686                 return;
687         }
688
689         csn->csn = (uint64_t)regdb_get_seqnum();
690 }
691
692 /**
693  * Drop the whole configuration (restarting empty) - registry version
694  */
695 static WERROR smbconf_reg_drop(struct smbconf_ctx *ctx)
696 {
697         char *path, *p;
698         WERROR werr = WERR_OK;
699         struct registry_key *parent_key = NULL;
700         struct registry_key *new_key = NULL;
701         TALLOC_CTX* mem_ctx = talloc_stackframe();
702         enum winreg_CreateAction action;
703         struct security_token *token;
704
705         werr = ntstatus_to_werror(registry_create_admin_token(ctx, &token));
706         if (!W_ERROR_IS_OK(werr)) {
707                 DEBUG(1, ("Error creating admin token\n"));
708                 goto done;
709         }
710
711         path = talloc_strdup(mem_ctx, ctx->path);
712         if (path == NULL) {
713                 werr = WERR_NOMEM;
714                 goto done;
715         }
716         p = strrchr(path, '\\');
717         *p = '\0';
718         werr = reg_open_path(mem_ctx, path, REG_KEY_WRITE, token,
719                              &parent_key);
720
721         if (!W_ERROR_IS_OK(werr)) {
722                 goto done;
723         }
724
725         werr = reg_deletekey_recursive(parent_key, p+1);
726
727         if (!W_ERROR_IS_OK(werr)) {
728                 goto done;
729         }
730
731         werr = reg_createkey(mem_ctx, parent_key, p+1, REG_KEY_WRITE,
732                              &new_key, &action);
733
734 done:
735         talloc_free(mem_ctx);
736         return werr;
737 }
738
739 /**
740  * get the list of share names defined in the configuration.
741  * registry version.
742  */
743 static WERROR smbconf_reg_get_share_names(struct smbconf_ctx *ctx,
744                                           TALLOC_CTX *mem_ctx,
745                                           uint32_t *num_shares,
746                                           char ***share_names)
747 {
748         uint32_t count;
749         uint32_t added_count = 0;
750         TALLOC_CTX *tmp_ctx = NULL;
751         WERROR werr = WERR_OK;
752         char *subkey_name = NULL;
753         char **tmp_share_names = NULL;
754
755         if ((num_shares == NULL) || (share_names == NULL)) {
756                 werr = WERR_INVALID_PARAM;
757                 goto done;
758         }
759
760         tmp_ctx = talloc_stackframe();
761
762         /* if there are values in the base key, return NULL as share name */
763
764         if (smbconf_reg_key_has_values(rpd(ctx)->base_key)) {
765                 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
766                                                    0, NULL);
767                 if (!W_ERROR_IS_OK(werr)) {
768                         goto done;
769                 }
770                 added_count++;
771         }
772
773         /* make sure "global" is always listed first */
774         if (smbconf_share_exists(ctx, GLOBAL_NAME)) {
775                 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
776                                                    added_count, GLOBAL_NAME);
777                 if (!W_ERROR_IS_OK(werr)) {
778                         goto done;
779                 }
780                 added_count++;
781         }
782
783         for (count = 0;
784              werr = reg_enumkey(tmp_ctx, rpd(ctx)->base_key, count,
785                                 &subkey_name, NULL),
786              W_ERROR_IS_OK(werr);
787              count++)
788         {
789                 if (strequal(subkey_name, GLOBAL_NAME)) {
790                         continue;
791                 }
792
793                 werr = smbconf_add_string_to_array(tmp_ctx,
794                                                    &tmp_share_names,
795                                                    added_count,
796                                                    subkey_name);
797                 if (!W_ERROR_IS_OK(werr)) {
798                         goto done;
799                 }
800                 added_count++;
801         }
802         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
803                 goto done;
804         }
805         werr = WERR_OK;
806
807         *num_shares = added_count;
808         if (added_count > 0) {
809                 *share_names = talloc_move(mem_ctx, &tmp_share_names);
810         } else {
811                 *share_names = NULL;
812         }
813
814 done:
815         talloc_free(tmp_ctx);
816         return werr;
817 }
818
819 /**
820  * check if a share/service of a given name exists - registry version
821  */
822 static bool smbconf_reg_share_exists(struct smbconf_ctx *ctx,
823                                      const char *servicename)
824 {
825         bool ret = false;
826         WERROR werr = WERR_OK;
827         TALLOC_CTX *mem_ctx = talloc_stackframe();
828         struct registry_key *key = NULL;
829
830         werr = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
831                                             REG_KEY_READ, &key);
832         if (W_ERROR_IS_OK(werr)) {
833                 ret = true;
834         }
835
836         talloc_free(mem_ctx);
837         return ret;
838 }
839
840 /**
841  * Add a service if it does not already exist - registry version
842  */
843 static WERROR smbconf_reg_create_share(struct smbconf_ctx *ctx,
844                                        const char *servicename)
845 {
846         WERROR werr;
847         struct registry_key *key = NULL;
848
849         if (servicename == NULL) {
850                 return WERR_OK;
851         }
852
853         werr = smbconf_reg_create_service_key(talloc_tos(), ctx,
854                                               servicename, &key);
855
856         talloc_free(key);
857         return werr;
858 }
859
860 /**
861  * get a definition of a share (service) from configuration.
862  */
863 static WERROR smbconf_reg_get_share(struct smbconf_ctx *ctx,
864                                     TALLOC_CTX *mem_ctx,
865                                     const char *servicename,
866                                     struct smbconf_service **service)
867 {
868         WERROR werr = WERR_OK;
869         struct registry_key *key = NULL;
870         struct smbconf_service *tmp_service = NULL;
871         TALLOC_CTX *tmp_ctx = talloc_stackframe();
872
873         werr = smbconf_reg_open_service_key(tmp_ctx, ctx, servicename,
874                                             REG_KEY_READ, &key);
875         if (!W_ERROR_IS_OK(werr)) {
876                 goto done;
877         }
878
879         tmp_service = TALLOC_ZERO_P(tmp_ctx, struct smbconf_service);
880         if (tmp_service == NULL) {
881                 werr =  WERR_NOMEM;
882                 goto done;
883         }
884
885         if (servicename != NULL) {
886                 tmp_service->name = talloc_strdup(tmp_service, servicename);
887                 if (tmp_service->name == NULL) {
888                         werr = WERR_NOMEM;
889                         goto done;
890                 }
891         }
892
893         werr = smbconf_reg_get_values(tmp_service, key,
894                                       &(tmp_service->num_params),
895                                       &(tmp_service->param_names),
896                                       &(tmp_service->param_values));
897
898         if (W_ERROR_IS_OK(werr)) {
899                 *service = talloc_move(mem_ctx, &tmp_service);
900         }
901
902 done:
903         talloc_free(tmp_ctx);
904         return werr;
905 }
906
907 /**
908  * delete a service from configuration
909  */
910 static WERROR smbconf_reg_delete_share(struct smbconf_ctx *ctx,
911                                        const char *servicename)
912 {
913         WERROR werr = WERR_OK;
914         TALLOC_CTX *mem_ctx = talloc_stackframe();
915
916         if (servicename != NULL) {
917                 werr = reg_deletekey_recursive(rpd(ctx)->base_key, servicename);
918         } else {
919                 werr = smbconf_reg_delete_values(rpd(ctx)->base_key);
920         }
921
922         talloc_free(mem_ctx);
923         return werr;
924 }
925
926 /**
927  * set a configuration parameter to the value provided.
928  */
929 static WERROR smbconf_reg_set_parameter(struct smbconf_ctx *ctx,
930                                         const char *service,
931                                         const char *param,
932                                         const char *valstr)
933 {
934         WERROR werr;
935         struct registry_key *key = NULL;
936         TALLOC_CTX *mem_ctx = talloc_stackframe();
937
938         werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
939                                             REG_KEY_WRITE, &key);
940         if (!W_ERROR_IS_OK(werr)) {
941                 goto done;
942         }
943
944         werr = smbconf_reg_set_value(key, param, valstr);
945
946 done:
947         talloc_free(mem_ctx);
948         return werr;
949 }
950
951 /**
952  * get the value of a configuration parameter as a string
953  */
954 static WERROR smbconf_reg_get_parameter(struct smbconf_ctx *ctx,
955                                         TALLOC_CTX *mem_ctx,
956                                         const char *service,
957                                         const char *param,
958                                         char **valstr)
959 {
960         WERROR werr = WERR_OK;
961         struct registry_key *key = NULL;
962         struct registry_value *value = NULL;
963
964         werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
965                                             REG_KEY_READ, &key);
966         if (!W_ERROR_IS_OK(werr)) {
967                 goto done;
968         }
969
970         if (!smbconf_reg_valname_valid(param)) {
971                 werr = WERR_INVALID_PARAM;
972                 goto done;
973         }
974
975         if (!smbconf_value_exists(key, param)) {
976                 werr = WERR_INVALID_PARAM;
977                 goto done;
978         }
979
980         werr = reg_queryvalue(mem_ctx, key, param, &value);
981         if (!W_ERROR_IS_OK(werr)) {
982                 goto done;
983         }
984
985         *valstr = smbconf_format_registry_value(mem_ctx, value);
986
987         if (*valstr == NULL) {
988                 werr = WERR_NOMEM;
989         }
990
991 done:
992         talloc_free(key);
993         talloc_free(value);
994         return werr;
995 }
996
997 /**
998  * delete a parameter from configuration
999  */
1000 static WERROR smbconf_reg_delete_parameter(struct smbconf_ctx *ctx,
1001                                            const char *service,
1002                                            const char *param)
1003 {
1004         struct registry_key *key = NULL;
1005         WERROR werr = WERR_OK;
1006         TALLOC_CTX *mem_ctx = talloc_stackframe();
1007
1008         werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
1009                                             REG_KEY_ALL, &key);
1010         if (!W_ERROR_IS_OK(werr)) {
1011                 goto done;
1012         }
1013
1014         if (!smbconf_reg_valname_valid(param)) {
1015                 werr = WERR_INVALID_PARAM;
1016                 goto done;
1017         }
1018
1019         if (!smbconf_value_exists(key, param)) {
1020                 werr = WERR_INVALID_PARAM;
1021                 goto done;
1022         }
1023
1024         werr = reg_deletevalue(key, param);
1025
1026 done:
1027         talloc_free(mem_ctx);
1028         return werr;
1029 }
1030
1031 static WERROR smbconf_reg_get_includes(struct smbconf_ctx *ctx,
1032                                        TALLOC_CTX *mem_ctx,
1033                                        const char *service,
1034                                        uint32_t *num_includes,
1035                                        char ***includes)
1036 {
1037         WERROR werr;
1038         struct registry_key *key = NULL;
1039         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1040
1041         werr = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
1042                                             REG_KEY_READ, &key);
1043         if (!W_ERROR_IS_OK(werr)) {
1044                 goto done;
1045         }
1046
1047         werr = smbconf_reg_get_includes_internal(mem_ctx, key, num_includes,
1048                                                  includes);
1049
1050 done:
1051         talloc_free(tmp_ctx);
1052         return werr;
1053 }
1054
1055 static WERROR smbconf_reg_set_includes(struct smbconf_ctx *ctx,
1056                                        const char *service,
1057                                        uint32_t num_includes,
1058                                        const char **includes)
1059 {
1060         WERROR werr = WERR_OK;
1061         struct registry_key *key = NULL;
1062         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1063
1064         werr = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
1065                                             REG_KEY_ALL, &key);
1066         if (!W_ERROR_IS_OK(werr)) {
1067                 goto done;
1068         }
1069
1070         if (num_includes == 0) {
1071                 if (!smbconf_value_exists(key, INCLUDES_VALNAME)) {
1072                         goto done;
1073                 }
1074                 werr = reg_deletevalue(key, INCLUDES_VALNAME);
1075         } else {
1076                 werr = smbconf_reg_set_multi_sz_value(key, INCLUDES_VALNAME,
1077                                                       num_includes, includes);
1078         }
1079
1080 done:
1081         talloc_free(tmp_ctx);
1082         return werr;
1083 }
1084
1085 static WERROR smbconf_reg_delete_includes(struct smbconf_ctx *ctx,
1086                                           const char *service)
1087 {
1088         WERROR werr = WERR_OK;
1089         struct registry_key *key = NULL;
1090         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1091
1092         werr = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
1093                                             REG_KEY_ALL, &key);
1094         if (!W_ERROR_IS_OK(werr)) {
1095                 goto done;
1096         }
1097
1098         if (!smbconf_value_exists(key, INCLUDES_VALNAME)) {
1099                 goto done;
1100         }
1101
1102         werr = reg_deletevalue(key, INCLUDES_VALNAME);
1103
1104
1105 done:
1106         talloc_free(tmp_ctx);
1107         return werr;
1108 }
1109
1110 static WERROR smbconf_reg_transaction_start(struct smbconf_ctx *ctx)
1111 {
1112         return regdb_transaction_start();
1113 }
1114
1115 static WERROR smbconf_reg_transaction_commit(struct smbconf_ctx *ctx)
1116 {
1117         return regdb_transaction_commit();
1118 }
1119
1120 static WERROR smbconf_reg_transaction_cancel(struct smbconf_ctx *ctx)
1121 {
1122         return regdb_transaction_cancel();
1123 }
1124
1125 struct smbconf_ops smbconf_ops_reg = {
1126         .init                   = smbconf_reg_init,
1127         .shutdown               = smbconf_reg_shutdown,
1128         .requires_messaging     = smbconf_reg_requires_messaging,
1129         .is_writeable           = smbconf_reg_is_writeable,
1130         .open_conf              = smbconf_reg_open,
1131         .close_conf             = smbconf_reg_close,
1132         .get_csn                = smbconf_reg_get_csn,
1133         .drop                   = smbconf_reg_drop,
1134         .get_share_names        = smbconf_reg_get_share_names,
1135         .share_exists           = smbconf_reg_share_exists,
1136         .create_share           = smbconf_reg_create_share,
1137         .get_share              = smbconf_reg_get_share,
1138         .delete_share           = smbconf_reg_delete_share,
1139         .set_parameter          = smbconf_reg_set_parameter,
1140         .get_parameter          = smbconf_reg_get_parameter,
1141         .delete_parameter       = smbconf_reg_delete_parameter,
1142         .get_includes           = smbconf_reg_get_includes,
1143         .set_includes           = smbconf_reg_set_includes,
1144         .delete_includes        = smbconf_reg_delete_includes,
1145         .transaction_start      = smbconf_reg_transaction_start,
1146         .transaction_commit     = smbconf_reg_transaction_commit,
1147         .transaction_cancel     = smbconf_reg_transaction_cancel,
1148 };
1149
1150
1151 /**
1152  * initialize the smbconf registry backend
1153  * the only function that is exported from this module
1154  */
1155 WERROR smbconf_init_reg(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx,
1156                         const char *path)
1157 {
1158         return smbconf_init_internal(mem_ctx, conf_ctx, path, &smbconf_ops_reg);
1159 }