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