summaryrefslogtreecommitdiff
path: root/source3/utils/smbpasswd.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/utils/smbpasswd.c')
-rw-r--r--source3/utils/smbpasswd.c973
1 files changed, 567 insertions, 406 deletions
diff --git a/source3/utils/smbpasswd.c b/source3/utils/smbpasswd.c
index 167eb2ed5f..a96fad0cdb 100644
--- a/source3/utils/smbpasswd.c
+++ b/source3/utils/smbpasswd.c
@@ -1,13 +1,12 @@
-#ifdef SMB_PASSWD
-
/*
- * Unix SMB/Netbios implementation. Version 1.9. smbpasswd module. Copyright
- * (C) Jeremy Allison 1995.
+ * Unix SMB/CIFS implementation.
+ * Copyright (C) Jeremy Allison 1995-1998
+ * 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 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
@@ -16,441 +15,603 @@
*
* 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.
- */
+ * Mass Ave, Cambridge, MA 02139, USA. */
#include "includes.h"
-#include "des.h"
-/* Static buffers we will return. */
-static struct smb_passwd pw_buf;
-static pstring user_name;
-static unsigned char smbpwd[16];
-static unsigned char smbntpwd[16];
+extern pstring global_myname;
+extern BOOL AllowDebugChange;
+
+/*
+ * Next two lines needed for SunOS and don't
+ * hurt anything else...
+ */
+extern char *optarg;
+extern int optind;
+
+/* forced running in root-mode */
+static BOOL local_mode;
+static BOOL got_pass = False, got_username = False;
+static int local_flags = 0;
+static BOOL stdin_passwd_get = False;
+static fstring user_name, user_password;
+static char *new_domain = NULL;
+static char *new_passwd = NULL;
+static char *old_passwd = NULL;
+static char *remote_machine = NULL;
+static pstring configfile;
+
+#ifdef WITH_LDAP_SAM
+static fstring ldap_secret;
+#endif
+
+/*********************************************************
+ Print command usage on stderr and die.
+**********************************************************/
+static void usage(void)
+{
+ printf("When run by root:\n");
+ printf(" smbpasswd [options] [username] [password]\n");
+ printf("otherwise:\n");
+ printf(" smbpasswd [options] [password]\n\n");
+
+ printf("options:\n");
+ printf(" -L local mode (must be first option)\n");
+ printf(" -h print this usage message\n");
+ printf(" -s use stdin for password prompt\n");
+ printf(" -c smb.conf file Use the given path to the smb.conf file\n");
+ printf(" -D LEVEL debug level\n");
+ printf(" -r MACHINE remote machine\n");
+ printf(" -U USER remote username\n");
+
+ printf("extra options when run by root or in local mode:\n");
+ printf(" -a add user\n");
+ printf(" -d disable user\n");
+ printf(" -e enable user\n");
+ printf(" -i interdomain trust account\n");
+ printf(" -m machine trust account\n");
+ printf(" -n set no password\n");
+#ifdef WITH_LDAP_SAM
+ printf(" -w ldap admin password\n");
+#endif
+ printf(" -x delete user\n");
+ printf(" -R ORDER name resolve order\n");
+
+ exit(1);
+}
+
+static void set_line_buffering(FILE *f)
+{
+ setvbuf(f, NULL, _IOLBF, 0);
+}
-static int gethexpwd(char *p, char *pwd)
+/*******************************************************************
+ Process command line options
+ ******************************************************************/
+static void process_options(int argc, char **argv, BOOL amroot)
{
- int i;
- unsigned char lonybble, hinybble;
- char *hexchars = "0123456789ABCDEF";
- char *p1, *p2;
- for (i = 0; i < 32; i += 2) {
- hinybble = toupper(p[i]);
- lonybble = toupper(p[i + 1]);
-
- p1 = strchr(hexchars, hinybble);
- p2 = strchr(hexchars, lonybble);
- if (!p1 || !p2)
- return (False);
-
- hinybble = PTR_DIFF(p1, hexchars);
- lonybble = PTR_DIFF(p2, hexchars);
-
- pwd[i / 2] = (hinybble << 4) | lonybble;
+ int ch;
+
+ if (amroot)
+ local_flags = LOCAL_SET_PASSWORD;
+
+ ZERO_STRUCT(user_name);
+ ZERO_STRUCT(user_password);
+
+ user_name[0] = '\0';
+
+ while ((ch = getopt(argc, argv, "c:axdehmnj:r:sw:R:D:U:L")) != EOF) {
+ switch(ch) {
+ case 'L':
+ local_mode = amroot = True;
+ local_flags = LOCAL_SET_PASSWORD;
+ break;
+ case 'c':
+ pstrcpy(configfile,optarg);
+ break;
+ case 'a':
+ if (!amroot) goto bad_args;
+ local_flags |= LOCAL_ADD_USER;
+ break;
+ case 'x':
+ if (!amroot) goto bad_args;
+ local_flags |= LOCAL_DELETE_USER;
+ local_flags &= ~LOCAL_SET_PASSWORD;
+ break;
+ case 'd':
+ if (!amroot) goto bad_args;
+ local_flags |= LOCAL_DISABLE_USER;
+ local_flags &= ~LOCAL_SET_PASSWORD;
+ break;
+ case 'e':
+ if (!amroot) goto bad_args;
+ local_flags |= LOCAL_ENABLE_USER;
+ local_flags &= ~LOCAL_SET_PASSWORD;
+ break;
+ case 'm':
+ if (!amroot) goto bad_args;
+ local_flags |= LOCAL_TRUST_ACCOUNT;
+ break;
+ case 'i':
+ if (!amroot) goto bad_args;
+ local_flags |= LOCAL_INTERDOM_ACCOUNT;
+ break;
+ case 'j':
+ if (!amroot) goto bad_args;
+ d_printf("See 'net rpc join' for this functionality\n");
+ exit(1);
+ break;
+ case 'n':
+ if (!amroot) goto bad_args;
+ local_flags |= LOCAL_SET_NO_PASSWORD;
+ new_passwd = smb_xstrdup("NO PASSWORD");
+ break;
+ case 'r':
+ remote_machine = optarg;
+ break;
+ case 's':
+ set_line_buffering(stdin);
+ set_line_buffering(stdout);
+ set_line_buffering(stderr);
+ stdin_passwd_get = True;
+ break;
+ case 'w':
+ if (!amroot) goto bad_args;
+#ifdef WITH_LDAP_SAM
+ local_flags |= LOCAL_SET_LDAP_ADMIN_PW;
+ fstrcpy(ldap_secret, optarg);
+ break;
+#else
+ printf("-w not available unless configured --with-ldap\n");
+ goto bad_args;
+#endif
+ case 'R':
+ if (!amroot) goto bad_args;
+ lp_set_name_resolve_order(optarg);
+ break;
+ case 'D':
+ DEBUGLEVEL = atoi(optarg);
+ break;
+ case 'U': {
+ char *lp;
+
+ got_username = True;
+ fstrcpy(user_name, optarg);
+
+ if ((lp = strchr(user_name, '%'))) {
+ *lp = 0;
+ fstrcpy(user_password, lp + 1);
+ got_pass = True;
+ memset(strchr_m(optarg, '%') + 1, 'X',
+ strlen(user_password));
+ }
+
+ break;
+ }
+ case 'h':
+ default:
+bad_args:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ switch(argc) {
+ case 0:
+ if (!got_username)
+ fstrcpy(user_name, "");
+ break;
+ case 1:
+ if (!amroot) {
+ new_passwd = argv[0];
+ break;
+ }
+ if (got_username)
+ usage();
+ fstrcpy(user_name, argv[0]);
+ break;
+ case 2:
+ if (!amroot || got_username || got_pass)
+ usage();
+ fstrcpy(user_name, argv[0]);
+ new_passwd = smb_xstrdup(argv[1]);
+ break;
+ default:
+ usage();
}
- return (True);
+
}
-struct smb_passwd *
-_my_get_smbpwnam(FILE * fp, char *name, BOOL * valid_old_pwd,
- BOOL *got_valid_nt_entry, long *pwd_seekpos)
+/*************************************************************
+ Utility function to prompt for passwords from stdin. Each
+ password entered must end with a newline.
+*************************************************************/
+static char *stdin_new_passwd(void)
{
- char linebuf[256];
- unsigned char c;
- unsigned char *p;
- long uidval;
- long linebuf_len;
+ static fstring new_passwd;
+ size_t len;
+
+ ZERO_ARRAY(new_passwd);
/*
- * Scan the file, a line at a time and check if the name matches.
+ * if no error is reported from fgets() and string at least contains
+ * the newline that ends the password, then replace the newline with
+ * a null terminator.
*/
- while (!feof(fp)) {
- linebuf[0] = '\0';
- *pwd_seekpos = ftell(fp);
+ if ( fgets(new_passwd, sizeof(new_passwd), stdin) != NULL) {
+ if ((len = strlen(new_passwd)) > 0) {
+ if(new_passwd[len-1] == '\n')
+ new_passwd[len - 1] = 0;
+ }
+ }
+ return(new_passwd);
+}
- fgets(linebuf, 256, fp);
- if (ferror(fp))
- return NULL;
- /*
- * Check if the string is terminated with a newline - if not
- * then we must keep reading and discard until we get one.
- */
- linebuf_len = strlen(linebuf);
- if (linebuf[linebuf_len - 1] != '\n') {
- c = '\0';
- while (!ferror(fp) && !feof(fp)) {
- c = fgetc(fp);
- if (c == '\n')
- break;
- }
- } else
- linebuf[linebuf_len - 1] = '\0';
+/*************************************************************
+ Utility function to get passwords via tty or stdin
+ Used if the '-s' option is set to silently get passwords
+ to enable scripting.
+*************************************************************/
+static char *get_pass( char *prompt, BOOL stdin_get)
+{
+ char *p;
+ if (stdin_get) {
+ p = stdin_new_passwd();
+ } else {
+ p = getpass(prompt);
+ }
+ return smb_xstrdup(p);
+}
- if ((linebuf[0] == 0) && feof(fp))
- break;
- /*
- * The line we have should be of the form :-
- *
- * username:uid:[32hex bytes]:....other flags presently
- * ignored....
- *
- * or,
- *
- * username:uid:[32hex bytes]:[32hex bytes]:....ignored....
- *
- * if Windows NT compatible passwords are also present.
- */
+/*************************************************************
+ Utility function to prompt for new password.
+*************************************************************/
+static char *prompt_for_new_password(BOOL stdin_get)
+{
+ char *p;
+ fstring new_passwd;
- if (linebuf[0] == '#' || linebuf[0] == '\0')
- continue;
- p = (unsigned char *) strchr(linebuf, ':');
- if (p == NULL)
- continue;
- /*
- * As 256 is shorter than a pstring we don't need to check
- * length here - if this ever changes....
- */
- strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
- user_name[PTR_DIFF(p, linebuf)] = '\0';
- if (!strequal(user_name, name))
- continue;
+ ZERO_ARRAY(new_passwd);
+
+ p = get_pass("New SMB password:", stdin_get);
+
+ fstrcpy(new_passwd, p);
+ SAFE_FREE(p);
+
+ p = get_pass("Retype new SMB password:", stdin_get);
+
+ if (strcmp(p, new_passwd)) {
+ fprintf(stderr, "Mismatch - password unchanged.\n");
+ ZERO_ARRAY(new_passwd);
+ SAFE_FREE(p);
+ return NULL;
+ }
+
+ return p;
+}
+
+
+/*************************************************************
+ Change a password either locally or remotely.
+*************************************************************/
- /* User name matches - get uid and password */
- p++; /* Go past ':' */
- if (!isdigit(*p))
- return (False);
+static BOOL password_change(const char *remote_machine, char *user_name,
+ char *old_passwd, char *new_passwd, int local_flags)
+{
+ BOOL ret;
+ pstring err_str;
+ pstring msg_str;
- uidval = atoi((char *) p);
- while (*p && isdigit(*p))
- p++;
+ if (remote_machine != NULL) {
+ if (local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|
+ LOCAL_TRUST_ACCOUNT|LOCAL_SET_NO_PASSWORD)) {
+ /* these things can't be done remotely yet */
+ return False;
+ }
+ ret = remote_password_change(remote_machine, user_name,
+ old_passwd, new_passwd, err_str, sizeof(err_str));
+ if(*err_str)
+ fprintf(stderr, err_str);
+ return ret;
+ }
+
+ ret = local_password_change(user_name, local_flags, new_passwd,
+ err_str, sizeof(err_str), msg_str, sizeof(msg_str));
- if (*p != ':')
- return (False);
+ if(*msg_str)
+ printf(msg_str);
+ if(*err_str)
+ fprintf(stderr, err_str);
+
+ return ret;
+}
+
+#ifdef WITH_LDAP_SAM
+/*******************************************************************
+ Store the LDAP admin password in secrets.tdb
+ ******************************************************************/
+static BOOL store_ldap_admin_pw (char* pw)
+{
+ if (!pw)
+ return False;
+
+ if (!secrets_init())
+ return False;
+
+ return secrets_store_ldap_pw(lp_ldap_admin_dn(), pw);
+}
+#endif
+
+
+/*************************************************************
+ Handle password changing for root.
+*************************************************************/
+
+static int process_root(void)
+{
+ struct passwd *pwd;
+ int result = 0;
+
+#ifdef WITH_LDAP_SAM
+ if (local_flags & LOCAL_SET_LDAP_ADMIN_PW)
+ {
+ printf("Setting stored password for \"%s\" in secrets.tdb\n",
+ lp_ldap_admin_dn());
+ if (!store_ldap_admin_pw(ldap_secret))
+ DEBUG(0,("ERROR: Failed to store the ldap admin password!\n"));
+ goto done;
+ }
+#endif
+
+ /*
+ * Ensure both add/delete user are not set
+ * Ensure add/delete user and either remote machine or join domain are
+ * not both set.
+ */
+ if(((local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER)) == (LOCAL_ADD_USER|LOCAL_DELETE_USER)) ||
+ ((local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER)) &&
+ (remote_machine != NULL))) {
+ usage();
+ }
+
+ /* Only load interfaces if we are doing network operations. */
+
+ if (remote_machine) {
+ load_interfaces();
+ }
+
+ if (!user_name[0] && (pwd = sys_getpwuid(geteuid()))) {
+ fstrcpy(user_name, pwd->pw_name);
+ }
+
+ if (!user_name[0]) {
+ fprintf(stderr,"You must specify a username\n");
+ exit(1);
+ }
+
+ if (local_flags & LOCAL_TRUST_ACCOUNT) {
+ /* add the $ automatically */
+ static fstring buf;
/*
- * Now get the password value - this should be 32 hex digits
- * which are the ascii representations of a 16 byte string.
- * Get two at a time and put them into the password.
+ * Remove any trailing '$' before we
+ * generate the initial machine password.
*/
- p++;
- *pwd_seekpos += PTR_DIFF(p, linebuf); /* Save exact position
- * of passwd in file -
- * this is used by
- * smbpasswd.c */
- if (*p == '*' || *p == 'X') {
- /* Password deliberately invalid - end here. */
- *valid_old_pwd = False;
- *got_valid_nt_entry = False;
- pw_buf.smb_nt_passwd = NULL; /* No NT password (yet)*/
-
- /* Now check if the NT compatible password is
- available. */
- p += 33; /* Move to the first character of the line after
- the lanman password. */
- if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
- /* NT Entry was valid - even if 'X' or '*', can be overwritten */
- *got_valid_nt_entry = True;
- if (*p != '*' && *p != 'X') {
- if(gethexpwd(p,smbntpwd))
- pw_buf.smb_nt_passwd = smbntpwd;
- }
- }
- pw_buf.smb_name = user_name;
- pw_buf.smb_userid = uidval;
- pw_buf.smb_passwd = NULL; /* No password */
- return (&pw_buf);
+
+ if (user_name[strlen(user_name)-1] == '$') {
+ user_name[strlen(user_name)-1] = 0;
}
- if (linebuf_len < (PTR_DIFF(p, linebuf) + 33))
- return (False);
- if (p[32] != ':')
- return (False);
+ if (local_flags & LOCAL_ADD_USER) {
+ SAFE_FREE(new_passwd);
+ new_passwd = smb_xstrdup(user_name);
+ strlower(new_passwd);
+ }
- if (!strncasecmp(p, "NO PASSWORD", 11)) {
- pw_buf.smb_passwd = NULL; /* No password */
- } else {
- if(!gethexpwd(p,smbpwd))
- return False;
- pw_buf.smb_passwd = smbpwd;
+ /*
+ * Now ensure the username ends in '$' for
+ * the machine add.
+ */
+
+ slprintf(buf, sizeof(buf)-1, "%s$", user_name);
+ fstrcpy(user_name, buf);
+ } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
+ static fstring buf;
+
+ if (local_flags & LOCAL_ADD_USER) {
+ /*
+ * Prompt for trusting domain's account password
+ */
+ new_passwd = prompt_for_new_password(stdin_passwd_get);
+ if(!new_passwd) {
+ fprintf(stderr, "Unable to get newpassword.\n");
+ exit(1);
+ }
}
+ slprintf(buf, sizeof(buf) - 1, "%s$", user_name);
+ fstrcpy(user_name, buf);
- pw_buf.smb_name = user_name;
- pw_buf.smb_userid = uidval;
- pw_buf.smb_nt_passwd = NULL;
- *got_valid_nt_entry = False;
- *valid_old_pwd = True;
-
- /* Now check if the NT compatible password is
- available. */
- p += 33; /* Move to the first character of the line after
- the lanman password. */
- if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
- /* NT Entry was valid - even if 'X' or '*', can be overwritten */
- *got_valid_nt_entry = True;
- if (*p != '*' && *p != 'X') {
- if(gethexpwd(p,smbntpwd))
- pw_buf.smb_nt_passwd = smbntpwd;
+ } else {
+
+ if (remote_machine != NULL) {
+ old_passwd = get_pass("Old SMB password:",stdin_passwd_get);
+ }
+
+ if (!(local_flags & LOCAL_SET_PASSWORD)) {
+
+ /*
+ * If we are trying to enable a user, first we need to find out
+ * if they are using a modern version of the smbpasswd file that
+ * disables a user by just writing a flag into the file. If so
+ * then we can re-enable a user without prompting for a new
+ * password. If not (ie. they have a no stored password in the
+ * smbpasswd file) then we need to prompt for a new password.
+ */
+
+ if(local_flags & LOCAL_ENABLE_USER) {
+ SAM_ACCOUNT *sampass = NULL;
+ BOOL ret;
+
+ pdb_init_sam(&sampass);
+ ret = pdb_getsampwnam(sampass, user_name);
+ if((sampass != False) && (pdb_get_lanman_passwd(sampass) == NULL)) {
+ local_flags |= LOCAL_SET_PASSWORD;
+ }
+ pdb_free_sam(&sampass);
}
}
- return &pw_buf;
+
+ if(local_flags & LOCAL_SET_PASSWORD) {
+ new_passwd = prompt_for_new_password(stdin_passwd_get);
+
+ if(!new_passwd) {
+ fprintf(stderr, "Unable to get new password.\n");
+ exit(1);
+ }
+ }
+ }
+
+ if (!password_change(remote_machine, user_name, old_passwd, new_passwd, local_flags)) {
+ fprintf(stderr,"Failed to modify password entry for user %s\n", user_name);
+ result = 1;
+ goto done;
+ }
+
+ if(remote_machine) {
+ printf("Password changed for user %s on %s.\n", user_name, remote_machine );
+ } else if(!(local_flags & (LOCAL_ADD_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|LOCAL_DELETE_USER|LOCAL_SET_NO_PASSWORD|LOCAL_SET_PASSWORD))) {
+ SAM_ACCOUNT *sampass = NULL;
+ BOOL ret;
+
+ pdb_init_sam(&sampass);
+ ret = pdb_getsampwnam(sampass, user_name);
+
+ printf("Password changed for user %s.", user_name );
+ if( (ret != False) && (pdb_get_acct_ctrl(sampass)&ACB_DISABLED) )
+ printf(" User has disabled flag set.");
+ if((ret != False) && (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ) )
+ printf(" User has no password flag set.");
+ printf("\n");
+ pdb_free_sam(&sampass);
}
- return NULL;
+
+ done:
+ SAFE_FREE(new_passwd);
+ return result;
}
-/*
- * Print command usage on stderr and die.
- */
-void
-usage(char *name)
+
+/*************************************************************
+ Handle password changing for non-root.
+*************************************************************/
+
+static int process_nonroot(void)
{
- fprintf(stderr, "Usage is : %s [username]\n", name);
- exit(1);
+ struct passwd *pwd = NULL;
+ int result = 0;
+
+ if (!user_name[0]) {
+ pwd = sys_getpwuid(getuid());
+ if (pwd) {
+ fstrcpy(user_name,pwd->pw_name);
+ } else {
+ fprintf(stderr, "smbpasswd: you don't exist - go away\n");
+ exit(1);
+ }
+ }
+
+ /*
+ * A non-root user is always setting a password
+ * via a remote machine (even if that machine is
+ * localhost).
+ */
+
+ load_interfaces(); /* Delayed from main() */
+
+ if (remote_machine == NULL) {
+ remote_machine = "127.0.0.1";
+ }
+
+ if (remote_machine != NULL) {
+ old_passwd = get_pass("Old SMB password:",stdin_passwd_get);
+ }
+
+ if (!new_passwd) {
+ new_passwd = prompt_for_new_password(stdin_passwd_get);
+ }
+
+ if (!new_passwd) {
+ fprintf(stderr, "Unable to get new password.\n");
+ exit(1);
+ }
+
+ if (!password_change(remote_machine, user_name, old_passwd, new_passwd, 0)) {
+ fprintf(stderr,"Failed to change password for %s\n", user_name);
+ result = 1;
+ goto done;
+ }
+
+ printf("Password changed for user %s\n", user_name);
+
+ done:
+ SAFE_FREE(old_passwd);
+ SAFE_FREE(new_passwd);
+
+ return result;
}
+
+
+/*********************************************************
+ Start here.
+**********************************************************/
int main(int argc, char **argv)
-{
- int real_uid;
- struct passwd *pwd;
- fstring old_passwd;
- uchar old_p16[16];
- uchar old_nt_p16[16];
- fstring new_passwd;
- uchar new_p16[16];
- uchar new_nt_p16[16];
- char *p;
- struct smb_passwd *smb_pwent;
- FILE *fp;
- BOOL valid_old_pwd = False;
- BOOL got_valid_nt_entry = False;
- long seekpos;
- int pwfd;
- char ascii_p16[66];
- char c;
- int ret, i, err, writelen;
- int lockfd = -1;
- char *pfile = SMB_PASSWD_FILE;
- char readbuf[16 * 1024];
-
- setup_logging(argv[0],True);
-
- charset_initialise();
-
-#ifndef DEBUG_PASSWORD
- /* Check the effective uid */
- if (geteuid() != 0) {
- fprintf(stderr, "%s: Must be setuid root.\n", argv[0]);
- exit(1);
- }
-#endif
-
- /* Get the real uid */
- real_uid = getuid();
-
- /* Deal with usage problems */
- if (real_uid == 0) {
- /* As root we can change anothers password. */
- if (argc != 1 && argc != 2)
- usage(argv[0]);
- } else if (argc != 1)
- usage(argv[0]);
-
-
- if (real_uid == 0 && argc == 2) {
- /* If we are root we can change anothers password. */
- strncpy(user_name, argv[1], sizeof(user_name) - 1);
- user_name[sizeof(user_name) - 1] = '\0';
- pwd = getpwnam(user_name);
- } else {
- pwd = getpwuid(real_uid);
- }
-
- if (pwd == 0) {
- fprintf(stderr, "%s: Unable to get UNIX password entry for user.\n", argv[0]);
- exit(1);
- }
- /* If we are root we don't ask for the old password. */
- old_passwd[0] = '\0';
- if (real_uid != 0) {
- p = getpass("Old SMB password:");
- strncpy(old_passwd, p, sizeof(fstring));
- old_passwd[sizeof(fstring)-1] = '\0';
- }
- new_passwd[0] = '\0';
- p = getpass("New SMB password:");
- strncpy(new_passwd, p, sizeof(fstring));
- new_passwd[sizeof(fstring)-1] = '\0';
- p = getpass("Retype new SMB password:");
- if (strcmp(p, new_passwd)) {
- fprintf(stderr, "%s: Mismatch - password unchanged.\n", argv[0]);
- exit(1);
- }
-
- if (new_passwd[0] == '\0') {
- printf("Password not set\n");
- exit(0);
- }
-
- /* Calculate the MD4 hash (NT compatible) of the old and new passwords */
- memset(old_nt_p16, '\0', 16);
- E_md4hash((uchar *)old_passwd, old_nt_p16);
-
- memset(new_nt_p16, '\0', 16);
- E_md4hash((uchar *) new_passwd, new_nt_p16);
-
- /* Mangle the passwords into Lanman format */
- old_passwd[14] = '\0';
- strupper(old_passwd);
- new_passwd[14] = '\0';
- strupper(new_passwd);
-
- /*
- * Calculate the SMB (lanman) hash functions of both old and new passwords.
- */
-
- memset(old_p16, '\0', 16);
- E_P16((uchar *) old_passwd, old_p16);
-
- memset(new_p16, '\0', 16);
- E_P16((uchar *) new_passwd, new_p16);
-
- /*
- * Open the smbpaswd file XXXX - we need to parse smb.conf to get the
- * filename
- */
- if ((fp = fopen(pfile, "r+")) == NULL) {
- err = errno;
- fprintf(stderr, "%s: Failed to open password file %s.\n",
- argv[0], pfile);
- errno = err;
- perror(argv[0]);
- exit(err);
- }
- /* Set read buffer to 16k for effiecient reads */
- setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
-
- /* make sure it is only rw by the owner */
- chmod(pfile, 0600);
-
- /* Lock the smbpasswd file for write. */
- if ((lockfd = pw_file_lock(pfile, F_WRLCK, 5)) < 0) {
- err = errno;
- fprintf(stderr, "%s: Failed to lock password file %s.\n",
- argv[0], pfile);
- fclose(fp);
- errno = err;
- perror(argv[0]);
- exit(err);
- }
- /* Get the smb passwd entry for this user */
- smb_pwent = _my_get_smbpwnam(fp, pwd->pw_name, &valid_old_pwd,
- &got_valid_nt_entry, &seekpos);
- if (smb_pwent == NULL) {
- fprintf(stderr, "%s: Failed to find entry for user %s in file %s.\n",
- argv[0], pwd->pw_name, pfile);
- fclose(fp);
- pw_file_unlock(lockfd);
- exit(1);
- }
- /* If we are root we don't need to check the old password. */
- if (real_uid != 0) {
- if ((valid_old_pwd == False) || (smb_pwent->smb_passwd == NULL)) {
- fprintf(stderr, "%s: User %s is disabled, plase contact your administrator to enable it.\n", argv[0], pwd->pw_name);
- fclose(fp);
- pw_file_unlock(lockfd);
- exit(1);
- }
- /* Check the old Lanman password */
- if (memcmp(old_p16, smb_pwent->smb_passwd, 16)) {
- fprintf(stderr, "%s: Couldn't change password.\n", argv[0]);
- fclose(fp);
- pw_file_unlock(lockfd);
- exit(1);
- }
- /* Check the NT password if it exists */
- if (smb_pwent->smb_nt_passwd != NULL) {
- if (memcmp(old_nt_p16, smb_pwent->smb_nt_passwd, 16)) {
- fprintf(stderr, "%s: Couldn't change password.\n", argv[0]);
- fclose(fp);
- pw_file_unlock(lockfd);
- exit(1);
- }
- }
- }
- /*
- * If we get here either we were root or the old password checked out
- * ok.
- */
- /* Create the 32 byte representation of the new p16 */
- for (i = 0; i < 16; i++) {
- sprintf(&ascii_p16[i * 2], "%02X", (uchar) new_p16[i]);
- }
- if(got_valid_nt_entry) {
- /* Add on the NT md4 hash */
- ascii_p16[32] = ':';
- for (i = 0; i < 16; i++) {
- sprintf(&ascii_p16[(i * 2)+33], "%02X", (uchar) new_nt_p16[i]);
- }
- }
- /*
- * Do an atomic write into the file at the position defined by
- * seekpos.
- */
- pwfd = fileno(fp);
- ret = lseek(pwfd, seekpos - 1, SEEK_SET);
- if (ret != seekpos - 1) {
- err = errno;
- fprintf(stderr, "%s: seek fail on file %s.\n",
- argv[0], pfile);
- fclose(fp);
- errno = err;
- perror(argv[0]);
- pw_file_unlock(lockfd);
- exit(1);
- }
- /* Sanity check - ensure the character is a ':' */
- if (read(pwfd, &c, 1) != 1) {
- err = errno;
- fprintf(stderr, "%s: read fail on file %s.\n",
- argv[0], pfile);
- fclose(fp);
- errno = err;
- perror(argv[0]);
- pw_file_unlock(lockfd);
- exit(1);
- }
- if (c != ':') {
- fprintf(stderr, "%s: sanity check on passwd file %s failed.\n",
- argv[0], pfile);
- fclose(fp);
- pw_file_unlock(lockfd);
- exit(1);
- }
- writelen = (got_valid_nt_entry) ? 65 : 32;
- if (write(pwfd, ascii_p16, writelen) != writelen) {
- err = errno;
- fprintf(stderr, "%s: write fail in file %s.\n",
- argv[0], pfile);
- fclose(fp);
- errno = err;
- perror(argv[0]);
- pw_file_unlock(lockfd);
- exit(err);
- }
- fclose(fp);
- pw_file_unlock(lockfd);
- printf("Password changed\n");
- return 0;
-}
+{
+ BOOL amroot = getuid() == 0;
-#else
+ pstrcpy(configfile, dyn_CONFIGFILE);
+ AllowDebugChange = False;
-#include "includes.h"
+#if defined(HAVE_SET_AUTH_PARAMETERS)
+ set_auth_parameters(argc, argv);
+#endif /* HAVE_SET_AUTH_PARAMETERS */
-int
-main(int argc, char **argv)
-{
- printf("smb password encryption not selected in Makefile\n");
- return 0;
+ process_options(argc, argv, amroot);
+
+ setup_logging("smbpasswd", True);
+
+ if (!lp_load(configfile,True,False,False)) {
+ fprintf(stderr, "Can't load %s - run testparm to debug it\n",
+ dyn_CONFIGFILE);
+ exit(1);
+ }
+
+ /*
+ * Set the machine NETBIOS name if not already
+ * set from the config file.
+ */
+
+ if (!*global_myname) {
+ char *p;
+ fstrcpy(global_myname, myhostname());
+ p = strchr_m(global_myname, '.' );
+ if (p) *p = 0;
+ }
+ strupper(global_myname);
+
+ /* Check the effective uid - make sure we are not setuid */
+ if (is_setuid_root()) {
+ fprintf(stderr, "smbpasswd must *NOT* be setuid root.\n");
+ exit(1);
+ }
+
+ if (local_mode || amroot) {
+ secrets_init();
+ return process_root();
+ }
+
+ return process_nonroot();
}
-#endif