smb3: add support for posix negotiate context
authorSteve French <stfrench@microsoft.com>
Sun, 20 May 2018 01:45:27 +0000 (20:45 -0500)
committerSteve French <stfrench@microsoft.com>
Wed, 30 May 2018 21:06:18 +0000 (16:06 -0500)
Unlike CIFS where UNIX/POSIX extensions had been negotiatable,
SMB3 did not have POSIX extensions yet.  Add the new SMB3.11
POSIX negotiate context to ask the server whether it can
support POSIX (and thus whether we can send the new POSIX open
context).

Signed-off-by: Steve French <smfrench@gmail.com>
fs/cifs/cifs_debug.c
fs/cifs/cifsglob.h
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.h

index 7b857002c063ef25afb0a6e2b9789a42c9bda3a0..842b198d851625e6369e61eeedc66a0d9205f4fc 100644 (file)
@@ -238,6 +238,10 @@ skip_rdma:
                        server->credits,  server->dialect);
                if (server->sign)
                        seq_printf(m, " signed");
+#ifdef CONFIG_CIFS_SMB311
+               if (server->posix_ext_supported)
+                       seq_printf(m, " posix");
+#endif /* 3.1.1 */
                i++;
                list_for_each(tmp2, &server->smb_ses_list) {
                        ses = list_entry(tmp2, struct cifs_ses,
index d2ac9ced28c909418f6efc0d497b0804d9dae864..b131a395b95c8619443c628285288c7434ed6f67 100644 (file)
@@ -683,6 +683,7 @@ struct TCP_Server_Info {
        __le16  cipher_type;
         /* save initital negprot hash */
        __u8    preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
+       bool    posix_ext_supported;
 #endif /* 3.1.1 */
        struct delayed_work reconnect; /* reconnect workqueue job */
        struct mutex reconnect_mutex; /* prevent simultaneous reconnects */
index a02f6b674d0f9d7cc115760a49b112bf54ca9dd6..5e947db322a718d9af61ed8245456e0fa56550bc 100644 (file)
@@ -368,6 +368,7 @@ smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon,
 
 #define SMB2_PREAUTH_INTEGRITY_CAPABILITIES    cpu_to_le16(1)
 #define SMB2_ENCRYPTION_CAPABILITIES           cpu_to_le16(2)
+#define SMB2_POSIX_EXTENSIONS_AVAILABLE                cpu_to_le16(0x100)
 
 static void
 build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt)
@@ -390,22 +391,36 @@ build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt)
        pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_CCM;
 }
 
+static void
+build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt)
+{
+       pneg_ctxt->ContextType = SMB2_POSIX_EXTENSIONS_AVAILABLE;
+       pneg_ctxt->DataLength = cpu_to_le16(POSIX_CTXT_DATA_LEN);
+}
+
 static void
 assemble_neg_contexts(struct smb2_negotiate_req *req,
                      unsigned int *total_len)
 {
        char *pneg_ctxt = (char *)req + OFFSET_OF_NEG_CONTEXT;
+       unsigned int ctxt_len;
 
+       *total_len += 2; /* Add 2 due to round to 8 byte boundary for 1st ctxt */
        build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt);
-       /* Add 2 to size to round to 8 byte boundary */
+       ctxt_len = DIV_ROUND_UP(sizeof(struct smb2_preauth_neg_context), 8) * 8;
+       *total_len += ctxt_len;
+       pneg_ctxt += ctxt_len;
 
-       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);
+       ctxt_len = DIV_ROUND_UP(sizeof(struct smb2_encryption_neg_context), 8) * 8;
+       *total_len += ctxt_len;
+       pneg_ctxt += ctxt_len;
+
+       build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt);
+       *total_len += sizeof(struct smb2_posix_neg_context);
 
-       *total_len += 4 + sizeof(struct smb2_preauth_neg_context)
-               + sizeof(struct smb2_encryption_neg_context);
+       req->NegotiateContextOffset = cpu_to_le32(OFFSET_OF_NEG_CONTEXT);
+       req->NegotiateContextCount = cpu_to_le16(3);
 }
 
 static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt)
@@ -488,6 +503,8 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
                else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES)
                        rc = decode_encrypt_ctx(server,
                                (struct smb2_encryption_neg_context *)pctx);
+               else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE)
+                       server->posix_ext_supported = true;
                else
                        cifs_dbg(VFS, "unknown negcontext of type %d ignored\n",
                                le16_to_cpu(pctx->ContextType));
index d28f358022c507cc0dc55dbebb382ed29dec708d..853e5a707276a8df1b70c1849af1c9c061104929 100644 (file)
@@ -300,6 +300,14 @@ struct smb2_encryption_neg_context {
        __le16  Ciphers[1]; /* Ciphers[0] since only one used now */
 } __packed;
 
+#define POSIX_CTXT_DATA_LEN    8
+struct smb2_posix_neg_context {
+       __le16  ContextType; /* 0x100 */
+       __le16  DataLength;
+       __le32  Reserved;
+       __le64  Reserved1; /* In case needed for future (eg version or caps) */
+} __packed;
+
 struct smb2_negotiate_rsp {
        struct smb2_hdr hdr;
        __le16 StructureSize;   /* Must be 65 */