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