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