[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250806203705.2560493-26-dhowells@redhat.com>
Date: Wed, 6 Aug 2025 21:36:46 +0100
From: David Howells <dhowells@...hat.com>
To: Steve French <sfrench@...ba.org>
Cc: David Howells <dhowells@...hat.com>,
Paulo Alcantara <pc@...guebit.org>,
Shyam Prasad N <sprasad@...rosoft.com>,
Tom Talpey <tom@...pey.com>,
Wang Zhaolong <wangzhaolong@...weicloud.com>,
Stefan Metzmacher <metze@...ba.org>,
Mina Almasry <almasrymina@...gle.com>,
linux-cifs@...r.kernel.org,
linux-kernel@...r.kernel.org,
netfs@...ts.linux.dev,
linux-fsdevel@...r.kernel.org
Subject: [RFC PATCH 25/31] cifs: Convert SMB2 Session Setup request
Signed-off-by: David Howells <dhowells@...hat.com>
cc: Steve French <sfrench@...ba.org>
cc: Paulo Alcantara <pc@...guebit.org>
cc: Shyam Prasad N <sprasad@...rosoft.com>
cc: Tom Talpey <tom@...pey.com>
cc: linux-cifs@...r.kernel.org
cc: netfs@...ts.linux.dev
cc: linux-fsdevel@...r.kernel.org
---
fs/smb/client/ntlmssp.h | 20 +--
fs/smb/client/sess.c | 271 ++++++++++++++++++++++------------------
fs/smb/client/smb2pdu.c | 172 ++++++++++---------------
3 files changed, 226 insertions(+), 237 deletions(-)
diff --git a/fs/smb/client/ntlmssp.h b/fs/smb/client/ntlmssp.h
index 875de43b72de..5ca249f1c51c 100644
--- a/fs/smb/client/ntlmssp.h
+++ b/fs/smb/client/ntlmssp.h
@@ -123,7 +123,7 @@ typedef struct _CHALLENGE_MESSAGE {
do not set the version is present flag */
} __attribute__((packed)) CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
-typedef struct _AUTHENTICATE_MESSAGE {
+struct ntlmssp_authenticate_message {
__u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
__le32 MessageType; /* NtLmsAuthenticate = 3 */
SECURITY_BUFFER LmChallengeResponse;
@@ -136,7 +136,7 @@ typedef struct _AUTHENTICATE_MESSAGE {
struct ntlmssp_version Version;
/* SECURITY_BUFFER */
char UserString[];
-} __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
+} __attribute__((packed));
/*
* Size of the session key (crypto key encrypted with the password
@@ -147,11 +147,11 @@ int build_ntlmssp_negotiate_blob(unsigned char **pbuffer, u16 *buflen,
struct cifs_ses *ses,
struct TCP_Server_Info *server,
const struct nls_table *nls_cp);
-int build_ntlmssp_smb3_negotiate_blob(unsigned char **pbuffer, u16 *buflen,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const struct nls_table *nls_cp);
-int build_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const struct nls_table *nls_cp);
+int build_ntlmssp_smb3_negotiate_blob(struct smb_message *smb,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const struct nls_table *nls_cp);
+int build_ntlmssp_auth_blob(struct smb_message *smb,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const struct nls_table *nls_cp);
diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c
index 330bc3d25bad..8063cf06ea9f 100644
--- a/fs/smb/client/sess.c
+++ b/fs/smb/client/sess.c
@@ -966,32 +966,86 @@ int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
return 0;
}
-static int size_of_ntlmssp_blob(struct cifs_ses *ses, int base_size)
+static int size_of_ntlmssp_blob(struct cifs_ses *ses, int base_size,
+ const struct nls_table *nls_cp)
{
int sz = base_size + ses->auth_key.len
- CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2;
if (ses->domainName)
- sz += sizeof(__le16) * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
+ sz += cifs_size_strtoUTF16(ses->domainName, CIFS_MAX_DOMAINNAME_LEN,
+ nls_cp);
else
sz += sizeof(__le16);
if (ses->user_name)
- sz += sizeof(__le16) * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN);
+ sz += cifs_size_strtoUTF16(ses->user_name, CIFS_MAX_USERNAME_LEN,
+ nls_cp);
else
sz += sizeof(__le16);
if (ses->workstation_name[0])
- sz += sizeof(__le16) * strnlen(ses->workstation_name,
- ntlmssp_workstation_name_size(ses));
+ sz += cifs_size_strtoUTF16(ses->workstation_name,
+ ntlmssp_workstation_name_size(ses),
+ nls_cp);
else
sz += sizeof(__le16);
return sz;
}
+static void cifs_append_security_string(struct smb_message *smb,
+ SECURITY_BUFFER *pbuf,
+ const char *str_value,
+ int str_length,
+ unsigned char **pcur,
+ const struct nls_table *nls_cp)
+{
+ int len;
+
+ if (!str_value) {
+ pbuf->BufferOffset = cpu_to_le32(smb->offset);
+ pbuf->Length = 0;
+ pbuf->MaximumLength = 0;
+ *(__le16 *)*pcur = 0;
+ smb->offset += 2;
+ pcur += 2;
+ } else {
+ len = cifs_strtoUTF16((__le16 *)*pcur,
+ str_value,
+ str_length,
+ nls_cp);
+ len *= sizeof(__le16);
+ pbuf->BufferOffset = cpu_to_le32(smb->offset);
+ pbuf->Length = cpu_to_le16(len);
+ pbuf->MaximumLength = cpu_to_le16(len);
+ smb->offset += len;
+ pcur += len;
+ }
+}
+
+static void cifs_append_security_blob(struct smb_message *smb,
+ SECURITY_BUFFER *pbuf,
+ const void *content,
+ int len,
+ unsigned char **pcur)
+{
+ if (!content) {
+ pbuf->BufferOffset = cpu_to_le32(smb->offset);
+ pbuf->Length = 0;
+ pbuf->MaximumLength = 0;
+ } else {
+ memcpy(pcur, content, len);
+ pbuf->BufferOffset = cpu_to_le32(smb->offset);
+ pbuf->Length = cpu_to_le16(len);
+ pbuf->MaximumLength = cpu_to_le16(len);
+ smb->offset += len;
+ pcur += len;
+ }
+}
+
static inline void cifs_security_buffer_from_str(SECURITY_BUFFER *pbuf,
- char *str_value,
+ const char *str_value,
int str_length,
unsigned char *pstart,
unsigned char **pcur,
@@ -1038,7 +1092,7 @@ int build_ntlmssp_negotiate_blob(unsigned char **pbuffer,
unsigned char *tmp;
int len;
- len = size_of_ntlmssp_blob(ses, sizeof(NEGOTIATE_MESSAGE));
+ len = size_of_ntlmssp_blob(ses, sizeof(NEGOTIATE_MESSAGE), nls_cp);
*pbuffer = kmalloc(len, GFP_KERNEL);
if (!*pbuffer) {
rc = -ENOMEM;
@@ -1088,173 +1142,148 @@ int build_ntlmssp_negotiate_blob(unsigned char **pbuffer,
* supported by modern servers. For safety limit to SMB3 or later
* See notes in MS-NLMP Section 2.2.2.1 e.g.
*/
-int build_ntlmssp_smb3_negotiate_blob(unsigned char **pbuffer,
- u16 *buflen,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const struct nls_table *nls_cp)
+int build_ntlmssp_smb3_negotiate_blob(struct smb_message *smb,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const struct nls_table *nls_cp)
{
- int rc = 0;
- struct negotiate_message *sec_blob;
- __u32 flags;
+ struct negotiate_message *neg_msg;
unsigned char *tmp;
+ __u32 flags;
+ void *blob;
int len;
+ int rc = 0;
- len = size_of_ntlmssp_blob(ses, sizeof(struct negotiate_message));
- *pbuffer = kmalloc(len, GFP_KERNEL);
- if (!*pbuffer) {
+ len = size_of_ntlmssp_blob(ses, sizeof(*neg_msg), nls_cp);
+ blob = cifs_allocate_tx_buf(server, len);
+ if (!blob) {
rc = -ENOMEM;
cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
- *buflen = 0;
goto setup_ntlm_smb3_neg_ret;
}
- sec_blob = (struct negotiate_message *)*pbuffer;
- memset(*pbuffer, 0, sizeof(struct negotiate_message));
- memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
- sec_blob->MessageType = NtLmNegotiate;
+ smb_add_segment_to_tx_buf(smb, blob, len);
+ smb->offset = sizeof(*neg_msg);
/* BB is NTLMV2 session security format easier to use here? */
- flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
- NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
- NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
- NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL |
- NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_VERSION;
+ flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
+ NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
+ NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
+ NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL |
+ NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_VERSION;
if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
- sec_blob->Version.ProductMajorVersion = LINUX_VERSION_MAJOR;
- sec_blob->Version.ProductMinorVersion = LINUX_VERSION_PATCHLEVEL;
- sec_blob->Version.ProductBuild = cpu_to_le16(SMB3_PRODUCT_BUILD);
- sec_blob->Version.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3;
+ neg_msg = (struct negotiate_message *)blob;
+ *neg_msg = (struct negotiate_message){
+ .Signature = NTLMSSP_SIGNATURE,
+ .MessageType = NtLmNegotiate,
+ .NegotiateFlags = cpu_to_le32(flags),
+ .Version.ProductMajorVersion = LINUX_VERSION_MAJOR,
+ .Version.ProductMinorVersion = LINUX_VERSION_PATCHLEVEL,
+ .Version.ProductBuild = cpu_to_le16(SMB3_PRODUCT_BUILD),
+ .Version.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3,
+ };
- tmp = *pbuffer + sizeof(struct negotiate_message);
ses->ntlmssp->client_flags = flags;
- sec_blob->NegotiateFlags = cpu_to_le32(flags);
+ tmp = blob + sizeof(struct negotiate_message);
/* these fields should be null in negotiate phase MS-NLMP 3.1.5.1.1 */
- cifs_security_buffer_from_str(&sec_blob->DomainName,
- NULL,
- CIFS_MAX_DOMAINNAME_LEN,
- *pbuffer, &tmp,
- nls_cp);
+ cifs_append_security_string(smb, &neg_msg->DomainName,
+ NULL, CIFS_MAX_DOMAINNAME_LEN,
+ &tmp, nls_cp);
- cifs_security_buffer_from_str(&sec_blob->WorkstationName,
- NULL,
- CIFS_MAX_WORKSTATION_LEN,
- *pbuffer, &tmp,
- nls_cp);
-
- *buflen = tmp - *pbuffer;
+ cifs_append_security_string(smb, &neg_msg->WorkstationName,
+ NULL, CIFS_MAX_WORKSTATION_LEN,
+ &tmp, nls_cp);
setup_ntlm_smb3_neg_ret:
return rc;
}
/* See MS-NLMP 2.2.1.3 */
-int build_ntlmssp_auth_blob(unsigned char **pbuffer,
- u16 *buflen,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const struct nls_table *nls_cp)
+int build_ntlmssp_auth_blob(struct smb_message *smb,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const struct nls_table *nls_cp)
{
- int rc;
- AUTHENTICATE_MESSAGE *sec_blob;
- __u32 flags;
+ struct ntlmssp_authenticate_message *auth_msg;
unsigned char *tmp;
+ __u32 flags;
+ void *blob;
int len;
+ int rc;
rc = setup_ntlmv2_rsp(ses, nls_cp);
if (rc) {
cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
- *buflen = 0;
goto setup_ntlmv2_ret;
}
- len = size_of_ntlmssp_blob(ses, sizeof(AUTHENTICATE_MESSAGE));
- *pbuffer = kmalloc(len, GFP_KERNEL);
- if (!*pbuffer) {
+ len = size_of_ntlmssp_blob(ses, sizeof(*auth_msg), nls_cp);
+ blob = cifs_allocate_tx_buf(server, len);
+ if (!blob) {
rc = -ENOMEM;
cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
- *buflen = 0;
goto setup_ntlmv2_ret;
}
- sec_blob = (AUTHENTICATE_MESSAGE *)*pbuffer;
- memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
- sec_blob->MessageType = NtLmAuthenticate;
+ smb_add_segment_to_tx_buf(smb, blob, len);
+ smb->offset = sizeof(*auth_msg);
/* send version information in ntlmssp authenticate also */
- flags = ses->ntlmssp->server_flags | NTLMSSP_REQUEST_TARGET |
- NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_VERSION |
+ flags = ses->ntlmssp->server_flags | NTLMSSP_REQUEST_TARGET |
+ NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_VERSION |
NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED;
- sec_blob->Version.ProductMajorVersion = LINUX_VERSION_MAJOR;
- sec_blob->Version.ProductMinorVersion = LINUX_VERSION_PATCHLEVEL;
- sec_blob->Version.ProductBuild = cpu_to_le16(SMB3_PRODUCT_BUILD);
- sec_blob->Version.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3;
+ auth_msg = blob;
+ *auth_msg = (struct ntlmssp_authenticate_message){
+ .Signature = NTLMSSP_SIGNATURE,
+ .MessageType = NtLmAuthenticate,
+ .NegotiateFlags = cpu_to_le32(flags),
+ .Version.ProductMajorVersion = LINUX_VERSION_MAJOR,
+ .Version.ProductMinorVersion = LINUX_VERSION_PATCHLEVEL,
+ .Version.ProductBuild = cpu_to_le16(SMB3_PRODUCT_BUILD),
+ .Version.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3,
+ };
- tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE);
- sec_blob->NegotiateFlags = cpu_to_le32(flags);
+ tmp = blob + sizeof(*auth_msg);
- sec_blob->LmChallengeResponse.BufferOffset =
- cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE));
- sec_blob->LmChallengeResponse.Length = 0;
- sec_blob->LmChallengeResponse.MaximumLength = 0;
+ cifs_append_security_blob(smb, &auth_msg->LmChallengeResponse,
+ NULL, 0, &tmp);
- sec_blob->NtChallengeResponse.BufferOffset =
- cpu_to_le32(tmp - *pbuffer);
- if (ses->user_name != NULL) {
- memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
- ses->auth_key.len - CIFS_SESS_KEY_SIZE);
- tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
+ /* Only send an NT Response for anonymous access */
+ if (ses->user_name)
+ cifs_append_security_blob(smb, &auth_msg->NtChallengeResponse,
+ ses->auth_key.response + CIFS_SESS_KEY_SIZE,
+ ses->auth_key.len - CIFS_SESS_KEY_SIZE,
+ &tmp);
+ else
+ cifs_append_security_blob(smb, &auth_msg->NtChallengeResponse,
+ NULL, 0, &tmp);
- sec_blob->NtChallengeResponse.Length =
- cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
- sec_blob->NtChallengeResponse.MaximumLength =
- cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
- } else {
- /*
- * don't send an NT Response for anonymous access
- */
- sec_blob->NtChallengeResponse.Length = 0;
- sec_blob->NtChallengeResponse.MaximumLength = 0;
- }
+ cifs_append_security_string(smb, &auth_msg->DomainName,
+ ses->domainName, CIFS_MAX_DOMAINNAME_LEN,
+ &tmp, nls_cp);
- cifs_security_buffer_from_str(&sec_blob->DomainName,
- ses->domainName,
- CIFS_MAX_DOMAINNAME_LEN,
- *pbuffer, &tmp,
- nls_cp);
+ cifs_append_security_string(smb, &auth_msg->UserName,
+ ses->user_name, CIFS_MAX_USERNAME_LEN,
+ &tmp, nls_cp);
- cifs_security_buffer_from_str(&sec_blob->UserName,
- ses->user_name,
- CIFS_MAX_USERNAME_LEN,
- *pbuffer, &tmp,
- nls_cp);
-
- cifs_security_buffer_from_str(&sec_blob->WorkstationName,
- ses->workstation_name,
- ntlmssp_workstation_name_size(ses),
- *pbuffer, &tmp,
- nls_cp);
+ cifs_append_security_string(smb, &auth_msg->WorkstationName,
+ ses->workstation_name,
+ ntlmssp_workstation_name_size(ses),
+ &tmp, nls_cp);
if ((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
(!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess) &&
- !calc_seckey(ses)) {
- memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
- sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
- sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
- sec_blob->SessionKey.MaximumLength =
- cpu_to_le16(CIFS_CPHTXT_SIZE);
- tmp += CIFS_CPHTXT_SIZE;
- } else {
- sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
- sec_blob->SessionKey.Length = 0;
- sec_blob->SessionKey.MaximumLength = 0;
- }
-
- *buflen = tmp - *pbuffer;
+ !calc_seckey(ses))
+ cifs_append_security_blob(smb, &auth_msg->SessionKey,
+ ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE,
+ &tmp);
+ else
+ cifs_append_security_blob(smb, &auth_msg->SessionKey,
+ NULL, 0, &tmp);
setup_ntlmv2_ret:
return rc;
}
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
index f1b6d36fe7cd..685af9c0cdcb 100644
--- a/fs/smb/client/smb2pdu.c
+++ b/fs/smb/client/smb2pdu.c
@@ -1740,33 +1740,29 @@ struct SMB2_sess_data {
void (*func)(struct SMB2_sess_data *);
int result;
u64 previous_session;
-
- /* we will send the SMB in three pieces:
- * a fixed length beginning part, an optional
- * SPNEGO blob (which can be zero length), and a
- * last part which will include the strings
- * and rest of bcc area. This allows us to avoid
- * a large buffer 17K allocation
- */
- int buf0_type;
- struct kvec iov[2];
};
-static int
-SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
+static struct smb_message *
+SMB2_create_session_request(struct SMB2_sess_data *sess_data)
{
- int rc;
+ struct smb_message *smb;
struct cifs_ses *ses = sess_data->ses;
struct TCP_Server_Info *server = sess_data->server;
struct smb2_sess_setup_req *req;
- unsigned int total_len;
bool is_binding = false;
- rc = smb2_plain_req_init(SMB2_SESSION_SETUP, NULL, server,
- (void **) &req,
- &total_len);
- if (rc)
- return rc;
+ /* We will send the SMB in three pieces:
+ * - a fixed length beginning part,
+ * - an optional SPNEGO blob (which can be zero length), and
+ * - a last part which will include the strings and rest of bcc area.
+ * This allows us to avoid a large buffer 17K allocation
+ */
+ smb = smb2_create_request(SMB2_SESSION_SETUP, server, NULL,
+ sizeof(*req), sizeof(*req), 0,
+ SMB2_REQ_DYNAMIC |
+ SMB2_REQ_SENSITIVE);
+ if (!smb)
+ return NULL;
spin_lock(&ses->ses_lock);
is_binding = (ses->ses_status == SES_GOOD);
@@ -1815,55 +1811,25 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
req->Channel = 0; /* MBZ */
- sess_data->iov[0].iov_base = (char *)req;
- /* 1 for pad */
- sess_data->iov[0].iov_len = total_len - 1;
- /*
- * This variable will be used to clear the buffer
- * allocated above in case of any error in the calling function.
- */
- sess_data->buf0_type = CIFS_SMALL_BUFFER;
-
- return 0;
-}
-
-static void
-SMB2_sess_free_buffer(struct SMB2_sess_data *sess_data)
-{
- struct kvec *iov = sess_data->iov;
-
- /* iov[1] is already freed by caller */
- if (sess_data->buf0_type != CIFS_NO_BUFFER && iov[0].iov_base)
- memzero_explicit(iov[0].iov_base, iov[0].iov_len);
-
- free_rsp_buf(sess_data->buf0_type, iov[0].iov_base);
- sess_data->buf0_type = CIFS_NO_BUFFER;
+ /* Testing shows that buffer offset must be at location of Buffer[0] */
+ req->SecurityBufferOffset = cpu_to_le16(sizeof(*req));
+ req->SecurityBufferLength = 0;
+ return smb;
}
static int
-SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data)
+SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data,
+ struct smb_message *smb)
{
int rc;
- struct smb_rqst rqst;
- struct smb2_sess_setup_req *req = sess_data->iov[0].iov_base;
- struct kvec rsp_iov = { NULL, 0 };
+ struct smb2_sess_setup_req *req = smb->request;
- /* Testing shows that buffer offset must be at location of Buffer[0] */
- req->SecurityBufferOffset =
- cpu_to_le16(sizeof(struct smb2_sess_setup_req));
- req->SecurityBufferLength = cpu_to_le16(sess_data->iov[1].iov_len);
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = sess_data->iov;
- rqst.rq_nvec = 2;
+ req->SecurityBufferLength = cpu_to_le16(smb->total_len - sizeof(*req));
/* BB add code to build os and lm fields */
- rc = cifs_send_recv(sess_data->xid, sess_data->ses,
- sess_data->server,
- &rqst,
- &sess_data->buf0_type,
- CIFS_LOG_ERROR | CIFS_SESS_OP, &rsp_iov);
- cifs_small_buf_release(sess_data->iov[0].iov_base);
+ rc = smb_send_recv_messages(sess_data->xid, sess_data->ses, sess_data->server,
+ smb, CIFS_LOG_ERROR | CIFS_SESS_OP);
+ smb_clear_request(smb);
if (rc == 0)
sess_data->ses->expired_pwd = false;
else if ((rc == -EACCES) || (rc == -EKEYEXPIRED) || (rc == -EKEYREVOKED)) {
@@ -1875,8 +1841,6 @@ SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data)
sess_data->ses->expired_pwd = true;
}
- memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec));
-
return rc;
}
@@ -1911,16 +1875,18 @@ SMB2_sess_establish_session(struct SMB2_sess_data *sess_data)
static void
SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
{
- int rc;
- struct cifs_ses *ses = sess_data->ses;
+ struct smb2_sess_setup_rsp *rsp = NULL;
struct TCP_Server_Info *server = sess_data->server;
struct cifs_spnego_msg *msg;
+ struct smb_message *smb = NULL;
+ struct cifs_ses *ses = sess_data->ses;
struct key *spnego_key = NULL;
- struct smb2_sess_setup_rsp *rsp = NULL;
+ void *key_buf = NULL;
bool is_binding = false;
+ int rc = -ENOMEM;
- rc = SMB2_sess_alloc_buffer(sess_data);
- if (rc)
+ smb = SMB2_create_session_request(sess_data);
+ if (!smb)
goto out;
spnego_key = cifs_get_spnego_key(ses, server);
@@ -1962,14 +1928,21 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
ses->auth_key.len = msg->sesskey_len;
}
- sess_data->iov[1].iov_base = msg->data + msg->sesskey_len;
- sess_data->iov[1].iov_len = msg->secblob_len;
+ /* Copy the key data here so that we can pass it to MSG_SPLICE_PAGES
+ * and the need to copy the whole message.
+ */
+ key_buf = cifs_allocate_tx_buf(server, msg->secblob_len);
+ if (!key_buf)
+ goto out;
+
+ memcpy(key_buf, msg->data + msg->sesskey_len, msg->secblob_len);
+ smb_add_segment_to_tx_buf(smb, key_buf, msg->secblob_len);
- rc = SMB2_sess_sendreceive(sess_data);
+ rc = SMB2_sess_sendreceive(sess_data, smb);
if (rc)
goto out_put_spnego_key;
- rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
+ rsp = (struct smb2_sess_setup_rsp *)smb->response;
/* keep session id and flags if binding */
if (!is_binding) {
ses->Suid = le64_to_cpu(rsp->hdr.SessionId);
@@ -1985,10 +1958,11 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
ses->auth_key.response = NULL;
ses->auth_key.len = 0;
}
+
out:
+ smb_put_messages(smb);
sess_data->result = rc;
sess_data->func = NULL;
- SMB2_sess_free_buffer(sess_data);
}
#else
static void
@@ -2006,14 +1980,13 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data);
static void
SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
{
- int rc;
- struct cifs_ses *ses = sess_data->ses;
- struct TCP_Server_Info *server = sess_data->server;
struct smb2_sess_setup_rsp *rsp = NULL;
- unsigned char *ntlmssp_blob = NULL;
+ struct TCP_Server_Info *server = sess_data->server;
+ struct smb_message *smb = NULL;
+ struct cifs_ses *ses = sess_data->ses;
bool use_spnego = false; /* else use raw ntlmssp */
- u16 blob_length = 0;
bool is_binding = false;
+ int rc = -ENOMEM;
/*
* If memory allocation is successful, caller of this function
@@ -2026,13 +1999,12 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
}
ses->ntlmssp->sesskey_per_smbsess = true;
- rc = SMB2_sess_alloc_buffer(sess_data);
- if (rc)
+ smb = SMB2_create_session_request(sess_data);
+ if (!smb)
goto out_err;
- rc = build_ntlmssp_smb3_negotiate_blob(&ntlmssp_blob,
- &blob_length, ses, server,
- sess_data->nls_cp);
+ rc = build_ntlmssp_smb3_negotiate_blob(smb, ses, server,
+ sess_data->nls_cp);
if (rc)
goto out;
@@ -2042,15 +2014,12 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
rc = -EOPNOTSUPP;
goto out;
}
- sess_data->iov[1].iov_base = ntlmssp_blob;
- sess_data->iov[1].iov_len = blob_length;
- rc = SMB2_sess_sendreceive(sess_data);
- rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
+ rc = SMB2_sess_sendreceive(sess_data, smb);
+ rsp = (struct smb2_sess_setup_rsp *)smb->response;
/* If true, rc here is expected and not an error */
- if (sess_data->buf0_type != CIFS_NO_BUFFER &&
- rsp->hdr.Status == STATUS_MORE_PROCESSING_REQUIRED)
+ if (rsp->hdr.Status == STATUS_MORE_PROCESSING_REQUIRED)
rc = 0;
if (rc)
@@ -2081,14 +2050,13 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
}
out:
- kfree_sensitive(ntlmssp_blob);
- SMB2_sess_free_buffer(sess_data);
if (!rc) {
sess_data->result = 0;
sess_data->func = SMB2_sess_auth_rawntlmssp_authenticate;
return;
}
out_err:
+ smb_put_messages(smb);
kfree_sensitive(ses->ntlmssp);
ses->ntlmssp = NULL;
sess_data->result = rc;
@@ -2098,26 +2066,23 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
static void
SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
{
- int rc;
+ struct smb_message *smb;
struct cifs_ses *ses = sess_data->ses;
struct TCP_Server_Info *server = sess_data->server;
struct smb2_sess_setup_req *req;
struct smb2_sess_setup_rsp *rsp = NULL;
- unsigned char *ntlmssp_blob = NULL;
bool use_spnego = false; /* else use raw ntlmssp */
- u16 blob_length = 0;
bool is_binding = false;
+ int rc = -ENOMEM;
- rc = SMB2_sess_alloc_buffer(sess_data);
- if (rc)
+ smb = SMB2_create_session_request(sess_data);
+ if (!smb)
goto out;
- req = (struct smb2_sess_setup_req *) sess_data->iov[0].iov_base;
+ req = smb->request;
req->hdr.SessionId = cpu_to_le64(ses->Suid);
- rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length,
- ses, server,
- sess_data->nls_cp);
+ rc = build_ntlmssp_auth_blob(smb, ses, server, sess_data->nls_cp);
if (rc) {
cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d\n", rc);
goto out;
@@ -2129,14 +2094,12 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
rc = -EOPNOTSUPP;
goto out;
}
- sess_data->iov[1].iov_base = ntlmssp_blob;
- sess_data->iov[1].iov_len = blob_length;
- rc = SMB2_sess_sendreceive(sess_data);
+ rc = SMB2_sess_sendreceive(sess_data, smb);
if (rc)
goto out;
- rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
+ rsp = (struct smb2_sess_setup_rsp *)smb->response;
spin_lock(&ses->ses_lock);
is_binding = (ses->ses_status == SES_GOOD);
@@ -2165,8 +2128,6 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
}
#endif
out:
- kfree_sensitive(ntlmssp_blob);
- SMB2_sess_free_buffer(sess_data);
kfree_sensitive(ses->ntlmssp);
ses->ntlmssp = NULL;
sess_data->result = rc;
@@ -2224,7 +2185,6 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
sess_data->xid = xid;
sess_data->ses = ses;
sess_data->server = server;
- sess_data->buf0_type = CIFS_NO_BUFFER;
sess_data->nls_cp = (struct nls_table *) nls_cp;
sess_data->previous_session = ses->Suid;
Powered by blists - more mailing lists