Commit 26ea888f authored by Steve French's avatar Steve French Committed by Steve French

Negotiate and save preferred compression algorithms

New negotiate context (3) allows the server and client to
negotiate which compression algorithms to use. Add support
for this and save it off in the server structure.

Also now displayed in /proc/fs/cifs/DebugData (see below example
to Windows 10) where compression algoirthm "LZ77" was negotiated:

Servers:
Number of credits: 326 Dialect 0x311 COMPRESS_LZ77 signed
1) Name: 192.168.92.17 Uses: 1 Capability: 0x300067	Session Status: 1 TCP status: 1 Instance: 1

See MS-XCA and MS-SMB2 2.2.3.1 for more details.
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
Reviewed-by: default avatarRonnie Sahlberg <lsahlber@redhat.com>
parent 392e1c5d
...@@ -332,6 +332,12 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) ...@@ -332,6 +332,12 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
#endif #endif
seq_printf(m, "\nNumber of credits: %d Dialect 0x%x", seq_printf(m, "\nNumber of credits: %d Dialect 0x%x",
server->credits, server->dialect); server->credits, server->dialect);
if (server->compress_algorithm == SMB3_COMPRESS_LZNT1)
seq_printf(m, " COMPRESS_LZNT1");
else if (server->compress_algorithm == SMB3_COMPRESS_LZ77)
seq_printf(m, " COMPRESS_LZ77");
else if (server->compress_algorithm == SMB3_COMPRESS_LZ77_HUFF)
seq_printf(m, " COMPRESS_LZ77_HUFF");
if (server->sign) if (server->sign)
seq_printf(m, " signed"); seq_printf(m, " signed");
if (server->posix_ext_supported) if (server->posix_ext_supported)
......
...@@ -734,6 +734,7 @@ struct TCP_Server_Info { ...@@ -734,6 +734,7 @@ struct TCP_Server_Info {
#endif /* STATS2 */ #endif /* STATS2 */
unsigned int max_read; unsigned int max_read;
unsigned int max_write; unsigned int max_write;
__le16 compress_algorithm;
__le16 cipher_type; __le16 cipher_type;
/* save initital negprot hash */ /* save initital negprot hash */
__u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE]; __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
......
...@@ -472,6 +472,19 @@ build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt) ...@@ -472,6 +472,19 @@ build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt)
pneg_ctxt->HashAlgorithms = SMB2_PREAUTH_INTEGRITY_SHA512; pneg_ctxt->HashAlgorithms = SMB2_PREAUTH_INTEGRITY_SHA512;
} }
static void
build_compression_ctxt(struct smb2_compression_capabilities_context *pneg_ctxt)
{
pneg_ctxt->ContextType = SMB2_COMPRESSION_CAPABILITIES;
pneg_ctxt->DataLength =
cpu_to_le16(sizeof(struct smb2_compression_capabilities_context)
- sizeof(struct smb2_neg_context));
pneg_ctxt->CompressionAlgorithmCount = cpu_to_le16(3);
pneg_ctxt->CompressionAlgorithms[0] = SMB3_COMPRESS_LZ77;
pneg_ctxt->CompressionAlgorithms[1] = SMB3_COMPRESS_LZ77_HUFF;
pneg_ctxt->CompressionAlgorithms[2] = SMB3_COMPRESS_LZNT1;
}
static void static void
build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt) build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt)
{ {
...@@ -538,10 +551,17 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, ...@@ -538,10 +551,17 @@ assemble_neg_contexts(struct smb2_negotiate_req *req,
*total_len += ctxt_len; *total_len += ctxt_len;
pneg_ctxt += ctxt_len; pneg_ctxt += ctxt_len;
build_compression_ctxt((struct smb2_compression_capabilities_context *)
pneg_ctxt);
ctxt_len = DIV_ROUND_UP(
sizeof(struct smb2_compression_capabilities_context), 8) * 8;
*total_len += ctxt_len;
pneg_ctxt += ctxt_len;
build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt); build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt);
*total_len += sizeof(struct smb2_posix_neg_context); *total_len += sizeof(struct smb2_posix_neg_context);
req->NegotiateContextCount = cpu_to_le16(3); req->NegotiateContextCount = cpu_to_le16(4);
} }
static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt) static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt)
...@@ -559,6 +579,27 @@ static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt) ...@@ -559,6 +579,27 @@ static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt)
printk_once(KERN_WARNING "unknown SMB3 hash algorithm\n"); printk_once(KERN_WARNING "unknown SMB3 hash algorithm\n");
} }
static void decode_compress_ctx(struct TCP_Server_Info *server,
struct smb2_compression_capabilities_context *ctxt)
{
unsigned int len = le16_to_cpu(ctxt->DataLength);
/* sizeof compress context is a one element compression capbility struct */
if (len < 10) {
printk_once(KERN_WARNING "server sent bad compression cntxt\n");
return;
}
if (le16_to_cpu(ctxt->CompressionAlgorithmCount) != 1) {
printk_once(KERN_WARNING "illegal SMB3 compress algorithm count\n");
return;
}
if (le16_to_cpu(ctxt->CompressionAlgorithms[0]) > 3) {
printk_once(KERN_WARNING "unknown compression algorithm\n");
return;
}
server->compress_algorithm = ctxt->CompressionAlgorithms[0];
}
static int decode_encrypt_ctx(struct TCP_Server_Info *server, static int decode_encrypt_ctx(struct TCP_Server_Info *server,
struct smb2_encryption_neg_context *ctxt) struct smb2_encryption_neg_context *ctxt)
{ {
...@@ -623,6 +664,9 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp, ...@@ -623,6 +664,9 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES)
rc = decode_encrypt_ctx(server, rc = decode_encrypt_ctx(server,
(struct smb2_encryption_neg_context *)pctx); (struct smb2_encryption_neg_context *)pctx);
else if (pctx->ContextType == SMB2_COMPRESSION_CAPABILITIES)
decode_compress_ctx(server,
(struct smb2_compression_capabilities_context *)pctx);
else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE) else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE)
server->posix_ext_supported = true; server->posix_ext_supported = true;
else else
......
...@@ -297,16 +297,19 @@ struct smb2_encryption_neg_context { ...@@ -297,16 +297,19 @@ struct smb2_encryption_neg_context {
} __packed; } __packed;
/* See MS-SMB2 2.2.3.1.3 */ /* See MS-SMB2 2.2.3.1.3 */
#define SMB3_COMPRESS_NONE 0x0000 #define SMB3_COMPRESS_NONE cpu_to_le16(0x0000)
#define SMB3_COMPRESS_LZNT1 0x0001 #define SMB3_COMPRESS_LZNT1 cpu_to_le16(0x0001)
#define SMB3_COMPRESS_LZ77 0x0002 #define SMB3_COMPRESS_LZ77 cpu_to_le16(0x0002)
#define SMB3_COMPRESS_LZ77_HUFF 0x0003 #define SMB3_COMPRESS_LZ77_HUFF cpu_to_le16(0x0003)
struct smb2_compression_capabilities_context { struct smb2_compression_capabilities_context {
__le16 ContextType; /* 3 */
__le16 DataLength;
__u32 Reserved;
__le16 CompressionAlgorithmCount; __le16 CompressionAlgorithmCount;
__u16 Padding; __u16 Padding;
__u32 Reserved; __u32 Reserved1;
__u16 CompressionAlgorithms[1]; __le16 CompressionAlgorithms[3];
} __packed; } __packed;
/* /*
......
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