aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <smfrench@gmail.com>2015-06-18 05:49:47 -0400
committerSteve French <steve.french@primarydata.com>2015-06-28 22:15:48 -0400
commitebb3a9d4ba3babd19c83b96fc88fc9b0d2f7d2d6 (patch)
treebfe7737d98d4aa53c9f428f0a73f3e0b025368f6
parentb3152e2c7aa9ad0c50085738d048fbf16d01d32d (diff)
Update negotiate protocol for SMB3.11 dialect
Send negotiate contexts when SMB3.11 dialect is negotiated (ie the preauth and the encryption contexts) and Initialize SMB3.11 preauth negotiate context salt to random bytes Followon patch will update session setup and tree connect Signed-off-by: Steve French <steve.french@primarydata.com>
-rw-r--r--fs/cifs/smb2pdu.c59
-rw-r--r--fs/cifs/smb2pdu.h6
2 files changed, 60 insertions, 5 deletions
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 0479e3c87a2c..b8b4f08ee094 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -304,6 +304,59 @@ small_smb2_init(__le16 smb2_command, struct cifs_tcon *tcon,
304 return rc; 304 return rc;
305} 305}
306 306
307#ifdef CONFIG_CIFS_SMB311
308/* offset is sizeof smb2_negotiate_req - 4 but rounded up to 8 bytes */
309#define OFFSET_OF_NEG_CONTEXT 0x68 /* sizeof(struct smb2_negotiate_req) - 4 */
310
311
312#define SMB2_PREAUTH_INTEGRITY_CAPABILITIES cpu_to_le16(1)
313#define SMB2_ENCRYPTION_CAPABILITIES cpu_to_le16(2)
314
315static void
316build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt)
317{
318 pneg_ctxt->ContextType = SMB2_PREAUTH_INTEGRITY_CAPABILITIES;
319 pneg_ctxt->DataLength = cpu_to_le16(38);
320 pneg_ctxt->HashAlgorithmCount = cpu_to_le16(1);
321 pneg_ctxt->SaltLength = cpu_to_le16(SMB311_SALT_SIZE);
322 get_random_bytes(pneg_ctxt->Salt, SMB311_SALT_SIZE);
323 pneg_ctxt->HashAlgorithms = SMB2_PREAUTH_INTEGRITY_SHA512;
324}
325
326static void
327build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt)
328{
329 pneg_ctxt->ContextType = SMB2_ENCRYPTION_CAPABILITIES;
330 pneg_ctxt->DataLength = cpu_to_le16(6);
331 pneg_ctxt->CipherCount = cpu_to_le16(2);
332 pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM;
333 pneg_ctxt->Ciphers[1] = SMB2_ENCRYPTION_AES128_CCM;
334}
335
336static void
337assemble_neg_contexts(struct smb2_negotiate_req *req)
338{
339
340 /* +4 is to account for the RFC1001 len field */
341 char *pneg_ctxt = (char *)req + OFFSET_OF_NEG_CONTEXT + 4;
342
343 build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt);
344 /* Add 2 to size to round to 8 byte boundary */
345 pneg_ctxt += 2 + sizeof(struct smb2_preauth_neg_context);
346 build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt);
347 req->NegotiateContextOffset = cpu_to_le32(OFFSET_OF_NEG_CONTEXT);
348 req->NegotiateContextCount = cpu_to_le16(2);
349 inc_rfc1001_len(req, 4 + sizeof(struct smb2_preauth_neg_context) + 2
350 + sizeof(struct smb2_encryption_neg_context)); /* calculate hash */
351}
352#else
353static void assemble_neg_contexts(struct smb2_negotiate_req *req)
354{
355 return;
356}
357#endif /* SMB311 */
358
359
307/* 360/*
308 * 361 *
309 * SMB2 Worker functions follow: 362 * SMB2 Worker functions follow:
@@ -363,10 +416,12 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
363 /* ClientGUID must be zero for SMB2.02 dialect */ 416 /* ClientGUID must be zero for SMB2.02 dialect */
364 if (ses->server->vals->protocol_id == SMB20_PROT_ID) 417 if (ses->server->vals->protocol_id == SMB20_PROT_ID)
365 memset(req->ClientGUID, 0, SMB2_CLIENT_GUID_SIZE); 418 memset(req->ClientGUID, 0, SMB2_CLIENT_GUID_SIZE);
366 else 419 else {
367 memcpy(req->ClientGUID, server->client_guid, 420 memcpy(req->ClientGUID, server->client_guid,
368 SMB2_CLIENT_GUID_SIZE); 421 SMB2_CLIENT_GUID_SIZE);
369 422 if (ses->server->vals->protocol_id == SMB311_PROT_ID)
423 assemble_neg_contexts(req);
424 }
370 iov[0].iov_base = (char *)req; 425 iov[0].iov_base = (char *)req;
371 /* 4 for rfc1002 length field */ 426 /* 4 for rfc1002 length field */
372 iov[0].iov_len = get_rfc1002_length(req) + 4; 427 iov[0].iov_len = get_rfc1002_length(req) + 4;
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 2d91c2a7b218..451108284a2f 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -220,7 +220,7 @@ struct smb2_negotiate_req {
220 220
221#define SMB311_SALT_SIZE 32 221#define SMB311_SALT_SIZE 32
222/* Hash Algorithm Types */ 222/* Hash Algorithm Types */
223#define SMB2_PREAUTH_INTEGRITY_SHA512 0x0001 223#define SMB2_PREAUTH_INTEGRITY_SHA512 cpu_to_le16(0x0001)
224 224
225struct smb2_preauth_neg_context { 225struct smb2_preauth_neg_context {
226 __le16 ContextType; /* 1 */ 226 __le16 ContextType; /* 1 */
@@ -240,8 +240,8 @@ struct smb2_encryption_neg_context {
240 __le16 ContextType; /* 2 */ 240 __le16 ContextType; /* 2 */
241 __le16 DataLength; 241 __le16 DataLength;
242 __le32 Reserved; 242 __le32 Reserved;
243 __le16 CipherCount; /* 1 for time being, only AES-128-CCM */ 243 __le16 CipherCount; /* AES-128-GCM and AES-128-CCM */
244 __le16 Ciphers; /* Ciphers[0] since only one used now */ 244 __le16 Ciphers[2]; /* Ciphers[0] since only one used now */
245} __packed; 245} __packed;
246 246
247struct smb2_negotiate_rsp { 247struct smb2_negotiate_rsp {