cifs: fix mount on old smb servers
The client was sending rfc1002 session request packet with a wrong
length field set, therefore failing to mount shares against old SMB
servers over port 139.
Fix this by calculating the correct length as specified in rfc1002.
Fixes: d7173623bf
("cifs: use ALIGN() and round_up() macros")
Cc: stable@vger.kernel.org
Signed-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com>
Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
de036dcaca
commit
d99e86ebde
|
@ -2843,72 +2843,48 @@ ip_rfc1001_connect(struct TCP_Server_Info *server)
|
||||||
* negprot - BB check reconnection in case where second
|
* negprot - BB check reconnection in case where second
|
||||||
* sessinit is sent but no second negprot
|
* sessinit is sent but no second negprot
|
||||||
*/
|
*/
|
||||||
struct rfc1002_session_packet *ses_init_buf;
|
struct rfc1002_session_packet req = {};
|
||||||
unsigned int req_noscope_len;
|
struct smb_hdr *smb_buf = (struct smb_hdr *)&req;
|
||||||
struct smb_hdr *smb_buf;
|
unsigned int len;
|
||||||
|
|
||||||
ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
|
req.trailer.session_req.called_len = sizeof(req.trailer.session_req.called_name);
|
||||||
GFP_KERNEL);
|
|
||||||
|
|
||||||
if (ses_init_buf) {
|
if (server->server_RFC1001_name[0] != 0)
|
||||||
ses_init_buf->trailer.session_req.called_len = 32;
|
rfc1002mangle(req.trailer.session_req.called_name,
|
||||||
|
server->server_RFC1001_name,
|
||||||
|
RFC1001_NAME_LEN_WITH_NULL);
|
||||||
|
else
|
||||||
|
rfc1002mangle(req.trailer.session_req.called_name,
|
||||||
|
DEFAULT_CIFS_CALLED_NAME,
|
||||||
|
RFC1001_NAME_LEN_WITH_NULL);
|
||||||
|
|
||||||
if (server->server_RFC1001_name[0] != 0)
|
req.trailer.session_req.calling_len = sizeof(req.trailer.session_req.calling_name);
|
||||||
rfc1002mangle(ses_init_buf->trailer.
|
|
||||||
session_req.called_name,
|
|
||||||
server->server_RFC1001_name,
|
|
||||||
RFC1001_NAME_LEN_WITH_NULL);
|
|
||||||
else
|
|
||||||
rfc1002mangle(ses_init_buf->trailer.
|
|
||||||
session_req.called_name,
|
|
||||||
DEFAULT_CIFS_CALLED_NAME,
|
|
||||||
RFC1001_NAME_LEN_WITH_NULL);
|
|
||||||
|
|
||||||
ses_init_buf->trailer.session_req.calling_len = 32;
|
/* calling name ends in null (byte 16) from old smb convention */
|
||||||
|
if (server->workstation_RFC1001_name[0] != 0)
|
||||||
|
rfc1002mangle(req.trailer.session_req.calling_name,
|
||||||
|
server->workstation_RFC1001_name,
|
||||||
|
RFC1001_NAME_LEN_WITH_NULL);
|
||||||
|
else
|
||||||
|
rfc1002mangle(req.trailer.session_req.calling_name,
|
||||||
|
"LINUX_CIFS_CLNT",
|
||||||
|
RFC1001_NAME_LEN_WITH_NULL);
|
||||||
|
|
||||||
/*
|
|
||||||
* calling name ends in null (byte 16) from old smb
|
|
||||||
* convention.
|
|
||||||
*/
|
|
||||||
if (server->workstation_RFC1001_name[0] != 0)
|
|
||||||
rfc1002mangle(ses_init_buf->trailer.
|
|
||||||
session_req.calling_name,
|
|
||||||
server->workstation_RFC1001_name,
|
|
||||||
RFC1001_NAME_LEN_WITH_NULL);
|
|
||||||
else
|
|
||||||
rfc1002mangle(ses_init_buf->trailer.
|
|
||||||
session_req.calling_name,
|
|
||||||
"LINUX_CIFS_CLNT",
|
|
||||||
RFC1001_NAME_LEN_WITH_NULL);
|
|
||||||
|
|
||||||
ses_init_buf->trailer.session_req.scope1 = 0;
|
|
||||||
ses_init_buf->trailer.session_req.scope2 = 0;
|
|
||||||
smb_buf = (struct smb_hdr *)ses_init_buf;
|
|
||||||
|
|
||||||
/* sizeof RFC1002_SESSION_REQUEST with no scopes */
|
|
||||||
req_noscope_len = sizeof(struct rfc1002_session_packet) - 2;
|
|
||||||
|
|
||||||
/* == cpu_to_be32(0x81000044) */
|
|
||||||
smb_buf->smb_buf_length =
|
|
||||||
cpu_to_be32((RFC1002_SESSION_REQUEST << 24) | req_noscope_len);
|
|
||||||
rc = smb_send(server, smb_buf, 0x44);
|
|
||||||
kfree(ses_init_buf);
|
|
||||||
/*
|
|
||||||
* RFC1001 layer in at least one server
|
|
||||||
* requires very short break before negprot
|
|
||||||
* presumably because not expecting negprot
|
|
||||||
* to follow so fast. This is a simple
|
|
||||||
* solution that works without
|
|
||||||
* complicating the code and causes no
|
|
||||||
* significant slowing down on mount
|
|
||||||
* for everyone else
|
|
||||||
*/
|
|
||||||
usleep_range(1000, 2000);
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* else the negprot may still work without this
|
* As per rfc1002, @len must be the number of bytes that follows the
|
||||||
* even though malloc failed
|
* length field of a rfc1002 session request payload.
|
||||||
*/
|
*/
|
||||||
|
len = sizeof(req) - offsetof(struct rfc1002_session_packet, trailer.session_req);
|
||||||
|
|
||||||
|
smb_buf->smb_buf_length = cpu_to_be32((RFC1002_SESSION_REQUEST << 24) | len);
|
||||||
|
rc = smb_send(server, smb_buf, len);
|
||||||
|
/*
|
||||||
|
* RFC1001 layer in at least one server requires very short break before
|
||||||
|
* negprot presumably because not expecting negprot to follow so fast.
|
||||||
|
* This is a simple solution that works without complicating the code
|
||||||
|
* and causes no significant slowing down on mount for everyone else
|
||||||
|
*/
|
||||||
|
usleep_range(1000, 2000);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue