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