Commit 77615fa9 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] cifs: assorted endianness bugfixes

        a) Flags2 left little-endian. SMBFLG2_... definitions switched to  
cpu_to_le16(...), which kills the need of conversions in ->Flags2.
	b) FILE_SYSTEM_UNIX_INFO (never used anywhere) is left little-endian;
when users appear, they can convert themselves.
	c) bugfix: in CIFSSessSetup() we used SecurityBlobLength of response
without conversion.  That would screw bigendian clients with servers that
give wcnt=4.
	d) bugfix: in CIFSNTLMSSPNegotiateSessSetup() we use 
SecurityBlob2->NegotiateFlags without conversion.  Again, problem on
big-endian.
	e) bugfix: SecurityBlob->MessageType is *not* host-endian.
	f) bugfix: ->sendmsg() expects its last argument to be equal to sum
of iovec lengths, so the value passed to kernel_sendmsg()/sock_sendmsg()
would better be correct...
Signed-off-by: default avatarAl Viro <viro@parcelfarce.linux.org.uk>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 0c5ba019
......@@ -61,7 +61,7 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
if((cifs_pdu == NULL) || (ses == NULL))
return -EINVAL;
if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0)
if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
return rc;
spin_lock(&GlobalMid_Lock);
......
......@@ -137,15 +137,15 @@
/*
* SMB flag2 definitions
*/
#define SMBFLG2_KNOWS_LONG_NAMES 0x0001 /* can send long (non-8.3) path names in response */
#define SMBFLG2_KNOWS_EAS 0x0002
#define SMBFLG2_SECURITY_SIGNATURE 0x0004
#define SMBFLG2_IS_LONG_NAME 0x0040
#define SMBFLG2_EXT_SEC 0x0800
#define SMBFLG2_DFS 0x1000
#define SMBFLG2_PAGING_IO 0x2000
#define SMBFLG2_ERR_STATUS 0x4000
#define SMBFLG2_UNICODE 0x8000
#define SMBFLG2_KNOWS_LONG_NAMES cpu_to_le16(1) /* can send long (non-8.3) path names in response */
#define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
#define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
#define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
#define SMBFLG2_EXT_SEC cpu_to_le16(0x80)
#define SMBFLG2_DFS cpu_to_le16(0x1000)
#define SMBFLG2_PAGING_IO cpu_to_le16(0x2000)
#define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000)
#define SMBFLG2_UNICODE cpu_to_le16(0x8000)
/*
* These are the file access permission bits defined in CIFS for the
......@@ -308,7 +308,7 @@ struct smb_hdr {
__le32 CifsError;
} Status;
__u8 Flags;
__u16 Flags2; /* note: le */
__le16 Flags2; /* note: le */
__le16 PidHigh;
union {
struct {
......
......@@ -811,7 +811,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
pSMB->Timeout = 0;
} else if (waitFlag == TRUE) {
timeout = 3; /* blocking operation, no timeout */
pSMB->Timeout = -1; /* blocking - do not time out */
pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
} else {
pSMB->Timeout = 0;
}
......@@ -2485,12 +2485,6 @@ CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
(FILE_SYSTEM_UNIX_INFO
*) (((char *) &pSMBr->hdr.Protocol) +
data_offset);
response_data->MajorVersionNumber =
le16_to_cpu(response_data->MajorVersionNumber);
response_data->MinorVersionNumber =
le16_to_cpu(response_data->MinorVersionNumber);
response_data->Capability =
le64_to_cpu(response_data->Capability);
memcpy(&tcon->fsUnixInfo, response_data,
sizeof (FILE_SYSTEM_UNIX_INFO));
}
......
......@@ -1634,6 +1634,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
} 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 mark SesInfo struct ? */
ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
......@@ -1642,11 +1643,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr = pByteArea(smb_buffer_response);
if ((pSMBr->resp.hdr.WordCount == 3)
|| ((pSMBr->resp.hdr.WordCount == 4)
&& (pSMBr->resp.SecurityBlobLength <
pSMBr->resp.ByteCount))) {
&& (blob_len < pSMBr->resp.ByteCount))) {
if (pSMBr->resp.hdr.WordCount == 4)
bcc_ptr +=
pSMBr->resp.SecurityBlobLength;
bcc_ptr += blob_len;
if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
if ((long) (bcc_ptr) % 2) {
......@@ -2201,16 +2200,16 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
memcpy(ses->server->cryptKey,
SecurityBlob2->Challenge,
CIFS_CRYPTO_KEY_SIZE);
if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
*pNTLMv2_flag = TRUE;
if((SecurityBlob2->NegotiateFlags &
NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
|| (sign_CIFS_PDUs > 1))
ses->server->secMode |=
SECMODE_SIGN_REQUIRED;
if ((SecurityBlob2->NegotiateFlags &
NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs))
cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
ses->server->secMode |=
SECMODE_SIGN_ENABLED;
......
......@@ -289,7 +289,7 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
{
/* Make sure that this really is an SMB, that it is a response,
and that the message ids match */
if ((*(unsigned int *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
(mid == smb->Mid)) {
if(smb->Flags & SMBFLG_RESPONSE)
return 0;
......@@ -301,7 +301,7 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
cERROR(1, ("Rcvd Request not response "));
}
} else { /* bad signature or mid */
if (*(unsigned int *) smb->Protocol != cpu_to_le32(0x424d53ff))
if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
cERROR(1,
("Bad protocol string signature header %x ",
*(unsigned int *) smb->Protocol));
......
......@@ -23,10 +23,10 @@
#define NTLMSSP_SIGNATURE "NTLMSSP"
/* Message Types */
#define NtLmNegotiate 1
#define NtLmChallenge 2
#define NtLmAuthenticate 3
#define UnknownMessage 8
#define NtLmNegotiate cpu_to_le32(1)
#define NtLmChallenge cpu_to_le32(2)
#define NtLmAuthenticate cpu_to_le32(3)
#define UnknownMessage cpu_to_le32(8)
/* Negotiate Flags */
#define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode
......
......@@ -123,11 +123,12 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
int i = 0;
struct msghdr smb_msg;
struct kvec iov;
unsigned len = smb_buf_length + 4;
if(ssocket == NULL)
return -ENOTSOCK; /* BB eventually add reconnect code here */
iov.iov_base = smb_buffer;
iov.iov_len = smb_buf_length + 4;
iov.iov_len = len;
smb_msg.msg_name = sin;
smb_msg.msg_namelen = sizeof (struct sockaddr);
......@@ -142,10 +143,10 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
cFYI(1, ("Sending smb of length %d ", smb_buf_length));
dump_smb(smb_buffer, smb_buf_length + 4);
dump_smb(smb_buffer, len);
while(iov.iov_len > 0) {
rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, smb_buf_length + 4);
while (len > 0) {
rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
i++;
if(i > 60) {
......@@ -163,6 +164,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
break;
iov.iov_base += rc;
iov.iov_len -= rc;
len -= rc;
}
if (rc < 0) {
......@@ -272,9 +274,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
return -EIO;
}
if (in_buf->smb_buf_length > 12)
in_buf->Flags2 = cpu_to_le16(in_buf->Flags2);
rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
midQ->midState = MID_REQUEST_SUBMITTED;
......@@ -329,7 +328,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
spin_lock(&GlobalMid_Lock);
if (midQ->resp_buf) {
spin_unlock(&GlobalMid_Lock);
receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length);
receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf);
} else {
cERROR(1,("No response buffer"));
if(midQ->midState == MID_REQUEST_SUBMITTED) {
......@@ -368,24 +367,20 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
if (midQ->resp_buf && out_buf
&& (midQ->midState == MID_RESPONSE_RECEIVED)) {
memcpy(out_buf, midQ->resp_buf,
receive_len +
4 /* include 4 byte RFC1001 header */ );
out_buf->smb_buf_length = receive_len;
memcpy((char *)out_buf + 4,
(char *)midQ->resp_buf + 4,
receive_len);
dump_smb(out_buf, 92);
/* convert the length into a more usable form */
out_buf->smb_buf_length =
be32_to_cpu(out_buf->smb_buf_length);
if((out_buf->smb_buf_length > 24) &&
if((receive_len > 24) &&
(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) {
rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */
if(rc)
cFYI(1,("Unexpected signature received from server"));
}
if (out_buf->smb_buf_length > 12)
out_buf->Flags2 = le16_to_cpu(out_buf->Flags2);
*pbytes_returned = out_buf->smb_buf_length;
/* BB special case reconnect tid and reconnect uid here? */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment