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