[CIFS] Support for setting up SMB sessions to legacy lanman servers part 2
This commit is contained in:
@@ -508,7 +508,7 @@ cifs_proc_init(void)
|
|||||||
pde->write_proc = multiuser_mount_write;
|
pde->write_proc = multiuser_mount_write;
|
||||||
|
|
||||||
pde =
|
pde =
|
||||||
create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs,
|
create_proc_read_entry("SecurityFlags", 0, proc_fs_cifs,
|
||||||
extended_security_read, NULL);
|
extended_security_read, NULL);
|
||||||
if (pde)
|
if (pde)
|
||||||
pde->write_proc = extended_security_write;
|
pde->write_proc = extended_security_write;
|
||||||
@@ -547,7 +547,7 @@ cifs_proc_clean(void)
|
|||||||
remove_proc_entry("MultiuserMount", proc_fs_cifs);
|
remove_proc_entry("MultiuserMount", proc_fs_cifs);
|
||||||
remove_proc_entry("OplockEnabled", proc_fs_cifs);
|
remove_proc_entry("OplockEnabled", proc_fs_cifs);
|
||||||
/* remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
|
/* remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
|
||||||
remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
|
remove_proc_entry("SecurityFlags",proc_fs_cifs);
|
||||||
/* remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); */
|
/* remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); */
|
||||||
remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
|
remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
|
||||||
remove_proc_entry("Experimental",proc_fs_cifs);
|
remove_proc_entry("Experimental",proc_fs_cifs);
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#include "md5.h"
|
#include "md5.h"
|
||||||
#include "cifs_unicode.h"
|
#include "cifs_unicode.h"
|
||||||
#include "cifsproto.h"
|
#include "cifsproto.h"
|
||||||
|
#include <linux/ctype.h>
|
||||||
|
|
||||||
/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
|
/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
|
||||||
/* the 16 byte signature must be allocated by the caller */
|
/* the 16 byte signature must be allocated by the caller */
|
||||||
@@ -35,6 +36,8 @@
|
|||||||
|
|
||||||
extern void mdfour(unsigned char *out, unsigned char *in, int n);
|
extern void mdfour(unsigned char *out, unsigned char *in, int n);
|
||||||
extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
|
extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
|
||||||
|
extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
|
||||||
|
unsigned char *p24);
|
||||||
|
|
||||||
static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu,
|
static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu,
|
||||||
const char * key, char * signature)
|
const char * key, char * signature)
|
||||||
@@ -45,7 +48,7 @@ static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
MD5Init(&context);
|
MD5Init(&context);
|
||||||
MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
|
MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
|
||||||
MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
|
MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
|
||||||
MD5Final(signature,&context);
|
MD5Final(signature,&context);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -90,7 +93,7 @@ static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
MD5Init(&context);
|
MD5Init(&context);
|
||||||
MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
|
MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
|
||||||
for(i=0;i<n_vec;i++) {
|
for(i=0;i<n_vec;i++) {
|
||||||
if(iov[i].iov_base == NULL) {
|
if(iov[i].iov_base == NULL) {
|
||||||
cERROR(1,("null iovec entry"));
|
cERROR(1,("null iovec entry"));
|
||||||
@@ -204,7 +207,7 @@ int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
|
|||||||
|
|
||||||
E_md4hash(password, temp_key);
|
E_md4hash(password, temp_key);
|
||||||
mdfour(key,temp_key,16);
|
mdfour(key,temp_key,16);
|
||||||
memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE);
|
memcpy(key+16,rn, CIFS_SESS_KEY_SIZE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,6 +264,37 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
|
|||||||
kfree(unicode_buf);
|
kfree(unicode_buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||||
|
void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char password_with_pad[CIFS_ENCPWD_SIZE];
|
||||||
|
|
||||||
|
memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
|
||||||
|
strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
|
||||||
|
|
||||||
|
/* calculate old style session key */
|
||||||
|
/* calling toupper is less broken than repeatedly
|
||||||
|
calling nls_toupper would be since that will never
|
||||||
|
work for UTF8, but neither handles multibyte code pages
|
||||||
|
but the only alternative would be converting to UCS-16 (Unicode)
|
||||||
|
(using a routine something like UniStrupr) then
|
||||||
|
uppercasing and then converting back from Unicode - which
|
||||||
|
would only worth doing it if we knew it were utf8. Basically
|
||||||
|
utf8 and other multibyte codepages each need their own strupper
|
||||||
|
function since a byte at a time will ont work. */
|
||||||
|
|
||||||
|
for(i = 0; i < CIFS_ENCPWD_SIZE; i++) {
|
||||||
|
password_with_pad[i] = toupper(password_with_pad[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
SMBencrypt(password_with_pad, ses->server->cryptKey, lnm_session_key);
|
||||||
|
/* clear password before we return/free memory */
|
||||||
|
memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
|
||||||
|
}
|
||||||
|
#endif /* CIFS_WEAK_PW_HASH */
|
||||||
|
|
||||||
void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response)
|
void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response)
|
||||||
{
|
{
|
||||||
struct HMACMD5Context context;
|
struct HMACMD5Context context;
|
||||||
|
@@ -158,7 +158,7 @@ struct TCP_Server_Info {
|
|||||||
/* 16th byte of RFC1001 workstation name is always null */
|
/* 16th byte of RFC1001 workstation name is always null */
|
||||||
char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
|
char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
|
||||||
__u32 sequence_number; /* needed for CIFS PDU signature */
|
__u32 sequence_number; /* needed for CIFS PDU signature */
|
||||||
char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
|
char mac_signing_key[CIFS_SESS_KEY_SIZE + 16];
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -116,7 +116,8 @@
|
|||||||
/*
|
/*
|
||||||
* Size of the session key (crypto key encrypted with the password
|
* Size of the session key (crypto key encrypted with the password
|
||||||
*/
|
*/
|
||||||
#define CIFS_SESSION_KEY_SIZE (24)
|
#define CIFS_SESS_KEY_SIZE (24)
|
||||||
|
#define V2_SESS_KEY_SIZE (86)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Maximum user name length
|
* Maximum user name length
|
||||||
|
@@ -287,6 +287,9 @@ extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
|
|||||||
extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
|
extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
|
||||||
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
|
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
|
||||||
extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
|
extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
|
||||||
|
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||||
|
extern void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key);
|
||||||
|
#endif /* CIFS_WEAK_PW_HASH */
|
||||||
extern int CIFSSMBCopy(int xid,
|
extern int CIFSSMBCopy(int xid,
|
||||||
struct cifsTconInfo *source_tcon,
|
struct cifsTconInfo *source_tcon,
|
||||||
const char *fromName,
|
const char *fromName,
|
||||||
|
@@ -438,12 +438,19 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
|||||||
goto neg_err_exit;
|
goto neg_err_exit;
|
||||||
} else if((pSMBr->hdr.WordCount == 13) &&
|
} else if((pSMBr->hdr.WordCount == 13) &&
|
||||||
(pSMBr->DialectIndex == LANMAN_PROT)) {
|
(pSMBr->DialectIndex == LANMAN_PROT)) {
|
||||||
|
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||||
struct lanman_neg_rsp * rsp =
|
struct lanman_neg_rsp * rsp =
|
||||||
(struct lanman_neg_rsp *)pSMBr;
|
(struct lanman_neg_rsp *)pSMBr;
|
||||||
|
|
||||||
|
if((extended_security & CIFSSEC_MAY_LANMAN) ||
|
||||||
/* BB Mark ses struct as negotiated lanman level BB */
|
(extended_security & CIFSSEC_MAY_PLNTXT))
|
||||||
server->secType = LANMAN;
|
server->secType = LANMAN;
|
||||||
|
else {
|
||||||
|
cERROR(1, ("mount failed weak security disabled"
|
||||||
|
" in /proc/fs/cifs/SecurityFlags"));
|
||||||
|
rc = -EOPNOTSUPP;
|
||||||
|
goto neg_err_exit;
|
||||||
|
}
|
||||||
server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
|
server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
|
||||||
server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
|
server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
|
||||||
server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
|
server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
|
||||||
@@ -469,6 +476,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cFYI(1,("LANMAN negotiated")); /* BB removeme BB */
|
cFYI(1,("LANMAN negotiated")); /* BB removeme BB */
|
||||||
|
#else /* weak security disabled */
|
||||||
|
cERROR(1,("mount failed, cifs module not built with "
|
||||||
|
"CIFS_WEAK_PW_HASH support"));
|
||||||
|
rc = -EOPNOTSUPP;
|
||||||
|
#endif /* WEAK_PW_HASH */
|
||||||
goto neg_err_exit;
|
goto neg_err_exit;
|
||||||
} else if(pSMBr->hdr.WordCount != 17) {
|
} else if(pSMBr->hdr.WordCount != 17) {
|
||||||
/* unknown wct */
|
/* unknown wct */
|
||||||
@@ -479,8 +491,13 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
|||||||
server->secMode = pSMBr->SecurityMode;
|
server->secMode = pSMBr->SecurityMode;
|
||||||
if((server->secMode & SECMODE_USER) == 0)
|
if((server->secMode & SECMODE_USER) == 0)
|
||||||
cFYI(1,("share mode security"));
|
cFYI(1,("share mode security"));
|
||||||
server->secType = NTLM; /* BB override default for
|
|
||||||
NTLMv2 or kerberos v5 */
|
if(extended_security & CIFSSEC_MUST_NTLMV2)
|
||||||
|
server->secType = NTLMv2;
|
||||||
|
else
|
||||||
|
server->secType = NTLM;
|
||||||
|
/* else krb5 ... */
|
||||||
|
|
||||||
/* one byte - no need to convert this or EncryptionKeyLen
|
/* one byte - no need to convert this or EncryptionKeyLen
|
||||||
from little endian */
|
from little endian */
|
||||||
server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
|
server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
|
||||||
|
@@ -1990,7 +1990,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
char session_key[CIFS_SESSION_KEY_SIZE],
|
char session_key[CIFS_SESS_KEY_SIZE],
|
||||||
const struct nls_table *nls_codepage)
|
const struct nls_table *nls_codepage)
|
||||||
{
|
{
|
||||||
struct smb_hdr *smb_buffer;
|
struct smb_hdr *smb_buffer;
|
||||||
@@ -2048,15 +2048,15 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
|
pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
|
||||||
|
|
||||||
pSMB->req_no_secext.CaseInsensitivePasswordLength =
|
pSMB->req_no_secext.CaseInsensitivePasswordLength =
|
||||||
cpu_to_le16(CIFS_SESSION_KEY_SIZE);
|
cpu_to_le16(CIFS_SESS_KEY_SIZE);
|
||||||
|
|
||||||
pSMB->req_no_secext.CaseSensitivePasswordLength =
|
pSMB->req_no_secext.CaseSensitivePasswordLength =
|
||||||
cpu_to_le16(CIFS_SESSION_KEY_SIZE);
|
cpu_to_le16(CIFS_SESS_KEY_SIZE);
|
||||||
bcc_ptr = pByteArea(smb_buffer);
|
bcc_ptr = pByteArea(smb_buffer);
|
||||||
memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
|
memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
|
||||||
bcc_ptr += CIFS_SESSION_KEY_SIZE;
|
bcc_ptr += CIFS_SESS_KEY_SIZE;
|
||||||
memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
|
memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
|
||||||
bcc_ptr += CIFS_SESSION_KEY_SIZE;
|
bcc_ptr += CIFS_SESS_KEY_SIZE;
|
||||||
|
|
||||||
if (ses->capabilities & CAP_UNICODE) {
|
if (ses->capabilities & CAP_UNICODE) {
|
||||||
if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
|
if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
|
||||||
@@ -3004,14 +3004,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
SecurityBlob->LmChallengeResponse.Buffer = 0;
|
SecurityBlob->LmChallengeResponse.Buffer = 0;
|
||||||
|
|
||||||
SecurityBlob->NtChallengeResponse.Length =
|
SecurityBlob->NtChallengeResponse.Length =
|
||||||
cpu_to_le16(CIFS_SESSION_KEY_SIZE);
|
cpu_to_le16(CIFS_SESS_KEY_SIZE);
|
||||||
SecurityBlob->NtChallengeResponse.MaximumLength =
|
SecurityBlob->NtChallengeResponse.MaximumLength =
|
||||||
cpu_to_le16(CIFS_SESSION_KEY_SIZE);
|
cpu_to_le16(CIFS_SESS_KEY_SIZE);
|
||||||
memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
|
memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
|
||||||
SecurityBlob->NtChallengeResponse.Buffer =
|
SecurityBlob->NtChallengeResponse.Buffer =
|
||||||
cpu_to_le32(SecurityBlobLength);
|
cpu_to_le32(SecurityBlobLength);
|
||||||
SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
|
SecurityBlobLength += CIFS_SESS_KEY_SIZE;
|
||||||
bcc_ptr += CIFS_SESSION_KEY_SIZE;
|
bcc_ptr += CIFS_SESS_KEY_SIZE;
|
||||||
|
|
||||||
if (ses->capabilities & CAP_UNICODE) {
|
if (ses->capabilities & CAP_UNICODE) {
|
||||||
if (domain == NULL) {
|
if (domain == NULL) {
|
||||||
@@ -3350,22 +3350,33 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
bcc_ptr = &pSMB->Password[0];
|
bcc_ptr = &pSMB->Password[0];
|
||||||
if((ses->server->secMode) & SECMODE_USER) {
|
if((ses->server->secMode) & SECMODE_USER) {
|
||||||
pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
|
pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
|
||||||
|
*bcc_ptr = 0; /* password is null byte */
|
||||||
bcc_ptr++; /* skip password */
|
bcc_ptr++; /* skip password */
|
||||||
|
/* already aligned so no need to do it below */
|
||||||
} else {
|
} else {
|
||||||
pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE);
|
pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
|
||||||
/* BB FIXME add code to fail this if NTLMv2 or Kerberos
|
/* BB FIXME add code to fail this if NTLMv2 or Kerberos
|
||||||
specified as required (when that support is added to
|
specified as required (when that support is added to
|
||||||
the vfs in the future) as only NTLM or the much
|
the vfs in the future) as only NTLM or the much
|
||||||
weaker LANMAN (which we do not send) is accepted
|
weaker LANMAN (which we do not send by default) is accepted
|
||||||
by Samba (not sure whether other servers allow
|
by Samba (not sure whether other servers allow
|
||||||
NTLMv2 password here) */
|
NTLMv2 password here) */
|
||||||
|
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||||
|
if((extended_security & CIFSSEC_MAY_LANMAN) &&
|
||||||
|
(ses->server->secType == LANMAN))
|
||||||
|
calc_lanman_hash(ses, bcc_ptr);
|
||||||
|
else
|
||||||
|
#endif /* CIFS_WEAK_PW_HASH */
|
||||||
SMBNTencrypt(ses->password,
|
SMBNTencrypt(ses->password,
|
||||||
ses->server->cryptKey,
|
ses->server->cryptKey,
|
||||||
bcc_ptr);
|
bcc_ptr);
|
||||||
|
|
||||||
bcc_ptr += CIFS_SESSION_KEY_SIZE;
|
bcc_ptr += CIFS_SESS_KEY_SIZE;
|
||||||
*bcc_ptr = 0;
|
if(ses->capabilities & CAP_UNICODE) {
|
||||||
bcc_ptr++; /* align */
|
/* must align unicode strings */
|
||||||
|
*bcc_ptr = 0; /* null byte password */
|
||||||
|
bcc_ptr++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ses->server->secMode &
|
if(ses->server->secMode &
|
||||||
@@ -3507,7 +3518,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
|
|||||||
struct nls_table * nls_info)
|
struct nls_table * nls_info)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
|
char ntlm_session_key[CIFS_SESS_KEY_SIZE];
|
||||||
int ntlmv2_flag = FALSE;
|
int ntlmv2_flag = FALSE;
|
||||||
int first_time = 0;
|
int first_time = 0;
|
||||||
|
|
||||||
|
@@ -84,7 +84,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
|
|||||||
|
|
||||||
static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
|
static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
|
||||||
{ERRerror, -EIO},
|
{ERRerror, -EIO},
|
||||||
{ERRbadpw, -EPERM},
|
{ERRbadpw, -EACCES}, /* was EPERM */
|
||||||
{ERRbadtype, -EREMOTE},
|
{ERRbadtype, -EREMOTE},
|
||||||
{ERRaccess, -EACCES},
|
{ERRaccess, -EACCES},
|
||||||
{ERRinvtid, -ENXIO},
|
{ERRinvtid, -ENXIO},
|
||||||
|
@@ -28,12 +28,8 @@
|
|||||||
#include "cifs_debug.h"
|
#include "cifs_debug.h"
|
||||||
#include "ntlmssp.h"
|
#include "ntlmssp.h"
|
||||||
#include "nterr.h"
|
#include "nterr.h"
|
||||||
#include <linux/ctype.h>
|
|
||||||
#include <linux/utsname.h>
|
#include <linux/utsname.h>
|
||||||
|
|
||||||
extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
|
|
||||||
unsigned char *p24);
|
|
||||||
|
|
||||||
extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
|
extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
|
||||||
unsigned char *p24);
|
unsigned char *p24);
|
||||||
|
|
||||||
@@ -80,7 +76,7 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
|
|||||||
return capabilities;
|
return capabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
||||||
const struct nls_table * nls_cp)
|
const struct nls_table * nls_cp)
|
||||||
{
|
{
|
||||||
char * bcc_ptr = *pbcc_area;
|
char * bcc_ptr = *pbcc_area;
|
||||||
@@ -130,7 +126,7 @@ void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
|||||||
*pbcc_area = bcc_ptr;
|
*pbcc_area = bcc_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
||||||
const struct nls_table * nls_cp)
|
const struct nls_table * nls_cp)
|
||||||
{
|
{
|
||||||
char * bcc_ptr = *pbcc_area;
|
char * bcc_ptr = *pbcc_area;
|
||||||
@@ -173,7 +169,7 @@ void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
|||||||
*pbcc_area = bcc_ptr;
|
*pbcc_area = bcc_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
|
static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
|
||||||
const struct nls_table * nls_cp)
|
const struct nls_table * nls_cp)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@@ -255,7 +251,7 @@ int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
|
static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
|
||||||
const struct nls_table * nls_cp)
|
const struct nls_table * nls_cp)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@@ -317,7 +313,6 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int wct;
|
int wct;
|
||||||
int i;
|
|
||||||
struct smb_hdr *smb_buf;
|
struct smb_hdr *smb_buf;
|
||||||
char *bcc_ptr;
|
char *bcc_ptr;
|
||||||
SESSION_SETUP_ANDX *pSMB;
|
SESSION_SETUP_ANDX *pSMB;
|
||||||
@@ -343,7 +338,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
#endif
|
#endif
|
||||||
wct = 10; /* lanman 2 style sessionsetup */
|
wct = 10; /* lanman 2 style sessionsetup */
|
||||||
} else if(type == NTLM) /* NTLMv2 may retry NTLM */
|
} else if((type == NTLM) || (type == NTLMv2)) /* NTLMv2 may retry NTLM */
|
||||||
wct = 13; /* old style NTLM sessionsetup */
|
wct = 13; /* old style NTLM sessionsetup */
|
||||||
else /* same size for negotiate or auth, NTLMSSP or extended security */
|
else /* same size for negotiate or auth, NTLMSSP or extended security */
|
||||||
wct = 12;
|
wct = 12;
|
||||||
@@ -360,41 +355,22 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||||||
|
|
||||||
if(type == LANMAN) {
|
if(type == LANMAN) {
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||||
char lnm_session_key[CIFS_SESSION_KEY_SIZE];
|
char lnm_session_key[CIFS_SESS_KEY_SIZE];
|
||||||
char password_with_pad[CIFS_ENCPWD_SIZE];
|
|
||||||
|
|
||||||
/* no capabilities flags in old lanman negotiation */
|
/* no capabilities flags in old lanman negotiation */
|
||||||
|
|
||||||
pSMB->old_req.PasswordLength = CIFS_SESSION_KEY_SIZE;
|
pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE;
|
||||||
/* BB calculate hash with password */
|
/* BB calculate hash with password */
|
||||||
/* and copy into bcc */
|
/* and copy into bcc */
|
||||||
|
|
||||||
memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
|
calc_lanman_hash(ses, lnm_session_key);
|
||||||
strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
|
|
||||||
|
|
||||||
/* calculate old style session key */
|
|
||||||
/* toupper may be less broken then repeatedly calling
|
|
||||||
nls_toupper would be, but neither handles multibyte code pages
|
|
||||||
but the only alternative would be converting to UCS-16 (Unicode)
|
|
||||||
uppercasing and converting back which is only worth doing if
|
|
||||||
we knew it were utf8. utf8 code page needs its own
|
|
||||||
toupper and tolower and strnicmp functions */
|
|
||||||
|
|
||||||
for(i = 0; i< CIFS_ENCPWD_SIZE; i++) {
|
|
||||||
password_with_pad[i] = toupper(password_with_pad[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
SMBencrypt(password_with_pad, ses->server->cryptKey,
|
|
||||||
lnm_session_key);
|
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_DEBUG2
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
|
cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
|
||||||
CIFS_SESSION_KEY_SIZE);
|
CIFS_SESS_KEY_SIZE);
|
||||||
#endif
|
#endif
|
||||||
/* clear password before we return/free memory */
|
memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
|
||||||
memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
|
bcc_ptr += CIFS_SESS_KEY_SIZE;
|
||||||
memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESSION_KEY_SIZE);
|
|
||||||
bcc_ptr += CIFS_SESSION_KEY_SIZE;
|
|
||||||
|
|
||||||
/* can not sign if LANMAN negotiated so no need
|
/* can not sign if LANMAN negotiated so no need
|
||||||
to calculate signing key? but what if server
|
to calculate signing key? but what if server
|
||||||
@@ -406,13 +382,13 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||||||
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
||||||
#endif
|
#endif
|
||||||
} else if (type == NTLM) {
|
} else if (type == NTLM) {
|
||||||
char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
|
char ntlm_session_key[CIFS_SESS_KEY_SIZE];
|
||||||
|
|
||||||
pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
|
pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
|
||||||
pSMB->req_no_secext.CaseInsensitivePasswordLength =
|
pSMB->req_no_secext.CaseInsensitivePasswordLength =
|
||||||
cpu_to_le16(CIFS_SESSION_KEY_SIZE);
|
cpu_to_le16(CIFS_SESS_KEY_SIZE);
|
||||||
pSMB->req_no_secext.CaseSensitivePasswordLength =
|
pSMB->req_no_secext.CaseSensitivePasswordLength =
|
||||||
cpu_to_le16(CIFS_SESSION_KEY_SIZE);
|
cpu_to_le16(CIFS_SESS_KEY_SIZE);
|
||||||
|
|
||||||
/* calculate session key */
|
/* calculate session key */
|
||||||
SMBNTencrypt(ses->password, ses->server->cryptKey,
|
SMBNTencrypt(ses->password, ses->server->cryptKey,
|
||||||
@@ -420,15 +396,48 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||||||
|
|
||||||
if(first_time) /* should this be moved into common code
|
if(first_time) /* should this be moved into common code
|
||||||
with similar ntlmv2 path? */
|
with similar ntlmv2 path? */
|
||||||
cifs_calculate_mac_key(
|
cifs_calculate_mac_key( ses->server->mac_signing_key,
|
||||||
ses->server->mac_signing_key,
|
|
||||||
ntlm_session_key, ses->password);
|
ntlm_session_key, ses->password);
|
||||||
/* copy session key */
|
/* copy session key */
|
||||||
|
|
||||||
memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESSION_KEY_SIZE);
|
memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
|
||||||
bcc_ptr += CIFS_SESSION_KEY_SIZE;
|
bcc_ptr += CIFS_SESS_KEY_SIZE;
|
||||||
memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESSION_KEY_SIZE);
|
memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
|
||||||
bcc_ptr += CIFS_SESSION_KEY_SIZE;
|
bcc_ptr += CIFS_SESS_KEY_SIZE;
|
||||||
|
if(ses->capabilities & CAP_UNICODE)
|
||||||
|
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
||||||
|
else
|
||||||
|
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
||||||
|
} else if (type == NTLMv2) {
|
||||||
|
char * v2_sess_key = kmalloc(V2_SESS_KEY_SIZE, GFP_KERNEL);
|
||||||
|
|
||||||
|
if(v2_sess_key == NULL) {
|
||||||
|
cifs_small_buf_release(smb_buf);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
|
||||||
|
|
||||||
|
/* LM2 password would be here if we supported it */
|
||||||
|
pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
|
||||||
|
/* cpu_to_le16(LM2_SESS_KEY_SIZE); */
|
||||||
|
|
||||||
|
pSMB->req_no_secext.CaseSensitivePasswordLength =
|
||||||
|
cpu_to_le16(V2_SESS_KEY_SIZE);
|
||||||
|
|
||||||
|
/* calculate session key */
|
||||||
|
CalcNTLMv2_response(ses, v2_sess_key);
|
||||||
|
if(first_time) /* should this be moved into common code
|
||||||
|
with similar ntlmv2 path? */
|
||||||
|
/* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
|
||||||
|
response BB FIXME, v2_sess_key); */
|
||||||
|
|
||||||
|
/* copy session key */
|
||||||
|
|
||||||
|
/* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
|
||||||
|
bcc_ptr += LM2_SESS_KEY_SIZE; */
|
||||||
|
memcpy(bcc_ptr, (char *)v2_sess_key, V2_SESS_KEY_SIZE);
|
||||||
|
bcc_ptr += V2_SESS_KEY_SIZE;
|
||||||
if(ses->capabilities & CAP_UNICODE)
|
if(ses->capabilities & CAP_UNICODE)
|
||||||
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user