Move logic of net_conf_getparm() to libnet_conf.c.
[ira/wip.git] / source / utils / net_conf.c
1 /*
2  *  Samba Unix/Linux SMB client library
3  *  Distributed SMB/CIFS Server Management Utility
4  *  Local configuration interface
5  *  Copyright (C) Michael Adam 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 /*
22  * This is an interface to the configuration stored inside the
23  * samba registry. In the future there might be support for other
24  * configuration backends as well.
25  */
26
27 #include "includes.h"
28 #include "utils/net.h"
29 #include "libnet/libnet.h"
30
31 /*
32  * usage functions
33  */
34
35 static int net_conf_list_usage(int argc, const char **argv)
36 {
37         d_printf("USAGE: net conf list\n");
38         return -1;
39 }
40
41 static int net_conf_import_usage(int argc, const char**argv)
42 {
43         d_printf("USAGE: net conf import [--test|-T] <filename> "
44                  "[<servicename>]\n"
45                  "\t[--test|-T]    testmode - do not act, just print "
46                                    "what would be done\n"
47                  "\t<servicename>  only import service <servicename>, "
48                                    "ignore the rest\n");
49         return -1;
50 }
51
52 static int net_conf_listshares_usage(int argc, const char **argv)
53 {
54         d_printf("USAGE: net conf listshares\n");
55         return -1;
56 }
57
58 static int net_conf_drop_usage(int argc, const char **argv)
59 {
60         d_printf("USAGE: net conf drop\n");
61         return -1;
62 }
63
64 static int net_conf_showshare_usage(int argc, const char **argv)
65 {
66         d_printf("USAGE: net conf showshare <sharename>\n");
67         return -1;
68 }
69
70 static int net_conf_addshare_usage(int argc, const char **argv)
71 {
72         d_printf("USAGE: net conf addshare <sharename> <path> "
73                  "[writeable={y|N} [guest_ok={y|N} [<comment>]]\n"
74                  "\t<sharename>      the new share name.\n"
75                  "\t<path>           the path on the filesystem to export.\n"
76                  "\twriteable={y|N}  set \"writeable to \"yes\" or "
77                  "\"no\" (default) on this share.\n"
78                  "\tguest_ok={y|N}   set \"guest ok\" to \"yes\" or "
79                  "\"no\" (default)   on this share.\n"
80                  "\t<comment>        optional comment for the new share.\n");
81         return -1;
82 }
83
84 static int net_conf_delshare_usage(int argc, const char **argv)
85 {
86         d_printf("USAGE: net conf delshare <sharename>\n");
87         return -1;
88 }
89
90 static int net_conf_setparm_usage(int argc, const char **argv)
91 {
92         d_printf("USAGE: net conf setparm <section> <param> <value>\n");
93         return -1;
94 }
95
96 static int net_conf_getparm_usage(int argc, const char **argv)
97 {
98         d_printf("USAGE: net conf getparm <section> <param>\n");
99         return -1;
100 }
101
102 static int net_conf_delparm_usage(int argc, const char **argv)
103 {
104         d_printf("USAGE: net conf delparm <section> <param>\n");
105         return -1;
106 }
107
108
109 /*
110  * Helper functions
111  */
112
113 static char *format_value(TALLOC_CTX *mem_ctx, struct registry_value *value)
114 {
115         char *result = NULL;
116
117         /* what if mem_ctx = NULL? */
118
119         switch (value->type) {
120         case REG_DWORD:
121                 result = talloc_asprintf(mem_ctx, "%d", value->v.dword);
122                 break;
123         case REG_SZ:
124         case REG_EXPAND_SZ:
125                 result = talloc_asprintf(mem_ctx, "%s", value->v.sz.str);
126                 break;
127         case REG_MULTI_SZ: {
128                 uint32 j;
129                 for (j = 0; j < value->v.multi_sz.num_strings; j++) {
130                         result = talloc_asprintf(mem_ctx, "\"%s\" ",
131                                                  value->v.multi_sz.strings[j]);
132                 }
133                 break;
134         }
135         case REG_BINARY:
136                 result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
137                                          (int)value->v.binary.length);
138                 break;
139         default:
140                 result = talloc_asprintf(mem_ctx, "<unprintable>");
141                 break;
142         }
143         return result;
144 }
145
146 /*
147  * delete a subkey of KEY_SMBCONF
148  */
149 static WERROR reg_delkey_internal(TALLOC_CTX *ctx, const char *keyname)
150 {
151         WERROR werr = WERR_OK;
152         struct registry_key *key = NULL;
153
154         werr = libnet_smbconf_open_basepath(ctx, REG_KEY_WRITE, &key);
155         if (!W_ERROR_IS_OK(werr)) {
156                 goto done;
157         }
158
159         werr = reg_deletekey_recursive(key, key, keyname);
160         if (!W_ERROR_IS_OK(werr)) {
161                 d_fprintf(stderr, "Error deleting registry key %s\\%s: %s\n",
162                           KEY_SMBCONF, keyname, dos_errstr(werr));
163         }
164
165 done:
166         TALLOC_FREE(key);
167         return werr;
168 }
169
170 static WERROR list_values(TALLOC_CTX *ctx, struct registry_key *key)
171 {
172         WERROR werr = WERR_OK;
173         uint32 idx = 0;
174         struct registry_value *valvalue = NULL;
175         char *valname = NULL;
176
177         for (idx = 0;
178              W_ERROR_IS_OK(werr = reg_enumvalue(ctx, key, idx, &valname,
179                                                 &valvalue));
180              idx++)
181         {
182                 d_printf("\t%s = %s\n", valname, format_value(ctx, valvalue));
183         }
184         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
185                 d_fprintf(stderr, "Error enumerating values: %s\n",
186                           dos_errstr(werr));
187                 goto done;
188         }
189         werr = WERR_OK;
190
191 done:
192         return werr;
193 }
194
195 static WERROR drop_smbconf_internal(TALLOC_CTX *ctx)
196 {
197         char *path, *p;
198         WERROR werr = WERR_OK;
199         NT_USER_TOKEN *token;
200         struct registry_key *parent_key = NULL;
201         struct registry_key *new_key = NULL;
202         TALLOC_CTX* tmp_ctx = NULL;
203         enum winreg_CreateAction action;
204
205         tmp_ctx = talloc_new(ctx);
206         if (tmp_ctx == NULL) {
207                 werr = WERR_NOMEM;
208                 goto done;
209         }
210
211         if (!(token = registry_create_admin_token(tmp_ctx))) {
212                 /* what is the appropriate error code here? */
213                 werr = WERR_CAN_NOT_COMPLETE;
214                 goto done;
215         }
216
217         path = talloc_strdup(tmp_ctx, KEY_SMBCONF);
218         if (path == NULL) {
219                 d_fprintf(stderr, "ERROR: out of memory!\n");
220                 werr = WERR_NOMEM;
221                 goto done;
222         }
223         p = strrchr(path, '\\');
224         *p = '\0';
225         werr = reg_open_path(tmp_ctx, path, REG_KEY_WRITE, token, &parent_key);
226
227         if (!W_ERROR_IS_OK(werr)) {
228                 goto done;
229         }
230
231         werr = reg_deletekey_recursive(tmp_ctx, parent_key, p+1);
232
233         if (!W_ERROR_IS_OK(werr)) {
234                 goto done;
235         }
236
237         werr = reg_createkey(tmp_ctx, parent_key, p+1, REG_KEY_WRITE,
238                              &new_key, &action);
239
240 done:
241         TALLOC_FREE(tmp_ctx);
242         return werr;
243 }
244
245 static char *parm_valstr(TALLOC_CTX *ctx, struct parm_struct *parm,
246                          struct share_params *share)
247 {
248         char *valstr = NULL;
249         int i = 0;
250         void *ptr = parm->ptr;
251
252         if (parm->p_class == P_LOCAL && share->service >= 0) {
253                 ptr = lp_local_ptr(share->service, ptr);
254         }
255
256         switch (parm->type) {
257         case P_CHAR:
258                 valstr = talloc_asprintf(ctx, "%c", *(char *)ptr);
259                 break;
260         case P_STRING:
261         case P_USTRING:
262                 valstr = talloc_asprintf(ctx, "%s", *(char **)ptr);
263                 break;
264         case P_BOOL:
265                 valstr = talloc_asprintf(ctx, "%s", BOOLSTR(*(bool *)ptr));
266                 break;
267         case P_BOOLREV:
268                 valstr = talloc_asprintf(ctx, "%s", BOOLSTR(!*(bool *)ptr));
269                 break;
270         case P_ENUM:
271                 for (i = 0; parm->enum_list[i].name; i++) {
272                         if (*(int *)ptr == parm->enum_list[i].value)
273                         {
274                                 valstr = talloc_asprintf(ctx, "%s",
275                                          parm->enum_list[i].name);
276                                 break;
277                         }
278                 }
279                 break;
280         case P_OCTAL: {
281                 char *o = octal_string(*(int *)ptr);
282                 valstr = talloc_move(ctx, &o);
283                 break;
284         }
285         case P_LIST:
286                 valstr = talloc_strdup(ctx, "");
287                 if ((char ***)ptr && *(char ***)ptr) {
288                         char **list = *(char ***)ptr;
289                         for (; *list; list++) {
290                                 /* surround strings with whitespace
291                                  * in double quotes */
292                                 if (strchr_m(*list, ' '))
293                                 {
294                                         valstr = talloc_asprintf_append(
295                                                 valstr, "\"%s\"%s",
296                                                 *list,
297                                                  ((*(list+1))?", ":""));
298                                 } else {
299                                         valstr = talloc_asprintf_append(
300                                                 valstr, "%s%s", *list,
301                                                  ((*(list+1))?", ":""));
302                                 }
303                         }
304                 }
305                 break;
306         case P_INTEGER:
307                 valstr = talloc_asprintf(ctx, "%d", *(int *)ptr);
308                 break;
309         case P_SEP:
310                 break;
311         default:
312                 valstr = talloc_asprintf(ctx, "<type unimplemented>\n");
313                 break;
314         }
315
316         return valstr;
317 }
318
319 static int import_process_service(TALLOC_CTX *ctx,
320                                   struct share_params *share)
321 {
322         int ret = -1;
323         struct parm_struct *parm;
324         int pnum = 0;
325         const char *servicename;
326         struct registry_key *key;
327         WERROR werr;
328         char *valstr = NULL;
329         TALLOC_CTX *tmp_ctx = NULL;
330
331         tmp_ctx = talloc_new(ctx);
332         if (tmp_ctx == NULL) {
333                 werr = WERR_NOMEM;
334                 goto done;
335         }
336
337         servicename = (share->service == GLOBAL_SECTION_SNUM)?
338                 GLOBAL_NAME : lp_servicename(share->service);
339
340         if (opt_testmode) {
341                 d_printf("[%s]\n", servicename);
342         } else {
343                 if (libnet_smbconf_key_exists(tmp_ctx, servicename)) {
344                         werr = reg_delkey_internal(tmp_ctx, servicename);
345                         if (!W_ERROR_IS_OK(werr)) {
346                                 goto done;
347                         }
348                 }
349                 werr = libnet_smbconf_reg_createkey_internal(tmp_ctx, servicename, &key);
350                 if (!W_ERROR_IS_OK(werr)) {
351                         goto done;
352                 }
353         }
354
355         while ((parm = lp_next_parameter(share->service, &pnum, 0)))
356         {
357                 if ((share->service < 0 && parm->p_class == P_LOCAL)
358                     && !(parm->flags & FLAG_GLOBAL))
359                         continue;
360
361                 valstr = parm_valstr(tmp_ctx, parm, share);
362
363                 if (parm->type != P_SEP) {
364                         if (opt_testmode) {
365                                 d_printf("\t%s = %s\n", parm->label, valstr);
366                         } else {
367                                 werr = libnet_smbconf_reg_setvalue_internal(key,
368                                                         parm->label, valstr);
369                                 if (!W_ERROR_IS_OK(werr)) {
370                                         goto done;
371                                 }
372                         }
373                 }
374         }
375
376         if (opt_testmode) {
377                 d_printf("\n");
378         }
379
380         ret = 0;
381
382 done:
383         TALLOC_FREE(tmp_ctx);
384         return ret;
385 }
386
387 /* return True iff there are nondefault globals */
388 static bool globals_exist(void)
389 {
390         int i = 0;
391         struct parm_struct *parm;
392
393         while ((parm = lp_next_parameter(GLOBAL_SECTION_SNUM, &i, 0)) != NULL) {
394                 if (parm->type != P_SEP) {
395                         return True;
396                 }
397         }
398         return False;
399 }
400
401 /*
402  * the conf functions
403  */
404
405 int net_conf_list(int argc, const char **argv)
406 {
407         WERROR werr = WERR_OK;
408         int ret = -1;
409         TALLOC_CTX *ctx;
410         struct registry_key *base_key = NULL;
411         struct registry_key *sub_key = NULL;
412         uint32 idx_key = 0;
413         char *subkey_name = NULL;
414
415         ctx = talloc_init("list");
416
417         if (argc != 0) {
418                 net_conf_list_usage(argc, argv);
419                 goto done;
420         }
421
422         werr = libnet_smbconf_open_basepath(ctx, REG_KEY_READ, &base_key);
423         if (!W_ERROR_IS_OK(werr)) {
424                 goto done;
425         }
426
427         if (libnet_smbconf_key_exists(ctx, GLOBAL_NAME))  {
428                 werr = reg_openkey(ctx, base_key, GLOBAL_NAME,
429                                    REG_KEY_READ, &sub_key);
430                 if (!W_ERROR_IS_OK(werr)) {
431                         d_fprintf(stderr, "Error opening subkey '%s' : %s\n",
432                                   subkey_name, dos_errstr(werr));
433                         goto done;
434                 }
435                 d_printf("[%s]\n", GLOBAL_NAME);
436                 if (!W_ERROR_IS_OK(list_values(ctx, sub_key))) {
437                         goto done;
438                 }
439                 d_printf("\n");
440         }
441
442         for (idx_key = 0;
443              W_ERROR_IS_OK(werr = reg_enumkey(ctx, base_key, idx_key,
444                                               &subkey_name, NULL));
445              idx_key++)
446         {
447                 if (strequal(subkey_name, GLOBAL_NAME)) {
448                         continue;
449                 }
450                 d_printf("[%s]\n", subkey_name);
451
452                 werr = reg_openkey(ctx, base_key, subkey_name,
453                                    REG_KEY_READ, &sub_key);
454                 if (!W_ERROR_IS_OK(werr)) {
455                         d_fprintf(stderr,
456                                   "Error opening subkey '%s': %s\n",
457                                   subkey_name, dos_errstr(werr));
458                         goto done;
459                 }
460                 if (!W_ERROR_IS_OK(list_values(ctx, sub_key))) {
461                         goto done;
462                 }
463                 d_printf("\n");
464         }
465         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
466                 d_fprintf(stderr, "Error enumerating subkeys: %s\n",
467                           dos_errstr(werr));
468                 goto done;
469         }
470
471         ret = 0;
472
473 done:
474         TALLOC_FREE(ctx);
475         return ret;
476 }
477
478 int net_conf_import(int argc, const char **argv)
479 {
480         int ret = -1;
481         const char *filename = NULL;
482         const char *servicename = NULL;
483         bool service_found = False;
484         TALLOC_CTX *ctx;
485         struct share_iterator *shares;
486         struct share_params *share;
487         struct share_params global_share = { GLOBAL_SECTION_SNUM };
488
489         ctx = talloc_init("net_conf_import");
490
491         switch (argc) {
492                 case 0:
493                 default:
494                         net_conf_import_usage(argc, argv);
495                         goto done;
496                 case 2:
497                         servicename = argv[1];
498                 case 1:
499                         filename = argv[0];
500                         break;
501         }
502
503         DEBUG(3,("net_conf_import: reading configuration from file %s.\n",
504                 filename));
505
506         if (!lp_load(filename,
507                      False,     /* global_only */
508                      True,      /* save_defaults */
509                      False,     /* add_ipc */
510                      True))     /* initialize_globals */
511         {
512                 d_fprintf(stderr, "Error parsing configuration file.\n");
513                 goto done;
514         }
515
516         if (opt_testmode) {
517                 d_printf("\nTEST MODE - "
518                          "would import the following configuration:\n\n");
519         }
520
521         if (((servicename == NULL) && globals_exist()) ||
522             strequal(servicename, GLOBAL_NAME))
523         {
524                 service_found = True;
525                 if (import_process_service(ctx, &global_share) != 0) {
526                         goto done;
527                 }
528         }
529
530         if (service_found && (servicename != NULL)) {
531                 ret = 0;
532                 goto done;
533         }
534
535         if (!(shares = share_list_all(ctx))) {
536                 d_fprintf(stderr, "Could not list shares...\n");
537                 goto done;
538         }
539         while ((share = next_share(shares)) != NULL) {
540                 if ((servicename == NULL)
541                     || strequal(servicename, lp_servicename(share->service)))
542                 {
543                         service_found = True;
544                         if (import_process_service(ctx, share)!= 0) {
545                                 goto done;
546                         }
547                 }
548         }
549
550         if ((servicename != NULL) && !service_found) {
551                 d_printf("Share %s not found in file %s\n",
552                          servicename, filename);
553                 goto done;
554
555         }
556
557         ret = 0;
558
559 done:
560         TALLOC_FREE(ctx);
561         return ret;
562 }
563
564 int net_conf_listshares(int argc, const char **argv)
565 {
566         WERROR werr = WERR_OK;
567         int ret = -1;
568         struct registry_key *key;
569         uint32 idx = 0;
570         char *subkey_name = NULL;
571         TALLOC_CTX *ctx;
572
573         ctx = talloc_init("listshares");
574
575         if (argc != 0) {
576                 net_conf_listshares_usage(argc, argv);
577                 goto done;
578         }
579
580         werr = libnet_smbconf_open_basepath(ctx, SEC_RIGHTS_ENUM_SUBKEYS, &key);
581         if (!W_ERROR_IS_OK(werr)) {
582                 goto done;
583         }
584
585         for (idx = 0;
586              W_ERROR_IS_OK(werr = reg_enumkey(ctx, key, idx,
587                                               &subkey_name, NULL));
588              idx++)
589         {
590                 d_printf("%s\n", subkey_name);
591         }
592         if (! W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
593                 d_fprintf(stderr, "Error enumerating subkeys: %s\n",
594                           dos_errstr(werr));
595                 goto done;
596         }
597
598         ret = 0;
599
600 done:
601         TALLOC_FREE(ctx);
602         return ret;
603 }
604
605 int net_conf_drop(int argc, const char **argv)
606 {
607         int ret = -1;
608         WERROR werr;
609
610         if (argc != 0) {
611                 net_conf_drop_usage(argc, argv);
612                 goto done;
613         }
614
615         werr = drop_smbconf_internal(NULL);
616         if (!W_ERROR_IS_OK(werr)) {
617                 d_fprintf(stderr, "Error deleting configuration: %s\n",
618                           dos_errstr(werr));
619                 goto done;
620         }
621
622         ret = 0;
623
624 done:
625         return ret;
626 }
627
628 int net_conf_showshare(int argc, const char **argv)
629 {
630         int ret = -1;
631         WERROR werr = WERR_OK;
632         struct registry_key *key = NULL;
633         TALLOC_CTX *ctx;
634
635         ctx = talloc_init("showshare");
636
637         if (argc != 1) {
638                 net_conf_showshare_usage(argc, argv);
639                 goto done;
640         }
641
642         werr = libnet_smbconf_open_path(ctx, argv[0], REG_KEY_READ, &key);
643         if (!W_ERROR_IS_OK(werr)) {
644                 goto done;
645         }
646
647         d_printf("[%s]\n", argv[0]);
648
649         if (!W_ERROR_IS_OK(list_values(ctx, key))) {
650                 goto done;
651         }
652
653         ret = 0;
654
655 done:
656         TALLOC_FREE(ctx);
657         return ret;
658 }
659
660 int net_conf_addshare(int argc, const char **argv)
661 {
662         int ret = -1;
663         WERROR werr = WERR_OK;
664         struct registry_key *newkey = NULL;
665         char *sharename = NULL;
666         const char *path = NULL;
667         const char *comment = NULL;
668         const char *guest_ok = "no";
669         const char *writeable = "no";
670         SMB_STRUCT_STAT sbuf;
671
672         switch (argc) {
673                 case 0:
674                 case 1:
675                 default:
676                         net_conf_addshare_usage(argc, argv);
677                         goto done;
678                 case 5:
679                         comment = argv[4];
680                 case 4:
681                         if (!strnequal(argv[3], "guest_ok=", 9)) {
682                                 net_conf_addshare_usage(argc, argv);
683                                 goto done;
684                         }
685                         switch (argv[3][9]) {
686                                 case 'y':
687                                 case 'Y':
688                                         guest_ok = "yes";
689                                         break;
690                                 case 'n':
691                                 case 'N':
692                                         guest_ok = "no";
693                                         break;
694                                 default:
695                                         net_conf_addshare_usage(argc, argv);
696                                         goto done;
697                         }
698                 case 3:
699                         if (!strnequal(argv[2], "writeable=", 10)) {
700                                 net_conf_addshare_usage(argc, argv);
701                                 goto done;
702                         }
703                         switch (argv[2][10]) {
704                                 case 'y':
705                                 case 'Y':
706                                         writeable = "yes";
707                                         break;
708                                 case 'n':
709                                 case 'N':
710                                         writeable = "no";
711                                         break;
712                                 default:
713                                         net_conf_addshare_usage(argc, argv);
714                                         goto done;
715                         }
716
717                 case 2:
718                         path = argv[1];
719                         sharename = strdup_lower(argv[0]);
720                         break;
721         }
722
723         /*
724          * validate arguments
725          */
726
727         /* validate share name */
728
729         if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS,
730                                strlen(sharename)))
731         {
732                 d_fprintf(stderr, "ERROR: share name %s contains "
733                         "invalid characters (any of %s)\n",
734                         sharename, INVALID_SHARENAME_CHARS);
735                 goto done;
736         }
737
738         if (getpwnam(sharename)) {
739                 d_fprintf(stderr, "ERROR: share name %s is already a valid "
740                           "system user name.\n", sharename);
741                 goto done;
742         }
743
744         if (strequal(sharename, GLOBAL_NAME)) {
745                 d_fprintf(stderr,
746                           "ERROR: 'global' is not a valid share name.\n");
747                 goto done;
748         }
749
750         /* validate path */
751
752         if (path[0] != '/') {
753                 d_fprintf(stderr,
754                           "Error: path '%s' is not an absolute path.\n",
755                           path);
756                 goto done;
757         }
758
759         if (sys_stat(path, &sbuf) != 0) {
760                 d_fprintf(stderr,
761                           "ERROR: cannot stat path '%s' to ensure "
762                           "this is a directory.\n"
763                           "Error was '%s'.\n",
764                           path, strerror(errno));
765                 goto done;
766         }
767
768         if (!S_ISDIR(sbuf.st_mode)) {
769                 d_fprintf(stderr,
770                           "ERROR: path '%s' is not a directory.\n",
771                           path);
772                 goto done;
773         }
774
775         /*
776          * create the share
777          */
778
779         werr = libnet_smbconf_reg_createkey_internal(NULL, argv[0], &newkey);
780         if (!W_ERROR_IS_OK(werr)) {
781                 goto done;
782         }
783
784         /* add config params as values */
785
786         werr = libnet_smbconf_reg_setvalue_internal(newkey, "path", path);
787         if (!W_ERROR_IS_OK(werr))
788                 goto done;
789
790         if (comment != NULL) {
791                 werr = libnet_smbconf_reg_setvalue_internal(newkey, "comment",
792                                                             comment);
793                 if (!W_ERROR_IS_OK(werr))
794                         goto done;
795         }
796
797         werr = libnet_smbconf_reg_setvalue_internal(newkey, "guest ok",
798                                                     guest_ok);
799         if (!W_ERROR_IS_OK(werr))
800                 goto done;
801
802         werr = libnet_smbconf_reg_setvalue_internal(newkey, "writeable",
803                                                     writeable);
804         if (!W_ERROR_IS_OK(werr))
805                 goto done;
806
807         ret = 0;
808
809 done:
810         TALLOC_FREE(newkey);
811         SAFE_FREE(sharename);
812         return ret;
813 }
814
815 int net_conf_delshare(int argc, const char **argv)
816 {
817         int ret = -1;
818         const char *sharename = NULL;
819
820         if (argc != 1) {
821                 net_conf_delshare_usage(argc, argv);
822                 goto done;
823         }
824         sharename = argv[0];
825
826         if (W_ERROR_IS_OK(reg_delkey_internal(NULL, sharename))) {
827                 ret = 0;
828         }
829 done:
830         return ret;
831 }
832
833 static int net_conf_setparm(int argc, const char **argv)
834 {
835         int ret = -1;
836         WERROR werr = WERR_OK;
837         char *service = NULL;
838         char *param = NULL;
839         const char *value_str = NULL;
840         TALLOC_CTX *ctx;
841
842         ctx = talloc_init("setparm");
843
844         if (argc != 3) {
845                 net_conf_setparm_usage(argc, argv);
846                 goto done;
847         }
848         service = strdup_lower(argv[0]);
849         param = strdup_lower(argv[1]);
850         value_str = argv[2];
851
852         werr = libnet_smbconf_setparm(ctx, service, param, value_str);
853
854         if (!W_ERROR_IS_OK(werr)) {
855                 d_fprintf(stderr, "Error setting value '%s': %s\n",
856                           param, dos_errstr(werr));
857                 goto done;
858         }
859
860         ret = 0;
861
862 done:
863         SAFE_FREE(service);
864         TALLOC_FREE(ctx);
865         return ret;
866 }
867
868 static int net_conf_getparm(int argc, const char **argv)
869 {
870         int ret = -1;
871         WERROR werr = WERR_OK;
872         char *service = NULL;
873         char *param = NULL;
874         struct registry_value *value = NULL;
875         TALLOC_CTX *ctx;
876
877         ctx = talloc_init("getparm");
878
879         if (argc != 2) {
880                 net_conf_getparm_usage(argc, argv);
881                 goto done;
882         }
883         service = strdup_lower(argv[0]);
884         param = strdup_lower(argv[1]);
885
886         werr = libnet_smbconf_getparm(ctx, service, param, &value);
887
888         if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
889                 d_fprintf(stderr,
890                           "Error: given service '%s' does not exist.\n",
891                           service);
892                 goto done;
893         } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
894                 d_fprintf(stderr,
895                           "Error: given parameter '%s' is not set.\n",
896                           param);
897                 goto done;
898         } else if (!W_ERROR_IS_OK(werr)) {
899                 d_fprintf(stderr, "Error getting value '%s': %s.\n",
900                           param, dos_errstr(werr));
901                 goto done;
902         }
903
904         d_printf("%s\n", format_value(ctx, value));
905
906         ret = 0;
907 done:
908         SAFE_FREE(service);
909         SAFE_FREE(param);
910         TALLOC_FREE(ctx);
911         return ret;
912 }
913
914 static int net_conf_delparm(int argc, const char **argv)
915 {
916         int ret = -1;
917         WERROR werr = WERR_OK;
918         char *service = NULL;
919         char *param = NULL;
920         TALLOC_CTX *ctx;
921
922         ctx = talloc_init("delparm");
923
924         if (argc != 2) {
925                 net_conf_delparm_usage(argc, argv);
926                 goto done;
927         }
928         service = strdup_lower(argv[0]);
929         param = strdup_lower(argv[1]);
930
931         werr = libnet_smbconf_delparm(ctx, service, param);
932
933         if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
934                 d_fprintf(stderr,
935                           "Error: given service '%s' does not exist.\n",
936                           service);
937                 goto done;
938         } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
939                 d_fprintf(stderr,
940                           "Error: given parameter '%s' is not set.\n",
941                           param);
942                 goto done;
943         } else if (!W_ERROR_IS_OK(werr)) {
944                 d_fprintf(stderr, "Error deleting value '%s': %s.\n",
945                           param, dos_errstr(werr));
946                 goto done;
947         }
948
949         ret = 0;
950
951 done:
952         return ret;
953 }
954
955 /*
956  * Entry-point for all the CONF functions.
957  */
958
959 int net_conf(int argc, const char **argv)
960 {
961         int ret = -1;
962         struct functable2 func[] = {
963                 {"list", net_conf_list,
964                  "Dump the complete configuration in smb.conf like format."},
965                 {"import", net_conf_import,
966                  "Import configuration from file in smb.conf format."},
967                 {"listshares", net_conf_listshares,
968                  "List the registry shares."},
969                 {"drop", net_conf_drop,
970                  "Delete the complete configuration from registry."},
971                 {"showshare", net_conf_showshare,
972                  "Show the definition of a registry share."},
973                 {"addshare", net_conf_addshare,
974                  "Create a new registry share."},
975                 {"delshare", net_conf_delshare,
976                  "Delete a registry share."},
977                 {"setparm", net_conf_setparm,
978                  "Store a parameter."},
979                 {"getparm", net_conf_getparm,
980                  "Retrieve the value of a parameter."},
981                 {"delparm", net_conf_delparm,
982                  "Delete a parameter."},
983                 {NULL, NULL, NULL}
984         };
985
986         if (!registry_init_regdb()) {
987                 d_fprintf(stderr, "Error initializing the registry!\n");
988                 goto done;
989         }
990
991         ret = net_run_function2(argc, argv, "net conf", func);
992
993         regdb_close();
994
995 done:
996         return ret;
997 }
998