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