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