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