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