diff options
Diffstat (limited to 'source3/utils/smbpasswd.c')
-rw-r--r-- | source3/utils/smbpasswd.c | 973 |
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 |