smb3: send NTLMSSP version information
authorSteve French <stfrench@microsoft.com>
Thu, 20 Jan 2022 04:00:29 +0000 (22:00 -0600)
committerSteve French <stfrench@microsoft.com>
Mon, 7 Feb 2022 21:48:16 +0000 (15:48 -0600)
For improved debugging it can be helpful to send version information
as other clients do during NTLMSSP negotiation. See protocol document
MS-NLMP section 2.2.1.1

Set the major and minor versions based on the kernel version, and the
BuildNumber based on the internal cifs.ko module version number,
and following the recommendation in the protocol documentation
(MS-NLMP section 2.2.10) we set the NTLMRevisionCurrent field to 15.

Reviewed-by: Shyam Prasad N <sprasad@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifs/cifsfs.h
fs/cifs/ntlmssp.h
fs/cifs/sess.c
fs/cifs/smb2pdu.c

index 9e5d9e192ef042202c079f204e157c6203c2f025..7c6f8180df694b717be977bfaafe4b1350f31fb8 100644 (file)
@@ -152,5 +152,6 @@ extern struct dentry *cifs_smb3_do_mount(struct file_system_type *fs_type,
 extern const struct export_operations cifs_export_ops;
 #endif /* CONFIG_CIFS_NFSD_EXPORT */
 
+#define SMB3_PRODUCT_BUILD 34
 #define CIFS_VERSION   "2.34"
 #endif                         /* _CIFSFS_H */
index 6d242af536cbff1a5ed830ec281cdb349c5518a9..2984584042527a0a461472a1921ce3bde9d657b1 100644 (file)
@@ -40,7 +40,7 @@
 #define NTLMSSP_REQUEST_NON_NT_KEY    0x400000
 #define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
 /* #define reserved4                 0x1000000 */
-#define NTLMSSP_NEGOTIATE_VERSION    0x2000000 /* we do not set */
+#define NTLMSSP_NEGOTIATE_VERSION    0x2000000 /* we only set for SMB2+ */
 /* #define reserved3                 0x4000000 */
 /* #define reserved2                 0x8000000 */
 /* #define reserved1                0x10000000 */
@@ -87,6 +87,30 @@ typedef struct _NEGOTIATE_MESSAGE {
        /* followed by WorkstationString */
 } __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
 
+#define NTLMSSP_REVISION_W2K3 0x0F
+
+/* See MS-NLMP section 2.2.2.10 */
+struct ntlmssp_version {
+       __u8    ProductMajorVersion;
+       __u8    ProductMinorVersion;
+       __le16  ProductBuild; /* we send the cifs.ko module version here */
+       __u8    Reserved[3];
+       __u8    NTLMRevisionCurrent; /* currently 0x0F */
+} __packed;
+
+/* see MS-NLMP section 2.2.1.1 */
+struct negotiate_message {
+       __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
+       __le32 MessageType;     /* NtLmNegotiate = 1 */
+       __le32 NegotiateFlags;
+       SECURITY_BUFFER DomainName;     /* RFC 1001 style and ASCII */
+       SECURITY_BUFFER WorkstationName;        /* RFC 1001 and ASCII */
+       struct  ntlmssp_version Version;
+       /* SECURITY_BUFFER */
+       char DomainString[0];
+       /* followed by WorkstationString */
+} __packed;
+
 typedef struct _CHALLENGE_MESSAGE {
        __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
        __le32 MessageType;   /* NtLmChallenge = 2 */
@@ -123,6 +147,10 @@ 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,
index 15373a377a36f2e828d8d975452fc75023191880..dc3b16d1be09aca808286134976e1a4efda7fb6c 100644 (file)
@@ -17,6 +17,8 @@
 #include "nterr.h"
 #include <linux/utsname.h>
 #include <linux/slab.h>
+#include <linux/version.h>
+#include "cifsfs.h"
 #include "cifs_spnego.h"
 #include "smb2proto.h"
 #include "fs_context.h"
@@ -809,6 +811,74 @@ setup_ntlm_neg_ret:
        return rc;
 }
 
+/*
+ * Build ntlmssp blob with additional fields, such as version,
+ * 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 rc = 0;
+       struct negotiate_message *sec_blob;
+       __u32 flags;
+       unsigned char *tmp;
+       int len;
+
+       len = size_of_ntlmssp_blob(ses, sizeof(struct negotiate_message));
+       *pbuffer = kmalloc(len, GFP_KERNEL);
+       if (!*pbuffer) {
+               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;
+
+       /* 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;
+       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;
+
+       tmp = *pbuffer + sizeof(struct negotiate_message);
+       ses->ntlmssp->client_flags = flags;
+       sec_blob->NegotiateFlags = cpu_to_le32(flags);
+
+       /* 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_security_buffer_from_str(&sec_blob->WorkstationName,
+                                     NULL,
+                                     CIFS_MAX_WORKSTATION_LEN,
+                                     *pbuffer, &tmp,
+                                     nls_cp);
+
+       *buflen = tmp - *pbuffer;
+setup_ntlm_smb3_neg_ret:
+       return rc;
+}
+
+
 int build_ntlmssp_auth_blob(unsigned char **pbuffer,
                                        u16 *buflen,
                                   struct cifs_ses *ses,
index 1e670e56b07adcb82117ad75ff1f7035696bf303..7e7909b1ae1180f836054d51a0da6bc918943231 100644 (file)
@@ -1506,7 +1506,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
        if (rc)
                goto out_err;
 
-       rc = build_ntlmssp_negotiate_blob(&ntlmssp_blob,
+       rc = build_ntlmssp_smb3_negotiate_blob(&ntlmssp_blob,
                                          &blob_length, ses, server,
                                          sess_data->nls_cp);
        if (rc)