Merge commit 'samba/v3-2-test' into v3-2-stable
[bbaumbach/samba-autobuild/.git] / source / libnet / libnet_conf.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  libnet smbconf registry Support
4  *  Copyright (C) Michael Adam 2007-2008
5  *  Copyright (C) Guenther Deschner 2007
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "includes.h"
22 #include "libnet/libnet.h"
23
24 /**********************************************************************
25  *
26  * Helper functions (mostly registry related)
27  * TODO: These should be eventually static.
28
29  **********************************************************************/
30
31 /**
32  * add a string to a talloced array of strings.
33  */
34 static WERROR libnet_conf_add_string_to_array(TALLOC_CTX *mem_ctx,
35                                               char ***array,
36                                               uint32_t count,
37                                               const char *string)
38 {
39         char **new_array = NULL;
40
41         if ((array == NULL) || (string == NULL)) {
42                 return WERR_INVALID_PARAM;
43         }
44
45         new_array = TALLOC_REALLOC_ARRAY(mem_ctx, *array, char *, count + 1);
46         if (new_array == NULL) {
47                 return WERR_NOMEM;
48         }
49
50         new_array[count] = talloc_strdup(new_array, string);
51
52         *array = new_array;
53
54         return WERR_OK;
55 }
56
57 static WERROR libnet_conf_reg_initialize(struct libnet_conf_ctx *ctx)
58 {
59         WERROR werr = WERR_OK;
60
61         if (!registry_init_regdb()) {
62                 werr = WERR_REG_IO_FAILURE;
63                 goto done;
64         }
65
66         werr = ntstatus_to_werror(registry_create_admin_token(ctx,
67                                                               &(ctx->token)));
68         if (!W_ERROR_IS_OK(werr)) {
69                 DEBUG(1, ("Error creating admin token\n"));
70                 goto done;
71         }
72
73 done:
74         return werr;
75 }
76
77 /**
78  * Open a registry key specified by "path"
79  */
80 static WERROR libnet_conf_reg_open_path(TALLOC_CTX *mem_ctx,
81                                         struct libnet_conf_ctx *ctx,
82                                         const char *path,
83                                         uint32 desired_access,
84                                         struct registry_key **key)
85 {
86         WERROR werr = WERR_OK;
87
88         if (ctx == NULL) {
89                 DEBUG(1, ("Error: configuration is not open!\n"));
90                 werr = WERR_INVALID_PARAM;
91                 goto done;
92         }
93
94         if (ctx->token == NULL) {
95                 DEBUG(1, ("Error: token missing from libnet_conf_ctx. "
96                           "was libnet_conf_open() called?\n"));
97                 werr = WERR_INVALID_PARAM;
98                 goto done;
99         }
100
101         if (path == NULL) {
102                 DEBUG(1, ("Error: NULL path string given\n"));
103                 werr = WERR_INVALID_PARAM;
104                 goto done;
105         }
106
107         werr = reg_open_path(mem_ctx, path, desired_access, ctx->token, key);
108
109         if (!W_ERROR_IS_OK(werr)) {
110                 DEBUG(1, ("Error opening registry path '%s': %s\n",
111                           path, dos_errstr(werr)));
112         }
113
114 done:
115         return werr;
116 }
117
118 /**
119  * Open a subkey of KEY_SMBCONF (i.e a service)
120  */
121 static WERROR libnet_conf_reg_open_service_key(TALLOC_CTX *mem_ctx,
122                                                struct libnet_conf_ctx *ctx,
123                                                const char *servicename,
124                                                uint32 desired_access,
125                                                struct registry_key **key)
126 {
127         WERROR werr = WERR_OK;
128         char *path = NULL;
129
130         if (servicename == NULL) {
131                 DEBUG(3, ("Error: NULL servicename given.\n"));
132                 werr = WERR_INVALID_PARAM;
133                 goto done;
134         }
135
136         path = talloc_asprintf(mem_ctx, "%s\\%s", KEY_SMBCONF, servicename);
137
138         werr = libnet_conf_reg_open_path(mem_ctx, ctx, path, desired_access,
139                                          key);
140
141 done:
142         TALLOC_FREE(path);
143         return werr;
144 }
145
146 /**
147  * open the base key KEY_SMBCONF
148  */
149 static WERROR libnet_conf_reg_open_base_key(TALLOC_CTX *mem_ctx,
150                                             struct libnet_conf_ctx *ctx,
151                                             uint32 desired_access,
152                                             struct registry_key **key)
153 {
154         return libnet_conf_reg_open_path(mem_ctx, ctx, KEY_SMBCONF,
155                                          desired_access, key);
156 }
157
158 /**
159  * check if a value exists in a given registry key
160  */
161 static bool libnet_conf_value_exists(struct registry_key *key,
162                                      const char *param)
163 {
164         bool ret = false;
165         WERROR werr = WERR_OK;
166         TALLOC_CTX *ctx = talloc_stackframe();
167         struct registry_value *value = NULL;
168
169         werr = reg_queryvalue(ctx, key, param, &value);
170         if (W_ERROR_IS_OK(werr)) {
171                 ret = true;
172         }
173
174         TALLOC_FREE(ctx);
175         return ret;
176 }
177
178 /**
179  * create a subkey of KEY_SMBCONF
180  */
181 static WERROR libnet_conf_reg_create_service_key(TALLOC_CTX *mem_ctx,
182                                                  struct libnet_conf_ctx *ctx,
183                                                  const char * subkeyname,
184                                                  struct registry_key **newkey)
185 {
186         WERROR werr = WERR_OK;
187         struct registry_key *create_parent = NULL;
188         TALLOC_CTX *create_ctx;
189         enum winreg_CreateAction action = REG_ACTION_NONE;
190
191         /* create a new talloc ctx for creation. it will hold
192          * the intermediate parent key (SMBCONF) for creation
193          * and will be destroyed when leaving this function... */
194         if (!(create_ctx = talloc_new(mem_ctx))) {
195                 werr = WERR_NOMEM;
196                 goto done;
197         }
198
199         werr = libnet_conf_reg_open_base_key(create_ctx, ctx, REG_KEY_WRITE,
200                                              &create_parent);
201         if (!W_ERROR_IS_OK(werr)) {
202                 goto done;
203         }
204
205         werr = reg_createkey(mem_ctx, create_parent, subkeyname,
206                              REG_KEY_WRITE, newkey, &action);
207         if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) {
208                 DEBUG(10, ("Key '%s' already exists.\n", subkeyname));
209                 werr = WERR_ALREADY_EXISTS;
210         }
211         if (!W_ERROR_IS_OK(werr)) {
212                 DEBUG(5, ("Error creating key %s: %s\n",
213                          subkeyname, dos_errstr(werr)));
214         }
215
216 done:
217         TALLOC_FREE(create_ctx);
218         return werr;
219 }
220
221 /**
222  * add a value to a key.
223  */
224 static WERROR libnet_conf_reg_set_value(struct registry_key *key,
225                                         const char *valname,
226                                         const char *valstr)
227 {
228         struct registry_value val;
229         WERROR werr = WERR_OK;
230         char *subkeyname;
231         const char *canon_valname;
232         const char *canon_valstr;
233
234         if (!lp_canonicalize_parameter_with_value(valname, valstr,
235                                                   &canon_valname,
236                                                   &canon_valstr))
237         {
238                 if (canon_valname == NULL) {
239                         DEBUG(5, ("invalid parameter '%s' given\n",
240                                   valname));
241                 } else {
242                         DEBUG(5, ("invalid value '%s' given for "
243                                   "parameter '%s'\n", valstr, valname));
244                 }
245                 werr = WERR_INVALID_PARAM;
246                 goto done;
247         }
248
249         ZERO_STRUCT(val);
250
251         val.type = REG_SZ;
252         val.v.sz.str = CONST_DISCARD(char *, canon_valstr);
253         val.v.sz.len = strlen(canon_valstr) + 1;
254
255         if (registry_smbconf_valname_forbidden(canon_valname)) {
256                 DEBUG(5, ("Parameter '%s' not allowed in registry.\n",
257                           canon_valname));
258                 werr = WERR_INVALID_PARAM;
259                 goto done;
260         }
261
262         subkeyname = strrchr_m(key->key->name, '\\');
263         if ((subkeyname == NULL) || (*(subkeyname +1) == '\0')) {
264                 DEBUG(5, ("Invalid registry key '%s' given as "
265                           "smbconf section.\n", key->key->name));
266                 werr = WERR_INVALID_PARAM;
267                 goto done;
268         }
269         subkeyname++;
270         if (!strequal(subkeyname, GLOBAL_NAME) &&
271             lp_parameter_is_global(valname))
272         {
273                 DEBUG(5, ("Global paramter '%s' not allowed in "
274                           "service definition ('%s').\n", canon_valname,
275                           subkeyname));
276                 werr = WERR_INVALID_PARAM;
277                 goto done;
278         }
279
280         werr = reg_setvalue(key, canon_valname, &val);
281         if (!W_ERROR_IS_OK(werr)) {
282                 DEBUG(5, ("Error adding value '%s' to "
283                           "key '%s': %s\n",
284                           canon_valname, key->key->name, dos_errstr(werr)));
285         }
286
287 done:
288         return werr;
289 }
290
291 /**
292  * format a registry_value into a string.
293  *
294  * This is intended to be used for smbconf registry values,
295  * which are ar stored as REG_SZ values, so the incomplete
296  * handling should be ok.
297  */
298 static char *libnet_conf_format_registry_value(TALLOC_CTX *mem_ctx,
299                                                struct registry_value *value)
300 {
301         char *result = NULL;
302
303         /* alternatively, create a new talloc context? */
304         if (mem_ctx == NULL) {
305                 return result;
306         }
307
308         switch (value->type) {
309         case REG_DWORD:
310                 result = talloc_asprintf(mem_ctx, "%d", value->v.dword);
311                 break;
312         case REG_SZ:
313         case REG_EXPAND_SZ:
314                 result = talloc_asprintf(mem_ctx, "%s", value->v.sz.str);
315                 break;
316         case REG_MULTI_SZ: {
317                 uint32 j;
318                 for (j = 0; j < value->v.multi_sz.num_strings; j++) {
319                         result = talloc_asprintf(mem_ctx, "\"%s\" ",
320                                                  value->v.multi_sz.strings[j]);
321                 }
322                 break;
323         }
324         case REG_BINARY:
325                 result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
326                                          (int)value->v.binary.length);
327                 break;
328         default:
329                 result = talloc_asprintf(mem_ctx, "<unprintable>");
330                 break;
331         }
332         return result;
333 }
334
335 /**
336  * Get the values of a key as a list of value names
337  * and a list of value strings (ordered)
338  */
339 static WERROR libnet_conf_reg_get_values(TALLOC_CTX *mem_ctx,
340                                          struct registry_key *key,
341                                          uint32_t *num_values,
342                                          char ***value_names,
343                                          char ***value_strings)
344 {
345         TALLOC_CTX *tmp_ctx = NULL;
346         WERROR werr = WERR_OK;
347         uint32_t count;
348         struct registry_value *valvalue = NULL;
349         char *valname = NULL;
350         char **tmp_valnames = NULL;
351         char **tmp_valstrings = NULL;
352
353         if ((num_values == NULL) || (value_names == NULL) ||
354             (value_strings == NULL))
355         {
356                 werr = WERR_INVALID_PARAM;
357                 goto done;
358         }
359
360         tmp_ctx = talloc_new(mem_ctx);
361         if (tmp_ctx == NULL) {
362                 werr = WERR_NOMEM;
363                 goto done;
364         }
365
366         for (count = 0;
367              W_ERROR_IS_OK(werr = reg_enumvalue(tmp_ctx, key, count, &valname,
368                                                 &valvalue));
369              count++)
370         {
371                 char *valstring;
372
373                 werr = libnet_conf_add_string_to_array(tmp_ctx,
374                                                        &tmp_valnames,
375                                                        count, valname);
376                 if (!W_ERROR_IS_OK(werr)) {
377                         goto done;
378                 }
379
380                 valstring = libnet_conf_format_registry_value(tmp_ctx,
381                                                               valvalue);
382                 werr = libnet_conf_add_string_to_array(tmp_ctx,
383                                                        &tmp_valstrings,
384                                                        count,
385                                                        valstring);
386                 if (!W_ERROR_IS_OK(werr)) {
387                         goto done;
388                 }
389         }
390         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
391                 goto done;
392         }
393
394         werr = WERR_OK;
395
396         *num_values = count;
397         if (count > 0) {
398                 *value_names = talloc_move(mem_ctx, &tmp_valnames);
399                 *value_strings = talloc_move(mem_ctx, &tmp_valstrings);
400         } else {
401                 *value_names = NULL;
402                 *value_strings = NULL;
403         }
404
405 done:
406         TALLOC_FREE(tmp_ctx);
407         return werr;
408 }
409
410 static int libnet_conf_destroy_ctx(struct libnet_conf_ctx *ctx)
411 {
412         return regdb_close();
413 }
414
415 /**********************************************************************
416  *
417  * The actual net conf api functions, that are exported.
418  *
419  **********************************************************************/
420
421 /**
422  * Open the configuration.
423  *
424  * This should be the first function in a sequence of calls to libnet_conf
425  * functions:
426  *
427  * Upon success, this creates and returns the conf context
428  * that should be passed around in subsequent calls to the other
429  * libnet_conf functions.
430  *
431  * After the work with the configuration is completed, libnet_conf_close()
432  * should be called.
433  */
434 WERROR libnet_conf_open(TALLOC_CTX *mem_ctx, struct libnet_conf_ctx **conf_ctx)
435 {
436         WERROR werr = WERR_OK;
437         struct libnet_conf_ctx *ctx;
438
439         if (conf_ctx == NULL) {
440                 return WERR_INVALID_PARAM;
441         }
442
443         ctx = TALLOC_ZERO_P(mem_ctx, struct libnet_conf_ctx);
444         if (ctx == NULL) {
445                 return WERR_NOMEM;
446         }
447
448         werr = libnet_conf_reg_initialize(ctx);
449         if (!W_ERROR_IS_OK(werr)) {
450                 goto fail;
451         }
452
453         talloc_set_destructor(ctx, libnet_conf_destroy_ctx);
454
455         *conf_ctx = ctx;
456         return werr;
457
458 fail:
459         TALLOC_FREE(ctx);
460         return werr;
461 }
462
463 /**
464  * Close the configuration.
465  */
466 void libnet_conf_close(struct libnet_conf_ctx *ctx)
467 {
468         /* this also closes the registry (by destructor): */
469         TALLOC_FREE(ctx);
470 }
471
472 /**
473  * Drop the whole configuration (restarting empty).
474  */
475 WERROR libnet_conf_drop(struct libnet_conf_ctx *ctx)
476 {
477         char *path, *p;
478         WERROR werr = WERR_OK;
479         struct registry_key *parent_key = NULL;
480         struct registry_key *new_key = NULL;
481         TALLOC_CTX* mem_ctx = talloc_stackframe();
482         enum winreg_CreateAction action;
483
484         path = talloc_strdup(mem_ctx, KEY_SMBCONF);
485         if (path == NULL) {
486                 werr = WERR_NOMEM;
487                 goto done;
488         }
489         p = strrchr(path, '\\');
490         *p = '\0';
491         werr = libnet_conf_reg_open_path(mem_ctx, ctx, path, REG_KEY_WRITE,
492                                          &parent_key);
493
494         if (!W_ERROR_IS_OK(werr)) {
495                 goto done;
496         }
497
498         werr = reg_deletekey_recursive(mem_ctx, parent_key, p+1);
499
500         if (!W_ERROR_IS_OK(werr)) {
501                 goto done;
502         }
503
504         werr = reg_createkey(mem_ctx, parent_key, p+1, REG_KEY_WRITE,
505                              &new_key, &action);
506
507 done:
508         TALLOC_FREE(mem_ctx);
509         return werr;
510 }
511
512 /**
513  * Get the whole configuration as lists of strings with counts:
514  *
515  *  num_shares   : number of shares
516  *  share_names  : list of length num_shares of share names
517  *  num_params   : list of length num_shares of parameter counts for each share
518  *  param_names  : list of lists of parameter names for each share
519  *  param_values : list of lists of parameter values for each share
520  */
521 WERROR libnet_conf_get_config(TALLOC_CTX *mem_ctx,
522                               struct libnet_conf_ctx *ctx, uint32_t *num_shares,
523                               char ***share_names, uint32_t **num_params,
524                               char ****param_names, char ****param_values)
525 {
526         WERROR werr = WERR_OK;
527         TALLOC_CTX *tmp_ctx = NULL;
528         uint32_t tmp_num_shares;
529         char **tmp_share_names;
530         uint32_t *tmp_num_params;
531         char ***tmp_param_names;
532         char ***tmp_param_values;
533         uint32_t count;
534
535         if ((num_shares == NULL) || (share_names == NULL) ||
536             (num_params == NULL) || (param_names == NULL) ||
537             (param_values == NULL))
538         {
539                 werr = WERR_INVALID_PARAM;
540                 goto done;
541         }
542
543         tmp_ctx = talloc_new(mem_ctx);
544         if (tmp_ctx == NULL) {
545                 werr = WERR_NOMEM;
546                 goto done;
547         }
548
549         werr = libnet_conf_get_share_names(tmp_ctx, ctx, &tmp_num_shares,
550                                            &tmp_share_names);
551         if (!W_ERROR_IS_OK(werr)) {
552                 goto done;
553         }
554
555         tmp_num_params   = TALLOC_ARRAY(tmp_ctx, uint32_t, tmp_num_shares);
556         tmp_param_names  = TALLOC_ARRAY(tmp_ctx, char **, tmp_num_shares);
557         tmp_param_values = TALLOC_ARRAY(tmp_ctx, char **, tmp_num_shares);
558
559         if ((tmp_num_params == NULL) || (tmp_param_names == NULL) ||
560             (tmp_param_values == NULL))
561         {
562                 werr = WERR_NOMEM;
563                 goto done;
564         }
565
566         for (count = 0; count < tmp_num_shares; count++) {
567                 werr = libnet_conf_get_share(mem_ctx, ctx,
568                                              tmp_share_names[count],
569                                              &tmp_num_params[count],
570                                              &tmp_param_names[count],
571                                              &tmp_param_values[count]);
572                 if (!W_ERROR_IS_OK(werr)) {
573                         goto done;
574                 }
575         }
576
577         werr = WERR_OK;
578
579         *num_shares = tmp_num_shares;
580         if (tmp_num_shares > 0) {
581                 *share_names = talloc_move(mem_ctx, &tmp_share_names);
582                 *num_params = talloc_move(mem_ctx, &tmp_num_params);
583                 *param_names = talloc_move(mem_ctx, &tmp_param_names);
584                 *param_values = talloc_move(mem_ctx, &tmp_param_values);
585         } else {
586                 *share_names = NULL;
587                 *num_params = NULL;
588                 *param_names = NULL;
589                 *param_values = NULL;
590         }
591
592 done:
593         TALLOC_FREE(tmp_ctx);
594         return werr;
595 }
596
597 /**
598  * get the list of share names defined in the configuration.
599  */
600 WERROR libnet_conf_get_share_names(TALLOC_CTX *mem_ctx,
601                                    struct libnet_conf_ctx *ctx,
602                                    uint32_t *num_shares,
603                                    char ***share_names)
604 {
605         uint32_t count;
606         uint32_t added_count = 0;
607         TALLOC_CTX *tmp_ctx = NULL;
608         WERROR werr = WERR_OK;
609         struct registry_key *key = NULL;
610         char *subkey_name = NULL;
611         char **tmp_share_names = NULL;
612
613         if ((num_shares == NULL) || (share_names == NULL)) {
614                 werr = WERR_INVALID_PARAM;
615                 goto done;
616         }
617
618         tmp_ctx = talloc_new(mem_ctx);
619         if (tmp_ctx == NULL) {
620                 werr = WERR_NOMEM;
621                 goto done;
622         }
623
624         /* make sure "global" is always listed first */
625         if (libnet_conf_share_exists(ctx, GLOBAL_NAME)) {
626                 werr = libnet_conf_add_string_to_array(tmp_ctx,
627                                                        &tmp_share_names,
628                                                        0, GLOBAL_NAME);
629                 if (!W_ERROR_IS_OK(werr)) {
630                         goto done;
631                 }
632                 added_count++;
633         }
634
635         werr = libnet_conf_reg_open_base_key(tmp_ctx, ctx,
636                                              SEC_RIGHTS_ENUM_SUBKEYS, &key);
637         if (!W_ERROR_IS_OK(werr)) {
638                 goto done;
639         }
640
641         for (count = 0;
642              W_ERROR_IS_OK(werr = reg_enumkey(tmp_ctx, key, count,
643                                               &subkey_name, NULL));
644              count++)
645         {
646                 if (strequal(subkey_name, GLOBAL_NAME)) {
647                         continue;
648                 }
649
650                 werr = libnet_conf_add_string_to_array(tmp_ctx,
651                                                        &tmp_share_names,
652                                                        added_count,
653                                                        subkey_name);
654                 if (!W_ERROR_IS_OK(werr)) {
655                         goto done;
656                 }
657                 added_count++;
658         }
659         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
660                 goto done;
661         }
662         werr = WERR_OK;
663
664         *num_shares = added_count;
665         if (added_count > 0) {
666                 *share_names = talloc_move(mem_ctx, &tmp_share_names);
667         } else {
668                 *share_names = NULL;
669         }
670
671 done:
672         TALLOC_FREE(tmp_ctx);
673         return werr;
674 }
675
676 /**
677  * check if a share/service of a given name exists
678  */
679 bool libnet_conf_share_exists(struct libnet_conf_ctx *ctx,
680                               const char *servicename)
681 {
682         bool ret = false;
683         WERROR werr = WERR_OK;
684         TALLOC_CTX *mem_ctx = talloc_stackframe();
685         struct registry_key *key = NULL;
686
687         werr = libnet_conf_reg_open_service_key(mem_ctx, ctx, servicename,
688                                                 REG_KEY_READ, &key);
689         if (W_ERROR_IS_OK(werr)) {
690                 ret = true;
691         }
692
693         TALLOC_FREE(mem_ctx);
694         return ret;
695 }
696
697 /**
698  * Add a service if it does not already exist.
699  */
700 WERROR libnet_conf_create_share(struct libnet_conf_ctx *ctx,
701                                 const char *servicename)
702 {
703         WERROR werr;
704         TALLOC_CTX *mem_ctx = talloc_stackframe();
705         struct registry_key *key = NULL;
706
707         if (libnet_conf_share_exists(ctx, servicename)) {
708                 werr = WERR_ALREADY_EXISTS;
709                 goto done;
710         }
711
712         werr = libnet_conf_reg_create_service_key(mem_ctx, ctx, servicename,
713                                                   &key);
714
715 done:
716         TALLOC_FREE(mem_ctx);
717         return werr;
718 }
719
720 /**
721  * get a definition of a share (service) from configuration.
722  */
723 WERROR libnet_conf_get_share(TALLOC_CTX *mem_ctx, struct libnet_conf_ctx *ctx,
724                              const char *servicename, uint32_t *num_params,
725                              char ***param_names, char ***param_values)
726 {
727         WERROR werr = WERR_OK;
728         struct registry_key *key = NULL;
729
730         werr = libnet_conf_reg_open_service_key(mem_ctx, ctx, servicename,
731                                                 REG_KEY_READ, &key);
732         if (!W_ERROR_IS_OK(werr)) {
733                 goto done;
734         }
735
736         werr = libnet_conf_reg_get_values(mem_ctx, key, num_params,
737                                           param_names, param_values);
738
739 done:
740         TALLOC_FREE(key);
741         return werr;
742 }
743
744 /**
745  * delete a service from configuration
746  */
747 WERROR libnet_conf_delete_share(struct libnet_conf_ctx *ctx,
748                                 const char *servicename)
749 {
750         WERROR werr = WERR_OK;
751         struct registry_key *key = NULL;
752         TALLOC_CTX *mem_ctx = talloc_stackframe();
753
754         werr = libnet_conf_reg_open_base_key(mem_ctx, ctx, REG_KEY_WRITE, &key);
755         if (!W_ERROR_IS_OK(werr)) {
756                 goto done;
757         }
758
759         werr = reg_deletekey_recursive(key, key, servicename);
760
761 done:
762         TALLOC_FREE(mem_ctx);
763         return werr;
764 }
765
766 /**
767  * set a configuration parameter to the value provided.
768  */
769 WERROR libnet_conf_set_parameter(struct libnet_conf_ctx *ctx,
770                                  const char *service,
771                                  const char *param,
772                                  const char *valstr)
773 {
774         WERROR werr;
775         struct registry_key *key = NULL;
776         TALLOC_CTX *mem_ctx = talloc_stackframe();
777
778         if (!libnet_conf_share_exists(ctx, service)) {
779                 werr = WERR_NO_SUCH_SERVICE;
780                 goto done;
781         }
782
783         werr = libnet_conf_reg_open_service_key(mem_ctx, ctx, service,
784                                                 REG_KEY_WRITE, &key);
785         if (!W_ERROR_IS_OK(werr)) {
786                 goto done;
787         }
788
789         werr = libnet_conf_reg_set_value(key, param, valstr);
790
791 done:
792         TALLOC_FREE(mem_ctx);
793         return werr;
794 }
795
796 /**
797  * Set a global parameter
798  * (i.e. a parameter in the [global] service).
799  *
800  * This also creates [global] when it does not exist.
801  */
802 WERROR libnet_conf_set_global_parameter(struct libnet_conf_ctx *ctx,
803                                         const char *param, const char *val)
804 {
805         WERROR werr;
806
807         if (!libnet_conf_share_exists(ctx, GLOBAL_NAME)) {
808                 werr = libnet_conf_create_share(ctx, GLOBAL_NAME);
809                 if (!W_ERROR_IS_OK(werr)) {
810                         goto done;
811                 }
812         }
813         werr = libnet_conf_set_parameter(ctx, GLOBAL_NAME, param, val);
814
815 done:
816         return werr;
817 }
818
819 /**
820  * get the value of a configuration parameter as a string
821  */
822 WERROR libnet_conf_get_parameter(TALLOC_CTX *mem_ctx,
823                                  struct libnet_conf_ctx *ctx,
824                                  const char *service,
825                                  const char *param,
826                                  char **valstr)
827 {
828         WERROR werr = WERR_OK;
829         struct registry_key *key = NULL;
830         struct registry_value *value = NULL;
831
832         if (valstr == NULL) {
833                 werr = WERR_INVALID_PARAM;
834                 goto done;
835         }
836
837         if (!libnet_conf_share_exists(ctx, service)) {
838                 werr = WERR_NO_SUCH_SERVICE;
839                 goto done;
840         }
841
842         werr = libnet_conf_reg_open_service_key(mem_ctx, ctx, service,
843                                                 REG_KEY_READ, &key);
844         if (!W_ERROR_IS_OK(werr)) {
845                 goto done;
846         }
847
848         if (!libnet_conf_value_exists(key, param)) {
849                 werr = WERR_INVALID_PARAM;
850                 goto done;
851         }
852
853         werr = reg_queryvalue(mem_ctx, key, param, &value);
854         if (!W_ERROR_IS_OK(werr)) {
855                 goto done;
856         }
857
858         *valstr = libnet_conf_format_registry_value(mem_ctx, value);
859
860         if (*valstr == NULL) {
861                 werr = WERR_NOMEM;
862         }
863
864 done:
865         TALLOC_FREE(key);
866         TALLOC_FREE(value);
867         return werr;
868 }
869
870 /**
871  * Get the value of a global parameter.
872  *
873  * Create [global] if it does not exist.
874  */
875 WERROR libnet_conf_get_global_parameter(TALLOC_CTX *mem_ctx,
876                                         struct libnet_conf_ctx *ctx,
877                                         const char *param,
878                                         char **valstr)
879 {
880         WERROR werr;
881
882         if (!libnet_conf_share_exists(ctx, GLOBAL_NAME)) {
883                 werr = libnet_conf_create_share(ctx, GLOBAL_NAME);
884                 if (!W_ERROR_IS_OK(werr)) {
885                         goto done;
886                 }
887         }
888         werr = libnet_conf_get_parameter(mem_ctx, ctx, GLOBAL_NAME, param,
889                                          valstr);
890
891 done:
892         return werr;
893 }
894
895 /**
896  * delete a parameter from configuration
897  */
898 WERROR libnet_conf_delete_parameter(struct libnet_conf_ctx *ctx,
899                                     const char *service, const char *param)
900 {
901         struct registry_key *key = NULL;
902         WERROR werr = WERR_OK;
903         TALLOC_CTX *mem_ctx = talloc_stackframe();
904
905         if (!libnet_conf_share_exists(ctx, service)) {
906                 return WERR_NO_SUCH_SERVICE;
907         }
908
909         werr = libnet_conf_reg_open_service_key(mem_ctx, ctx, service,
910                                                 REG_KEY_ALL,
911                                                 &key);
912         if (!W_ERROR_IS_OK(werr)) {
913                 goto done;
914         }
915
916         if (!libnet_conf_value_exists(key, param)) {
917                 werr = WERR_INVALID_PARAM;
918                 goto done;
919         }
920
921         werr = reg_deletevalue(key, param);
922
923 done:
924         TALLOC_FREE(mem_ctx);
925         return werr;
926 }
927
928 /**
929  * Delete a global parameter.
930  *
931  * Create [global] if it does not exist.
932  */
933 WERROR libnet_conf_delete_global_parameter(struct libnet_conf_ctx *ctx,
934                                            const char *param)
935 {
936         WERROR werr;
937
938         if (!libnet_conf_share_exists(ctx, GLOBAL_NAME)) {
939                 werr = libnet_conf_create_share(ctx, GLOBAL_NAME);
940                 if (!W_ERROR_IS_OK(werr)) {
941                         goto done;
942                 }
943         }
944         werr = libnet_conf_delete_parameter(ctx, GLOBAL_NAME, param);
945
946 done:
947         return werr;
948 }