]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Update negotiate protocol for SMB3.1 dialect
authorSteve French <steve.french@primarydata.com>
Fri, 6 Feb 2015 06:08:28 +0000 (00:08 -0600)
committerSteve French <smfrench@gmail.com>
Tue, 7 Apr 2015 03:53:51 +0000 (22:53 -0500)
Send negotiate contexts when SMB3.1 dialect is negotiated
(ie the preauth and the encryption contexts) and
Initialize SMB3.1 preauth negotiate context salt to random bytes

Followon patch will update session setup

Signed-off-by: Steve French <steve.french@primarydata.com>
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.h

index 34e0a70f4e39222d7a95f522d712ca36ee5fe379..74ea2849a759f3cad77cb1029a131df9c453dfdd 100644 (file)
@@ -304,6 +304,58 @@ small_smb2_init(__le16 smb2_command, struct cifs_tcon *tcon,
        return rc;
 }
 
+#ifdef CONFIG_CIFS_SMB31
+/* offset is sizeof smb2_negotiate_req - 4 but rounded up to 8 bytes */
+#define OFFSET_OF_NEG_CONTEXT 0x68  /* sizeof(struct smb2_negotiate_req) - 4 */
+
+
+#define SMB2_PREAUTH_INTEGRITY_CAPABILITIES    cpu_to_le16(1)
+#define SMB2_ENCRYPTION_CAPABILITIES           cpu_to_le16(2)
+
+static void
+build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt)
+{
+       pneg_ctxt->ContextType = SMB2_PREAUTH_INTEGRITY_CAPABILITIES;
+       pneg_ctxt->DataLength = cpu_to_le16(38);
+       pneg_ctxt->HashAlgorithmCount = cpu_to_le16(1);
+       pneg_ctxt->SaltLength = cpu_to_le16(SMB31_SALT_SIZE);
+       get_random_bytes(pneg_ctxt->Salt, SMB31_SALT_SIZE);
+       pneg_ctxt->HashAlgorithms = SMB2_PREAUTH_INTEGRITY_SHA512;
+}
+
+static void
+build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt)
+{
+       pneg_ctxt->ContextType = SMB2_ENCRYPTION_CAPABILITIES;
+       pneg_ctxt->DataLength = cpu_to_le16(6);
+       pneg_ctxt->CipherCount = cpu_to_le16(1);
+       pneg_ctxt->Ciphers = SMB2_ENCRYPTION_AES128_CCM;
+}
+
+static void
+assemble_neg_contexts(struct smb2_negotiate_req *req)
+{
+
+       /* +4 is to account for the RFC1001 len field */
+       char *pneg_ctxt = (char *)req + OFFSET_OF_NEG_CONTEXT + 4;
+
+       build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt);
+       /* Add 2 to size to round to 8 byte boundary */
+       pneg_ctxt += 2 + sizeof(struct smb2_preauth_neg_context);
+       build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt);
+       req->NegotiateContextOffset = cpu_to_le32(OFFSET_OF_NEG_CONTEXT);
+       req->NegotiateContextCount = cpu_to_le16(2);
+       inc_rfc1001_len(req, 4 + sizeof(struct smb2_preauth_neg_context) + 2
+                       + sizeof(struct smb2_encryption_neg_context));
+}
+#else
+static void assemble_neg_contexts(struct smb2_negotiate_req *req)
+{
+       return;
+}
+#endif /* SMB31 */
+
+
 /*
  *
  *     SMB2 Worker functions follow:
@@ -363,10 +415,12 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
        /* ClientGUID must be zero for SMB2.02 dialect */
        if (ses->server->vals->protocol_id == SMB20_PROT_ID)
                memset(req->ClientGUID, 0, SMB2_CLIENT_GUID_SIZE);
-       else
+       else {
                memcpy(req->ClientGUID, server->client_guid,
                        SMB2_CLIENT_GUID_SIZE);
-
+               if (ses->server->vals->protocol_id == SMB31_PROT_ID)
+                       assemble_neg_contexts(req);
+       }
        iov[0].iov_base = (char *)req;
        /* 4 for rfc1002 length field */
        iov[0].iov_len = get_rfc1002_length(req) + 4;
index 8b89dc00df5838e93202370f82c38b811abd5b84..623baf5c6f3eb290267a55118c11c8a71258e68d 100644 (file)
@@ -220,7 +220,7 @@ struct smb2_negotiate_req {
 
 #define SMB31_SALT_SIZE                        32
 /* Hash Algorithm Types */
-#define SMB2_PREAUTH_INTEGRITY_SHA512  0x0001
+#define SMB2_PREAUTH_INTEGRITY_SHA512  cpu_to_le16(0x0001)
 
 struct smb2_preauth_neg_context {
        __le16  ContextType; /* 1 */