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