CVE-2022-2031 s4:kdc: Reject tickets during the last two minutes of their life
[Samba.git] / lib / cmdline / cmdline.c
blob0c0b3ead7daf4dc57e5bef083a8046f1f0ae7e63
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"
25 #include <samba/version.h>
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;
33 static NTSTATUS (*cli_credentials_set_machine_account_fn)(
34 struct cli_credentials *cred,
35 struct loadparm_context *lp_ctx) =
36 cli_credentials_set_machine_account;
38 /* PRIVATE */
39 bool samba_cmdline_set_talloc_ctx(TALLOC_CTX *mem_ctx)
41 if (cmdline_mem_ctx != NULL) {
42 return false;
45 cmdline_mem_ctx = mem_ctx;
46 return true;
49 TALLOC_CTX *samba_cmdline_get_talloc_ctx(void)
51 return cmdline_mem_ctx;
54 static void _samba_cmdline_talloc_log(const char *message)
56 D_ERR("%s", message);
59 bool samba_cmdline_init_common(TALLOC_CTX *mem_ctx)
61 bool ok;
63 ok = samba_cmdline_set_talloc_ctx(mem_ctx);
64 if (!ok) {
65 return false;
68 cmdline_daemon_cfg = (struct samba_cmdline_daemon_cfg) {
69 .fork = true,
72 fault_setup();
75 * Log to stdout by default.
76 * This can be changed to stderr using the option: --debug-stdout
78 setup_logging(getprogname(), DEBUG_DEFAULT_STDERR);
80 talloc_set_log_fn(_samba_cmdline_talloc_log);
81 talloc_set_abort_fn(smb_panic);
83 return true;
86 bool samba_cmdline_set_load_config_fn(samba_cmdline_load_config fn)
88 cmdline_load_config_fn = fn;
89 return true;
92 /* PUBLIC */
93 bool samba_cmdline_set_lp_ctx(struct loadparm_context *lp_ctx)
95 if (lp_ctx == NULL) {
96 return false;
98 cmdline_lp_ctx = lp_ctx;
100 return true;
103 struct loadparm_context *samba_cmdline_get_lp_ctx(void)
105 return cmdline_lp_ctx;
108 bool samba_cmdline_set_creds(struct cli_credentials *creds)
110 if (creds == NULL) {
111 return false;
114 TALLOC_FREE(cmdline_creds);
115 cmdline_creds = creds;
117 return true;
120 struct cli_credentials *samba_cmdline_get_creds(void)
122 return cmdline_creds;
125 struct samba_cmdline_daemon_cfg *samba_cmdline_get_daemon_cfg(void)
127 return &cmdline_daemon_cfg;
130 void samba_cmdline_set_machine_account_fn(
131 NTSTATUS (*fn) (struct cli_credentials *cred,
132 struct loadparm_context *lp_ctx))
134 cli_credentials_set_machine_account_fn = fn;
137 void samba_cmdline_burn(int argc, char *argv[])
139 bool found = false;
140 bool is_user = false;
141 char *p = NULL;
142 int i;
143 size_t ulen = 0;
145 for (i = 0; i < argc; i++) {
146 p = argv[i];
147 if (p == NULL) {
148 return;
151 if (strncmp(p, "-U", 2) == 0) {
152 ulen = 2;
153 found = true;
154 is_user = true;
155 } else if (strncmp(p, "--user", 6) == 0) {
156 ulen = 6;
157 found = true;
158 is_user = true;
159 } else if (strncmp(p, "--password", 10) == 0) {
160 ulen = 10;
161 found = true;
164 if (found) {
165 char *q = NULL;
167 if (strlen(p) == ulen) {
168 continue;
171 if (is_user) {
172 q = strchr_m(p, '%');
173 if (q != NULL) {
174 p = q;
176 } else {
177 p += ulen;
180 memset_s(p, strlen(p), '\0', strlen(p));
181 found = false;
182 is_user = false;
187 static bool is_popt_table_end(const struct poptOption *o)
189 if (o->longName == NULL &&
190 o->shortName == 0 &&
191 o->argInfo == 0 &&
192 o->arg == NULL &&
193 o->val == 0 &&
194 o->descrip == NULL &&
195 o->argDescrip == NULL) {
196 return true;
199 return false;
202 static void find_duplicates(const struct poptOption *needle,
203 const struct poptOption *haystack,
204 size_t *count)
206 for(;
207 !is_popt_table_end(haystack);
208 haystack++) {
209 switch (haystack->argInfo) {
210 case POPT_ARG_INCLUDE_TABLE:
211 if (haystack->arg != NULL) {
212 find_duplicates(needle, haystack->arg, count);
215 break;
216 default:
217 if (needle->shortName != 0 &&
218 needle->shortName == haystack->shortName) {
219 (*count)++;
220 break;
223 if (needle->longName != NULL &&
224 haystack->longName != NULL &&
225 strequal(needle->longName, haystack->longName)) {
226 (*count)++;
227 break;
229 break;
232 if (*count > 1) {
233 return;
238 static bool cmdline_sanity_checker(const struct poptOption *current_opts,
239 const struct poptOption *full_opts)
241 const struct poptOption *o = current_opts;
243 for(;
244 !is_popt_table_end(o);
245 o++) {
246 bool ok;
248 switch (o->argInfo) {
249 case POPT_ARG_INCLUDE_TABLE:
250 if (o->arg != NULL) {
251 ok = cmdline_sanity_checker(o->arg, full_opts);
252 if (!ok) {
253 return false;
257 break;
258 default:
259 if (o->longName != NULL || o->shortName != 0) {
260 size_t count = 0;
262 find_duplicates(o, full_opts, &count);
263 if (count > 1) {
264 DBG_ERR("Duplicate option '--%s|-%c' "
265 "detected!\n",
266 o->longName,
267 o->shortName != 0 ?
268 o->shortName :
269 '-');
270 return false;
274 break;
278 return true;
281 bool samba_cmdline_sanity_check(const struct poptOption *opts)
283 return cmdline_sanity_checker(opts, opts);
286 poptContext samba_popt_get_context(const char * name,
287 int argc, const char ** argv,
288 const struct poptOption * options,
289 unsigned int flags)
291 #ifdef DEVELOPER
292 bool ok;
294 ok = samba_cmdline_sanity_check(options);
295 if (!ok) {
296 return NULL;
298 #endif
299 return poptGetContext(name, argc, argv, options, flags);
302 /**********************************************************
303 * COMMON SAMBA POPT
304 **********************************************************/
306 static bool log_to_file;
308 static bool set_logfile(TALLOC_CTX *mem_ctx,
309 struct loadparm_context *lp_ctx,
310 const char *log_basename,
311 const char *process_name,
312 bool from_cmdline)
314 bool ok = false;
315 char *new_logfile = talloc_asprintf(mem_ctx,
316 "%s/log.%s",
317 log_basename,
318 process_name);
319 if (new_logfile == NULL) {
320 return false;
323 if (from_cmdline) {
324 ok = lpcfg_set_cmdline(lp_ctx,
325 "log file",
326 new_logfile);
327 } else {
328 ok = lpcfg_do_global_parameter(lp_ctx,
329 "log file",
330 new_logfile);
332 if (!ok) {
333 fprintf(stderr,
334 "Failed to set log to %s\n",
335 new_logfile);
336 TALLOC_FREE(new_logfile);
337 return false;
339 debug_set_logfile(new_logfile);
340 TALLOC_FREE(new_logfile);
342 return true;
345 static void popt_samba_callback(poptContext popt_ctx,
346 enum poptCallbackReason reason,
347 const struct poptOption *opt,
348 const char *arg, const void *data)
350 TALLOC_CTX *mem_ctx = samba_cmdline_get_talloc_ctx();
351 struct loadparm_context *lp_ctx = samba_cmdline_get_lp_ctx();
352 const char *pname = NULL;
353 bool ok;
355 /* Find out basename of current program */
356 pname = getprogname();
358 if (reason == POPT_CALLBACK_REASON_PRE) {
359 if (lp_ctx == NULL) {
360 fprintf(stderr,
361 "Command line parsing not initialized!\n");
362 exit(1);
364 ok = set_logfile(mem_ctx,
365 lp_ctx,
366 get_dyn_LOGFILEBASE(),
367 pname,
368 false);
369 if (!ok) {
370 fprintf(stderr,
371 "Failed to set log file for %s\n",
372 pname);
373 exit(1);
375 return;
378 if (reason == POPT_CALLBACK_REASON_POST) {
379 ok = cmdline_load_config_fn();
380 if (!ok) {
381 fprintf(stderr,
382 "%s - Failed to load config file!\n",
383 getprogname());
384 exit(1);
387 if (log_to_file) {
388 const struct loadparm_substitution *lp_sub =
389 lpcfg_noop_substitution();
390 char *logfile = NULL;
392 logfile = lpcfg_logfile(lp_ctx, lp_sub, mem_ctx);
393 if (logfile == NULL) {
394 fprintf(stderr,
395 "Failed to setup logging to file!");
396 exit(1);
398 debug_set_logfile(logfile);
399 setup_logging(logfile, DEBUG_FILE);
400 TALLOC_FREE(logfile);
403 return;
406 switch(opt->val) {
407 case OPT_LEAK_REPORT:
408 talloc_enable_leak_report();
409 break;
410 case OPT_LEAK_REPORT_FULL:
411 talloc_enable_leak_report_full();
412 break;
413 case OPT_OPTION:
414 if (arg != NULL) {
415 ok = lpcfg_set_option(lp_ctx, arg);
416 if (!ok) {
417 fprintf(stderr, "Error setting option '%s'\n", arg);
418 exit(1);
421 break;
422 case 'd':
423 if (arg != NULL) {
424 ok = lpcfg_set_cmdline(lp_ctx, "log level", arg);
425 if (!ok) {
426 fprintf(stderr,
427 "Failed to set debug level to: %s\n",
428 arg);
429 exit(1);
432 break;
433 case OPT_DEBUG_STDOUT:
434 setup_logging(pname, DEBUG_STDOUT);
435 break;
436 case OPT_CONFIGFILE:
437 if (arg != NULL) {
438 set_dyn_CONFIGFILE(arg);
440 break;
441 case 'l':
442 if (arg != NULL) {
443 ok = set_logfile(mem_ctx, lp_ctx, arg, pname, true);
444 if (!ok) {
445 fprintf(stderr,
446 "Failed to set log file for %s\n",
447 arg);
448 exit(1);
450 log_to_file = true;
452 set_dyn_LOGFILEBASE(arg);
454 break;
458 static struct poptOption popt_common_debug[] = {
460 .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
461 .arg = (void *)popt_samba_callback,
464 .longName = "debuglevel",
465 .shortName = 'd',
466 .argInfo = POPT_ARG_STRING,
467 .val = 'd',
468 .descrip = "Set debug level",
469 .argDescrip = "DEBUGLEVEL",
472 .longName = "debug-stdout",
473 .argInfo = POPT_ARG_NONE,
474 .val = OPT_DEBUG_STDOUT,
475 .descrip = "Send debug output to standard output",
477 POPT_TABLEEND
480 static struct poptOption popt_common_option[] = {
482 .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
483 .arg = (void *)popt_samba_callback,
486 .longName = "option",
487 .argInfo = POPT_ARG_STRING,
488 .val = OPT_OPTION,
489 .descrip = "Set smb.conf option from command line",
490 .argDescrip = "name=value",
492 POPT_TABLEEND
495 static struct poptOption popt_common_config[] = {
497 .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
498 .arg = (void *)popt_samba_callback,
501 .longName = "configfile",
502 .argInfo = POPT_ARG_STRING,
503 .val = OPT_CONFIGFILE,
504 .descrip = "Use alternative configuration file",
505 .argDescrip = "CONFIGFILE",
507 POPT_TABLEEND
510 static struct poptOption popt_common_samba[] = {
512 .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
513 .arg = (void *)popt_samba_callback,
516 .longName = "debuglevel",
517 .shortName = 'd',
518 .argInfo = POPT_ARG_STRING,
519 .val = 'd',
520 .descrip = "Set debug level",
521 .argDescrip = "DEBUGLEVEL",
524 .longName = "debug-stdout",
525 .argInfo = POPT_ARG_NONE,
526 .val = OPT_DEBUG_STDOUT,
527 .descrip = "Send debug output to standard output",
530 .longName = "configfile",
531 .shortName = 's',
532 .argInfo = POPT_ARG_STRING,
533 .val = OPT_CONFIGFILE,
534 .descrip = "Use alternative configuration file",
535 .argDescrip = "CONFIGFILE",
538 .longName = "option",
539 .argInfo = POPT_ARG_STRING,
540 .val = OPT_OPTION,
541 .descrip = "Set smb.conf option from command line",
542 .argDescrip = "name=value",
545 .longName = "log-basename",
546 .shortName = 'l',
547 .argInfo = POPT_ARG_STRING,
548 .val = 'l',
549 .descrip = "Basename for log/debug files",
550 .argDescrip = "LOGFILEBASE",
553 .longName = "leak-report",
554 .argInfo = POPT_ARG_NONE,
555 .val = OPT_LEAK_REPORT,
556 .descrip = "enable talloc leak reporting on exit",
559 .longName = "leak-report-full",
560 .argInfo = POPT_ARG_NONE,
561 .val = OPT_LEAK_REPORT_FULL,
562 .descrip = "enable full talloc leak reporting on exit",
564 POPT_TABLEEND
567 static struct poptOption popt_common_samba_ldb[] = {
569 .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
570 .arg = (void *)popt_samba_callback,
573 .longName = "debuglevel",
574 .shortName = 'd',
575 .argInfo = POPT_ARG_STRING,
576 .val = 'd',
577 .descrip = "Set debug level",
578 .argDescrip = "DEBUGLEVEL",
581 .longName = "debug-stdout",
582 .argInfo = POPT_ARG_NONE,
583 .val = OPT_DEBUG_STDOUT,
584 .descrip = "Send debug output to standard output",
587 .longName = "configfile",
588 .argInfo = POPT_ARG_STRING,
589 .val = OPT_CONFIGFILE,
590 .descrip = "Use alternative configuration file",
591 .argDescrip = "CONFIGFILE",
594 .longName = "option",
595 .argInfo = POPT_ARG_STRING,
596 .val = OPT_OPTION,
597 .descrip = "Set smb.conf option from command line",
598 .argDescrip = "name=value",
601 .longName = "log-basename",
602 .shortName = 'l',
603 .argInfo = POPT_ARG_STRING,
604 .val = 'l',
605 .descrip = "Basename for log/debug files",
606 .argDescrip = "LOGFILEBASE",
609 .longName = "leak-report",
610 .argInfo = POPT_ARG_NONE,
611 .val = OPT_LEAK_REPORT,
612 .descrip = "enable talloc leak reporting on exit",
615 .longName = "leak-report-full",
616 .argInfo = POPT_ARG_NONE,
617 .val = OPT_LEAK_REPORT_FULL,
618 .descrip = "enable full talloc leak reporting on exit",
620 POPT_TABLEEND
623 /**********************************************************
624 * CONNECTION POPT
625 **********************************************************/
627 static void popt_connection_callback(poptContext popt_ctx,
628 enum poptCallbackReason reason,
629 const struct poptOption *opt,
630 const char *arg,
631 const void *data)
633 struct loadparm_context *lp_ctx = cmdline_lp_ctx;
635 if (reason == POPT_CALLBACK_REASON_PRE) {
636 if (lp_ctx == NULL) {
637 fprintf(stderr,
638 "Command line parsing not initialized!\n");
639 exit(1);
641 return;
644 switch(opt->val) {
645 case 'O':
646 if (arg != NULL) {
647 lpcfg_set_cmdline(lp_ctx, "socket options", arg);
649 break;
650 case 'R':
651 if (arg != NULL) {
652 lpcfg_set_cmdline(lp_ctx, "name resolve order", arg);
654 break;
655 case 'm':
656 if (arg != NULL) {
657 lpcfg_set_cmdline(lp_ctx, "client max protocol", arg);
659 break;
660 case OPT_NETBIOS_SCOPE:
661 if (arg != NULL) {
662 lpcfg_set_cmdline(lp_ctx, "netbios scope", arg);
664 break;
665 case 'n':
666 if (arg != NULL) {
667 lpcfg_set_cmdline(lp_ctx, "netbios name", arg);
669 break;
670 case 'W':
671 if (arg != NULL) {
672 lpcfg_set_cmdline(lp_ctx, "workgroup", arg);
674 break;
675 case 'r':
676 if (arg != NULL) {
677 lpcfg_set_cmdline(lp_ctx, "realm", arg);
679 break;
683 static struct poptOption popt_common_connection[] = {
685 .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE,
686 .arg = (void *)popt_connection_callback,
689 .longName = "name-resolve",
690 .shortName = 'R',
691 .argInfo = POPT_ARG_STRING,
692 .val = 'R',
693 .descrip = "Use these name resolution services only",
694 .argDescrip = "NAME-RESOLVE-ORDER",
697 .longName = "socket-options",
698 .shortName = 'O',
699 .argInfo = POPT_ARG_STRING,
700 .val = 'O',
701 .descrip = "socket options to use",
702 .argDescrip = "SOCKETOPTIONS",
705 .longName = "max-protocol",
706 .shortName = 'm',
707 .argInfo = POPT_ARG_STRING,
708 .val = 'm',
709 .descrip = "Set max protocol level",
710 .argDescrip = "MAXPROTOCOL",
713 .longName = "netbiosname",
714 .shortName = 'n',
715 .argInfo = POPT_ARG_STRING,
716 .val = 'n',
717 .descrip = "Primary netbios name",
718 .argDescrip = "NETBIOSNAME",
721 .longName = "netbios-scope",
722 .argInfo = POPT_ARG_STRING,
723 .val = OPT_NETBIOS_SCOPE,
724 .descrip = "Use this Netbios scope",
725 .argDescrip = "SCOPE",
728 .longName = "workgroup",
729 .shortName = 'W',
730 .argInfo = POPT_ARG_STRING,
731 .val = 'W',
732 .descrip = "Set the workgroup name",
733 .argDescrip = "WORKGROUP",
736 .longName = "realm",
737 .argInfo = POPT_ARG_STRING,
738 .val = 'r',
739 .descrip = "Set the realm name",
740 .argDescrip = "REALM",
742 POPT_TABLEEND
745 /**********************************************************
746 * CREDENTIALS POPT
747 **********************************************************/
749 static bool skip_password_callback;
750 static bool machine_account_pending;
752 static void popt_common_credentials_callback(poptContext popt_ctx,
753 enum poptCallbackReason reason,
754 const struct poptOption *opt,
755 const char *arg,
756 const void *data)
758 struct loadparm_context *lp_ctx = samba_cmdline_get_lp_ctx();
759 struct cli_credentials *creds = samba_cmdline_get_creds();
760 bool ok;
762 if (reason == POPT_CALLBACK_REASON_PRE) {
763 if (creds == NULL) {
764 fprintf(stderr,
765 "Command line parsing not initialized!\n");
766 exit(1);
768 return;
771 if (reason == POPT_CALLBACK_REASON_POST) {
772 const char *username = NULL;
773 enum credentials_obtained username_obtained =
774 CRED_UNINITIALISED;
775 enum credentials_obtained password_obtained =
776 CRED_UNINITIALISED;
779 * This calls cli_credentials_set_conf() to get the defaults
780 * form smb.conf and set the winbind separator.
782 * Just warn that we can't read the smb.conf. The might not be
783 * one available or we want to ignore it.
785 ok = cli_credentials_guess(creds, lp_ctx);
786 if (!ok) {
787 fprintf(stderr,
788 "Unable to read defaults from smb.conf\n");
791 (void)cli_credentials_get_password_and_obtained(creds,
792 &password_obtained);
793 if (!skip_password_callback &&
794 password_obtained < CRED_CALLBACK) {
795 ok = cli_credentials_set_cmdline_callbacks(creds);
796 if (!ok) {
797 fprintf(stderr,
798 "Failed to set cmdline password "
799 "callback\n");
800 exit(1);
804 if (machine_account_pending) {
805 NTSTATUS status;
807 status = cli_credentials_set_machine_account_fn(
808 creds, lp_ctx);
809 if (!NT_STATUS_IS_OK(status)) {
810 fprintf(stderr,
811 "Failed to set machine account: %s\n",
812 nt_errstr(status));
813 exit(1);
818 * When we set the username during the handling of the options
819 * passed to the binary we haven't loaded the config yet. This
820 * means that we didn't take the 'winbind separator' into
821 * account.
823 * The username might contain the domain name and thus it
824 * hasn't been correctly parsed yet. If we have a username we
825 * need to set it again to run the string parser for the
826 * username correctly.
828 username =
829 cli_credentials_get_username_and_obtained(
830 creds, &username_obtained);
831 if (username_obtained == CRED_SPECIFIED &&
832 username != NULL && username[0] != '\0') {
833 cli_credentials_parse_string(creds,
834 username,
835 CRED_SPECIFIED);
838 return;
841 switch(opt->val) {
842 case 'U':
843 if (arg != NULL) {
844 cli_credentials_parse_string(creds,
845 arg,
846 CRED_SPECIFIED);
848 break;
849 case OPT_PASSWORD:
850 if (arg != NULL) {
851 ok = cli_credentials_set_password(creds,
852 arg,
853 CRED_SPECIFIED);
854 if (!ok) {
855 fprintf(stderr,
856 "Failed to set password!\n");
857 exit(1);
860 skip_password_callback = true;
862 break;
863 case OPT_NT_HASH:
864 cli_credentials_set_password_will_be_nt_hash(creds, true);
865 break;
866 case 'A':
867 if (arg != NULL) {
868 ok = cli_credentials_parse_file(creds,
869 arg,
870 CRED_SPECIFIED);
871 if (!ok) {
872 fprintf(stderr,
873 "Failed to set parse authentication file!\n");
874 exit(1);
876 skip_password_callback = true;
878 break;
879 case 'N':
880 ok = cli_credentials_set_password(creds,
881 NULL,
882 CRED_SPECIFIED);
883 if (!ok) {
884 fprintf(stderr,
885 "Failed to set password!\n");
886 exit(1);
888 skip_password_callback = true;
889 break;
890 case 'P':
892 * Later, after this is all over, get the machine account
893 * details from the secrets.(l|t)db.
895 machine_account_pending = true;
896 break;
897 case OPT_SIMPLE_BIND_DN:
898 if (arg != NULL) {
899 ok = cli_credentials_set_bind_dn(creds, arg);
900 if (!ok) {
901 fprintf(stderr,
902 "Failed to set bind DN!\n");
903 exit(1);
906 break;
907 case OPT_USE_KERBEROS:
908 if (arg != NULL) {
909 int32_t use_kerberos =
910 lpcfg_parse_enum_vals("client use kerberos", arg);
912 if (use_kerberos == INT_MIN) {
913 fprintf(stderr, "Failed to parse --use-kerberos\n");
914 exit(1);
917 ok = cli_credentials_set_kerberos_state(creds,
918 use_kerberos,
919 CRED_SPECIFIED);
920 if (!ok) {
921 fprintf(stderr,
922 "Failed to set Kerberos state to %s!\n", arg);
923 exit(1);
926 break;
927 case OPT_USE_KERBEROS_CCACHE:
928 if (arg != NULL) {
929 const char *error_string = NULL;
930 int rc;
932 ok = cli_credentials_set_kerberos_state(creds,
933 CRED_USE_KERBEROS_REQUIRED,
934 CRED_SPECIFIED);
935 if (!ok) {
936 fprintf(stderr,
937 "Failed to set Kerberos state to %s!\n", arg);
938 exit(1);
941 rc = cli_credentials_set_ccache(creds,
942 lp_ctx,
943 arg,
944 CRED_SPECIFIED,
945 &error_string);
946 if (rc != 0) {
947 fprintf(stderr,
948 "Error reading krb5 credentials cache: '%s'"
949 " - %s\n",
950 arg,
951 error_string);
952 exit(1);
955 skip_password_callback = true;
957 break;
958 case OPT_USE_WINBIND_CCACHE:
960 uint32_t gensec_features;
962 gensec_features = cli_credentials_get_gensec_features(creds);
963 gensec_features |= GENSEC_FEATURE_NTLM_CCACHE;
965 ok = cli_credentials_set_gensec_features(creds,
966 gensec_features,
967 CRED_SPECIFIED);
968 if (!ok) {
969 fprintf(stderr,
970 "Failed to set gensec feature!\n");
971 exit(1);
974 skip_password_callback = true;
975 break;
977 case OPT_CLIENT_PROTECTION:
978 if (arg != NULL) {
979 uint32_t gensec_features;
980 enum smb_signing_setting signing_state =
981 SMB_SIGNING_OFF;
982 enum smb_encryption_setting encryption_state =
983 SMB_ENCRYPTION_OFF;
985 gensec_features =
986 cli_credentials_get_gensec_features(
987 creds);
989 if (strequal(arg, "off")) {
990 gensec_features &=
991 ~(GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL);
993 signing_state = SMB_SIGNING_OFF;
994 encryption_state = SMB_ENCRYPTION_OFF;
995 } else if (strequal(arg, "sign")) {
996 gensec_features |= GENSEC_FEATURE_SIGN;
998 signing_state = SMB_SIGNING_REQUIRED;
999 encryption_state = SMB_ENCRYPTION_OFF;
1000 } else if (strequal(arg, "encrypt")) {
1001 gensec_features |= GENSEC_FEATURE_SEAL;
1003 signing_state = SMB_SIGNING_REQUIRED;
1004 encryption_state = SMB_ENCRYPTION_REQUIRED;
1005 } else {
1006 fprintf(stderr,
1007 "Failed to parse --client-protection\n");
1008 exit(1);
1011 ok = cli_credentials_set_gensec_features(creds,
1012 gensec_features,
1013 CRED_SPECIFIED);
1014 if (!ok) {
1015 fprintf(stderr,
1016 "Failed to set gensec feature!\n");
1017 exit(1);
1020 ok = cli_credentials_set_smb_signing(creds,
1021 signing_state,
1022 CRED_SPECIFIED);
1023 if (!ok) {
1024 fprintf(stderr,
1025 "Failed to set smb signing!\n");
1026 exit(1);
1029 ok = cli_credentials_set_smb_encryption(creds,
1030 encryption_state,
1031 CRED_SPECIFIED);
1032 if (!ok) {
1033 fprintf(stderr,
1034 "Failed to set smb encryption!\n");
1035 exit(1);
1038 break;
1039 } /* switch */
1042 static struct poptOption popt_common_credentials[] = {
1044 .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
1045 .arg = (void *)popt_common_credentials_callback,
1048 .longName = "user",
1049 .shortName = 'U',
1050 .argInfo = POPT_ARG_STRING,
1051 .val = 'U',
1052 .descrip = "Set the network username",
1053 .argDescrip = "[DOMAIN/]USERNAME[%PASSWORD]",
1056 .longName = "no-pass",
1057 .shortName = 'N',
1058 .argInfo = POPT_ARG_NONE,
1059 .val = 'N',
1060 .descrip = "Don't ask for a password",
1063 .longName = "password",
1064 .argInfo = POPT_ARG_STRING,
1065 .val = OPT_PASSWORD,
1066 .descrip = "Password",
1069 .longName = "pw-nt-hash",
1070 .argInfo = POPT_ARG_NONE,
1071 .val = OPT_NT_HASH,
1072 .descrip = "The supplied password is the NT hash",
1075 .longName = "authentication-file",
1076 .shortName = 'A',
1077 .argInfo = POPT_ARG_STRING,
1078 .val = 'A',
1079 .descrip = "Get the credentials from a file",
1080 .argDescrip = "FILE",
1083 .longName = "machine-pass",
1084 .shortName = 'P',
1085 .argInfo = POPT_ARG_NONE,
1086 .val = 'P',
1087 .descrip = "Use stored machine account password",
1090 .longName = "simple-bind-dn",
1091 .argInfo = POPT_ARG_STRING,
1092 .val = OPT_SIMPLE_BIND_DN,
1093 .descrip = "DN to use for a simple bind",
1094 .argDescrip = "DN",
1097 .longName = "use-kerberos",
1098 .argInfo = POPT_ARG_STRING,
1099 .val = OPT_USE_KERBEROS,
1100 .descrip = "Use Kerberos authentication",
1101 .argDescrip = "desired|required|off",
1104 .longName = "use-krb5-ccache",
1105 .argInfo = POPT_ARG_STRING,
1106 .val = OPT_USE_KERBEROS_CCACHE,
1107 .descrip = "Credentials cache location for Kerberos",
1108 .argDescrip = "CCACHE",
1111 .longName = "use-winbind-ccache",
1112 .argInfo = POPT_ARG_NONE,
1113 .val = OPT_USE_WINBIND_CCACHE,
1114 .descrip = "Use the winbind ccache for authentication",
1117 .longName = "client-protection",
1118 .argInfo = POPT_ARG_STRING,
1119 .val = OPT_CLIENT_PROTECTION,
1120 .descrip = "Configure used protection for client connections",
1121 .argDescrip = "sign|encrypt|off",
1123 POPT_TABLEEND
1126 /**********************************************************
1127 * VERSION POPT
1128 **********************************************************/
1130 static void popt_version_callback(poptContext ctx,
1131 enum poptCallbackReason reason,
1132 const struct poptOption *opt,
1133 const char *arg,
1134 const void *data)
1136 switch(opt->val) {
1137 case 'V':
1138 printf("Version %s\n", SAMBA_VERSION_STRING);
1139 exit(0);
1143 static struct poptOption popt_common_version[] = {
1145 .argInfo = POPT_ARG_CALLBACK,
1146 .arg = (void *)popt_version_callback,
1149 .longName = "version",
1150 .shortName = 'V',
1151 .argInfo = POPT_ARG_NONE,
1152 .val = 'V',
1153 .descrip = "Print version",
1155 POPT_TABLEEND
1158 /**********************************************************
1159 * DAEMON POPT
1160 **********************************************************/
1162 static void popt_daemon_callback(poptContext ctx,
1163 enum poptCallbackReason reason,
1164 const struct poptOption *opt,
1165 const char *arg,
1166 const void *data)
1168 switch(opt->val) {
1169 case OPT_DAEMON:
1170 cmdline_daemon_cfg.daemon = true;
1171 break;
1172 case OPT_INTERACTIVE:
1173 cmdline_daemon_cfg.interactive = true;
1174 cmdline_daemon_cfg.fork = false;
1175 break;
1176 case OPT_FORK:
1177 cmdline_daemon_cfg.fork = false;
1178 break;
1179 case OPT_NO_PROCESS_GROUP:
1180 cmdline_daemon_cfg.no_process_group = true;
1181 break;
1185 static struct poptOption popt_common_daemon[] = {
1187 .argInfo = POPT_ARG_CALLBACK,
1188 .arg = (void *)popt_daemon_callback
1191 .longName = "daemon",
1192 .shortName = 'D',
1193 .argInfo = POPT_ARG_NONE,
1194 .arg = NULL,
1195 .val = OPT_DAEMON,
1196 .descrip = "Become a daemon (default)" ,
1199 .longName = "interactive",
1200 .shortName = 'i',
1201 .argInfo = POPT_ARG_NONE,
1202 .arg = NULL,
1203 .val = OPT_INTERACTIVE,
1204 .descrip = "Run interactive (not a daemon) and log to stdout",
1207 .longName = "foreground",
1208 .shortName = 'F',
1209 .argInfo = POPT_ARG_NONE,
1210 .arg = NULL,
1211 .val = OPT_FORK,
1212 .descrip = "Run daemon in foreground (for daemontools, etc.)",
1215 .longName = "no-process-group",
1216 .shortName = '\0',
1217 .argInfo = POPT_ARG_NONE,
1218 .arg = NULL,
1219 .val = OPT_NO_PROCESS_GROUP,
1220 .descrip = "Don't create a new process group" ,
1222 POPT_TABLEEND
1225 /**********************************************************
1226 * LEGACY S3 POPT
1227 **********************************************************/
1229 static void popt_legacy_s3_callback(poptContext ctx,
1230 enum poptCallbackReason reason,
1231 const struct poptOption *opt,
1232 const char *arg,
1233 const void *data)
1235 struct cli_credentials *creds = samba_cmdline_get_creds();
1236 bool ok;
1238 switch(opt->val) {
1239 case 'k':
1240 fprintf(stderr,
1241 "WARNING: The option -k|--kerberos is deprecated!\n");
1243 ok = cli_credentials_set_kerberos_state(creds,
1244 CRED_USE_KERBEROS_REQUIRED,
1245 CRED_SPECIFIED);
1246 if (!ok) {
1247 fprintf(stderr,
1248 "Failed to set Kerberos state to %s!\n", arg);
1249 exit(1);
1252 skip_password_callback = true;
1253 break;
1257 /* We allow '-k yes' too. */
1258 static struct poptOption popt_legacy_s3[] = {
1260 .argInfo = POPT_ARG_CALLBACK,
1261 .arg = (void *)popt_legacy_s3_callback,
1264 .longName = "kerberos",
1265 .shortName = 'k',
1266 .argInfo = POPT_ARG_NONE,
1267 .val = 'k',
1268 .descrip = "DEPRECATED: Migrate to --use-kerberos",
1270 POPT_TABLEEND
1273 /**********************************************************
1274 * LEGACY S4 POPT
1275 **********************************************************/
1277 static void popt_legacy_s4_callback(poptContext ctx,
1278 enum poptCallbackReason reason,
1279 const struct poptOption *opt,
1280 const char *arg,
1281 const void *data)
1283 struct cli_credentials *creds = samba_cmdline_get_creds();
1284 bool ok;
1286 switch(opt->val) {
1287 case 'k': {
1288 enum credentials_use_kerberos use_kerberos =
1289 CRED_USE_KERBEROS_REQUIRED;
1291 fprintf(stderr,
1292 "WARNING: The option -k|--kerberos is deprecated!\n");
1294 if (arg != NULL) {
1295 if (strcasecmp_m(arg, "yes") == 0) {
1296 use_kerberos = CRED_USE_KERBEROS_REQUIRED;
1297 } else if (strcasecmp_m(arg, "no") == 0) {
1298 use_kerberos = CRED_USE_KERBEROS_DISABLED;
1299 } else {
1300 fprintf(stderr,
1301 "Error parsing -k %s. Should be "
1302 "-k [yes|no]\n",
1303 arg);
1304 exit(1);
1308 ok = cli_credentials_set_kerberos_state(creds,
1309 use_kerberos,
1310 CRED_SPECIFIED);
1311 if (!ok) {
1312 fprintf(stderr,
1313 "Failed to set Kerberos state to %s!\n", arg);
1314 exit(1);
1317 break;
1322 static struct poptOption popt_legacy_s4[] = {
1324 .argInfo = POPT_ARG_CALLBACK,
1325 .arg = (void *)popt_legacy_s4_callback,
1328 .longName = "kerberos",
1329 .shortName = 'k',
1330 .argInfo = POPT_ARG_STRING,
1331 .val = 'k',
1332 .descrip = "DEPRECATED: Migrate to --use-kerberos",
1334 POPT_TABLEEND
1337 struct poptOption *samba_cmdline_get_popt(enum smb_cmdline_popt_options opt)
1339 switch (opt) {
1340 case SAMBA_CMDLINE_POPT_OPT_DEBUG_ONLY:
1341 return popt_common_debug;
1342 break;
1343 case SAMBA_CMDLINE_POPT_OPT_OPTION_ONLY:
1344 return popt_common_option;
1345 break;
1346 case SAMBA_CMDLINE_POPT_OPT_CONFIG_ONLY:
1347 return popt_common_config;
1348 break;
1349 case SAMBA_CMDLINE_POPT_OPT_SAMBA:
1350 return popt_common_samba;
1351 break;
1352 case SAMBA_CMDLINE_POPT_OPT_CONNECTION:
1353 return popt_common_connection;
1354 break;
1355 case SAMBA_CMDLINE_POPT_OPT_CREDENTIALS:
1356 return popt_common_credentials;
1357 break;
1358 case SAMBA_CMDLINE_POPT_OPT_VERSION:
1359 return popt_common_version;
1360 break;
1361 case SAMBA_CMDLINE_POPT_OPT_DAEMON:
1362 return popt_common_daemon;
1363 break;
1364 case SAMBA_CMDLINE_POPT_OPT_SAMBA_LDB:
1365 return popt_common_samba_ldb;
1366 break;
1367 case SAMBA_CMDLINE_POPT_OPT_LEGACY_S3:
1368 return popt_legacy_s3;
1369 break;
1370 case SAMBA_CMDLINE_POPT_OPT_LEGACY_S4:
1371 return popt_legacy_s4;
1372 break;
1375 /* Never reached */
1376 return NULL;