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