summaryrefslogtreecommitdiffstats
path: root/source/smbd
diff options
context:
space:
mode:
authorLuke Leighton <lkcl@samba.org>1999-06-29 18:47:06 +0000
committerLuke Leighton <lkcl@samba.org>1999-06-29 18:47:06 +0000
commitab1a6aa42db5217f025941fb5107436556bc23b7 (patch)
tree1bc342852e54df8cbf73de89d49871b5c3d12091 /source/smbd
parentde9a38b0bcb5adcb6e502f2200d3e84bdcbdfc48 (diff)
downloadsamba-ab1a6aa42db5217f025941fb5107436556bc23b7.tar.gz
samba-ab1a6aa42db5217f025941fb5107436556bc23b7.tar.xz
samba-ab1a6aa42db5217f025941fb5107436556bc23b7.zip
improving authentication code (tidyup).
Diffstat (limited to 'source/smbd')
-rw-r--r--source/smbd/password.c147
-rw-r--r--source/smbd/reply.c8
-rw-r--r--source/smbd/service.c4
3 files changed, 109 insertions, 50 deletions
diff --git a/source/smbd/password.c b/source/smbd/password.c
index c05b82ef150..14a63c6ef43 100644
--- a/source/smbd/password.c
+++ b/source/smbd/password.c
@@ -292,51 +292,78 @@ static BOOL update_smbpassword_file(char *user, char *password)
/****************************************************************************
core of smb password checking routine.
****************************************************************************/
-BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8)
+static BOOL smb_pwd_check_ntlmv1(char *password, unsigned char *part_passwd,
+ unsigned char *c8)
{
/* Finish the encryption of part_passwd. */
- unsigned char p21[21];
unsigned char p24[24];
if (part_passwd == NULL)
DEBUG(10,("No password set - allowing access\n"));
/* No password set - always true ! */
if (part_passwd == NULL)
- return 1;
+ return True;
- memset(p21,'\0',21);
- memcpy(p21,part_passwd,16);
- E_P24(p21, c8, p24);
+ SMBOWFencrypt(part_passwd, c8, p24);
#if DEBUG_PASSWORD
- {
- int i;
- DEBUG(100,("Part password (P16) was |"));
- for(i = 0; i < 16; i++)
- DEBUG(100,("%X ", (unsigned char)part_passwd[i]));
- DEBUG(100,("|\n"));
- DEBUG(100,("Password from client was |"));
- for(i = 0; i < 24; i++)
- DEBUG(100,("%X ", (unsigned char)password[i]));
- DEBUG(100,("|\n"));
- DEBUG(100,("Given challenge was |"));
- for(i = 0; i < 8; i++)
- DEBUG(100,("%X ", (unsigned char)c8[i]));
- DEBUG(100,("|\n"));
- DEBUG(100,("Value from encryption was |"));
- for(i = 0; i < 24; i++)
- DEBUG(100,("%X ", (unsigned char)p24[i]));
- DEBUG(100,("|\n"));
- }
+ DEBUG(100,("Part password (P16) was |"));
+ dump_data(100, part_passwd, 16);
+ DEBUG(100,("Password from client was |"));
+ dump_data(100, password, 24);
+ DEBUG(100,("Given challenge was |"));
+ dump_data(100, c8, 8);
+ DEBUG(100,("Value from encryption was |"));
+ dump_data(100, p24, 24);
#endif
return (memcmp(p24, password, 24) == 0);
}
/****************************************************************************
+core of smb password checking routine.
+****************************************************************************/
+static BOOL smb_pwd_check_ntlmv2(char *password, size_t pwd_len,
+ unsigned char *part_passwd,
+ unsigned char const *c8,
+ const char *user, const char *domain)
+{
+ /* Finish the encryption of part_passwd. */
+ unsigned char kr[16];
+
+ if (part_passwd == NULL)
+ {
+ DEBUG(10,("No password set - allowing access\n"));
+ }
+ /* No password set - always true ! */
+ if (part_passwd == NULL)
+ {
+ return True;
+ }
+
+ ntv2_owf_gen(part_passwd, user, domain, kr);
+ SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, kr);
+
+#if DEBUG_PASSWORD
+ DEBUG(100,("Part password (P16) was |"));
+ dump_data(100, part_passwd, 16);
+ DEBUG(100,("Password from client was |"));
+ dump_data(100, password, pwd_len);
+ DEBUG(100,("Given challenge was |"));
+ dump_data(100, c8, 8);
+ DEBUG(100,("Value from encryption was |"));
+ dump_data(100, kr, 16);
+#endif
+
+ return (memcmp(kr, password, 16) == 0);
+}
+
+/****************************************************************************
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, uchar chal[8],
- uchar lm_pass[24], uchar nt_pass[24])
+ const char *user, const char *domain,
+ uchar *lm_pass, size_t lm_pwd_len,
+ uchar *nt_pass, size_t nt_pwd_len)
{
uchar challenge[8];
@@ -345,7 +372,8 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8],
DEBUG(4,("Checking SMB password for user %s\n",
smb_pass->unix_name));
- if(smb_pass->acct_ctrl & ACB_DISABLED) {
+ if (smb_pass->acct_ctrl & ACB_DISABLED)
+ {
DEBUG(3,("account for user %s was disabled.\n",
smb_pass->unix_name));
return(False);
@@ -366,35 +394,59 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8],
memcpy(challenge, chal, 8);
}
- if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL)) {
+ if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL))
+ {
/* We have the NT MD4 hash challenge available - see if we can
use it (ie. does it exist in the smbpasswd file).
*/
- DEBUG(4,("smb_password_ok: Checking NT MD4 password\n"));
- if (smb_password_check((char *)nt_pass,
+ if (lp_server_ntlmv2())
+ {
+ DEBUG(4,("smb_password_ok: Check NTLMv2 password\n"));
+ if (smb_pwd_check_ntlmv2(nt_pass, nt_pwd_len,
+ (uchar *)smb_pass->smb_nt_passwd,
+ challenge, user, domain))
+ {
+ return True;
+ }
+ }
+ if (lp_server_ntlmv2() != True && nt_pwd_len == 24)
+ {
+ DEBUG(4,("smb_password_ok: Check NT MD4 password\n"));
+ if (smb_pwd_check_ntlmv1((char *)nt_pass,
(uchar *)smb_pass->smb_nt_passwd,
- challenge)) {
- DEBUG(4,("NT MD4 password check succeeded\n"));
- return(True);
+ challenge))
+ {
+ DEBUG(4,("NT MD4 password check succeeded\n"));
+ return True;
+ }
}
DEBUG(4,("NT MD4 password check failed\n"));
}
+ if (lp_server_ntlmv2() == False)
+ {
+ DEBUG(4,("Not checking LM MD4 password\n"));
+ return False;
+ }
+
/* Try against the lanman password. smb_pass->smb_passwd == NULL means
no password, allow access. */
DEBUG(4,("Checking LM MD4 password\n"));
- if((smb_pass->smb_passwd == NULL) &&
- (smb_pass->acct_ctrl & ACB_PWNOTREQ)) {
+ if ((smb_pass->smb_passwd == NULL) &&
+ (smb_pass->acct_ctrl & ACB_PWNOTREQ))
+ {
DEBUG(4,("no password required for user %s\n",
smb_pass->unix_name));
return True;
}
- if((smb_pass->smb_passwd != NULL) &&
- smb_password_check((char *)lm_pass,
- (uchar *)smb_pass->smb_passwd, challenge)) {
+ if ((smb_pass->smb_passwd != NULL) &&
+ smb_pwd_check_ntlmv1((char *)lm_pass,
+ (uchar *)smb_pass->smb_passwd,
+ challenge))
+ {
DEBUG(4,("LM MD4 password check succeeded\n"));
return(True);
}
@@ -411,8 +463,9 @@ SMB hash
return True if the password is correct, False otherwise
****************************************************************************/
-BOOL pass_check_smb(char *user, char *domain,
- uchar *chal, uchar *lm_pwd, uchar *nt_pwd,
+BOOL pass_check_smb(char *user, char *domain, uchar *chal,
+ uchar *lm_pwd, size_t lm_pwd_len,
+ uchar *nt_pwd, size_t nt_pwd_len,
struct passwd *pwd, uchar user_sess_key[16])
{
const struct passwd *pass;
@@ -466,7 +519,9 @@ BOOL pass_check_smb(char *user, char *domain,
return(True);
}
- if (smb_password_ok(smb_pass, chal, lm_pwd, nt_pwd))
+ if (smb_password_ok(smb_pass, chal, user, domain,
+ lm_pwd, lm_pwd_len,
+ nt_pwd, nt_pwd_len))
{
if (user_sess_key != NULL)
{
@@ -479,7 +534,7 @@ BOOL pass_check_smb(char *user, char *domain,
return(True);
}
- DEBUG(3,("Error smb_password_check failed\n"));
+ DEBUG(3,("Error pass_check_smb failed\n"));
return False;
}
@@ -491,9 +546,9 @@ return True if the password is correct, False otherwise
BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd,
uchar user_sess_key[16])
{
- if (pwlen == 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords()))
+ if (pwlen >= 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords()))
{
- /* if 24 bytes long assume it is an encrypted password */
+ /* if 24 bytes or longer assume it is an encrypted password */
uchar challenge[8];
if (!last_challenge(challenge))
@@ -503,7 +558,9 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd,
}
return pass_check_smb(user, global_myworkgroup,
- challenge, (uchar *)password, (uchar *)password, pwd, user_sess_key);
+ challenge, (uchar *)password,
+ pwlen, (uchar *)password, pwlen,
+ pwd, user_sess_key);
}
return pass_check(user, password, pwlen, pwd,
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index 58f327771d6..c44cf069a9a 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -441,7 +441,9 @@ 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, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
+ if (!smb_password_ok(smb_trust_acct, NULL, NULL, NULL,
+ (unsigned char *)smb_passwd, smb_passlen,
+ (unsigned char *)smb_nt_passwd, smb_nt_passlen))
{
DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
@@ -570,7 +572,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int
set_remote_arch( RA_WIN95);
}
- if (passlen1 != 24 && passlen2 != 24)
+ if (passlen1 != 24 && passlen2 <= 24)
doencrypt = False;
if (passlen1 > MAX_PASS_LEN) {
@@ -593,7 +595,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int
setting passlen2 to some random value which really stuffs
things up. we need to fix that one. */
- if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
+ if (passlen1 > 0 && passlen2 > 0 && passlen2 <= 24 && passlen2 != 1)
passlen2 = 0;
}
diff --git a/source/smbd/service.c b/source/smbd/service.c
index becfd01504d..232579a0f16 100644
--- a/source/smbd/service.c
+++ b/source/smbd/service.c
@@ -390,10 +390,10 @@ connection_struct *make_connection(char *service,char *user,char *password, int
#endif
if (*lp_force_user(snum)) {
- struct passwd *pass2;
+ const struct passwd *pass2;
fstring fuser;
fstrcpy(fuser,lp_force_user(snum));
- pass2 = (struct passwd *)Get_Pwnam(fuser,True);
+ pass2 = (const struct passwd *)Get_Pwnam(fuser,True);
if (pass2) {
conn->uid = pass2->pw_uid;
string_set(&conn->user,fuser);