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