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