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