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