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