From 02075be0bbc2095073f8898350fded64a7c97c79 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 21 Mar 2005 02:08:38 +0000 Subject: 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) --- source4/lib/basic.mk | 4 +- source4/lib/cmdline/config.m4 | 19 ++- source4/lib/cmdline/config.mk | 7 + source4/lib/cmdline/credentials.c | 49 ++++++ source4/lib/cmdline/getsmbpass.c | 158 ++++++++++++++++++ source4/lib/cmdline/popt_common.c | 303 ++++------------------------------ source4/lib/cmdline/popt_common.h | 9 +- source4/lib/credentials.c | 301 +++++++++++++++++++++++++++++++++ source4/lib/getsmbpass.c | 158 ------------------ source4/lib/registry/tools/regdiff.c | 4 +- source4/lib/registry/tools/regpatch.c | 2 +- source4/lib/registry/tools/regshell.c | 2 +- source4/lib/registry/tools/regtree.c | 2 +- 13 files changed, 577 insertions(+), 441 deletions(-) create mode 100644 source4/lib/cmdline/config.mk create mode 100644 source4/lib/cmdline/credentials.c create mode 100644 source4/lib/cmdline/getsmbpass.c create mode 100644 source4/lib/credentials.c delete mode 100644 source4/lib/getsmbpass.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 257f59d8ed..29dbbd22c7 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 e2121d1f14..45c3a70f9f 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 0000000000..803c81f273 --- /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 0000000000..d827baed76 --- /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/cmdline/getsmbpass.c b/source4/lib/cmdline/getsmbpass.c new file mode 100644 index 0000000000..4ffcde8dfd --- /dev/null +++ b/source4/lib/cmdline/getsmbpass.c @@ -0,0 +1,158 @@ +/* Copyright (C) 1992-1998 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* Modified to use with samba by Jeremy Allison, 8th July 1995. */ + +#include "includes.h" +#include "system/terminal.h" +#include "system/wait.h" + +#ifdef REPLACE_GETPASS + +#ifdef SYSV_TERMIO + +/* SYSTEM V TERMIO HANDLING */ + +static struct termio t; + +#define ECHO_IS_ON(t) ((t).c_lflag & ECHO) +#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) +#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) + +#ifndef TCSAFLUSH +#define TCSAFLUSH 1 +#endif + +#ifndef TCSANOW +#define TCSANOW 0 +#endif + +static int tcgetattr(int fd, struct termio *_t) +{ + return ioctl(fd, TCGETA, _t); +} + +static int tcsetattr(int fd, int flags, struct termio *_t) +{ + if(flags & TCSAFLUSH) + ioctl(fd, TCFLSH, TCIOFLUSH); + return ioctl(fd, TCSETS, _t); +} + +#elif !defined(TCSAFLUSH) + +/* BSD TERMIO HANDLING */ + +static struct sgttyb t; + +#define ECHO_IS_ON(t) ((t).sg_flags & ECHO) +#define TURN_ECHO_OFF(t) ((t).sg_flags &= ~ECHO) +#define TURN_ECHO_ON(t) ((t).sg_flags |= ECHO) + +#define TCSAFLUSH 1 +#define TCSANOW 0 + +static int tcgetattr(int fd, struct sgttyb *_t) +{ + return ioctl(fd, TIOCGETP, (char *)_t); +} + +static int tcsetattr(int fd, int flags, struct sgttyb *_t) +{ + return ioctl(fd, TIOCSETP, (char *)_t); +} + +#else /* POSIX TERMIO HANDLING */ +#define ECHO_IS_ON(t) ((t).c_lflag & ECHO) +#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) +#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) + +static struct termios t; +#endif /* SYSV_TERMIO */ + +char *getsmbpass(const char *prompt) +{ + FILE *in, *out; + int echo_off; + static char buf[256]; + static size_t bufsize = sizeof(buf); + size_t nread; + + /* Catch problematic signals */ + CatchSignal(SIGINT, SIGNAL_CAST SIG_IGN); + + /* Try to write to and read from the terminal if we can. + If we can't open the terminal, use stderr and stdin. */ + + in = fopen ("/dev/tty", "w+"); + if (in == NULL) + { + in = stdin; + out = stderr; + } + else + out = in; + + setvbuf(in, NULL, _IONBF, 0); + + /* Turn echoing off if it is on now. */ + + if (tcgetattr (fileno (in), &t) == 0) + { + if (ECHO_IS_ON(t)) + { + TURN_ECHO_OFF(t); + echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0; + TURN_ECHO_ON(t); + } + else + echo_off = 0; + } + else + echo_off = 0; + + /* Write the prompt. */ + fputs (prompt, out); + fflush (out); + + /* Read the password. */ + buf[0] = 0; + fgets(buf, bufsize, in); + nread = strlen(buf); + if (buf[nread - 1] == '\n') + buf[nread - 1] = '\0'; + + /* Restore echoing. */ + if (echo_off) + (void) tcsetattr (fileno (in), TCSANOW, &t); + + if (in != stdin) + /* We opened the terminal; now close it. */ + fclose (in); + + /* Catch problematic signals */ + CatchSignal(SIGINT, SIGNAL_CAST SIG_DFL); + + printf("\n"); + return buf; +} + +#else + void getsmbpasswd_dummy(void); + void getsmbpasswd_dummy(void) {;} +#endif diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 0445877e7a..0792a16b3d 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 d6ae43d083..28676de56b 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 0000000000..5c78d2b2e6 --- /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/getsmbpass.c b/source4/lib/getsmbpass.c deleted file mode 100644 index 4ffcde8dfd..0000000000 --- a/source4/lib/getsmbpass.c +++ /dev/null @@ -1,158 +0,0 @@ -/* Copyright (C) 1992-1998 Free Software Foundation, Inc. -This file is part of the GNU C Library. - -The GNU C Library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -The GNU C Library 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with the GNU C Library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 675 Mass Ave, -Cambridge, MA 02139, USA. */ - -/* Modified to use with samba by Jeremy Allison, 8th July 1995. */ - -#include "includes.h" -#include "system/terminal.h" -#include "system/wait.h" - -#ifdef REPLACE_GETPASS - -#ifdef SYSV_TERMIO - -/* SYSTEM V TERMIO HANDLING */ - -static struct termio t; - -#define ECHO_IS_ON(t) ((t).c_lflag & ECHO) -#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) -#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) - -#ifndef TCSAFLUSH -#define TCSAFLUSH 1 -#endif - -#ifndef TCSANOW -#define TCSANOW 0 -#endif - -static int tcgetattr(int fd, struct termio *_t) -{ - return ioctl(fd, TCGETA, _t); -} - -static int tcsetattr(int fd, int flags, struct termio *_t) -{ - if(flags & TCSAFLUSH) - ioctl(fd, TCFLSH, TCIOFLUSH); - return ioctl(fd, TCSETS, _t); -} - -#elif !defined(TCSAFLUSH) - -/* BSD TERMIO HANDLING */ - -static struct sgttyb t; - -#define ECHO_IS_ON(t) ((t).sg_flags & ECHO) -#define TURN_ECHO_OFF(t) ((t).sg_flags &= ~ECHO) -#define TURN_ECHO_ON(t) ((t).sg_flags |= ECHO) - -#define TCSAFLUSH 1 -#define TCSANOW 0 - -static int tcgetattr(int fd, struct sgttyb *_t) -{ - return ioctl(fd, TIOCGETP, (char *)_t); -} - -static int tcsetattr(int fd, int flags, struct sgttyb *_t) -{ - return ioctl(fd, TIOCSETP, (char *)_t); -} - -#else /* POSIX TERMIO HANDLING */ -#define ECHO_IS_ON(t) ((t).c_lflag & ECHO) -#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) -#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) - -static struct termios t; -#endif /* SYSV_TERMIO */ - -char *getsmbpass(const char *prompt) -{ - FILE *in, *out; - int echo_off; - static char buf[256]; - static size_t bufsize = sizeof(buf); - size_t nread; - - /* Catch problematic signals */ - CatchSignal(SIGINT, SIGNAL_CAST SIG_IGN); - - /* Try to write to and read from the terminal if we can. - If we can't open the terminal, use stderr and stdin. */ - - in = fopen ("/dev/tty", "w+"); - if (in == NULL) - { - in = stdin; - out = stderr; - } - else - out = in; - - setvbuf(in, NULL, _IONBF, 0); - - /* Turn echoing off if it is on now. */ - - if (tcgetattr (fileno (in), &t) == 0) - { - if (ECHO_IS_ON(t)) - { - TURN_ECHO_OFF(t); - echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0; - TURN_ECHO_ON(t); - } - else - echo_off = 0; - } - else - echo_off = 0; - - /* Write the prompt. */ - fputs (prompt, out); - fflush (out); - - /* Read the password. */ - buf[0] = 0; - fgets(buf, bufsize, in); - nread = strlen(buf); - if (buf[nread - 1] == '\n') - buf[nread - 1] = '\0'; - - /* Restore echoing. */ - if (echo_off) - (void) tcsetattr (fileno (in), TCSANOW, &t); - - if (in != stdin) - /* We opened the terminal; now close it. */ - fclose (in); - - /* Catch problematic signals */ - CatchSignal(SIGINT, SIGNAL_CAST SIG_DFL); - - printf("\n"); - return buf; -} - -#else - void getsmbpasswd_dummy(void); - void getsmbpasswd_dummy(void) {;} -#endif diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index ceae3a427e..7206e1e44d 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 ee7568cc0f..ce3d9a7e1b 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 ee80837bab..cab2c5e34b 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 f061f33bd3..81a7fb7f99 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 { -- cgit