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