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