Line data Source code
1 : /*
2 : * Copyright (c) 2020 Andreas Schneider <asn@samba.org>
3 : *
4 : * This program is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 3 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * This program is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "includes.h"
19 : #include "lib/param/param.h"
20 : #include "dynconfig/dynconfig.h"
21 : #include "auth/gensec/gensec.h"
22 : #include "libcli/smb/smb_util.h"
23 : #include "cmdline_private.h"
24 :
25 : #include <samba/version.h>
26 :
27 : static TALLOC_CTX *cmdline_mem_ctx;
28 : static struct loadparm_context *cmdline_lp_ctx;
29 : static struct cli_credentials *cmdline_creds;
30 : static samba_cmdline_load_config cmdline_load_config_fn;
31 : static struct samba_cmdline_daemon_cfg cmdline_daemon_cfg;
32 :
33 : static NTSTATUS (*cli_credentials_set_machine_account_fn)(
34 : struct cli_credentials *cred,
35 : struct loadparm_context *lp_ctx) =
36 : cli_credentials_set_machine_account;
37 :
38 : /* PRIVATE */
39 8241 : bool samba_cmdline_set_talloc_ctx(TALLOC_CTX *mem_ctx)
40 : {
41 8241 : if (cmdline_mem_ctx != NULL) {
42 0 : return false;
43 : }
44 :
45 8241 : cmdline_mem_ctx = mem_ctx;
46 8241 : return true;
47 : }
48 :
49 30005 : TALLOC_CTX *samba_cmdline_get_talloc_ctx(void)
50 : {
51 30005 : return cmdline_mem_ctx;
52 : }
53 :
54 6 : static void _samba_cmdline_talloc_log(const char *message)
55 : {
56 6 : D_ERR("%s", message);
57 6 : }
58 :
59 8241 : bool samba_cmdline_init_common(TALLOC_CTX *mem_ctx)
60 : {
61 : bool ok;
62 :
63 8241 : ok = samba_cmdline_set_talloc_ctx(mem_ctx);
64 8241 : if (!ok) {
65 0 : return false;
66 : }
67 :
68 8241 : cmdline_daemon_cfg = (struct samba_cmdline_daemon_cfg) {
69 : .fork = true,
70 : };
71 :
72 8241 : fault_setup();
73 :
74 : /*
75 : * Log to stderr by default.
76 : * This can be changed to stdout using the option: --debug-stdout
77 : */
78 8241 : setup_logging(getprogname(), DEBUG_DEFAULT_STDERR);
79 :
80 8241 : talloc_set_log_fn(_samba_cmdline_talloc_log);
81 8241 : talloc_set_abort_fn(smb_panic);
82 :
83 8241 : return true;
84 : }
85 :
86 8241 : bool samba_cmdline_set_load_config_fn(samba_cmdline_load_config fn)
87 : {
88 8241 : cmdline_load_config_fn = fn;
89 8241 : return true;
90 : }
91 :
92 : /* PUBLIC */
93 8241 : bool samba_cmdline_set_lp_ctx(struct loadparm_context *lp_ctx)
94 : {
95 8241 : if (lp_ctx == NULL) {
96 0 : return false;
97 : }
98 8241 : cmdline_lp_ctx = lp_ctx;
99 :
100 8241 : return true;
101 : }
102 :
103 57935 : struct loadparm_context *samba_cmdline_get_lp_ctx(void)
104 : {
105 57935 : return cmdline_lp_ctx;
106 : }
107 :
108 8241 : bool samba_cmdline_set_creds(struct cli_credentials *creds)
109 : {
110 8241 : if (creds == NULL) {
111 0 : return false;
112 : }
113 :
114 8241 : TALLOC_FREE(cmdline_creds);
115 8241 : cmdline_creds = creds;
116 :
117 8241 : return true;
118 : }
119 :
120 1544433 : struct cli_credentials *samba_cmdline_get_creds(void)
121 : {
122 1544433 : return cmdline_creds;
123 : }
124 :
125 3897 : struct samba_cmdline_daemon_cfg *samba_cmdline_get_daemon_cfg(void)
126 : {
127 3897 : return &cmdline_daemon_cfg;
128 : }
129 :
130 5142 : void samba_cmdline_set_machine_account_fn(
131 : NTSTATUS (*fn) (struct cli_credentials *cred,
132 : struct loadparm_context *lp_ctx))
133 : {
134 5142 : cli_credentials_set_machine_account_fn = fn;
135 5142 : }
136 :
137 2389 : void samba_cmdline_burn(int argc, char *argv[])
138 : {
139 2389 : bool found = false;
140 2389 : bool is_user = false;
141 2389 : char *p = NULL;
142 : int i;
143 2389 : size_t ulen = 0;
144 :
145 18496 : for (i = 0; i < argc; i++) {
146 16107 : p = argv[i];
147 16107 : if (p == NULL) {
148 0 : return;
149 : }
150 :
151 16107 : if (strncmp(p, "-U", 2) == 0) {
152 1506 : ulen = 2;
153 1506 : found = true;
154 1506 : is_user = true;
155 14601 : } else if (strncmp(p, "--user", 6) == 0) {
156 0 : ulen = 6;
157 0 : found = true;
158 0 : is_user = true;
159 14601 : } else if (strncmp(p, "--password", 10) == 0) {
160 0 : ulen = 10;
161 0 : found = true;
162 : }
163 :
164 16107 : if (found) {
165 1554 : char *q = NULL;
166 :
167 1554 : if (strlen(p) == ulen) {
168 48 : continue;
169 : }
170 :
171 1506 : if (is_user) {
172 1506 : q = strchr_m(p, '%');
173 1506 : if (q != NULL) {
174 1490 : p = q;
175 : }
176 : } else {
177 0 : p += ulen;
178 : }
179 :
180 1506 : memset_s(p, strlen(p), '\0', strlen(p));
181 1506 : found = false;
182 1506 : is_user = false;
183 : }
184 : }
185 : }
186 :
187 24836820 : static bool is_popt_table_end(const struct poptOption *o)
188 : {
189 28874425 : if (o->longName == NULL &&
190 9743161 : o->shortName == 0 &&
191 7193771 : o->argInfo == 0 &&
192 3650375 : o->arg == NULL &&
193 3650375 : o->val == 0 &&
194 3650375 : o->descrip == NULL &&
195 2148190 : o->argDescrip == NULL) {
196 2148190 : return true;
197 : }
198 :
199 22688630 : return false;
200 : }
201 :
202 2096736 : static void find_duplicates(const struct poptOption *needle,
203 : const struct poptOption *haystack,
204 : size_t *count)
205 : {
206 18690642 : for(;
207 24334055 : !is_popt_table_end(haystack);
208 22237319 : haystack++) {
209 22237319 : switch (haystack->argInfo) {
210 1729607 : case POPT_ARG_INCLUDE_TABLE:
211 1729607 : if (haystack->arg != NULL) {
212 1729607 : find_duplicates(needle, haystack->arg, count);
213 : }
214 :
215 1729607 : break;
216 20507712 : default:
217 26850580 : if (needle->shortName != 0 &&
218 9440553 : needle->shortName == haystack->shortName) {
219 174198 : (*count)++;
220 174198 : break;
221 : }
222 :
223 34075545 : if (needle->longName != NULL &&
224 38731501 : haystack->longName != NULL &&
225 18471619 : strequal(needle->longName, haystack->longName)) {
226 192931 : (*count)++;
227 192931 : break;
228 : }
229 20140583 : break;
230 : }
231 :
232 22237319 : if (*count > 1) {
233 0 : return;
234 : }
235 : }
236 : }
237 :
238 51454 : static bool cmdline_sanity_checker(const struct poptOption *current_opts,
239 : const struct poptOption *full_opts)
240 : {
241 51454 : const struct poptOption *o = current_opts;
242 :
243 406441 : for(;
244 502765 : !is_popt_table_end(o);
245 451311 : o++) {
246 : bool ok;
247 :
248 451311 : switch (o->argInfo) {
249 42091 : case POPT_ARG_INCLUDE_TABLE:
250 42091 : if (o->arg != NULL) {
251 42091 : ok = cmdline_sanity_checker(o->arg, full_opts);
252 42091 : if (!ok) {
253 0 : return false;
254 : }
255 : }
256 :
257 42091 : break;
258 409220 : default:
259 409220 : if (o->longName != NULL || o->shortName != 0) {
260 367129 : size_t count = 0;
261 :
262 367129 : find_duplicates(o, full_opts, &count);
263 367129 : if (count > 1) {
264 0 : DBG_ERR("Duplicate option '--%s|-%c' "
265 : "detected!\n",
266 : o->longName,
267 : o->shortName != 0 ?
268 : o->shortName :
269 : '-');
270 0 : return false;
271 : }
272 : }
273 :
274 409220 : break;
275 : }
276 : }
277 :
278 51454 : return true;
279 : }
280 :
281 9363 : bool samba_cmdline_sanity_check(const struct poptOption *opts)
282 : {
283 9363 : return cmdline_sanity_checker(opts, opts);
284 : }
285 :
286 8115 : poptContext samba_popt_get_context(const char * name,
287 : int argc, const char ** argv,
288 : const struct poptOption * options,
289 : unsigned int flags)
290 : {
291 : #ifdef DEVELOPER
292 : bool ok;
293 :
294 8115 : ok = samba_cmdline_sanity_check(options);
295 8115 : if (!ok) {
296 0 : return NULL;
297 : }
298 : #endif
299 8115 : return poptGetContext(name, argc, argv, options, flags);
300 : }
301 :
302 : /**********************************************************
303 : * COMMON SAMBA POPT
304 : **********************************************************/
305 :
306 : static bool log_to_file;
307 :
308 10609 : static bool set_logfile(TALLOC_CTX *mem_ctx,
309 : struct loadparm_context *lp_ctx,
310 : const char *log_basename,
311 : const char *process_name,
312 : bool from_cmdline)
313 : {
314 10609 : bool ok = false;
315 10609 : char *new_logfile = talloc_asprintf(mem_ctx,
316 : "%s/log.%s",
317 : log_basename,
318 : process_name);
319 10609 : if (new_logfile == NULL) {
320 0 : return false;
321 : }
322 :
323 10609 : if (from_cmdline) {
324 213 : ok = lpcfg_set_cmdline(lp_ctx,
325 : "log file",
326 : new_logfile);
327 : } else {
328 10396 : ok = lpcfg_do_global_parameter(lp_ctx,
329 : "log file",
330 : new_logfile);
331 : }
332 10609 : if (!ok) {
333 0 : fprintf(stderr,
334 : "Failed to set log to %s\n",
335 : new_logfile);
336 0 : TALLOC_FREE(new_logfile);
337 0 : return false;
338 : }
339 10609 : debug_set_logfile(new_logfile);
340 10609 : TALLOC_FREE(new_logfile);
341 :
342 10609 : return true;
343 : }
344 :
345 30005 : static void popt_samba_callback(poptContext popt_ctx,
346 : enum poptCallbackReason reason,
347 : const struct poptOption *opt,
348 : const char *arg, const void *data)
349 : {
350 30005 : TALLOC_CTX *mem_ctx = samba_cmdline_get_talloc_ctx();
351 30005 : struct loadparm_context *lp_ctx = samba_cmdline_get_lp_ctx();
352 30005 : const char *pname = NULL;
353 : bool ok;
354 :
355 : /* Find out basename of current program */
356 30005 : pname = getprogname();
357 :
358 30005 : if (reason == POPT_CALLBACK_REASON_PRE) {
359 10396 : if (lp_ctx == NULL) {
360 0 : fprintf(stderr,
361 : "Command line parsing not initialized!\n");
362 0 : exit(1);
363 : }
364 10396 : ok = set_logfile(mem_ctx,
365 : lp_ctx,
366 : get_dyn_LOGFILEBASE(),
367 : pname,
368 : false);
369 10396 : if (!ok) {
370 0 : fprintf(stderr,
371 : "Failed to set log file for %s\n",
372 : pname);
373 0 : exit(1);
374 : }
375 10396 : return;
376 : }
377 :
378 19609 : if (reason == POPT_CALLBACK_REASON_POST) {
379 10337 : ok = cmdline_load_config_fn();
380 10337 : if (!ok) {
381 0 : fprintf(stderr,
382 : "%s - Failed to load config file!\n",
383 : getprogname());
384 0 : exit(1);
385 : }
386 :
387 10337 : if (log_to_file) {
388 131 : const struct loadparm_substitution *lp_sub =
389 82 : lpcfg_noop_substitution();
390 213 : char *logfile = NULL;
391 :
392 213 : logfile = lpcfg_logfile(lp_ctx, lp_sub, mem_ctx);
393 213 : if (logfile == NULL) {
394 0 : fprintf(stderr,
395 : "Failed to setup logging to file!");
396 0 : exit(1);
397 : }
398 213 : debug_set_logfile(logfile);
399 213 : setup_logging(logfile, DEBUG_FILE);
400 213 : TALLOC_FREE(logfile);
401 : }
402 :
403 10337 : return;
404 : }
405 :
406 9272 : switch(opt->val) {
407 0 : case OPT_LEAK_REPORT:
408 0 : talloc_enable_leak_report();
409 0 : break;
410 0 : case OPT_LEAK_REPORT_FULL:
411 0 : talloc_enable_leak_report_full();
412 0 : break;
413 4839 : case OPT_OPTION:
414 4839 : if (arg != NULL) {
415 4839 : ok = lpcfg_set_option(lp_ctx, arg);
416 4839 : if (!ok) {
417 1 : fprintf(stderr, "Error setting option '%s'\n", arg);
418 1 : exit(1);
419 : }
420 : }
421 4838 : break;
422 156 : case 'd':
423 156 : if (arg != NULL) {
424 156 : ok = lpcfg_set_cmdline(lp_ctx, "log level", arg);
425 156 : if (!ok) {
426 0 : fprintf(stderr,
427 : "Failed to set debug level to: %s\n",
428 : arg);
429 0 : exit(1);
430 : }
431 : }
432 156 : break;
433 76 : case OPT_DEBUG_STDOUT:
434 76 : setup_logging(pname, DEBUG_STDOUT);
435 76 : break;
436 3988 : case OPT_CONFIGFILE:
437 3988 : if (arg != NULL) {
438 3988 : set_dyn_CONFIGFILE(arg);
439 : }
440 3988 : break;
441 213 : case 'l':
442 213 : if (arg != NULL) {
443 213 : ok = set_logfile(mem_ctx, lp_ctx, arg, pname, true);
444 213 : if (!ok) {
445 0 : fprintf(stderr,
446 : "Failed to set log file for %s\n",
447 : arg);
448 0 : exit(1);
449 : }
450 213 : log_to_file = true;
451 :
452 213 : set_dyn_LOGFILEBASE(arg);
453 : }
454 213 : break;
455 : }
456 : }
457 :
458 : static struct poptOption popt_common_debug[] = {
459 : {
460 : .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
461 : .arg = (void *)popt_samba_callback,
462 : },
463 : {
464 : .longName = "debuglevel",
465 : .shortName = 'd',
466 : .argInfo = POPT_ARG_STRING,
467 : .val = 'd',
468 : .descrip = "Set debug level",
469 : .argDescrip = "DEBUGLEVEL",
470 : },
471 : {
472 : .longName = "debug-stdout",
473 : .argInfo = POPT_ARG_NONE,
474 : .val = OPT_DEBUG_STDOUT,
475 : .descrip = "Send debug output to standard output",
476 : },
477 : POPT_TABLEEND
478 : };
479 :
480 : static struct poptOption popt_common_option[] = {
481 : {
482 : .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
483 : .arg = (void *)popt_samba_callback,
484 : },
485 : {
486 : .longName = "option",
487 : .argInfo = POPT_ARG_STRING,
488 : .val = OPT_OPTION,
489 : .descrip = "Set smb.conf option from command line",
490 : .argDescrip = "name=value",
491 : },
492 : POPT_TABLEEND
493 : };
494 :
495 : static struct poptOption popt_common_config[] = {
496 : {
497 : .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
498 : .arg = (void *)popt_samba_callback,
499 : },
500 : {
501 : .longName = "configfile",
502 : .argInfo = POPT_ARG_STRING,
503 : .val = OPT_CONFIGFILE,
504 : .descrip = "Use alternative configuration file",
505 : .argDescrip = "CONFIGFILE",
506 : },
507 : POPT_TABLEEND
508 : };
509 :
510 : static struct poptOption popt_common_samba[] = {
511 : {
512 : .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
513 : .arg = (void *)popt_samba_callback,
514 : },
515 : {
516 : .longName = "debuglevel",
517 : .shortName = 'd',
518 : .argInfo = POPT_ARG_STRING,
519 : .val = 'd',
520 : .descrip = "Set debug level",
521 : .argDescrip = "DEBUGLEVEL",
522 : },
523 : {
524 : .longName = "debug-stdout",
525 : .argInfo = POPT_ARG_NONE,
526 : .val = OPT_DEBUG_STDOUT,
527 : .descrip = "Send debug output to standard output",
528 : },
529 : {
530 : .longName = "configfile",
531 : .shortName = 's',
532 : .argInfo = POPT_ARG_STRING,
533 : .val = OPT_CONFIGFILE,
534 : .descrip = "Use alternative configuration file",
535 : .argDescrip = "CONFIGFILE",
536 : },
537 : {
538 : .longName = "option",
539 : .argInfo = POPT_ARG_STRING,
540 : .val = OPT_OPTION,
541 : .descrip = "Set smb.conf option from command line",
542 : .argDescrip = "name=value",
543 : },
544 : {
545 : .longName = "log-basename",
546 : .shortName = 'l',
547 : .argInfo = POPT_ARG_STRING,
548 : .val = 'l',
549 : .descrip = "Basename for log/debug files",
550 : .argDescrip = "LOGFILEBASE",
551 : },
552 : {
553 : .longName = "leak-report",
554 : .argInfo = POPT_ARG_NONE,
555 : .val = OPT_LEAK_REPORT,
556 : .descrip = "enable talloc leak reporting on exit",
557 : },
558 : {
559 : .longName = "leak-report-full",
560 : .argInfo = POPT_ARG_NONE,
561 : .val = OPT_LEAK_REPORT_FULL,
562 : .descrip = "enable full talloc leak reporting on exit",
563 : },
564 : POPT_TABLEEND
565 : };
566 :
567 : static struct poptOption popt_common_samba_ldb[] = {
568 : {
569 : .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
570 : .arg = (void *)popt_samba_callback,
571 : },
572 : {
573 : .longName = "debuglevel",
574 : .shortName = 'd',
575 : .argInfo = POPT_ARG_STRING,
576 : .val = 'd',
577 : .descrip = "Set debug level",
578 : .argDescrip = "DEBUGLEVEL",
579 : },
580 : {
581 : .longName = "debug-stdout",
582 : .argInfo = POPT_ARG_NONE,
583 : .val = OPT_DEBUG_STDOUT,
584 : .descrip = "Send debug output to standard output",
585 : },
586 : {
587 : .longName = "configfile",
588 : .argInfo = POPT_ARG_STRING,
589 : .val = OPT_CONFIGFILE,
590 : .descrip = "Use alternative configuration file",
591 : .argDescrip = "CONFIGFILE",
592 : },
593 : {
594 : .longName = "option",
595 : .argInfo = POPT_ARG_STRING,
596 : .val = OPT_OPTION,
597 : .descrip = "Set smb.conf option from command line",
598 : .argDescrip = "name=value",
599 : },
600 : {
601 : .longName = "log-basename",
602 : .shortName = 'l',
603 : .argInfo = POPT_ARG_STRING,
604 : .val = 'l',
605 : .descrip = "Basename for log/debug files",
606 : .argDescrip = "LOGFILEBASE",
607 : },
608 : {
609 : .longName = "leak-report",
610 : .argInfo = POPT_ARG_NONE,
611 : .val = OPT_LEAK_REPORT,
612 : .descrip = "enable talloc leak reporting on exit",
613 : },
614 : {
615 : .longName = "leak-report-full",
616 : .argInfo = POPT_ARG_NONE,
617 : .val = OPT_LEAK_REPORT_FULL,
618 : .descrip = "enable full talloc leak reporting on exit",
619 : },
620 : POPT_TABLEEND
621 : };
622 :
623 : /**********************************************************
624 : * CONNECTION POPT
625 : **********************************************************/
626 :
627 6130 : static void popt_connection_callback(poptContext popt_ctx,
628 : enum poptCallbackReason reason,
629 : const struct poptOption *opt,
630 : const char *arg,
631 : const void *data)
632 : {
633 6130 : struct loadparm_context *lp_ctx = cmdline_lp_ctx;
634 :
635 6130 : if (reason == POPT_CALLBACK_REASON_PRE) {
636 4787 : if (lp_ctx == NULL) {
637 0 : fprintf(stderr,
638 : "Command line parsing not initialized!\n");
639 0 : exit(1);
640 : }
641 4787 : return;
642 : }
643 :
644 1343 : switch(opt->val) {
645 0 : case 'O':
646 0 : if (arg != NULL) {
647 0 : lpcfg_set_cmdline(lp_ctx, "socket options", arg);
648 : }
649 0 : break;
650 0 : case 'R':
651 0 : if (arg != NULL) {
652 0 : lpcfg_set_cmdline(lp_ctx, "name resolve order", arg);
653 : }
654 0 : break;
655 528 : case 'm':
656 528 : if (arg != NULL) {
657 528 : lpcfg_set_cmdline(lp_ctx, "client max protocol", arg);
658 : }
659 528 : break;
660 0 : case OPT_NETBIOS_SCOPE:
661 0 : if (arg != NULL) {
662 0 : lpcfg_set_cmdline(lp_ctx, "netbios scope", arg);
663 : }
664 0 : break;
665 8 : case 'n':
666 8 : if (arg != NULL) {
667 8 : lpcfg_set_cmdline(lp_ctx, "netbios name", arg);
668 : }
669 8 : break;
670 782 : case 'W':
671 782 : if (arg != NULL) {
672 782 : lpcfg_set_cmdline(lp_ctx, "workgroup", arg);
673 : }
674 782 : break;
675 25 : case 'r':
676 25 : if (arg != NULL) {
677 25 : lpcfg_set_cmdline(lp_ctx, "realm", arg);
678 : }
679 25 : break;
680 : }
681 : }
682 :
683 : static struct poptOption popt_common_connection[] = {
684 : {
685 : .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE,
686 : .arg = (void *)popt_connection_callback,
687 : },
688 : {
689 : .longName = "name-resolve",
690 : .shortName = 'R',
691 : .argInfo = POPT_ARG_STRING,
692 : .val = 'R',
693 : .descrip = "Use these name resolution services only",
694 : .argDescrip = "NAME-RESOLVE-ORDER",
695 : },
696 : {
697 : .longName = "socket-options",
698 : .shortName = 'O',
699 : .argInfo = POPT_ARG_STRING,
700 : .val = 'O',
701 : .descrip = "socket options to use",
702 : .argDescrip = "SOCKETOPTIONS",
703 : },
704 : {
705 : .longName = "max-protocol",
706 : .shortName = 'm',
707 : .argInfo = POPT_ARG_STRING,
708 : .val = 'm',
709 : .descrip = "Set max protocol level",
710 : .argDescrip = "MAXPROTOCOL",
711 : },
712 : {
713 : .longName = "netbiosname",
714 : .shortName = 'n',
715 : .argInfo = POPT_ARG_STRING,
716 : .val = 'n',
717 : .descrip = "Primary netbios name",
718 : .argDescrip = "NETBIOSNAME",
719 : },
720 : {
721 : .longName = "netbios-scope",
722 : .argInfo = POPT_ARG_STRING,
723 : .val = OPT_NETBIOS_SCOPE,
724 : .descrip = "Use this Netbios scope",
725 : .argDescrip = "SCOPE",
726 : },
727 : {
728 : .longName = "workgroup",
729 : .shortName = 'W',
730 : .argInfo = POPT_ARG_STRING,
731 : .val = 'W',
732 : .descrip = "Set the workgroup name",
733 : .argDescrip = "WORKGROUP",
734 : },
735 : {
736 : .longName = "realm",
737 : .argInfo = POPT_ARG_STRING,
738 : .val = 'r',
739 : .descrip = "Set the realm name",
740 : .argDescrip = "REALM",
741 : },
742 : POPT_TABLEEND
743 : };
744 :
745 : /**********************************************************
746 : * CREDENTIALS POPT
747 : **********************************************************/
748 :
749 : static bool skip_password_callback;
750 : static bool machine_account_pending;
751 :
752 13393 : static void popt_common_credentials_callback(poptContext popt_ctx,
753 : enum poptCallbackReason reason,
754 : const struct poptOption *opt,
755 : const char *arg,
756 : const void *data)
757 : {
758 13393 : struct loadparm_context *lp_ctx = samba_cmdline_get_lp_ctx();
759 13393 : struct cli_credentials *creds = samba_cmdline_get_creds();
760 : bool ok;
761 :
762 13393 : if (reason == POPT_CALLBACK_REASON_PRE) {
763 4610 : if (creds == NULL) {
764 0 : fprintf(stderr,
765 : "Command line parsing not initialized!\n");
766 0 : exit(1);
767 : }
768 4610 : return;
769 : }
770 :
771 8783 : if (reason == POPT_CALLBACK_REASON_POST) {
772 4592 : const char *username = NULL;
773 4592 : enum credentials_obtained username_obtained =
774 : CRED_UNINITIALISED;
775 4592 : enum credentials_obtained password_obtained =
776 : CRED_UNINITIALISED;
777 :
778 : /*
779 : * This calls cli_credentials_set_conf() to get the defaults
780 : * form smb.conf and set the winbind separator.
781 : *
782 : * Just warn that we can't read the smb.conf. The might not be
783 : * one available or we want to ignore it.
784 : */
785 4592 : ok = cli_credentials_guess(creds, lp_ctx);
786 4592 : if (!ok) {
787 0 : fprintf(stderr,
788 : "Unable to read defaults from smb.conf\n");
789 : }
790 :
791 4592 : (void)cli_credentials_get_password_and_obtained(creds,
792 : &password_obtained);
793 7483 : if (!skip_password_callback &&
794 4229 : password_obtained < CRED_CALLBACK) {
795 1205 : ok = cli_credentials_set_cmdline_callbacks(creds);
796 1205 : if (!ok) {
797 0 : fprintf(stderr,
798 : "Failed to set cmdline password "
799 : "callback\n");
800 0 : exit(1);
801 : }
802 : }
803 :
804 4592 : if (machine_account_pending) {
805 : NTSTATUS status;
806 :
807 78 : status = cli_credentials_set_machine_account_fn(
808 : creds, lp_ctx);
809 78 : if (!NT_STATUS_IS_OK(status)) {
810 0 : fprintf(stderr,
811 : "Failed to set machine account: %s\n",
812 : nt_errstr(status));
813 0 : exit(1);
814 : }
815 : }
816 :
817 : /*
818 : * When we set the username during the handling of the options
819 : * passed to the binary we haven't loaded the config yet. This
820 : * means that we didn't take the 'winbind separator' into
821 : * account.
822 : *
823 : * The username might contain the domain name and thus it
824 : * hasn't been correctly parsed yet. If we have a username we
825 : * need to set it again to run the string parser for the
826 : * username correctly.
827 : */
828 3107 : username =
829 1485 : cli_credentials_get_username_and_obtained(
830 : creds, &username_obtained);
831 4592 : if (username_obtained == CRED_SPECIFIED &&
832 3208 : username != NULL && username[0] != '\0') {
833 3009 : cli_credentials_parse_string(creds,
834 : username,
835 : CRED_SPECIFIED);
836 : }
837 :
838 4592 : return;
839 : }
840 :
841 4191 : switch(opt->val) {
842 3116 : case 'U':
843 3116 : if (arg != NULL) {
844 3116 : cli_credentials_parse_string(creds,
845 : arg,
846 : CRED_SPECIFIED);
847 : }
848 3116 : break;
849 119 : case OPT_PASSWORD:
850 119 : if (arg != NULL) {
851 119 : ok = cli_credentials_set_password(creds,
852 : arg,
853 : CRED_SPECIFIED);
854 119 : if (!ok) {
855 0 : fprintf(stderr,
856 : "Failed to set password!\n");
857 0 : exit(1);
858 : }
859 :
860 119 : skip_password_callback = true;
861 : }
862 119 : break;
863 0 : case OPT_NT_HASH:
864 0 : cli_credentials_set_password_will_be_nt_hash(creds, true);
865 0 : break;
866 14 : case 'A':
867 14 : if (arg != NULL) {
868 14 : ok = cli_credentials_parse_file(creds,
869 : arg,
870 : CRED_SPECIFIED);
871 14 : if (!ok) {
872 0 : fprintf(stderr,
873 : "Failed to set parse authentication file!\n");
874 0 : exit(1);
875 : }
876 14 : skip_password_callback = true;
877 : }
878 14 : break;
879 20 : case 'N':
880 20 : ok = cli_credentials_set_password(creds,
881 : NULL,
882 : CRED_SPECIFIED);
883 20 : if (!ok) {
884 0 : fprintf(stderr,
885 : "Failed to set password!\n");
886 0 : exit(1);
887 : }
888 20 : skip_password_callback = true;
889 20 : break;
890 78 : case 'P':
891 : /*
892 : * Later, after this is all over, get the machine account
893 : * details from the secrets.(l|t)db.
894 : */
895 78 : machine_account_pending = true;
896 78 : break;
897 55 : case OPT_SIMPLE_BIND_DN:
898 55 : if (arg != NULL) {
899 55 : ok = cli_credentials_set_bind_dn(creds, arg);
900 55 : if (!ok) {
901 0 : fprintf(stderr,
902 : "Failed to set bind DN!\n");
903 0 : exit(1);
904 : }
905 : }
906 55 : break;
907 115 : case OPT_USE_KERBEROS: {
908 115 : int32_t use_kerberos = INT_MIN;
909 115 : if (arg == NULL) {
910 0 : fprintf(stderr,
911 : "Failed to parse "
912 : "--use-kerberos=desired|required|off: "
913 : "Missing argument\n");
914 0 : exit(1);
915 : }
916 :
917 115 : use_kerberos = lpcfg_parse_enum_vals("client use kerberos",
918 : arg);
919 115 : if (use_kerberos == INT_MIN) {
920 0 : fprintf(stderr,
921 : "Failed to parse "
922 : "--use-kerberos=desired|required|off: "
923 : "Invalid argument\n");
924 0 : exit(1);
925 : }
926 :
927 115 : ok = cli_credentials_set_kerberos_state(creds,
928 : use_kerberos,
929 : CRED_SPECIFIED);
930 115 : if (!ok) {
931 0 : fprintf(stderr,
932 : "Failed to set Kerberos state to %s!\n", arg);
933 0 : exit(1);
934 : }
935 115 : break;
936 : }
937 189 : case OPT_USE_KERBEROS_CCACHE: {
938 189 : const char *error_string = NULL;
939 : int rc;
940 :
941 189 : if (arg == NULL) {
942 0 : fprintf(stderr,
943 : "Failed to parse --use-krb5-ccache=CCACHE: "
944 : "Missing argument\n");
945 0 : exit(1);
946 : }
947 :
948 189 : ok = cli_credentials_set_kerberos_state(creds,
949 : CRED_USE_KERBEROS_REQUIRED,
950 : CRED_SPECIFIED);
951 189 : if (!ok) {
952 0 : fprintf(stderr,
953 : "Failed to set Kerberos state to %s!\n", arg);
954 0 : exit(1);
955 : }
956 :
957 189 : rc = cli_credentials_set_ccache(creds,
958 : lp_ctx,
959 : arg,
960 : CRED_SPECIFIED,
961 : &error_string);
962 189 : if (rc != 0) {
963 0 : fprintf(stderr,
964 : "Error reading krb5 credentials cache: '%s'"
965 : " - %s\n",
966 : arg,
967 : error_string);
968 0 : exit(1);
969 : }
970 :
971 189 : skip_password_callback = true;
972 189 : break;
973 : }
974 12 : case OPT_USE_WINBIND_CCACHE:
975 : {
976 : uint32_t gensec_features;
977 :
978 12 : gensec_features = cli_credentials_get_gensec_features(creds);
979 12 : gensec_features |= GENSEC_FEATURE_NTLM_CCACHE;
980 :
981 12 : ok = cli_credentials_set_gensec_features(creds,
982 : gensec_features,
983 : CRED_SPECIFIED);
984 12 : if (!ok) {
985 0 : fprintf(stderr,
986 : "Failed to set gensec feature!\n");
987 0 : exit(1);
988 : }
989 :
990 12 : skip_password_callback = true;
991 12 : break;
992 : }
993 473 : case OPT_CLIENT_PROTECTION: {
994 : uint32_t gensec_features;
995 473 : enum smb_signing_setting signing_state =
996 : SMB_SIGNING_OFF;
997 473 : enum smb_encryption_setting encryption_state =
998 : SMB_ENCRYPTION_OFF;
999 :
1000 473 : if (arg == NULL) {
1001 0 : fprintf(stderr,
1002 : "Failed to parse "
1003 : "--client-protection=sign|encrypt|off: "
1004 : "Missing argument\n");
1005 0 : exit(1);
1006 : }
1007 :
1008 354 : gensec_features =
1009 119 : cli_credentials_get_gensec_features(
1010 : creds);
1011 :
1012 473 : if (strequal(arg, "off")) {
1013 14 : gensec_features &=
1014 : ~(GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL);
1015 :
1016 14 : signing_state = SMB_SIGNING_OFF;
1017 14 : encryption_state = SMB_ENCRYPTION_OFF;
1018 459 : } else if (strequal(arg, "sign")) {
1019 324 : gensec_features |= GENSEC_FEATURE_SIGN;
1020 :
1021 324 : signing_state = SMB_SIGNING_REQUIRED;
1022 324 : encryption_state = SMB_ENCRYPTION_OFF;
1023 135 : } else if (strequal(arg, "encrypt")) {
1024 135 : gensec_features |= GENSEC_FEATURE_SEAL;
1025 :
1026 135 : signing_state = SMB_SIGNING_REQUIRED;
1027 135 : encryption_state = SMB_ENCRYPTION_REQUIRED;
1028 : } else {
1029 0 : fprintf(stderr,
1030 : "Failed to parse --client-protection\n");
1031 0 : exit(1);
1032 : }
1033 :
1034 473 : ok = cli_credentials_set_gensec_features(creds,
1035 : gensec_features,
1036 : CRED_SPECIFIED);
1037 473 : if (!ok) {
1038 0 : fprintf(stderr,
1039 : "Failed to set gensec feature!\n");
1040 0 : exit(1);
1041 : }
1042 :
1043 473 : ok = cli_credentials_set_smb_signing(creds,
1044 : signing_state,
1045 : CRED_SPECIFIED);
1046 473 : if (!ok) {
1047 0 : fprintf(stderr,
1048 : "Failed to set smb signing!\n");
1049 0 : exit(1);
1050 : }
1051 :
1052 473 : ok = cli_credentials_set_smb_encryption(creds,
1053 : encryption_state,
1054 : CRED_SPECIFIED);
1055 473 : if (!ok) {
1056 0 : fprintf(stderr,
1057 : "Failed to set smb encryption!\n");
1058 0 : exit(1);
1059 : }
1060 473 : break;
1061 : }
1062 : } /* switch */
1063 : }
1064 :
1065 : static struct poptOption popt_common_credentials[] = {
1066 : {
1067 : .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
1068 : .arg = (void *)popt_common_credentials_callback,
1069 : },
1070 : {
1071 : .longName = "user",
1072 : .shortName = 'U',
1073 : .argInfo = POPT_ARG_STRING,
1074 : .val = 'U',
1075 : .descrip = "Set the network username",
1076 : .argDescrip = "[DOMAIN/]USERNAME[%PASSWORD]",
1077 : },
1078 : {
1079 : .longName = "no-pass",
1080 : .shortName = 'N',
1081 : .argInfo = POPT_ARG_NONE,
1082 : .val = 'N',
1083 : .descrip = "Don't ask for a password",
1084 : },
1085 : {
1086 : .longName = "password",
1087 : .argInfo = POPT_ARG_STRING,
1088 : .val = OPT_PASSWORD,
1089 : .descrip = "Password",
1090 : },
1091 : {
1092 : .longName = "pw-nt-hash",
1093 : .argInfo = POPT_ARG_NONE,
1094 : .val = OPT_NT_HASH,
1095 : .descrip = "The supplied password is the NT hash",
1096 : },
1097 : {
1098 : .longName = "authentication-file",
1099 : .shortName = 'A',
1100 : .argInfo = POPT_ARG_STRING,
1101 : .val = 'A',
1102 : .descrip = "Get the credentials from a file",
1103 : .argDescrip = "FILE",
1104 : },
1105 : {
1106 : .longName = "machine-pass",
1107 : .shortName = 'P',
1108 : .argInfo = POPT_ARG_NONE,
1109 : .val = 'P',
1110 : .descrip = "Use stored machine account password",
1111 : },
1112 : {
1113 : .longName = "simple-bind-dn",
1114 : .argInfo = POPT_ARG_STRING,
1115 : .val = OPT_SIMPLE_BIND_DN,
1116 : .descrip = "DN to use for a simple bind",
1117 : .argDescrip = "DN",
1118 : },
1119 : {
1120 : .longName = "use-kerberos",
1121 : .argInfo = POPT_ARG_STRING,
1122 : .val = OPT_USE_KERBEROS,
1123 : .descrip = "Use Kerberos authentication",
1124 : .argDescrip = "desired|required|off",
1125 : },
1126 : {
1127 : .longName = "use-krb5-ccache",
1128 : .argInfo = POPT_ARG_STRING,
1129 : .val = OPT_USE_KERBEROS_CCACHE,
1130 : .descrip = "Credentials cache location for Kerberos",
1131 : .argDescrip = "CCACHE",
1132 : },
1133 : {
1134 : .longName = "use-winbind-ccache",
1135 : .argInfo = POPT_ARG_NONE,
1136 : .val = OPT_USE_WINBIND_CCACHE,
1137 : .descrip = "Use the winbind ccache for authentication",
1138 : },
1139 : {
1140 : .longName = "client-protection",
1141 : .argInfo = POPT_ARG_STRING,
1142 : .val = OPT_CLIENT_PROTECTION,
1143 : .descrip = "Configure used protection for client connections",
1144 : .argDescrip = "sign|encrypt|off",
1145 : },
1146 : POPT_TABLEEND
1147 : };
1148 :
1149 : /**********************************************************
1150 : * VERSION POPT
1151 : **********************************************************/
1152 :
1153 0 : static void popt_version_callback(poptContext ctx,
1154 : enum poptCallbackReason reason,
1155 : const struct poptOption *opt,
1156 : const char *arg,
1157 : const void *data)
1158 : {
1159 0 : switch(opt->val) {
1160 0 : case 'V':
1161 0 : printf("Version %s\n", SAMBA_VERSION_STRING);
1162 0 : exit(0);
1163 : }
1164 0 : }
1165 :
1166 : static struct poptOption popt_common_version[] = {
1167 : {
1168 : .argInfo = POPT_ARG_CALLBACK,
1169 : .arg = (void *)popt_version_callback,
1170 : },
1171 : {
1172 : .longName = "version",
1173 : .shortName = 'V',
1174 : .argInfo = POPT_ARG_NONE,
1175 : .val = 'V',
1176 : .descrip = "Print version",
1177 : },
1178 : POPT_TABLEEND
1179 : };
1180 :
1181 : /**********************************************************
1182 : * DAEMON POPT
1183 : **********************************************************/
1184 :
1185 392 : static void popt_daemon_callback(poptContext ctx,
1186 : enum poptCallbackReason reason,
1187 : const struct poptOption *opt,
1188 : const char *arg,
1189 : const void *data)
1190 : {
1191 392 : switch(opt->val) {
1192 67 : case OPT_DAEMON:
1193 67 : cmdline_daemon_cfg.daemon = true;
1194 67 : break;
1195 53 : case OPT_INTERACTIVE:
1196 53 : cmdline_daemon_cfg.interactive = true;
1197 53 : cmdline_daemon_cfg.fork = false;
1198 53 : break;
1199 143 : case OPT_FORK:
1200 143 : cmdline_daemon_cfg.fork = false;
1201 143 : break;
1202 129 : case OPT_NO_PROCESS_GROUP:
1203 129 : cmdline_daemon_cfg.no_process_group = true;
1204 129 : break;
1205 : }
1206 392 : }
1207 :
1208 : static struct poptOption popt_common_daemon[] = {
1209 : {
1210 : .argInfo = POPT_ARG_CALLBACK,
1211 : .arg = (void *)popt_daemon_callback
1212 : },
1213 : {
1214 : .longName = "daemon",
1215 : .shortName = 'D',
1216 : .argInfo = POPT_ARG_NONE,
1217 : .arg = NULL,
1218 : .val = OPT_DAEMON,
1219 : .descrip = "Become a daemon (default)" ,
1220 : },
1221 : {
1222 : .longName = "interactive",
1223 : .shortName = 'i',
1224 : .argInfo = POPT_ARG_NONE,
1225 : .arg = NULL,
1226 : .val = OPT_INTERACTIVE,
1227 : .descrip = "Run interactive (not a daemon) and log to stdout",
1228 : },
1229 : {
1230 : .longName = "foreground",
1231 : .shortName = 'F',
1232 : .argInfo = POPT_ARG_NONE,
1233 : .arg = NULL,
1234 : .val = OPT_FORK,
1235 : .descrip = "Run daemon in foreground (for daemontools, etc.)",
1236 : },
1237 : {
1238 : .longName = "no-process-group",
1239 : .shortName = '\0',
1240 : .argInfo = POPT_ARG_NONE,
1241 : .arg = NULL,
1242 : .val = OPT_NO_PROCESS_GROUP,
1243 : .descrip = "Don't create a new process group" ,
1244 : },
1245 : POPT_TABLEEND
1246 : };
1247 :
1248 : /**********************************************************
1249 : * LEGACY S3 POPT
1250 : **********************************************************/
1251 :
1252 9 : static void popt_legacy_s3_callback(poptContext ctx,
1253 : enum poptCallbackReason reason,
1254 : const struct poptOption *opt,
1255 : const char *arg,
1256 : const void *data)
1257 : {
1258 9 : struct cli_credentials *creds = samba_cmdline_get_creds();
1259 : bool ok;
1260 :
1261 9 : switch(opt->val) {
1262 9 : case 'k':
1263 9 : fprintf(stderr,
1264 : "WARNING: The option -k|--kerberos is deprecated!\n");
1265 :
1266 9 : ok = cli_credentials_set_kerberos_state(creds,
1267 : CRED_USE_KERBEROS_REQUIRED,
1268 : CRED_SPECIFIED);
1269 9 : if (!ok) {
1270 0 : fprintf(stderr,
1271 : "Failed to set Kerberos state to %s!\n", arg);
1272 0 : exit(1);
1273 : }
1274 :
1275 9 : skip_password_callback = true;
1276 9 : break;
1277 : }
1278 9 : }
1279 :
1280 : /* We allow '-k yes' too. */
1281 : static struct poptOption popt_legacy_s3[] = {
1282 : {
1283 : .argInfo = POPT_ARG_CALLBACK,
1284 : .arg = (void *)popt_legacy_s3_callback,
1285 : },
1286 : {
1287 : .longName = "kerberos",
1288 : .shortName = 'k',
1289 : .argInfo = POPT_ARG_NONE,
1290 : .val = 'k',
1291 : .descrip = "DEPRECATED: Migrate to --use-kerberos",
1292 : },
1293 : POPT_TABLEEND
1294 : };
1295 :
1296 : /**********************************************************
1297 : * LEGACY S4 POPT
1298 : **********************************************************/
1299 :
1300 685 : static void popt_legacy_s4_callback(poptContext ctx,
1301 : enum poptCallbackReason reason,
1302 : const struct poptOption *opt,
1303 : const char *arg,
1304 : const void *data)
1305 : {
1306 685 : struct cli_credentials *creds = samba_cmdline_get_creds();
1307 : bool ok;
1308 :
1309 685 : switch(opt->val) {
1310 685 : case 'k': {
1311 685 : enum credentials_use_kerberos use_kerberos =
1312 : CRED_USE_KERBEROS_REQUIRED;
1313 :
1314 685 : fprintf(stderr,
1315 : "WARNING: The option -k|--kerberos is deprecated!\n");
1316 :
1317 685 : if (arg != NULL) {
1318 685 : if (strcasecmp_m(arg, "yes") == 0) {
1319 517 : use_kerberos = CRED_USE_KERBEROS_REQUIRED;
1320 168 : } else if (strcasecmp_m(arg, "no") == 0) {
1321 168 : use_kerberos = CRED_USE_KERBEROS_DISABLED;
1322 : } else {
1323 0 : fprintf(stderr,
1324 : "Error parsing -k %s. Should be "
1325 : "-k [yes|no]\n",
1326 : arg);
1327 0 : exit(1);
1328 : }
1329 : }
1330 :
1331 685 : ok = cli_credentials_set_kerberos_state(creds,
1332 : use_kerberos,
1333 : CRED_SPECIFIED);
1334 685 : if (!ok) {
1335 0 : fprintf(stderr,
1336 : "Failed to set Kerberos state to %s!\n", arg);
1337 0 : exit(1);
1338 : }
1339 :
1340 685 : break;
1341 : }
1342 : }
1343 685 : }
1344 :
1345 : static struct poptOption popt_legacy_s4[] = {
1346 : {
1347 : .argInfo = POPT_ARG_CALLBACK,
1348 : .arg = (void *)popt_legacy_s4_callback,
1349 : },
1350 : {
1351 : .longName = "kerberos",
1352 : .shortName = 'k',
1353 : .argInfo = POPT_ARG_STRING,
1354 : .val = 'k',
1355 : .descrip = "DEPRECATED: Migrate to --use-kerberos",
1356 : },
1357 : POPT_TABLEEND
1358 : };
1359 :
1360 33608 : struct poptOption *samba_cmdline_get_popt(enum smb_cmdline_popt_options opt)
1361 : {
1362 33608 : switch (opt) {
1363 2012 : case SAMBA_CMDLINE_POPT_OPT_DEBUG_ONLY:
1364 2012 : return popt_common_debug;
1365 : break;
1366 2012 : case SAMBA_CMDLINE_POPT_OPT_OPTION_ONLY:
1367 2012 : return popt_common_option;
1368 : break;
1369 137 : case SAMBA_CMDLINE_POPT_OPT_CONFIG_ONLY:
1370 137 : return popt_common_config;
1371 : break;
1372 4981 : case SAMBA_CMDLINE_POPT_OPT_SAMBA:
1373 4981 : return popt_common_samba;
1374 : break;
1375 4781 : case SAMBA_CMDLINE_POPT_OPT_CONNECTION:
1376 4781 : return popt_common_connection;
1377 : break;
1378 4604 : case SAMBA_CMDLINE_POPT_OPT_CREDENTIALS:
1379 4604 : return popt_common_credentials;
1380 : break;
1381 8973 : case SAMBA_CMDLINE_POPT_OPT_VERSION:
1382 8973 : return popt_common_version;
1383 : break;
1384 256 : case SAMBA_CMDLINE_POPT_OPT_DAEMON:
1385 256 : return popt_common_daemon;
1386 : break;
1387 1248 : case SAMBA_CMDLINE_POPT_OPT_SAMBA_LDB:
1388 1248 : return popt_common_samba_ldb;
1389 : break;
1390 2253 : case SAMBA_CMDLINE_POPT_OPT_LEGACY_S3:
1391 2253 : return popt_legacy_s3;
1392 : break;
1393 2351 : case SAMBA_CMDLINE_POPT_OPT_LEGACY_S4:
1394 2351 : return popt_legacy_s4;
1395 : break;
1396 : }
1397 :
1398 : /* Never reached */
1399 0 : return NULL;
1400 : }
|