From 726ccf1d56b2979c827dd8586d1aeb6cb8de236c Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 11 Aug 2020 16:37:16 +0200 Subject: [PATCH] lib:cmdline: Parse cmdline options with popt Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett --- lib/cmdline/cmdline.c | 791 +++++++++++++++++++++++++++++++++- lib/cmdline/cmdline.h | 100 ++++- lib/cmdline/cmdline_private.h | 16 + lib/cmdline/cmdline_s3.c | 27 +- lib/cmdline/cmdline_s4.c | 4 +- lib/cmdline/wscript | 2 + 6 files changed, 928 insertions(+), 12 deletions(-) diff --git a/lib/cmdline/cmdline.c b/lib/cmdline/cmdline.c index 8ca43571f5e..1171a05be49 100644 --- a/lib/cmdline/cmdline.c +++ b/lib/cmdline/cmdline.c @@ -17,8 +17,13 @@ #include "includes.h" #include "lib/param/param.h" +#include "dynconfig/dynconfig.h" +#include "auth/gensec/gensec.h" +#include "libcli/smb/smb_util.h" #include "cmdline_private.h" +#include + static TALLOC_CTX *cmdline_mem_ctx; static struct loadparm_context *cmdline_lp_ctx; static struct cli_credentials *cmdline_creds; @@ -58,9 +63,9 @@ bool samba_cmdline_init_common(TALLOC_CTX *mem_ctx) /* * Log to stdout by default. - * This can be changed to stderr using the option: --debug-stderr + * This can be changed to stderr using the option: --debug-stdout */ - setup_logging(getprogname(), DEBUG_DEFAULT_STDOUT); + setup_logging(getprogname(), DEBUG_DEFAULT_STDERR); talloc_set_log_fn(_samba_cmdline_talloc_log); talloc_set_abort_fn(smb_panic); @@ -106,3 +111,785 @@ struct cli_credentials *samba_cmdline_get_creds(void) { return cmdline_creds; } + +/********************************************************** + * COMMON SAMBA POPT + **********************************************************/ + +static bool log_to_file; + +static void popt_samba_callback(poptContext popt_ctx, + enum poptCallbackReason reason, + const struct poptOption *opt, + const char *arg, const void *data) +{ + TALLOC_CTX *mem_ctx = samba_cmdline_get_talloc_ctx(); + struct loadparm_context *lp_ctx = samba_cmdline_get_lp_ctx(); + const char *pname = NULL; + bool ok; + + if (reason == POPT_CALLBACK_REASON_PRE) { + if (lp_ctx == NULL) { + fprintf(stderr, + "Command line parsing not initialized!\n"); + exit(1); + } + return; + } + + if (reason == POPT_CALLBACK_REASON_POST) { + ok = cmdline_load_config_fn(); + if (!ok) { + fprintf(stderr, + "%s - Failed to load config file!\n", + getprogname()); + exit(1); + } + + if (log_to_file) { + const struct loadparm_substitution *lp_sub = + lpcfg_noop_substitution(); + char *logfile = NULL; + + logfile = lpcfg_logfile(lp_ctx, lp_sub, mem_ctx); + if (logfile == NULL) { + fprintf(stderr, + "Failed to setup logging to file!"); + exit(1); + } + debug_set_logfile(logfile); + setup_logging(logfile, DEBUG_FILE); + TALLOC_FREE(logfile); + } + + return; + } + + /* Find out basename of current program */ + pname = strrchr_m(poptGetInvocationName(popt_ctx), '/'); + if (pname == NULL) { + pname = poptGetInvocationName(popt_ctx); + } else { + pname++; + } + + switch(opt->val) { + case OPT_LEAK_REPORT: + talloc_enable_leak_report(); + break; + case OPT_LEAK_REPORT_FULL: + talloc_enable_leak_report_full(); + break; + case OPT_OPTION: + if (arg != NULL) { + ok = lpcfg_set_option(lp_ctx, arg); + if (!ok) { + fprintf(stderr, "Error setting option '%s'\n", arg); + exit(1); + } + } + break; + case 'd': + if (arg != NULL) { + ok = lpcfg_set_cmdline(lp_ctx, "log level", arg); + if (!ok) { + fprintf(stderr, + "Failed to set debug level to: %s\n", + arg); + exit(1); + } + } + break; + case OPT_DEBUG_STDOUT: + setup_logging(pname, DEBUG_STDOUT); + break; + case OPT_CONFIGFILE: + if (arg != NULL) { + set_dyn_CONFIGFILE(arg); + } + break; + case 'l': + if (arg != NULL) { + char *new_logfile = talloc_asprintf(mem_ctx, + "%s/log.%s", + arg, + pname); + if (new_logfile == NULL) { + fprintf(stderr, + "Failed to allocate memory\n"); + exit(1); + } + + ok = lpcfg_set_cmdline(lp_ctx, + "log file", + new_logfile); + if (!ok) { + fprintf(stderr, + "Failed to set log file: %s\n", + new_logfile); + TALLOC_FREE(new_logfile); + exit(1); + } + log_to_file = true; + + TALLOC_FREE(new_logfile); + } + break; + } +} + +static struct poptOption popt_common_samba[] = { + { + .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST, + .arg = (void *)popt_samba_callback, + }, + { + .longName = "debuglevel", + .shortName = 'd', + .argInfo = POPT_ARG_STRING, + .val = 'd', + .descrip = "Set debug level", + .argDescrip = "DEBUGLEVEL", + }, + { + .longName = "debug-stdout", + .argInfo = POPT_ARG_NONE, + .val = OPT_DEBUG_STDOUT, + .descrip = "Send debug output to standard output", + }, + { + .longName = "configfile", + .shortName = 's', + .argInfo = POPT_ARG_STRING, + .val = OPT_CONFIGFILE, + .descrip = "Use alternative configuration file", + .argDescrip = "CONFIGFILE", + }, + { + .longName = "option", + .argInfo = POPT_ARG_STRING, + .val = OPT_OPTION, + .descrip = "Set smb.conf option from command line", + .argDescrip = "name=value", + }, + { + .longName = "log-basename", + .shortName = 'l', + .argInfo = POPT_ARG_STRING, + .val = 'l', + .descrip = "Basename for log/debug files", + .argDescrip = "LOGFILEBASE", + }, + { + .longName = "leak-report", + .argInfo = POPT_ARG_NONE, + .val = OPT_LEAK_REPORT, + .descrip = "enable talloc leak reporting on exit", + }, + { + .longName = "leak-report-full", + .argInfo = POPT_ARG_NONE, + .val = OPT_LEAK_REPORT_FULL, + .descrip = "enable full talloc leak reporting on exit", + }, + POPT_TABLEEND +}; + +static struct poptOption popt_common_samba_ldb[] = { + { + .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST, + .arg = (void *)popt_samba_callback, + }, + { + .longName = "debuglevel", + .shortName = 'd', + .argInfo = POPT_ARG_STRING, + .val = 'd', + .descrip = "Set debug level", + .argDescrip = "DEBUGLEVEL", + }, + { + .longName = "debug-stdout", + .argInfo = POPT_ARG_NONE, + .val = OPT_DEBUG_STDOUT, + .descrip = "Send debug output to standard output", + }, + { + .longName = "configfile", + .argInfo = POPT_ARG_STRING, + .val = OPT_CONFIGFILE, + .descrip = "Use alternative configuration file", + .argDescrip = "CONFIGFILE", + }, + { + .longName = "option", + .argInfo = POPT_ARG_STRING, + .val = OPT_OPTION, + .descrip = "Set smb.conf option from command line", + .argDescrip = "name=value", + }, + { + .longName = "log-basename", + .shortName = 'l', + .argInfo = POPT_ARG_STRING, + .val = 'l', + .descrip = "Basename for log/debug files", + .argDescrip = "LOGFILEBASE", + }, + { + .longName = "leak-report", + .argInfo = POPT_ARG_NONE, + .val = OPT_LEAK_REPORT, + .descrip = "enable talloc leak reporting on exit", + }, + { + .longName = "leak-report-full", + .argInfo = POPT_ARG_NONE, + .val = OPT_LEAK_REPORT_FULL, + .descrip = "enable full talloc leak reporting on exit", + }, + POPT_TABLEEND +}; + +/********************************************************** + * CONNECTION POPT + **********************************************************/ + +static void popt_connection_callback(poptContext popt_ctx, + enum poptCallbackReason reason, + const struct poptOption *opt, + const char *arg, + const void *data) +{ + struct loadparm_context *lp_ctx = cmdline_lp_ctx; + + if (reason == POPT_CALLBACK_REASON_PRE) { + if (lp_ctx == NULL) { + fprintf(stderr, + "Command line parsing not initialized!\n"); + exit(1); + } + return; + } + + switch(opt->val) { + case 'O': + if (arg != NULL) { + lpcfg_set_cmdline(lp_ctx, "socket options", arg); + } + break; + case 'R': + if (arg != NULL) { + lpcfg_set_cmdline(lp_ctx, "name resolve order", arg); + } + break; + case 'm': + if (arg != NULL) { + lpcfg_set_cmdline(lp_ctx, "client max protocol", arg); + } + break; + case OPT_NETBIOS_SCOPE: + if (arg != NULL) { + lpcfg_set_cmdline(lp_ctx, "netbios scope", arg); + } + break; + case 'n': + if (arg != NULL) { + lpcfg_set_cmdline(lp_ctx, "netbios name", arg); + } + break; + case 'W': + if (arg != NULL) { + lpcfg_set_cmdline(lp_ctx, "workgroup", arg); + } + break; + case 'r': + if (arg != NULL) { + lpcfg_set_cmdline(lp_ctx, "realm", arg); + } + break; + } +} + +static struct poptOption popt_common_connection[] = { + { + .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, + .arg = (void *)popt_connection_callback, + }, + { + .longName = "name-resolve", + .shortName = 'R', + .argInfo = POPT_ARG_STRING, + .val = 'R', + .descrip = "Use these name resolution services only", + .argDescrip = "NAME-RESOLVE-ORDER", + }, + { + .longName = "socket-options", + .shortName = 'O', + .argInfo = POPT_ARG_STRING, + .val = 'O', + .descrip = "socket options to use", + .argDescrip = "SOCKETOPTIONS", + }, + { + .longName = "maxprotocol", + .shortName = 'm', + .argInfo = POPT_ARG_STRING, + .val = 'm', + .descrip = "Set max protocol level", + .argDescrip = "MAXPROTOCOL", + }, + { + .longName = "netbiosname", + .shortName = 'n', + .argInfo = POPT_ARG_STRING, + .val = 'n', + .descrip = "Primary netbios name", + .argDescrip = "NETBIOSNAME", + }, + { + .longName = "netbios-scope", + .argInfo = POPT_ARG_STRING, + .val = OPT_NETBIOS_SCOPE, + .descrip = "Use this Netbios scope", + .argDescrip = "SCOPE", + }, + { + .longName = "workgroup", + .shortName = 'W', + .argInfo = POPT_ARG_STRING, + .val = 'W', + .descrip = "Set the workgroup name", + .argDescrip = "WORKGROUP", + }, + { + .longName = "realm", + .argInfo = POPT_ARG_STRING, + .val = 'r', + .descrip = "Set the realm name", + .argDescrip = "REALM", + }, + POPT_TABLEEND +}; + +/********************************************************** + * CREDENTIALS POPT + **********************************************************/ + +static bool skip_password_callback; +static bool machine_account_pending; + +static void popt_common_credentials_callback(poptContext popt_ctx, + enum poptCallbackReason reason, + const struct poptOption *opt, + const char *arg, + const void *data) +{ + struct loadparm_context *lp_ctx = samba_cmdline_get_lp_ctx(); + struct cli_credentials *creds = samba_cmdline_get_creds(); + bool ok; + + if (reason == POPT_CALLBACK_REASON_PRE) { + if (creds == NULL) { + fprintf(stderr, + "Command line parsing not initialized!\n"); + exit(1); + } + return; + } + + if (reason == POPT_CALLBACK_REASON_POST) { + const char *username = NULL; + enum credentials_obtained username_obtained = + CRED_UNINITIALISED; + enum credentials_obtained password_obtained = + CRED_UNINITIALISED; + + /* + * This calls cli_credentials_set_conf() to get the defaults + * form smb.conf and set the winbind separator. + */ + cli_credentials_guess(creds, lp_ctx); + + (void)cli_credentials_get_password_and_obtained(creds, + &password_obtained); + if (!skip_password_callback && + password_obtained < CRED_CALLBACK) { + ok = cli_credentials_set_cmdline_callbacks(creds); + if (!ok) { + fprintf(stderr, + "Failed to set cmdline password " + "callback\n"); + exit(1); + } + } + + if (machine_account_pending) { + NTSTATUS status; + + status = cli_credentials_set_machine_account(creds, + lp_ctx); + if (!NT_STATUS_IS_OK(status)) { + fprintf(stderr, + "Failed to set machine account: %s\n", + nt_errstr(status)); + exit(1); + } + } + + /* + * When we set the username during the handling of the options + * passed to the binary we haven't loaded the config yet. This + * means that we didn't take the 'winbind separator' into + * account. + * + * The username might contain the domain name and thus it + * hasn't been correctly parsed yet. If we have a username we + * need to set it again to run the string parser for the + * username correctly. + */ + username = + cli_credentials_get_username_and_obtained( + creds, &username_obtained); + if (username_obtained == CRED_SPECIFIED && + username != NULL && username[0] != '\0') { + cli_credentials_parse_string(creds, + username, + CRED_SPECIFIED); + } + + return; + } + + switch(opt->val) { + case 'U': + if (arg != NULL) { + cli_credentials_parse_string(creds, + arg, + CRED_SPECIFIED); + } + break; + case OPT_PASSWORD: + if (arg != NULL) { + ok = cli_credentials_set_password(creds, + arg, + CRED_SPECIFIED); + if (!ok) { + fprintf(stderr, + "Failed to set password!\n"); + exit(1); + } + + skip_password_callback = true; + } + break; + case OPT_NT_HASH: + cli_credentials_set_password_will_be_nt_hash(creds, true); + break; + case 'A': + if (arg != NULL) { + ok = cli_credentials_parse_file(creds, + arg, + CRED_SPECIFIED); + if (!ok) { + fprintf(stderr, + "Failed to set parse authentication file!\n"); + exit(1); + } + skip_password_callback = true; + } + break; + case 'N': + ok = cli_credentials_set_password(creds, + NULL, + CRED_SPECIFIED); + if (!ok) { + fprintf(stderr, + "Failed to set password!\n"); + exit(1); + } + skip_password_callback = true; + break; + case 'P': + /* + * Later, after this is all over, get the machine account + * details from the secrets.(l|t)db. + */ + machine_account_pending = true; + break; + case OPT_SIMPLE_BIND_DN: + if (arg != NULL) { + ok = cli_credentials_set_bind_dn(creds, arg); + if (!ok) { + fprintf(stderr, + "Failed to set bind DN!\n"); + exit(1); + } + } + break; + case OPT_USE_KERBEROS: + if (arg != NULL) { + int32_t use_kerberos = + lpcfg_parse_enum_vals("client use kerberos", arg); + + if (use_kerberos == INT_MIN) { + fprintf(stderr, "Failed to parse --use-kerberos\n"); + exit(1); + } + + ok = cli_credentials_set_kerberos_state(creds, + use_kerberos, + CRED_SPECIFIED); + if (!ok) { + fprintf(stderr, + "Failed to set Kerberos state to %s!\n", arg); + exit(1); + } + } + break; + case OPT_USE_KERBEROS_CCACHE: + if (arg != NULL) { + const char *error_string = NULL; + int rc; + + rc = cli_credentials_set_ccache(creds, + lp_ctx, + arg, + CRED_SPECIFIED, + &error_string); + if (rc != 0) { + fprintf(stderr, + "Error reading krb5 credentials cache: '%s'" + " - %s\n", + arg, + error_string); + exit(1); + } + + skip_password_callback = true; + } + break; + case OPT_USE_WINBIND_CCACHE: + { + uint32_t gensec_features; + + gensec_features = cli_credentials_get_gensec_features(creds); + gensec_features |= GENSEC_FEATURE_NTLM_CCACHE; + + ok = cli_credentials_set_gensec_features(creds, + gensec_features, + CRED_SPECIFIED); + if (!ok) { + fprintf(stderr, + "Failed to set gensec feature!\n"); + exit(1); + } + + skip_password_callback = true; + break; + } + case OPT_CLIENT_PROTECTION: + if (arg != NULL) { + uint32_t gensec_features; + enum smb_signing_setting signing_state = + SMB_SIGNING_OFF; + enum smb_encryption_setting encryption_state = + SMB_ENCRYPTION_OFF; + + gensec_features = + cli_credentials_get_gensec_features( + creds); + + if (strequal(arg, "off")) { + gensec_features &= + ~(GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL); + + signing_state = SMB_SIGNING_OFF; + encryption_state = SMB_ENCRYPTION_OFF; + } else if (strequal(arg, "sign")) { + gensec_features |= GENSEC_FEATURE_SIGN; + + signing_state = SMB_SIGNING_REQUIRED; + encryption_state = SMB_ENCRYPTION_OFF; + } else if (strequal(arg, "encrypt")) { + gensec_features |= GENSEC_FEATURE_SEAL; + + signing_state = SMB_SIGNING_REQUIRED; + encryption_state = SMB_ENCRYPTION_REQUIRED; + } else { + fprintf(stderr, + "Failed to parse --client-protection\n"); + exit(1); + } + + ok = cli_credentials_set_gensec_features(creds, + gensec_features, + CRED_SPECIFIED); + if (!ok) { + fprintf(stderr, + "Failed to set gensec feature!\n"); + exit(1); + } + + ok = cli_credentials_set_smb_signing(creds, + signing_state, + CRED_SPECIFIED); + if (!ok) { + fprintf(stderr, + "Failed to set smb signing!\n"); + exit(1); + } + + ok = cli_credentials_set_smb_encryption(creds, + encryption_state, + CRED_SPECIFIED); + if (!ok) { + fprintf(stderr, + "Failed to set smb encryption!\n"); + exit(1); + } + } + break; + } /* switch */ +} + +static struct poptOption popt_common_credentials[] = { + { + .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST, + .arg = (void *)popt_common_credentials_callback, + }, + { + .longName = "user", + .shortName = 'U', + .argInfo = POPT_ARG_STRING, + .val = 'U', + .descrip = "Set the network username", + .argDescrip = "[DOMAIN/]USERNAME[%PASSWORD]", + }, + { + .longName = "no-pass", + .shortName = 'N', + .argInfo = POPT_ARG_NONE, + .val = 'N', + .descrip = "Don't ask for a password", + }, + { + .longName = "password", + .argInfo = POPT_ARG_STRING, + .val = OPT_PASSWORD, + .descrip = "Password", + }, + { + .longName = "pw-nt-hash", + .argInfo = POPT_ARG_NONE, + .val = OPT_NT_HASH, + .descrip = "The supplied password is the NT hash", + }, + { + .longName = "authentication-file", + .shortName = 'A', + .argInfo = POPT_ARG_STRING, + .val = 'A', + .descrip = "Get the credentials from a file", + .argDescrip = "FILE", + }, + { + .longName = "machine-pass", + .shortName = 'P', + .argInfo = POPT_ARG_NONE, + .val = 'P', + .descrip = "Use stored machine account password", + }, + { + .longName = "simple-bind-dn", + .argInfo = POPT_ARG_STRING, + .val = OPT_SIMPLE_BIND_DN, + .descrip = "DN to use for a simple bind", + .argDescrip = "DN", + }, + { + .longName = "use-kerberos", + .argInfo = POPT_ARG_STRING, + .val = OPT_USE_KERBEROS, + .descrip = "Use Kerberos authentication", + .argDescrip = "desired|required|off", + }, + { + .longName = "use-krb5-ccache", + .argInfo = POPT_ARG_STRING, + .val = OPT_USE_KERBEROS_CCACHE, + .descrip = "Credentials cache location for Kerberos", + .argDescrip = "CCACHE", + }, + { + .longName = "use-winbind-ccache", + .argInfo = POPT_ARG_NONE, + .val = OPT_USE_WINBIND_CCACHE, + .descrip = "Use the winbind ccache for authentication", + }, + { + .longName = "client-protection", + .argInfo = POPT_ARG_STRING, + .val = OPT_CLIENT_PROTECTION, + .descrip = "Configure used protection for client connections", + .argDescrip = "sign|encrypt|off", + }, + POPT_TABLEEND +}; + +/********************************************************** + * VERSION POPT + **********************************************************/ + +static void popt_version_callback(poptContext ctx, + enum poptCallbackReason reason, + const struct poptOption *opt, + const char *arg, + const void *data) +{ + switch(opt->val) { + case 'V': + printf("Version %s\n", SAMBA_VERSION_STRING); + exit(0); + } +} + +static struct poptOption popt_common_version[] = { + { + .argInfo = POPT_ARG_CALLBACK, + .arg = (void *)popt_version_callback, + }, + { + .longName = "version", + .shortName = 'V', + .argInfo = POPT_ARG_NONE, + .val = 'V', + .descrip = "Print version", + }, + POPT_TABLEEND +}; + +struct poptOption *samba_cmdline_get_popt(enum smb_cmdline_popt_options opt) +{ + switch (opt) { + case SAMBA_CMDLINE_POPT_OPT_SAMBA: + return popt_common_samba; + break; + case SAMBA_CMDLINE_POPT_OPT_CONNECTION: + return popt_common_connection; + break; + case SAMBA_CMDLINE_POPT_OPT_CREDENTIALS: + return popt_common_credentials; + break; + case SAMBA_CMDLINE_POPT_OPT_VERSION: + return popt_common_version; + break; + case SAMBA_CMDLINE_POPT_OPT_SAMBA_LDB: + return popt_common_samba_ldb; + break; + } + + /* Never reached */ + return NULL; +} diff --git a/lib/cmdline/cmdline.h b/lib/cmdline/cmdline.h index c184fc9efd3..899c82d742c 100644 --- a/lib/cmdline/cmdline.h +++ b/lib/cmdline/cmdline.h @@ -19,12 +19,39 @@ #define _CMDLINE_H #include "auth/credentials/credentials.h" +#include + +#ifndef POPT_TABLEEND +#define POPT_TABLEEND { \ + .longName = NULL, \ + .shortName = 0, \ + .argInfo = 0, \ + .arg = NULL, \ + .val = 0, \ + .descrip = NULL, \ + .argDescrip = NULL } +#endif + +enum samba_cmdline_config_type { + SAMBA_CMDLINE_CONFIG_CLIENT = 0, + SAMBA_CMDLINE_CONFIG_SERVER, +}; + +enum smb_cmdline_popt_options { + SAMBA_CMDLINE_POPT_OPT_SAMBA = 1, + SAMBA_CMDLINE_POPT_OPT_CONNECTION, + SAMBA_CMDLINE_POPT_OPT_CREDENTIALS, + SAMBA_CMDLINE_POPT_OPT_VERSION, + SAMBA_CMDLINE_POPT_OPT_SAMBA_LDB, +}; /** * @brief Initialize the commandline interface for parsing options. * * This initialized the interface for parsing options given on the command * line. It sets up the loadparm and client credentials contexts. + * The function will also setup fault handler, set logging to STDERR by + * default, setup talloc logging and the panic handler. * * @param[in] mem_ctx The talloc memory context to use for allocating memory. * This should be a long living context till the client @@ -35,7 +62,9 @@ * * @return true on success, false if an error occured. */ -bool samba_cmdline_init(TALLOC_CTX *mem_ctx, bool require_smbconf); +bool samba_cmdline_init(TALLOC_CTX *mem_ctx, + enum samba_cmdline_config_type config_type, + bool require_smbconf); /** * @brief Get a pointer of loadparm context used for the command line interface. @@ -51,4 +80,73 @@ struct loadparm_context *samba_cmdline_get_lp_ctx(void); */ struct cli_credentials *samba_cmdline_get_creds(void); +/** + * @brief Get a pointer to the poptOption for the given option section. + * + * @param[in] opt The options to retrieve. + * + * @return A pointer to the poptOption array. + */ +struct poptOption *samba_cmdline_get_popt(enum smb_cmdline_popt_options opt); + +/** + * @brief A popt structure for common samba options. + */ +#define POPT_COMMON_SAMBA { \ + .longName = NULL, \ + .shortName = '\0', \ + .argInfo = POPT_ARG_INCLUDE_TABLE, \ + .arg = samba_cmdline_get_popt(SAMBA_CMDLINE_POPT_OPT_SAMBA), \ + .val = 0, \ + .descrip = "Common Samba options:", \ + .argDescrip = NULL }, + +/** + * @brief A popt structure for connection options. + */ +#define POPT_COMMON_CONNECTION { \ + .longName = NULL, \ + .shortName = '\0', \ + .argInfo = POPT_ARG_INCLUDE_TABLE, \ + .arg = samba_cmdline_get_popt(SAMBA_CMDLINE_POPT_OPT_CONNECTION), \ + .val = 0, \ + .descrip = "Connection options:", \ + .argDescrip = NULL }, + +/** + * @brief A popt structure for credential options. + */ +#define POPT_COMMON_CREDENTIALS { \ + .longName = NULL, \ + .shortName = '\0', \ + .argInfo = POPT_ARG_INCLUDE_TABLE, \ + .arg = samba_cmdline_get_popt(SAMBA_CMDLINE_POPT_OPT_CREDENTIALS), \ + .val = 0, \ + .descrip = "Credential options:", \ + .argDescrip = NULL }, + +/** + * @brief A popt structure for version options. + */ +#define POPT_COMMON_VERSION { \ + .longName = NULL, \ + .shortName = '\0', \ + .argInfo = POPT_ARG_INCLUDE_TABLE, \ + .arg = samba_cmdline_get_popt(SAMBA_CMDLINE_POPT_OPT_VERSION), \ + .val = 0, \ + .descrip = "Version options:", \ + .argDescrip = NULL }, + +/** + * @brief A popt structure for common samba options. + */ +#define POPT_COMMON_SAMBA_LDB { \ + .longName = NULL, \ + .shortName = '\0', \ + .argInfo = POPT_ARG_INCLUDE_TABLE, \ + .arg = samba_cmdline_get_popt(SAMBA_CMDLINE_POPT_OPT_SAMBA_LDB), \ + .val = 0, \ + .descrip = "Common Samba options:", \ + .argDescrip = NULL }, + #endif /* _CMDLINE_H */ diff --git a/lib/cmdline/cmdline_private.h b/lib/cmdline/cmdline_private.h index 57816359777..2261e753447 100644 --- a/lib/cmdline/cmdline_private.h +++ b/lib/cmdline/cmdline_private.h @@ -20,6 +20,22 @@ #include "lib/cmdline/cmdline.h" +enum { + OPT_OPTION = 0x1000000, + OPT_NETBIOS_SCOPE, + OPT_LEAK_REPORT, + OPT_LEAK_REPORT_FULL, + OPT_DEBUG_STDOUT, + OPT_CONFIGFILE, + OPT_SIMPLE_BIND_DN, + OPT_PASSWORD, + OPT_NT_HASH, + OPT_USE_KERBEROS, + OPT_USE_KERBEROS_CCACHE, + OPT_USE_WINBIND_CCACHE, + OPT_CLIENT_PROTECTION, +}; + typedef bool (*samba_cmdline_load_config)(void); /** diff --git a/lib/cmdline/cmdline_s3.c b/lib/cmdline/cmdline_s3.c index 77d2818f453..d9bda695203 100644 --- a/lib/cmdline/cmdline_s3.c +++ b/lib/cmdline/cmdline_s3.c @@ -21,18 +21,20 @@ #include "lib/util/debug.h" #include "lib/util/fault.h" #include "source3/param/loadparm.h" +#include "dynconfig/dynconfig.h" #include "source3/lib/interface.h" #include "auth/credentials/credentials.h" #include "dynconfig/dynconfig.h" #include "cmdline_private.h" static bool _require_smbconf; +static enum samba_cmdline_config_type _config_type; static bool _samba_cmdline_load_config_s3(void) { struct loadparm_context *lp_ctx = samba_cmdline_get_lp_ctx(); const char *config_file = NULL; - bool ok; + bool ok = false; /* Load smb conf */ config_file = lpcfg_configfile(lp_ctx); @@ -45,15 +47,21 @@ static bool _samba_cmdline_load_config_s3(void) } } - /* - * Load load smb.conf from getenv("SMB_CONF_PATH") default - * location. - */ - ok = lp_load_client(lp_default_path()); + config_file = get_dyn_CONFIGFILE(); + + switch (_config_type) { + case SAMBA_CMDLINE_CONFIG_CLIENT: + ok = lp_load_client(config_file); + break; + case SAMBA_CMDLINE_CONFIG_SERVER: + ok = lp_load_initial_only(config_file); + break; + } + if (!ok) { fprintf(stderr, "Can't load %s - run testparm to debug it\n", - lp_default_path()); + config_file); if (_require_smbconf) { return false; @@ -65,7 +73,9 @@ static bool _samba_cmdline_load_config_s3(void) return true; } -bool samba_cmdline_init(TALLOC_CTX *mem_ctx, bool require_smbconf) +bool samba_cmdline_init(TALLOC_CTX *mem_ctx, + enum samba_cmdline_config_type config_type, + bool require_smbconf) { struct loadparm_context *lp_ctx = NULL; struct cli_credentials *creds = NULL; @@ -86,6 +96,7 @@ bool samba_cmdline_init(TALLOC_CTX *mem_ctx, bool require_smbconf) } _require_smbconf = require_smbconf; + _config_type = config_type; creds = cli_credentials_init(mem_ctx); if (creds == NULL) { diff --git a/lib/cmdline/cmdline_s4.c b/lib/cmdline/cmdline_s4.c index cf55cce1904..61c1b96ba8d 100644 --- a/lib/cmdline/cmdline_s4.c +++ b/lib/cmdline/cmdline_s4.c @@ -58,7 +58,9 @@ static bool _samba_cmdline_load_config_s4(void) return true; } -bool samba_cmdline_init(TALLOC_CTX *mem_ctx, bool require_smbconf) +bool samba_cmdline_init(TALLOC_CTX *mem_ctx, + enum samba_cmdline_config_type config_type, + bool require_smbconf) { struct loadparm_context *lp_ctx = NULL; struct cli_credentials *creds = NULL; diff --git a/lib/cmdline/wscript b/lib/cmdline/wscript index 87c7260ea19..26967514a60 100644 --- a/lib/cmdline/wscript +++ b/lib/cmdline/wscript @@ -9,8 +9,10 @@ def build(bld): source='cmdline.c', deps=''' talloc + cli_smb_common samba-hostconfig samba-credentials + CREDENTIALS_CMDLINE popt ''', private_library=True)