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, ...@@ -61,7 +61,7 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
if((cifs_pdu == NULL) || (ses == NULL)) if((cifs_pdu == NULL) || (ses == NULL))
return -EINVAL; return -EINVAL;
if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0) if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
return rc; return rc;
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
......
...@@ -137,15 +137,15 @@ ...@@ -137,15 +137,15 @@
/* /*
* SMB flag2 definitions * SMB flag2 definitions
*/ */
#define SMBFLG2_KNOWS_LONG_NAMES 0x0001 /* can send long (non-8.3) path names in response */ #define SMBFLG2_KNOWS_LONG_NAMES cpu_to_le16(1) /* can send long (non-8.3) path names in response */
#define SMBFLG2_KNOWS_EAS 0x0002 #define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
#define SMBFLG2_SECURITY_SIGNATURE 0x0004 #define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
#define SMBFLG2_IS_LONG_NAME 0x0040 #define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
#define SMBFLG2_EXT_SEC 0x0800 #define SMBFLG2_EXT_SEC cpu_to_le16(0x80)
#define SMBFLG2_DFS 0x1000 #define SMBFLG2_DFS cpu_to_le16(0x1000)
#define SMBFLG2_PAGING_IO 0x2000 #define SMBFLG2_PAGING_IO cpu_to_le16(0x2000)
#define SMBFLG2_ERR_STATUS 0x4000 #define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000)
#define SMBFLG2_UNICODE 0x8000 #define SMBFLG2_UNICODE cpu_to_le16(0x8000)
/* /*
* These are the file access permission bits defined in CIFS for the * These are the file access permission bits defined in CIFS for the
...@@ -308,7 +308,7 @@ struct smb_hdr { ...@@ -308,7 +308,7 @@ struct smb_hdr {
__le32 CifsError; __le32 CifsError;
} Status; } Status;
__u8 Flags; __u8 Flags;
__u16 Flags2; /* note: le */ __le16 Flags2; /* note: le */
__le16 PidHigh; __le16 PidHigh;
union { union {
struct { struct {
......
...@@ -811,7 +811,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, ...@@ -811,7 +811,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
pSMB->Timeout = 0; pSMB->Timeout = 0;
} else if (waitFlag == TRUE) { } else if (waitFlag == TRUE) {
timeout = 3; /* blocking operation, no timeout */ 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 { } else {
pSMB->Timeout = 0; pSMB->Timeout = 0;
} }
...@@ -2485,12 +2485,6 @@ CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon, ...@@ -2485,12 +2485,6 @@ CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
(FILE_SYSTEM_UNIX_INFO (FILE_SYSTEM_UNIX_INFO
*) (((char *) &pSMBr->hdr.Protocol) + *) (((char *) &pSMBr->hdr.Protocol) +
data_offset); 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, memcpy(&tcon->fsUnixInfo, response_data,
sizeof (FILE_SYSTEM_UNIX_INFO)); sizeof (FILE_SYSTEM_UNIX_INFO));
} }
......
...@@ -1634,6 +1634,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -1634,6 +1634,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
} else if ((smb_buffer_response->WordCount == 3) } else if ((smb_buffer_response->WordCount == 3)
|| (smb_buffer_response->WordCount == 4)) { || (smb_buffer_response->WordCount == 4)) {
__u16 action = le16_to_cpu(pSMBr->resp.Action); __u16 action = le16_to_cpu(pSMBr->resp.Action);
__u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
if (action & GUEST_LOGIN) if (action & GUEST_LOGIN)
cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */ cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */ ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
...@@ -1642,11 +1643,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -1642,11 +1643,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr = pByteArea(smb_buffer_response); bcc_ptr = pByteArea(smb_buffer_response);
if ((pSMBr->resp.hdr.WordCount == 3) if ((pSMBr->resp.hdr.WordCount == 3)
|| ((pSMBr->resp.hdr.WordCount == 4) || ((pSMBr->resp.hdr.WordCount == 4)
&& (pSMBr->resp.SecurityBlobLength < && (blob_len < pSMBr->resp.ByteCount))) {
pSMBr->resp.ByteCount))) {
if (pSMBr->resp.hdr.WordCount == 4) if (pSMBr->resp.hdr.WordCount == 4)
bcc_ptr += bcc_ptr += blob_len;
pSMBr->resp.SecurityBlobLength;
if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
if ((long) (bcc_ptr) % 2) { if ((long) (bcc_ptr) % 2) {
...@@ -2201,16 +2200,16 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, ...@@ -2201,16 +2200,16 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
memcpy(ses->server->cryptKey, memcpy(ses->server->cryptKey,
SecurityBlob2->Challenge, SecurityBlob2->Challenge,
CIFS_CRYPTO_KEY_SIZE); CIFS_CRYPTO_KEY_SIZE);
if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2) if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
*pNTLMv2_flag = TRUE; *pNTLMv2_flag = TRUE;
if((SecurityBlob2->NegotiateFlags & if((SecurityBlob2->NegotiateFlags &
NTLMSSP_NEGOTIATE_ALWAYS_SIGN) cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
|| (sign_CIFS_PDUs > 1)) || (sign_CIFS_PDUs > 1))
ses->server->secMode |= ses->server->secMode |=
SECMODE_SIGN_REQUIRED; SECMODE_SIGN_REQUIRED;
if ((SecurityBlob2->NegotiateFlags & if ((SecurityBlob2->NegotiateFlags &
NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs)) cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
ses->server->secMode |= ses->server->secMode |=
SECMODE_SIGN_ENABLED; SECMODE_SIGN_ENABLED;
......
...@@ -289,7 +289,7 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid) ...@@ -289,7 +289,7 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
{ {
/* Make sure that this really is an SMB, that it is a response, /* Make sure that this really is an SMB, that it is a response,
and that the message ids match */ 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)) { (mid == smb->Mid)) {
if(smb->Flags & SMBFLG_RESPONSE) if(smb->Flags & SMBFLG_RESPONSE)
return 0; return 0;
...@@ -301,7 +301,7 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid) ...@@ -301,7 +301,7 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
cERROR(1, ("Rcvd Request not response ")); cERROR(1, ("Rcvd Request not response "));
} }
} else { /* bad signature or mid */ } else { /* bad signature or mid */
if (*(unsigned int *) smb->Protocol != cpu_to_le32(0x424d53ff)) if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
cERROR(1, cERROR(1,
("Bad protocol string signature header %x ", ("Bad protocol string signature header %x ",
*(unsigned int *) smb->Protocol)); *(unsigned int *) smb->Protocol));
......
...@@ -23,10 +23,10 @@ ...@@ -23,10 +23,10 @@
#define NTLMSSP_SIGNATURE "NTLMSSP" #define NTLMSSP_SIGNATURE "NTLMSSP"
/* Message Types */ /* Message Types */
#define NtLmNegotiate 1 #define NtLmNegotiate cpu_to_le32(1)
#define NtLmChallenge 2 #define NtLmChallenge cpu_to_le32(2)
#define NtLmAuthenticate 3 #define NtLmAuthenticate cpu_to_le32(3)
#define UnknownMessage 8 #define UnknownMessage cpu_to_le32(8)
/* Negotiate Flags */ /* Negotiate Flags */
#define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode #define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode
......
...@@ -123,11 +123,12 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, ...@@ -123,11 +123,12 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
int i = 0; int i = 0;
struct msghdr smb_msg; struct msghdr smb_msg;
struct kvec iov; struct kvec iov;
unsigned len = smb_buf_length + 4;
if(ssocket == NULL) if(ssocket == NULL)
return -ENOTSOCK; /* BB eventually add reconnect code here */ return -ENOTSOCK; /* BB eventually add reconnect code here */
iov.iov_base = smb_buffer; iov.iov_base = smb_buffer;
iov.iov_len = smb_buf_length + 4; iov.iov_len = len;
smb_msg.msg_name = sin; smb_msg.msg_name = sin;
smb_msg.msg_namelen = sizeof (struct sockaddr); smb_msg.msg_namelen = sizeof (struct sockaddr);
...@@ -142,10 +143,10 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, ...@@ -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); smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
cFYI(1, ("Sending smb of length %d ", 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) { while (len > 0) {
rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, smb_buf_length + 4); rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
if ((rc == -ENOSPC) || (rc == -EAGAIN)) { if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
i++; i++;
if(i > 60) { if(i > 60) {
...@@ -163,6 +164,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, ...@@ -163,6 +164,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
break; break;
iov.iov_base += rc; iov.iov_base += rc;
iov.iov_len -= rc; iov.iov_len -= rc;
len -= rc;
} }
if (rc < 0) { if (rc < 0) {
...@@ -272,9 +274,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -272,9 +274,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
return -EIO; 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); rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
midQ->midState = MID_REQUEST_SUBMITTED; midQ->midState = MID_REQUEST_SUBMITTED;
...@@ -329,7 +328,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -329,7 +328,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
if (midQ->resp_buf) { if (midQ->resp_buf) {
spin_unlock(&GlobalMid_Lock); 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 { } else {
cERROR(1,("No response buffer")); cERROR(1,("No response buffer"));
if(midQ->midState == MID_REQUEST_SUBMITTED) { if(midQ->midState == MID_REQUEST_SUBMITTED) {
...@@ -368,24 +367,20 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -368,24 +367,20 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
if (midQ->resp_buf && out_buf if (midQ->resp_buf && out_buf
&& (midQ->midState == MID_RESPONSE_RECEIVED)) { && (midQ->midState == MID_RESPONSE_RECEIVED)) {
memcpy(out_buf, midQ->resp_buf, out_buf->smb_buf_length = receive_len;
receive_len + memcpy((char *)out_buf + 4,
4 /* include 4 byte RFC1001 header */ ); (char *)midQ->resp_buf + 4,
receive_len);
dump_smb(out_buf, 92); dump_smb(out_buf, 92);
/* convert the length into a more usable form */ /* convert the length into a more usable form */
out_buf->smb_buf_length = if((receive_len > 24) &&
be32_to_cpu(out_buf->smb_buf_length);
if((out_buf->smb_buf_length > 24) &&
(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) { (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 */ rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */
if(rc) if(rc)
cFYI(1,("Unexpected signature received from server")); 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; *pbytes_returned = out_buf->smb_buf_length;
/* BB special case reconnect tid and reconnect uid here? */ /* 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