febc8dc9e13cbb2777fc48465a68a9ed9b9fc420
[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 2 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, write to the Free Software
19  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
20  */
21
22 /*
23  * This is an interface to the configuration stored inside the 
24  * samba registry. In the future there might be support for other 
25  * configuration backends as well.
26  */
27
28 #include "includes.h"
29 #include "utils/net.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> [<servicename>]\n"
44                  "\t[--test|-T]    testmode - do not act, just print "
45                                    "what would be done\n"
46                  "\t<servicename>  only import service <servicename>, "
47                                    "ignore the rest\n");
48         return -1;
49 }
50
51 static int net_conf_listshares_usage(int argc, const char **argv)
52 {
53         d_printf("USAGE: net conf listshares\n");
54         return -1;
55 }
56
57 static int net_conf_drop_usage(int argc, const char **argv)
58 {
59         d_printf("USAGE: net conf drop\n");
60         return -1;
61 }
62
63 static int net_conf_showshare_usage(int argc, const char **argv)
64 {
65         d_printf("USAGE: net conf showshare <sharename>\n");
66         return -1;
67 }
68
69 static int net_conf_addshare_usage(int argc, const char **argv)
70 {
71         d_printf("USAGE: net conf addshare <sharename> <path> "
72                  "[writeable={y|N} [guest_ok={y|N} [<comment>]]\n"
73                  "\t<sharename>      the new share name.\n"
74                  "\t<path>           the path on the filesystem to export.\n"
75                  "\twriteable={y|N}  set \"writeable to \"yes\" or "
76                  "\"no\" (default) on this share.\n"
77                  "\tguest_ok={y|N}   set \"guest ok\" to \"yes\" or "
78                  "\"no\" (default)   on this share.\n"
79                  "\t<comment>        optional comment for the new share.\n");
80         return -1;
81 }
82
83 static int net_conf_delshare_usage(int argc, const char **argv)
84 {
85         d_printf("USAGE: net conf delshare <sharename>\n");
86         return -1;
87 }
88
89 static int net_conf_setparm_usage(int argc, const char **argv)
90 {
91         d_printf("USAGE: net conf setparm <section> <param> <value>\n");
92         return -1;
93 }
94
95 static int net_conf_getparm_usage(int argc, const char **argv)
96 {
97         d_printf("USAGE: net conf getparm <section> <param>\n");
98         return -1;
99 }
100
101 static int net_conf_delparm_usage(int argc, const char **argv)
102 {
103         d_printf("USAGE: net conf delparm <section> <param>\n");
104         return -1;
105 }
106
107
108 /*
109  * Helper functions
110  */
111
112 static char *format_value(TALLOC_CTX *mem_ctx, struct registry_value *value)
113 {
114         char *result = NULL;
115
116         /* what if mem_ctx = NULL? */
117
118         switch (value->type) {
119         case REG_DWORD:
120                 result = talloc_asprintf(mem_ctx, "%d", value->v.dword);
121                 break;
122         case REG_SZ:
123         case REG_EXPAND_SZ:
124                 result = talloc_asprintf(mem_ctx, "%s", value->v.sz.str);
125                 break;
126         case REG_MULTI_SZ: {
127                 uint32 j;
128                 for (j = 0; j < value->v.multi_sz.num_strings; j++) {
129                         result = talloc_asprintf(mem_ctx, "\"%s\" ", 
130                                                  value->v.multi_sz.strings[j]);
131                 }
132                 break;
133         }
134         case REG_BINARY:
135                 result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
136                                          (int)value->v.binary.length);
137                 break;
138         default:
139                 result = talloc_asprintf(mem_ctx, "<unprintable>");
140                 break;
141         }
142         return result;
143 }
144
145 /*
146  * add a value to a key. 
147  */
148 static WERROR reg_setvalue_internal(struct registry_key *key,
149                                     const char *valname,
150                                     const char *valtype,
151                                     const char *valstr)
152 {
153         struct registry_value val;
154         WERROR werr = WERR_OK;
155
156         ZERO_STRUCT(val);
157
158         if (strequal(valtype, "dword")) {
159                 val.type = REG_DWORD;
160                 val.v.dword = strtoul(valstr, NULL, 10);
161         }
162         else if (strequal(valtype, "sz")) {
163                 val.type = REG_SZ;
164                 val.v.sz.str = CONST_DISCARD(char *, valstr);
165                 val.v.sz.len = strlen(valstr) + 1;
166         }
167         else {
168                 d_fprintf(stderr, "Only value types DWORD and SZ are"
169                           "currently implemented for setting values.\n");
170                 werr = WERR_INVALID_PARAM;
171                 goto done;
172         }
173
174         if (!lp_parameter_is_valid(valname)) {
175                 d_fprintf(stderr, "Invalid parameter '%s' given.\n", valname);
176                 werr = WERR_INVALID_PARAM;
177                 goto done;
178         }
179
180         if (registry_smbconf_valname_forbidden(valname)) {
181                 d_fprintf(stderr, "Parameter '%s' not allowed in registry.\n",
182                           valname);
183                 werr = WERR_INVALID_PARAM;
184                 goto done;
185         }
186
187         if (!strequal(strrchr_m(key->key->name, '\\')+1, GLOBAL_NAME) &&
188             lp_parameter_is_global(valname))
189         {
190                 d_fprintf(stderr, "Global paramter '%s' not allowed in "
191                           "service definition ('%s').\n", valname,
192                           strrchr_m(key->key->name, '\\')+1);
193                 werr = WERR_INVALID_PARAM;
194                 goto done;
195         }
196
197         werr = reg_setvalue(key, valname, &val);
198         if (!W_ERROR_IS_OK(werr)) {
199                 d_fprintf(stderr,
200                           "Error adding value '%s' to "
201                           "key '%s': %s\n",
202                           valname, key->key->name, dos_errstr(werr));
203         }
204
205 done:
206         return werr;
207 }
208
209 /* 
210  * Open a subkey of KEY_SMBCONF (i.e a service)
211  * - variant without error output (q = quiet)-
212  */
213 static WERROR smbconf_open_path_q(TALLOC_CTX *ctx, const char *subkeyname,
214                                   uint32 desired_access, 
215                                   struct registry_key **key)
216 {
217         WERROR werr = WERR_OK;
218         char *path = NULL;
219         NT_USER_TOKEN *token;
220
221         if (!(token = registry_create_admin_token(ctx))) {
222                 DEBUG(1, ("Error creating admin token\n"));
223                 goto done;
224         }
225
226         if (subkeyname == NULL) {
227                 path = talloc_strdup(ctx, KEY_SMBCONF);
228         }
229         else {
230                 path = talloc_asprintf(ctx, "%s\\%s", KEY_SMBCONF, subkeyname);
231         }
232
233         werr = reg_open_path(ctx, path, desired_access,
234                              token, key);
235
236 done:
237         TALLOC_FREE(path);
238         return werr;
239 }
240
241 /* 
242  * Open a subkey of KEY_SMBCONF (i.e a service)
243  * - variant with error output -
244  */
245 static WERROR smbconf_open_path(TALLOC_CTX *ctx, const char *subkeyname,
246                                 uint32 desired_access, 
247                                 struct registry_key **key)
248 {
249         WERROR werr = WERR_OK;
250
251         werr = smbconf_open_path_q(ctx, subkeyname, desired_access, key);
252         if (!W_ERROR_IS_OK(werr)) {
253                 d_fprintf(stderr, "Error opening registry path '%s\\%s': %s\n",
254                           KEY_SMBCONF, 
255                           (subkeyname == NULL) ? "" : subkeyname, 
256                           dos_errstr(werr));
257         }
258
259         return werr;
260 }
261
262 /*
263  * open the base key KEY_SMBCONF
264  */
265 static WERROR smbconf_open_basepath(TALLOC_CTX *ctx, uint32 desired_access,
266                                     struct registry_key **key)
267 {
268         return smbconf_open_path(ctx, NULL, desired_access, key);
269 }
270
271 /*
272  * delete a subkey of KEY_SMBCONF
273  */
274 static WERROR reg_delkey_internal(TALLOC_CTX *ctx, const char *keyname)
275 {
276         WERROR werr = WERR_OK;
277         struct registry_key *key = NULL;
278
279         werr = smbconf_open_basepath(ctx, REG_KEY_WRITE, &key);
280         if (!W_ERROR_IS_OK(werr)) {
281                 goto done;
282         }
283
284         werr = reg_deletekey_recursive(key, key, keyname);
285         if (!W_ERROR_IS_OK(werr)) {
286                 d_fprintf(stderr, "Error deleting registry key %s\\%s: %s\n",
287                           KEY_SMBCONF, keyname, dos_errstr(werr));
288         }
289
290 done:
291         TALLOC_FREE(key);
292         return werr;
293 }
294
295 /*
296  * create a subkey of KEY_SMBCONF
297  */
298 static WERROR reg_createkey_internal(TALLOC_CTX *ctx,
299                                      const char * subkeyname,
300                                      struct registry_key **newkey)
301 {
302         WERROR werr = WERR_OK;
303         struct registry_key *create_parent = NULL;
304         TALLOC_CTX *create_ctx;
305         enum winreg_CreateAction action = REG_ACTION_NONE;
306
307         /* create a new talloc ctx for creation. it will hold
308          * the intermediate parent key (SMBCONF) for creation
309          * and will be destroyed when leaving this function... */
310         if (!(create_ctx = talloc_new(ctx))) {
311                 werr = WERR_NOMEM;
312                 goto done;
313         }
314
315         werr = smbconf_open_basepath(create_ctx, REG_KEY_WRITE, &create_parent);
316         if (!W_ERROR_IS_OK(werr)) {
317                 goto done;
318         }
319
320         werr = reg_createkey(ctx, create_parent, subkeyname, 
321                              REG_KEY_WRITE, newkey, &action);
322         if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) {
323                 d_fprintf(stderr, "Key '%s' already exists.\n", subkeyname);
324                 werr = WERR_ALREADY_EXISTS;
325         }
326         if (!W_ERROR_IS_OK(werr)) {
327                 d_fprintf(stderr, "Error creating key %s: %s\n",
328                          subkeyname, dos_errstr(werr));
329         }
330
331 done:
332         TALLOC_FREE(create_ctx);
333         return werr;
334 }
335
336 /*
337  * check if a subkey of KEY_SMBCONF of a given name exists
338  */
339 static BOOL smbconf_key_exists(TALLOC_CTX *ctx, const char *subkeyname)
340 {
341         BOOL ret = False;
342         WERROR werr = WERR_OK;
343         TALLOC_CTX *mem_ctx;
344         struct registry_key *key;
345
346         if (!(mem_ctx = talloc_new(ctx))) {
347                 d_fprintf(stderr, "ERROR: Out of memory...!\n");
348                 goto done;
349         }
350
351         werr = smbconf_open_path_q(mem_ctx, subkeyname, REG_KEY_READ, &key);
352         if (W_ERROR_IS_OK(werr)) {
353                 ret = True;
354         }
355
356 done:
357         TALLOC_FREE(mem_ctx);
358         return ret;
359 }
360
361 static BOOL smbconf_value_exists(TALLOC_CTX *ctx, struct registry_key *key,
362                                  const char *param)
363 {
364         BOOL ret = False;
365         WERROR werr = WERR_OK;
366         struct registry_value *value = NULL;
367
368         werr = reg_queryvalue(ctx, key, param, &value); 
369         if (W_ERROR_IS_OK(werr)) {
370                 ret = True;
371         }
372
373         TALLOC_FREE(value);
374         return ret;
375 }
376
377 static WERROR list_values(TALLOC_CTX *ctx, struct registry_key *key)
378 {
379         WERROR werr = WERR_OK;
380         uint32 idx = 0;
381         struct registry_value *valvalue = NULL;
382         char *valname = NULL;
383
384         for (idx = 0;
385              W_ERROR_IS_OK(werr = reg_enumvalue(ctx, key, idx, &valname,
386                                                 &valvalue));
387              idx++)
388         {
389                 d_printf("\t%s = %s\n", valname, format_value(ctx, valvalue));
390         }
391         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
392                 d_fprintf(stderr, "Error enumerating values: %s\n",
393                           dos_errstr(werr));
394                 goto done;
395         }
396         werr = WERR_OK;
397
398 done:
399         return werr; 
400 }
401
402 static WERROR drop_smbconf_internal(TALLOC_CTX *ctx)
403 {
404         char *path, *p;
405         WERROR werr = WERR_OK;
406         NT_USER_TOKEN *token;
407         struct registry_key *parent_key = NULL;
408         struct registry_key *new_key = NULL;
409         TALLOC_CTX* tmp_ctx = NULL;
410         enum winreg_CreateAction action;
411
412         tmp_ctx = talloc_new(ctx);
413         if (tmp_ctx == NULL) {
414                 werr = WERR_NOMEM;
415                 goto done;
416         }
417
418         if (!(token = registry_create_admin_token(tmp_ctx))) {
419                 /* what is the appropriate error code here? */
420                 werr = WERR_CAN_NOT_COMPLETE; 
421                 goto done;
422         }
423
424         path = talloc_strdup(tmp_ctx, KEY_SMBCONF);
425         if (path == NULL) {
426                 d_fprintf(stderr, "ERROR: out of memory!\n");
427                 werr = WERR_NOMEM;
428                 goto done;
429         }
430         p = strrchr(path, '\\');
431         *p = '\0';
432         werr = reg_open_path(tmp_ctx, path, REG_KEY_WRITE, token, &parent_key);
433
434         if (!W_ERROR_IS_OK(werr)) {
435                 goto done;
436         }
437
438         werr = reg_deletekey_recursive(tmp_ctx, parent_key, p+1);
439
440         if (!W_ERROR_IS_OK(werr)) {
441                 goto done;
442         }
443         
444         werr = reg_createkey(tmp_ctx, parent_key, p+1, REG_KEY_WRITE, 
445                              &new_key, &action);
446
447 done:
448         TALLOC_FREE(tmp_ctx);
449         return werr;
450 }
451
452 static int import_process_service(TALLOC_CTX *ctx, 
453                                   struct share_params *share)
454 {
455         int ret = -1;
456         struct parm_struct *parm;
457         int pnum = 0;
458         const char *servicename;
459         struct registry_key *key;
460         WERROR werr;
461         const char *valtype = NULL;
462         char *valstr = NULL;
463
464         servicename = (share->service == GLOBAL_SECTION_SNUM)?
465                 GLOBAL_NAME : lp_servicename(share->service);
466
467         if (opt_testmode) {
468                 d_printf("[%s]\n", servicename);
469         }
470         else {
471                 if (smbconf_key_exists(ctx, servicename)) {
472                         werr = reg_delkey_internal(ctx, servicename);
473                         if (!W_ERROR_IS_OK(werr)) {
474                                 goto done;
475                         }
476                 }
477                 werr = reg_createkey_internal(ctx, servicename, &key);
478                 if (!W_ERROR_IS_OK(werr)) {
479                         goto done;
480                 }
481         }
482
483         while ((parm = lp_next_parameter(share->service, &pnum, 0)))
484         {
485                 void *ptr = parm->ptr;
486                 int i = 0;
487
488                 if ((share->service < 0 && parm->p_class == P_LOCAL) 
489                     && !(parm->flags & FLAG_GLOBAL))
490                         continue;
491
492                 if (parm->p_class == P_LOCAL && share->service >= 0) {
493                         ptr = lp_local_ptr(share->service, ptr);
494                 }
495
496                 valtype = "sz";
497
498                 switch (parm->type) {
499                 case P_CHAR:
500                         valstr = talloc_asprintf(ctx, "%c", *(char *)ptr);
501                         break;
502                 case P_STRING:
503                 case P_USTRING:
504                         valstr = talloc_asprintf(ctx, "%s", *(char **)ptr);
505                         break;
506                 case P_GSTRING:
507                 case P_UGSTRING:
508                         valstr = talloc_asprintf(ctx, "%s", (char *)ptr);
509                         break;
510                 case P_BOOL:
511                         valstr = talloc_asprintf(ctx, "%s", 
512                                                 BOOLSTR(*(BOOL *)ptr));
513                         break;
514                 case P_BOOLREV:
515                         valstr = talloc_asprintf(ctx, "%s", 
516                                                 BOOLSTR(!*(BOOL *)ptr));
517                         break;
518                 case P_ENUM:
519                         for (i = 0; parm->enum_list[i].name; i++) {
520                                 if (*(int *)ptr == 
521                                     parm->enum_list[i].value) 
522                                 {
523                                         valstr = talloc_asprintf(ctx, "%s",
524                                                  parm->enum_list[i].name);
525                                         break;
526                                 }
527                         }
528                         break;
529                 case P_OCTAL:
530                         valstr = talloc_asprintf(ctx, "%s", octal_string(*(int *)ptr));
531                         break;
532                 case P_LIST:
533                         valstr = talloc_strdup(ctx, "");
534                         if ((char ***)ptr && *(char ***)ptr) {
535                                 char **list = *(char ***)ptr;
536                                 for (; *list; list++) {
537                                         /* surround strings with whitespace 
538                                          * in double quotes */
539                                         if (strchr_m(*list, ' '))
540                                         {
541                                                 valstr = talloc_asprintf_append(
542                                                         valstr, "\"%s\"%s", 
543                                                         *list, 
544                                                          ((*(list+1))?", ":""));
545                                         }
546                                         else {
547                                                 valstr = talloc_asprintf_append(
548                                                         valstr, "%s%s", *list, 
549                                                          ((*(list+1))?", ":""));
550                                         }
551                                 }
552                         }
553                         break;
554                 case P_INTEGER:
555                         valtype = "dword";
556                         valstr = talloc_asprintf(ctx, "%d", *(int *)ptr);
557                         break;
558                 case P_SEP:
559                         break;
560                 default:
561                         valstr = talloc_asprintf(ctx, "<type unimplemented>\n");
562                         break;
563                 }
564
565                 if (parm->type != P_SEP) {
566                         if (opt_testmode) {
567                                 d_printf("\t%s = %s\n", parm->label, valstr);
568                         }
569                         else {
570                                 werr = reg_setvalue_internal(key, parm->label, 
571                                                              valtype, valstr);
572                                 if (!W_ERROR_IS_OK(werr)) {
573                                         goto done;
574                                 }
575                         }
576                 }
577         }
578
579         if (opt_testmode) {
580                 d_printf("\n");
581         }
582
583         ret = 0;
584 done:
585         return ret;
586 }
587
588
589 /*
590  * the conf functions 
591  */
592
593 int net_conf_list(int argc, const char **argv)
594 {
595         WERROR werr = WERR_OK;
596         int ret = -1;
597         TALLOC_CTX *ctx;
598         struct registry_key *base_key = NULL;
599         struct registry_key *sub_key = NULL;
600         uint32 idx_key = 0;
601         char *subkey_name = NULL;
602
603         ctx = talloc_init("list");
604
605         if (argc != 0) {
606                 net_conf_list_usage(argc, argv);
607                 goto done;
608         }
609
610         werr = smbconf_open_basepath(ctx, REG_KEY_READ, &base_key);
611         if (!W_ERROR_IS_OK(werr)) {
612                 goto done;
613         }
614
615         if (smbconf_key_exists(ctx, GLOBAL_NAME))  {
616                 werr = reg_openkey(ctx, base_key, GLOBAL_NAME, 
617                                    REG_KEY_READ, &sub_key);
618                 if (!W_ERROR_IS_OK(werr)) {
619                         d_fprintf(stderr, "Error opening subkey '%s' : %s\n",
620                                   subkey_name, dos_errstr(werr));
621                         goto done;
622                 }
623                 d_printf("[%s]\n", GLOBAL_NAME);
624                 if (!W_ERROR_IS_OK(list_values(ctx, sub_key))) {
625                         goto done;
626                 }
627                 d_printf("\n");
628         }
629
630         for (idx_key = 0;
631              W_ERROR_IS_OK(werr = reg_enumkey(ctx, base_key, idx_key,
632                                               &subkey_name, NULL));
633              idx_key++) 
634         {
635                 if (strequal(subkey_name, GLOBAL_NAME)) {
636                         continue;
637                 }
638                 d_printf("[%s]\n", subkey_name);
639
640                 werr = reg_openkey(ctx, base_key, subkey_name, 
641                                    REG_KEY_READ, &sub_key);
642                 if (!W_ERROR_IS_OK(werr)) {
643                         d_fprintf(stderr, 
644                                   "Error opening subkey '%s': %s\n",
645                                   subkey_name, dos_errstr(werr));
646                         goto done;
647                 }
648                 if (!W_ERROR_IS_OK(list_values(ctx, sub_key))) {
649                         goto done;
650                 }
651                 d_printf("\n");
652         }
653         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
654                 d_fprintf(stderr, "Error enumerating subkeys: %s\n", 
655                           dos_errstr(werr));
656                 goto done;
657         }
658
659         ret = 0;
660
661 done:
662         TALLOC_FREE(ctx);
663         return ret;
664 }
665
666 int net_conf_import(int argc, const char **argv)
667 {
668         int ret = -1;
669         const char *filename = NULL;
670         const char *servicename = NULL;
671         BOOL service_found = False;
672         TALLOC_CTX *ctx;
673         struct share_iterator *shares;
674         struct share_params *share;
675         struct share_params global_share = { GLOBAL_SECTION_SNUM };
676
677         ctx = talloc_init("net_conf_import");
678
679         switch (argc) {
680                 case 0:
681                 default:
682                         net_conf_import_usage(argc, argv);
683                         goto done;
684                 case 2:
685                         servicename = argv[1];
686                 case 1:
687                         filename = argv[0];
688                         break;
689         }
690
691         DEBUG(3,("net_conf_import: reading configuration from file %s.\n",
692                 filename));
693
694         if (!lp_load(filename, 
695                      False,     /* global_only */
696                      True,      /* save_defaults */
697                      False,     /* add_ipc */
698                      True))     /* initialize_globals */
699         {
700                 d_fprintf(stderr, "Error parsing configuration file.\n");
701                 goto done;
702         }
703
704         if (opt_testmode) {
705                 d_printf("\nTEST MODE - would import the following configuration:\n\n");
706         }
707
708         if ((servicename == NULL) || strequal(servicename, GLOBAL_NAME)) {
709                 service_found = True;
710                 if (import_process_service(ctx, &global_share) != 0) {
711                         goto done;
712                 }
713         }
714
715         if (service_found && (servicename != NULL)) {
716                 ret = 0;
717                 goto done;
718         }
719
720         if (!(shares = share_list_all(ctx))) {
721                 d_fprintf(stderr, "Could not list shares...\n");
722                 goto done;
723         }
724         while ((share = next_share(shares)) != NULL) {
725                 if ((servicename == NULL) 
726                     || strequal(servicename, lp_servicename(share->service))) 
727                 {
728                         service_found = True;
729                         if (import_process_service(ctx, share)!= 0) {
730                                 goto done;
731                         }
732                 }
733         }
734         
735         if ((servicename != NULL) && !service_found) {
736                 d_printf("Share %s not found in file %s\n", 
737                          servicename, filename);
738                 goto done;
739
740         }
741
742         ret = 0;
743         
744 done:
745         TALLOC_FREE(ctx);
746         return ret;
747 }
748
749 int net_conf_listshares(int argc, const char **argv)
750 {
751         WERROR werr = WERR_OK;
752         int ret = -1;
753         struct registry_key *key;
754         uint32 idx = 0;
755         char *subkey_name = NULL;
756         TALLOC_CTX *ctx;
757
758         ctx = talloc_init("listshares");
759
760         if (argc != 0) {
761                 net_conf_listshares_usage(argc, argv);
762                 goto done;
763         }
764
765         werr = smbconf_open_basepath(ctx, SEC_RIGHTS_ENUM_SUBKEYS, &key);
766         if (!W_ERROR_IS_OK(werr)) {
767                 goto done;
768         }
769
770         for (idx = 0;
771              W_ERROR_IS_OK(werr = reg_enumkey(ctx, key, idx,
772                                               &subkey_name, NULL));
773              idx++) 
774         {
775                 d_printf("%s\n", subkey_name);
776         }
777         if (! W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
778                 d_fprintf(stderr, "Error enumerating subkeys: %s\n", 
779                           dos_errstr(werr));
780                 goto done;
781         }
782
783         ret = 0;
784
785 done:
786         TALLOC_FREE(ctx);
787         return ret;
788 }
789
790 int net_conf_drop(int argc, const char **argv)
791 {
792         int ret = -1;
793         WERROR werr;
794
795         if (argc != 0) {
796                 net_conf_drop_usage(argc, argv);
797                 goto done;
798         }
799
800         werr = drop_smbconf_internal(NULL);
801         if (!W_ERROR_IS_OK(werr)) {
802                 d_fprintf(stderr, "Error deleting configuration: %s\n",
803                           dos_errstr(werr));
804                 goto done;
805         }
806
807         ret = 0;
808
809 done:
810         return ret;
811 }
812
813 int net_conf_showshare(int argc, const char **argv)
814 {
815         int ret = -1;
816         WERROR werr = WERR_OK;
817         struct registry_key *key = NULL;
818         TALLOC_CTX *ctx;
819
820         ctx = talloc_init("showshare");
821
822         if (argc != 1) {
823                 net_conf_showshare_usage(argc, argv);
824                 goto done;
825         }
826
827         werr = smbconf_open_path(ctx, argv[0], REG_KEY_READ, &key);
828         if (!W_ERROR_IS_OK(werr)) {
829                 goto done;
830         }
831
832         d_printf("[%s]\n", argv[0]);
833
834         if (!W_ERROR_IS_OK(list_values(ctx, key))) {
835                 goto done;
836         }
837
838         ret = 0;
839
840 done:
841         TALLOC_FREE(ctx);
842         return ret;
843 }
844
845 int net_conf_addshare(int argc, const char **argv)
846 {
847         int ret = -1;
848         WERROR werr = WERR_OK;
849         struct registry_key *newkey = NULL;
850         char *sharename = NULL;
851         const char *path = NULL;
852         const char *comment = NULL;
853         const char *guest_ok = "no";
854         const char *writeable = "no";
855         SMB_STRUCT_STAT sbuf;
856
857         switch (argc) {
858                 case 0:
859                 case 1:
860                 default: 
861                         net_conf_addshare_usage(argc, argv);
862                         goto done;
863                 case 5:
864                         comment = argv[4];
865                 case 4:
866                         if (!strnequal(argv[3], "guest_ok=", 9)) {
867                                 net_conf_addshare_usage(argc, argv);
868                                 goto done;
869                         }
870                         switch (argv[3][9]) {
871                                 case 'y':
872                                 case 'Y':
873                                         guest_ok = "yes";
874                                         break;
875                                 case 'n':
876                                 case 'N':
877                                         guest_ok = "no";
878                                         break;
879                                 default: 
880                                         net_conf_addshare_usage(argc, argv);
881                                         goto done;
882                         }
883                 case 3:
884                         if (!strnequal(argv[2], "writeable=", 10)) {
885                                 net_conf_addshare_usage(argc, argv);
886                                 goto done;
887                         }
888                         switch (argv[2][10]) {
889                                 case 'y':
890                                 case 'Y':
891                                         writeable = "yes";
892                                         break;
893                                 case 'n':
894                                 case 'N':
895                                         writeable = "no";
896                                         break;
897                                 default:
898                                         net_conf_addshare_usage(argc, argv);
899                                         goto done;
900                         }
901
902                 case 2:
903                         path = argv[1];
904                         sharename = strdup_lower(argv[0]);
905                         break;
906         }
907
908         /* 
909          * validate arguments 
910          */
911
912         /* validate share name */
913
914         if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS, 
915                                strlen(sharename))) 
916         {
917                 d_fprintf(stderr, "ERROR: share name %s contains "
918                         "invalid characters (any of %s)\n",
919                         sharename, INVALID_SHARENAME_CHARS);
920                 goto done;
921         }
922
923         if (getpwnam(sharename)) {
924                 d_fprintf(stderr, "ERROR: share name %s is already a valid "
925                           "system user name.\n", sharename);
926                 goto done;
927         }
928
929         if (strequal(sharename, GLOBAL_NAME)) {
930                 d_fprintf(stderr, 
931                           "ERROR: 'global' is not a valid share name.\n");
932                 goto done;
933         }
934
935         /* validate path */
936
937         if (path[0] != '/') {
938                 d_fprintf(stderr, 
939                           "Error: path '%s' is not an absolute path.\n",
940                           path);
941                 goto done;
942         }
943
944         if (sys_stat(path, &sbuf) != 0) {
945                 d_fprintf(stderr,
946                           "ERROR: cannot stat path '%s' to ensure "
947                           "this is a directory.\n"
948                           "Error was '%s'.\n", 
949                           path, strerror(errno));
950                 goto done;
951         }
952
953         if (!S_ISDIR(sbuf.st_mode)) {
954                 d_fprintf(stderr,
955                           "ERROR: path '%s' is not a directory.\n",
956                           path);
957                 goto done;
958         }
959
960         /* 
961          * create the share 
962          */
963
964         werr = reg_createkey_internal(NULL, argv[0], &newkey);
965         if (!W_ERROR_IS_OK(werr)) {
966                 goto done;
967         }
968
969         /* add config params as values */
970
971         werr = reg_setvalue_internal(newkey, "path", "sz", path);
972         if (!W_ERROR_IS_OK(werr))
973                 goto done;
974
975         if (comment != NULL) {
976                 werr = reg_setvalue_internal(newkey, "comment", "sz", comment);
977                 if (!W_ERROR_IS_OK(werr))
978                         goto done;
979         }
980
981         werr = reg_setvalue_internal(newkey, "guest ok", "sz", guest_ok);
982         if (!W_ERROR_IS_OK(werr))
983                 goto done;
984         
985         werr = reg_setvalue_internal(newkey, "writeable", "sz", writeable);
986         if (!W_ERROR_IS_OK(werr))
987                 goto done;
988
989         ret = 0;
990
991 done:
992         TALLOC_FREE(newkey);
993         SAFE_FREE(sharename);
994         return ret;
995 }
996
997 int net_conf_delshare(int argc, const char **argv)
998 {
999         int ret = -1;
1000         const char *sharename = NULL;
1001
1002         if (argc != 1) {
1003                 net_conf_delshare_usage(argc, argv);
1004                 goto done;
1005         }
1006         sharename = argv[0];
1007         
1008         if (W_ERROR_IS_OK(reg_delkey_internal(NULL, sharename))) {
1009                 ret = 0;
1010         }
1011 done:
1012         return ret;
1013 }
1014
1015 static int net_conf_setparm(int argc, const char **argv)
1016 {
1017         int ret = -1;
1018         WERROR werr = WERR_OK;
1019         struct registry_key *key = NULL;
1020         char *service = NULL;
1021         char *param = NULL;
1022         const char *value_str = NULL;
1023         TALLOC_CTX *ctx;
1024
1025         ctx = talloc_init("setparm");
1026
1027         if (argc != 3) {
1028                 net_conf_setparm_usage(argc, argv);
1029                 goto done;
1030         }
1031         service = strdup_lower(argv[0]);
1032         param = strdup_lower(argv[1]);
1033         value_str = argv[2];
1034
1035         if (!smbconf_key_exists(ctx, service)) {
1036                 werr = reg_createkey_internal(ctx, service, &key);
1037         }
1038         else {
1039                 werr = smbconf_open_path(ctx, service, REG_KEY_READ, &key);
1040         }
1041         if (!W_ERROR_IS_OK(werr)) {
1042                 goto done;
1043         }
1044
1045         werr = reg_setvalue_internal(key, param, "sz", value_str);
1046         if (!W_ERROR_IS_OK(werr)) {
1047                 d_fprintf(stderr, "Error setting value '%s': %s\n",
1048                           param, dos_errstr(werr));
1049                 goto done;
1050         }
1051
1052
1053         ret = 0;
1054
1055 done:
1056         SAFE_FREE(service);
1057         TALLOC_FREE(ctx);
1058         return ret;
1059 }
1060
1061 static int net_conf_getparm(int argc, const char **argv)
1062 {
1063         int ret = -1;
1064         WERROR werr = WERR_OK;
1065         struct registry_key *key = NULL;
1066         char *service = NULL;
1067         char *param = NULL;
1068         struct registry_value *value = NULL;
1069         TALLOC_CTX *ctx;
1070
1071         ctx = talloc_init("getparm");
1072
1073         if (argc != 2) {
1074                 net_conf_getparm_usage(argc, argv);
1075                 goto done;
1076         }
1077         service = strdup_lower(argv[0]);
1078         param = strdup_lower(argv[1]);
1079
1080         if (!smbconf_key_exists(ctx, service)) {
1081                 d_fprintf(stderr, 
1082                           "ERROR: given service '%s' does not exist.\n",
1083                           service);
1084                 goto done;
1085         }
1086
1087         werr = smbconf_open_path(ctx, service, REG_KEY_READ, &key);
1088         if (!W_ERROR_IS_OK(werr)) {
1089                 goto done;
1090         }
1091
1092         werr = reg_queryvalue(ctx, key, param, &value);
1093         if (!W_ERROR_IS_OK(werr)) {
1094                 d_fprintf(stderr, "Error querying value '%s': %s.\n",
1095                           param, dos_errstr(werr));
1096                 goto done;
1097         }
1098         
1099         d_printf("%s\n", format_value(ctx, value));
1100         
1101         ret = 0;
1102 done:
1103         SAFE_FREE(service);
1104         SAFE_FREE(param);
1105         TALLOC_FREE(ctx);
1106         return ret;
1107 }
1108
1109 static int net_conf_delparm(int argc, const char **argv)
1110 {
1111         int ret = -1;
1112         WERROR werr = WERR_OK;
1113         struct registry_key *key = NULL;
1114         char *service = NULL;
1115         char *param = NULL;
1116         TALLOC_CTX *ctx;
1117
1118         ctx = talloc_init("delparm");
1119
1120         if (argc != 2) {
1121                 net_conf_delparm_usage(argc, argv);
1122                 goto done;
1123         }
1124         service = strdup_lower(argv[0]);
1125         param = strdup_lower(argv[1]);
1126
1127         if (!smbconf_key_exists(ctx, service)) {
1128                 d_fprintf(stderr, 
1129                           "Error: given service '%s' does not exist.\n",
1130                           service);
1131                 goto done;
1132         }
1133
1134         werr = smbconf_open_path(ctx, service, REG_KEY_READ, &key);
1135         if (!W_ERROR_IS_OK(werr)) {
1136                 goto done;
1137         }
1138
1139         if (!smbconf_value_exists(ctx, key, param)) {
1140                 d_fprintf(stderr, 
1141                           "Error: given parameter '%s' is not set.\n",
1142                           param);
1143                 goto done;
1144         }
1145         werr = reg_deletevalue(key, param);
1146         if (!W_ERROR_IS_OK(werr)) {
1147                 d_fprintf(stderr, "Error deleting value '%s': %s.\n",
1148                           param, dos_errstr(werr));
1149                 goto done;
1150         }
1151
1152         ret = 0;
1153
1154 done:
1155         return ret;
1156 }
1157
1158 /*
1159  * Entry-point for all the CONF functions.
1160  */
1161
1162 int net_conf(int argc, const char **argv)
1163 {
1164         int ret = -1;
1165         struct functable2 func[] = {
1166                 {"list", net_conf_list, 
1167                  "Dump the complete configuration in smb.conf like format."},
1168                 {"import", net_conf_import,
1169                  "Import configuration from file in smb.conf format."},
1170                 {"listshares", net_conf_listshares, 
1171                  "List the registry shares."},
1172                 {"drop", net_conf_drop,
1173                  "Delete the complete configuration from registry."},
1174                 {"showshare", net_conf_showshare, 
1175                  "Show the definition of a registry share."},
1176                 {"addshare", net_conf_addshare, 
1177                  "Create a new registry share."},
1178                 {"delshare", net_conf_delshare, 
1179                  "Delete a registry share."},
1180                 {"setparm", net_conf_setparm, 
1181                  "Store a parameter."},
1182                 {"getparm", net_conf_getparm, 
1183                  "Retrieve the value of a parameter."},
1184                 {"delparm", net_conf_delparm, 
1185                  "Delete a parameter."},
1186                 {NULL, NULL, NULL}
1187         };
1188
1189         if (!registry_init_regdb()) {
1190                 d_fprintf(stderr, "Error initializing the registry!\n");
1191                 goto done;
1192         }
1193
1194         ret = net_run_function2(argc, argv, "net conf", func);
1195
1196         regdb_close();
1197
1198 done:
1199         return ret;
1200 }
1201
1202 /* END */