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