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