Line data Source code
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-2008
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 Samba's configuration as made available
23 : * by the libsmbconf interface (source/lib/smbconf/smbconf.c).
24 : *
25 : * This currently supports local interaction with the configuration
26 : * stored in the registry. But other backends and remote access via
27 : * rpc might get implemented in the future.
28 : */
29 :
30 : #include "includes.h"
31 : #include "system/filesys.h"
32 : #include "utils/net.h"
33 : #include "utils/net_conf_util.h"
34 : #include "lib/smbconf/smbconf.h"
35 : #include "lib/smbconf/smbconf_init.h"
36 : #include "lib/smbconf/smbconf_reg.h"
37 : #include "lib/param/loadparm.h"
38 :
39 : /**********************************************************************
40 : *
41 : * usage functions
42 : *
43 : **********************************************************************/
44 :
45 0 : static int net_conf_list_usage(struct net_context *c, int argc,
46 : const char **argv)
47 : {
48 0 : d_printf("%s net conf list\n", _("Usage:"));
49 0 : return -1;
50 : }
51 :
52 0 : static int net_conf_import_usage(struct net_context *c, int argc,
53 : const char**argv)
54 : {
55 0 : d_printf("%s\n%s",
56 : _("Usage:"),
57 : _(" net conf import [--test|-T] <filename> "
58 : "[<servicename>]\n"
59 : "\t[--test|-T] testmode - do not act, just print "
60 : "what would be done\n"
61 : "\t<servicename> only import service <servicename>, "
62 : "ignore the rest\n"));
63 0 : return -1;
64 : }
65 :
66 0 : static int net_conf_listshares_usage(struct net_context *c, int argc,
67 : const char **argv)
68 : {
69 0 : d_printf("%s\nnet conf listshares\n", _("Usage:"));
70 0 : return -1;
71 : }
72 :
73 0 : static int net_conf_drop_usage(struct net_context *c, int argc,
74 : const char **argv)
75 : {
76 0 : d_printf("%s\nnet conf drop\n", _("Usage:"));
77 0 : return -1;
78 : }
79 :
80 0 : static int net_conf_showshare_usage(struct net_context *c, int argc,
81 : const char **argv)
82 : {
83 0 : d_printf("%s\n%s",
84 : _("Usage:"),
85 : _("net conf showshare <sharename>\n"));
86 0 : return -1;
87 : }
88 :
89 0 : static int net_conf_addshare_usage(struct net_context *c, int argc,
90 : const char **argv)
91 : {
92 0 : d_printf("%s\n%s",
93 : _("Usage:"),
94 : _(" net conf addshare <sharename> <path> "
95 : "[writeable={y|N} [guest_ok={y|N} [<comment>]]]\n"
96 : "\t<sharename> the new share name.\n"
97 : "\t<path> the path on the filesystem to export.\n"
98 : "\twriteable={y|N} set \"writeable to \"yes\" or "
99 : "\"no\" (default) on this share.\n"
100 : "\tguest_ok={y|N} set \"guest ok\" to \"yes\" or "
101 : "\"no\" (default) on this share.\n"
102 : "\t<comment> optional comment for the new share.\n"));
103 0 : return -1;
104 : }
105 :
106 0 : static int net_conf_delshare_usage(struct net_context *c, int argc,
107 : const char **argv)
108 : {
109 0 : d_printf("%s\n%s",
110 : _("Usage:"),
111 : _("net conf delshare <sharename>\n"));
112 0 : return -1;
113 : }
114 :
115 0 : static int net_conf_setparm_usage(struct net_context *c, int argc,
116 : const char **argv)
117 : {
118 0 : d_printf("%s\n%s",
119 : _("Usage:"),
120 : _(" net conf setparm <section> <param> <value>\n"));
121 0 : return -1;
122 : }
123 :
124 0 : static int net_conf_getparm_usage(struct net_context *c, int argc,
125 : const char **argv)
126 : {
127 0 : d_printf("%s\n%s",
128 : _("Usage:"),
129 : _(" net conf getparm <section> <param>\n"));
130 0 : return -1;
131 : }
132 :
133 0 : static int net_conf_delparm_usage(struct net_context *c, int argc,
134 : const char **argv)
135 : {
136 0 : d_printf("%s\n%s",
137 : _("Usage:"),
138 : _(" net conf delparm <section> <param>\n"));
139 0 : return -1;
140 : }
141 :
142 0 : static int net_conf_getincludes_usage(struct net_context *c, int argc,
143 : const char **argv)
144 : {
145 0 : d_printf("%s\n%s",
146 : _("Usage:"),
147 : _(" net conf getincludes <section>\n"));
148 0 : return -1;
149 : }
150 :
151 0 : static int net_conf_setincludes_usage(struct net_context *c, int argc,
152 : const char **argv)
153 : {
154 0 : d_printf("%s\n%s",
155 : _("Usage:"),
156 : _(" net conf setincludes <section> [<filename>]*\n"));
157 0 : return -1;
158 : }
159 :
160 0 : static int net_conf_delincludes_usage(struct net_context *c, int argc,
161 : const char **argv)
162 : {
163 0 : d_printf("%s\n%s",
164 : _("Usage:"),
165 : _(" net conf delincludes <section>\n"));
166 0 : return -1;
167 : }
168 :
169 :
170 : /**********************************************************************
171 : *
172 : * Helper functions
173 : *
174 : **********************************************************************/
175 :
176 : /**
177 : * This functions process a service previously loaded with libsmbconf.
178 : */
179 0 : static sbcErr import_process_service(struct net_context *c,
180 : struct smbconf_ctx *conf_ctx,
181 : struct smbconf_service *service)
182 : {
183 0 : sbcErr err = SBC_ERR_OK;
184 :
185 0 : if (c->opt_testmode) {
186 : uint32_t idx;
187 0 : const char *indent = "";
188 0 : if (service->name != NULL) {
189 0 : d_printf("[%s]\n", service->name);
190 0 : indent = "\t";
191 : }
192 0 : for (idx = 0; idx < service->num_params; idx++) {
193 0 : d_printf("%s%s = %s\n", indent,
194 0 : service->param_names[idx],
195 0 : service->param_values[idx]);
196 : }
197 0 : d_printf("\n");
198 0 : goto done;
199 : }
200 :
201 0 : if (smbconf_share_exists(conf_ctx, service->name)) {
202 0 : err = smbconf_delete_share(conf_ctx, service->name);
203 0 : if (!SBC_ERROR_IS_OK(err)) {
204 0 : goto done;
205 : }
206 : }
207 :
208 0 : err = smbconf_create_set_share(conf_ctx, service);
209 :
210 0 : done:
211 0 : return err;
212 : }
213 :
214 :
215 : /**********************************************************************
216 : *
217 : * the main conf functions
218 : *
219 : **********************************************************************/
220 :
221 0 : static int net_conf_list(struct net_context *c, struct smbconf_ctx *conf_ctx,
222 : int argc, const char **argv)
223 : {
224 : sbcErr err;
225 0 : int ret = -1;
226 : TALLOC_CTX *mem_ctx;
227 : uint32_t num_shares;
228 : uint32_t share_count, param_count;
229 0 : struct smbconf_service **shares = NULL;
230 :
231 0 : mem_ctx = talloc_stackframe();
232 :
233 0 : if (argc != 0 || c->display_usage) {
234 0 : net_conf_list_usage(c, argc, argv);
235 0 : goto done;
236 : }
237 :
238 0 : err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &shares);
239 0 : if (!SBC_ERROR_IS_OK(err)) {
240 0 : d_fprintf(stderr, _("Error getting config: %s\n"),
241 : sbcErrorString(err));
242 0 : goto done;
243 : }
244 :
245 0 : for (share_count = 0; share_count < num_shares; share_count++) {
246 0 : const char *indent = "";
247 0 : if (shares[share_count]->name != NULL) {
248 0 : d_printf("[%s]\n", shares[share_count]->name);
249 0 : indent = "\t";
250 : }
251 0 : for (param_count = 0;
252 0 : param_count < shares[share_count]->num_params;
253 0 : param_count++)
254 : {
255 0 : d_printf("%s%s = %s\n",
256 : indent,
257 0 : shares[share_count]->param_names[param_count],
258 0 : shares[share_count]->param_values[param_count]);
259 : }
260 0 : d_printf("\n");
261 : }
262 :
263 0 : ret = 0;
264 :
265 0 : done:
266 0 : TALLOC_FREE(mem_ctx);
267 0 : return ret;
268 : }
269 :
270 0 : static int net_conf_import(struct net_context *c, struct smbconf_ctx *conf_ctx,
271 : int argc, const char **argv)
272 : {
273 0 : int ret = -1;
274 0 : const char *filename = NULL;
275 0 : const char *servicename = NULL;
276 0 : char *conf_source = NULL;
277 : TALLOC_CTX *mem_ctx;
278 : struct smbconf_ctx *txt_ctx;
279 : sbcErr err;
280 :
281 0 : if (c->display_usage)
282 0 : return net_conf_import_usage(c, argc, argv);
283 :
284 0 : mem_ctx = talloc_stackframe();
285 :
286 0 : switch (argc) {
287 0 : case 0:
288 : default:
289 0 : net_conf_import_usage(c, argc, argv);
290 0 : goto done;
291 0 : case 2:
292 0 : servicename = talloc_strdup(mem_ctx, argv[1]);
293 0 : if (servicename == NULL) {
294 0 : d_printf(_("error: out of memory!\n"));
295 0 : goto done;
296 : }
297 :
298 : FALL_THROUGH;
299 : case 1:
300 0 : filename = argv[0];
301 0 : break;
302 : }
303 :
304 0 : DEBUG(3,("net_conf_import: reading configuration from file %s.\n",
305 : filename));
306 :
307 0 : conf_source = talloc_asprintf(mem_ctx, "file:%s", filename);
308 0 : if (conf_source == NULL) {
309 0 : d_printf(_("error: out of memory!\n"));
310 0 : goto done;
311 : }
312 :
313 0 : err = smbconf_init(mem_ctx, &txt_ctx, conf_source);
314 0 : if (!SBC_ERROR_IS_OK(err)) {
315 0 : d_printf(_("error loading file '%s': %s\n"), filename,
316 : sbcErrorString(err));
317 0 : goto done;
318 : }
319 :
320 0 : if (c->opt_testmode) {
321 0 : d_printf(_("\nTEST MODE - "
322 : "would import the following configuration:\n\n"));
323 : }
324 :
325 0 : if (servicename != NULL) {
326 0 : struct smbconf_service *service = NULL;
327 :
328 0 : err = smbconf_get_share(txt_ctx, mem_ctx,
329 : servicename,
330 : &service);
331 0 : if (!SBC_ERROR_IS_OK(err)) {
332 0 : goto cancel;
333 : }
334 :
335 0 : err = smbconf_transaction_start(conf_ctx);
336 0 : if (!SBC_ERROR_IS_OK(err)) {
337 0 : d_printf(_("error starting transaction: %s\n"),
338 : sbcErrorString(err));
339 0 : goto done;
340 : }
341 :
342 0 : err = import_process_service(c, conf_ctx, service);
343 0 : if (!SBC_ERROR_IS_OK(err)) {
344 0 : d_printf(_("error importing service %s: %s\n"),
345 : servicename, sbcErrorString(err));
346 0 : goto cancel;
347 : }
348 : } else {
349 0 : struct smbconf_service **services = NULL;
350 : uint32_t num_shares, sidx;
351 :
352 0 : err = smbconf_get_config(txt_ctx, mem_ctx,
353 : &num_shares,
354 : &services);
355 0 : if (!SBC_ERROR_IS_OK(err)) {
356 0 : goto cancel;
357 : }
358 0 : if (!c->opt_testmode) {
359 0 : if (!SBC_ERROR_IS_OK(smbconf_drop(conf_ctx))) {
360 0 : goto cancel;
361 : }
362 : }
363 :
364 : /*
365 : * Wrap the importing of shares into a transaction,
366 : * but only 100 at a time, in order to save memory.
367 : * The allocated memory accumulates across the actions
368 : * within the transaction, and for me, some 1500
369 : * imported shares, the MAX_TALLOC_SIZE of 256 MB
370 : * was exceeded.
371 : */
372 0 : err = smbconf_transaction_start(conf_ctx);
373 0 : if (!SBC_ERROR_IS_OK(err)) {
374 0 : d_printf(_("error starting transaction: %s\n"),
375 : sbcErrorString(err));
376 0 : goto done;
377 : }
378 :
379 0 : for (sidx = 0; sidx < num_shares; sidx++) {
380 0 : err = import_process_service(c, conf_ctx,
381 0 : services[sidx]);
382 0 : if (!SBC_ERROR_IS_OK(err)) {
383 0 : d_printf(_("error importing service %s: %s\n"),
384 0 : services[sidx]->name,
385 : sbcErrorString(err));
386 0 : goto cancel;
387 : }
388 :
389 0 : if (sidx % 100) {
390 0 : continue;
391 : }
392 :
393 0 : err = smbconf_transaction_commit(conf_ctx);
394 0 : if (!SBC_ERROR_IS_OK(err)) {
395 0 : d_printf(_("error committing transaction: "
396 : "%s\n"),
397 : sbcErrorString(err));
398 0 : goto done;
399 : }
400 0 : err = smbconf_transaction_start(conf_ctx);
401 0 : if (!SBC_ERROR_IS_OK(err)) {
402 0 : d_printf(_("error starting transaction: %s\n"),
403 : sbcErrorString(err));
404 0 : goto done;
405 : }
406 : }
407 : }
408 :
409 0 : err = smbconf_transaction_commit(conf_ctx);
410 0 : if (!SBC_ERROR_IS_OK(err)) {
411 0 : d_printf(_("error committing transaction: %s\n"),
412 : sbcErrorString(err));
413 : } else {
414 0 : ret = 0;
415 : }
416 :
417 0 : goto done;
418 :
419 0 : cancel:
420 0 : err = smbconf_transaction_cancel(conf_ctx);
421 0 : if (!SBC_ERROR_IS_OK(err)) {
422 0 : d_printf(_("error cancelling transaction: %s\n"),
423 : sbcErrorString(err));
424 : }
425 :
426 0 : done:
427 0 : TALLOC_FREE(mem_ctx);
428 0 : return ret;
429 : }
430 :
431 0 : static int net_conf_listshares(struct net_context *c,
432 : struct smbconf_ctx *conf_ctx, int argc,
433 : const char **argv)
434 : {
435 : sbcErr err;
436 0 : int ret = -1;
437 0 : uint32_t count, num_shares = 0;
438 0 : char **share_names = NULL;
439 : TALLOC_CTX *mem_ctx;
440 :
441 0 : mem_ctx = talloc_stackframe();
442 :
443 0 : if (argc != 0 || c->display_usage) {
444 0 : net_conf_listshares_usage(c, argc, argv);
445 0 : goto done;
446 : }
447 :
448 0 : err = smbconf_get_share_names(conf_ctx, mem_ctx, &num_shares,
449 : &share_names);
450 0 : if (!SBC_ERROR_IS_OK(err)) {
451 0 : goto done;
452 : }
453 :
454 0 : for (count = 0; count < num_shares; count++)
455 : {
456 0 : d_printf("%s\n", share_names[count]);
457 : }
458 :
459 0 : ret = 0;
460 :
461 0 : done:
462 0 : TALLOC_FREE(mem_ctx);
463 0 : return ret;
464 : }
465 :
466 0 : static int net_conf_drop(struct net_context *c, struct smbconf_ctx *conf_ctx,
467 : int argc, const char **argv)
468 : {
469 0 : int ret = -1;
470 : sbcErr err;
471 :
472 0 : if (argc != 0 || c->display_usage) {
473 0 : net_conf_drop_usage(c, argc, argv);
474 0 : goto done;
475 : }
476 :
477 0 : err = smbconf_drop(conf_ctx);
478 0 : if (!SBC_ERROR_IS_OK(err)) {
479 0 : d_fprintf(stderr, _("Error deleting configuration: %s\n"),
480 : sbcErrorString(err));
481 0 : goto done;
482 : }
483 :
484 0 : ret = 0;
485 :
486 0 : done:
487 0 : return ret;
488 : }
489 :
490 0 : static int net_conf_showshare(struct net_context *c,
491 : struct smbconf_ctx *conf_ctx, int argc,
492 : const char **argv)
493 : {
494 0 : int ret = -1;
495 : sbcErr err;
496 0 : const char *sharename = NULL;
497 : TALLOC_CTX *mem_ctx;
498 : uint32_t count;
499 0 : struct smbconf_service *service = NULL;
500 :
501 0 : mem_ctx = talloc_stackframe();
502 :
503 0 : if (argc != 1 || c->display_usage) {
504 0 : net_conf_showshare_usage(c, argc, argv);
505 0 : goto done;
506 : }
507 :
508 0 : sharename = talloc_strdup(mem_ctx, argv[0]);
509 0 : if (sharename == NULL) {
510 0 : d_printf("error: out of memory!\n");
511 0 : goto done;
512 : }
513 :
514 0 : err = smbconf_get_share(conf_ctx, mem_ctx, sharename, &service);
515 0 : if (!SBC_ERROR_IS_OK(err)) {
516 0 : d_printf(_("error getting share parameters: %s\n"),
517 : sbcErrorString(err));
518 0 : goto done;
519 : }
520 :
521 0 : d_printf("[%s]\n", service->name);
522 :
523 0 : for (count = 0; count < service->num_params; count++) {
524 0 : d_printf("\t%s = %s\n", service->param_names[count],
525 0 : service->param_values[count]);
526 : }
527 :
528 0 : ret = 0;
529 :
530 0 : done:
531 0 : TALLOC_FREE(mem_ctx);
532 0 : return ret;
533 : }
534 :
535 : /**
536 : * Add a share, with a couple of standard parameters, partly optional.
537 : *
538 : * This is a high level utility function of the net conf utility,
539 : * not a direct frontend to the smbconf API.
540 : */
541 1 : static int net_conf_addshare(struct net_context *c,
542 : struct smbconf_ctx *conf_ctx, int argc,
543 : const char **argv)
544 : {
545 1 : int ret = -1;
546 : sbcErr err;
547 1 : char *sharename = NULL;
548 1 : const char *path = NULL;
549 1 : const char *comment = NULL;
550 1 : const char *guest_ok = "no";
551 1 : const char *writeable = "no";
552 1 : TALLOC_CTX *mem_ctx = talloc_stackframe();
553 :
554 1 : if (c->display_usage) {
555 0 : net_conf_addshare_usage(c, argc, argv);
556 0 : ret = 0;
557 0 : goto done;
558 : }
559 :
560 1 : switch (argc) {
561 0 : case 0:
562 : case 1:
563 : default:
564 0 : net_conf_addshare_usage(c, argc, argv);
565 0 : goto done;
566 1 : case 5:
567 1 : comment = argv[4];
568 :
569 : FALL_THROUGH;
570 1 : case 4:
571 1 : if (!strnequal(argv[3], "guest_ok=", 9)) {
572 0 : net_conf_addshare_usage(c, argc, argv);
573 0 : goto done;
574 : }
575 1 : switch (argv[3][9]) {
576 0 : case 'y':
577 : case 'Y':
578 0 : guest_ok = "yes";
579 0 : break;
580 1 : case 'n':
581 : case 'N':
582 1 : guest_ok = "no";
583 1 : break;
584 0 : default:
585 0 : net_conf_addshare_usage(c, argc, argv);
586 0 : goto done;
587 : }
588 :
589 1 : FALL_THROUGH;
590 : case 3:
591 1 : if (!strnequal(argv[2], "writeable=", 10)) {
592 0 : net_conf_addshare_usage(c, argc, argv);
593 0 : goto done;
594 : }
595 1 : switch (argv[2][10]) {
596 0 : case 'y':
597 : case 'Y':
598 0 : writeable = "yes";
599 0 : break;
600 1 : case 'n':
601 : case 'N':
602 1 : writeable = "no";
603 1 : break;
604 0 : default:
605 0 : net_conf_addshare_usage(c, argc, argv);
606 0 : goto done;
607 : }
608 :
609 1 : FALL_THROUGH;
610 : case 2:
611 1 : path = argv[1];
612 1 : sharename = talloc_strdup(mem_ctx, argv[0]);
613 1 : if (sharename == NULL) {
614 0 : d_printf(_("error: out of memory!\n"));
615 0 : goto done;
616 : }
617 :
618 1 : break;
619 : }
620 :
621 : /*
622 : * validate arguments
623 : */
624 :
625 : /* validate share name */
626 :
627 1 : if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS,
628 1 : strlen(sharename)))
629 : {
630 0 : d_fprintf(stderr, _("ERROR: share name %s contains "
631 : "invalid characters (any of %s)\n"),
632 : sharename, INVALID_SHARENAME_CHARS);
633 0 : goto done;
634 : }
635 :
636 1 : if (strequal(sharename, GLOBAL_NAME)) {
637 0 : d_fprintf(stderr,
638 0 : _("ERROR: 'global' is not a valid share name.\n"));
639 0 : goto done;
640 : }
641 :
642 1 : if (smbconf_share_exists(conf_ctx, sharename)) {
643 0 : d_fprintf(stderr, _("ERROR: share %s already exists.\n"),
644 : sharename);
645 0 : goto done;
646 : }
647 :
648 : /* validate path */
649 :
650 1 : if (path[0] != '/') {
651 0 : bool ok = false;
652 :
653 0 : if (strequal(sharename, HOMES_NAME) && path[0] == '\0') {
654 : /* The homes share can be an empty path. */
655 0 : ok = true;
656 : }
657 0 : if (!ok) {
658 0 : d_fprintf(stderr,
659 0 : _("Error: path '%s' is not an absolute path.\n"),
660 : path);
661 0 : goto done;
662 : }
663 : }
664 :
665 : /*
666 : * start a transaction
667 : */
668 :
669 1 : err = smbconf_transaction_start(conf_ctx);
670 1 : if (!SBC_ERROR_IS_OK(err)) {
671 0 : d_printf("error starting transaction: %s\n",
672 : sbcErrorString(err));
673 0 : goto done;
674 : }
675 :
676 : /*
677 : * create the share
678 : */
679 :
680 1 : err = smbconf_create_share(conf_ctx, sharename);
681 1 : if (!SBC_ERROR_IS_OK(err)) {
682 0 : d_fprintf(stderr, _("Error creating share %s: %s\n"),
683 : sharename, sbcErrorString(err));
684 0 : goto cancel;
685 : }
686 :
687 : /*
688 : * fill the share with parameters
689 : */
690 :
691 1 : err = smbconf_set_parameter(conf_ctx, sharename, "path", path);
692 1 : if (!SBC_ERROR_IS_OK(err)) {
693 0 : d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
694 : "path", sbcErrorString(err));
695 0 : goto cancel;
696 : }
697 :
698 1 : if (comment != NULL) {
699 1 : err = smbconf_set_parameter(conf_ctx, sharename, "comment",
700 : comment);
701 1 : if (!SBC_ERROR_IS_OK(err)) {
702 0 : d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
703 : "comment", sbcErrorString(err));
704 0 : goto cancel;
705 : }
706 : }
707 :
708 1 : err = smbconf_set_parameter(conf_ctx, sharename, "guest ok", guest_ok);
709 1 : if (!SBC_ERROR_IS_OK(err)) {
710 0 : d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
711 : "'guest ok'", sbcErrorString(err));
712 0 : goto cancel;
713 : }
714 :
715 1 : err = smbconf_set_parameter(conf_ctx, sharename, "writeable",
716 : writeable);
717 1 : if (!SBC_ERROR_IS_OK(err)) {
718 0 : d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
719 : "writeable", sbcErrorString(err));
720 0 : goto cancel;
721 : }
722 :
723 : /*
724 : * commit the whole thing
725 : */
726 :
727 1 : err = smbconf_transaction_commit(conf_ctx);
728 1 : if (!SBC_ERROR_IS_OK(err)) {
729 0 : d_printf("error committing transaction: %s\n",
730 : sbcErrorString(err));
731 : } else {
732 1 : ret = 0;
733 : }
734 :
735 1 : goto done;
736 :
737 0 : cancel:
738 0 : err = smbconf_transaction_cancel(conf_ctx);
739 0 : if (!SBC_ERROR_IS_OK(err)) {
740 0 : d_printf("error cancelling transaction: %s\n",
741 : sbcErrorString(err));
742 : }
743 :
744 1 : done:
745 1 : TALLOC_FREE(mem_ctx);
746 1 : return ret;
747 : }
748 :
749 1 : static int net_conf_delshare(struct net_context *c,
750 : struct smbconf_ctx *conf_ctx, int argc,
751 : const char **argv)
752 : {
753 1 : int ret = -1;
754 1 : const char *sharename = NULL;
755 : sbcErr err;
756 : NTSTATUS status;
757 1 : TALLOC_CTX *mem_ctx = talloc_stackframe();
758 :
759 1 : if (argc != 1 || c->display_usage) {
760 0 : net_conf_delshare_usage(c, argc, argv);
761 0 : goto done;
762 : }
763 1 : sharename = talloc_strdup(mem_ctx, argv[0]);
764 1 : if (sharename == NULL) {
765 0 : d_printf(_("error: out of memory!\n"));
766 0 : goto done;
767 : }
768 :
769 1 : err = smbconf_delete_share(conf_ctx, sharename);
770 1 : if (!SBC_ERROR_IS_OK(err)) {
771 0 : d_fprintf(stderr, _("Error deleting share %s: %s\n"),
772 : sharename, sbcErrorString(err));
773 0 : goto done;
774 : }
775 :
776 1 : status = delete_share_security(sharename);
777 2 : if (!NT_STATUS_IS_OK(status) &&
778 1 : !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
779 0 : d_fprintf(stderr, _("deleting share acl failed for %s: %s\n"),
780 : sharename, nt_errstr(status));
781 0 : goto done;
782 : }
783 :
784 1 : ret = 0;
785 1 : done:
786 1 : TALLOC_FREE(mem_ctx);
787 1 : return ret;
788 : }
789 :
790 5 : static int net_conf_setparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
791 : int argc, const char **argv)
792 : {
793 5 : int ret = -1;
794 : sbcErr err;
795 5 : char *service = NULL;
796 5 : char *param = NULL;
797 5 : const char *value_str = NULL;
798 5 : TALLOC_CTX *mem_ctx = talloc_stackframe();
799 :
800 5 : if (argc != 3 || c->display_usage) {
801 0 : net_conf_setparm_usage(c, argc, argv);
802 0 : goto done;
803 : }
804 : /*
805 : * NULL service name means "dangling parameters" to libsmbconf.
806 : * We use the empty string from the command line for this purpose.
807 : */
808 5 : if (strlen(argv[0]) != 0) {
809 5 : service = talloc_strdup(mem_ctx, argv[0]);
810 5 : if (service == NULL) {
811 0 : d_printf(_("error: out of memory!\n"));
812 0 : goto done;
813 : }
814 : }
815 5 : param = strlower_talloc(mem_ctx, argv[1]);
816 5 : if (param == NULL) {
817 0 : d_printf(_("error: out of memory!\n"));
818 0 : goto done;
819 : }
820 5 : value_str = argv[2];
821 :
822 5 : if (!net_conf_param_valid(service,param, value_str)) {
823 0 : goto done;
824 : }
825 :
826 5 : err = smbconf_transaction_start(conf_ctx);
827 5 : if (!SBC_ERROR_IS_OK(err)) {
828 0 : d_printf(_("error starting transaction: %s\n"),
829 : sbcErrorString(err));
830 0 : goto done;
831 : }
832 :
833 5 : if (!smbconf_share_exists(conf_ctx, service)) {
834 0 : err = smbconf_create_share(conf_ctx, service);
835 0 : if (!SBC_ERROR_IS_OK(err)) {
836 0 : d_fprintf(stderr, _("Error creating share '%s': %s\n"),
837 : service, sbcErrorString(err));
838 0 : goto cancel;
839 : }
840 : }
841 :
842 5 : err = smbconf_set_parameter(conf_ctx, service, param, value_str);
843 5 : if (!SBC_ERROR_IS_OK(err)) {
844 0 : d_fprintf(stderr, _("Error setting value '%s': %s\n"),
845 : param, sbcErrorString(err));
846 0 : goto cancel;
847 : }
848 :
849 5 : err = smbconf_transaction_commit(conf_ctx);
850 5 : if (!SBC_ERROR_IS_OK(err)) {
851 0 : d_printf(_("error committing transaction: %s\n"),
852 : sbcErrorString(err));
853 : } else {
854 5 : ret = 0;
855 : }
856 :
857 5 : goto done;
858 :
859 0 : cancel:
860 0 : err = smbconf_transaction_cancel(conf_ctx);
861 0 : if (!SBC_ERROR_IS_OK(err)) {
862 0 : d_printf(_("error cancelling transaction: %s\n"),
863 : sbcErrorString(err));
864 : }
865 :
866 5 : done:
867 5 : TALLOC_FREE(mem_ctx);
868 5 : return ret;
869 : }
870 :
871 0 : static int net_conf_getparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
872 : int argc, const char **argv)
873 : {
874 0 : int ret = -1;
875 : sbcErr err;
876 0 : char *service = NULL;
877 0 : char *param = NULL;
878 0 : char *valstr = NULL;
879 : TALLOC_CTX *mem_ctx;
880 :
881 0 : mem_ctx = talloc_stackframe();
882 :
883 0 : if (argc != 2 || c->display_usage) {
884 0 : net_conf_getparm_usage(c, argc, argv);
885 0 : goto done;
886 : }
887 : /*
888 : * NULL service name means "dangling parameters" to libsmbconf.
889 : * We use the empty string from the command line for this purpose.
890 : */
891 0 : if (strlen(argv[0]) != 0) {
892 0 : service = talloc_strdup(mem_ctx, argv[0]);
893 0 : if (service == NULL) {
894 0 : d_printf(_("error: out of memory!\n"));
895 0 : goto done;
896 : }
897 : }
898 0 : param = strlower_talloc(mem_ctx, argv[1]);
899 0 : if (param == NULL) {
900 0 : d_printf(_("error: out of memory!\n"));
901 0 : goto done;
902 : }
903 :
904 0 : err = smbconf_get_parameter(conf_ctx, mem_ctx, service, param, &valstr);
905 0 : if (SBC_ERROR_EQUAL(err, SBC_ERR_NO_SUCH_SERVICE)) {
906 0 : d_fprintf(stderr,
907 0 : _("Error: given service '%s' does not exist.\n"),
908 : service);
909 0 : goto done;
910 0 : } else if (SBC_ERROR_EQUAL(err, SBC_ERR_INVALID_PARAM)) {
911 0 : d_fprintf(stderr,
912 0 : _("Error: given parameter '%s' is not set.\n"),
913 : param);
914 0 : goto done;
915 0 : } else if (!SBC_ERROR_IS_OK(err)) {
916 0 : d_fprintf(stderr, _("Error getting value '%s': %s.\n"),
917 : param, sbcErrorString(err));
918 0 : goto done;
919 : }
920 :
921 0 : d_printf("%s\n", valstr);
922 :
923 0 : ret = 0;
924 0 : done:
925 0 : TALLOC_FREE(mem_ctx);
926 0 : return ret;
927 : }
928 :
929 0 : static int net_conf_delparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
930 : int argc, const char **argv)
931 : {
932 0 : int ret = -1;
933 : sbcErr err;
934 0 : char *service = NULL;
935 0 : char *param = NULL;
936 0 : TALLOC_CTX *mem_ctx = talloc_stackframe();
937 :
938 0 : if (argc != 2 || c->display_usage) {
939 0 : net_conf_delparm_usage(c, argc, argv);
940 0 : goto done;
941 : }
942 : /*
943 : * NULL service name means "dangling parameters" to libsmbconf.
944 : * We use the empty string from the command line for this purpose.
945 : */
946 0 : if (strlen(argv[0]) != 0) {
947 0 : service = talloc_strdup(mem_ctx, argv[0]);
948 0 : if (service == NULL) {
949 0 : d_printf(_("error: out of memory!\n"));
950 0 : goto done;
951 : }
952 : }
953 0 : param = strlower_talloc(mem_ctx, argv[1]);
954 0 : if (param == NULL) {
955 0 : d_printf("error: out of memory!\n");
956 0 : goto done;
957 : }
958 :
959 0 : err = smbconf_delete_parameter(conf_ctx, service, param);
960 0 : if (SBC_ERROR_EQUAL(err, SBC_ERR_NO_SUCH_SERVICE)) {
961 0 : d_fprintf(stderr,
962 0 : _("Error: given service '%s' does not exist.\n"),
963 : service);
964 0 : goto done;
965 0 : } else if (SBC_ERROR_EQUAL(err, SBC_ERR_INVALID_PARAM)) {
966 0 : d_fprintf(stderr,
967 0 : _("Error: given parameter '%s' is not set.\n"),
968 : param);
969 0 : goto done;
970 0 : } else if (!SBC_ERROR_IS_OK(err)) {
971 0 : d_fprintf(stderr, _("Error deleting value '%s': %s.\n"),
972 : param, sbcErrorString(err));
973 0 : goto done;
974 : }
975 :
976 0 : ret = 0;
977 :
978 0 : done:
979 0 : TALLOC_FREE(mem_ctx);
980 0 : return ret;
981 : }
982 :
983 0 : static int net_conf_getincludes(struct net_context *c,
984 : struct smbconf_ctx *conf_ctx,
985 : int argc, const char **argv)
986 : {
987 : sbcErr err;
988 : uint32_t num_includes;
989 : uint32_t count;
990 : char *service;
991 0 : char **includes = NULL;
992 0 : int ret = -1;
993 0 : TALLOC_CTX *mem_ctx = talloc_stackframe();
994 :
995 0 : if (argc != 1 || c->display_usage) {
996 0 : net_conf_getincludes_usage(c, argc, argv);
997 0 : goto done;
998 : }
999 :
1000 0 : service = talloc_strdup(mem_ctx, argv[0]);
1001 0 : if (service == NULL) {
1002 0 : d_printf(_("error: out of memory!\n"));
1003 0 : goto done;
1004 : }
1005 :
1006 0 : err = smbconf_get_includes(conf_ctx, mem_ctx, service,
1007 : &num_includes, &includes);
1008 0 : if (!SBC_ERROR_IS_OK(err)) {
1009 0 : d_printf(_("error getting includes: %s\n"), sbcErrorString(err));
1010 0 : goto done;
1011 : }
1012 :
1013 0 : for (count = 0; count < num_includes; count++) {
1014 0 : d_printf("include = %s\n", includes[count]);
1015 : }
1016 :
1017 0 : ret = 0;
1018 :
1019 0 : done:
1020 0 : TALLOC_FREE(mem_ctx);
1021 0 : return ret;
1022 : }
1023 :
1024 0 : static int net_conf_setincludes(struct net_context *c,
1025 : struct smbconf_ctx *conf_ctx,
1026 : int argc, const char **argv)
1027 : {
1028 : sbcErr err;
1029 : char *service;
1030 : uint32_t num_includes;
1031 : const char **includes;
1032 0 : int ret = -1;
1033 0 : TALLOC_CTX *mem_ctx = talloc_stackframe();
1034 :
1035 0 : if (argc < 1 || c->display_usage) {
1036 0 : net_conf_setincludes_usage(c, argc, argv);
1037 0 : goto done;
1038 : }
1039 :
1040 0 : service = talloc_strdup(mem_ctx, argv[0]);
1041 0 : if (service == NULL) {
1042 0 : d_printf(_("error: out of memory!\n"));
1043 0 : goto done;
1044 : }
1045 :
1046 0 : num_includes = argc - 1;
1047 0 : if (num_includes == 0) {
1048 0 : includes = NULL;
1049 : } else {
1050 0 : includes = argv + 1;
1051 : }
1052 :
1053 0 : err = smbconf_set_includes(conf_ctx, service, num_includes, includes);
1054 0 : if (!SBC_ERROR_IS_OK(err)) {
1055 0 : d_printf(_("error setting includes: %s\n"), sbcErrorString(err));
1056 0 : goto done;
1057 : }
1058 :
1059 0 : ret = 0;
1060 :
1061 0 : done:
1062 0 : TALLOC_FREE(mem_ctx);
1063 0 : return ret;
1064 : }
1065 :
1066 0 : static int net_conf_delincludes(struct net_context *c,
1067 : struct smbconf_ctx *conf_ctx,
1068 : int argc, const char **argv)
1069 : {
1070 : sbcErr err;
1071 : char *service;
1072 0 : int ret = -1;
1073 0 : TALLOC_CTX *mem_ctx = talloc_stackframe();
1074 :
1075 0 : if (argc != 1 || c->display_usage) {
1076 0 : net_conf_delincludes_usage(c, argc, argv);
1077 0 : goto done;
1078 : }
1079 :
1080 0 : service = talloc_strdup(mem_ctx, argv[0]);
1081 0 : if (service == NULL) {
1082 0 : d_printf(_("error: out of memory!\n"));
1083 0 : goto done;
1084 : }
1085 :
1086 0 : err = smbconf_delete_includes(conf_ctx, service);
1087 0 : if (!SBC_ERROR_IS_OK(err)) {
1088 0 : d_printf(_("error deleting includes: %s\n"), sbcErrorString(err));
1089 0 : goto done;
1090 : }
1091 :
1092 0 : ret = 0;
1093 :
1094 0 : done:
1095 0 : TALLOC_FREE(mem_ctx);
1096 0 : return ret;
1097 : }
1098 :
1099 :
1100 : /**********************************************************************
1101 : *
1102 : * Wrapper and net_conf_run_function mechanism.
1103 : *
1104 : **********************************************************************/
1105 :
1106 : /**
1107 : * Wrapper function to call the main conf functions.
1108 : * The wrapper calls handles opening and closing of the
1109 : * configuration.
1110 : */
1111 7 : static int net_conf_wrap_function(struct net_context *c,
1112 : int (*fn)(struct net_context *,
1113 : struct smbconf_ctx *,
1114 : int, const char **),
1115 : int argc, const char **argv)
1116 : {
1117 : sbcErr err;
1118 7 : TALLOC_CTX *mem_ctx = talloc_stackframe();
1119 : struct smbconf_ctx *conf_ctx;
1120 7 : int ret = -1;
1121 :
1122 7 : err = smbconf_init(mem_ctx, &conf_ctx, "registry:");
1123 7 : if (!SBC_ERROR_IS_OK(err)) {
1124 0 : talloc_free(mem_ctx);
1125 0 : return -1;
1126 : }
1127 :
1128 7 : ret = fn(c, conf_ctx, argc, argv);
1129 :
1130 7 : smbconf_shutdown(conf_ctx);
1131 :
1132 7 : talloc_free(mem_ctx);
1133 7 : return ret;
1134 : }
1135 :
1136 : /*
1137 : * We need a functable struct of our own, because the
1138 : * functions are called through a wrapper that handles
1139 : * the opening and closing of the configuration, and so on.
1140 : */
1141 : struct conf_functable {
1142 : const char *funcname;
1143 : int (*fn)(struct net_context *c, struct smbconf_ctx *ctx, int argc,
1144 : const char **argv);
1145 : int valid_transports;
1146 : const char *description;
1147 : const char *usage;
1148 : };
1149 :
1150 : /**
1151 : * This imitates net_run_function but calls the main functions
1152 : * through the wrapper net_conf_wrap_function().
1153 : */
1154 7 : static int net_conf_run_function(struct net_context *c, int argc,
1155 : const char **argv, const char *whoami,
1156 : struct conf_functable *table)
1157 : {
1158 : int i;
1159 :
1160 7 : if (argc != 0) {
1161 53 : for (i=0; table[i].funcname; i++) {
1162 53 : if (strcasecmp_m(argv[0], table[i].funcname) == 0)
1163 7 : return net_conf_wrap_function(c, table[i].fn,
1164 : argc-1,
1165 : argv+1);
1166 : }
1167 : }
1168 :
1169 0 : d_printf(_("Usage:\n"));
1170 0 : for (i=0; table[i].funcname; i++) {
1171 0 : if (c->display_usage == false)
1172 0 : d_printf("%s %-15s %s\n", whoami, table[i].funcname,
1173 0 : table[i].description);
1174 : else
1175 0 : d_printf("%s\n", table[i].usage);
1176 : }
1177 :
1178 0 : return c->display_usage?0:-1;
1179 : }
1180 :
1181 : /*
1182 : * Entry-point for all the CONF functions.
1183 : */
1184 :
1185 7 : int net_conf(struct net_context *c, int argc, const char **argv)
1186 : {
1187 7 : int ret = -1;
1188 7 : struct conf_functable func_table[] = {
1189 : {
1190 : "list",
1191 : net_conf_list,
1192 : NET_TRANSPORT_LOCAL,
1193 : N_("Dump the complete configuration in smb.conf like "
1194 : "format."),
1195 : N_("net conf list\n"
1196 : " Dump the complete configuration in smb.conf "
1197 : "like format.")
1198 :
1199 : },
1200 : {
1201 : "import",
1202 : net_conf_import,
1203 : NET_TRANSPORT_LOCAL,
1204 : N_("Import configuration from file in smb.conf "
1205 : "format."),
1206 : N_("net conf import\n"
1207 : " Import configuration from file in smb.conf "
1208 : "format.")
1209 : },
1210 : {
1211 : "listshares",
1212 : net_conf_listshares,
1213 : NET_TRANSPORT_LOCAL,
1214 : N_("List the share names."),
1215 : N_("net conf listshares\n"
1216 : " List the share names.")
1217 : },
1218 : {
1219 : "drop",
1220 : net_conf_drop,
1221 : NET_TRANSPORT_LOCAL,
1222 : N_("Delete the complete configuration."),
1223 : N_("net conf drop\n"
1224 : " Delete the complete configuration.")
1225 : },
1226 : {
1227 : "showshare",
1228 : net_conf_showshare,
1229 : NET_TRANSPORT_LOCAL,
1230 : N_("Show the definition of a share."),
1231 : N_("net conf showshare\n"
1232 : " Show the definition of a share.")
1233 : },
1234 : {
1235 : "addshare",
1236 : net_conf_addshare,
1237 : NET_TRANSPORT_LOCAL,
1238 : N_("Create a new share."),
1239 : N_("net conf addshare\n"
1240 : " Create a new share.")
1241 : },
1242 : {
1243 : "delshare",
1244 : net_conf_delshare,
1245 : NET_TRANSPORT_LOCAL,
1246 : N_("Delete a share."),
1247 : N_("net conf delshare\n"
1248 : " Delete a share.")
1249 : },
1250 : {
1251 : "setparm",
1252 : net_conf_setparm,
1253 : NET_TRANSPORT_LOCAL,
1254 : N_("Store a parameter."),
1255 : N_("net conf setparm\n"
1256 : " Store a parameter.")
1257 : },
1258 : {
1259 : "getparm",
1260 : net_conf_getparm,
1261 : NET_TRANSPORT_LOCAL,
1262 : N_("Retrieve the value of a parameter."),
1263 : N_("net conf getparm\n"
1264 : " Retrieve the value of a parameter.")
1265 : },
1266 : {
1267 : "delparm",
1268 : net_conf_delparm,
1269 : NET_TRANSPORT_LOCAL,
1270 : N_("Delete a parameter."),
1271 : N_("net conf delparm\n"
1272 : " Delete a parameter.")
1273 : },
1274 : {
1275 : "getincludes",
1276 : net_conf_getincludes,
1277 : NET_TRANSPORT_LOCAL,
1278 : N_("Show the includes of a share definition."),
1279 : N_("net conf getincludes\n"
1280 : " Show the includes of a share definition.")
1281 : },
1282 : {
1283 : "setincludes",
1284 : net_conf_setincludes,
1285 : NET_TRANSPORT_LOCAL,
1286 : N_("Set includes for a share."),
1287 : N_("net conf setincludes\n"
1288 : " Set includes for a share.")
1289 : },
1290 : {
1291 : "delincludes",
1292 : net_conf_delincludes,
1293 : NET_TRANSPORT_LOCAL,
1294 : N_("Delete includes from a share definition."),
1295 : N_("net conf delincludes\n"
1296 : " Delete includes from a share definition.")
1297 : },
1298 : {NULL, NULL, 0, NULL, NULL}
1299 : };
1300 :
1301 7 : ret = net_conf_run_function(c, argc, argv, "net conf", func_table);
1302 :
1303 7 : return ret;
1304 : }
1305 :
|