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:
Paulo Alcantara 2023-02-16 15:33:22 -03:00 committed by Steve French
parent de036dcaca
commit d99e86ebde
1 changed files with 35 additions and 59 deletions

View File

@ -2843,72 +2843,48 @@ ip_rfc1001_connect(struct TCP_Server_Info *server)
* negprot - BB check reconnection in case where second
* sessinit is sent but no second negprot
*/
struct rfc1002_session_packet *ses_init_buf;
unsigned int req_noscope_len;
struct smb_hdr *smb_buf;
struct rfc1002_session_packet req = {};
struct smb_hdr *smb_buf = (struct smb_hdr *)&req;
unsigned int len;
ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
GFP_KERNEL);
if (ses_init_buf) {
ses_init_buf->trailer.session_req.called_len = 32;
req.trailer.session_req.called_len = sizeof(req.trailer.session_req.called_name);
if (server->server_RFC1001_name[0] != 0)
rfc1002mangle(ses_init_buf->trailer.
session_req.called_name,
rfc1002mangle(req.trailer.session_req.called_name,
server->server_RFC1001_name,
RFC1001_NAME_LEN_WITH_NULL);
else
rfc1002mangle(ses_init_buf->trailer.
session_req.called_name,
rfc1002mangle(req.trailer.session_req.called_name,
DEFAULT_CIFS_CALLED_NAME,
RFC1001_NAME_LEN_WITH_NULL);
ses_init_buf->trailer.session_req.calling_len = 32;
req.trailer.session_req.calling_len = sizeof(req.trailer.session_req.calling_name);
/*
* calling name ends in null (byte 16) from old smb
* convention.
*/
/* 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,
rfc1002mangle(req.trailer.session_req.calling_name,
server->workstation_RFC1001_name,
RFC1001_NAME_LEN_WITH_NULL);
else
rfc1002mangle(ses_init_buf->trailer.
session_req.calling_name,
rfc1002mangle(req.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
* As per rfc1002, @len must be the number of bytes that follows the
* 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);
}
/*
* else the negprot may still work without this
* even though malloc failed
*/
return rc;
}