summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorLuke Leighton <lkcl@samba.org>1998-10-19 17:32:10 +0000
committerLuke Leighton <lkcl@samba.org>1998-10-19 17:32:10 +0000
commit01de6030843f5f402dee8bf72f564a91ae8437ca (patch)
tree2319ade00e775979ed5d3343bb8a89a21aa2bc2b /source3/smbd
parent33790c41501af0e8fdc2fbc7128cf2a42cafa087 (diff)
downloadsamba-01de6030843f5f402dee8bf72f564a91ae8437ca.tar.gz
samba-01de6030843f5f402dee8bf72f564a91ae8437ca.tar.bz2
samba-01de6030843f5f402dee8bf72f564a91ae8437ca.zip
- dce/rpc code
- removed debug info in struni2 and unistr2 (security risk) - rpc_pipe function was getting pointer to data then calling realloc *dur* - password check function, the start of "credential checking", user, wks, domain, pass as the credentials (not just user,pass which is incorrect in a domain context) - cli_write needs to return ssize_t not size_t, because total can be -1 if the write fails. - fixed signed / unsigned warnings (how come i don't get those any more when i compile with gcc???) - nt password change added in smbd. yes, jeremy, i verified that the SMBtrans2 version still works. (This used to be commit fcfb40d2b0fc565ee4f66b3a3761c246366a2ef3)
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/chgpasswd.c323
-rw-r--r--source3/smbd/ipc.c24
-rw-r--r--source3/smbd/password.c23
-rw-r--r--source3/smbd/reply.c2
4 files changed, 234 insertions, 138 deletions
diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c
index 4131bc9297..45497e4cf8 100644
--- a/source3/smbd/chgpasswd.c
+++ b/source3/smbd/chgpasswd.c
@@ -69,7 +69,7 @@ static int findpty(char **slave)
grantpt(master);
unlockpt(master);
*slave = ptsname(master);
- if(*slave == NULL) {
+ if (*slave == NULL) {
DEBUG(0,("findpty: Unable to create master/slave pty pair.\n"));
return -1;
} else {
@@ -109,7 +109,7 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram,
int gid;
int uid;
- if(pass == NULL) {
+ if (pass == NULL) {
DEBUG(0,("dochild: user name %s doesn't exist in the UNIX password database.\n",
name));
return False;
@@ -180,7 +180,7 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram,
}
/* make us completely into the right uid */
- if(!as_root) {
+ if (!as_root) {
#ifdef HAVE_SETRESUID
setresgid(0,0,0);
setresuid(0,0,0);
@@ -269,7 +269,7 @@ static int talktochild(int master, char *chatsequence)
if (!strequal(chatbuf,"."))
ok = expect(master,chatbuf,buf);
- if(lp_passwd_chat_debug())
+ if (lp_passwd_chat_debug())
DEBUG(100,("talktochild: chatbuf=[%s] responsebuf=[%s]\n",chatbuf,buf));
if (!ok) {
@@ -282,7 +282,7 @@ static int talktochild(int master, char *chatsequence)
if (!strequal(chatbuf,"."))
writestring(master,chatbuf);
- if(lp_passwd_chat_debug())
+ if (lp_passwd_chat_debug())
DEBUG(100,("talktochild: sendbuf=[%s]\n",chatbuf));
}
@@ -352,16 +352,16 @@ static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequenc
/* make sure it doesn't freeze */
alarm(20);
- if(as_root)
+ if (as_root)
become_root(False);
DEBUG(3,("Dochild for user %s (uid=%d,gid=%d)\n",name,(int)getuid(),(int)getgid()));
chstat = dochild(master, slavedev, name, passwordprogram, as_root);
- if(as_root)
+ if (as_root)
unbecome_root(False);
}
- if(chstat)
+ if (chstat)
DEBUG(3,("Password change %ssuccessful for user %s\n", (chstat?"":"un"), name));
return (chstat);
}
@@ -416,7 +416,7 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root)
len = strlen(oldpass);
for(i = 0; i < len; i++) {
- if(iscntrl((int)oldpass[i])) {
+ if (iscntrl((int)oldpass[i])) {
DEBUG(0,("chat_with_program: oldpass contains control characters (disallowed).\n"));
return False;
}
@@ -424,7 +424,7 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root)
len = strlen(newpass);
for(i = 0; i < len; i++) {
- if(iscntrl((int)newpass[i])) {
+ if (iscntrl((int)newpass[i])) {
DEBUG(0,("chat_with_program: newpass contains control characters (disallowed).\n"));
return False;
}
@@ -452,12 +452,12 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root)
Code to check the lanman hashed password.
************************************************************/
-BOOL check_lanman_password(char *user, unsigned char *pass1,
- unsigned char *pass2, struct smb_passwd **psmbpw)
+BOOL check_lanman_password(char *user, uchar *pass1,
+ uchar *pass2, struct smb_passwd **psmbpw)
{
- unsigned char unenc_new_pw[16];
- unsigned char unenc_old_pw[16];
- unsigned char null_pw[16];
+ uchar unenc_new_pw[16];
+ uchar unenc_old_pw[16];
+ uchar null_pw[16];
struct smb_passwd *smbpw;
*psmbpw = NULL;
@@ -466,21 +466,21 @@ BOOL check_lanman_password(char *user, unsigned char *pass1,
smbpw = getsmbpwnam(user);
unbecome_root(0);
- if(smbpw == NULL)
+ if (smbpw == NULL)
{
DEBUG(0,("check_lanman_password: getsmbpwnam returned NULL\n"));
return False;
}
- if(smbpw->acct_ctrl & ACB_DISABLED)
+ if (smbpw->acct_ctrl & ACB_DISABLED)
{
DEBUG(0,("check_lanman_password: account %s disabled.\n", user));
return False;
}
- if((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ))
+ if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ))
{
- unsigned char no_pw[14];
+ uchar no_pw[14];
memset(no_pw, '\0', 14);
E_P16((uchar *)no_pw, (uchar *)null_pw);
smbpw->smb_passwd = null_pw;
@@ -496,7 +496,7 @@ BOOL check_lanman_password(char *user, unsigned char *pass1,
D_P16(unenc_new_pw, pass1, unenc_old_pw);
/* Check that the two old passwords match. */
- if(memcmp(smbpw->smb_passwd, unenc_old_pw, 16))
+ if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16))
{
DEBUG(0,("check_lanman_password: old password doesn't match.\n"));
return False;
@@ -512,27 +512,27 @@ BOOL check_lanman_password(char *user, unsigned char *pass1,
no longer be valid.
************************************************************/
-BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsigned char *pass2)
+BOOL change_lanman_password(struct smb_passwd *smbpw, uchar *pass1, uchar *pass2)
{
- unsigned char unenc_new_pw[16];
- unsigned char null_pw[16];
+ uchar unenc_new_pw[16];
+ uchar null_pw[16];
BOOL ret;
- if(smbpw == NULL)
+ if (smbpw == NULL)
{
DEBUG(0,("change_lanman_password: no smb password entry.\n"));
return False;
}
- if(smbpw->acct_ctrl & ACB_DISABLED)
+ if (smbpw->acct_ctrl & ACB_DISABLED)
{
DEBUG(0,("change_lanman_password: account %s disabled.\n", smbpw->smb_name));
return False;
}
- if((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ))
+ if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ))
{
- unsigned char no_pw[14];
+ uchar no_pw[14];
memset(no_pw, '\0', 14);
E_P16((uchar *)no_pw, (uchar *)null_pw);
smbpw->smb_passwd = null_pw;
@@ -556,90 +556,197 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsi
}
/***********************************************************
- Code to check the OEM hashed password.
+ Code to check and change the OEM hashed password.
************************************************************/
-
-BOOL check_oem_password(char *user, unsigned char *data,
- struct smb_passwd **psmbpw, char *new_passwd,
- int new_passwd_size)
+BOOL pass_oem_change(char *user,
+ uchar *lmdata, uchar *lmhash,
+ uchar *ntdata, uchar *nthash)
{
- struct smb_passwd *smbpw = NULL;
- int new_pw_len;
- fstring upper_case_new_passwd;
- unsigned char new_p16[16];
- unsigned char unenc_old_pw[16];
- unsigned char null_pw[16];
-
- become_root(0);
- *psmbpw = smbpw = getsmbpwnam(user);
- unbecome_root(0);
-
- if(smbpw == NULL)
- {
- DEBUG(0,("check_oem_password: getsmbpwnam returned NULL\n"));
- return False;
- }
-
- if(smbpw->acct_ctrl & ACB_DISABLED)
- {
- DEBUG(0,("check_lanman_password: account %s disabled.\n", user));
- return False;
- }
-
- if((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ))
- {
- unsigned char no_pw[14];
- memset(no_pw, '\0', 14);
- E_P16((uchar *)no_pw, (uchar *)null_pw);
- smbpw->smb_passwd = null_pw;
- } else if (smbpw->smb_passwd == NULL) {
- DEBUG(0,("check_oem_password: no lanman password !\n"));
- return False;
- }
-
- /*
- * Call the hash function to get the new password.
- */
- SamOEMhash( (unsigned char *)data, (unsigned char *)smbpw->smb_passwd, True);
-
- /*
- * The length of the new password is in the last 4 bytes of
- * the data buffer.
- */
- new_pw_len = IVAL(data,512);
- if(new_pw_len < 0 || new_pw_len > new_passwd_size - 1) {
- DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len));
- return False;
- }
-
- memcpy(new_passwd, &data[512-new_pw_len], new_pw_len);
- new_passwd[new_pw_len] = '\0';
-
- /*
- * To ensure we got the correct new password, hash it and
- * use it as a key to test the passed old password.
- */
-
- memset(upper_case_new_passwd, '\0', sizeof(upper_case_new_passwd));
- fstrcpy(upper_case_new_passwd, new_passwd);
- strupper(upper_case_new_passwd);
-
- E_P16((uchar *)upper_case_new_passwd, new_p16);
-
- /*
- * Now use new_p16 as the key to see if the old
- * password matches.
- */
- D_P16(new_p16, &data[516], unenc_old_pw);
+ fstring new_passwd;
+ struct smb_passwd *sampw;
+ BOOL ret = check_oem_password( user, lmdata, lmhash, ntdata, nthash,
+ &sampw,
+ new_passwd, sizeof(new_passwd));
+
+ /*
+ * At this point we have the new case-sensitive plaintext
+ * password in the fstring new_passwd. If we wanted to synchronise
+ * with UNIX passwords we would call a UNIX password changing
+ * function here. However it would have to be done as root
+ * as the plaintext of the old users password is not
+ * available. JRA.
+ */
+
+ if ( ret && lp_unix_password_sync())
+ {
+ ret = chgpasswd(user,"", new_passwd, True);
+ }
+
+ if (ret)
+ {
+ ret = change_oem_password( sampw, new_passwd, False );
+ }
+
+ memset(new_passwd, 0, sizeof(new_passwd));
+
+ return ret;
+}
- if(memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) {
- DEBUG(0,("check_oem_password: old password doesn't match.\n"));
- return False;
- }
+/***********************************************************
+ Code to check the OEM hashed password.
- memset(upper_case_new_passwd, '\0', strlen(upper_case_new_passwd));
+ this function ignores the 516 byte nt OEM hashed password
+ but does use the lm OEM password to check the nt hashed-hash.
- return True;
+************************************************************/
+BOOL check_oem_password(char *user,
+ uchar *lmdata, uchar *lmhash,
+ uchar *ntdata, uchar *nthash,
+ struct smb_passwd **psmbpw, char *new_passwd,
+ int new_passwd_size)
+{
+ struct smb_passwd *smbpw = NULL;
+ int new_pw_len;
+ uchar new_ntp16[16];
+ uchar unenc_old_ntpw[16];
+ uchar new_p16[16];
+ uchar unenc_old_pw[16];
+ uchar null_pw[16];
+ uchar null_ntpw[16];
+ uchar no_pw[2];
+ BOOL nt_pass_set = (ntdata != NULL && nthash != NULL);
+
+ become_root(False);
+ *psmbpw = smbpw = getsmbpwnam(user);
+ unbecome_root(False);
+
+ if (smbpw == NULL)
+ {
+ DEBUG(0,("check_oem_password: getsmbpwnam returned NULL\n"));
+ return False;
+ }
+
+ if (smbpw->acct_ctrl & ACB_DISABLED)
+ {
+ DEBUG(0,("check_lanman_password: account %s disabled.\n", user));
+ return False;
+ }
+
+ /* construct a null password (in case one is needed */
+ no_pw[0] = 0;
+ no_pw[1] = 0;
+ nt_lm_owf_gen(no_pw, null_ntpw, null_pw);
+
+ /* check for null passwords */
+ if (smbpw->smb_passwd == NULL)
+ {
+ if (smbpw->acct_ctrl & ACB_PWNOTREQ)
+ {
+ smbpw->smb_passwd = null_pw;
+ }
+ else
+ {
+ DEBUG(0,("check_oem_password: no lanman password !\n"));
+ return False;
+ }
+ }
+
+ if (smbpw->smb_nt_passwd == NULL && nt_pass_set)
+ {
+ if (smbpw->acct_ctrl & ACB_PWNOTREQ)
+ {
+ smbpw->smb_nt_passwd = null_pw;
+ }
+ else
+ {
+ DEBUG(0,("check_oem_password: no ntlm password !\n"));
+ return False;
+ }
+ }
+
+ /*
+ * Call the hash function to get the new password.
+ */
+ SamOEMhash( (uchar *)lmdata, (uchar *)smbpw->smb_passwd, True);
+
+ /*
+ * The length of the new password is in the last 4 bytes of
+ * the data buffer.
+ */
+
+ new_pw_len = IVAL(lmdata, 512);
+ if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1)
+ {
+ DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len));
+ return False;
+ }
+
+ if (nt_pass_set)
+ {
+ /*
+ * nt passwords are in unicode
+ */
+ int uni_pw_len = new_pw_len;
+ char *pw;
+ new_pw_len /= 2;
+ pw = 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';
+ }
+
+ /*
+ * To ensure we got the correct new password, hash it and
+ * use it as a key to test the passed old password.
+ */
+
+ nt_lm_owf_gen(new_passwd, new_ntp16, new_p16);
+
+ if (!nt_pass_set)
+ {
+ /*
+ * Now use new_p16 as the key to see if the old
+ * password matches.
+ */
+ D_P16(new_p16 , lmhash, unenc_old_pw);
+
+ if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16))
+ {
+ DEBUG(0,("check_oem_password: old lm password doesn't match.\n"));
+ return False;
+ }
+
+#ifdef DEBUG_PASSWORD
+ DEBUG(100,("check_oem_password: password %s ok\n", new_passwd));
+#endif
+ return True;
+ }
+
+ /*
+ * Now use new_p16 as the key to see if the old
+ * password matches.
+ */
+ D_P16(new_ntp16, lmhash, unenc_old_pw);
+ D_P16(new_ntp16, nthash, unenc_old_ntpw);
+
+ if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16))
+ {
+ DEBUG(0,("check_oem_password: old lm password doesn't match.\n"));
+ return False;
+ }
+
+ if (memcmp(smbpw->smb_nt_passwd, unenc_old_ntpw, 16))
+ {
+ DEBUG(0,("check_oem_password: old nt password doesn't match.\n"));
+ return False;
+ }
+#ifdef DEBUG_PASSWORD
+ DEBUG(100,("check_oem_password: password %s ok\n", new_passwd));
+#endif
+ return True;
}
/***********************************************************
@@ -653,8 +760,8 @@ BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, BOOL overri
{
int ret;
fstring upper_case_new_passwd;
- unsigned char new_nt_p16[16];
- unsigned char new_p16[16];
+ uchar new_nt_p16[16];
+ uchar new_p16[16];
memset(upper_case_new_passwd, '\0', sizeof(upper_case_new_passwd));
fstrcpy(upper_case_new_passwd, new_passwd);
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c
index df04cd82a0..2b8b8698db 100644
--- a/source3/smbd/ipc.c
+++ b/source3/smbd/ipc.c
@@ -1692,11 +1692,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
int *rdata_len,int *rparam_len)
{
fstring user;
- fstring new_passwd;
- struct smb_passwd *sampw = NULL;
char *p = param + 2;
- int ret = True;
-
*rparam_len = 2;
*rparam = REALLOC(*rparam,*rparam_len);
@@ -1736,24 +1732,8 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
*/
(void)Get_Pwnam( user, True);
- if(check_oem_password( user, (unsigned char *)data, &sampw,
- new_passwd, (int)sizeof(new_passwd)) == False) {
- return True;
- }
-
- /*
- * At this point we have the new case-sensitive plaintext
- * password in the fstring new_passwd. If we wanted to synchronise
- * with UNIX passwords we would call a UNIX password changing
- * function here. However it would have to be done as root
- * as the plaintext of the old users password is not
- * available. JRA.
- */
-
- if(lp_unix_password_sync())
- ret = chgpasswd(user,"", new_passwd, True);
-
- if(ret && change_oem_password( sampw, new_passwd, False)) {
+ if (pass_oem_change(user, (uchar*) data, &data[516], NULL, NULL))
+ {
SSVAL(*rparam,0,NERR_Success);
}
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index 1c9eb19759..eac8c9cd65 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -383,8 +383,7 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha
Do a specific test for an smb password being correct, given a smb_password and
the lanman and NT responses.
****************************************************************************/
-
-BOOL smb_password_ok(struct smb_passwd *smb_pass,
+BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8],
uchar lm_pass[24], uchar nt_pass[24])
{
uchar challenge[8];
@@ -400,9 +399,19 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass,
return(False);
}
- if (!last_challenge(challenge)) {
- DEBUG(1,("no challenge done - password failed\n"));
- return False;
+ if (chal == NULL)
+ {
+ DEBUG(5,("use last SMBnegprot challenge\n"));
+ if (!last_challenge(challenge))
+ {
+ DEBUG(1,("no challenge done - password failed\n"));
+ return False;
+ }
+ }
+ else
+ {
+ DEBUG(5,("challenge received\n"));
+ memcpy(challenge, chal, 8);
}
if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL)) {
@@ -450,7 +459,7 @@ SMB hash
return True if the password is correct, False otherwise
****************************************************************************/
BOOL pass_check_smb(char *user, char *domain,
- char *challenge, char *lm_pwd, char *nt_pwd,
+ uchar *chal, char *lm_pwd, char *nt_pwd,
struct passwd *pwd)
{
struct passwd *pass;
@@ -504,7 +513,7 @@ BOOL pass_check_smb(char *user, char *domain,
return(True);
}
- if (smb_password_ok(smb_pass, (uchar *)lm_pwd, (uchar *)nt_pwd))
+ if (smb_password_ok(smb_pass, chal, (uchar *)lm_pwd, (uchar *)nt_pwd))
{
return(True);
}
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index bcb408c2a6..8b96ff17fd 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -413,7 +413,7 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out
return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
}
- if (!smb_password_ok(smb_trust_acct, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
+ if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
{
DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);