diff options
Diffstat (limited to 'source/smbd/chgpasswd.c')
-rw-r--r-- | source/smbd/chgpasswd.c | 268 |
1 files changed, 146 insertions, 122 deletions
diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c index 9e593b022ef..33ecfc5c2ff 100644 --- a/source/smbd/chgpasswd.c +++ b/source/smbd/chgpasswd.c @@ -1,5 +1,6 @@ /* - Unix SMB/CIFS implementation. + Unix SMB/Netbios implementation. + Version 1.9. Samba utility functions Copyright (C) Andrew Tridgell 1992-1998 @@ -50,12 +51,6 @@ extern struct passdb_ops pdb_ops; -static BOOL check_oem_password(const char *user, - uchar * lmdata, const uchar * lmhash, - const uchar * ntdata, const uchar * nthash, - SAM_ACCOUNT **hnd, char *new_passwd, - int new_passwd_size); - #if ALLOW_CHANGE_PASSWORD static int findpty(char **slave) @@ -117,18 +112,20 @@ static int findpty(char **slave) return (-1); } -static int dochild(int master, const char *slavedev, const struct passwd *pass, - const char *passwordprogram, BOOL as_root) +static int dochild(int master, char *slavedev, char *name, + char *passwordprogram, BOOL as_root) { int slave; struct termios stermios; + struct passwd *pass = Get_Pwnam(name, True); gid_t gid; uid_t uid; if (pass == NULL) { DEBUG(0, - ("dochild: user doesn't exist in the UNIX password database.\n")); + ("dochild: user name %s doesn't exist in the UNIX password database.\n", + name)); return False; } @@ -167,17 +164,17 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, /* Make slave stdin/out/err of child. */ - if (sys_dup2(slave, STDIN_FILENO) != STDIN_FILENO) + if (dup2(slave, STDIN_FILENO) != STDIN_FILENO) { DEBUG(3, ("Could not re-direct stdin\n")); return (False); } - if (sys_dup2(slave, STDOUT_FILENO) != STDOUT_FILENO) + if (dup2(slave, STDOUT_FILENO) != STDOUT_FILENO) { DEBUG(3, ("Could not re-direct stdout\n")); return (False); } - if (sys_dup2(slave, STDERR_FILENO) != STDERR_FILENO) + if (dup2(slave, STDERR_FILENO) != STDERR_FILENO) { DEBUG(3, ("Could not re-direct stderr\n")); return (False); @@ -199,15 +196,13 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, #ifdef ONLCR stermios.c_oflag &= ~(ONLCR); #endif - if (tcsetattr(0, TCSANOW, &stermios) < 0) - { + if (tcsetattr(0, TCSANOW, &stermios) < 0) { DEBUG(3, ("could not set attributes of pty\n")); return (False); } /* make us completely into the right uid */ - if (!as_root) - { + if (!as_root) { become_user_permanently(uid, gid); } @@ -323,7 +318,7 @@ static int talktochild(int master, char *seq) return (count > 0); } -static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, +static BOOL chat_with_program(char *passwordprogram, char *name, char *chatsequence, BOOL as_root) { char *slavedev; @@ -332,19 +327,12 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, int wstat; BOOL chstat = False; - if (pass == NULL) - { - DEBUG(0, - ("chat_with_program: user doesn't exist in the UNIX password database.\n")); - return False; - } - /* allocate a pseudo-terminal device */ if ((master = findpty(&slavedev)) < 0) { DEBUG(3, ("Cannot Allocate pty for password change: %s\n", - pass->pw_name)); + name)); return (False); } @@ -359,7 +347,7 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, { DEBUG(3, ("Cannot fork() child for password change: %s\n", - pass->pw_name)); + name)); close(master); CatchChild(); return (False); @@ -372,7 +360,7 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, { DEBUG(3, ("Child failed to change password: %s\n", - pass->pw_name)); + name)); kill(pid, SIGKILL); /* be sure to end this process */ } @@ -438,10 +426,10 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, become_root(); DEBUG(3, - ("Dochild for user %s (uid=%d,gid=%d)\n", pass->pw_name, + ("Dochild for user %s (uid=%d,gid=%d)\n", name, (int)getuid(), (int)getgid())); chstat = - dochild(master, slavedev, pass, passwordprogram, + dochild(master, slavedev, name, passwordprogram, as_root); if (as_root) @@ -460,24 +448,19 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, if (chstat) DEBUG(3, ("Password change %ssuccessful for user %s\n", - (chstat ? "" : "un"), pass->pw_name)); + (chstat ? "" : "un"), name)); return (chstat); } -BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root) +BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) { pstring passwordprogram; pstring chatsequence; size_t i; size_t len; - struct passwd *pass; - - if (!name) { - DEBUG(1, ("NULL username specfied to chgpasswd()!\n")); - } - + strlower(name); DEBUG(3, ("Password change for user: %s\n", name)); #if DEBUG_PASSWORD @@ -522,8 +505,6 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL return False; } } - - pass = Get_Pwnam(name); #ifdef WITH_PAM if (lp_pam_password_change()) { @@ -532,12 +513,8 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL if (as_root) become_root(); - if (pass) { - ret = smb_pam_passchange(pass->pw_name, oldpass, newpass); - } else { - ret = smb_pam_passchange(name, oldpass, newpass); - } - + ret = smb_pam_passchange(name, oldpass, newpass); + if (as_root) unbecome_root(); @@ -545,16 +522,6 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL } #endif - /* A non-PAM password change just doen't make sense without a valid local user */ - - if (pass == NULL) - { - DEBUG(0, - ("chgpasswd: user %s doesn't exist in the UNIX password database.\n", - name)); - return False; - } - pstrcpy(passwordprogram, lp_passwd_program()); pstrcpy(chatsequence, lp_passwd_chat()); @@ -586,12 +553,12 @@ the string %%u, and the given string %s does not.\n", passwordprogram )); all_string_sub(chatsequence, "%o", oldpass, sizeof(pstring)); all_string_sub(chatsequence, "%n", newpass, sizeof(pstring)); return (chat_with_program - (passwordprogram, pass, chatsequence, as_root)); + (passwordprogram, name, chatsequence, as_root)); } #else /* ALLOW_CHANGE_PASSWORD */ -BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root) +BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) { DEBUG(0, ("Password changing not compiled in (user=%s)\n", name)); return (False); @@ -605,11 +572,12 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL BOOL check_lanman_password(char *user, uchar * pass1, uchar * pass2, SAM_ACCOUNT **hnd) { + static uchar null_pw[16]; uchar unenc_new_pw[16]; uchar unenc_old_pw[16]; SAM_ACCOUNT *sampass = NULL; uint16 acct_ctrl; - const uint8 *lanman_pw; + uint8 *lanman_pw; BOOL ret; become_root(); @@ -618,7 +586,7 @@ BOOL check_lanman_password(char *user, uchar * pass1, if (ret == False) { DEBUG(0,("check_lanman_password: getsampwnam returned NULL\n")); - pdb_free_sam(&sampass); + pdb_free_sam(sampass); return False; } @@ -627,21 +595,24 @@ BOOL check_lanman_password(char *user, uchar * pass1, if (acct_ctrl & ACB_DISABLED) { DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); - pdb_free_sam(&sampass); + pdb_free_sam(sampass); return False; } - if (lanman_pw == NULL) { - if (acct_ctrl & ACB_PWNOTREQ) { - /* this saves the pointer for the caller */ - *hnd = sampass; - return True; - } else { - DEBUG(0, ("check_lanman_password: no lanman password !\n")); - pdb_free_sam(&sampass); + if ((lanman_pw == NULL) && (acct_ctrl & ACB_PWNOTREQ)) { + uchar no_pw[14]; + memset(no_pw, '\0', 14); + E_P16(no_pw, null_pw); + if (!pdb_set_lanman_passwd(sampass, null_pw)) { + pdb_free_sam(sampass); return False; } } + else if (lanman_pw == NULL) { + DEBUG(0, ("check_lanman_password: no lanman password !\n")); + pdb_free_sam(sampass); + return False; + } /* Get the new lanman hash. */ D_P16(lanman_pw, pass2, unenc_new_pw); @@ -652,12 +623,13 @@ BOOL check_lanman_password(char *user, uchar * pass1, /* Check that the two old passwords match. */ if (memcmp(lanman_pw, unenc_old_pw, 16)) { DEBUG(0,("check_lanman_password: old password doesn't match.\n")); - pdb_free_sam(&sampass); + pdb_free_sam(sampass); return False; } /* this saves the pointer for the caller */ *hnd = sampass; + return True; } @@ -674,7 +646,7 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar * pass1, uchar unenc_new_pw[16]; BOOL ret; uint16 acct_ctrl; - const uint8 *pwd; + uint8 *pwd; if (sampass == NULL) { DEBUG(0,("change_lanman_password: no smb password entry.\n")); @@ -690,40 +662,28 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar * pass1, return False; } - if (pwd == NULL) { - if (acct_ctrl & ACB_PWNOTREQ) { - uchar no_pw[14]; - memset(no_pw, '\0', 14); - E_P16(no_pw, null_pw); - - /* Get the new lanman hash. */ - D_P16(null_pw, pass2, unenc_new_pw); - } else { - DEBUG(0,("change_lanman_password: no lanman password !\n")); + if ((pwd == NULL) && (acct_ctrl & ACB_PWNOTREQ)) { + uchar no_pw[14]; + memset(no_pw, '\0', 14); + E_P16(no_pw, null_pw); + if (!pdb_set_lanman_passwd(sampass, null_pw)) return False; - } - } else { - /* Get the new lanman hash. */ - D_P16(pwd, pass2, unenc_new_pw); } - - if (!pdb_set_lanman_passwd(sampass, unenc_new_pw)) { + else if (pwd == NULL) { + DEBUG(0,("change_lanman_password: no lanman password !\n")); return False; } - if (!pdb_set_nt_passwd (sampass, NULL)) { - return False; /* We lose the NT hash. Sorry. */ - } + /* Get the new lanman hash. */ + D_P16(pwd, pass2, unenc_new_pw); + + if (!pdb_set_lanman_passwd(sampass, unenc_new_pw)) + return False; + pdb_set_nt_passwd (sampass, NULL); /* We lose the NT hash. Sorry. */ - if (!pdb_set_pass_changed_now (sampass)) { - pdb_free_sam(&sampass); - /* Not quite sure what this one qualifies as, but this will do */ - return False; - } - /* Now flush the sam_passwd struct to persistent storage */ become_root(); - ret = pdb_update_sam_account (sampass); + ret = pdb_update_sam_account (sampass, False); unbecome_root(); return ret; @@ -737,7 +697,6 @@ BOOL pass_oem_change(char *user, uchar * ntdata, uchar * nthash) { fstring new_passwd; - const char *unix_user; SAM_ACCOUNT *sampass = NULL; BOOL ret = check_oem_password(user, lmdata, lmhash, ntdata, nthash, &sampass, new_passwd, sizeof(new_passwd)); @@ -751,17 +710,15 @@ BOOL pass_oem_change(char *user, * available. JRA. */ - unix_user = pdb_get_username(sampass); - - if ((ret) && (unix_user) && (*unix_user) && lp_unix_password_sync()) - ret = chgpasswd(unix_user, "", new_passwd, True); + if (ret && lp_unix_password_sync()) + ret = chgpasswd(user, "", new_passwd, True); if (ret) - ret = change_oem_password(sampass, new_passwd); + ret = change_oem_password(sampass, new_passwd, False); memset(new_passwd, 0, sizeof(new_passwd)); - pdb_free_sam(&sampass); + pdb_free_sam(sampass); return ret; } @@ -773,16 +730,16 @@ BOOL pass_oem_change(char *user, but does use the lm OEM password to check the nt hashed-hash. ************************************************************/ -static BOOL check_oem_password(const char *user, - uchar * lmdata, const uchar * lmhash, - const uchar * ntdata, const uchar * nthash, - SAM_ACCOUNT **hnd, char *new_passwd, - int new_passwd_size) +BOOL check_oem_password(char *user, + uchar * lmdata, uchar * lmhash, + uchar * ntdata, uchar * nthash, + SAM_ACCOUNT **hnd, char *new_passwd, + int new_passwd_size) { static uchar null_pw[16]; static uchar null_ntpw[16]; SAM_ACCOUNT *sampass = NULL; - const uint8 *lanman_pw, *nt_pw; + uint8 *lanman_pw, *nt_pw; uint16 acct_ctrl; int new_pw_len; uchar new_ntp16[16]; @@ -802,6 +759,7 @@ static BOOL check_oem_password(const char *user, if (ret == False) { DEBUG(0, ("check_oem_password: getsmbpwnam returned NULL\n")); + pdb_free_sam(sampass); return False; } @@ -825,23 +783,29 @@ static BOOL check_oem_password(const char *user, /* check for null passwords */ if (lanman_pw == NULL) { - if (!(acct_ctrl & ACB_PWNOTREQ)) { + if (acct_ctrl & ACB_PWNOTREQ) { + if (!pdb_set_lanman_passwd(sampass, null_pw)) { + return False; + } + } else { DEBUG(0,("check_oem_password: no lanman password !\n")); return False; } } - + if (pdb_get_nt_passwd(sampass) == NULL && nt_pass_set) { - if (!(acct_ctrl & ACB_PWNOTREQ)) { + if (acct_ctrl & ACB_PWNOTREQ) + pdb_set_nt_passwd(sampass, null_pw); + else { DEBUG(0,("check_oem_password: no ntlm password !\n")); return False; } } - + /* * Call the hash function to get the new password. */ - SamOEMhash( lmdata, lanman_pw, 516); + SamOEMhash((uchar *) lmdata, (uchar *)lanman_pw, 516); /* * The length of the new password is in the last 4 bytes of @@ -858,9 +822,11 @@ static BOOL check_oem_password(const char *user, /* * nt passwords are in unicode */ - pull_ucs2(NULL, new_passwd, - (const smb_ucs2_t *)&lmdata[512 - new_pw_len], - new_passwd_size, new_pw_len, 0); + int uni_pw_len = new_pw_len; + char *pw; + new_pw_len /= 2; + pw = dos_unistrn2((uint16 *)(&lmdata[512 - uni_pw_len]), new_pw_len); + memcpy(new_passwd, pw, new_pw_len + 1); } else { memcpy(new_passwd, &lmdata[512 - new_pw_len], new_pw_len); new_passwd[new_pw_len] = 0; @@ -921,23 +887,81 @@ static BOOL check_oem_password(const char *user, /*********************************************************** Code to change the oem password. Changes both the lanman and NT hashes. + override = False, normal + override = True, override XXXXXXXXXX'd password ************************************************************/ -BOOL change_oem_password(SAM_ACCOUNT *hnd, char *new_passwd) +BOOL change_oem_password(SAM_ACCOUNT *hnd, char *new_passwd, + BOOL override) { BOOL ret; + uchar new_nt_p16[16]; + uchar new_p16[16]; + + nt_lm_owf_gen(new_passwd, new_nt_p16, new_p16); - if (!pdb_set_plaintext_passwd (hnd, new_passwd)) { + if (!pdb_set_lanman_passwd (hnd, new_p16)) + return False; + if (!pdb_set_nt_passwd(hnd, new_nt_p16)) return False; - } /* Now write it into the file. */ become_root(); - ret = pdb_update_sam_account (hnd); + ret = pdb_update_sam_account (hnd, override); unbecome_root(); + memset(new_passwd, '\0', strlen(new_passwd)); + return ret; } +/*********************************************************** + Code to check a plaintext password against smbpasswd entries. +***********************************************************/ +BOOL check_plaintext_password(char *user, char *old_passwd, + int old_passwd_size, SAM_ACCOUNT **hnd) +{ + SAM_ACCOUNT *sampass = NULL; + uchar old_pw[16], old_ntpw[16]; + BOOL ret; + + pdb_init_sam(&sampass); + become_root(); + ret = pdb_getsampwnam(sampass, user); + unbecome_root(); + + *hnd = sampass; + + if (ret == False) + { + DEBUG(0,("check_plaintext_password: getsmbpwnam returned NULL\n")); + return False; + } + + if (pdb_get_acct_ctrl(sampass) & ACB_DISABLED) + { + DEBUG(0,("check_plaintext_password: account %s disabled.\n", user)); + return (False); + } + + nt_lm_owf_gen(old_passwd, old_ntpw, old_pw); + +#ifdef DEBUG_PASSWORD + DEBUG(100, ("check_plaintext_password: nt_passwd \n")); + dump_data(100, pdb_get_nt_passwd(sampass), 16); + DEBUG(100, ("check_plaintext_password: old_ntpw \n")); + dump_data(100, old_ntpw, 16); + DEBUG(100, ("check_plaintext_password: lanman_passwd \n")); + dump_data(100, pdb_get_lanman_passwd(sampass), 16); + DEBUG(100, ("check_plaintext_password: old_pw\n")); + dump_data(100, old_pw, 16); +#endif + + if (memcmp(pdb_get_nt_passwd(sampass), old_ntpw, 16) + && memcmp(pdb_get_lanman_passwd(sampass), old_pw, 16)) + return (False); + else + return (True); +} |