844a9b6b483bf218e43d7f330a3c8d7ff13aeb35
[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 sbcErr smbconf_reg_init(struct smbconf_ctx *ctx, const char *path)
573 {
574         WERROR werr = WERR_OK;
575         sbcErr err;
576         struct security_token *token;
577
578         if (path == NULL) {
579                 path = KEY_SMBCONF;
580         }
581         ctx->path = talloc_strdup(ctx, path);
582         if (ctx->path == NULL) {
583                 werr = WERR_NOMEM;
584                 goto done;
585         }
586
587         ctx->data = TALLOC_ZERO_P(ctx, struct reg_private_data);
588
589         werr = ntstatus_to_werror(registry_create_admin_token(ctx, &token));
590         if (!W_ERROR_IS_OK(werr)) {
591                 DEBUG(1, ("Error creating admin token\n"));
592                 err = SBC_ERR_UNKNOWN_FAILURE;
593                 goto done;
594         }
595         rpd(ctx)->open = false;
596
597         werr = registry_init_smbconf(path);
598         if (!W_ERROR_IS_OK(werr)) {
599                 err = SBC_ERR_BADFILE;
600                 goto done;
601         }
602
603         err = ctx->ops->open_conf(ctx);
604         if (!SBC_ERROR_IS_OK(err)) {
605                 DEBUG(1, ("Error opening the registry.\n"));
606                 goto done;
607         }
608
609         werr = reg_open_path(ctx, ctx->path,
610                              KEY_ENUMERATE_SUB_KEYS | REG_KEY_WRITE,
611                              token, &rpd(ctx)->base_key);
612         if (!W_ERROR_IS_OK(werr)) {
613                 err = SBC_ERR_UNKNOWN_FAILURE;
614                 goto done;
615         }
616
617 done:
618         return err;
619 }
620
621 static int smbconf_reg_shutdown(struct smbconf_ctx *ctx)
622 {
623         return ctx->ops->close_conf(ctx);
624 }
625
626 static bool smbconf_reg_requires_messaging(struct smbconf_ctx *ctx)
627 {
628 #ifdef CLUSTER_SUPPORT
629         if (lp_clustering() && lp_parm_bool(-1, "ctdb", "registry.tdb", true)) {
630                 return true;
631         }
632 #endif
633         return false;
634 }
635
636 static bool smbconf_reg_is_writeable(struct smbconf_ctx *ctx)
637 {
638         /*
639          * The backend has write support.
640          *
641          *  TODO: add access checks whether the concrete
642          *  config source is really writeable by the calling user.
643          */
644         return true;
645 }
646
647 static sbcErr smbconf_reg_open(struct smbconf_ctx *ctx)
648 {
649         WERROR werr;
650
651         if (rpd(ctx)->open) {
652                 return SBC_ERR_OK;
653         }
654
655         werr = regdb_open();
656         if (!W_ERROR_IS_OK(werr)) {
657                 return SBC_ERR_BADFILE;
658         }
659
660         rpd(ctx)->open = true;
661         return SBC_ERR_OK;
662 }
663
664 static int smbconf_reg_close(struct smbconf_ctx *ctx)
665 {
666         int ret;
667
668         if (!rpd(ctx)->open) {
669                 return 0;
670         }
671
672         ret = regdb_close();
673         if (ret == 0) {
674                 rpd(ctx)->open = false;
675         }
676         return ret;
677 }
678
679 /**
680  * Get the change sequence number of the given service/parameter.
681  * service and parameter strings may be NULL.
682  */
683 static void smbconf_reg_get_csn(struct smbconf_ctx *ctx,
684                                 struct smbconf_csn *csn,
685                                 const char *service, const char *param)
686 {
687         if (csn == NULL) {
688                 return;
689         }
690
691         if (!SBC_ERROR_IS_OK(ctx->ops->open_conf(ctx))) {
692                 return;
693         }
694
695         csn->csn = (uint64_t)regdb_get_seqnum();
696 }
697
698 /**
699  * Drop the whole configuration (restarting empty) - registry version
700  */
701 static sbcErr smbconf_reg_drop(struct smbconf_ctx *ctx)
702 {
703         char *path, *p;
704         WERROR werr = WERR_OK;
705         sbcErr err = SBC_ERR_OK;
706         struct registry_key *parent_key = NULL;
707         struct registry_key *new_key = NULL;
708         TALLOC_CTX* mem_ctx = talloc_stackframe();
709         enum winreg_CreateAction action;
710         struct security_token *token;
711
712         werr = ntstatus_to_werror(registry_create_admin_token(ctx, &token));
713         if (!W_ERROR_IS_OK(werr)) {
714                 DEBUG(1, ("Error creating admin token\n"));
715                 err = SBC_ERR_UNKNOWN_FAILURE;
716                 goto done;
717         }
718
719         path = talloc_strdup(mem_ctx, ctx->path);
720         if (path == NULL) {
721                 err = SBC_ERR_NOMEM;
722                 goto done;
723         }
724         p = strrchr(path, '\\');
725         if (p == NULL) {
726                 err = SBC_ERR_INVALID_PARAM;
727                 goto done;
728         }
729         *p = '\0';
730         werr = reg_open_path(mem_ctx, path, REG_KEY_WRITE, token,
731                              &parent_key);
732         if (!W_ERROR_IS_OK(werr)) {
733                 err = SBC_ERR_IO_FAILURE;
734                 goto done;
735         }
736
737         werr = reg_deletekey_recursive(parent_key, p+1);
738         if (!W_ERROR_IS_OK(werr)) {
739                 err = SBC_ERR_IO_FAILURE;
740                 goto done;
741         }
742
743         werr = reg_createkey(mem_ctx, parent_key, p+1, REG_KEY_WRITE,
744                              &new_key, &action);
745         if (!W_ERROR_IS_OK(werr)) {
746                 err = SBC_ERR_IO_FAILURE;
747                 goto done;
748         }
749
750 done:
751         talloc_free(mem_ctx);
752         return err;
753 }
754
755 /**
756  * get the list of share names defined in the configuration.
757  * registry version.
758  */
759 static WERROR smbconf_reg_get_share_names(struct smbconf_ctx *ctx,
760                                           TALLOC_CTX *mem_ctx,
761                                           uint32_t *num_shares,
762                                           char ***share_names)
763 {
764         uint32_t count;
765         uint32_t added_count = 0;
766         TALLOC_CTX *tmp_ctx = NULL;
767         WERROR werr = WERR_OK;
768         char *subkey_name = NULL;
769         char **tmp_share_names = NULL;
770
771         if ((num_shares == NULL) || (share_names == NULL)) {
772                 werr = WERR_INVALID_PARAM;
773                 goto done;
774         }
775
776         tmp_ctx = talloc_stackframe();
777
778         /* if there are values in the base key, return NULL as share name */
779
780         if (smbconf_reg_key_has_values(rpd(ctx)->base_key)) {
781                 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
782                                                    0, NULL);
783                 if (!W_ERROR_IS_OK(werr)) {
784                         goto done;
785                 }
786                 added_count++;
787         }
788
789         /* make sure "global" is always listed first */
790         if (smbconf_share_exists(ctx, GLOBAL_NAME)) {
791                 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
792                                                    added_count, GLOBAL_NAME);
793                 if (!W_ERROR_IS_OK(werr)) {
794                         goto done;
795                 }
796                 added_count++;
797         }
798
799         for (count = 0;
800              werr = reg_enumkey(tmp_ctx, rpd(ctx)->base_key, count,
801                                 &subkey_name, NULL),
802              W_ERROR_IS_OK(werr);
803              count++)
804         {
805                 if (strequal(subkey_name, GLOBAL_NAME)) {
806                         continue;
807                 }
808
809                 werr = smbconf_add_string_to_array(tmp_ctx,
810                                                    &tmp_share_names,
811                                                    added_count,
812                                                    subkey_name);
813                 if (!W_ERROR_IS_OK(werr)) {
814                         goto done;
815                 }
816                 added_count++;
817         }
818         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
819                 goto done;
820         }
821         werr = WERR_OK;
822
823         *num_shares = added_count;
824         if (added_count > 0) {
825                 *share_names = talloc_move(mem_ctx, &tmp_share_names);
826         } else {
827                 *share_names = NULL;
828         }
829
830 done:
831         talloc_free(tmp_ctx);
832         return werr;
833 }
834
835 /**
836  * check if a share/service of a given name exists - registry version
837  */
838 static bool smbconf_reg_share_exists(struct smbconf_ctx *ctx,
839                                      const char *servicename)
840 {
841         bool ret = false;
842         WERROR werr = WERR_OK;
843         TALLOC_CTX *mem_ctx = talloc_stackframe();
844         struct registry_key *key = NULL;
845
846         werr = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
847                                             REG_KEY_READ, &key);
848         if (W_ERROR_IS_OK(werr)) {
849                 ret = true;
850         }
851
852         talloc_free(mem_ctx);
853         return ret;
854 }
855
856 /**
857  * Add a service if it does not already exist - registry version
858  */
859 static WERROR smbconf_reg_create_share(struct smbconf_ctx *ctx,
860                                        const char *servicename)
861 {
862         WERROR werr;
863         struct registry_key *key = NULL;
864
865         if (servicename == NULL) {
866                 return WERR_OK;
867         }
868
869         werr = smbconf_reg_create_service_key(talloc_tos(), ctx,
870                                               servicename, &key);
871
872         talloc_free(key);
873         return werr;
874 }
875
876 /**
877  * get a definition of a share (service) from configuration.
878  */
879 static WERROR smbconf_reg_get_share(struct smbconf_ctx *ctx,
880                                     TALLOC_CTX *mem_ctx,
881                                     const char *servicename,
882                                     struct smbconf_service **service)
883 {
884         WERROR werr = WERR_OK;
885         struct registry_key *key = NULL;
886         struct smbconf_service *tmp_service = NULL;
887         TALLOC_CTX *tmp_ctx = talloc_stackframe();
888
889         werr = smbconf_reg_open_service_key(tmp_ctx, ctx, servicename,
890                                             REG_KEY_READ, &key);
891         if (!W_ERROR_IS_OK(werr)) {
892                 goto done;
893         }
894
895         tmp_service = TALLOC_ZERO_P(tmp_ctx, struct smbconf_service);
896         if (tmp_service == NULL) {
897                 werr =  WERR_NOMEM;
898                 goto done;
899         }
900
901         if (servicename != NULL) {
902                 tmp_service->name = talloc_strdup(tmp_service, servicename);
903                 if (tmp_service->name == NULL) {
904                         werr = WERR_NOMEM;
905                         goto done;
906                 }
907         }
908
909         werr = smbconf_reg_get_values(tmp_service, key,
910                                       &(tmp_service->num_params),
911                                       &(tmp_service->param_names),
912                                       &(tmp_service->param_values));
913
914         if (W_ERROR_IS_OK(werr)) {
915                 *service = talloc_move(mem_ctx, &tmp_service);
916         }
917
918 done:
919         talloc_free(tmp_ctx);
920         return werr;
921 }
922
923 /**
924  * delete a service from configuration
925  */
926 static WERROR smbconf_reg_delete_share(struct smbconf_ctx *ctx,
927                                        const char *servicename)
928 {
929         WERROR werr = WERR_OK;
930         TALLOC_CTX *mem_ctx = talloc_stackframe();
931
932         if (servicename != NULL) {
933                 werr = reg_deletekey_recursive(rpd(ctx)->base_key, servicename);
934         } else {
935                 werr = smbconf_reg_delete_values(rpd(ctx)->base_key);
936         }
937
938         talloc_free(mem_ctx);
939         return werr;
940 }
941
942 /**
943  * set a configuration parameter to the value provided.
944  */
945 static WERROR smbconf_reg_set_parameter(struct smbconf_ctx *ctx,
946                                         const char *service,
947                                         const char *param,
948                                         const char *valstr)
949 {
950         WERROR werr;
951         struct registry_key *key = NULL;
952         TALLOC_CTX *mem_ctx = talloc_stackframe();
953
954         werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
955                                             REG_KEY_WRITE, &key);
956         if (!W_ERROR_IS_OK(werr)) {
957                 goto done;
958         }
959
960         werr = smbconf_reg_set_value(key, param, valstr);
961
962 done:
963         talloc_free(mem_ctx);
964         return werr;
965 }
966
967 /**
968  * get the value of a configuration parameter as a string
969  */
970 static WERROR smbconf_reg_get_parameter(struct smbconf_ctx *ctx,
971                                         TALLOC_CTX *mem_ctx,
972                                         const char *service,
973                                         const char *param,
974                                         char **valstr)
975 {
976         WERROR werr = WERR_OK;
977         struct registry_key *key = NULL;
978         struct registry_value *value = NULL;
979
980         werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
981                                             REG_KEY_READ, &key);
982         if (!W_ERROR_IS_OK(werr)) {
983                 goto done;
984         }
985
986         if (!smbconf_reg_valname_valid(param)) {
987                 werr = WERR_INVALID_PARAM;
988                 goto done;
989         }
990
991         if (!smbconf_value_exists(key, param)) {
992                 werr = WERR_INVALID_PARAM;
993                 goto done;
994         }
995
996         werr = reg_queryvalue(mem_ctx, key, param, &value);
997         if (!W_ERROR_IS_OK(werr)) {
998                 goto done;
999         }
1000
1001         *valstr = smbconf_format_registry_value(mem_ctx, value);
1002
1003         if (*valstr == NULL) {
1004                 werr = WERR_NOMEM;
1005         }
1006
1007 done:
1008         talloc_free(key);
1009         talloc_free(value);
1010         return werr;
1011 }
1012
1013 /**
1014  * delete a parameter from configuration
1015  */
1016 static WERROR smbconf_reg_delete_parameter(struct smbconf_ctx *ctx,
1017                                            const char *service,
1018                                            const char *param)
1019 {
1020         struct registry_key *key = NULL;
1021         WERROR werr = WERR_OK;
1022         TALLOC_CTX *mem_ctx = talloc_stackframe();
1023
1024         werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
1025                                             REG_KEY_ALL, &key);
1026         if (!W_ERROR_IS_OK(werr)) {
1027                 goto done;
1028         }
1029
1030         if (!smbconf_reg_valname_valid(param)) {
1031                 werr = WERR_INVALID_PARAM;
1032                 goto done;
1033         }
1034
1035         if (!smbconf_value_exists(key, param)) {
1036                 werr = WERR_INVALID_PARAM;
1037                 goto done;
1038         }
1039
1040         werr = reg_deletevalue(key, param);
1041
1042 done:
1043         talloc_free(mem_ctx);
1044         return werr;
1045 }
1046
1047 static WERROR smbconf_reg_get_includes(struct smbconf_ctx *ctx,
1048                                        TALLOC_CTX *mem_ctx,
1049                                        const char *service,
1050                                        uint32_t *num_includes,
1051                                        char ***includes)
1052 {
1053         WERROR werr;
1054         struct registry_key *key = NULL;
1055         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1056
1057         werr = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
1058                                             REG_KEY_READ, &key);
1059         if (!W_ERROR_IS_OK(werr)) {
1060                 goto done;
1061         }
1062
1063         werr = smbconf_reg_get_includes_internal(mem_ctx, key, num_includes,
1064                                                  includes);
1065
1066 done:
1067         talloc_free(tmp_ctx);
1068         return werr;
1069 }
1070
1071 static WERROR smbconf_reg_set_includes(struct smbconf_ctx *ctx,
1072                                        const char *service,
1073                                        uint32_t num_includes,
1074                                        const char **includes)
1075 {
1076         WERROR werr = WERR_OK;
1077         struct registry_key *key = NULL;
1078         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1079
1080         werr = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
1081                                             REG_KEY_ALL, &key);
1082         if (!W_ERROR_IS_OK(werr)) {
1083                 goto done;
1084         }
1085
1086         if (num_includes == 0) {
1087                 if (!smbconf_value_exists(key, INCLUDES_VALNAME)) {
1088                         goto done;
1089                 }
1090                 werr = reg_deletevalue(key, INCLUDES_VALNAME);
1091         } else {
1092                 werr = smbconf_reg_set_multi_sz_value(key, INCLUDES_VALNAME,
1093                                                       num_includes, includes);
1094         }
1095
1096 done:
1097         talloc_free(tmp_ctx);
1098         return werr;
1099 }
1100
1101 static WERROR smbconf_reg_delete_includes(struct smbconf_ctx *ctx,
1102                                           const char *service)
1103 {
1104         WERROR werr = WERR_OK;
1105         struct registry_key *key = NULL;
1106         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1107
1108         werr = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
1109                                             REG_KEY_ALL, &key);
1110         if (!W_ERROR_IS_OK(werr)) {
1111                 goto done;
1112         }
1113
1114         if (!smbconf_value_exists(key, INCLUDES_VALNAME)) {
1115                 goto done;
1116         }
1117
1118         werr = reg_deletevalue(key, INCLUDES_VALNAME);
1119
1120
1121 done:
1122         talloc_free(tmp_ctx);
1123         return werr;
1124 }
1125
1126 static WERROR smbconf_reg_transaction_start(struct smbconf_ctx *ctx)
1127 {
1128         return regdb_transaction_start();
1129 }
1130
1131 static WERROR smbconf_reg_transaction_commit(struct smbconf_ctx *ctx)
1132 {
1133         return regdb_transaction_commit();
1134 }
1135
1136 static WERROR smbconf_reg_transaction_cancel(struct smbconf_ctx *ctx)
1137 {
1138         return regdb_transaction_cancel();
1139 }
1140
1141 struct smbconf_ops smbconf_ops_reg = {
1142         .init                   = smbconf_reg_init,
1143         .shutdown               = smbconf_reg_shutdown,
1144         .requires_messaging     = smbconf_reg_requires_messaging,
1145         .is_writeable           = smbconf_reg_is_writeable,
1146         .open_conf              = smbconf_reg_open,
1147         .close_conf             = smbconf_reg_close,
1148         .get_csn                = smbconf_reg_get_csn,
1149         .drop                   = smbconf_reg_drop,
1150         .get_share_names        = smbconf_reg_get_share_names,
1151         .share_exists           = smbconf_reg_share_exists,
1152         .create_share           = smbconf_reg_create_share,
1153         .get_share              = smbconf_reg_get_share,
1154         .delete_share           = smbconf_reg_delete_share,
1155         .set_parameter          = smbconf_reg_set_parameter,
1156         .get_parameter          = smbconf_reg_get_parameter,
1157         .delete_parameter       = smbconf_reg_delete_parameter,
1158         .get_includes           = smbconf_reg_get_includes,
1159         .set_includes           = smbconf_reg_set_includes,
1160         .delete_includes        = smbconf_reg_delete_includes,
1161         .transaction_start      = smbconf_reg_transaction_start,
1162         .transaction_commit     = smbconf_reg_transaction_commit,
1163         .transaction_cancel     = smbconf_reg_transaction_cancel,
1164 };
1165
1166
1167 /**
1168  * initialize the smbconf registry backend
1169  * the only function that is exported from this module
1170  */
1171 sbcErr smbconf_init_reg(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx,
1172                         const char *path)
1173 {
1174         return smbconf_init_internal(mem_ctx, conf_ctx, path, &smbconf_ops_reg);
1175 }