Commit 2edd6c5b authored by Steve French's avatar Steve French

[CIFS] NTLMSSP support moving into new file, old dead code removed

Remove dead NTLMSSP support from connect.c prior to addition of
the new code to replace it.
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent 051a2a0d
......@@ -2605,736 +2605,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
return rc;
}
static int
CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
struct cifsSesInfo *ses, bool *pNTLMv2_flag,
const struct nls_table *nls_codepage)
{
struct smb_hdr *smb_buffer;
struct smb_hdr *smb_buffer_response;
SESSION_SETUP_ANDX *pSMB;
SESSION_SETUP_ANDX *pSMBr;
char *bcc_ptr;
char *domain;
int rc = 0;
int remaining_words = 0;
int bytes_returned = 0;
int len;
int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
PNEGOTIATE_MESSAGE SecurityBlob;
PCHALLENGE_MESSAGE SecurityBlob2;
__u32 negotiate_flags, capabilities;
__u16 count;
cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
if (ses == NULL)
return -EINVAL;
domain = ses->domainName;
*pNTLMv2_flag = false;
smb_buffer = cifs_buf_get();
if (smb_buffer == NULL) {
return -ENOMEM;
}
smb_buffer_response = smb_buffer;
pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
/* send SMBsessionSetup here */
header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
NULL /* no tCon exists yet */ , 12 /* wct */ );
smb_buffer->Mid = GetNextMid(ses->server);
pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
pSMB->req.AndXCommand = 0xFF;
pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
CAP_EXTENDED_SECURITY;
if (ses->capabilities & CAP_UNICODE) {
smb_buffer->Flags2 |= SMBFLG2_UNICODE;
capabilities |= CAP_UNICODE;
}
if (ses->capabilities & CAP_STATUS32) {
smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
capabilities |= CAP_STATUS32;
}
if (ses->capabilities & CAP_DFS) {
smb_buffer->Flags2 |= SMBFLG2_DFS;
capabilities |= CAP_DFS;
}
pSMB->req.Capabilities = cpu_to_le32(capabilities);
bcc_ptr = (char *) &pSMB->req.SecurityBlob;
SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
SecurityBlob->MessageType = NtLmNegotiate;
negotiate_flags =
NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
NTLMSSP_NEGOTIATE_56 |
/* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
if (sign_CIFS_PDUs)
negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
/* setup pointers to domain name and workstation name */
bcc_ptr += SecurityBlobLength;
SecurityBlob->WorkstationName.BufferOffset = 0;
SecurityBlob->WorkstationName.Length = 0;
SecurityBlob->WorkstationName.MaximumLength = 0;
/* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
along with username on auth request (ie the response to challenge) */
SecurityBlob->DomainName.BufferOffset = 0;
SecurityBlob->DomainName.Length = 0;
SecurityBlob->DomainName.MaximumLength = 0;
if (ses->capabilities & CAP_UNICODE) {
if ((long) bcc_ptr % 2) {
*bcc_ptr = 0;
bcc_ptr++;
}
bytes_returned =
cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
32, nls_codepage);
bcc_ptr += 2 * bytes_returned;
bytes_returned =
cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
nls_codepage);
bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2; /* null terminate Linux version */
bytes_returned =
cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
64, nls_codepage);
bcc_ptr += 2 * bytes_returned;
*(bcc_ptr + 1) = 0;
*(bcc_ptr + 2) = 0;
bcc_ptr += 2; /* null terminate network opsys string */
*(bcc_ptr + 1) = 0;
*(bcc_ptr + 2) = 0;
bcc_ptr += 2; /* null domain */
} else { /* ASCII */
strcpy(bcc_ptr, "Linux version ");
bcc_ptr += strlen("Linux version ");
strcpy(bcc_ptr, utsname()->release);
bcc_ptr += strlen(utsname()->release) + 1;
strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
bcc_ptr++; /* empty domain field */
*bcc_ptr = 0;
}
SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
smb_buffer->smb_buf_length += count;
pSMB->req.ByteCount = cpu_to_le16(count);
rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
&bytes_returned, CIFS_LONG_OP);
if (smb_buffer_response->Status.CifsError ==
cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
rc = 0;
if (rc) {
/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
} else if ((smb_buffer_response->WordCount == 3)
|| (smb_buffer_response->WordCount == 4)) {
__u16 action = le16_to_cpu(pSMBr->resp.Action);
__u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
if (action & GUEST_LOGIN)
cFYI(1, ("Guest login"));
/* Do we want to set anything in SesInfo struct when guest login? */
bcc_ptr = pByteArea(smb_buffer_response);
/* response can have either 3 or 4 word count - Samba sends 3 */
SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
if (SecurityBlob2->MessageType != NtLmChallenge) {
cFYI(1, ("Unexpected NTLMSSP message type received %d",
SecurityBlob2->MessageType));
} else if (ses) {
ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
cFYI(1, ("UID = %d", ses->Suid));
if ((pSMBr->resp.hdr.WordCount == 3)
|| ((pSMBr->resp.hdr.WordCount == 4)
&& (blob_len <
pSMBr->resp.ByteCount))) {
if (pSMBr->resp.hdr.WordCount == 4) {
bcc_ptr += blob_len;
cFYI(1, ("Security Blob Length %d",
blob_len));
}
cFYI(1, ("NTLMSSP Challenge rcvd"));
memcpy(ses->server->cryptKey,
SecurityBlob2->Challenge,
CIFS_CRYPTO_KEY_SIZE);
/* NTLMV2 flag is not for NTLMv2 password hash */
/* if (SecurityBlob2->NegotiateFlags &
cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
*pNTLMv2_flag = true; */ /* BB wrong */
if ((SecurityBlob2->NegotiateFlags &
cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
|| (sign_CIFS_PDUs > 1))
ses->server->secMode |=
SECMODE_SIGN_REQUIRED;
if ((SecurityBlob2->NegotiateFlags &
cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
ses->server->secMode |=
SECMODE_SIGN_ENABLED;
if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
if ((long) (bcc_ptr) % 2) {
remaining_words =
(BCC(smb_buffer_response)
- 1) / 2;
/* Must word align unicode strings */
bcc_ptr++;
} else {
remaining_words =
BCC
(smb_buffer_response) / 2;
}
len =
UniStrnlen((wchar_t *) bcc_ptr,
remaining_words - 1);
/* We look for obvious messed up bcc or strings in response so we do not go off
the end since (at least) WIN2K and Windows XP have a major bug in not null
terminating last Unicode string in response */
kfree(ses->serverOS);
ses->serverOS =
kzalloc(2 * (len + 1), GFP_KERNEL);
cifs_strfromUCS_le(ses->serverOS,
(__le16 *)
bcc_ptr, len,
nls_codepage);
bcc_ptr += 2 * (len + 1);
remaining_words -= len + 1;
ses->serverOS[2 * len] = 0;
ses->serverOS[1 + (2 * len)] = 0;
if (remaining_words > 0) {
len = UniStrnlen((wchar_t *)
bcc_ptr,
remaining_words
- 1);
kfree(ses->serverNOS);
ses->serverNOS =
kzalloc(2 * (len + 1),
GFP_KERNEL);
cifs_strfromUCS_le(ses->
serverNOS,
(__le16 *)
bcc_ptr,
len,
nls_codepage);
bcc_ptr += 2 * (len + 1);
ses->serverNOS[2 * len] = 0;
ses->serverNOS[1 +
(2 * len)] = 0;
remaining_words -= len + 1;
if (remaining_words > 0) {
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
/* last string not always null terminated
(for e.g. for Windows XP & 2000) */
kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(2 *
(len +
1),
GFP_KERNEL);
cifs_strfromUCS_le
(ses->serverDomain,
(__le16 *)bcc_ptr,
len, nls_codepage);
bcc_ptr +=
2 * (len + 1);
ses->serverDomain[2*len]
= 0;
ses->serverDomain
[1 + (2 * len)]
= 0;
} /* else no more room so create dummy domain string */
else {
kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(2,
GFP_KERNEL);
}
} else { /* no room so create dummy domain and NOS string */
kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(2, GFP_KERNEL);
kfree(ses->serverNOS);
ses->serverNOS =
kzalloc(2, GFP_KERNEL);
}
} else { /* ASCII */
len = strnlen(bcc_ptr, 1024);
if (((long) bcc_ptr + len) - (long)
pByteArea(smb_buffer_response)
<= BCC(smb_buffer_response)) {
kfree(ses->serverOS);
ses->serverOS =
kzalloc(len + 1,
GFP_KERNEL);
strncpy(ses->serverOS,
bcc_ptr, len);
bcc_ptr += len;
bcc_ptr[0] = 0; /* null terminate string */
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
kfree(ses->serverNOS);
ses->serverNOS =
kzalloc(len + 1,
GFP_KERNEL);
strncpy(ses->serverNOS, bcc_ptr, len);
bcc_ptr += len;
bcc_ptr[0] = 0;
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(len + 1,
GFP_KERNEL);
strncpy(ses->serverDomain,
bcc_ptr, len);
bcc_ptr += len;
bcc_ptr[0] = 0;
bcc_ptr++;
} else
cFYI(1,
("field of length %d "
"extends beyond end of smb",
len));
}
} else {
cERROR(1, ("Security Blob Length extends beyond"
" end of SMB"));
}
} else {
cERROR(1, ("No session structure passed in."));
}
} else {
cERROR(1, ("Invalid Word count %d:",
smb_buffer_response->WordCount));
rc = -EIO;
}
cifs_buf_release(smb_buffer);
return rc;
}
static int
CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char *ntlm_session_key, bool ntlmv2_flag,
const struct nls_table *nls_codepage)
{
struct smb_hdr *smb_buffer;
struct smb_hdr *smb_buffer_response;
SESSION_SETUP_ANDX *pSMB;
SESSION_SETUP_ANDX *pSMBr;
char *bcc_ptr;
char *user;
char *domain;
int rc = 0;
int remaining_words = 0;
int bytes_returned = 0;
int len;
int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
PAUTHENTICATE_MESSAGE SecurityBlob;
__u32 negotiate_flags, capabilities;
__u16 count;
cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
if (ses == NULL)
return -EINVAL;
user = ses->userName;
domain = ses->domainName;
smb_buffer = cifs_buf_get();
if (smb_buffer == NULL) {
return -ENOMEM;
}
smb_buffer_response = smb_buffer;
pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
/* send SMBsessionSetup here */
header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
NULL /* no tCon exists yet */ , 12 /* wct */ );
smb_buffer->Mid = GetNextMid(ses->server);
pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
pSMB->req.AndXCommand = 0xFF;
pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
pSMB->req.hdr.Uid = ses->Suid;
if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
CAP_EXTENDED_SECURITY;
if (ses->capabilities & CAP_UNICODE) {
smb_buffer->Flags2 |= SMBFLG2_UNICODE;
capabilities |= CAP_UNICODE;
}
if (ses->capabilities & CAP_STATUS32) {
smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
capabilities |= CAP_STATUS32;
}
if (ses->capabilities & CAP_DFS) {
smb_buffer->Flags2 |= SMBFLG2_DFS;
capabilities |= CAP_DFS;
}
pSMB->req.Capabilities = cpu_to_le32(capabilities);
bcc_ptr = (char *)&pSMB->req.SecurityBlob;
SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
SecurityBlob->MessageType = NtLmAuthenticate;
bcc_ptr += SecurityBlobLength;
negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
NTLMSSP_NEGOTIATE_56 | NTLMSSP_NEGOTIATE_128 |
NTLMSSP_NEGOTIATE_EXTENDED_SEC;
if (sign_CIFS_PDUs)
negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
/* setup pointers to domain name and workstation name */
SecurityBlob->WorkstationName.BufferOffset = 0;
SecurityBlob->WorkstationName.Length = 0;
SecurityBlob->WorkstationName.MaximumLength = 0;
SecurityBlob->SessionKey.Length = 0;
SecurityBlob->SessionKey.MaximumLength = 0;
SecurityBlob->SessionKey.BufferOffset = 0;
SecurityBlob->LmChallengeResponse.Length = 0;
SecurityBlob->LmChallengeResponse.MaximumLength = 0;
SecurityBlob->LmChallengeResponse.BufferOffset = 0;
SecurityBlob->NtChallengeResponse.Length =
cpu_to_le16(CIFS_SESS_KEY_SIZE);
SecurityBlob->NtChallengeResponse.MaximumLength =
cpu_to_le16(CIFS_SESS_KEY_SIZE);
memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
SecurityBlob->NtChallengeResponse.BufferOffset =
cpu_to_le32(SecurityBlobLength);
SecurityBlobLength += CIFS_SESS_KEY_SIZE;
bcc_ptr += CIFS_SESS_KEY_SIZE;
if (ses->capabilities & CAP_UNICODE) {
if (domain == NULL) {
SecurityBlob->DomainName.BufferOffset = 0;
SecurityBlob->DomainName.Length = 0;
SecurityBlob->DomainName.MaximumLength = 0;
} else {
__u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
nls_codepage);
ln *= 2;
SecurityBlob->DomainName.MaximumLength =
cpu_to_le16(ln);
SecurityBlob->DomainName.BufferOffset =
cpu_to_le32(SecurityBlobLength);
bcc_ptr += ln;
SecurityBlobLength += ln;
SecurityBlob->DomainName.Length = cpu_to_le16(ln);
}
if (user == NULL) {
SecurityBlob->UserName.BufferOffset = 0;
SecurityBlob->UserName.Length = 0;
SecurityBlob->UserName.MaximumLength = 0;
} else {
__u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
nls_codepage);
ln *= 2;
SecurityBlob->UserName.MaximumLength =
cpu_to_le16(ln);
SecurityBlob->UserName.BufferOffset =
cpu_to_le32(SecurityBlobLength);
bcc_ptr += ln;
SecurityBlobLength += ln;
SecurityBlob->UserName.Length = cpu_to_le16(ln);
}
/* SecurityBlob->WorkstationName.Length =
cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
SecurityBlob->WorkstationName.Length *= 2;
SecurityBlob->WorkstationName.MaximumLength =
cpu_to_le16(SecurityBlob->WorkstationName.Length);
SecurityBlob->WorkstationName.BufferOffset =
cpu_to_le32(SecurityBlobLength);
bcc_ptr += SecurityBlob->WorkstationName.Length;
SecurityBlobLength += SecurityBlob->WorkstationName.Length;
SecurityBlob->WorkstationName.Length =
cpu_to_le16(SecurityBlob->WorkstationName.Length); */
if ((long) bcc_ptr % 2) {
*bcc_ptr = 0;
bcc_ptr++;
}
bytes_returned =
cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
32, nls_codepage);
bcc_ptr += 2 * bytes_returned;
bytes_returned =
cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
nls_codepage);
bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2; /* null term version string */
bytes_returned =
cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
64, nls_codepage);
bcc_ptr += 2 * bytes_returned;
*(bcc_ptr + 1) = 0;
*(bcc_ptr + 2) = 0;
bcc_ptr += 2; /* null terminate network opsys string */
*(bcc_ptr + 1) = 0;
*(bcc_ptr + 2) = 0;
bcc_ptr += 2; /* null domain */
} else { /* ASCII */
if (domain == NULL) {
SecurityBlob->DomainName.BufferOffset = 0;
SecurityBlob->DomainName.Length = 0;
SecurityBlob->DomainName.MaximumLength = 0;
} else {
__u16 ln;
negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
strncpy(bcc_ptr, domain, 63);
ln = strnlen(domain, 64);
SecurityBlob->DomainName.MaximumLength =
cpu_to_le16(ln);
SecurityBlob->DomainName.BufferOffset =
cpu_to_le32(SecurityBlobLength);
bcc_ptr += ln;
SecurityBlobLength += ln;
SecurityBlob->DomainName.Length = cpu_to_le16(ln);
}
if (user == NULL) {
SecurityBlob->UserName.BufferOffset = 0;
SecurityBlob->UserName.Length = 0;
SecurityBlob->UserName.MaximumLength = 0;
} else {
__u16 ln;
strncpy(bcc_ptr, user, 63);
ln = strnlen(user, 64);
SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
SecurityBlob->UserName.BufferOffset =
cpu_to_le32(SecurityBlobLength);
bcc_ptr += ln;
SecurityBlobLength += ln;
SecurityBlob->UserName.Length = cpu_to_le16(ln);
}
/* BB fill in our workstation name if known BB */
strcpy(bcc_ptr, "Linux version ");
bcc_ptr += strlen("Linux version ");
strcpy(bcc_ptr, utsname()->release);
bcc_ptr += strlen(utsname()->release) + 1;
strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
bcc_ptr++; /* null domain */
*bcc_ptr = 0;
}
SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
smb_buffer->smb_buf_length += count;
pSMB->req.ByteCount = cpu_to_le16(count);
rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
&bytes_returned, CIFS_LONG_OP);
if (rc) {
/* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */
} else if ((smb_buffer_response->WordCount == 3) ||
(smb_buffer_response->WordCount == 4)) {
__u16 action = le16_to_cpu(pSMBr->resp.Action);
__u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
if (action & GUEST_LOGIN)
cFYI(1, ("Guest login")); /* BB Should we set anything
in SesInfo struct ? */
/* if (SecurityBlob2->MessageType != NtLm??) {
cFYI("Unexpected message type on auth response is %d"));
} */
if (ses) {
cFYI(1,
("Check challenge UID %d vs auth response UID %d",
ses->Suid, smb_buffer_response->Uid));
/* UID left in wire format */
ses->Suid = smb_buffer_response->Uid;
bcc_ptr = pByteArea(smb_buffer_response);
/* response can have either 3 or 4 word count - Samba sends 3 */
if ((pSMBr->resp.hdr.WordCount == 3)
|| ((pSMBr->resp.hdr.WordCount == 4)
&& (blob_len <
pSMBr->resp.ByteCount))) {
if (pSMBr->resp.hdr.WordCount == 4) {
bcc_ptr +=
blob_len;
cFYI(1,
("Security Blob Length %d ",
blob_len));
}
cFYI(1,
("NTLMSSP response to Authenticate "));
if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
if ((long) (bcc_ptr) % 2) {
remaining_words =
(BCC(smb_buffer_response)
- 1) / 2;
bcc_ptr++; /* Unicode strings must be word aligned */
} else {
remaining_words = BCC(smb_buffer_response) / 2;
}
len = UniStrnlen((wchar_t *) bcc_ptr,
remaining_words - 1);
/* We look for obvious messed up bcc or strings in response so we do not go off
the end since (at least) WIN2K and Windows XP have a major bug in not null
terminating last Unicode string in response */
kfree(ses->serverOS);
ses->serverOS =
kzalloc(2 * (len + 1), GFP_KERNEL);
cifs_strfromUCS_le(ses->serverOS,
(__le16 *)
bcc_ptr, len,
nls_codepage);
bcc_ptr += 2 * (len + 1);
remaining_words -= len + 1;
ses->serverOS[2 * len] = 0;
ses->serverOS[1 + (2 * len)] = 0;
if (remaining_words > 0) {
len = UniStrnlen((wchar_t *)
bcc_ptr,
remaining_words
- 1);
kfree(ses->serverNOS);
ses->serverNOS =
kzalloc(2 * (len + 1),
GFP_KERNEL);
cifs_strfromUCS_le(ses->
serverNOS,
(__le16 *)
bcc_ptr,
len,
nls_codepage);
bcc_ptr += 2 * (len + 1);
ses->serverNOS[2 * len] = 0;
ses->serverNOS[1+(2*len)] = 0;
remaining_words -= len + 1;
if (remaining_words > 0) {
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
/* last string not always null terminated (e.g. for Windows XP & 2000) */
kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(2 *
(len +
1),
GFP_KERNEL);
cifs_strfromUCS_le
(ses->
serverDomain,
(__le16 *)
bcc_ptr, len,
nls_codepage);
bcc_ptr +=
2 * (len + 1);
ses->
serverDomain[2
* len]
= 0;
ses->
serverDomain[1
+
(2
*
len)]
= 0;
} /* else no more room so create dummy domain string */
else {
kfree(ses->serverDomain);
ses->serverDomain = kzalloc(2,GFP_KERNEL);
}
} else { /* no room so create dummy domain and NOS string */
kfree(ses->serverDomain);
ses->serverDomain = kzalloc(2, GFP_KERNEL);
kfree(ses->serverNOS);
ses->serverNOS = kzalloc(2, GFP_KERNEL);
}
} else { /* ASCII */
len = strnlen(bcc_ptr, 1024);
if (((long) bcc_ptr + len) -
(long) pByteArea(smb_buffer_response)
<= BCC(smb_buffer_response)) {
kfree(ses->serverOS);
ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
strncpy(ses->serverOS,bcc_ptr, len);
bcc_ptr += len;
bcc_ptr[0] = 0; /* null terminate the string */
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
kfree(ses->serverNOS);
ses->serverNOS = kzalloc(len+1,
GFP_KERNEL);
strncpy(ses->serverNOS,
bcc_ptr, len);
bcc_ptr += len;
bcc_ptr[0] = 0;
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(len+1,
GFP_KERNEL);
strncpy(ses->serverDomain,
bcc_ptr, len);
bcc_ptr += len;
bcc_ptr[0] = 0;
bcc_ptr++;
} else
cFYI(1, ("field of length %d "
"extends beyond end of smb ",
len));
}
} else {
cERROR(1, ("Security Blob extends beyond end "
"of SMB"));
}
} else {
cERROR(1, ("No session structure passed in."));
}