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