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 2 : static int net_conf_import_usage(struct net_context *c, int argc,
53 : const char**argv)
54 : {
55 2 : 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 2 : 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 2 : static int net_conf_drop_usage(struct net_context *c, int argc,
74 : const char **argv)
75 : {
76 2 : d_printf("%s\nnet conf drop\n", _("Usage:"));
77 2 : 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 2 : static int net_conf_addshare_usage(struct net_context *c, int argc,
90 : const char **argv)
91 : {
92 2 : 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 2 : return -1;
104 : }
105 :
106 2 : static int net_conf_delshare_usage(struct net_context *c, int argc,
107 : const char **argv)
108 : {
109 2 : d_printf("%s\n%s",
110 : _("Usage:"),
111 : _("net conf delshare <sharename>\n"));
112 2 : return -1;
113 : }
114 :
115 2 : static int net_conf_setparm_usage(struct net_context *c, int argc,
116 : const char **argv)
117 : {
118 2 : d_printf("%s\n%s",
119 : _("Usage:"),
120 : _(" net conf setparm <section> <param> <value>\n"));
121 2 : return -1;
122 : }
123 :
124 2 : static int net_conf_getparm_usage(struct net_context *c, int argc,
125 : const char **argv)
126 : {
127 2 : d_printf("%s\n%s",
128 : _("Usage:"),
129 : _(" net conf getparm <section> <param>\n"));
130 2 : return -1;
131 : }
132 :
133 2 : static int net_conf_delparm_usage(struct net_context *c, int argc,
134 : const char **argv)
135 : {
136 2 : d_printf("%s\n%s",
137 : _("Usage:"),
138 : _(" net conf delparm <section> <param>\n"));
139 2 : return -1;
140 : }
141 :
142 2 : static int net_conf_getincludes_usage(struct net_context *c, int argc,
143 : const char **argv)
144 : {
145 2 : d_printf("%s\n%s",
146 : _("Usage:"),
147 : _(" net conf getincludes <section>\n"));
148 2 : return -1;
149 : }
150 :
151 2 : static int net_conf_setincludes_usage(struct net_context *c, int argc,
152 : const char **argv)
153 : {
154 2 : d_printf("%s\n%s",
155 : _("Usage:"),
156 : _(" net conf setincludes <section> [<filename>]*\n"));
157 2 : return -1;
158 : }
159 :
160 2 : static int net_conf_delincludes_usage(struct net_context *c, int argc,
161 : const char **argv)
162 : {
163 2 : d_printf("%s\n%s",
164 : _("Usage:"),
165 : _(" net conf delincludes <section>\n"));
166 2 : 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 418 : static sbcErr import_process_service(struct net_context *c,
180 : struct smbconf_ctx *conf_ctx,
181 : struct smbconf_service *service)
182 : {
183 418 : sbcErr err = SBC_ERR_OK;
184 :
185 418 : if (c->opt_testmode) {
186 0 : 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 418 : 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 418 : err = smbconf_create_set_share(conf_ctx, service);
209 :
210 418 : done:
211 418 : return err;
212 : }
213 :
214 :
215 : /**********************************************************************
216 : *
217 : * the main conf functions
218 : *
219 : **********************************************************************/
220 :
221 20 : static int net_conf_list(struct net_context *c, struct smbconf_ctx *conf_ctx,
222 : int argc, const char **argv)
223 : {
224 0 : sbcErr err;
225 20 : int ret = -1;
226 0 : TALLOC_CTX *mem_ctx;
227 0 : uint32_t num_shares;
228 0 : uint32_t share_count, param_count;
229 20 : struct smbconf_service **shares = NULL;
230 :
231 20 : mem_ctx = talloc_stackframe();
232 :
233 20 : if (argc != 0 || c->display_usage) {
234 0 : net_conf_list_usage(c, argc, argv);
235 0 : goto done;
236 : }
237 :
238 20 : err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &shares);
239 20 : 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 860 : for (share_count = 0; share_count < num_shares; share_count++) {
246 840 : const char *indent = "";
247 840 : if (shares[share_count]->name != NULL) {
248 840 : d_printf("[%s]\n", shares[share_count]->name);
249 840 : indent = "\t";
250 : }
251 840 : for (param_count = 0;
252 4630 : param_count < shares[share_count]->num_params;
253 3790 : param_count++)
254 : {
255 3790 : d_printf("%s%s = %s\n",
256 : indent,
257 3790 : shares[share_count]->param_names[param_count],
258 3790 : shares[share_count]->param_values[param_count]);
259 : }
260 840 : d_printf("\n");
261 : }
262 :
263 20 : ret = 0;
264 :
265 20 : done:
266 20 : TALLOC_FREE(mem_ctx);
267 20 : return ret;
268 : }
269 :
270 6 : static int net_conf_import(struct net_context *c, struct smbconf_ctx *conf_ctx,
271 : int argc, const char **argv)
272 : {
273 6 : int ret = -1;
274 6 : const char *filename = NULL;
275 6 : const char *servicename = NULL;
276 6 : char *conf_source = NULL;
277 0 : TALLOC_CTX *mem_ctx;
278 0 : struct smbconf_ctx *txt_ctx;
279 0 : sbcErr err;
280 :
281 6 : if (c->display_usage)
282 0 : return net_conf_import_usage(c, argc, argv);
283 :
284 6 : mem_ctx = talloc_stackframe();
285 :
286 6 : switch (argc) {
287 2 : case 0:
288 : default:
289 2 : net_conf_import_usage(c, argc, argv);
290 2 : 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 0 : FALL_THROUGH;
299 : case 1:
300 4 : filename = argv[0];
301 4 : break;
302 : }
303 :
304 4 : DEBUG(3,("net_conf_import: reading configuration from file %s.\n",
305 : filename));
306 :
307 4 : conf_source = talloc_asprintf(mem_ctx, "file:%s", filename);
308 4 : if (conf_source == NULL) {
309 0 : d_printf(_("error: out of memory!\n"));
310 0 : goto done;
311 : }
312 :
313 4 : err = smbconf_init(mem_ctx, &txt_ctx, conf_source);
314 4 : 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 4 : if (c->opt_testmode) {
321 0 : d_printf(_("\nTEST MODE - "
322 : "would import the following configuration:\n\n"));
323 : }
324 :
325 4 : 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 4 : struct smbconf_service **services = NULL;
350 0 : uint32_t num_shares, sidx;
351 :
352 4 : err = smbconf_get_config(txt_ctx, mem_ctx,
353 : &num_shares,
354 : &services);
355 4 : if (!SBC_ERROR_IS_OK(err)) {
356 0 : goto cancel;
357 : }
358 4 : if (!c->opt_testmode) {
359 4 : 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 4 : err = smbconf_transaction_start(conf_ctx);
373 4 : 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 422 : for (sidx = 0; sidx < num_shares; sidx++) {
380 418 : err = import_process_service(c, conf_ctx,
381 418 : services[sidx]);
382 418 : 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 418 : if (sidx % 100) {
390 412 : continue;
391 : }
392 :
393 6 : err = smbconf_transaction_commit(conf_ctx);
394 6 : 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 6 : err = smbconf_transaction_start(conf_ctx);
401 6 : 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 4 : err = smbconf_transaction_commit(conf_ctx);
410 4 : if (!SBC_ERROR_IS_OK(err)) {
411 0 : d_printf(_("error committing transaction: %s\n"),
412 : sbcErrorString(err));
413 : } else {
414 4 : ret = 0;
415 : }
416 :
417 4 : 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 6 : TALLOC_FREE(mem_ctx);
428 6 : return ret;
429 : }
430 :
431 4 : static int net_conf_listshares(struct net_context *c,
432 : struct smbconf_ctx *conf_ctx, int argc,
433 : const char **argv)
434 : {
435 0 : sbcErr err;
436 4 : int ret = -1;
437 4 : uint32_t count, num_shares = 0;
438 4 : char **share_names = NULL;
439 0 : TALLOC_CTX *mem_ctx;
440 :
441 4 : mem_ctx = talloc_stackframe();
442 :
443 4 : if (argc != 0 || c->display_usage) {
444 0 : net_conf_listshares_usage(c, argc, argv);
445 0 : goto done;
446 : }
447 :
448 4 : err = smbconf_get_share_names(conf_ctx, mem_ctx, &num_shares,
449 : &share_names);
450 4 : if (!SBC_ERROR_IS_OK(err)) {
451 0 : goto done;
452 : }
453 :
454 402 : for (count = 0; count < num_shares; count++)
455 : {
456 398 : d_printf("%s\n", share_names[count]);
457 : }
458 :
459 4 : ret = 0;
460 :
461 4 : done:
462 4 : TALLOC_FREE(mem_ctx);
463 4 : return ret;
464 : }
465 :
466 28 : static int net_conf_drop(struct net_context *c, struct smbconf_ctx *conf_ctx,
467 : int argc, const char **argv)
468 : {
469 28 : int ret = -1;
470 0 : sbcErr err;
471 :
472 28 : if (argc != 0 || c->display_usage) {
473 2 : net_conf_drop_usage(c, argc, argv);
474 2 : goto done;
475 : }
476 :
477 26 : err = smbconf_drop(conf_ctx);
478 26 : 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 26 : ret = 0;
485 :
486 28 : done:
487 28 : return ret;
488 : }
489 :
490 212 : static int net_conf_showshare(struct net_context *c,
491 : struct smbconf_ctx *conf_ctx, int argc,
492 : const char **argv)
493 : {
494 212 : int ret = -1;
495 0 : sbcErr err;
496 212 : const char *sharename = NULL;
497 0 : TALLOC_CTX *mem_ctx;
498 0 : uint32_t count;
499 212 : struct smbconf_service *service = NULL;
500 :
501 212 : mem_ctx = talloc_stackframe();
502 :
503 212 : if (argc != 1 || c->display_usage) {
504 0 : net_conf_showshare_usage(c, argc, argv);
505 0 : goto done;
506 : }
507 :
508 212 : sharename = talloc_strdup(mem_ctx, argv[0]);
509 212 : if (sharename == NULL) {
510 0 : d_printf("error: out of memory!\n");
511 0 : goto done;
512 : }
513 :
514 212 : err = smbconf_get_share(conf_ctx, mem_ctx, sharename, &service);
515 212 : 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 212 : d_printf("[%s]\n", service->name);
522 :
523 1042 : for (count = 0; count < service->num_params; count++) {
524 830 : d_printf("\t%s = %s\n", service->param_names[count],
525 830 : service->param_values[count]);
526 : }
527 :
528 212 : ret = 0;
529 :
530 212 : done:
531 212 : TALLOC_FREE(mem_ctx);
532 212 : 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 221 : static int net_conf_addshare(struct net_context *c,
542 : struct smbconf_ctx *conf_ctx, int argc,
543 : const char **argv)
544 : {
545 221 : int ret = -1;
546 0 : sbcErr err;
547 221 : char *sharename = NULL;
548 221 : const char *path = NULL;
549 221 : const char *comment = NULL;
550 221 : const char *guest_ok = "no";
551 221 : const char *writeable = "no";
552 221 : TALLOC_CTX *mem_ctx = talloc_stackframe();
553 :
554 221 : if (c->display_usage) {
555 0 : net_conf_addshare_usage(c, argc, argv);
556 0 : ret = 0;
557 0 : goto done;
558 : }
559 :
560 221 : switch (argc) {
561 2 : case 0:
562 : case 1:
563 : default:
564 2 : net_conf_addshare_usage(c, argc, argv);
565 2 : goto done;
566 209 : case 5:
567 209 : comment = argv[4];
568 :
569 0 : FALL_THROUGH;
570 209 : case 4:
571 209 : if (!strnequal(argv[3], "guest_ok=", 9)) {
572 0 : net_conf_addshare_usage(c, argc, argv);
573 0 : goto done;
574 : }
575 209 : switch (argv[3][9]) {
576 102 : case 'y':
577 : case 'Y':
578 102 : guest_ok = "yes";
579 102 : break;
580 107 : case 'n':
581 : case 'N':
582 107 : guest_ok = "no";
583 107 : break;
584 0 : default:
585 0 : net_conf_addshare_usage(c, argc, argv);
586 0 : goto done;
587 : }
588 :
589 0 : FALL_THROUGH;
590 : case 3:
591 209 : if (!strnequal(argv[2], "writeable=", 10)) {
592 0 : net_conf_addshare_usage(c, argc, argv);
593 0 : goto done;
594 : }
595 209 : switch (argv[2][10]) {
596 102 : case 'y':
597 : case 'Y':
598 102 : writeable = "yes";
599 102 : break;
600 107 : case 'n':
601 : case 'N':
602 107 : writeable = "no";
603 107 : break;
604 0 : default:
605 0 : net_conf_addshare_usage(c, argc, argv);
606 0 : goto done;
607 : }
608 :
609 0 : FALL_THROUGH;
610 : case 2:
611 219 : path = argv[1];
612 219 : sharename = talloc_strdup(mem_ctx, argv[0]);
613 219 : if (sharename == NULL) {
614 0 : d_printf(_("error: out of memory!\n"));
615 0 : goto done;
616 : }
617 :
618 219 : break;
619 : }
620 :
621 : /*
622 : * validate arguments
623 : */
624 :
625 : /* validate share name */
626 :
627 219 : if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS,
628 219 : 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 219 : 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 219 : if (smbconf_share_exists(conf_ctx, sharename)) {
643 2 : d_fprintf(stderr, _("ERROR: share %s already exists.\n"),
644 : sharename);
645 2 : goto done;
646 : }
647 :
648 : /* validate path */
649 :
650 217 : 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 217 : err = smbconf_transaction_start(conf_ctx);
670 217 : 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 217 : err = smbconf_create_share(conf_ctx, sharename);
681 217 : 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 217 : err = smbconf_set_parameter(conf_ctx, sharename, "path", path);
692 217 : 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 217 : if (comment != NULL) {
699 207 : err = smbconf_set_parameter(conf_ctx, sharename, "comment",
700 : comment);
701 207 : 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 217 : err = smbconf_set_parameter(conf_ctx, sharename, "guest ok", guest_ok);
709 217 : 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 217 : err = smbconf_set_parameter(conf_ctx, sharename, "writeable",
716 : writeable);
717 217 : 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 217 : err = smbconf_transaction_commit(conf_ctx);
728 217 : if (!SBC_ERROR_IS_OK(err)) {
729 0 : d_printf("error committing transaction: %s\n",
730 : sbcErrorString(err));
731 : } else {
732 217 : ret = 0;
733 : }
734 :
735 217 : 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 0 : done:
745 221 : TALLOC_FREE(mem_ctx);
746 221 : return ret;
747 : }
748 :
749 11 : static int net_conf_delshare(struct net_context *c,
750 : struct smbconf_ctx *conf_ctx, int argc,
751 : const char **argv)
752 : {
753 11 : int ret = -1;
754 11 : const char *sharename = NULL;
755 0 : sbcErr err;
756 0 : NTSTATUS status;
757 11 : TALLOC_CTX *mem_ctx = talloc_stackframe();
758 :
759 11 : if (argc != 1 || c->display_usage) {
760 2 : net_conf_delshare_usage(c, argc, argv);
761 2 : goto done;
762 : }
763 9 : sharename = talloc_strdup(mem_ctx, argv[0]);
764 9 : if (sharename == NULL) {
765 0 : d_printf(_("error: out of memory!\n"));
766 0 : goto done;
767 : }
768 :
769 9 : err = smbconf_delete_share(conf_ctx, sharename);
770 9 : if (!SBC_ERROR_IS_OK(err)) {
771 2 : d_fprintf(stderr, _("Error deleting share %s: %s\n"),
772 : sharename, sbcErrorString(err));
773 2 : goto done;
774 : }
775 :
776 7 : status = delete_share_security(sharename);
777 7 : if (!NT_STATUS_IS_OK(status) &&
778 5 : !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 7 : ret = 0;
785 11 : done:
786 11 : TALLOC_FREE(mem_ctx);
787 11 : return ret;
788 : }
789 :
790 37 : static int net_conf_setparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
791 : int argc, const char **argv)
792 : {
793 37 : int ret = -1;
794 0 : sbcErr err;
795 37 : char *service = NULL;
796 37 : char *param = NULL;
797 37 : const char *value_str = NULL;
798 37 : TALLOC_CTX *mem_ctx = talloc_stackframe();
799 :
800 37 : if (argc != 3 || c->display_usage) {
801 2 : net_conf_setparm_usage(c, argc, argv);
802 2 : 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 35 : if (strlen(argv[0]) != 0) {
809 35 : service = talloc_strdup(mem_ctx, argv[0]);
810 35 : if (service == NULL) {
811 0 : d_printf(_("error: out of memory!\n"));
812 0 : goto done;
813 : }
814 : }
815 35 : param = strlower_talloc(mem_ctx, argv[1]);
816 35 : if (param == NULL) {
817 0 : d_printf(_("error: out of memory!\n"));
818 0 : goto done;
819 : }
820 35 : value_str = argv[2];
821 :
822 35 : if (!net_conf_param_valid(service,param, value_str)) {
823 10 : goto done;
824 : }
825 :
826 25 : err = smbconf_transaction_start(conf_ctx);
827 25 : 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 25 : if (!smbconf_share_exists(conf_ctx, service)) {
834 2 : err = smbconf_create_share(conf_ctx, service);
835 2 : 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 25 : err = smbconf_set_parameter(conf_ctx, service, param, value_str);
843 25 : 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 25 : err = smbconf_transaction_commit(conf_ctx);
850 25 : if (!SBC_ERROR_IS_OK(err)) {
851 0 : d_printf(_("error committing transaction: %s\n"),
852 : sbcErrorString(err));
853 : } else {
854 25 : ret = 0;
855 : }
856 :
857 25 : 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 0 : done:
867 37 : TALLOC_FREE(mem_ctx);
868 37 : return ret;
869 : }
870 :
871 8 : static int net_conf_getparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
872 : int argc, const char **argv)
873 : {
874 8 : int ret = -1;
875 0 : sbcErr err;
876 8 : char *service = NULL;
877 8 : char *param = NULL;
878 8 : char *valstr = NULL;
879 0 : TALLOC_CTX *mem_ctx;
880 :
881 8 : mem_ctx = talloc_stackframe();
882 :
883 8 : if (argc != 2 || c->display_usage) {
884 2 : net_conf_getparm_usage(c, argc, argv);
885 2 : 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 6 : if (strlen(argv[0]) != 0) {
892 6 : service = talloc_strdup(mem_ctx, argv[0]);
893 6 : if (service == NULL) {
894 0 : d_printf(_("error: out of memory!\n"));
895 0 : goto done;
896 : }
897 : }
898 6 : param = strlower_talloc(mem_ctx, argv[1]);
899 6 : if (param == NULL) {
900 0 : d_printf(_("error: out of memory!\n"));
901 0 : goto done;
902 : }
903 :
904 6 : err = smbconf_get_parameter(conf_ctx, mem_ctx, service, param, &valstr);
905 6 : 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 6 : } 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 6 : } 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 6 : d_printf("%s\n", valstr);
922 :
923 6 : ret = 0;
924 8 : done:
925 8 : TALLOC_FREE(mem_ctx);
926 8 : return ret;
927 : }
928 :
929 6 : static int net_conf_delparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
930 : int argc, const char **argv)
931 : {
932 6 : int ret = -1;
933 0 : sbcErr err;
934 6 : char *service = NULL;
935 6 : char *param = NULL;
936 6 : TALLOC_CTX *mem_ctx = talloc_stackframe();
937 :
938 6 : if (argc != 2 || c->display_usage) {
939 2 : net_conf_delparm_usage(c, argc, argv);
940 2 : 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 4 : if (strlen(argv[0]) != 0) {
947 4 : service = talloc_strdup(mem_ctx, argv[0]);
948 4 : if (service == NULL) {
949 0 : d_printf(_("error: out of memory!\n"));
950 0 : goto done;
951 : }
952 : }
953 4 : param = strlower_talloc(mem_ctx, argv[1]);
954 4 : if (param == NULL) {
955 0 : d_printf("error: out of memory!\n");
956 0 : goto done;
957 : }
958 :
959 4 : err = smbconf_delete_parameter(conf_ctx, service, param);
960 4 : if (SBC_ERROR_EQUAL(err, SBC_ERR_NO_SUCH_SERVICE)) {
961 2 : d_fprintf(stderr,
962 2 : _("Error: given service '%s' does not exist.\n"),
963 : service);
964 2 : goto done;
965 2 : } 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 2 : } 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 2 : ret = 0;
977 :
978 6 : done:
979 6 : TALLOC_FREE(mem_ctx);
980 6 : return ret;
981 : }
982 :
983 4 : static int net_conf_getincludes(struct net_context *c,
984 : struct smbconf_ctx *conf_ctx,
985 : int argc, const char **argv)
986 : {
987 0 : sbcErr err;
988 0 : uint32_t num_includes;
989 0 : uint32_t count;
990 0 : char *service;
991 4 : char **includes = NULL;
992 4 : int ret = -1;
993 4 : TALLOC_CTX *mem_ctx = talloc_stackframe();
994 :
995 4 : if (argc != 1 || c->display_usage) {
996 2 : net_conf_getincludes_usage(c, argc, argv);
997 2 : goto done;
998 : }
999 :
1000 2 : service = talloc_strdup(mem_ctx, argv[0]);
1001 2 : if (service == NULL) {
1002 0 : d_printf(_("error: out of memory!\n"));
1003 0 : goto done;
1004 : }
1005 :
1006 2 : err = smbconf_get_includes(conf_ctx, mem_ctx, service,
1007 : &num_includes, &includes);
1008 2 : if (!SBC_ERROR_IS_OK(err)) {
1009 0 : d_printf(_("error getting includes: %s\n"), sbcErrorString(err));
1010 0 : goto done;
1011 : }
1012 :
1013 8 : for (count = 0; count < num_includes; count++) {
1014 6 : d_printf("include = %s\n", includes[count]);
1015 : }
1016 :
1017 2 : ret = 0;
1018 :
1019 4 : done:
1020 4 : TALLOC_FREE(mem_ctx);
1021 4 : return ret;
1022 : }
1023 :
1024 4 : static int net_conf_setincludes(struct net_context *c,
1025 : struct smbconf_ctx *conf_ctx,
1026 : int argc, const char **argv)
1027 : {
1028 0 : sbcErr err;
1029 0 : char *service;
1030 0 : uint32_t num_includes;
1031 0 : const char **includes;
1032 4 : int ret = -1;
1033 4 : TALLOC_CTX *mem_ctx = talloc_stackframe();
1034 :
1035 4 : if (argc < 1 || c->display_usage) {
1036 2 : net_conf_setincludes_usage(c, argc, argv);
1037 2 : goto done;
1038 : }
1039 :
1040 2 : service = talloc_strdup(mem_ctx, argv[0]);
1041 2 : if (service == NULL) {
1042 0 : d_printf(_("error: out of memory!\n"));
1043 0 : goto done;
1044 : }
1045 :
1046 2 : num_includes = argc - 1;
1047 2 : if (num_includes == 0) {
1048 0 : includes = NULL;
1049 : } else {
1050 2 : includes = argv + 1;
1051 : }
1052 :
1053 2 : err = smbconf_set_includes(conf_ctx, service, num_includes, includes);
1054 2 : if (!SBC_ERROR_IS_OK(err)) {
1055 0 : d_printf(_("error setting includes: %s\n"), sbcErrorString(err));
1056 0 : goto done;
1057 : }
1058 :
1059 2 : ret = 0;
1060 :
1061 4 : done:
1062 4 : TALLOC_FREE(mem_ctx);
1063 4 : return ret;
1064 : }
1065 :
1066 8 : static int net_conf_delincludes(struct net_context *c,
1067 : struct smbconf_ctx *conf_ctx,
1068 : int argc, const char **argv)
1069 : {
1070 0 : sbcErr err;
1071 0 : char *service;
1072 8 : int ret = -1;
1073 8 : TALLOC_CTX *mem_ctx = talloc_stackframe();
1074 :
1075 8 : if (argc != 1 || c->display_usage) {
1076 2 : net_conf_delincludes_usage(c, argc, argv);
1077 2 : goto done;
1078 : }
1079 :
1080 6 : service = talloc_strdup(mem_ctx, argv[0]);
1081 6 : if (service == NULL) {
1082 0 : d_printf(_("error: out of memory!\n"));
1083 0 : goto done;
1084 : }
1085 :
1086 6 : err = smbconf_delete_includes(conf_ctx, service);
1087 6 : if (!SBC_ERROR_IS_OK(err)) {
1088 2 : d_printf(_("error deleting includes: %s\n"), sbcErrorString(err));
1089 2 : goto done;
1090 : }
1091 :
1092 4 : ret = 0;
1093 :
1094 8 : done:
1095 8 : TALLOC_FREE(mem_ctx);
1096 8 : 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 569 : 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 0 : sbcErr err;
1118 569 : TALLOC_CTX *mem_ctx = talloc_stackframe();
1119 0 : struct smbconf_ctx *conf_ctx;
1120 569 : int ret = -1;
1121 :
1122 569 : err = smbconf_init(mem_ctx, &conf_ctx, "registry:");
1123 569 : if (!SBC_ERROR_IS_OK(err)) {
1124 0 : talloc_free(mem_ctx);
1125 0 : return -1;
1126 : }
1127 :
1128 569 : ret = fn(c, conf_ctx, argc, argv);
1129 :
1130 569 : smbconf_shutdown(conf_ctx);
1131 :
1132 569 : talloc_free(mem_ctx);
1133 569 : 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 569 : 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 0 : int i;
1159 :
1160 569 : if (argc != 0) {
1161 3243 : for (i=0; table[i].funcname; i++) {
1162 3243 : if (strcasecmp_m(argv[0], table[i].funcname) == 0)
1163 569 : 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 569 : int net_conf(struct net_context *c, int argc, const char **argv)
1186 : {
1187 569 : int ret = -1;
1188 569 : 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 569 : ret = net_conf_run_function(c, argc, argv, "net conf", func_table);
1302 :
1303 569 : return ret;
1304 : }
1305 :
|