From: Jelmer Vernooij Date: Mon, 21 Mar 2005 02:08:38 +0000 (+0000) Subject: r5917: First step in using the new cli_credentials structure. This patch X-Git-Url: http://git.samba.org/?a=commitdiff_plain;h=02075be0bbc2095073f8898350fded64a7c97c79;p=abartlet%2Fsamba.git%2F.git r5917: First step in using the new cli_credentials structure. This patch puts support for it into popt_common, adds a few utility functions (in lib/credentials.c) and the callback functions for the command-line (lib/cmdline/credentials.c). Comments are welcome :-) (This used to be commit 1d49b57c50fe8c2683ea23e9df41ce8ad774db98) --- diff --git a/source4/build/m4/rewrite.m4 b/source4/build/m4/rewrite.m4 index e1557da1f18..3361679f2c9 100644 --- a/source4/build/m4/rewrite.m4 +++ b/source4/build/m4/rewrite.m4 @@ -589,22 +589,6 @@ if test x"$samba_cv_HAVE_BROKEN_GETGROUPS" = x"yes"; then AC_DEFINE(HAVE_BROKEN_GETGROUPS,1,[Whether getgroups is broken]) fi -AC_CACHE_CHECK([whether getpass should be replaced],samba_cv_REPLACE_GETPASS,[ -SAVE_CPPFLAGS="$CPPFLAGS" -CPPFLAGS="$CPPFLAGS -I${srcdir-.}/ -I${srcdir-.}/include -I${srcdir-.}/ubiqx -I${srcdir-.}/popt -I${srcdir-.}/smbwrapper" -AC_TRY_COMPILE([ -#define REPLACE_GETPASS 1 -#define NO_CONFIG_H 1 -#define main dont_declare_main -#include "${srcdir-.}/lib/cmdline/getsmbpass.c" -#undef main -],[],samba_cv_REPLACE_GETPASS=yes,samba_cv_REPLACE_GETPASS=no) -CPPFLAGS="$SAVE_CPPFLAGS" -]) -if test x"$samba_cv_REPLACE_GETPASS" = x"yes"; then - AC_DEFINE(REPLACE_GETPASS,1,[Whether getpass should be replaced]) -fi - AC_CACHE_CHECK([for broken inet_ntoa],samba_cv_REPLACE_INET_NTOA,[ AC_TRY_RUN([ #include diff --git a/source4/build/smb_build/main.pm b/source4/build/smb_build/main.pm index 0b57e5952d5..381c548ac14 100644 --- a/source4/build/smb_build/main.pm +++ b/source4/build/smb_build/main.pm @@ -38,6 +38,7 @@ sub smb_build_main($) "lib/messaging/config.mk", "lib/events/config.mk", "lib/popt/config.mk", + "lib/cmdline/config.mk", "smb_server/config.mk", "rpc_server/config.mk", "ldap_server/config.mk", diff --git a/source4/client/client.c b/source4/client/client.c index 0ebebf747e2..fd5be736079 100644 --- a/source4/client/client.c +++ b/source4/client/client.c @@ -45,9 +45,6 @@ pstring cur_dir = "\\"; static pstring cd_path = ""; static pstring service; static pstring desthost; -static pstring username; -static pstring domain; -static pstring password; static char *cmdstr = NULL; static int io_bufsize = 64512; @@ -103,7 +100,7 @@ static double dir_total; #define USENMB /* some forward declarations */ -static struct smbcli_state *do_connect(const char *server, const char *share); +static struct smbcli_state *do_connect(const char *server, const char *share, struct cli_credentials *cred); /******************************************************************* @@ -202,7 +199,7 @@ static void send_message(void) int total_len = 0; int grp_id; - if (!smbcli_message_start(cli->tree, desthost, username, &grp_id)) { + if (!smbcli_message_start(cli->tree, desthost, cli_credentials_get_username(cmdline_credentials), &grp_id)) { d_printf("message start: %s\n", smbcli_errstr(cli->tree)); return; } @@ -2559,8 +2556,9 @@ static BOOL browse_host(const char *query_host) DCERPC_SRVSVC_UUID, DCERPC_SRVSVC_VERSION, lp_netbios_name(), - domain, - username, password); + cli_credentials_get_domain(cmdline_credentials), + cli_credentials_get_username(cmdline_credentials), + cli_credentials_get_password(cmdline_credentials)); if (!NT_STATUS_IS_OK(status)) { d_printf("Failed to connect to %s - %s\n", binding, nt_errstr(status)); @@ -2753,7 +2751,7 @@ static int process_command_string(char *cmd) /* establish the connection if not already */ if (!cli) { - cli = do_connect(desthost, service); + cli = do_connect(desthost, service, cmdline_credentials); if (!cli) return 0; } @@ -3039,7 +3037,7 @@ static void process_stdin(void) /***************************************************** return a connection to a server *******************************************************/ -static struct smbcli_state *do_connect(const char *server, const char *share) +static struct smbcli_state *do_connect(const char *server, const char *share, struct cli_credentials *cred) { struct smbcli_state *c; NTSTATUS status; @@ -3050,7 +3048,9 @@ static struct smbcli_state *do_connect(const char *server, const char *share) } status = smbcli_full_connection(NULL, &c, lp_netbios_name(), server, - share, NULL, username, domain, password); + share, NULL, cli_credentials_get_username(cred), + cli_credentials_get_domain(cred), + cli_credentials_get_password(cred)); if (!NT_STATUS_IS_OK(status)) { d_printf("Connection to \\\\%s\\%s failed - %s\n", server, share, nt_errstr(status)); @@ -3068,7 +3068,7 @@ static int process(char *base_directory) { int rc = 0; - cli = do_connect(desthost, service); + cli = do_connect(desthost, service, cmdline_credentials); if (!cli) { return 1; } @@ -3261,7 +3261,7 @@ static void remember_query_host(const char *arg, } if (poptPeekArg(pc)) { - cmdline_set_userpassword(poptGetArg(pc)); + cli_credentials_set_password(cmdline_credentials, poptGetArg(pc), CRED_SPECIFIED); } /*init_names(); */ @@ -3273,10 +3273,6 @@ static void remember_query_host(const char *arg, poptFreeContext(pc); - pstrcpy(username, cmdline_get_username()); - pstrcpy(domain, cmdline_get_userdomain()); - pstrcpy(password, cmdline_get_userpassword()); - DEBUG( 3, ( "Client started (version %s).\n", SAMBA_VERSION_STRING ) ); talloc_free(mem_ctx); diff --git a/source4/include/credentials.h b/source4/include/credentials.h index 0e816158781..7b223dad5aa 100644 --- a/source4/include/credentials.h +++ b/source4/include/credentials.h @@ -3,7 +3,7 @@ Client credentials structure - Copyright (C) 2004 Jelmer Vernooij + Copyright (C) Jelmer Vernooij 2004-2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,17 +20,32 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* In order of priority */ +enum credentials_obtained { + CRED_GUESSED = 0, /* Current value should be used, which was guessed */ + CRED_CALLBACK, /* Callback should be used to obtain value */ + CRED_SPECIFIED /* Was explicitly specified on the command-line */ +}; + struct cli_credentials { /* Preferred methods, NULL means default */ const char **preferred_methods; + enum credentials_obtained workstation_obtained; + enum credentials_obtained username_obtained; + enum credentials_obtained password_obtained; + enum credentials_obtained domain_obtained; + enum credentials_obtained realm_obtained; + + const char *workstation; const char *username; const char *password; const char *domain; const char *realm; - const char *(*username_cb) (struct cli_credentials *); + const char *(*workstation_cb) (struct cli_credentials *); const char *(*password_cb) (struct cli_credentials *); + const char *(*username_cb) (struct cli_credentials *); const char *(*domain_cb) (struct cli_credentials *); const char *(*realm_cb) (struct cli_credentials *); diff --git a/source4/include/includes.h b/source4/include/includes.h index 9a802aebd03..ce78e14d7db 100644 --- a/source4/include/includes.h +++ b/source4/include/includes.h @@ -123,6 +123,7 @@ extern int errno; #include "smb.h" #include "byteorder.h" #include "module.h" +#include "credentials.h" #include "librpc/ndr/libndr.h" #include "librpc/gen_ndr/ndr_misc.h" #include "librpc/gen_ndr/ndr_dcerpc.h" diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 257f59d8ed9..29dbbd22c76 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -39,7 +39,6 @@ INIT_OBJ_FILES = lib/version.o ADD_OBJ_FILES = \ lib/debug.o \ lib/fault.o \ - lib/getsmbpass.o \ lib/pidfile.o \ lib/signal.o \ lib/system.o \ @@ -65,7 +64,8 @@ ADD_OBJ_FILES = \ lib/idtree.o \ lib/unix_privs.o \ lib/db_wrap.o \ - lib/gencache.o + lib/gencache.o \ + lib/credentials.o REQUIRED_SUBSYSTEMS = \ LIBLDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO EXT_LIB_DL LIBTALLOC # End SUBSYSTEM LIBBASIC diff --git a/source4/lib/cmdline/config.m4 b/source4/lib/cmdline/config.m4 index e2121d1f144..45c3a70f9f6 100644 --- a/source4/lib/cmdline/config.m4 +++ b/source4/lib/cmdline/config.m4 @@ -77,4 +77,21 @@ SMB_EXT_LIB(READLINE, [${TMP_LIBCMDLINE_LIBS}]) SMB_SUBSYSTEM(LIBCMDLINE,[], [${TMP_LIBCMDLINE_OBJS}], [], - [LIBPOPT EXT_LIB_READLINE EXT_LIB_ALLLIBS]) + [LIBPOPT EXT_LIB_READLINE EXT_LIB_ALLLIBS LIBCMDLINE_CREDENTIALS]) + +AC_CACHE_CHECK([whether getpass should be replaced],samba_cv_REPLACE_GETPASS,[ +SAVE_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS -I${srcdir-.}/ -I${srcdir-.}/include -I${srcdir-.}/ubiqx -I${srcdir-.}/popt -I${srcdir-.}/smbwrapper" +AC_TRY_COMPILE([ +#define REPLACE_GETPASS 1 +#define NO_CONFIG_H 1 +#define main dont_declare_main +#include "${srcdir-.}/lib/cmdline/getsmbpass.c" +#undef main +],[],samba_cv_REPLACE_GETPASS=yes,samba_cv_REPLACE_GETPASS=no) +CPPFLAGS="$SAVE_CPPFLAGS" +]) +if test x"$samba_cv_REPLACE_GETPASS" = x"yes"; then + AC_DEFINE(REPLACE_GETPASS,1,[Whether getpass should be replaced]) +fi + diff --git a/source4/lib/cmdline/config.mk b/source4/lib/cmdline/config.mk new file mode 100644 index 00000000000..803c81f2733 --- /dev/null +++ b/source4/lib/cmdline/config.mk @@ -0,0 +1,7 @@ +############################## +# Start SUBSYSTEM LIBCMDLINE_CREDENTIALS +[SUBSYSTEM::LIBCMDLINE_CREDENTIALS] +ADD_OBJ_FILES = lib/cmdline/getsmbpass.o \ + lib/cmdline/credentials.o +# End SUBSYSTEM LIBCMDLINE_CREDENTIALS +############################## diff --git a/source4/lib/cmdline/credentials.c b/source4/lib/cmdline/credentials.c new file mode 100644 index 00000000000..d827baed76a --- /dev/null +++ b/source4/lib/cmdline/credentials.c @@ -0,0 +1,49 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Jelmer Vernooij 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "version.h" +#include "dynconfig.h" +#include "system/filesys.h" +#include "system/passwd.h" +#include "lib/cmdline/popt_common.h" + +static const char *cmdline_get_userpassword(struct cli_credentials *credentials) +{ + char *prompt; + char *ret; + + prompt = talloc_asprintf(NULL, "Password for [%s\\%s]:", + cli_credentials_get_domain(credentials), + cli_credentials_get_username(credentials)); + + ret = getpass(prompt); + + talloc_free(prompt); + return ret; +} + +void cli_credentials_set_cmdline_callbacks(struct cli_credentials *cred) +{ + if (cred->password_obtained <= CRED_CALLBACK) { + cred->password_cb = cmdline_get_userpassword; + cred->password_obtained = CRED_CALLBACK; + } +} diff --git a/source4/lib/getsmbpass.c b/source4/lib/cmdline/getsmbpass.c similarity index 100% rename from source4/lib/getsmbpass.c rename to source4/lib/cmdline/getsmbpass.c diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 0445877e7a9..0792a16b3d1 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -38,10 +38,9 @@ * -i,--scope */ - enum {OPT_OPTION=1,OPT_LEAK_REPORT,OPT_LEAK_REPORT_FULL}; -static struct cmdline_auth_info cmdline_auth_info; +struct cli_credentials *cmdline_credentials = NULL; static void popt_common_callback(poptContext con, enum poptCallbackReason reason, @@ -160,182 +159,34 @@ struct poptOption popt_common_version[] = { POPT_TABLEEND }; - - -/**************************************************************************** - * get a password from a a file or file descriptor - * exit on failure - * ****************************************************************************/ -static void get_password_file(struct cmdline_auth_info *a) -{ - int fd = -1; - char *p; - BOOL close_it = False; - pstring spec; - char pass[128]; - - if ((p = getenv("PASSWD_FD")) != NULL) { - pstrcpy(spec, "descriptor "); - pstrcat(spec, p); - sscanf(p, "%d", &fd); - close_it = False; - } else if ((p = getenv("PASSWD_FILE")) != NULL) { - fd = open(p, O_RDONLY, 0); - pstrcpy(spec, p); - if (fd < 0) { - fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n", - spec, strerror(errno)); - exit(1); - } - close_it = True; - } - - for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */ - p && p - pass < sizeof(pass);) { - switch (read(fd, p, 1)) { - case 1: - if (*p != '\n' && *p != '\0') { - *++p = '\0'; /* advance p, and null-terminate pass */ - break; - } - case 0: - if (p - pass) { - *p = '\0'; /* null-terminate it, just in case... */ - p = NULL; /* then force the loop condition to become false */ - break; - } else { - fprintf(stderr, "Error reading password from file %s: %s\n", - spec, "empty password\n"); - exit(1); - } - - default: - fprintf(stderr, "Error reading password from file %s: %s\n", - spec, strerror(errno)); - exit(1); - } - } - pstrcpy(a->password, pass); - if (close_it) - close(fd); -} - -static void get_credentials_file(const char *file, struct cmdline_auth_info *info) -{ - XFILE *auth; - fstring buf; - uint16_t len = 0; - char *ptr, *val, *param; - - if ((auth=x_fopen(file, O_RDONLY, 0)) == NULL) - { - /* fail if we can't open the credentials file */ - d_printf("ERROR: Unable to open credentials file!\n"); - exit(-1); - } - - while (!x_feof(auth)) - { - /* get a line from the file */ - if (!x_fgets(buf, sizeof(buf), auth)) - continue; - len = strlen(buf); - - if ((len) && (buf[len-1]=='\n')) - { - buf[len-1] = '\0'; - len--; - } - if (len == 0) - continue; - - /* break up the line into parameter & value. - * will need to eat a little whitespace possibly */ - param = buf; - if (!(ptr = strchr_m (buf, '='))) - continue; - - val = ptr+1; - *ptr = '\0'; - - /* eat leading white space */ - while ((*val!='\0') && ((*val==' ') || (*val=='\t'))) - val++; - - if (strwicmp("password", param) == 0) { - pstrcpy(info->password, val); - info->got_pass = True; - } else if (strwicmp("username", param) == 0) { - pstrcpy(info->username, val); - } else if (strwicmp("domain", param) == 0) { - pstrcpy(info->domain,val); - info->got_domain = True; - } - memset(buf, 0, sizeof(buf)); - } - x_fclose(auth); -} - /* Handle command line options: * -U,--user * -A,--authentication-file * -k,--use-kerberos * -N,--no-pass * -S,--signing - * -P --machine-pass + * -P --machine-pass */ +static BOOL dont_ask = False; + static void popt_common_credentials_callback(poptContext con, enum poptCallbackReason reason, const struct poptOption *opt, const char *arg, const void *data) { - char *p; - if (reason == POPT_CALLBACK_REASON_PRE) { - cmdline_auth_info.use_kerberos = False; - cmdline_auth_info.got_pass = False; - pstrcpy(cmdline_auth_info.username, "GUEST"); - - if (getenv("LOGNAME"))pstrcpy(cmdline_auth_info.username,getenv("LOGNAME")); - - if (getenv("USER")) { - pstring tmp; - - pstrcpy(cmdline_auth_info.username,getenv("USER")); + cmdline_credentials = talloc_zero(talloc_autofree_context(), struct cli_credentials); + cli_credentials_guess(cmdline_credentials); - pstrcpy(tmp,cmdline_auth_info.username); - if ((p = strchr_m(tmp,'\\'))) { - *p = 0; - pstrcpy(cmdline_auth_info.domain,tmp); - cmdline_auth_info.got_domain = True; - pstrcpy(cmdline_auth_info.username,p+1); - } - - if ((p = strchr_m(cmdline_auth_info.username,'%'))) { - *p = 0; - pstrcpy(cmdline_auth_info.password,p+1); - cmdline_auth_info.got_pass = True; - memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(cmdline_auth_info.password)); - } - } - - if (getenv("DOMAIN")) { - pstrcpy(cmdline_auth_info.domain,getenv("DOMAIN")); - cmdline_auth_info.got_domain = True; - } - - if (getenv("PASSWD")) { - pstrcpy(cmdline_auth_info.password,getenv("PASSWD")); - cmdline_auth_info.got_pass = True; - } - - if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) { - get_password_file(&cmdline_auth_info); - cmdline_auth_info.got_pass = True; + return; + } + + if (reason == POPT_CALLBACK_REASON_POST) { + if (!dont_ask) { + cli_credentials_set_cmdline_callbacks(cmdline_credentials); } - return; } @@ -343,41 +194,18 @@ static void popt_common_credentials_callback(poptContext con, case 'U': { char *lp; - pstring tmp; - - pstrcpy(cmdline_auth_info.username,arg); - pstrcpy(tmp,cmdline_auth_info.username); - if ((p = strchr_m(tmp,'\\'))) { - *p = 0; - pstrcpy(cmdline_auth_info.domain,tmp); - cmdline_auth_info.got_domain = True; - pstrcpy(cmdline_auth_info.username,p+1); - } + cli_credentials_parse_string(cmdline_credentials,arg, CRED_SPECIFIED); - if ((lp=strchr_m(cmdline_auth_info.username,'%'))) { + if ((lp=strchr_m(arg,'%'))) { *lp = 0; - pstrcpy(cmdline_auth_info.password,lp+1); - cmdline_auth_info.got_pass = True; - memset(strchr_m(arg,'%')+1,'X',strlen(cmdline_auth_info.password)); + memset(strchr_m(arg,'%')+1,'X',strlen(cmdline_credentials->password)); } } break; case 'A': - get_credentials_file(arg, &cmdline_auth_info); - break; - - case 'k': -#ifndef HAVE_KRB5 - d_printf("No kerberos support compiled in\n"); - exit(1); -#else - cmdline_auth_info.use_kerberos = True; - cmdline_auth_info.got_pass = True; - lp_set_cmdline("gensec:krb5", "True"); - lp_set_cmdline("gensec:ms_krb5", "True"); -#endif + cli_credentials_parse_file(cmdline_credentials, arg, CRED_SPECIFIED); break; case 'S': @@ -401,97 +229,38 @@ static void popt_common_credentials_callback(poptContext con, d_printf("ERROR: Unable to fetch machine password\n"); exit(1); } - snprintf(cmdline_auth_info.username, sizeof(cmdline_auth_info.username), - "%s$", lp_netbios_name()); - pstrcpy(cmdline_auth_info.password,opt_password); + cmdline_credentials->username = talloc_asprintf(cmdline_credentials, "%s$", lp_netbios_name()); + cmdline_credentials->username_obtained = CRED_SPECIFIED; + cli_credentials_set_password(cmdline_credentials, opt_password, CRED_SPECIFIED); free(opt_password); - cmdline_auth_info.got_pass = True; - pstrcpy(cmdline_auth_info.domain, lp_workgroup()); - cmdline_auth_info.got_domain = True; - - /* machine accounts only work with kerberos */ - cmdline_auth_info.use_kerberos = True; + cli_credentials_set_domain(cmdline_credentials, lp_workgroup(), CRED_SPECIFIED); } + /* machine accounts only work with kerberos */ + + case 'k': +#ifndef HAVE_KRB5 + d_printf("No kerberos support compiled in\n"); + exit(1); +#else + lp_set_cmdline("gensec:krb5", "True"); + lp_set_cmdline("gensec:ms_krb5", "True"); +#endif break; + + } } struct poptOption popt_common_credentials[] = { - { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_credentials_callback }, + { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST, popt_common_credentials_callback }, { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "USERNAME" }, - { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, 0, "Don't ask for a password" }, - { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, 'k', "Use kerberos (active directory) authentication" }, + { "no-pass", 'N', POPT_ARG_NONE, &dont_ask, True, "Don't ask for a password" }, + { "kerberos", 'k', POPT_ARG_NONE, NULL, 'k', "Use kerberos (active directory) authentication" }, { "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" }, { "signing", 'S', POPT_ARG_STRING, NULL, 'S', "Set the client signing state", "on|off|required" }, - { "machine-pass", 'P', POPT_ARG_NONE, NULL, 'P', "Use stored machine account password" }, + { "machine-pass", 'P', POPT_ARG_NONE, NULL, 'P', "Use stored machine account password (implies -k)" }, POPT_TABLEEND }; - -void cmdline_set_username(const char *name) -{ - pstrcpy(cmdline_auth_info.username, name); -} - -const char *cmdline_get_username(void) -{ - return cmdline_auth_info.username; -} - -void cmdline_set_userdomain(const char *domain) -{ - cmdline_auth_info.got_domain = True; - pstrcpy(cmdline_auth_info.domain, domain); -} - -const char *cmdline_get_userdomain(void) -{ - if (cmdline_auth_info.got_domain) { - return cmdline_auth_info.domain; - } - - /* I think this should be lp_netbios_name() - * instead of lp_workgroup(), because if you're logged in - * as domain user the getenv("USER") contains the domain - * and this code path isn't used - * --metze - */ - return lp_netbios_name(); -} - -const char *cmdline_get_userpassword(void) -{ - char *prompt; - char *ret; - - if (cmdline_auth_info.got_pass) { - return cmdline_auth_info.password; - } - - prompt = talloc_asprintf(NULL, "Password for [%s\\%s]:", - cmdline_get_userdomain(), - cmdline_get_username()); - - ret = getpass(prompt); - - talloc_free(prompt); - return ret; -} - -void cmdline_set_userpassword(const char *pass) -{ - cmdline_auth_info.got_pass = True; - pstrcpy(cmdline_auth_info.password, pass); -} - -void cmdline_set_use_kerberos(BOOL use_kerberos) -{ - cmdline_auth_info.use_kerberos = use_kerberos; -} - -BOOL cmdline_get_use_kerberos(void) -{ - return cmdline_auth_info.use_kerberos; -} diff --git a/source4/lib/cmdline/popt_common.h b/source4/lib/cmdline/popt_common.h index d6ae43d0837..28676de56b0 100644 --- a/source4/lib/cmdline/popt_common.h +++ b/source4/lib/cmdline/popt_common.h @@ -39,13 +39,6 @@ extern struct poptOption popt_common_credentials[]; #define POPT_COMMON_VERSION { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version, 0, "Common samba options:", NULL }, #define POPT_COMMON_CREDENTIALS { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_credentials, 0, "Authentication options:", NULL }, -struct cmdline_auth_info { - pstring username; - pstring domain; - BOOL got_domain; - pstring password; - BOOL got_pass; - BOOL use_kerberos; -}; +extern struct cli_credentials *cmdline_credentials; #endif /* _POPT_COMMON_H */ diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c new file mode 100644 index 00000000000..5c78d2b2e67 --- /dev/null +++ b/source4/lib/credentials.c @@ -0,0 +1,301 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Jelmer Vernooij 2005 + Copyright (C) Tim Potter 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "system/filesys.h" + +const char *cli_credentials_get_username(struct cli_credentials *cred) +{ + if (cred->username_obtained == CRED_CALLBACK) { + cred->username = cred->username_cb(cred); + cred->username_obtained = CRED_SPECIFIED; + } + + return cred->username; +} + +BOOL cli_credentials_set_username(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +{ + if (obtained >= cred->username_obtained) { + cred->username = talloc_strdup(cred, val); + cred->username_obtained = obtained; + return True; + } + + return False; +} + +const char *cli_credentials_get_password(struct cli_credentials *cred) +{ + if (cred->password_obtained == CRED_CALLBACK) { + cred->password = cred->password_cb(cred); + cred->password_obtained = CRED_SPECIFIED; + } + + return cred->password; +} + +BOOL cli_credentials_set_password(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +{ + if (obtained >= cred->password_obtained) { + cred->password = talloc_strdup(cred, val); + cred->password_obtained = obtained; + return True; + } + + return False; +} + +const char *cli_credentials_get_domain(struct cli_credentials *cred) +{ + if (cred->domain_obtained == CRED_CALLBACK) { + cred->domain = cred->domain_cb(cred); + cred->domain_obtained = CRED_SPECIFIED; + } + + return cred->domain; +} + + +BOOL cli_credentials_set_domain(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +{ + if (obtained >= cred->domain_obtained) { + cred->domain = talloc_strdup(cred, val); + cred->domain_obtained = obtained; + return True; + } + + return False; +} + +const char *cli_credentials_get_realm(struct cli_credentials *cred) +{ + if (cred->realm_obtained == CRED_CALLBACK) { + cred->realm = cred->realm_cb(cred); + cred->realm_obtained = CRED_SPECIFIED; + } + + return cred->realm; +} + +BOOL cli_credentials_set_realm(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +{ + if (obtained >= cred->realm_obtained) { + cred->realm = talloc_strdup(cred, val); + cred->realm_obtained = obtained; + return True; + } + + return False; +} + +const char *cli_credentials_get_workstation(struct cli_credentials *cred) +{ + if (cred->workstation_obtained == CRED_CALLBACK) { + cred->workstation = cred->workstation_cb(cred); + cred->workstation_obtained = CRED_SPECIFIED; + } + + return cred->workstation; +} + +BOOL cli_credentials_set_workstation(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +{ + if (obtained >= cred->workstation_obtained) { + cred->workstation = talloc_strdup(cred, val); + cred->workstation_obtained = obtained; + return True; + } + + return False; +} + +BOOL cli_credentials_parse_password_fd(struct cli_credentials *credentials, int fd, enum credentials_obtained obtained) +{ + char *p; + char pass[128]; + + for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */ + p && p - pass < sizeof(pass);) { + switch (read(fd, p, 1)) { + case 1: + if (*p != '\n' && *p != '\0') { + *++p = '\0'; /* advance p, and null-terminate pass */ + break; + } + case 0: + if (p - pass) { + *p = '\0'; /* null-terminate it, just in case... */ + p = NULL; /* then force the loop condition to become false */ + break; + } else { + fprintf(stderr, "Error reading password from file descriptor %d: %s\n", fd, "empty password\n"); + return False; + } + + default: + fprintf(stderr, "Error reading password from file descriptor %d: %s\n", + fd, strerror(errno)); + return False; + } + } + + cli_credentials_set_password(credentials, pass, obtained); + return True; +} + +BOOL cli_credentials_parse_password_file(struct cli_credentials *credentials, const char *file, enum credentials_obtained obtained) +{ + int fd = open(file, O_RDONLY, 0); + BOOL ret; + + if (fd < 0) { + fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n", + file, strerror(errno)); + return False; + } + + ret = cli_credentials_parse_password_fd(credentials, fd, obtained); + + close(fd); + + return ret; +} + +BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file, enum credentials_obtained obtained) +{ + XFILE *auth; + char buf[128]; + uint16_t len = 0; + char *ptr, *val, *param; + + if ((auth=x_fopen(file, O_RDONLY, 0)) == NULL) + { + /* fail if we can't open the credentials file */ + d_printf("ERROR: Unable to open credentials file!\n"); + return False; + } + + while (!x_feof(auth)) + { + /* get a line from the file */ + if (!x_fgets(buf, sizeof(buf), auth)) + continue; + len = strlen(buf); + + if ((len) && (buf[len-1]=='\n')) + { + buf[len-1] = '\0'; + len--; + } + if (len == 0) + continue; + + /* break up the line into parameter & value. + * will need to eat a little whitespace possibly */ + param = buf; + if (!(ptr = strchr_m (buf, '='))) + continue; + + val = ptr+1; + *ptr = '\0'; + + /* eat leading white space */ + while ((*val!='\0') && ((*val==' ') || (*val=='\t'))) + val++; + + if (strwicmp("password", param) == 0) { + cli_credentials_set_password(cred, val, obtained); + } else if (strwicmp("username", param) == 0) { + cli_credentials_set_username(cred, val, obtained); + } else if (strwicmp("domain", param) == 0) { + cli_credentials_set_domain(cred, val, obtained); + } else if (strwicmp("realm", param) == 0) { + cli_credentials_set_realm(cred, val, obtained); + } + memset(buf, 0, sizeof(buf)); + } + + x_fclose(auth); + return True; +} + + +void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained) +{ + char *uname, *p; + + uname = talloc_strdup(credentials, data); + cli_credentials_set_username(credentials, uname, obtained); + + if ((p = strchr_m(uname,'\\'))) { + *p = 0; + cli_credentials_set_domain(credentials, uname, obtained); + credentials->username = uname = p+1; + } + + if ((p = strchr_m(uname,'@'))) { + *p = 0; + cli_credentials_set_realm(credentials, p+1, obtained); + } + + if ((p = strchr_m(uname,'%'))) { + *p = 0; + cli_credentials_set_password(credentials, p+1, obtained); + } +} + +void cli_credentials_guess(struct cli_credentials *cred) +{ + char *p; + + cli_credentials_set_domain(cred, lp_workgroup(), CRED_GUESSED); + cli_credentials_set_workstation(cred, lp_netbios_name(), CRED_GUESSED); + cli_credentials_set_realm(cred, lp_realm(), CRED_GUESSED); + + if (getenv("LOGNAME")) { + cli_credentials_set_username(cred, getenv("LOGNAME"), CRED_GUESSED); + } + + if (getenv("USER")) { + cli_credentials_parse_string(cred, getenv("USER"), CRED_GUESSED); + if ((p = strchr_m(getenv("USER"),'%'))) { + *p = 0; + memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(cred->password)); + } + } + + if (getenv("DOMAIN")) { + cli_credentials_set_domain(cred, getenv("DOMAIN"), CRED_GUESSED); + } + + if (getenv("PASSWD")) { + cli_credentials_set_password(cred, getenv("PASSWD"), CRED_GUESSED); + } + + if (getenv("PASSWD_FD")) { + cli_credentials_parse_password_fd(cred, atoi(getenv("PASSWD_FD")), CRED_GUESSED); + } + + if (getenv("PASSWD_FILE")) { + cli_credentials_parse_password_file(cred, getenv("PASSWD_FILE"), CRED_GUESSED); + } +} diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index ceae3a427e4..7206e1e44dc 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -146,8 +146,8 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, else if (!h2) error = reg_open_local(&h2); break; case 'R': - if (!h1 && !from_null) error = reg_open_remote(&h1, cmdline_get_username(), cmdline_get_userpassword(), poptGetOptArg(pc)); - else if (!h2) error = reg_open_remote(&h2, cmdline_get_username(), cmdline_get_userpassword(), poptGetOptArg(pc)); + if (!h1 && !from_null) error = reg_open_remote(&h1, cli_credentials_get_username(cmdline_credentials), cli_credentials_get_password(cmdline_credentials), poptGetOptArg(pc)); + else if (!h2) error = reg_open_remote(&h2, cli_credentials_get_username(cmdline_credentials), cli_credentials_get_password(cmdline_credentials), poptGetOptArg(pc)); break; } diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index ee7568cc0fe..ce3d9a7e1b2 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -769,7 +769,7 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd setup_logging(argv[0], True); if (remote) { - error = reg_open_remote (&h, cmdline_get_username(), cmdline_get_userpassword(), remote); + error = reg_open_remote (&h, cli_credentials_get_username(cmdline_credentials), cli_credentials_get_password(cmdline_credentials), remote); } else { error = reg_open_local (&h); } diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index ee80837babd..cab2c5e34b0 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -395,7 +395,7 @@ static char **reg_completion(const char *text, int start, int end) setup_logging("regtree", True); if (remote) { - error = reg_open_remote (&h, cmdline_get_username(), cmdline_get_userpassword(), remote); + error = reg_open_remote (&h, cli_credentials_get_username(cmdline_credentials), cli_credentials_get_password(cmdline_credentials), remote); } else if (backend) { error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, &curkey); } else { diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index f061f33bd3f..81a7fb7f995 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -105,7 +105,7 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) setup_logging("regtree", True); if (remote) { - error = reg_open_remote(&h, cmdline_get_username(), cmdline_get_userpassword(), remote); + error = reg_open_remote(&h, cli_credentials_get_username(cmdline_credentials), cli_credentials_get_password(cmdline_credentials), remote); } else if (backend) { error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, &root); } else { diff --git a/source4/libcli/climessage.c b/source4/libcli/climessage.c index 113b752e8be..febd7db65cb 100644 --- a/source4/libcli/climessage.c +++ b/source4/libcli/climessage.c @@ -26,7 +26,7 @@ /**************************************************************************** start a message sequence ****************************************************************************/ -BOOL smbcli_message_start(struct smbcli_tree *tree, char *host, char *username, +BOOL smbcli_message_start(struct smbcli_tree *tree, char *host, const char *username, int *grp) { struct smbcli_request *req; diff --git a/source4/torture/torture.c b/source4/torture/torture.c index 588bf1bcffd..c7762f1b8a9 100644 --- a/source4/torture/torture.c +++ b/source4/torture/torture.c @@ -2729,7 +2729,7 @@ static BOOL is_binding_string(const char *binding_string) } if (!lp_parm_string(-1,"torture","username")) { - lp_set_cmdline("torture:username", cmdline_get_username()); + lp_set_cmdline("torture:username", cli_credentials_get_username(cmdline_credentials)); } if (!lp_parm_string(-1,"torture","userdomain")) { /* @@ -2738,13 +2738,13 @@ static BOOL is_binding_string(const char *binding_string) * for all cmdline tools * --metze */ - if (strequal(lp_netbios_name(),cmdline_get_userdomain())) { - cmdline_set_userdomain(lp_workgroup()); + if (strequal(lp_netbios_name(),cli_credentials_get_domain(cmdline_credentials))) { + cli_credentials_set_domain(cmdline_credentials, lp_workgroup(), CRED_SPECIFIED); } - lp_set_cmdline("torture:userdomain", cmdline_get_userdomain()); + lp_set_cmdline("torture:userdomain", cli_credentials_get_domain(cmdline_credentials)); } if (!lp_parm_string(-1,"torture","password")) { - lp_set_cmdline("torture:password", cmdline_get_userpassword()); + lp_set_cmdline("torture:password", cli_credentials_get_password(cmdline_credentials)); } if (argc_new == 0) { diff --git a/source4/utils/net/net.c b/source4/utils/net/net.c index fb87a5a6d9d..96ae23c7e4b 100644 --- a/source4/utils/net/net.c +++ b/source4/utils/net/net.c @@ -200,9 +200,7 @@ static int binary_net(int argc, const char **argv) ZERO_STRUCTP(ctx); ctx->mem_ctx = mem_ctx; - ctx->user.account_name = talloc_strdup(ctx->mem_ctx, cmdline_get_username()); - ctx->user.domain_name = talloc_strdup(ctx->mem_ctx, cmdline_get_userdomain()); - ctx->user.password = talloc_strdup(ctx->mem_ctx, cmdline_get_userpassword()); + ctx->credentials = cmdline_credentials; rc = net_run_function(ctx, argc_new-1, argv_new+1, net_functable, net_usage); diff --git a/source4/utils/net/net.h b/source4/utils/net/net.h index 2967063bde7..6f3aa1086bd 100644 --- a/source4/utils/net/net.h +++ b/source4/utils/net/net.h @@ -24,11 +24,7 @@ struct net_context { TALLOC_CTX *mem_ctx; - struct { - const char *account_name; - const char *domain_name; - const char *password; - } user; + struct cli_credentials *credentials; }; struct net_functable { diff --git a/source4/utils/net/net_join.c b/source4/utils/net/net_join.c index 6183da87b52..3a0a52cab5e 100644 --- a/source4/utils/net/net_join.c +++ b/source4/utils/net/net_join.c @@ -61,9 +61,9 @@ int net_join(struct net_context *ctx, int argc, const char **argv) if (!libnetctx) { return -1; } - libnetctx->user.account_name = ctx->user.account_name; - libnetctx->user.domain_name = ctx->user.domain_name; - libnetctx->user.password = ctx->user.password; + libnetctx->user.account_name= cli_credentials_get_username(ctx->credentials); + libnetctx->user.domain_name = cli_credentials_get_domain(ctx->credentials); + libnetctx->user.password = cli_credentials_get_password(ctx->credentials); /* prepare password change */ r.generic.level = LIBNET_JOIN_GENERIC; diff --git a/source4/utils/net/net_password.c b/source4/utils/net/net_password.c index ee0376989d3..a68c0b1c6a6 100644 --- a/source4/utils/net/net_password.c +++ b/source4/utils/net/net_password.c @@ -48,7 +48,8 @@ static int net_password_change(struct net_context *ctx, int argc, const char **a new_password = argv[0]; } else { password_prompt = talloc_asprintf(ctx->mem_ctx, "Enter new password for account [%s\\%s]:", - ctx->user.domain_name, ctx->user.account_name); + cli_credentials_get_domain(ctx->credentials), + cli_credentials_get_username(ctx->credentials)); new_password = getpass(password_prompt); } @@ -56,15 +57,15 @@ static int net_password_change(struct net_context *ctx, int argc, const char **a if (!libnetctx) { return -1; } - libnetctx->user.account_name = ctx->user.account_name; - libnetctx->user.domain_name = ctx->user.domain_name; - libnetctx->user.password = ctx->user.password; + libnetctx->user.account_name= cli_credentials_get_username(ctx->credentials); + libnetctx->user.domain_name = cli_credentials_get_domain(ctx->credentials); + libnetctx->user.password = cli_credentials_get_password(ctx->credentials); /* prepare password change */ r.generic.level = LIBNET_CHANGE_PASSWORD_GENERIC; - r.generic.in.account_name = ctx->user.account_name; - r.generic.in.domain_name = ctx->user.domain_name; - r.generic.in.oldpassword = ctx->user.password; + r.generic.in.account_name = cli_credentials_get_username(ctx->credentials); + r.generic.in.domain_name = cli_credentials_get_domain(ctx->credentials); + r.generic.in.oldpassword = cli_credentials_get_password(ctx->credentials); r.generic.in.newpassword = new_password; /* do password change */ @@ -120,7 +121,7 @@ static int net_password_set(struct net_context *ctx, int argc, const char **argv account_name = talloc_strdup(ctx->mem_ctx, p+1); } else { account_name = tmp; - domain_name = ctx->user.domain_name; + domain_name = cli_credentials_get_domain(ctx->credentials); } if (!new_password) { @@ -133,9 +134,9 @@ static int net_password_set(struct net_context *ctx, int argc, const char **argv if (!libnetctx) { return -1; } - libnetctx->user.account_name = ctx->user.account_name; - libnetctx->user.domain_name = ctx->user.domain_name; - libnetctx->user.password = ctx->user.password; + libnetctx->user.account_name= cli_credentials_get_username(ctx->credentials); + libnetctx->user.domain_name = cli_credentials_get_domain(ctx->credentials); + libnetctx->user.password = cli_credentials_get_password(ctx->credentials); /* prepare password change */ r.generic.level = LIBNET_SET_PASSWORD_GENERIC; diff --git a/source4/utils/net/net_time.c b/source4/utils/net/net_time.c index 5f318ac4ea5..df3b52a4abf 100644 --- a/source4/utils/net/net_time.c +++ b/source4/utils/net/net_time.c @@ -47,9 +47,9 @@ int net_time(struct net_context *ctx, int argc, const char **argv) if (!libnetctx) { return -1; } - libnetctx->user.account_name = ctx->user.account_name; - libnetctx->user.domain_name = ctx->user.domain_name; - libnetctx->user.password = ctx->user.password; + libnetctx->user.account_name= cli_credentials_get_username(ctx->credentials); + libnetctx->user.domain_name = cli_credentials_get_domain(ctx->credentials); + libnetctx->user.password = cli_credentials_get_password(ctx->credentials); /* prepare to get the time */ r.generic.level = LIBNET_REMOTE_TOD_GENERIC; diff --git a/source4/utils/net/net_user.c b/source4/utils/net/net_user.c index 4a472e69973..82f80b9e602 100644 --- a/source4/utils/net/net_user.c +++ b/source4/utils/net/net_user.c @@ -47,9 +47,9 @@ static int net_user_add(struct net_context *ctx, int argc, const char **argv) lnet_ctx = libnet_context_init(); if (!lnet_ctx) return -1; - lnet_ctx->user.domain_name = ctx->user.domain_name; - lnet_ctx->user.account_name = ctx->user.account_name; - lnet_ctx->user.password = ctx->user.password; + lnet_ctx->user.domain_name = cli_credentials_get_domain(ctx->credentials); + lnet_ctx->user.account_name = cli_credentials_get_username(ctx->credentials); + lnet_ctx->user.password = cli_credentials_get_password(ctx->credentials); /* calling CreateUser function */ r.generic.level = LIBNET_CREATE_USER_GENERIC;