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