libsmbconf: Convert smbconf_delete_share() to sbcErr.
[ddiss/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 sbcErr smbconf_reg_delete_values(struct registry_key *key)
542 {
543         WERROR werr;
544         sbcErr err;
545         char *valname;
546         struct registry_value *valvalue;
547         uint32_t count;
548         TALLOC_CTX *mem_ctx = talloc_stackframe();
549
550         for (count = 0;
551              werr = reg_enumvalue(mem_ctx, key, count, &valname, &valvalue),
552              W_ERROR_IS_OK(werr);
553              count++)
554         {
555                 werr = reg_deletevalue(key, valname);
556                 if (!W_ERROR_IS_OK(werr)) {
557                         err = SBC_ERR_ACCESS_DENIED;
558                         goto done;
559                 }
560         }
561         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
562                 DEBUG(1, ("smbconf_reg_delete_values: "
563                           "Error enumerating values of %s: %s\n",
564                           key->key->name,
565                           win_errstr(werr)));
566                 err = SBC_ERR_ACCESS_DENIED;
567                 goto done;
568         }
569
570         err = SBC_ERR_OK;
571
572 done:
573         talloc_free(mem_ctx);
574         return err;
575 }
576
577 /**********************************************************************
578  *
579  * smbconf operations: registry implementations
580  *
581  **********************************************************************/
582
583 /**
584  * initialize the registry smbconf backend
585  */
586 static sbcErr smbconf_reg_init(struct smbconf_ctx *ctx, const char *path)
587 {
588         WERROR werr = WERR_OK;
589         sbcErr err;
590         struct security_token *token;
591
592         if (path == NULL) {
593                 path = KEY_SMBCONF;
594         }
595         ctx->path = talloc_strdup(ctx, path);
596         if (ctx->path == NULL) {
597                 werr = WERR_NOMEM;
598                 goto done;
599         }
600
601         ctx->data = TALLOC_ZERO_P(ctx, struct reg_private_data);
602
603         werr = ntstatus_to_werror(registry_create_admin_token(ctx, &token));
604         if (!W_ERROR_IS_OK(werr)) {
605                 DEBUG(1, ("Error creating admin token\n"));
606                 err = SBC_ERR_UNKNOWN_FAILURE;
607                 goto done;
608         }
609         rpd(ctx)->open = false;
610
611         werr = registry_init_smbconf(path);
612         if (!W_ERROR_IS_OK(werr)) {
613                 err = SBC_ERR_BADFILE;
614                 goto done;
615         }
616
617         err = ctx->ops->open_conf(ctx);
618         if (!SBC_ERROR_IS_OK(err)) {
619                 DEBUG(1, ("Error opening the registry.\n"));
620                 goto done;
621         }
622
623         werr = reg_open_path(ctx, ctx->path,
624                              KEY_ENUMERATE_SUB_KEYS | REG_KEY_WRITE,
625                              token, &rpd(ctx)->base_key);
626         if (!W_ERROR_IS_OK(werr)) {
627                 err = SBC_ERR_UNKNOWN_FAILURE;
628                 goto done;
629         }
630
631 done:
632         return err;
633 }
634
635 static int smbconf_reg_shutdown(struct smbconf_ctx *ctx)
636 {
637         return ctx->ops->close_conf(ctx);
638 }
639
640 static bool smbconf_reg_requires_messaging(struct smbconf_ctx *ctx)
641 {
642 #ifdef CLUSTER_SUPPORT
643         if (lp_clustering() && lp_parm_bool(-1, "ctdb", "registry.tdb", true)) {
644                 return true;
645         }
646 #endif
647         return false;
648 }
649
650 static bool smbconf_reg_is_writeable(struct smbconf_ctx *ctx)
651 {
652         /*
653          * The backend has write support.
654          *
655          *  TODO: add access checks whether the concrete
656          *  config source is really writeable by the calling user.
657          */
658         return true;
659 }
660
661 static sbcErr smbconf_reg_open(struct smbconf_ctx *ctx)
662 {
663         WERROR werr;
664
665         if (rpd(ctx)->open) {
666                 return SBC_ERR_OK;
667         }
668
669         werr = regdb_open();
670         if (!W_ERROR_IS_OK(werr)) {
671                 return SBC_ERR_BADFILE;
672         }
673
674         rpd(ctx)->open = true;
675         return SBC_ERR_OK;
676 }
677
678 static int smbconf_reg_close(struct smbconf_ctx *ctx)
679 {
680         int ret;
681
682         if (!rpd(ctx)->open) {
683                 return 0;
684         }
685
686         ret = regdb_close();
687         if (ret == 0) {
688                 rpd(ctx)->open = false;
689         }
690         return ret;
691 }
692
693 /**
694  * Get the change sequence number of the given service/parameter.
695  * service and parameter strings may be NULL.
696  */
697 static void smbconf_reg_get_csn(struct smbconf_ctx *ctx,
698                                 struct smbconf_csn *csn,
699                                 const char *service, const char *param)
700 {
701         if (csn == NULL) {
702                 return;
703         }
704
705         if (!SBC_ERROR_IS_OK(ctx->ops->open_conf(ctx))) {
706                 return;
707         }
708
709         csn->csn = (uint64_t)regdb_get_seqnum();
710 }
711
712 /**
713  * Drop the whole configuration (restarting empty) - registry version
714  */
715 static sbcErr smbconf_reg_drop(struct smbconf_ctx *ctx)
716 {
717         char *path, *p;
718         WERROR werr = WERR_OK;
719         sbcErr err = SBC_ERR_OK;
720         struct registry_key *parent_key = NULL;
721         struct registry_key *new_key = NULL;
722         TALLOC_CTX* mem_ctx = talloc_stackframe();
723         enum winreg_CreateAction action;
724         struct security_token *token;
725
726         werr = ntstatus_to_werror(registry_create_admin_token(ctx, &token));
727         if (!W_ERROR_IS_OK(werr)) {
728                 DEBUG(1, ("Error creating admin token\n"));
729                 err = SBC_ERR_UNKNOWN_FAILURE;
730                 goto done;
731         }
732
733         path = talloc_strdup(mem_ctx, ctx->path);
734         if (path == NULL) {
735                 err = SBC_ERR_NOMEM;
736                 goto done;
737         }
738         p = strrchr(path, '\\');
739         if (p == NULL) {
740                 err = SBC_ERR_INVALID_PARAM;
741                 goto done;
742         }
743         *p = '\0';
744         werr = reg_open_path(mem_ctx, path, REG_KEY_WRITE, token,
745                              &parent_key);
746         if (!W_ERROR_IS_OK(werr)) {
747                 err = SBC_ERR_IO_FAILURE;
748                 goto done;
749         }
750
751         werr = reg_deletekey_recursive(parent_key, p+1);
752         if (!W_ERROR_IS_OK(werr)) {
753                 err = SBC_ERR_IO_FAILURE;
754                 goto done;
755         }
756
757         werr = reg_createkey(mem_ctx, parent_key, p+1, REG_KEY_WRITE,
758                              &new_key, &action);
759         if (!W_ERROR_IS_OK(werr)) {
760                 err = SBC_ERR_IO_FAILURE;
761                 goto done;
762         }
763
764 done:
765         talloc_free(mem_ctx);
766         return err;
767 }
768
769 /**
770  * get the list of share names defined in the configuration.
771  * registry version.
772  */
773 static sbcErr smbconf_reg_get_share_names(struct smbconf_ctx *ctx,
774                                           TALLOC_CTX *mem_ctx,
775                                           uint32_t *num_shares,
776                                           char ***share_names)
777 {
778         uint32_t count;
779         uint32_t added_count = 0;
780         TALLOC_CTX *tmp_ctx = NULL;
781         WERROR werr;
782         sbcErr err = SBC_ERR_OK;
783         char *subkey_name = NULL;
784         char **tmp_share_names = NULL;
785
786         if ((num_shares == NULL) || (share_names == NULL)) {
787                 return SBC_ERR_INVALID_PARAM;
788         }
789
790         tmp_ctx = talloc_stackframe();
791
792         /* if there are values in the base key, return NULL as share name */
793
794         if (smbconf_reg_key_has_values(rpd(ctx)->base_key)) {
795                 err = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
796                                                    0, NULL);
797                 if (!SBC_ERROR_IS_OK(err)) {
798                         goto done;
799                 }
800                 added_count++;
801         }
802
803         /* make sure "global" is always listed first */
804         if (smbconf_share_exists(ctx, GLOBAL_NAME)) {
805                 err = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
806                                                   added_count, GLOBAL_NAME);
807                 if (!SBC_ERROR_IS_OK(err)) {
808                         goto done;
809                 }
810                 added_count++;
811         }
812
813         for (count = 0;
814              werr = reg_enumkey(tmp_ctx, rpd(ctx)->base_key, count,
815                                 &subkey_name, NULL),
816              W_ERROR_IS_OK(werr);
817              count++)
818         {
819                 if (strequal(subkey_name, GLOBAL_NAME)) {
820                         continue;
821                 }
822
823                 err = smbconf_add_string_to_array(tmp_ctx,
824                                                    &tmp_share_names,
825                                                    added_count,
826                                                    subkey_name);
827                 if (!SBC_ERROR_IS_OK(err)) {
828                         goto done;
829                 }
830                 added_count++;
831         }
832         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
833                 err = SBC_ERR_NO_MORE_ITEMS;
834                 goto done;
835         }
836         err = SBC_ERR_OK;
837
838         *num_shares = added_count;
839         if (added_count > 0) {
840                 *share_names = talloc_move(mem_ctx, &tmp_share_names);
841         } else {
842                 *share_names = NULL;
843         }
844
845 done:
846         talloc_free(tmp_ctx);
847         return err;
848 }
849
850 /**
851  * check if a share/service of a given name exists - registry version
852  */
853 static bool smbconf_reg_share_exists(struct smbconf_ctx *ctx,
854                                      const char *servicename)
855 {
856         bool ret = false;
857         sbcErr err;
858         TALLOC_CTX *mem_ctx = talloc_stackframe();
859         struct registry_key *key = NULL;
860
861         err = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
862                                            REG_KEY_READ, &key);
863         if (SBC_ERROR_IS_OK(err)) {
864                 ret = true;
865         }
866
867         talloc_free(mem_ctx);
868         return ret;
869 }
870
871 /**
872  * Add a service if it does not already exist - registry version
873  */
874 static sbcErr smbconf_reg_create_share(struct smbconf_ctx *ctx,
875                                        const char *servicename)
876 {
877         sbcErr err;
878         struct registry_key *key = NULL;
879
880         if (servicename == NULL) {
881                 return SBC_ERR_OK;
882         }
883
884         err = smbconf_reg_create_service_key(talloc_tos(), ctx,
885                                              servicename, &key);
886
887         talloc_free(key);
888         return err;
889 }
890
891 /**
892  * get a definition of a share (service) from configuration.
893  */
894 static sbcErr smbconf_reg_get_share(struct smbconf_ctx *ctx,
895                                     TALLOC_CTX *mem_ctx,
896                                     const char *servicename,
897                                     struct smbconf_service **service)
898 {
899         sbcErr err;
900         struct registry_key *key = NULL;
901         struct smbconf_service *tmp_service = NULL;
902         TALLOC_CTX *tmp_ctx = talloc_stackframe();
903
904         err = smbconf_reg_open_service_key(tmp_ctx, ctx, servicename,
905                                            REG_KEY_READ, &key);
906         if (!SBC_ERROR_IS_OK(err)) {
907                 goto done;
908         }
909
910         tmp_service = TALLOC_ZERO_P(tmp_ctx, struct smbconf_service);
911         if (tmp_service == NULL) {
912                 err = SBC_ERR_NOMEM;
913                 goto done;
914         }
915
916         if (servicename != NULL) {
917                 tmp_service->name = talloc_strdup(tmp_service, servicename);
918                 if (tmp_service->name == NULL) {
919                         err = SBC_ERR_NOMEM;
920                         goto done;
921                 }
922         }
923
924         err = smbconf_reg_get_values(tmp_service, key,
925                                      &(tmp_service->num_params),
926                                      &(tmp_service->param_names),
927                                      &(tmp_service->param_values));
928         if (SBC_ERROR_IS_OK(err)) {
929                 *service = talloc_move(mem_ctx, &tmp_service);
930         }
931
932 done:
933         talloc_free(tmp_ctx);
934         return err;
935 }
936
937 /**
938  * delete a service from configuration
939  */
940 static sbcErr smbconf_reg_delete_share(struct smbconf_ctx *ctx,
941                                        const char *servicename)
942 {
943         WERROR werr;
944         sbcErr err = SBC_ERR_OK;
945         TALLOC_CTX *mem_ctx = talloc_stackframe();
946
947         if (servicename != NULL) {
948                 werr = reg_deletekey_recursive(rpd(ctx)->base_key, servicename);
949                 if (!W_ERROR_IS_OK(werr)) {
950                         err = SBC_ERR_ACCESS_DENIED;
951                 }
952         } else {
953                 err = smbconf_reg_delete_values(rpd(ctx)->base_key);
954         }
955
956         talloc_free(mem_ctx);
957         return err;
958 }
959
960 /**
961  * set a configuration parameter to the value provided.
962  */
963 static WERROR smbconf_reg_set_parameter(struct smbconf_ctx *ctx,
964                                         const char *service,
965                                         const char *param,
966                                         const char *valstr)
967 {
968         WERROR werr;
969         sbcErr err;
970         struct registry_key *key = NULL;
971         TALLOC_CTX *mem_ctx = talloc_stackframe();
972
973         err = smbconf_reg_open_service_key(mem_ctx, ctx, service,
974                                            REG_KEY_WRITE, &key);
975         if (!SBC_ERROR_IS_OK(err)) {
976                 werr = WERR_NOMEM;
977                 goto done;
978         }
979
980         werr = smbconf_reg_set_value(key, param, valstr);
981
982 done:
983         talloc_free(mem_ctx);
984         return werr;
985 }
986
987 /**
988  * get the value of a configuration parameter as a string
989  */
990 static WERROR smbconf_reg_get_parameter(struct smbconf_ctx *ctx,
991                                         TALLOC_CTX *mem_ctx,
992                                         const char *service,
993                                         const char *param,
994                                         char **valstr)
995 {
996         WERROR werr = WERR_OK;
997         sbcErr err;
998         struct registry_key *key = NULL;
999         struct registry_value *value = NULL;
1000
1001         err = smbconf_reg_open_service_key(mem_ctx, ctx, service,
1002                                            REG_KEY_READ, &key);
1003         if (!SBC_ERROR_IS_OK(err)) {
1004                 werr = WERR_NOMEM;
1005                 goto done;
1006         }
1007
1008         if (!smbconf_reg_valname_valid(param)) {
1009                 werr = WERR_INVALID_PARAM;
1010                 goto done;
1011         }
1012
1013         if (!smbconf_value_exists(key, param)) {
1014                 werr = WERR_INVALID_PARAM;
1015                 goto done;
1016         }
1017
1018         werr = reg_queryvalue(mem_ctx, key, param, &value);
1019         if (!W_ERROR_IS_OK(werr)) {
1020                 goto done;
1021         }
1022
1023         *valstr = smbconf_format_registry_value(mem_ctx, value);
1024
1025         if (*valstr == NULL) {
1026                 werr = WERR_NOMEM;
1027         }
1028
1029 done:
1030         talloc_free(key);
1031         talloc_free(value);
1032         return werr;
1033 }
1034
1035 /**
1036  * delete a parameter from configuration
1037  */
1038 static WERROR smbconf_reg_delete_parameter(struct smbconf_ctx *ctx,
1039                                            const char *service,
1040                                            const char *param)
1041 {
1042         struct registry_key *key = NULL;
1043         WERROR werr = WERR_OK;
1044         sbcErr err;
1045         TALLOC_CTX *mem_ctx = talloc_stackframe();
1046
1047         err = smbconf_reg_open_service_key(mem_ctx, ctx, service,
1048                                            REG_KEY_ALL, &key);
1049         if (!SBC_ERROR_IS_OK(err)) {
1050                 werr = WERR_NOMEM;
1051                 goto done;
1052         }
1053
1054         if (!smbconf_reg_valname_valid(param)) {
1055                 werr = WERR_INVALID_PARAM;
1056                 goto done;
1057         }
1058
1059         if (!smbconf_value_exists(key, param)) {
1060                 werr = WERR_INVALID_PARAM;
1061                 goto done;
1062         }
1063
1064         werr = reg_deletevalue(key, param);
1065
1066 done:
1067         talloc_free(mem_ctx);
1068         return werr;
1069 }
1070
1071 static WERROR smbconf_reg_get_includes(struct smbconf_ctx *ctx,
1072                                        TALLOC_CTX *mem_ctx,
1073                                        const char *service,
1074                                        uint32_t *num_includes,
1075                                        char ***includes)
1076 {
1077         WERROR werr;
1078         sbcErr err;
1079         struct registry_key *key = NULL;
1080         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1081
1082         err = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
1083                                            REG_KEY_READ, &key);
1084         if (!SBC_ERROR_IS_OK(err)) {
1085                 werr = WERR_NOMEM;
1086                 goto done;
1087         }
1088
1089         err = smbconf_reg_get_includes_internal(mem_ctx, key, num_includes,
1090                                                  includes);
1091         if (!SBC_ERROR_IS_OK(err)) {
1092                 werr = WERR_NOMEM;
1093                 goto done;
1094         }
1095
1096 done:
1097         talloc_free(tmp_ctx);
1098         return werr;
1099 }
1100
1101 static WERROR smbconf_reg_set_includes(struct smbconf_ctx *ctx,
1102                                        const char *service,
1103                                        uint32_t num_includes,
1104                                        const char **includes)
1105 {
1106         WERROR werr = WERR_OK;
1107         sbcErr err;
1108         struct registry_key *key = NULL;
1109         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1110
1111         err = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
1112                                            REG_KEY_ALL, &key);
1113         if (!SBC_ERROR_IS_OK(err)) {
1114                 werr = WERR_NOMEM;
1115                 goto done;
1116         }
1117
1118         if (num_includes == 0) {
1119                 if (!smbconf_value_exists(key, INCLUDES_VALNAME)) {
1120                         goto done;
1121                 }
1122                 werr = reg_deletevalue(key, INCLUDES_VALNAME);
1123         } else {
1124                 werr = smbconf_reg_set_multi_sz_value(key, INCLUDES_VALNAME,
1125                                                       num_includes, includes);
1126         }
1127
1128 done:
1129         talloc_free(tmp_ctx);
1130         return werr;
1131 }
1132
1133 static WERROR smbconf_reg_delete_includes(struct smbconf_ctx *ctx,
1134                                           const char *service)
1135 {
1136         WERROR werr = WERR_OK;
1137         sbcErr err;
1138         struct registry_key *key = NULL;
1139         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1140
1141         err = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
1142                                            REG_KEY_ALL, &key);
1143         if (!SBC_ERROR_IS_OK(err)) {
1144                 werr = WERR_NOMEM;
1145                 goto done;
1146         }
1147
1148         if (!smbconf_value_exists(key, INCLUDES_VALNAME)) {
1149                 goto done;
1150         }
1151
1152         werr = reg_deletevalue(key, INCLUDES_VALNAME);
1153
1154
1155 done:
1156         talloc_free(tmp_ctx);
1157         return werr;
1158 }
1159
1160 static WERROR smbconf_reg_transaction_start(struct smbconf_ctx *ctx)
1161 {
1162         return regdb_transaction_start();
1163 }
1164
1165 static WERROR smbconf_reg_transaction_commit(struct smbconf_ctx *ctx)
1166 {
1167         return regdb_transaction_commit();
1168 }
1169
1170 static WERROR smbconf_reg_transaction_cancel(struct smbconf_ctx *ctx)
1171 {
1172         return regdb_transaction_cancel();
1173 }
1174
1175 struct smbconf_ops smbconf_ops_reg = {
1176         .init                   = smbconf_reg_init,
1177         .shutdown               = smbconf_reg_shutdown,
1178         .requires_messaging     = smbconf_reg_requires_messaging,
1179         .is_writeable           = smbconf_reg_is_writeable,
1180         .open_conf              = smbconf_reg_open,
1181         .close_conf             = smbconf_reg_close,
1182         .get_csn                = smbconf_reg_get_csn,
1183         .drop                   = smbconf_reg_drop,
1184         .get_share_names        = smbconf_reg_get_share_names,
1185         .share_exists           = smbconf_reg_share_exists,
1186         .create_share           = smbconf_reg_create_share,
1187         .get_share              = smbconf_reg_get_share,
1188         .delete_share           = smbconf_reg_delete_share,
1189         .set_parameter          = smbconf_reg_set_parameter,
1190         .get_parameter          = smbconf_reg_get_parameter,
1191         .delete_parameter       = smbconf_reg_delete_parameter,
1192         .get_includes           = smbconf_reg_get_includes,
1193         .set_includes           = smbconf_reg_set_includes,
1194         .delete_includes        = smbconf_reg_delete_includes,
1195         .transaction_start      = smbconf_reg_transaction_start,
1196         .transaction_commit     = smbconf_reg_transaction_commit,
1197         .transaction_cancel     = smbconf_reg_transaction_cancel,
1198 };
1199
1200
1201 /**
1202  * initialize the smbconf registry backend
1203  * the only function that is exported from this module
1204  */
1205 sbcErr smbconf_init_reg(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx,
1206                         const char *path)
1207 {
1208         return smbconf_init_internal(mem_ctx, conf_ctx, path, &smbconf_ops_reg);
1209 }