libsmbconf: add function smbconf_reg_valname_valid() and use it in get_values()
[ddiss/samba.git] / source3 / lib / smbconf / smbconf_reg.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  libsmbconf - Samba configuration library, registry backend
4  *  Copyright (C) Michael Adam 2008
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "includes.h"
21 #include "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                 NULL
55         };
56         const char **forbidden = NULL;
57
58         for (forbidden = forbidden_valnames; *forbidden != NULL; forbidden++) {
59                 if (strwicmp(valname, *forbidden) == 0) {
60                         return true;
61                 }
62         }
63         return false;
64 }
65
66 static bool smbconf_reg_valname_valid(const char *valname)
67 {
68         return (lp_parameter_is_valid(valname) &&
69                 !smbconf_reg_valname_forbidden(valname));
70 }
71
72 /**
73  * Open a registry key specified by "path"
74  */
75 static WERROR smbconf_reg_open_path(TALLOC_CTX *mem_ctx,
76                                     struct smbconf_ctx *ctx,
77                                     const char *path,
78                                     uint32 desired_access,
79                                     struct registry_key **key)
80 {
81         WERROR werr = WERR_OK;
82
83         if (ctx == NULL) {
84                 DEBUG(1, ("Error: configuration is not open!\n"));
85                 werr = WERR_INVALID_PARAM;
86                 goto done;
87         }
88
89         if (rpd(ctx)->token == NULL) {
90                 DEBUG(1, ("Error: token missing from smbconf_ctx. "
91                           "was smbconf_init() called?\n"));
92                 werr = WERR_INVALID_PARAM;
93                 goto done;
94         }
95
96         werr = ctx->ops->open_conf(ctx);
97         if (!W_ERROR_IS_OK(werr)) {
98                 DEBUG(1, ("Error opening the registry.\n"));
99                 goto done;
100         }
101
102         if (path == NULL) {
103                 DEBUG(1, ("Error: NULL path string given\n"));
104                 werr = WERR_INVALID_PARAM;
105                 goto done;
106         }
107
108         werr = reg_open_path(mem_ctx, path, desired_access, rpd(ctx)->token,
109                              key);
110
111         if (!W_ERROR_IS_OK(werr)) {
112                 DEBUG(1, ("Error opening registry path '%s': %s\n",
113                           path, dos_errstr(werr)));
114         }
115
116 done:
117         return werr;
118 }
119
120 /**
121  * Open a subkey of the base key (i.e a service)
122  */
123 static WERROR smbconf_reg_open_service_key(TALLOC_CTX *mem_ctx,
124                                            struct smbconf_ctx *ctx,
125                                            const char *servicename,
126                                            uint32 desired_access,
127                                            struct registry_key **key)
128 {
129         WERROR werr = WERR_OK;
130         char *path = NULL;
131
132         if (servicename == NULL) {
133                 DEBUG(3, ("Error: NULL servicename given.\n"));
134                 werr = WERR_INVALID_PARAM;
135                 goto done;
136         }
137
138         path = talloc_asprintf(mem_ctx, "%s\\%s", ctx->path, servicename);
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                 goto done;
402         }
403
404         werr = reg_queryvalue(tmp_ctx, key, INCLUDES_VALNAME, &value);
405         if (!W_ERROR_IS_OK(werr)) {
406                 goto done;
407         }
408
409         if (value->type != REG_MULTI_SZ) {
410                 /* wront type -- ignore */
411                 goto done;
412         }
413
414         for (count = 0; count < value->v.multi_sz.num_strings; count++)
415         {
416                 werr = smbconf_add_string_to_array(tmp_ctx,
417                                         &tmp_includes,
418                                         count,
419                                         value->v.multi_sz.strings[count]);
420                 if (!W_ERROR_IS_OK(werr)) {
421                         goto done;
422                 }
423         }
424
425         if (count > 0) {
426                 *includes = talloc_move(mem_ctx, &tmp_includes);
427                 if (*includes == NULL) {
428                         werr = WERR_NOMEM;
429                         goto done;
430                 }
431                 *num_includes = count;
432         } else {
433                 *num_includes = 0;
434                 *includes = NULL;
435         }
436
437 done:
438         TALLOC_FREE(tmp_ctx);
439         return werr;
440 }
441
442 /**
443  * Get the values of a key as a list of value names
444  * and a list of value strings (ordered)
445  */
446 static WERROR smbconf_reg_get_values(TALLOC_CTX *mem_ctx,
447                                      struct registry_key *key,
448                                      uint32_t *num_values,
449                                      char ***value_names,
450                                      char ***value_strings)
451 {
452         TALLOC_CTX *tmp_ctx = NULL;
453         WERROR werr = WERR_OK;
454         uint32_t count;
455         struct registry_value *valvalue = NULL;
456         char *valname = NULL;
457         uint32_t tmp_num_values = 0;
458         char **tmp_valnames = NULL;
459         char **tmp_valstrings = NULL;
460
461         if ((num_values == NULL) || (value_names == NULL) ||
462             (value_strings == NULL))
463         {
464                 werr = WERR_INVALID_PARAM;
465                 goto done;
466         }
467
468         tmp_ctx = talloc_stackframe();
469         if (tmp_ctx == NULL) {
470                 werr = WERR_NOMEM;
471                 goto done;
472         }
473
474         for (count = 0;
475              werr = reg_enumvalue(tmp_ctx, key, count, &valname, &valvalue),
476              W_ERROR_IS_OK(werr);
477              count++)
478         {
479                 char *valstring;
480
481                 if (!smbconf_reg_valname_valid(valname)) {
482                         continue;
483                 }
484
485                 werr = smbconf_add_string_to_array(tmp_ctx,
486                                                    &tmp_valnames,
487                                                    tmp_num_values, valname);
488                 if (!W_ERROR_IS_OK(werr)) {
489                         goto done;
490                 }
491
492                 valstring = smbconf_format_registry_value(tmp_ctx, valvalue);
493                 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_valstrings,
494                                                    tmp_num_values, valstring);
495                 if (!W_ERROR_IS_OK(werr)) {
496                         goto done;
497                 }
498                 tmp_num_values++;
499         }
500         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
501                 goto done;
502         }
503
504         werr = WERR_OK;
505
506         *num_values = tmp_num_values;
507         if (tmp_num_values > 0) {
508                 *value_names = talloc_move(mem_ctx, &tmp_valnames);
509                 *value_strings = talloc_move(mem_ctx, &tmp_valstrings);
510         } else {
511                 *value_names = NULL;
512                 *value_strings = NULL;
513         }
514
515 done:
516         TALLOC_FREE(tmp_ctx);
517         return werr;
518 }
519
520 /**********************************************************************
521  *
522  * smbconf operations: registry implementations
523  *
524  **********************************************************************/
525
526 /**
527  * initialize the registry smbconf backend
528  */
529 static WERROR smbconf_reg_init(struct smbconf_ctx *ctx, const char *path)
530 {
531         WERROR werr = WERR_OK;
532
533         if (path == NULL) {
534                 path = KEY_SMBCONF;
535         }
536         ctx->path = talloc_strdup(ctx, path);
537         if (ctx->path == NULL) {
538                 werr = WERR_NOMEM;
539                 goto done;
540         }
541
542         ctx->data = TALLOC_ZERO_P(ctx, struct reg_private_data);
543
544         werr = ntstatus_to_werror(registry_create_admin_token(ctx,
545                                                         &(rpd(ctx)->token)));
546         if (!W_ERROR_IS_OK(werr)) {
547                 DEBUG(1, ("Error creating admin token\n"));
548                 goto done;
549         }
550         rpd(ctx)->open = false;
551
552         if (!registry_init_smbconf()) {
553                 werr = WERR_REG_IO_FAILURE;
554                 goto done;
555         }
556
557 done:
558         return werr;
559 }
560
561 static int smbconf_reg_shutdown(struct smbconf_ctx *ctx)
562 {
563         return ctx->ops->close_conf(ctx);
564 }
565
566 static WERROR smbconf_reg_open(struct smbconf_ctx *ctx)
567 {
568         WERROR werr;
569
570         if (rpd(ctx)->open) {
571                 return WERR_OK;
572         }
573
574         werr = regdb_open();
575         if (W_ERROR_IS_OK(werr)) {
576                 rpd(ctx)->open = true;
577         }
578         return werr;
579 }
580
581 static int smbconf_reg_close(struct smbconf_ctx *ctx)
582 {
583         int ret;
584
585         if (!rpd(ctx)->open) {
586                 return 0;
587         }
588
589         ret = regdb_close();
590         if (ret == 0) {
591                 rpd(ctx)->open = false;
592         }
593         return ret;
594 }
595
596 /**
597  * Get the change sequence number of the given service/parameter.
598  * service and parameter strings may be NULL.
599  */
600 static void smbconf_reg_get_csn(struct smbconf_ctx *ctx,
601                                 struct smbconf_csn *csn,
602                                 const char *service, const char *param)
603 {
604         if (csn == NULL) {
605                 return;
606         }
607
608         if (!W_ERROR_IS_OK(ctx->ops->open_conf(ctx))) {
609                 return;
610         }
611
612         csn->csn = (uint64_t)regdb_get_seqnum();
613 }
614
615 /**
616  * Drop the whole configuration (restarting empty) - registry version
617  */
618 static WERROR smbconf_reg_drop(struct smbconf_ctx *ctx)
619 {
620         char *path, *p;
621         WERROR werr = WERR_OK;
622         struct registry_key *parent_key = NULL;
623         struct registry_key *new_key = NULL;
624         TALLOC_CTX* mem_ctx = talloc_stackframe();
625         enum winreg_CreateAction action;
626
627         path = talloc_strdup(mem_ctx, ctx->path);
628         if (path == NULL) {
629                 werr = WERR_NOMEM;
630                 goto done;
631         }
632         p = strrchr(path, '\\');
633         *p = '\0';
634         werr = smbconf_reg_open_path(mem_ctx, ctx, path, REG_KEY_WRITE,
635                                      &parent_key);
636
637         if (!W_ERROR_IS_OK(werr)) {
638                 goto done;
639         }
640
641         werr = reg_deletekey_recursive(mem_ctx, parent_key, p+1);
642
643         if (!W_ERROR_IS_OK(werr)) {
644                 goto done;
645         }
646
647         werr = reg_createkey(mem_ctx, parent_key, p+1, REG_KEY_WRITE,
648                              &new_key, &action);
649
650 done:
651         TALLOC_FREE(mem_ctx);
652         return werr;
653 }
654
655 /**
656  * get the list of share names defined in the configuration.
657  * registry version.
658  */
659 static WERROR smbconf_reg_get_share_names(struct smbconf_ctx *ctx,
660                                           TALLOC_CTX *mem_ctx,
661                                           uint32_t *num_shares,
662                                           char ***share_names)
663 {
664         uint32_t count;
665         uint32_t added_count = 0;
666         TALLOC_CTX *tmp_ctx = NULL;
667         WERROR werr = WERR_OK;
668         struct registry_key *key = NULL;
669         char *subkey_name = NULL;
670         char **tmp_share_names = NULL;
671
672         if ((num_shares == NULL) || (share_names == NULL)) {
673                 werr = WERR_INVALID_PARAM;
674                 goto done;
675         }
676
677         tmp_ctx = talloc_stackframe();
678         if (tmp_ctx == NULL) {
679                 werr = WERR_NOMEM;
680                 goto done;
681         }
682
683         /* make sure "global" is always listed first */
684         if (smbconf_share_exists(ctx, GLOBAL_NAME)) {
685                 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
686                                                    0, GLOBAL_NAME);
687                 if (!W_ERROR_IS_OK(werr)) {
688                         goto done;
689                 }
690                 added_count++;
691         }
692
693         werr = smbconf_reg_open_base_key(tmp_ctx, ctx,
694                                          SEC_RIGHTS_ENUM_SUBKEYS, &key);
695         if (!W_ERROR_IS_OK(werr)) {
696                 goto done;
697         }
698
699         for (count = 0;
700              werr = reg_enumkey(tmp_ctx, key, count, &subkey_name, NULL),
701              W_ERROR_IS_OK(werr);
702              count++)
703         {
704                 if (strequal(subkey_name, GLOBAL_NAME)) {
705                         continue;
706                 }
707
708                 werr = smbconf_add_string_to_array(tmp_ctx,
709                                                    &tmp_share_names,
710                                                    added_count,
711                                                    subkey_name);
712                 if (!W_ERROR_IS_OK(werr)) {
713                         goto done;
714                 }
715                 added_count++;
716         }
717         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
718                 goto done;
719         }
720         werr = WERR_OK;
721
722         *num_shares = added_count;
723         if (added_count > 0) {
724                 *share_names = talloc_move(mem_ctx, &tmp_share_names);
725         } else {
726                 *share_names = NULL;
727         }
728
729 done:
730         TALLOC_FREE(tmp_ctx);
731         return werr;
732 }
733
734 /**
735  * check if a share/service of a given name exists - registry version
736  */
737 static bool smbconf_reg_share_exists(struct smbconf_ctx *ctx,
738                                      const char *servicename)
739 {
740         bool ret = false;
741         WERROR werr = WERR_OK;
742         TALLOC_CTX *mem_ctx = talloc_stackframe();
743         struct registry_key *key = NULL;
744
745         werr = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
746                                             REG_KEY_READ, &key);
747         if (W_ERROR_IS_OK(werr)) {
748                 ret = true;
749         }
750
751         TALLOC_FREE(mem_ctx);
752         return ret;
753 }
754
755 /**
756  * Add a service if it does not already exist - registry version
757  */
758 static WERROR smbconf_reg_create_share(struct smbconf_ctx *ctx,
759                                        const char *servicename)
760 {
761         WERROR werr;
762         TALLOC_CTX *mem_ctx = talloc_stackframe();
763         struct registry_key *key = NULL;
764
765         werr = smbconf_reg_create_service_key(mem_ctx, ctx, servicename, &key);
766
767         TALLOC_FREE(mem_ctx);
768         return werr;
769 }
770
771 /**
772  * get a definition of a share (service) from configuration.
773  */
774 static WERROR smbconf_reg_get_share(struct smbconf_ctx *ctx,
775                                     TALLOC_CTX *mem_ctx,
776                                     const char *servicename,
777                                     uint32_t *num_params,
778                                     char ***param_names, char ***param_values)
779 {
780         WERROR werr = WERR_OK;
781         struct registry_key *key = NULL;
782
783         werr = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
784                                             REG_KEY_READ, &key);
785         if (!W_ERROR_IS_OK(werr)) {
786                 goto done;
787         }
788
789         werr = smbconf_reg_get_values(mem_ctx, key, num_params,
790                                       param_names, param_values);
791
792 done:
793         TALLOC_FREE(key);
794         return werr;
795 }
796
797 /**
798  * delete a service from configuration
799  */
800 static WERROR smbconf_reg_delete_share(struct smbconf_ctx *ctx,
801                                        const char *servicename)
802 {
803         WERROR werr = WERR_OK;
804         struct registry_key *key = NULL;
805         TALLOC_CTX *mem_ctx = talloc_stackframe();
806
807         werr = smbconf_reg_open_base_key(mem_ctx, ctx, REG_KEY_WRITE, &key);
808         if (!W_ERROR_IS_OK(werr)) {
809                 goto done;
810         }
811
812         werr = reg_deletekey_recursive(key, key, servicename);
813
814 done:
815         TALLOC_FREE(mem_ctx);
816         return werr;
817 }
818
819 /**
820  * set a configuration parameter to the value provided.
821  */
822 static WERROR smbconf_reg_set_parameter(struct smbconf_ctx *ctx,
823                                         const char *service,
824                                         const char *param,
825                                         const char *valstr)
826 {
827         WERROR werr;
828         struct registry_key *key = NULL;
829         TALLOC_CTX *mem_ctx = talloc_stackframe();
830
831         werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
832                                             REG_KEY_WRITE, &key);
833         if (!W_ERROR_IS_OK(werr)) {
834                 goto done;
835         }
836
837         werr = smbconf_reg_set_value(key, param, valstr);
838
839 done:
840         TALLOC_FREE(mem_ctx);
841         return werr;
842 }
843
844 /**
845  * get the value of a configuration parameter as a string
846  */
847 static WERROR smbconf_reg_get_parameter(struct smbconf_ctx *ctx,
848                                         TALLOC_CTX *mem_ctx,
849                                         const char *service,
850                                         const char *param,
851                                         char **valstr)
852 {
853         WERROR werr = WERR_OK;
854         struct registry_key *key = NULL;
855         struct registry_value *value = NULL;
856
857         werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
858                                             REG_KEY_READ, &key);
859         if (!W_ERROR_IS_OK(werr)) {
860                 goto done;
861         }
862
863         if (!smbconf_value_exists(key, param)) {
864                 werr = WERR_INVALID_PARAM;
865                 goto done;
866         }
867
868         werr = reg_queryvalue(mem_ctx, key, param, &value);
869         if (!W_ERROR_IS_OK(werr)) {
870                 goto done;
871         }
872
873         *valstr = smbconf_format_registry_value(mem_ctx, value);
874
875         if (*valstr == NULL) {
876                 werr = WERR_NOMEM;
877         }
878
879 done:
880         TALLOC_FREE(key);
881         TALLOC_FREE(value);
882         return werr;
883 }
884
885 /**
886  * delete a parameter from configuration
887  */
888 static WERROR smbconf_reg_delete_parameter(struct smbconf_ctx *ctx,
889                                            const char *service,
890                                            const char *param)
891 {
892         struct registry_key *key = NULL;
893         WERROR werr = WERR_OK;
894         TALLOC_CTX *mem_ctx = talloc_stackframe();
895
896         werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
897                                             REG_KEY_ALL, &key);
898         if (!W_ERROR_IS_OK(werr)) {
899                 goto done;
900         }
901
902         if (!smbconf_value_exists(key, param)) {
903                 werr = WERR_INVALID_PARAM;
904                 goto done;
905         }
906
907         werr = reg_deletevalue(key, param);
908
909 done:
910         TALLOC_FREE(mem_ctx);
911         return werr;
912 }
913
914 static WERROR smbconf_reg_get_includes(struct smbconf_ctx *ctx,
915                                        TALLOC_CTX *mem_ctx,
916                                        const char *service,
917                                        uint32_t *num_includes,
918                                        char ***includes)
919 {
920         WERROR werr;
921         struct registry_key *key = NULL;
922         TALLOC_CTX *tmp_ctx = talloc_stackframe();
923
924         werr = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
925                                             REG_KEY_READ, &key);
926         if (!W_ERROR_IS_OK(werr)) {
927                 goto done;
928         }
929
930         werr = smbconf_reg_get_includes_internal(mem_ctx, key, num_includes,
931                                                  includes);
932
933 done:
934         TALLOC_FREE(tmp_ctx);
935         return werr;
936 }
937
938 static WERROR smbconf_reg_set_includes(struct smbconf_ctx *ctx,
939                                        const char *service,
940                                        uint32_t num_includes,
941                                        const char **includes)
942 {
943         WERROR werr = WERR_OK;
944         struct registry_key *key = NULL;
945         TALLOC_CTX *tmp_ctx = talloc_stackframe();
946
947         werr = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
948                                             REG_KEY_ALL, &key);
949         if (!W_ERROR_IS_OK(werr)) {
950                 goto done;
951         }
952
953         werr = smbconf_reg_set_multi_sz_value(key, INCLUDES_VALNAME,
954                                               num_includes, includes);
955
956 done:
957         TALLOC_FREE(tmp_ctx);
958         return werr;
959 }
960
961
962 struct smbconf_ops smbconf_ops_reg = {
963         .init                   = smbconf_reg_init,
964         .shutdown               = smbconf_reg_shutdown,
965         .open_conf              = smbconf_reg_open,
966         .close_conf             = smbconf_reg_close,
967         .get_csn                = smbconf_reg_get_csn,
968         .drop                   = smbconf_reg_drop,
969         .get_share_names        = smbconf_reg_get_share_names,
970         .share_exists           = smbconf_reg_share_exists,
971         .create_share           = smbconf_reg_create_share,
972         .get_share              = smbconf_reg_get_share,
973         .delete_share           = smbconf_reg_delete_share,
974         .set_parameter          = smbconf_reg_set_parameter,
975         .get_parameter          = smbconf_reg_get_parameter,
976         .delete_parameter       = smbconf_reg_delete_parameter,
977         .get_includes           = smbconf_reg_get_includes,
978         .set_includes           = smbconf_reg_set_includes,
979 };
980
981
982 /**
983  * initialize the smbconf registry backend
984  * the only function that is exported from this module
985  */
986 WERROR smbconf_init_reg(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx,
987                         const char *path)
988 {
989         return smbconf_init(mem_ctx, conf_ctx, path, &smbconf_ops_reg);
990 }