f7385586fb336a619e69361874cef296a6a13d46
[samba.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> [<servicename>]\n"
43                  "\t[--test|-T]    testmode - do not act, just print "
44                                    "what would be done\n"
45                  "\t<servicename>  only import service <servicename>, "
46                                    "ignore the rest\n");
47         return -1;
48 }
49
50 static int net_conf_listshares_usage(int argc, const char **argv)
51 {
52         d_printf("USAGE: net conf listshares\n");
53         return -1;
54 }
55
56 static int net_conf_drop_usage(int argc, const char **argv)
57 {
58         d_printf("USAGE: net conf drop\n");
59         return -1;
60 }
61
62 static int net_conf_showshare_usage(int argc, const char **argv)
63 {
64         d_printf("USAGE: net conf showshare <sharename>\n");
65         return -1;
66 }
67
68 static int net_conf_addshare_usage(int argc, const char **argv)
69 {
70         d_printf("USAGE: net conf addshare <sharename> <path> "
71                  "[writeable={y|N} [guest_ok={y|N} [<comment>]]\n"
72                  "\t<sharename>      the new share name.\n"
73                  "\t<path>           the path on the filesystem to export.\n"
74                  "\twriteable={y|N}  set \"writeable to \"yes\" or "
75                  "\"no\" (default) on this share.\n"
76                  "\tguest_ok={y|N}   set \"guest ok\" to \"yes\" or "
77                  "\"no\" (default)   on this share.\n"
78                  "\t<comment>        optional comment for the new share.\n");
79         return -1;
80 }
81
82 static int net_conf_delshare_usage(int argc, const char **argv)
83 {
84         d_printf("USAGE: net conf delshare <sharename>\n");
85         return -1;
86 }
87
88 static int net_conf_setparm_usage(int argc, const char **argv)
89 {
90         d_printf("USAGE: net conf setparm <section> <param> <value>\n");
91         return -1;
92 }
93
94 static int net_conf_getparm_usage(int argc, const char **argv)
95 {
96         d_printf("USAGE: net conf getparm <section> <param>\n");
97         return -1;
98 }
99
100 static int net_conf_delparm_usage(int argc, const char **argv)
101 {
102         d_printf("USAGE: net conf delparm <section> <param>\n");
103         return -1;
104 }
105
106
107 /*
108  * Helper functions
109  */
110
111 static char *format_value(TALLOC_CTX *mem_ctx, struct registry_value *value)
112 {
113         char *result = NULL;
114
115         /* what if mem_ctx = NULL? */
116
117         switch (value->type) {
118         case REG_DWORD:
119                 result = talloc_asprintf(mem_ctx, "%d", value->v.dword);
120                 break;
121         case REG_SZ:
122         case REG_EXPAND_SZ:
123                 result = talloc_asprintf(mem_ctx, "%s", value->v.sz.str);
124                 break;
125         case REG_MULTI_SZ: {
126                 uint32 j;
127                 for (j = 0; j < value->v.multi_sz.num_strings; j++) {
128                         result = talloc_asprintf(mem_ctx, "\"%s\" ", 
129                                                  value->v.multi_sz.strings[j]);
130                 }
131                 break;
132         }
133         case REG_BINARY:
134                 result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
135                                          (int)value->v.binary.length);
136                 break;
137         default:
138                 result = talloc_asprintf(mem_ctx, "<unprintable>");
139                 break;
140         }
141         return result;
142 }
143
144 /*
145  * add a value to a key. 
146  */
147 static WERROR reg_setvalue_internal(struct registry_key *key,
148                                     const char *valname,
149                                     const char *valstr)
150 {
151         struct registry_value val;
152         WERROR werr = WERR_OK;
153         char *subkeyname;
154         const char *canon_valname;
155         const char *canon_valstr;
156         BOOL canon_inverse;
157         struct parm_struct *parm;
158
159         if (!lp_parameter_is_valid(valname)) {
160                 d_fprintf(stderr, "Invalid parameter '%s' given.\n", valname);
161                 werr = WERR_INVALID_PARAM;
162                 goto done;
163         }
164
165         if (!lp_canonicalize_parameter(valname, &canon_valname, &canon_inverse))
166         {
167                 d_fprintf(stderr, "ERROR: could not canonicalize parameter "
168                           "'%s' after successful validation: this should not "
169                           "happen!\n", valname);
170                 werr = WERR_INVALID_PARAM;
171                 goto done;
172         }
173         if (canon_inverse) {
174                 if (!lp_invert_boolean(valstr, &canon_valstr)) {
175                         d_fprintf(stderr, "invalid value '%s' given for "
176                                   "parameter '%s'\n", valstr, canon_valname);
177                         werr = WERR_INVALID_PARAM;
178                         goto done;
179                 }
180         } else {
181                 parm = lp_get_parameter(canon_valname);
182                 if (parm->type == P_BOOL) {
183                         if (!lp_canonicalize_boolean(valstr, &canon_valstr)) {
184                                 d_fprintf(stderr, "invalied value '%s' given "
185                                           "for parameter '%s'\n", valstr,
186                                           canon_valname);
187                                 werr = WERR_INVALID_PARAM;
188                                 goto done;
189                         }
190                 } else {
191                         canon_valstr = valstr;
192                 }
193         }
194
195         ZERO_STRUCT(val);
196
197         val.type = REG_SZ;
198         val.v.sz.str = CONST_DISCARD(char *, canon_valstr);
199         val.v.sz.len = strlen(canon_valstr) + 1;
200
201         if (registry_smbconf_valname_forbidden(canon_valname)) {
202                 d_fprintf(stderr, "Parameter '%s' not allowed in registry.\n",
203                           canon_valname);
204                 werr = WERR_INVALID_PARAM;
205                 goto done;
206         }
207
208         subkeyname = strrchr_m(key->key->name, '\\');
209         if ((subkeyname == NULL) || (*(subkeyname +1) == '\0')) {
210                 d_fprintf(stderr, "Invalid registry key '%s' given as "
211                           "smbconf section.\n", key->key->name);
212                 werr = WERR_INVALID_PARAM;
213                 goto done;
214         }
215         subkeyname++;
216         if (!strequal(subkeyname, GLOBAL_NAME) &&
217             lp_parameter_is_global(valname))
218         {
219                 d_fprintf(stderr, "Global paramter '%s' not allowed in "
220                           "service definition ('%s').\n", canon_valname,
221                           subkeyname);
222                 werr = WERR_INVALID_PARAM;
223                 goto done;
224         }
225
226         werr = reg_setvalue(key, canon_valname, &val);
227         if (!W_ERROR_IS_OK(werr)) {
228                 d_fprintf(stderr,
229                           "Error adding value '%s' to "
230                           "key '%s': %s\n",
231                           canon_valname, key->key->name, dos_errstr(werr));
232         }
233
234 done:
235         return werr;
236 }
237
238 /* 
239  * Open a subkey of KEY_SMBCONF (i.e a service)
240  * - variant without error output (q = quiet)-
241  */
242 static WERROR smbconf_open_path_q(TALLOC_CTX *ctx, const char *subkeyname,
243                                   uint32 desired_access, 
244                                   struct registry_key **key)
245 {
246         WERROR werr = WERR_OK;
247         char *path = NULL;
248         NT_USER_TOKEN *token;
249
250         if (!(token = registry_create_admin_token(ctx))) {
251                 DEBUG(1, ("Error creating admin token\n"));
252                 goto done;
253         }
254
255         if (subkeyname == NULL) {
256                 path = talloc_strdup(ctx, KEY_SMBCONF);
257         }
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                                 }
537                                 else {
538                                         valstr = talloc_asprintf_append(
539                                                 valstr, "%s%s", *list,
540                                                  ((*(list+1))?", ":""));
541                                 }
542                         }
543                 }
544                 break;
545         case P_INTEGER:
546                 valstr = talloc_asprintf(ctx, "%d", *(int *)ptr);
547                 break;
548         case P_SEP:
549                 break;
550         default:
551                 valstr = talloc_asprintf(ctx, "<type unimplemented>\n");
552                 break;
553         }
554
555         return valstr;
556 }
557
558 static int import_process_service(TALLOC_CTX *ctx,
559                                   struct share_params *share)
560 {
561         int ret = -1;
562         struct parm_struct *parm;
563         int pnum = 0;
564         const char *servicename;
565         struct registry_key *key;
566         WERROR werr;
567         char *valstr = NULL;
568         TALLOC_CTX *tmp_ctx = NULL;
569
570         tmp_ctx = talloc_new(ctx);
571         if (tmp_ctx == NULL) {
572                 werr = WERR_NOMEM;
573                 goto done;
574         }
575
576         servicename = (share->service == GLOBAL_SECTION_SNUM)?
577                 GLOBAL_NAME : lp_servicename(share->service);
578
579         if (opt_testmode) {
580                 d_printf("[%s]\n", servicename);
581         }
582         else {
583                 if (smbconf_key_exists(tmp_ctx, servicename)) {
584                         werr = reg_delkey_internal(tmp_ctx, servicename);
585                         if (!W_ERROR_IS_OK(werr)) {
586                                 goto done;
587                         }
588                 }
589                 werr = reg_createkey_internal(tmp_ctx, servicename, &key);
590                 if (!W_ERROR_IS_OK(werr)) {
591                         goto done;
592                 }
593         }
594
595         while ((parm = lp_next_parameter(share->service, &pnum, 0)))
596         {
597                 if ((share->service < 0 && parm->p_class == P_LOCAL)
598                     && !(parm->flags & FLAG_GLOBAL))
599                         continue;
600
601                 valstr = parm_valstr(tmp_ctx, parm, share);
602
603                 if (parm->type != P_SEP) {
604                         if (opt_testmode) {
605                                 d_printf("\t%s = %s\n", parm->label, valstr);
606                         }
607                         else {
608                                 werr = reg_setvalue_internal(key, parm->label,
609                                                              valstr);
610                                 if (!W_ERROR_IS_OK(werr)) {
611                                         goto done;
612                                 }
613                         }
614                 }
615         }
616
617         if (opt_testmode) {
618                 d_printf("\n");
619         }
620
621         ret = 0;
622
623 done:
624         TALLOC_FREE(tmp_ctx);
625         return ret;
626 }
627
628 /* return True iff there are nondefault globals */
629 static BOOL globals_exist(void)
630 {
631         int i = 0;
632         struct parm_struct *parm;
633
634         while ((parm = lp_next_parameter(GLOBAL_SECTION_SNUM, &i, 0)) != NULL) {
635                 if (parm->type != P_SEP) {
636                         return True;
637                 }
638         }
639         return False;
640 }
641
642 /*
643  * the conf functions 
644  */
645
646 int net_conf_list(int argc, const char **argv)
647 {
648         WERROR werr = WERR_OK;
649         int ret = -1;
650         TALLOC_CTX *ctx;
651         struct registry_key *base_key = NULL;
652         struct registry_key *sub_key = NULL;
653         uint32 idx_key = 0;
654         char *subkey_name = NULL;
655
656         ctx = talloc_init("list");
657
658         if (argc != 0) {
659                 net_conf_list_usage(argc, argv);
660                 goto done;
661         }
662
663         werr = smbconf_open_basepath(ctx, REG_KEY_READ, &base_key);
664         if (!W_ERROR_IS_OK(werr)) {
665                 goto done;
666         }
667
668         if (smbconf_key_exists(ctx, GLOBAL_NAME))  {
669                 werr = reg_openkey(ctx, base_key, GLOBAL_NAME, 
670                                    REG_KEY_READ, &sub_key);
671                 if (!W_ERROR_IS_OK(werr)) {
672                         d_fprintf(stderr, "Error opening subkey '%s' : %s\n",
673                                   subkey_name, dos_errstr(werr));
674                         goto done;
675                 }
676                 d_printf("[%s]\n", GLOBAL_NAME);
677                 if (!W_ERROR_IS_OK(list_values(ctx, sub_key))) {
678                         goto done;
679                 }
680                 d_printf("\n");
681         }
682
683         for (idx_key = 0;
684              W_ERROR_IS_OK(werr = reg_enumkey(ctx, base_key, idx_key,
685                                               &subkey_name, NULL));
686              idx_key++) 
687         {
688                 if (strequal(subkey_name, GLOBAL_NAME)) {
689                         continue;
690                 }
691                 d_printf("[%s]\n", subkey_name);
692
693                 werr = reg_openkey(ctx, base_key, subkey_name, 
694                                    REG_KEY_READ, &sub_key);
695                 if (!W_ERROR_IS_OK(werr)) {
696                         d_fprintf(stderr, 
697                                   "Error opening subkey '%s': %s\n",
698                                   subkey_name, dos_errstr(werr));
699                         goto done;
700                 }
701                 if (!W_ERROR_IS_OK(list_values(ctx, sub_key))) {
702                         goto done;
703                 }
704                 d_printf("\n");
705         }
706         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
707                 d_fprintf(stderr, "Error enumerating subkeys: %s\n", 
708                           dos_errstr(werr));
709                 goto done;
710         }
711
712         ret = 0;
713
714 done:
715         TALLOC_FREE(ctx);
716         return ret;
717 }
718
719 int net_conf_import(int argc, const char **argv)
720 {
721         int ret = -1;
722         const char *filename = NULL;
723         const char *servicename = NULL;
724         BOOL service_found = False;
725         TALLOC_CTX *ctx;
726         struct share_iterator *shares;
727         struct share_params *share;
728         struct share_params global_share = { GLOBAL_SECTION_SNUM };
729
730         ctx = talloc_init("net_conf_import");
731
732         switch (argc) {
733                 case 0:
734                 default:
735                         net_conf_import_usage(argc, argv);
736                         goto done;
737                 case 2:
738                         servicename = argv[1];
739                 case 1:
740                         filename = argv[0];
741                         break;
742         }
743
744         DEBUG(3,("net_conf_import: reading configuration from file %s.\n",
745                 filename));
746
747         if (!lp_load(filename,
748                      False,     /* global_only */
749                      True,      /* save_defaults */
750                      False,     /* add_ipc */
751                      True))     /* initialize_globals */
752         {
753                 d_fprintf(stderr, "Error parsing configuration file.\n");
754                 goto done;
755         }
756
757         if (opt_testmode) {
758                 d_printf("\nTEST MODE - "
759                          "would import the following configuration:\n\n");
760         }
761
762         if (((servicename == NULL) && globals_exist()) ||
763             strequal(servicename, GLOBAL_NAME))
764         {
765                 service_found = True;
766                 if (import_process_service(ctx, &global_share) != 0) {
767                         goto done;
768                 }
769         }
770
771         if (service_found && (servicename != NULL)) {
772                 ret = 0;
773                 goto done;
774         }
775
776         if (!(shares = share_list_all(ctx))) {
777                 d_fprintf(stderr, "Could not list shares...\n");
778                 goto done;
779         }
780         while ((share = next_share(shares)) != NULL) {
781                 if ((servicename == NULL)
782                     || strequal(servicename, lp_servicename(share->service)))
783                 {
784                         service_found = True;
785                         if (import_process_service(ctx, share)!= 0) {
786                                 goto done;
787                         }
788                 }
789         }
790
791         if ((servicename != NULL) && !service_found) {
792                 d_printf("Share %s not found in file %s\n",
793                          servicename, filename);
794                 goto done;
795
796         }
797
798         ret = 0;
799
800 done:
801         TALLOC_FREE(ctx);
802         return ret;
803 }
804
805 int net_conf_listshares(int argc, const char **argv)
806 {
807         WERROR werr = WERR_OK;
808         int ret = -1;
809         struct registry_key *key;
810         uint32 idx = 0;
811         char *subkey_name = NULL;
812         TALLOC_CTX *ctx;
813
814         ctx = talloc_init("listshares");
815
816         if (argc != 0) {
817                 net_conf_listshares_usage(argc, argv);
818                 goto done;
819         }
820
821         werr = smbconf_open_basepath(ctx, SEC_RIGHTS_ENUM_SUBKEYS, &key);
822         if (!W_ERROR_IS_OK(werr)) {
823                 goto done;
824         }
825
826         for (idx = 0;
827              W_ERROR_IS_OK(werr = reg_enumkey(ctx, key, idx,
828                                               &subkey_name, NULL));
829              idx++) 
830         {
831                 d_printf("%s\n", subkey_name);
832         }
833         if (! W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
834                 d_fprintf(stderr, "Error enumerating subkeys: %s\n", 
835                           dos_errstr(werr));
836                 goto done;
837         }
838
839         ret = 0;
840
841 done:
842         TALLOC_FREE(ctx);
843         return ret;
844 }
845
846 int net_conf_drop(int argc, const char **argv)
847 {
848         int ret = -1;
849         WERROR werr;
850
851         if (argc != 0) {
852                 net_conf_drop_usage(argc, argv);
853                 goto done;
854         }
855
856         werr = drop_smbconf_internal(NULL);
857         if (!W_ERROR_IS_OK(werr)) {
858                 d_fprintf(stderr, "Error deleting configuration: %s\n",
859                           dos_errstr(werr));
860                 goto done;
861         }
862
863         ret = 0;
864
865 done:
866         return ret;
867 }
868
869 int net_conf_showshare(int argc, const char **argv)
870 {
871         int ret = -1;
872         WERROR werr = WERR_OK;
873         struct registry_key *key = NULL;
874         TALLOC_CTX *ctx;
875
876         ctx = talloc_init("showshare");
877
878         if (argc != 1) {
879                 net_conf_showshare_usage(argc, argv);
880                 goto done;
881         }
882
883         werr = smbconf_open_path(ctx, argv[0], REG_KEY_READ, &key);
884         if (!W_ERROR_IS_OK(werr)) {
885                 goto done;
886         }
887
888         d_printf("[%s]\n", argv[0]);
889
890         if (!W_ERROR_IS_OK(list_values(ctx, key))) {
891                 goto done;
892         }
893
894         ret = 0;
895
896 done:
897         TALLOC_FREE(ctx);
898         return ret;
899 }
900
901 int net_conf_addshare(int argc, const char **argv)
902 {
903         int ret = -1;
904         WERROR werr = WERR_OK;
905         struct registry_key *newkey = NULL;
906         char *sharename = NULL;
907         const char *path = NULL;
908         const char *comment = NULL;
909         const char *guest_ok = "no";
910         const char *writeable = "no";
911         SMB_STRUCT_STAT sbuf;
912
913         switch (argc) {
914                 case 0:
915                 case 1:
916                 default: 
917                         net_conf_addshare_usage(argc, argv);
918                         goto done;
919                 case 5:
920                         comment = argv[4];
921                 case 4:
922                         if (!strnequal(argv[3], "guest_ok=", 9)) {
923                                 net_conf_addshare_usage(argc, argv);
924                                 goto done;
925                         }
926                         switch (argv[3][9]) {
927                                 case 'y':
928                                 case 'Y':
929                                         guest_ok = "yes";
930                                         break;
931                                 case 'n':
932                                 case 'N':
933                                         guest_ok = "no";
934                                         break;
935                                 default: 
936                                         net_conf_addshare_usage(argc, argv);
937                                         goto done;
938                         }
939                 case 3:
940                         if (!strnequal(argv[2], "writeable=", 10)) {
941                                 net_conf_addshare_usage(argc, argv);
942                                 goto done;
943                         }
944                         switch (argv[2][10]) {
945                                 case 'y':
946                                 case 'Y':
947                                         writeable = "yes";
948                                         break;
949                                 case 'n':
950                                 case 'N':
951                                         writeable = "no";
952                                         break;
953                                 default:
954                                         net_conf_addshare_usage(argc, argv);
955                                         goto done;
956                         }
957
958                 case 2:
959                         path = argv[1];
960                         sharename = strdup_lower(argv[0]);
961                         break;
962         }
963
964         /* 
965          * validate arguments 
966          */
967
968         /* validate share name */
969
970         if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS, 
971                                strlen(sharename))) 
972         {
973                 d_fprintf(stderr, "ERROR: share name %s contains "
974                         "invalid characters (any of %s)\n",
975                         sharename, INVALID_SHARENAME_CHARS);
976                 goto done;
977         }
978
979         if (getpwnam(sharename)) {
980                 d_fprintf(stderr, "ERROR: share name %s is already a valid "
981                           "system user name.\n", sharename);
982                 goto done;
983         }
984
985         if (strequal(sharename, GLOBAL_NAME)) {
986                 d_fprintf(stderr, 
987                           "ERROR: 'global' is not a valid share name.\n");
988                 goto done;
989         }
990
991         /* validate path */
992
993         if (path[0] != '/') {
994                 d_fprintf(stderr, 
995                           "Error: path '%s' is not an absolute path.\n",
996                           path);
997                 goto done;
998         }
999
1000         if (sys_stat(path, &sbuf) != 0) {
1001                 d_fprintf(stderr,
1002                           "ERROR: cannot stat path '%s' to ensure "
1003                           "this is a directory.\n"
1004                           "Error was '%s'.\n", 
1005                           path, strerror(errno));
1006                 goto done;
1007         }
1008
1009         if (!S_ISDIR(sbuf.st_mode)) {
1010                 d_fprintf(stderr,
1011                           "ERROR: path '%s' is not a directory.\n",
1012                           path);
1013                 goto done;
1014         }
1015
1016         /* 
1017          * create the share 
1018          */
1019
1020         werr = reg_createkey_internal(NULL, argv[0], &newkey);
1021         if (!W_ERROR_IS_OK(werr)) {
1022                 goto done;
1023         }
1024
1025         /* add config params as values */
1026
1027         werr = reg_setvalue_internal(newkey, "path", path);
1028         if (!W_ERROR_IS_OK(werr))
1029                 goto done;
1030
1031         if (comment != NULL) {
1032                 werr = reg_setvalue_internal(newkey, "comment", comment);
1033                 if (!W_ERROR_IS_OK(werr))
1034                         goto done;
1035         }
1036
1037         werr = reg_setvalue_internal(newkey, "guest ok", guest_ok);
1038         if (!W_ERROR_IS_OK(werr))
1039                 goto done;
1040         
1041         werr = reg_setvalue_internal(newkey, "writeable", writeable);
1042         if (!W_ERROR_IS_OK(werr))
1043                 goto done;
1044
1045         ret = 0;
1046
1047 done:
1048         TALLOC_FREE(newkey);
1049         SAFE_FREE(sharename);
1050         return ret;
1051 }
1052
1053 int net_conf_delshare(int argc, const char **argv)
1054 {
1055         int ret = -1;
1056         const char *sharename = NULL;
1057
1058         if (argc != 1) {
1059                 net_conf_delshare_usage(argc, argv);
1060                 goto done;
1061         }
1062         sharename = argv[0];
1063         
1064         if (W_ERROR_IS_OK(reg_delkey_internal(NULL, sharename))) {
1065                 ret = 0;
1066         }
1067 done:
1068         return ret;
1069 }
1070
1071 static int net_conf_setparm(int argc, const char **argv)
1072 {
1073         int ret = -1;
1074         WERROR werr = WERR_OK;
1075         struct registry_key *key = NULL;
1076         char *service = NULL;
1077         char *param = NULL;
1078         const char *value_str = NULL;
1079         TALLOC_CTX *ctx;
1080
1081         ctx = talloc_init("setparm");
1082
1083         if (argc != 3) {
1084                 net_conf_setparm_usage(argc, argv);
1085                 goto done;
1086         }
1087         service = strdup_lower(argv[0]);
1088         param = strdup_lower(argv[1]);
1089         value_str = argv[2];
1090
1091         if (!smbconf_key_exists(ctx, service)) {
1092                 werr = reg_createkey_internal(ctx, service, &key);
1093         }
1094         else {
1095                 werr = smbconf_open_path(ctx, service, REG_KEY_READ, &key);
1096         }
1097         if (!W_ERROR_IS_OK(werr)) {
1098                 goto done;
1099         }
1100
1101         werr = reg_setvalue_internal(key, param, value_str);
1102         if (!W_ERROR_IS_OK(werr)) {
1103                 d_fprintf(stderr, "Error setting value '%s': %s\n",
1104                           param, dos_errstr(werr));
1105                 goto done;
1106         }
1107
1108
1109         ret = 0;
1110
1111 done:
1112         SAFE_FREE(service);
1113         TALLOC_FREE(ctx);
1114         return ret;
1115 }
1116
1117 static int net_conf_getparm(int argc, const char **argv)
1118 {
1119         int ret = -1;
1120         WERROR werr = WERR_OK;
1121         struct registry_key *key = NULL;
1122         char *service = NULL;
1123         char *param = NULL;
1124         struct registry_value *value = NULL;
1125         TALLOC_CTX *ctx;
1126
1127         ctx = talloc_init("getparm");
1128
1129         if (argc != 2) {
1130                 net_conf_getparm_usage(argc, argv);
1131                 goto done;
1132         }
1133         service = strdup_lower(argv[0]);
1134         param = strdup_lower(argv[1]);
1135
1136         if (!smbconf_key_exists(ctx, service)) {
1137                 d_fprintf(stderr, 
1138                           "ERROR: given service '%s' does not exist.\n",
1139                           service);
1140                 goto done;
1141         }
1142
1143         werr = smbconf_open_path(ctx, service, REG_KEY_READ, &key);
1144         if (!W_ERROR_IS_OK(werr)) {
1145                 goto done;
1146         }
1147
1148         werr = reg_queryvalue(ctx, key, param, &value);
1149         if (!W_ERROR_IS_OK(werr)) {
1150                 d_fprintf(stderr, "Error querying value '%s': %s.\n",
1151                           param, dos_errstr(werr));
1152                 goto done;
1153         }
1154         
1155         d_printf("%s\n", format_value(ctx, value));
1156         
1157         ret = 0;
1158 done:
1159         SAFE_FREE(service);
1160         SAFE_FREE(param);
1161         TALLOC_FREE(ctx);
1162         return ret;
1163 }
1164
1165 static int net_conf_delparm(int argc, const char **argv)
1166 {
1167         int ret = -1;
1168         WERROR werr = WERR_OK;
1169         struct registry_key *key = NULL;
1170         char *service = NULL;
1171         char *param = NULL;
1172         TALLOC_CTX *ctx;
1173
1174         ctx = talloc_init("delparm");
1175
1176         if (argc != 2) {
1177                 net_conf_delparm_usage(argc, argv);
1178                 goto done;
1179         }
1180         service = strdup_lower(argv[0]);
1181         param = strdup_lower(argv[1]);
1182
1183         if (!smbconf_key_exists(ctx, service)) {
1184                 d_fprintf(stderr, 
1185                           "Error: given service '%s' does not exist.\n",
1186                           service);
1187                 goto done;
1188         }
1189
1190         werr = smbconf_open_path(ctx, service, REG_KEY_READ, &key);
1191         if (!W_ERROR_IS_OK(werr)) {
1192                 goto done;
1193         }
1194
1195         if (!smbconf_value_exists(ctx, key, param)) {
1196                 d_fprintf(stderr, 
1197                           "Error: given parameter '%s' is not set.\n",
1198                           param);
1199                 goto done;
1200         }
1201         werr = reg_deletevalue(key, param);
1202         if (!W_ERROR_IS_OK(werr)) {
1203                 d_fprintf(stderr, "Error deleting value '%s': %s.\n",
1204                           param, dos_errstr(werr));
1205                 goto done;
1206         }
1207
1208         ret = 0;
1209
1210 done:
1211         return ret;
1212 }
1213
1214 /*
1215  * Entry-point for all the CONF functions.
1216  */
1217
1218 int net_conf(int argc, const char **argv)
1219 {
1220         int ret = -1;
1221         struct functable2 func[] = {
1222                 {"list", net_conf_list, 
1223                  "Dump the complete configuration in smb.conf like format."},
1224                 {"import", net_conf_import,
1225                  "Import configuration from file in smb.conf format."},
1226                 {"listshares", net_conf_listshares, 
1227                  "List the registry shares."},
1228                 {"drop", net_conf_drop,
1229                  "Delete the complete configuration from registry."},
1230                 {"showshare", net_conf_showshare, 
1231                  "Show the definition of a registry share."},
1232                 {"addshare", net_conf_addshare, 
1233                  "Create a new registry share."},
1234                 {"delshare", net_conf_delshare, 
1235                  "Delete a registry share."},
1236                 {"setparm", net_conf_setparm, 
1237                  "Store a parameter."},
1238                 {"getparm", net_conf_getparm, 
1239                  "Retrieve the value of a parameter."},
1240                 {"delparm", net_conf_delparm, 
1241                  "Delete a parameter."},
1242                 {NULL, NULL, NULL}
1243         };
1244
1245         if (!registry_init_regdb()) {
1246                 d_fprintf(stderr, "Error initializing the registry!\n");
1247                 goto done;
1248         }
1249
1250         ret = net_run_function2(argc, argv, "net conf", func);
1251
1252         regdb_close();
1253
1254 done:
1255         return ret;
1256 }
1257
1258 /* END */