[CIFS] Remove older session setup implementation

Two years ago, when the session setup code in cifs was rewritten and moved
to fs/cifs/sess.c, we were asked to keep the old code for a release or so
(which could be reenabled at runtime) since it was such a large change and
because the asn (SPNEGO) and NTLMSSP code was not rewritten and needed to
be. This was useful to avoid regressions, but is long overdue to be removed.
Now that the Kerberos (asn/spnego) code is working in fs/cifs/sess.c,
and the NTLMSSP code moved (NTLMSSP blob setup be rewritten with the
next patch in this series) quite a bit of dead code from fs/cifs/connect.c
now can be removed.

This old code should have been removed last year, but the earlier krb5
patches did not move/remove the NTLMSSP code which we had asked to
be done first.  Since no one else volunteered, I am doing it now.

It is extremely important that we continue to examine the documentation
for this area, to make sure our code continues to be uptodate with
changes since Windows 2003.

Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
Steve French 2009-04-30 16:13:32 +00:00
parent f58841666b
commit 20418acd68
1 changed files with 7 additions and 374 deletions

View File

@ -2592,310 +2592,6 @@ out:
return rc;
}
static int
CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char session_key[CIFS_SESS_KEY_SIZE],
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;
__u32 capabilities;
__u16 count;
cFYI(1, ("In sesssetup"));
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;
pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
/* send SMBsessionSetup here */
header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
NULL /* no tCon exists yet */ , 13 /* wct */ );
smb_buffer->Mid = GetNextMid(ses->server);
pSMB->req_no_secext.AndXCommand = 0xFF;
pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
pSMB->req_no_secext.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_LARGE_WRITE_X | CAP_LARGE_READ_X;
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_no_secext.Capabilities = cpu_to_le32(capabilities);
pSMB->req_no_secext.CaseInsensitivePasswordLength =
cpu_to_le16(CIFS_SESS_KEY_SIZE);
pSMB->req_no_secext.CaseSensitivePasswordLength =
cpu_to_le16(CIFS_SESS_KEY_SIZE);
bcc_ptr = pByteArea(smb_buffer);
memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
bcc_ptr += CIFS_SESS_KEY_SIZE;
memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
bcc_ptr += CIFS_SESS_KEY_SIZE;
if (ses->capabilities & CAP_UNICODE) {
if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
*bcc_ptr = 0;
bcc_ptr++;
}
if (user == NULL)
bytes_returned = 0; /* skip null user */
else
bytes_returned =
cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
nls_codepage);
/* convert number of 16 bit words to bytes */
bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2; /* trailing null */
if (domain == NULL)
bytes_returned =
cifs_strtoUCS((__le16 *) bcc_ptr,
"CIFS_LINUX_DOM", 32, nls_codepage);
else
bytes_returned =
cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
nls_codepage);
bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2;
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;
bytes_returned =
cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
64, nls_codepage);
bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2;
} else {
if (user != NULL) {
strncpy(bcc_ptr, user, 200);
bcc_ptr += strnlen(user, 200);
}
*bcc_ptr = 0;
bcc_ptr++;
if (domain == NULL) {
strcpy(bcc_ptr, "CIFS_LINUX_DOM");
bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
} else {
strncpy(bcc_ptr, domain, 64);
bcc_ptr += strnlen(domain, 64);
*bcc_ptr = 0;
bcc_ptr++;
}
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;
}
count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
smb_buffer->smb_buf_length += count;
pSMB->req_no_secext.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); now done in SendReceive */
} 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 mark SesInfo struct? */
ses->Suid = smb_buffer_response->Uid; /* UID left in wire format
(little endian) */
cFYI(1, ("UID = %d ", ses->Suid));
/* response can have either 3 or 4 word count - Samba sends 3 */
bcc_ptr = pByteArea(smb_buffer_response);
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;
if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
if ((long) (bcc_ptr) % 2) {
remaining_words =
(BCC(smb_buffer_response) - 1) / 2;
/* Unicode strings must be word
aligned */
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);
if (ses->serverOS == NULL)
goto sesssetup_nomem;
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);
if (ses->serverNOS == NULL)
goto sesssetup_nomem;
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;
if (strncmp(ses->serverNOS,
"NT LAN Manager 4", 16) == 0) {
cFYI(1, ("NT4 server"));
ses->flags |= CIFS_SES_NT4;
}
remaining_words -= len + 1;
if (remaining_words > 0) {
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
/* last string is not always null terminated
(for e.g. for Windows XP & 2000) */
kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(2*(len+1),
GFP_KERNEL);
if (ses->serverDomain == NULL)
goto sesssetup_nomem;
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 { /* else no more room so create
dummy domain string */
kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(2, GFP_KERNEL);
}
} else { /* no room so create dummy domain
and NOS string */
/* if these kcallocs fail not much we
can do, but better to not fail the
sesssetup itself */
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);
if (ses->serverOS == NULL)
goto sesssetup_nomem;
strncpy(ses->serverOS, bcc_ptr, len);
bcc_ptr += len;
/* null terminate the string */
bcc_ptr[0] = 0;
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
kfree(ses->serverNOS);
ses->serverNOS = kzalloc(len + 1,
GFP_KERNEL);
if (ses->serverNOS == NULL)
goto sesssetup_nomem;
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);
if (ses->serverDomain == NULL)
goto sesssetup_nomem;
strncpy(ses->serverDomain, bcc_ptr,
len);
bcc_ptr += len;
bcc_ptr[0] = 0;
bcc_ptr++;
} else
cFYI(1,
("Variable field of length %d "
"extends beyond end of smb ",
len));
}
} else {
cERROR(1, ("Security Blob Length extends beyond "
"end of SMB"));
}
} else {
cERROR(1, ("Invalid Word count %d: ",
smb_buffer_response->WordCount));
rc = -EIO;
}
sesssetup_nomem: /* do not return an error on nomem for the info strings,
since that could make reconnection harder, and
reconnection might be needed to free memory */
cifs_buf_release(smb_buffer);
return rc;
}
static int
CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
struct cifsSesInfo *ses, bool *pNTLMv2_flag,
@ -3229,6 +2925,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
return rc;
}
static int
CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char *ntlm_session_key, bool ntlmv2_flag,
@ -3831,83 +3528,19 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
pSesInfo->capabilities = server->capabilities;
if (linuxExtEnabled == 0)
pSesInfo->capabilities &= (~CAP_UNIX);
/* pSesInfo->sequence_number = 0;*/
cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
server->secMode, server->capabilities, server->timeAdj));
if (experimEnabled < 2)
rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
else if (extended_security
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
&& (server->secType == NTLMSSP)) {
rc = -EOPNOTSUPP;
} else if (extended_security
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
&& (server->secType == RawNTLMSSP)) {
cFYI(1, ("NTLMSSP sesssetup"));
rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag,
nls_info);
if (!rc) {
if (ntlmv2_flag) {
char *v2_response;
cFYI(1, ("more secure NTLM ver2 hash"));
if (CalcNTLMv2_partial_mac_key(pSesInfo,
nls_info)) {
rc = -ENOMEM;
goto ss_err_exit;
} else
v2_response = kmalloc(16 + 64 /* blob*/,
GFP_KERNEL);
if (v2_response) {
CalcNTLMv2_response(pSesInfo,
v2_response);
/* if (first_time)
cifs_calculate_ntlmv2_mac_key */
kfree(v2_response);
/* BB Put dummy sig in SessSetup PDU? */
} else {
rc = -ENOMEM;
goto ss_err_exit;
}
} else {
SMBNTencrypt(pSesInfo->password,
server->cryptKey,
ntlm_session_key);
if (first_time)
cifs_calculate_mac_key(
&server->mac_signing_key,
ntlm_session_key,
pSesInfo->password);
}
/* for better security the weaker lanman hash not sent
in AuthSessSetup so we no longer calculate it */
rc = CIFSNTLMSSPAuthSessSetup(xid, pSesInfo,
ntlm_session_key,
ntlmv2_flag,
nls_info);
}
} else { /* old style NTLM 0.12 session setup */
SMBNTencrypt(pSesInfo->password, server->cryptKey,
ntlm_session_key);
if (first_time)
cifs_calculate_mac_key(&server->mac_signing_key,
ntlm_session_key,
pSesInfo->password);
rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info);
}
rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
if (rc) {
cERROR(1, ("Send error in SessSetup = %d", rc));
} else {
cFYI(1, ("CIFS Session Established successfully"));
spin_lock(&GlobalMid_Lock);
pSesInfo->status = CifsGood;
pSesInfo->need_reconnect = false;
spin_unlock(&GlobalMid_Lock);
spin_lock(&GlobalMid_Lock);
pSesInfo->status = CifsGood;
pSesInfo->need_reconnect = false;
spin_unlock(&GlobalMid_Lock);
}
ss_err_exit: