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