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