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