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