CVE-2023-4154 dsdb/tests: Add test for SEARCH_FLAG_RODC_ATTRIBUTE behaviour
[Samba.git] / lib / cmdline / cmdline.c
blobdb962146bd27502d5ff91af3ddd09577c12a9222
1 /*
2 * Copyright (c) 2020 Andreas Schneider <asn@samba.org>
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.
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.
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/>.
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"
26 #include <samba/version.h>
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;
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;
39 /* PRIVATE */
40 bool samba_cmdline_set_talloc_ctx(TALLOC_CTX *mem_ctx)
42 if (cmdline_mem_ctx != NULL) {
43 return false;
46 cmdline_mem_ctx = mem_ctx;
47 return true;
50 TALLOC_CTX *samba_cmdline_get_talloc_ctx(void)
52 return cmdline_mem_ctx;
55 static void _samba_cmdline_talloc_log(const char *message)
57 D_ERR("%s", message);
60 bool samba_cmdline_init_common(TALLOC_CTX *mem_ctx)
62 bool ok;
64 ok = samba_cmdline_set_talloc_ctx(mem_ctx);
65 if (!ok) {
66 return false;
69 cmdline_daemon_cfg = (struct samba_cmdline_daemon_cfg) {
70 .fork = true,
73 fault_setup();
76 * Log to stderr by default.
77 * This can be changed to stdout using the option: --debug-stdout
79 setup_logging(getprogname(), DEBUG_DEFAULT_STDERR);
81 talloc_set_log_fn(_samba_cmdline_talloc_log);
82 talloc_set_abort_fn(smb_panic);
84 return true;
87 bool samba_cmdline_set_load_config_fn(samba_cmdline_load_config fn)
89 cmdline_load_config_fn = fn;
90 return true;
93 /* PUBLIC */
94 bool samba_cmdline_set_lp_ctx(struct loadparm_context *lp_ctx)
96 if (lp_ctx == NULL) {
97 return false;
99 cmdline_lp_ctx = lp_ctx;
101 return true;
104 struct loadparm_context *samba_cmdline_get_lp_ctx(void)
106 return cmdline_lp_ctx;
109 bool samba_cmdline_set_creds(struct cli_credentials *creds)
111 if (creds == NULL) {
112 return false;
115 TALLOC_FREE(cmdline_creds);
116 cmdline_creds = creds;
118 return true;
121 struct cli_credentials *samba_cmdline_get_creds(void)
123 return cmdline_creds;
126 struct samba_cmdline_daemon_cfg *samba_cmdline_get_daemon_cfg(void)
128 return &cmdline_daemon_cfg;
131 void samba_cmdline_set_machine_account_fn(
132 NTSTATUS (*fn) (struct cli_credentials *cred,
133 struct loadparm_context *lp_ctx))
135 cli_credentials_set_machine_account_fn = fn;
138 bool samba_cmdline_burn(int argc, char *argv[])
140 bool burnt = false;
141 bool found = false;
142 bool is_user = false;
143 char *p = NULL;
144 int i;
145 size_t ulen = 0;
147 for (i = 0; i < argc; i++) {
148 p = argv[i];
149 if (p == NULL) {
150 return false;
154 * Take care that this list must be in longest-match
155 * first order
157 if (strncmp(p, "-U", 2) == 0) {
158 ulen = 2;
159 found = true;
160 is_user = true;
161 } else if (strncmp(p, "--user", 6) == 0) {
162 ulen = 6;
163 found = true;
164 is_user = true;
165 } else if (strncmp(p, "--password2", 11) == 0) {
166 ulen = 11;
167 found = true;
168 } else if (strncmp(p, "--password", 10) == 0) {
169 ulen = 10;
170 found = true;
171 } else if (strncmp(p, "--newpassword", 13) == 0) {
172 ulen = 13;
173 found = true;
176 if (found) {
177 char *q = NULL;
179 if (strlen(p) == ulen) {
180 continue;
183 if (is_user) {
184 q = strchr_m(p, '%');
185 if (q != NULL) {
186 p = q;
188 } else {
189 p += ulen;
192 memset_s(p, strlen(p), '\0', strlen(p));
193 found = false;
194 is_user = false;
195 burnt = true;
198 return burnt;
201 static bool is_popt_table_end(const struct poptOption *o)
203 if (o->longName == NULL &&
204 o->shortName == 0 &&
205 o->argInfo == 0 &&
206 o->arg == NULL &&
207 o->val == 0 &&
208 o->descrip == NULL &&
209 o->argDescrip == NULL) {
210 return true;
213 return false;
216 static void find_duplicates(const struct poptOption *needle,
217 const struct poptOption *haystack,
218 size_t *count)
220 for(;
221 !is_popt_table_end(haystack);
222 haystack++) {
223 switch (haystack->argInfo) {
224 case POPT_ARG_INCLUDE_TABLE:
225 if (haystack->arg != NULL) {
226 find_duplicates(needle, haystack->arg, count);
229 break;
230 default:
231 if (needle->shortName != 0 &&
232 needle->shortName == haystack->shortName) {
233 (*count)++;
234 break;
237 if (needle->longName != NULL &&
238 haystack->longName != NULL &&
239 strequal(needle->longName, haystack->longName)) {
240 (*count)++;
241 break;
243 break;
246 if (*count > 1) {
247 return;
252 static bool cmdline_sanity_checker(const struct poptOption *current_opts,
253 const struct poptOption *full_opts)
255 const struct poptOption *o = current_opts;
257 for(;
258 !is_popt_table_end(o);
259 o++) {
260 bool ok;
262 switch (o->argInfo) {
263 case POPT_ARG_INCLUDE_TABLE:
264 if (o->arg != NULL) {
265 ok = cmdline_sanity_checker(o->arg, full_opts);
266 if (!ok) {
267 return false;
271 break;
272 default:
273 if (o->longName != NULL || o->shortName != 0) {
274 size_t count = 0;
276 find_duplicates(o, full_opts, &count);
277 if (count > 1) {
278 DBG_ERR("Duplicate option '--%s|-%c' "
279 "detected!\n",
280 o->longName,
281 o->shortName != 0 ?
282 o->shortName :
283 '-');
284 return false;
288 break;
292 return true;
295 bool samba_cmdline_sanity_check(const struct poptOption *opts)
297 return cmdline_sanity_checker(opts, opts);
300 poptContext samba_popt_get_context(const char * name,
301 int argc, const char ** argv,
302 const struct poptOption * options,
303 unsigned int flags)
305 #ifdef DEVELOPER
306 bool ok;
308 ok = samba_cmdline_sanity_check(options);
309 if (!ok) {
310 return NULL;
312 #endif
313 process_save_binary_name(name);
314 return poptGetContext(name, argc, argv, options, flags);
317 /**********************************************************
318 * COMMON SAMBA POPT
319 **********************************************************/
321 static bool log_to_file;
323 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)
329 bool ok = false;
330 char *new_logfile = talloc_asprintf(mem_ctx,
331 "%s/log.%s",
332 log_basename,
333 process_name);
334 if (new_logfile == NULL) {
335 return false;
338 if (from_cmdline) {
339 ok = lpcfg_set_cmdline(lp_ctx,
340 "log file",
341 new_logfile);
342 } else {
343 ok = lpcfg_do_global_parameter(lp_ctx,
344 "log file",
345 new_logfile);
347 if (!ok) {
348 fprintf(stderr,
349 "Failed to set log to %s\n",
350 new_logfile);
351 TALLOC_FREE(new_logfile);
352 return false;
354 debug_set_logfile(new_logfile);
355 TALLOC_FREE(new_logfile);
357 return true;
360 static void popt_samba_callback(poptContext popt_ctx,
361 enum poptCallbackReason reason,
362 const struct poptOption *opt,
363 const char *arg, const void *data)
365 TALLOC_CTX *mem_ctx = samba_cmdline_get_talloc_ctx();
366 struct loadparm_context *lp_ctx = samba_cmdline_get_lp_ctx();
367 const char *pname = NULL;
368 bool ok;
370 /* Find out basename of current program */
371 pname = getprogname();
373 if (reason == POPT_CALLBACK_REASON_PRE) {
374 if (lp_ctx == NULL) {
375 fprintf(stderr,
376 "Command line parsing not initialized!\n");
377 exit(1);
379 ok = set_logfile(mem_ctx,
380 lp_ctx,
381 get_dyn_LOGFILEBASE(),
382 pname,
383 false);
384 if (!ok) {
385 fprintf(stderr,
386 "Failed to set log file for %s\n",
387 pname);
388 exit(1);
390 return;
393 if (reason == POPT_CALLBACK_REASON_POST) {
394 ok = cmdline_load_config_fn();
395 if (!ok) {
396 fprintf(stderr,
397 "%s - Failed to load config file!\n",
398 getprogname());
399 exit(1);
402 if (log_to_file) {
403 const struct loadparm_substitution *lp_sub =
404 lpcfg_noop_substitution();
405 char *logfile = NULL;
407 logfile = lpcfg_logfile(lp_ctx, lp_sub, mem_ctx);
408 if (logfile == NULL) {
409 fprintf(stderr,
410 "Failed to setup logging to file!");
411 exit(1);
413 debug_set_logfile(logfile);
414 setup_logging(logfile, DEBUG_FILE);
415 TALLOC_FREE(logfile);
418 return;
421 switch(opt->val) {
422 case OPT_LEAK_REPORT:
423 talloc_enable_leak_report();
424 break;
425 case OPT_LEAK_REPORT_FULL:
426 talloc_enable_leak_report_full();
427 break;
428 case OPT_OPTION:
429 if (arg != NULL) {
430 ok = lpcfg_set_option(lp_ctx, arg);
431 if (!ok) {
432 fprintf(stderr, "Error setting option '%s'\n", arg);
433 exit(1);
436 break;
437 case 'd':
438 if (arg != NULL) {
439 ok = lpcfg_set_cmdline(lp_ctx, "log level", arg);
440 if (!ok) {
441 fprintf(stderr,
442 "Failed to set debug level to: %s\n",
443 arg);
444 exit(1);
447 break;
448 case OPT_DEBUG_STDOUT:
449 setup_logging(pname, DEBUG_STDOUT);
450 break;
451 case OPT_CONFIGFILE:
452 if (arg != NULL) {
453 set_dyn_CONFIGFILE(arg);
455 break;
456 case 'l':
457 if (arg != NULL) {
458 ok = set_logfile(mem_ctx, lp_ctx, arg, pname, true);
459 if (!ok) {
460 fprintf(stderr,
461 "Failed to set log file for %s\n",
462 arg);
463 exit(1);
465 log_to_file = true;
467 set_dyn_LOGFILEBASE(arg);
469 break;
473 static struct poptOption popt_common_debug[] = {
475 .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
476 .arg = (void *)popt_samba_callback,
479 .longName = "debuglevel",
480 .shortName = 'd',
481 .argInfo = POPT_ARG_STRING,
482 .val = 'd',
483 .descrip = "Set debug level",
484 .argDescrip = "DEBUGLEVEL",
487 .longName = "debug-stdout",
488 .argInfo = POPT_ARG_NONE,
489 .val = OPT_DEBUG_STDOUT,
490 .descrip = "Send debug output to standard output",
492 POPT_TABLEEND
495 static struct poptOption popt_common_option[] = {
497 .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
498 .arg = (void *)popt_samba_callback,
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",
507 POPT_TABLEEND
510 static struct poptOption popt_common_config[] = {
512 .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
513 .arg = (void *)popt_samba_callback,
516 .longName = "configfile",
517 .argInfo = POPT_ARG_STRING,
518 .val = OPT_CONFIGFILE,
519 .descrip = "Use alternative configuration file",
520 .argDescrip = "CONFIGFILE",
522 POPT_TABLEEND
525 static struct poptOption popt_common_samba[] = {
527 .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
528 .arg = (void *)popt_samba_callback,
531 .longName = "debuglevel",
532 .shortName = 'd',
533 .argInfo = POPT_ARG_STRING,
534 .val = 'd',
535 .descrip = "Set debug level",
536 .argDescrip = "DEBUGLEVEL",
539 .longName = "debug-stdout",
540 .argInfo = POPT_ARG_NONE,
541 .val = OPT_DEBUG_STDOUT,
542 .descrip = "Send debug output to standard output",
545 .longName = "configfile",
546 .shortName = 's',
547 .argInfo = POPT_ARG_STRING,
548 .val = OPT_CONFIGFILE,
549 .descrip = "Use alternative configuration file",
550 .argDescrip = "CONFIGFILE",
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",
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",
568 .longName = "leak-report",
569 .argInfo = POPT_ARG_NONE,
570 .val = OPT_LEAK_REPORT,
571 .descrip = "enable talloc leak reporting on exit",
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",
579 POPT_TABLEEND
582 static struct poptOption popt_common_samba_ldb[] = {
584 .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
585 .arg = (void *)popt_samba_callback,
588 .longName = "debuglevel",
589 .shortName = 'd',
590 .argInfo = POPT_ARG_STRING,
591 .val = 'd',
592 .descrip = "Set debug level",
593 .argDescrip = "DEBUGLEVEL",
596 .longName = "debug-stdout",
597 .argInfo = POPT_ARG_NONE,
598 .val = OPT_DEBUG_STDOUT,
599 .descrip = "Send debug output to standard output",
602 .longName = "configfile",
603 .argInfo = POPT_ARG_STRING,
604 .val = OPT_CONFIGFILE,
605 .descrip = "Use alternative configuration file",
606 .argDescrip = "CONFIGFILE",
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",
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",
624 .longName = "leak-report",
625 .argInfo = POPT_ARG_NONE,
626 .val = OPT_LEAK_REPORT,
627 .descrip = "enable talloc leak reporting on exit",
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",
635 POPT_TABLEEND
638 /**********************************************************
639 * CONNECTION POPT
640 **********************************************************/
642 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)
648 struct loadparm_context *lp_ctx = cmdline_lp_ctx;
650 if (reason == POPT_CALLBACK_REASON_PRE) {
651 if (lp_ctx == NULL) {
652 fprintf(stderr,
653 "Command line parsing not initialized!\n");
654 exit(1);
656 return;
659 switch(opt->val) {
660 case 'O':
661 if (arg != NULL) {
662 lpcfg_set_cmdline(lp_ctx, "socket options", arg);
664 break;
665 case 'R':
666 if (arg != NULL) {
667 lpcfg_set_cmdline(lp_ctx, "name resolve order", arg);
669 break;
670 case 'm':
671 if (arg != NULL) {
672 lpcfg_set_cmdline(lp_ctx, "client max protocol", arg);
674 break;
675 case OPT_NETBIOS_SCOPE:
676 if (arg != NULL) {
677 lpcfg_set_cmdline(lp_ctx, "netbios scope", arg);
679 break;
680 case 'n':
681 if (arg != NULL) {
682 lpcfg_set_cmdline(lp_ctx, "netbios name", arg);
684 break;
685 case 'W':
686 if (arg != NULL) {
687 lpcfg_set_cmdline(lp_ctx, "workgroup", arg);
689 break;
690 case 'r':
691 if (arg != NULL) {
692 lpcfg_set_cmdline(lp_ctx, "realm", arg);
694 break;
698 static struct poptOption popt_common_connection[] = {
700 .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE,
701 .arg = (void *)popt_connection_callback,
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",
712 .longName = "socket-options",
713 .shortName = 'O',
714 .argInfo = POPT_ARG_STRING,
715 .val = 'O',
716 .descrip = "socket options to use",
717 .argDescrip = "SOCKETOPTIONS",
720 .longName = "max-protocol",
721 .shortName = 'm',
722 .argInfo = POPT_ARG_STRING,
723 .val = 'm',
724 .descrip = "Set max protocol level",
725 .argDescrip = "MAXPROTOCOL",
728 .longName = "netbiosname",
729 .shortName = 'n',
730 .argInfo = POPT_ARG_STRING,
731 .val = 'n',
732 .descrip = "Primary netbios name",
733 .argDescrip = "NETBIOSNAME",
736 .longName = "netbios-scope",
737 .argInfo = POPT_ARG_STRING,
738 .val = OPT_NETBIOS_SCOPE,
739 .descrip = "Use this Netbios scope",
740 .argDescrip = "SCOPE",
743 .longName = "workgroup",
744 .shortName = 'W',
745 .argInfo = POPT_ARG_STRING,
746 .val = 'W',
747 .descrip = "Set the workgroup name",
748 .argDescrip = "WORKGROUP",
751 .longName = "realm",
752 .argInfo = POPT_ARG_STRING,
753 .val = 'r',
754 .descrip = "Set the realm name",
755 .argDescrip = "REALM",
757 POPT_TABLEEND
760 /**********************************************************
761 * CREDENTIALS POPT
762 **********************************************************/
764 static bool skip_password_callback;
765 static bool machine_account_pending;
767 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)
773 struct loadparm_context *lp_ctx = samba_cmdline_get_lp_ctx();
774 struct cli_credentials *creds = samba_cmdline_get_creds();
775 bool ok;
777 if (reason == POPT_CALLBACK_REASON_PRE) {
778 if (creds == NULL) {
779 fprintf(stderr,
780 "Command line parsing not initialized!\n");
781 exit(1);
783 return;
786 if (reason == POPT_CALLBACK_REASON_POST) {
787 const char *username = NULL;
788 enum credentials_obtained username_obtained =
789 CRED_UNINITIALISED;
790 enum credentials_obtained password_obtained =
791 CRED_UNINITIALISED;
794 * This calls cli_credentials_set_conf() to get the defaults
795 * form smb.conf and set the winbind separator.
797 * Just warn that we can't read the smb.conf. There might not be
798 * one available or we want to ignore it.
800 ok = cli_credentials_guess(creds, lp_ctx);
801 if (!ok) {
802 fprintf(stderr,
803 "Unable to read defaults from smb.conf\n");
806 (void)cli_credentials_get_password_and_obtained(creds,
807 &password_obtained);
808 if (!skip_password_callback &&
809 password_obtained < CRED_CALLBACK) {
810 ok = cli_credentials_set_cmdline_callbacks(creds);
811 if (!ok) {
812 fprintf(stderr,
813 "Failed to set cmdline password "
814 "callback\n");
815 exit(1);
819 if (machine_account_pending) {
820 NTSTATUS status;
822 status = cli_credentials_set_machine_account_fn(
823 creds, lp_ctx);
824 if (!NT_STATUS_IS_OK(status)) {
825 fprintf(stderr,
826 "Failed to set machine account: %s\n",
827 nt_errstr(status));
828 exit(1);
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.
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.
843 username =
844 cli_credentials_get_username_and_obtained(
845 creds, &username_obtained);
846 if (username_obtained == CRED_SPECIFIED &&
847 username != NULL && username[0] != '\0') {
848 cli_credentials_parse_string(creds,
849 username,
850 CRED_SPECIFIED);
853 return;
856 switch(opt->val) {
857 case 'U':
858 if (arg != NULL) {
859 cli_credentials_parse_string(creds,
860 arg,
861 CRED_SPECIFIED);
863 break;
864 case OPT_PASSWORD:
865 if (arg != NULL) {
866 ok = cli_credentials_set_password(creds,
867 arg,
868 CRED_SPECIFIED);
869 if (!ok) {
870 fprintf(stderr,
871 "Failed to set password!\n");
872 exit(1);
875 skip_password_callback = true;
877 break;
878 case OPT_NT_HASH:
879 cli_credentials_set_password_will_be_nt_hash(creds, true);
880 break;
881 case 'A':
882 if (arg != NULL) {
883 ok = cli_credentials_parse_file(creds,
884 arg,
885 CRED_SPECIFIED);
886 if (!ok) {
887 fprintf(stderr,
888 "Failed to set parse authentication file!\n");
889 exit(1);
891 skip_password_callback = true;
893 break;
894 case 'N':
895 ok = cli_credentials_set_password(creds,
896 NULL,
897 CRED_SPECIFIED);
898 if (!ok) {
899 fprintf(stderr,
900 "Failed to set password!\n");
901 exit(1);
903 skip_password_callback = true;
904 break;
905 case 'P':
907 * Later, after this is all over, get the machine account
908 * details from the secrets.(l|t)db.
910 machine_account_pending = true;
911 break;
912 case OPT_SIMPLE_BIND_DN:
913 if (arg != NULL) {
914 ok = cli_credentials_set_bind_dn(creds, arg);
915 if (!ok) {
916 fprintf(stderr,
917 "Failed to set bind DN!\n");
918 exit(1);
921 break;
922 case OPT_USE_KERBEROS: {
923 int32_t use_kerberos = INT_MIN;
924 if (arg == NULL) {
925 fprintf(stderr,
926 "Failed to parse "
927 "--use-kerberos=desired|required|off: "
928 "Missing argument\n");
929 exit(1);
932 use_kerberos = lpcfg_parse_enum_vals("client use kerberos",
933 arg);
934 if (use_kerberos == INT_MIN) {
935 fprintf(stderr,
936 "Failed to parse "
937 "--use-kerberos=desired|required|off: "
938 "Invalid argument\n");
939 exit(1);
942 ok = cli_credentials_set_kerberos_state(creds,
943 use_kerberos,
944 CRED_SPECIFIED);
945 if (!ok) {
946 fprintf(stderr,
947 "Failed to set Kerberos state to %s!\n", arg);
948 exit(1);
950 break;
952 case OPT_USE_KERBEROS_CCACHE: {
953 const char *error_string = NULL;
954 int rc;
956 if (arg == NULL) {
957 fprintf(stderr,
958 "Failed to parse --use-krb5-ccache=CCACHE: "
959 "Missing argument\n");
960 exit(1);
963 ok = cli_credentials_set_kerberos_state(creds,
964 CRED_USE_KERBEROS_REQUIRED,
965 CRED_SPECIFIED);
966 if (!ok) {
967 fprintf(stderr,
968 "Failed to set Kerberos state to %s!\n", arg);
969 exit(1);
972 rc = cli_credentials_set_ccache(creds,
973 lp_ctx,
974 arg,
975 CRED_SPECIFIED,
976 &error_string);
977 if (rc != 0) {
978 fprintf(stderr,
979 "Error reading krb5 credentials cache: '%s'"
980 " - %s\n",
981 arg,
982 error_string);
983 exit(1);
986 skip_password_callback = true;
987 break;
989 case OPT_USE_WINBIND_CCACHE:
991 uint32_t gensec_features;
993 gensec_features = cli_credentials_get_gensec_features(creds);
994 gensec_features |= GENSEC_FEATURE_NTLM_CCACHE;
996 ok = cli_credentials_set_gensec_features(creds,
997 gensec_features,
998 CRED_SPECIFIED);
999 if (!ok) {
1000 fprintf(stderr,
1001 "Failed to set gensec feature!\n");
1002 exit(1);
1005 skip_password_callback = true;
1006 break;
1008 case OPT_CLIENT_PROTECTION: {
1009 uint32_t gensec_features;
1010 enum smb_signing_setting signing_state =
1011 SMB_SIGNING_OFF;
1012 enum smb_encryption_setting encryption_state =
1013 SMB_ENCRYPTION_OFF;
1015 if (arg == NULL) {
1016 fprintf(stderr,
1017 "Failed to parse "
1018 "--client-protection=sign|encrypt|off: "
1019 "Missing argument\n");
1020 exit(1);
1023 gensec_features =
1024 cli_credentials_get_gensec_features(
1025 creds);
1027 if (strequal(arg, "off")) {
1028 gensec_features &=
1029 ~(GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL);
1031 signing_state = SMB_SIGNING_OFF;
1032 encryption_state = SMB_ENCRYPTION_OFF;
1033 } else if (strequal(arg, "sign")) {
1034 gensec_features |= GENSEC_FEATURE_SIGN;
1036 signing_state = SMB_SIGNING_REQUIRED;
1037 encryption_state = SMB_ENCRYPTION_OFF;
1038 } else if (strequal(arg, "encrypt")) {
1039 gensec_features |= GENSEC_FEATURE_SEAL;
1041 signing_state = SMB_SIGNING_REQUIRED;
1042 encryption_state = SMB_ENCRYPTION_REQUIRED;
1043 } else {
1044 fprintf(stderr,
1045 "Failed to parse --client-protection\n");
1046 exit(1);
1049 ok = cli_credentials_set_gensec_features(creds,
1050 gensec_features,
1051 CRED_SPECIFIED);
1052 if (!ok) {
1053 fprintf(stderr,
1054 "Failed to set gensec feature!\n");
1055 exit(1);
1058 ok = cli_credentials_set_smb_signing(creds,
1059 signing_state,
1060 CRED_SPECIFIED);
1061 if (!ok) {
1062 fprintf(stderr,
1063 "Failed to set smb signing!\n");
1064 exit(1);
1067 ok = cli_credentials_set_smb_encryption(creds,
1068 encryption_state,
1069 CRED_SPECIFIED);
1070 if (!ok) {
1071 fprintf(stderr,
1072 "Failed to set smb encryption!\n");
1073 exit(1);
1075 break;
1077 } /* switch */
1080 static struct poptOption popt_common_credentials[] = {
1082 .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
1083 .arg = (void *)popt_common_credentials_callback,
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]",
1094 .longName = "no-pass",
1095 .shortName = 'N',
1096 .argInfo = POPT_ARG_NONE,
1097 .val = 'N',
1098 .descrip = "Don't ask for a password",
1101 .longName = "password",
1102 .argInfo = POPT_ARG_STRING,
1103 .val = OPT_PASSWORD,
1104 .descrip = "Password",
1107 .longName = "pw-nt-hash",
1108 .argInfo = POPT_ARG_NONE,
1109 .val = OPT_NT_HASH,
1110 .descrip = "The supplied password is the NT hash",
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",
1121 .longName = "machine-pass",
1122 .shortName = 'P',
1123 .argInfo = POPT_ARG_NONE,
1124 .val = 'P',
1125 .descrip = "Use stored machine account password",
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",
1135 .longName = "use-kerberos",
1136 .argInfo = POPT_ARG_STRING,
1137 .val = OPT_USE_KERBEROS,
1138 .descrip = "Use Kerberos authentication",
1139 .argDescrip = "desired|required|off",
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",
1149 .longName = "use-winbind-ccache",
1150 .argInfo = POPT_ARG_NONE,
1151 .val = OPT_USE_WINBIND_CCACHE,
1152 .descrip = "Use the winbind ccache for authentication",
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",
1161 POPT_TABLEEND
1164 /**********************************************************
1165 * VERSION POPT
1166 **********************************************************/
1168 static void popt_version_callback(poptContext ctx,
1169 enum poptCallbackReason reason,
1170 const struct poptOption *opt,
1171 const char *arg,
1172 const void *data)
1174 switch(opt->val) {
1175 case 'V':
1176 printf("Version %s\n", SAMBA_VERSION_STRING);
1177 exit(0);
1181 static struct poptOption popt_common_version[] = {
1183 .argInfo = POPT_ARG_CALLBACK,
1184 .arg = (void *)popt_version_callback,
1187 .longName = "version",
1188 .shortName = 'V',
1189 .argInfo = POPT_ARG_NONE,
1190 .val = 'V',
1191 .descrip = "Print version",
1193 POPT_TABLEEND
1196 /**********************************************************
1197 * DAEMON POPT
1198 **********************************************************/
1200 static void popt_daemon_callback(poptContext ctx,
1201 enum poptCallbackReason reason,
1202 const struct poptOption *opt,
1203 const char *arg,
1204 const void *data)
1206 switch(opt->val) {
1207 case OPT_DAEMON:
1208 cmdline_daemon_cfg.daemon = true;
1209 break;
1210 case OPT_INTERACTIVE:
1211 cmdline_daemon_cfg.interactive = true;
1212 cmdline_daemon_cfg.fork = false;
1213 break;
1214 case OPT_FORK:
1215 cmdline_daemon_cfg.fork = false;
1216 break;
1217 case OPT_NO_PROCESS_GROUP:
1218 cmdline_daemon_cfg.no_process_group = true;
1219 break;
1223 static struct poptOption popt_common_daemon[] = {
1225 .argInfo = POPT_ARG_CALLBACK,
1226 .arg = (void *)popt_daemon_callback
1229 .longName = "daemon",
1230 .shortName = 'D',
1231 .argInfo = POPT_ARG_NONE,
1232 .arg = NULL,
1233 .val = OPT_DAEMON,
1234 .descrip = "Become a daemon (default)" ,
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",
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.)",
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" ,
1260 POPT_TABLEEND
1263 /**********************************************************
1264 * LEGACY S3 POPT
1265 **********************************************************/
1267 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)
1273 struct cli_credentials *creds = samba_cmdline_get_creds();
1274 bool ok;
1276 switch(opt->val) {
1277 case 'k':
1278 fprintf(stderr,
1279 "WARNING: The option -k|--kerberos is deprecated!\n");
1281 ok = cli_credentials_set_kerberos_state(creds,
1282 CRED_USE_KERBEROS_REQUIRED,
1283 CRED_SPECIFIED);
1284 if (!ok) {
1285 fprintf(stderr,
1286 "Failed to set Kerberos state to %s!\n", arg);
1287 exit(1);
1290 skip_password_callback = true;
1291 break;
1295 /* We allow '-k yes' too. */
1296 static struct poptOption popt_legacy_s3[] = {
1298 .argInfo = POPT_ARG_CALLBACK,
1299 .arg = (void *)popt_legacy_s3_callback,
1302 .longName = "kerberos",
1303 .shortName = 'k',
1304 .argInfo = POPT_ARG_NONE,
1305 .val = 'k',
1306 .descrip = "DEPRECATED: Migrate to --use-kerberos",
1308 POPT_TABLEEND
1311 /**********************************************************
1312 * LEGACY S4 POPT
1313 **********************************************************/
1315 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)
1321 struct cli_credentials *creds = samba_cmdline_get_creds();
1322 bool ok;
1324 switch(opt->val) {
1325 case 'k': {
1326 enum credentials_use_kerberos use_kerberos =
1327 CRED_USE_KERBEROS_REQUIRED;
1329 fprintf(stderr,
1330 "WARNING: The option -k|--kerberos is deprecated!\n");
1332 if (arg != NULL) {
1333 if (strcasecmp_m(arg, "yes") == 0) {
1334 use_kerberos = CRED_USE_KERBEROS_REQUIRED;
1335 } else if (strcasecmp_m(arg, "no") == 0) {
1336 use_kerberos = CRED_USE_KERBEROS_DISABLED;
1337 } else {
1338 fprintf(stderr,
1339 "Error parsing -k %s. Should be "
1340 "-k [yes|no]\n",
1341 arg);
1342 exit(1);
1346 ok = cli_credentials_set_kerberos_state(creds,
1347 use_kerberos,
1348 CRED_SPECIFIED);
1349 if (!ok) {
1350 fprintf(stderr,
1351 "Failed to set Kerberos state to %s!\n", arg);
1352 exit(1);
1355 break;
1360 static struct poptOption popt_legacy_s4[] = {
1362 .argInfo = POPT_ARG_CALLBACK,
1363 .arg = (void *)popt_legacy_s4_callback,
1366 .longName = "kerberos",
1367 .shortName = 'k',
1368 .argInfo = POPT_ARG_STRING,
1369 .val = 'k',
1370 .descrip = "DEPRECATED: Migrate to --use-kerberos",
1372 POPT_TABLEEND
1375 struct poptOption *samba_cmdline_get_popt(enum smb_cmdline_popt_options opt)
1377 switch (opt) {
1378 case SAMBA_CMDLINE_POPT_OPT_DEBUG_ONLY:
1379 return popt_common_debug;
1380 break;
1381 case SAMBA_CMDLINE_POPT_OPT_OPTION_ONLY:
1382 return popt_common_option;
1383 break;
1384 case SAMBA_CMDLINE_POPT_OPT_CONFIG_ONLY:
1385 return popt_common_config;
1386 break;
1387 case SAMBA_CMDLINE_POPT_OPT_SAMBA:
1388 return popt_common_samba;
1389 break;
1390 case SAMBA_CMDLINE_POPT_OPT_CONNECTION:
1391 return popt_common_connection;
1392 break;
1393 case SAMBA_CMDLINE_POPT_OPT_CREDENTIALS:
1394 return popt_common_credentials;
1395 break;
1396 case SAMBA_CMDLINE_POPT_OPT_VERSION:
1397 return popt_common_version;
1398 break;
1399 case SAMBA_CMDLINE_POPT_OPT_DAEMON:
1400 return popt_common_daemon;
1401 break;
1402 case SAMBA_CMDLINE_POPT_OPT_SAMBA_LDB:
1403 return popt_common_samba_ldb;
1404 break;
1405 case SAMBA_CMDLINE_POPT_OPT_LEGACY_S3:
1406 return popt_legacy_s3;
1407 break;
1408 case SAMBA_CMDLINE_POPT_OPT_LEGACY_S4:
1409 return popt_legacy_s4;
1410 break;
1413 /* Never reached */
1414 return NULL;