summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-03-03 19:00:59 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-03-03 19:00:59 -0500
commit0a040b2113ec226bcf56fcbe02d035bb5b30c35e (patch)
tree2e2b8908640ffce4b474802134a18412a23b180d /fs
parent4e66c42c60fdf9be81837857454a41b39bf1b773 (diff)
parentef65aaede23f75977af56a8c330bb9be8c6e125c (diff)
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull SMB3 fixes from Steve French: "Some small bug fixes as well as SMB2.1/SMB3 enablement for DFS (global namespace) which previously was only enabled for CIFS" * 'for-next' of git://git.samba.org/sfrench/cifs-2.6: smb2: Enforce sec= mount option CIFS: Fix sparse warnings CIFS: implement get_dfs_refer for SMB2+ CIFS: use DFS pathnames in SMB2+ Create requests CIFS: set signing flag in SMB2+ TreeConnect if needed CIFS: let ses->ipc_tid hold smb2 TreeIds CIFS: add use_ipc flag to SMB2_ioctl() CIFS: add build_path_from_dentry_optional_prefix() CIFS: move DFS response parsing out of SMB1 code CIFS: Fix possible use after free in demultiplex thread
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifs_dfs_ref.c4
-rw-r--r--fs/cifs/cifs_unicode.h6
-rw-r--r--fs/cifs/cifsglob.h5
-rw-r--r--fs/cifs/cifspdu.h16
-rw-r--r--fs/cifs/cifsproto.h9
-rw-r--r--fs/cifs/cifssmb.c119
-rw-r--r--fs/cifs/connect.c3
-rw-r--r--fs/cifs/dir.c13
-rw-r--r--fs/cifs/misc.c105
-rw-r--r--fs/cifs/sess.c4
-rw-r--r--fs/cifs/smb1ops.c1
-rw-r--r--fs/cifs/smb2file.c3
-rw-r--r--fs/cifs/smb2ops.c160
-rw-r--r--fs/cifs/smb2pdu.c154
-rw-r--r--fs/cifs/smb2pdu.h8
-rw-r--r--fs/cifs/smb2proto.h5
16 files changed, 447 insertions, 168 deletions
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index 9156be545b0f..6b61df117fd4 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -303,7 +303,9 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
303 * gives us the latter, so we must adjust the result. 303 * gives us the latter, so we must adjust the result.
304 */ 304 */
305 mnt = ERR_PTR(-ENOMEM); 305 mnt = ERR_PTR(-ENOMEM);
306 full_path = build_path_from_dentry(mntpt); 306
307 /* always use tree name prefix */
308 full_path = build_path_from_dentry_optional_prefix(mntpt, true);
307 if (full_path == NULL) 309 if (full_path == NULL)
308 goto cdda_exit; 310 goto cdda_exit;
309 311
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
index 479bc0a941f3..3d7298cc0aeb 100644
--- a/fs/cifs/cifs_unicode.h
+++ b/fs/cifs/cifs_unicode.h
@@ -130,10 +130,10 @@ wchar_t cifs_toupper(wchar_t in);
130 * Returns: 130 * Returns:
131 * Address of the first string 131 * Address of the first string
132 */ 132 */
133static inline wchar_t * 133static inline __le16 *
134UniStrcat(wchar_t *ucs1, const wchar_t *ucs2) 134UniStrcat(__le16 *ucs1, const __le16 *ucs2)
135{ 135{
136 wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */ 136 __le16 *anchor = ucs1; /* save a pointer to start of ucs1 */
137 137
138 while (*ucs1++) ; /* To end of first string */ 138 while (*ucs1++) ; /* To end of first string */
139 ucs1--; /* Return to the null */ 139 ucs1--; /* Return to the null */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 1a90bb3e2986..d42dd3288647 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -443,6 +443,9 @@ struct smb_version_operations {
443 int (*is_transform_hdr)(void *buf); 443 int (*is_transform_hdr)(void *buf);
444 int (*receive_transform)(struct TCP_Server_Info *, 444 int (*receive_transform)(struct TCP_Server_Info *,
445 struct mid_q_entry **); 445 struct mid_q_entry **);
446 enum securityEnum (*select_sectype)(struct TCP_Server_Info *,
447 enum securityEnum);
448
446}; 449};
447 450
448struct smb_version_values { 451struct smb_version_values {
@@ -822,7 +825,7 @@ struct cifs_ses {
822 int ses_count; /* reference counter */ 825 int ses_count; /* reference counter */
823 enum statusEnum status; 826 enum statusEnum status;
824 unsigned overrideSecFlg; /* if non-zero override global sec flags */ 827 unsigned overrideSecFlg; /* if non-zero override global sec flags */
825 __u16 ipc_tid; /* special tid for connection to IPC share */ 828 __u32 ipc_tid; /* special tid for connection to IPC share */
826 char *serverOS; /* name of operating system underlying server */ 829 char *serverOS; /* name of operating system underlying server */
827 char *serverNOS; /* name of network operating system of server */ 830 char *serverNOS; /* name of network operating system of server */
828 char *serverDomain; /* security realm of server */ 831 char *serverDomain; /* security realm of server */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index f5b87303ce46..1ce733f3582f 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -2086,17 +2086,21 @@ typedef struct dfs_referral_level_3 { /* version 4 is same, + one flag bit */
2086 __u8 ServiceSiteGuid[16]; /* MBZ, ignored */ 2086 __u8 ServiceSiteGuid[16]; /* MBZ, ignored */
2087} __attribute__((packed)) REFERRAL3; 2087} __attribute__((packed)) REFERRAL3;
2088 2088
2089typedef struct smb_com_transaction_get_dfs_refer_rsp { 2089struct get_dfs_referral_rsp {
2090 struct smb_hdr hdr; /* wct = 10 */
2091 struct trans2_resp t2;
2092 __u16 ByteCount;
2093 __u8 Pad;
2094 __le16 PathConsumed; 2090 __le16 PathConsumed;
2095 __le16 NumberOfReferrals; 2091 __le16 NumberOfReferrals;
2096 __le32 DFSFlags; 2092 __le32 DFSFlags;
2097 REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */ 2093 REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */
2098 /* followed by the strings pointed to by the referral structures */ 2094 /* followed by the strings pointed to by the referral structures */
2099} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_RSP; 2095} __packed;
2096
2097typedef struct smb_com_transaction_get_dfs_refer_rsp {
2098 struct smb_hdr hdr; /* wct = 10 */
2099 struct trans2_resp t2;
2100 __u16 ByteCount;
2101 __u8 Pad;
2102 struct get_dfs_referral_rsp dfs_data;
2103} __packed TRANSACTION2_GET_DFS_REFER_RSP;
2100 2104
2101/* DFS Flags */ 2105/* DFS Flags */
2102#define DFSREF_REFERRAL_SERVER 0x00000001 /* all targets are DFS roots */ 2106#define DFSREF_REFERRAL_SERVER 0x00000001 /* all targets are DFS roots */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 406d2c10ba78..97e5d236d265 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -61,6 +61,8 @@ extern void exit_cifs_idmap(void);
61extern int init_cifs_spnego(void); 61extern int init_cifs_spnego(void);
62extern void exit_cifs_spnego(void); 62extern void exit_cifs_spnego(void);
63extern char *build_path_from_dentry(struct dentry *); 63extern char *build_path_from_dentry(struct dentry *);
64extern char *build_path_from_dentry_optional_prefix(struct dentry *direntry,
65 bool prefix);
64extern char *cifs_build_path_to_root(struct smb_vol *vol, 66extern char *cifs_build_path_to_root(struct smb_vol *vol,
65 struct cifs_sb_info *cifs_sb, 67 struct cifs_sb_info *cifs_sb,
66 struct cifs_tcon *tcon, 68 struct cifs_tcon *tcon,
@@ -284,6 +286,11 @@ extern int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
284 const struct nls_table *nls_codepage, 286 const struct nls_table *nls_codepage,
285 unsigned int *num_referrals, 287 unsigned int *num_referrals,
286 struct dfs_info3_param **referrals, int remap); 288 struct dfs_info3_param **referrals, int remap);
289extern int parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
290 unsigned int *num_of_nodes,
291 struct dfs_info3_param **target_nodes,
292 const struct nls_table *nls_codepage, int remap,
293 const char *searchName, bool is_unicode);
287extern void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon, 294extern void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
288 struct cifs_sb_info *cifs_sb, 295 struct cifs_sb_info *cifs_sb,
289 struct smb_vol *vol); 296 struct smb_vol *vol);
@@ -526,4 +533,6 @@ int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
526int __cifs_calc_signature(struct smb_rqst *rqst, 533int __cifs_calc_signature(struct smb_rqst *rqst,
527 struct TCP_Server_Info *server, char *signature, 534 struct TCP_Server_Info *server, char *signature,
528 struct shash_desc *shash); 535 struct shash_desc *shash);
536enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
537 enum securityEnum);
529#endif /* _CIFSPROTO_H */ 538#endif /* _CIFSPROTO_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index f5099fb8a22f..066950671929 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -4786,117 +4786,6 @@ GetInodeNumOut:
4786 return rc; 4786 return rc;
4787} 4787}
4788 4788
4789/* parses DFS refferal V3 structure
4790 * caller is responsible for freeing target_nodes
4791 * returns:
4792 * on success - 0
4793 * on failure - errno
4794 */
4795static int
4796parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4797 unsigned int *num_of_nodes,
4798 struct dfs_info3_param **target_nodes,
4799 const struct nls_table *nls_codepage, int remap,
4800 const char *searchName)
4801{
4802 int i, rc = 0;
4803 char *data_end;
4804 bool is_unicode;
4805 struct dfs_referral_level_3 *ref;
4806
4807 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4808 is_unicode = true;
4809 else
4810 is_unicode = false;
4811 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4812
4813 if (*num_of_nodes < 1) {
4814 cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d\n",
4815 *num_of_nodes);
4816 rc = -EINVAL;
4817 goto parse_DFS_referrals_exit;
4818 }
4819
4820 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4821 if (ref->VersionNumber != cpu_to_le16(3)) {
4822 cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3\n",
4823 le16_to_cpu(ref->VersionNumber));
4824 rc = -EINVAL;
4825 goto parse_DFS_referrals_exit;
4826 }
4827
4828 /* get the upper boundary of the resp buffer */
4829 data_end = (char *)(&(pSMBr->PathConsumed)) +
4830 le16_to_cpu(pSMBr->t2.DataCount);
4831
4832 cifs_dbg(FYI, "num_referrals: %d dfs flags: 0x%x ...\n",
4833 *num_of_nodes, le32_to_cpu(pSMBr->DFSFlags));
4834
4835 *target_nodes = kcalloc(*num_of_nodes, sizeof(struct dfs_info3_param),
4836 GFP_KERNEL);
4837 if (*target_nodes == NULL) {
4838 rc = -ENOMEM;
4839 goto parse_DFS_referrals_exit;
4840 }
4841
4842 /* collect necessary data from referrals */
4843 for (i = 0; i < *num_of_nodes; i++) {
4844 char *temp;
4845 int max_len;
4846 struct dfs_info3_param *node = (*target_nodes)+i;
4847
4848 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4849 if (is_unicode) {
4850 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4851 GFP_KERNEL);
4852 if (tmp == NULL) {
4853 rc = -ENOMEM;
4854 goto parse_DFS_referrals_exit;
4855 }
4856 cifsConvertToUTF16((__le16 *) tmp, searchName,
4857 PATH_MAX, nls_codepage, remap);
4858 node->path_consumed = cifs_utf16_bytes(tmp,
4859 le16_to_cpu(pSMBr->PathConsumed),
4860 nls_codepage);
4861 kfree(tmp);
4862 } else
4863 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4864
4865 node->server_type = le16_to_cpu(ref->ServerType);
4866 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4867
4868 /* copy DfsPath */
4869 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4870 max_len = data_end - temp;
4871 node->path_name = cifs_strndup_from_utf16(temp, max_len,
4872 is_unicode, nls_codepage);
4873 if (!node->path_name) {
4874 rc = -ENOMEM;
4875 goto parse_DFS_referrals_exit;
4876 }
4877
4878 /* copy link target UNC */
4879 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4880 max_len = data_end - temp;
4881 node->node_name = cifs_strndup_from_utf16(temp, max_len,
4882 is_unicode, nls_codepage);
4883 if (!node->node_name) {
4884 rc = -ENOMEM;
4885 goto parse_DFS_referrals_exit;
4886 }
4887
4888 ref++;
4889 }
4890
4891parse_DFS_referrals_exit:
4892 if (rc) {
4893 free_dfs_info_array(*target_nodes, *num_of_nodes);
4894 *target_nodes = NULL;
4895 *num_of_nodes = 0;
4896 }
4897 return rc;
4898}
4899
4900int 4789int
4901CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses, 4790CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4902 const char *search_name, struct dfs_info3_param **target_nodes, 4791 const char *search_name, struct dfs_info3_param **target_nodes,
@@ -4993,9 +4882,11 @@ getDFSRetry:
4993 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset)); 4882 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4994 4883
4995 /* parse returned result into more usable form */ 4884 /* parse returned result into more usable form */
4996 rc = parse_DFS_referrals(pSMBr, num_of_nodes, 4885 rc = parse_dfs_referrals(&pSMBr->dfs_data,
4997 target_nodes, nls_codepage, remap, 4886 le16_to_cpu(pSMBr->t2.DataCount),
4998 search_name); 4887 num_of_nodes, target_nodes, nls_codepage,
4888 remap, search_name,
4889 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
4999 4890
5000GetDFSRefExit: 4891GetDFSRefExit:
5001 cifs_buf_release(pSMB); 4892 cifs_buf_release(pSMB);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 3aa457f83214..9ae695ae3ed7 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2074,7 +2074,8 @@ match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2074 * that was specified, or "Unspecified" if that sectype was not 2074 * that was specified, or "Unspecified" if that sectype was not
2075 * compatible with the given NEGOTIATE request. 2075 * compatible with the given NEGOTIATE request.
2076 */ 2076 */
2077 if (select_sectype(server, vol->sectype) == Unspecified) 2077 if (server->ops->select_sectype(server, vol->sectype)
2078 == Unspecified)
2078 return false; 2079 return false;
2079 2080
2080 /* 2081 /*
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 2c227a99f369..56366e984076 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -81,6 +81,17 @@ cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
81char * 81char *
82build_path_from_dentry(struct dentry *direntry) 82build_path_from_dentry(struct dentry *direntry)
83{ 83{
84 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
85 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
86 bool prefix = tcon->Flags & SMB_SHARE_IS_IN_DFS;
87
88 return build_path_from_dentry_optional_prefix(direntry,
89 prefix);
90}
91
92char *
93build_path_from_dentry_optional_prefix(struct dentry *direntry, bool prefix)
94{
84 struct dentry *temp; 95 struct dentry *temp;
85 int namelen; 96 int namelen;
86 int dfsplen; 97 int dfsplen;
@@ -92,7 +103,7 @@ build_path_from_dentry(struct dentry *direntry)
92 unsigned seq; 103 unsigned seq;
93 104
94 dirsep = CIFS_DIR_SEP(cifs_sb); 105 dirsep = CIFS_DIR_SEP(cifs_sb);
95 if (tcon->Flags & SMB_SHARE_IS_IN_DFS) 106 if (prefix)
96 dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1); 107 dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
97 else 108 else
98 dfsplen = 0; 109 dfsplen = 0;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index c6729156f9a0..d3fb11529ed9 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -640,3 +640,108 @@ cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink,
640 cifs_add_pending_open_locked(fid, tlink, open); 640 cifs_add_pending_open_locked(fid, tlink, open);
641 spin_unlock(&tlink_tcon(open->tlink)->open_file_lock); 641 spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
642} 642}
643
644/* parses DFS refferal V3 structure
645 * caller is responsible for freeing target_nodes
646 * returns:
647 * - on success - 0
648 * - on failure - errno
649 */
650int
651parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
652 unsigned int *num_of_nodes,
653 struct dfs_info3_param **target_nodes,
654 const struct nls_table *nls_codepage, int remap,
655 const char *searchName, bool is_unicode)
656{
657 int i, rc = 0;
658 char *data_end;
659 struct dfs_referral_level_3 *ref;
660
661 *num_of_nodes = le16_to_cpu(rsp->NumberOfReferrals);
662
663 if (*num_of_nodes < 1) {
664 cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d\n",
665 *num_of_nodes);
666 rc = -EINVAL;
667 goto parse_DFS_referrals_exit;
668 }
669
670 ref = (struct dfs_referral_level_3 *) &(rsp->referrals);
671 if (ref->VersionNumber != cpu_to_le16(3)) {
672 cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3\n",
673 le16_to_cpu(ref->VersionNumber));
674 rc = -EINVAL;
675 goto parse_DFS_referrals_exit;
676 }
677
678 /* get the upper boundary of the resp buffer */
679 data_end = (char *)rsp + rsp_size;
680
681 cifs_dbg(FYI, "num_referrals: %d dfs flags: 0x%x ...\n",
682 *num_of_nodes, le32_to_cpu(rsp->DFSFlags));
683
684 *target_nodes = kcalloc(*num_of_nodes, sizeof(struct dfs_info3_param),
685 GFP_KERNEL);
686 if (*target_nodes == NULL) {
687 rc = -ENOMEM;
688 goto parse_DFS_referrals_exit;
689 }
690
691 /* collect necessary data from referrals */
692 for (i = 0; i < *num_of_nodes; i++) {
693 char *temp;
694 int max_len;
695 struct dfs_info3_param *node = (*target_nodes)+i;
696
697 node->flags = le32_to_cpu(rsp->DFSFlags);
698 if (is_unicode) {
699 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
700 GFP_KERNEL);
701 if (tmp == NULL) {
702 rc = -ENOMEM;
703 goto parse_DFS_referrals_exit;
704 }
705 cifsConvertToUTF16((__le16 *) tmp, searchName,
706 PATH_MAX, nls_codepage, remap);
707 node->path_consumed = cifs_utf16_bytes(tmp,
708 le16_to_cpu(rsp->PathConsumed),
709 nls_codepage);
710 kfree(tmp);
711 } else
712 node->path_consumed = le16_to_cpu(rsp->PathConsumed);
713
714 node->server_type = le16_to_cpu(ref->ServerType);
715 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
716
717 /* copy DfsPath */
718 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
719 max_len = data_end - temp;
720 node->path_name = cifs_strndup_from_utf16(temp, max_len,
721 is_unicode, nls_codepage);
722 if (!node->path_name) {
723 rc = -ENOMEM;
724 goto parse_DFS_referrals_exit;
725 }
726
727 /* copy link target UNC */
728 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
729 max_len = data_end - temp;
730 node->node_name = cifs_strndup_from_utf16(temp, max_len,
731 is_unicode, nls_codepage);
732 if (!node->node_name) {
733 rc = -ENOMEM;
734 goto parse_DFS_referrals_exit;
735 }
736
737 ref++;
738 }
739
740parse_DFS_referrals_exit:
741 if (rc) {
742 free_dfs_info_array(*target_nodes, *num_of_nodes);
743 *target_nodes = NULL;
744 *num_of_nodes = 0;
745 }
746 return rc;
747}
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index dcbcc927399a..8b0502cd39af 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -498,7 +498,7 @@ setup_ntlmv2_ret:
498} 498}
499 499
500enum securityEnum 500enum securityEnum
501select_sectype(struct TCP_Server_Info *server, enum securityEnum requested) 501cifs_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
502{ 502{
503 switch (server->negflavor) { 503 switch (server->negflavor) {
504 case CIFS_NEGFLAVOR_EXTENDED: 504 case CIFS_NEGFLAVOR_EXTENDED:
@@ -1391,7 +1391,7 @@ static int select_sec(struct cifs_ses *ses, struct sess_data *sess_data)
1391{ 1391{
1392 int type; 1392 int type;
1393 1393
1394 type = select_sectype(ses->server, ses->sectype); 1394 type = cifs_select_sectype(ses->server, ses->sectype);
1395 cifs_dbg(FYI, "sess setup type %d\n", type); 1395 cifs_dbg(FYI, "sess setup type %d\n", type);
1396 if (type == Unspecified) { 1396 if (type == Unspecified) {
1397 cifs_dbg(VFS, 1397 cifs_dbg(VFS,
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 67a987e4d026..cc93ba4da9b5 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -1087,6 +1087,7 @@ struct smb_version_operations smb1_operations = {
1087 .is_read_op = cifs_is_read_op, 1087 .is_read_op = cifs_is_read_op,
1088 .wp_retry_size = cifs_wp_retry_size, 1088 .wp_retry_size = cifs_wp_retry_size,
1089 .dir_needs_close = cifs_dir_needs_close, 1089 .dir_needs_close = cifs_dir_needs_close,
1090 .select_sectype = cifs_select_sectype,
1090#ifdef CONFIG_CIFS_XATTR 1091#ifdef CONFIG_CIFS_XATTR
1091 .query_all_EAs = CIFSSMBQAllEAs, 1092 .query_all_EAs = CIFSSMBQAllEAs,
1092 .set_EA = CIFSSMBSetEA, 1093 .set_EA = CIFSSMBSetEA,
diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c
index b2aff0c6f22c..b4b1f0305f29 100644
--- a/fs/cifs/smb2file.c
+++ b/fs/cifs/smb2file.c
@@ -73,7 +73,8 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
73 nr_ioctl_req.Timeout = 0; /* use server default (120 seconds) */ 73 nr_ioctl_req.Timeout = 0; /* use server default (120 seconds) */
74 nr_ioctl_req.Reserved = 0; 74 nr_ioctl_req.Reserved = 0;
75 rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid, 75 rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid,
76 fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY, true, 76 fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY,
77 true /* is_fsctl */, false /* use_ipc */,
77 (char *)&nr_ioctl_req, sizeof(nr_ioctl_req), 78 (char *)&nr_ioctl_req, sizeof(nr_ioctl_req),
78 NULL, NULL /* no return info */); 79 NULL, NULL /* no return info */);
79 if (rc == -EOPNOTSUPP) { 80 if (rc == -EOPNOTSUPP) {
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index a44b4dbe4aae..0231108d9387 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -282,6 +282,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
282 282
283 rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, 283 rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
284 FSCTL_QUERY_NETWORK_INTERFACE_INFO, true /* is_fsctl */, 284 FSCTL_QUERY_NETWORK_INTERFACE_INFO, true /* is_fsctl */,
285 false /* use_ipc */,
285 NULL /* no data input */, 0 /* no data input */, 286 NULL /* no data input */, 0 /* no data input */,
286 (char **)&out_buf, &ret_data_len); 287 (char **)&out_buf, &ret_data_len);
287 if (rc != 0) 288 if (rc != 0)
@@ -571,6 +572,7 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
571 572
572 rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid, 573 rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
573 FSCTL_SRV_REQUEST_RESUME_KEY, true /* is_fsctl */, 574 FSCTL_SRV_REQUEST_RESUME_KEY, true /* is_fsctl */,
575 false /* use_ipc */,
574 NULL, 0 /* no input */, 576 NULL, 0 /* no input */,
575 (char **)&res_key, &ret_data_len); 577 (char **)&res_key, &ret_data_len);
576 578
@@ -635,7 +637,8 @@ smb2_clone_range(const unsigned int xid,
635 /* Request server copy to target from src identified by key */ 637 /* Request server copy to target from src identified by key */
636 rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid, 638 rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
637 trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE, 639 trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE,
638 true /* is_fsctl */, (char *)pcchunk, 640 true /* is_fsctl */, false /* use_ipc */,
641 (char *)pcchunk,
639 sizeof(struct copychunk_ioctl), (char **)&retbuf, 642 sizeof(struct copychunk_ioctl), (char **)&retbuf,
640 &ret_data_len); 643 &ret_data_len);
641 if (rc == 0) { 644 if (rc == 0) {
@@ -787,7 +790,8 @@ static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
787 790
788 rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, 791 rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
789 cfile->fid.volatile_fid, FSCTL_SET_SPARSE, 792 cfile->fid.volatile_fid, FSCTL_SET_SPARSE,
790 true /* is_fctl */, &setsparse, 1, NULL, NULL); 793 true /* is_fctl */, false /* use_ipc */,
794 &setsparse, 1, NULL, NULL);
791 if (rc) { 795 if (rc) {
792 tcon->broken_sparse_sup = true; 796 tcon->broken_sparse_sup = true;
793 cifs_dbg(FYI, "set sparse rc = %d\n", rc); 797 cifs_dbg(FYI, "set sparse rc = %d\n", rc);
@@ -857,7 +861,8 @@ smb2_duplicate_extents(const unsigned int xid,
857 rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid, 861 rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
858 trgtfile->fid.volatile_fid, 862 trgtfile->fid.volatile_fid,
859 FSCTL_DUPLICATE_EXTENTS_TO_FILE, 863 FSCTL_DUPLICATE_EXTENTS_TO_FILE,
860 true /* is_fsctl */, (char *)&dup_ext_buf, 864 true /* is_fsctl */, false /* use_ipc */,
865 (char *)&dup_ext_buf,
861 sizeof(struct duplicate_extents_to_file), 866 sizeof(struct duplicate_extents_to_file),
862 NULL, 867 NULL,
863 &ret_data_len); 868 &ret_data_len);
@@ -891,7 +896,8 @@ smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
891 return SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, 896 return SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
892 cfile->fid.volatile_fid, 897 cfile->fid.volatile_fid,
893 FSCTL_SET_INTEGRITY_INFORMATION, 898 FSCTL_SET_INTEGRITY_INFORMATION,
894 true /* is_fsctl */, (char *)&integr_info, 899 true /* is_fsctl */, false /* use_ipc */,
900 (char *)&integr_info,
895 sizeof(struct fsctl_set_integrity_information_req), 901 sizeof(struct fsctl_set_integrity_information_req),
896 NULL, 902 NULL,
897 &ret_data_len); 903 &ret_data_len);
@@ -910,7 +916,8 @@ smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
910 rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, 916 rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
911 cfile->fid.volatile_fid, 917 cfile->fid.volatile_fid,
912 FSCTL_SRV_ENUMERATE_SNAPSHOTS, 918 FSCTL_SRV_ENUMERATE_SNAPSHOTS,
913 true /* is_fsctl */, NULL, 0 /* no input data */, 919 true /* is_fsctl */, false /* use_ipc */,
920 NULL, 0 /* no input data */,
914 (char **)&retbuf, 921 (char **)&retbuf,
915 &ret_data_len); 922 &ret_data_len);
916 cifs_dbg(FYI, "enum snaphots ioctl returned %d and ret buflen is %d\n", 923 cifs_dbg(FYI, "enum snaphots ioctl returned %d and ret buflen is %d\n",
@@ -1097,6 +1104,103 @@ smb2_new_lease_key(struct cifs_fid *fid)
1097 generate_random_uuid(fid->lease_key); 1104 generate_random_uuid(fid->lease_key);
1098} 1105}
1099 1106
1107static int
1108smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
1109 const char *search_name,
1110 struct dfs_info3_param **target_nodes,
1111 unsigned int *num_of_nodes,
1112 const struct nls_table *nls_codepage, int remap)
1113{
1114 int rc;
1115 __le16 *utf16_path = NULL;
1116 int utf16_path_len = 0;
1117 struct cifs_tcon *tcon;
1118 struct fsctl_get_dfs_referral_req *dfs_req = NULL;
1119 struct get_dfs_referral_rsp *dfs_rsp = NULL;
1120 u32 dfs_req_size = 0, dfs_rsp_size = 0;
1121
1122 cifs_dbg(FYI, "smb2_get_dfs_refer path <%s>\n", search_name);
1123
1124 /*
1125 * Use any tcon from the current session. Here, the first one.
1126 */
1127 spin_lock(&cifs_tcp_ses_lock);
1128 tcon = list_first_entry_or_null(&ses->tcon_list, struct cifs_tcon,
1129 tcon_list);
1130 if (tcon)
1131 tcon->tc_count++;
1132 spin_unlock(&cifs_tcp_ses_lock);
1133
1134 if (!tcon) {
1135 cifs_dbg(VFS, "session %p has no tcon available for a dfs referral request\n",
1136 ses);
1137 rc = -ENOTCONN;
1138 goto out;
1139 }
1140
1141 utf16_path = cifs_strndup_to_utf16(search_name, PATH_MAX,
1142 &utf16_path_len,
1143 nls_codepage, remap);
1144 if (!utf16_path) {
1145 rc = -ENOMEM;
1146 goto out;
1147 }
1148
1149 dfs_req_size = sizeof(*dfs_req) + utf16_path_len;
1150 dfs_req = kzalloc(dfs_req_size, GFP_KERNEL);
1151 if (!dfs_req) {
1152 rc = -ENOMEM;
1153 goto out;
1154 }
1155
1156 /* Highest DFS referral version understood */
1157 dfs_req->MaxReferralLevel = DFS_VERSION;
1158
1159 /* Path to resolve in an UTF-16 null-terminated string */
1160 memcpy(dfs_req->RequestFileName, utf16_path, utf16_path_len);
1161
1162 do {
1163 /* try first with IPC */
1164 rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
1165 FSCTL_DFS_GET_REFERRALS,
1166 true /* is_fsctl */, true /* use_ipc */,
1167 (char *)dfs_req, dfs_req_size,
1168 (char **)&dfs_rsp, &dfs_rsp_size);
1169 if (rc == -ENOTCONN) {
1170 /* try with normal tcon */
1171 rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
1172 FSCTL_DFS_GET_REFERRALS,
1173 true /* is_fsctl */, false /*use_ipc*/,
1174 (char *)dfs_req, dfs_req_size,
1175 (char **)&dfs_rsp, &dfs_rsp_size);
1176 }
1177 } while (rc == -EAGAIN);
1178
1179 if (rc) {
1180 cifs_dbg(VFS, "ioctl error in smb2_get_dfs_refer rc=%d\n", rc);
1181 goto out;
1182 }
1183
1184 rc = parse_dfs_referrals(dfs_rsp, dfs_rsp_size,
1185 num_of_nodes, target_nodes,
1186 nls_codepage, remap, search_name,
1187 true /* is_unicode */);
1188 if (rc) {
1189 cifs_dbg(VFS, "parse error in smb2_get_dfs_refer rc=%d\n", rc);
1190 goto out;
1191 }
1192
1193 out:
1194 if (tcon) {
1195 spin_lock(&cifs_tcp_ses_lock);
1196 tcon->tc_count--;
1197 spin_unlock(&cifs_tcp_ses_lock);
1198 }
1199 kfree(utf16_path);
1200 kfree(dfs_req);
1201 kfree(dfs_rsp);
1202 return rc;
1203}
1100#define SMB2_SYMLINK_STRUCT_SIZE \ 1204#define SMB2_SYMLINK_STRUCT_SIZE \
1101 (sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp)) 1205 (sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp))
1102 1206
@@ -1220,7 +1324,8 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
1220 1324
1221 rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, 1325 rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
1222 cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA, 1326 cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
1223 true /* is_fctl */, (char *)&fsctl_buf, 1327 true /* is_fctl */, false /* use_ipc */,
1328 (char *)&fsctl_buf,
1224 sizeof(struct file_zero_data_information), NULL, NULL); 1329 sizeof(struct file_zero_data_information), NULL, NULL);
1225 free_xid(xid); 1330 free_xid(xid);
1226 return rc; 1331 return rc;
@@ -1254,7 +1359,8 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
1254 1359
1255 rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, 1360 rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
1256 cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA, 1361 cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
1257 true /* is_fctl */, (char *)&fsctl_buf, 1362 true /* is_fctl */, false /* use_ipc */,
1363 (char *)&fsctl_buf,
1258 sizeof(struct file_zero_data_information), NULL, NULL); 1364 sizeof(struct file_zero_data_information), NULL, NULL);
1259 free_xid(xid); 1365 free_xid(xid);
1260 return rc; 1366 return rc;
@@ -1609,6 +1715,26 @@ static void cifs_crypt_complete(struct crypto_async_request *req, int err)
1609 complete(&res->completion); 1715 complete(&res->completion);
1610} 1716}
1611 1717
1718static int
1719smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
1720{
1721 struct cifs_ses *ses;
1722 u8 *ses_enc_key;
1723
1724 spin_lock(&cifs_tcp_ses_lock);
1725 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
1726 if (ses->Suid != ses_id)
1727 continue;
1728 ses_enc_key = enc ? ses->smb3encryptionkey :
1729 ses->smb3decryptionkey;
1730 memcpy(key, ses_enc_key, SMB3_SIGN_KEY_SIZE);
1731 spin_unlock(&cifs_tcp_ses_lock);
1732 return 0;
1733 }
1734 spin_unlock(&cifs_tcp_ses_lock);
1735
1736 return 1;
1737}
1612/* 1738/*
1613 * Encrypt or decrypt @rqst message. @rqst has the following format: 1739 * Encrypt or decrypt @rqst message. @rqst has the following format:
1614 * iov[0] - transform header (associate data), 1740 * iov[0] - transform header (associate data),
@@ -1622,10 +1748,10 @@ crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
1622 struct smb2_transform_hdr *tr_hdr = 1748 struct smb2_transform_hdr *tr_hdr =
1623 (struct smb2_transform_hdr *)rqst->rq_iov[0].iov_base; 1749 (struct smb2_transform_hdr *)rqst->rq_iov[0].iov_base;
1624 unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24; 1750 unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24;
1625 struct cifs_ses *ses;
1626 int rc = 0; 1751 int rc = 0;
1627 struct scatterlist *sg; 1752 struct scatterlist *sg;
1628 u8 sign[SMB2_SIGNATURE_SIZE] = {}; 1753 u8 sign[SMB2_SIGNATURE_SIZE] = {};
1754 u8 key[SMB3_SIGN_KEY_SIZE];
1629 struct aead_request *req; 1755 struct aead_request *req;
1630 char *iv; 1756 char *iv;
1631 unsigned int iv_len; 1757 unsigned int iv_len;
@@ -1635,9 +1761,10 @@ crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
1635 1761
1636 init_completion(&result.completion); 1762 init_completion(&result.completion);
1637 1763
1638 ses = smb2_find_smb_ses(server, tr_hdr->SessionId); 1764 rc = smb2_get_enc_key(server, tr_hdr->SessionId, enc, key);
1639 if (!ses) { 1765 if (rc) {
1640 cifs_dbg(VFS, "%s: Could not find session\n", __func__); 1766 cifs_dbg(VFS, "%s: Could not get %scryption key\n", __func__,
1767 enc ? "en" : "de");
1641 return 0; 1768 return 0;
1642 } 1769 }
1643 1770
@@ -1649,8 +1776,7 @@ crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
1649 1776
1650 tfm = enc ? server->secmech.ccmaesencrypt : 1777 tfm = enc ? server->secmech.ccmaesencrypt :
1651 server->secmech.ccmaesdecrypt; 1778 server->secmech.ccmaesdecrypt;
1652 rc = crypto_aead_setkey(tfm, enc ? ses->smb3encryptionkey : 1779 rc = crypto_aead_setkey(tfm, key, SMB3_SIGN_KEY_SIZE);
1653 ses->smb3decryptionkey, SMB3_SIGN_KEY_SIZE);
1654 if (rc) { 1780 if (rc) {
1655 cifs_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc); 1781 cifs_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc);
1656 return rc; 1782 return rc;
@@ -2254,6 +2380,8 @@ struct smb_version_operations smb20_operations = {
2254 .clone_range = smb2_clone_range, 2380 .clone_range = smb2_clone_range,
2255 .wp_retry_size = smb2_wp_retry_size, 2381 .wp_retry_size = smb2_wp_retry_size,
2256 .dir_needs_close = smb2_dir_needs_close, 2382 .dir_needs_close = smb2_dir_needs_close,
2383 .get_dfs_refer = smb2_get_dfs_refer,
2384 .select_sectype = smb2_select_sectype,
2257}; 2385};
2258 2386
2259struct smb_version_operations smb21_operations = { 2387struct smb_version_operations smb21_operations = {
@@ -2335,6 +2463,8 @@ struct smb_version_operations smb21_operations = {
2335 .wp_retry_size = smb2_wp_retry_size, 2463 .wp_retry_size = smb2_wp_retry_size,
2336 .dir_needs_close = smb2_dir_needs_close, 2464 .dir_needs_close = smb2_dir_needs_close,
2337 .enum_snapshots = smb3_enum_snapshots, 2465 .enum_snapshots = smb3_enum_snapshots,
2466 .get_dfs_refer = smb2_get_dfs_refer,
2467 .select_sectype = smb2_select_sectype,
2338}; 2468};
2339 2469
2340struct smb_version_operations smb30_operations = { 2470struct smb_version_operations smb30_operations = {
@@ -2426,6 +2556,8 @@ struct smb_version_operations smb30_operations = {
2426 .free_transform_rq = smb3_free_transform_rq, 2556 .free_transform_rq = smb3_free_transform_rq,
2427 .is_transform_hdr = smb3_is_transform_hdr, 2557 .is_transform_hdr = smb3_is_transform_hdr,
2428 .receive_transform = smb3_receive_transform, 2558 .receive_transform = smb3_receive_transform,
2559 .get_dfs_refer = smb2_get_dfs_refer,
2560 .select_sectype = smb2_select_sectype,
2429}; 2561};
2430 2562
2431#ifdef CONFIG_CIFS_SMB311 2563#ifdef CONFIG_CIFS_SMB311
@@ -2518,6 +2650,8 @@ struct smb_version_operations smb311_operations = {
2518 .free_transform_rq = smb3_free_transform_rq, 2650 .free_transform_rq = smb3_free_transform_rq,
2519 .is_transform_hdr = smb3_is_transform_hdr, 2651 .is_transform_hdr = smb3_is_transform_hdr,
2520 .receive_transform = smb3_receive_transform, 2652 .receive_transform = smb3_receive_transform,
2653 .get_dfs_refer = smb2_get_dfs_refer,
2654 .select_sectype = smb2_select_sectype,
2521}; 2655};
2522#endif /* CIFS_SMB311 */ 2656#endif /* CIFS_SMB311 */
2523 2657
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index ad83b3db2840..7446496850a3 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -620,6 +620,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
620 620
621 rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, 621 rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
622 FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */, 622 FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */,
623 false /* use_ipc */,
623 (char *)&vneg_inbuf, sizeof(struct validate_negotiate_info_req), 624 (char *)&vneg_inbuf, sizeof(struct validate_negotiate_info_req),
624 (char **)&pneg_rsp, &rsplen); 625 (char **)&pneg_rsp, &rsplen);
625 626
@@ -656,6 +657,28 @@ vneg_out:
656 return -EIO; 657 return -EIO;
657} 658}
658 659
660enum securityEnum
661smb2_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
662{
663 switch (requested) {
664 case Kerberos:
665 case RawNTLMSSP:
666 return requested;
667 case NTLMv2:
668 return RawNTLMSSP;
669 case Unspecified:
670 if (server->sec_ntlmssp &&
671 (global_secflags & CIFSSEC_MAY_NTLMSSP))
672 return RawNTLMSSP;
673 if ((server->sec_kerberos || server->sec_mskerberos) &&
674 (global_secflags & CIFSSEC_MAY_KRB5))
675 return Kerberos;
676 /* Fallthrough */
677 default:
678 return Unspecified;
679 }
680}
681
659struct SMB2_sess_data { 682struct SMB2_sess_data {
660 unsigned int xid; 683 unsigned int xid;
661 struct cifs_ses *ses; 684 struct cifs_ses *ses;
@@ -1008,10 +1031,17 @@ out:
1008static int 1031static int
1009SMB2_select_sec(struct cifs_ses *ses, struct SMB2_sess_data *sess_data) 1032SMB2_select_sec(struct cifs_ses *ses, struct SMB2_sess_data *sess_data)
1010{ 1033{
1011 if (ses->sectype != Kerberos && ses->sectype != RawNTLMSSP) 1034 int type;
1012 ses->sectype = RawNTLMSSP; 1035
1036 type = smb2_select_sectype(ses->server, ses->sectype);
1037 cifs_dbg(FYI, "sess setup type %d\n", type);
1038 if (type == Unspecified) {
1039 cifs_dbg(VFS,
1040 "Unable to select appropriate authentication method!");
1041 return -EINVAL;
1042 }
1013 1043
1014 switch (ses->sectype) { 1044 switch (type) {
1015 case Kerberos: 1045 case Kerberos:
1016 sess_data->func = SMB2_auth_kerberos; 1046 sess_data->func = SMB2_auth_kerberos;
1017 break; 1047 break;
@@ -1019,7 +1049,7 @@ SMB2_select_sec(struct cifs_ses *ses, struct SMB2_sess_data *sess_data)
1019 sess_data->func = SMB2_sess_auth_rawntlmssp_negotiate; 1049 sess_data->func = SMB2_sess_auth_rawntlmssp_negotiate;
1020 break; 1050 break;
1021 default: 1051 default:
1022 cifs_dbg(VFS, "secType %d not supported!\n", ses->sectype); 1052 cifs_dbg(VFS, "secType %d not supported!\n", type);
1023 return -EOPNOTSUPP; 1053 return -EOPNOTSUPP;
1024 } 1054 }
1025 1055
@@ -1167,8 +1197,8 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
1167 1197
1168 /* since no tcon, smb2_init can not do this, so do here */ 1198 /* since no tcon, smb2_init can not do this, so do here */
1169 req->hdr.sync_hdr.SessionId = ses->Suid; 1199 req->hdr.sync_hdr.SessionId = ses->Suid;
1170 /* if (ses->server->sec_mode & SECMODE_SIGN_REQUIRED) 1200 if (ses->server->sign)
1171 req->hdr.Flags |= SMB2_FLAGS_SIGNED; */ 1201 req->hdr.sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
1172 } else if (encryption_required(tcon)) 1202 } else if (encryption_required(tcon))
1173 flags |= CIFS_TRANSFORM_REQ; 1203 flags |= CIFS_TRANSFORM_REQ;
1174 1204
@@ -1527,6 +1557,51 @@ add_durable_context(struct kvec *iov, unsigned int *num_iovec,
1527 return 0; 1557 return 0;
1528} 1558}
1529 1559
1560static int
1561alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
1562 const char *treename, const __le16 *path)
1563{
1564 int treename_len, path_len;
1565 struct nls_table *cp;
1566 const __le16 sep[] = {cpu_to_le16('\\'), cpu_to_le16(0x0000)};
1567
1568 /*
1569 * skip leading "\\"
1570 */
1571 treename_len = strlen(treename);
1572 if (treename_len < 2 || !(treename[0] == '\\' && treename[1] == '\\'))
1573 return -EINVAL;
1574
1575 treename += 2;
1576 treename_len -= 2;
1577
1578 path_len = UniStrnlen((wchar_t *)path, PATH_MAX);
1579
1580 /*
1581 * make room for one path separator between the treename and
1582 * path
1583 */
1584 *out_len = treename_len + 1 + path_len;
1585
1586 /*
1587 * final path needs to be null-terminated UTF16 with a
1588 * size aligned to 8
1589 */
1590
1591 *out_size = roundup((*out_len+1)*2, 8);
1592 *out_path = kzalloc(*out_size, GFP_KERNEL);
1593 if (!*out_path)
1594 return -ENOMEM;
1595
1596 cp = load_nls_default();
1597 cifs_strtoUTF16(*out_path, treename, treename_len, cp);
1598 UniStrcat(*out_path, sep);
1599 UniStrcat(*out_path, path);
1600 unload_nls(cp);
1601
1602 return 0;
1603}
1604
1530int 1605int
1531SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, 1606SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
1532 __u8 *oplock, struct smb2_file_all_info *buf, 1607 __u8 *oplock, struct smb2_file_all_info *buf,
@@ -1575,30 +1650,49 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
1575 req->ShareAccess = FILE_SHARE_ALL_LE; 1650 req->ShareAccess = FILE_SHARE_ALL_LE;
1576 req->CreateDisposition = cpu_to_le32(oparms->disposition); 1651 req->CreateDisposition = cpu_to_le32(oparms->disposition);
1577 req->CreateOptions = cpu_to_le32(oparms->create_options & CREATE_OPTIONS_MASK); 1652 req->CreateOptions = cpu_to_le32(oparms->create_options & CREATE_OPTIONS_MASK);
1578 uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2;
1579 /* do not count rfc1001 len field */
1580 req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req) - 4);
1581 1653
1582 iov[0].iov_base = (char *)req; 1654 iov[0].iov_base = (char *)req;
1583 /* 4 for rfc1002 length field */ 1655 /* 4 for rfc1002 length field */
1584 iov[0].iov_len = get_rfc1002_length(req) + 4; 1656 iov[0].iov_len = get_rfc1002_length(req) + 4;
1585
1586 /* MUST set path len (NameLength) to 0 opening root of share */
1587 req->NameLength = cpu_to_le16(uni_path_len - 2);
1588 /* -1 since last byte is buf[0] which is sent below (path) */ 1657 /* -1 since last byte is buf[0] which is sent below (path) */
1589 iov[0].iov_len--; 1658 iov[0].iov_len--;
1590 if (uni_path_len % 8 != 0) { 1659
1591 copy_size = uni_path_len / 8 * 8; 1660 req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req) - 4);
1592 if (copy_size < uni_path_len) 1661
1593 copy_size += 8; 1662 /* [MS-SMB2] 2.2.13 NameOffset:
1594 1663 * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of
1595 copy_path = kzalloc(copy_size, GFP_KERNEL); 1664 * the SMB2 header, the file name includes a prefix that will
1596 if (!copy_path) 1665 * be processed during DFS name normalization as specified in
1597 return -ENOMEM; 1666 * section 3.3.5.9. Otherwise, the file name is relative to
1598 memcpy((char *)copy_path, (const char *)path, 1667 * the share that is identified by the TreeId in the SMB2
1599 uni_path_len); 1668 * header.
1669 */
1670 if (tcon->share_flags & SHI1005_FLAGS_DFS) {
1671 int name_len;
1672
1673 req->hdr.sync_hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS;
1674 rc = alloc_path_with_tree_prefix(&copy_path, &copy_size,
1675 &name_len,
1676 tcon->treeName, path);
1677 if (rc)
1678 return rc;
1679 req->NameLength = cpu_to_le16(name_len * 2);
1600 uni_path_len = copy_size; 1680 uni_path_len = copy_size;
1601 path = copy_path; 1681 path = copy_path;
1682 } else {
1683 uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2;
1684 /* MUST set path len (NameLength) to 0 opening root of share */
1685 req->NameLength = cpu_to_le16(uni_path_len - 2);
1686 if (uni_path_len % 8 != 0) {
1687 copy_size = roundup(uni_path_len, 8);
1688 copy_path = kzalloc(copy_size, GFP_KERNEL);
1689 if (!copy_path)
1690 return -ENOMEM;
1691 memcpy((char *)copy_path, (const char *)path,
1692 uni_path_len);
1693 uni_path_len = copy_size;
1694 path = copy_path;
1695 }
1602 } 1696 }
1603 1697
1604 iov[1].iov_len = uni_path_len; 1698 iov[1].iov_len = uni_path_len;
@@ -1683,8 +1777,9 @@ creat_exit:
1683 */ 1777 */
1684int 1778int
1685SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, 1779SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
1686 u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data, 1780 u64 volatile_fid, u32 opcode, bool is_fsctl, bool use_ipc,
1687 u32 indatalen, char **out_data, u32 *plen /* returned data len */) 1781 char *in_data, u32 indatalen,
1782 char **out_data, u32 *plen /* returned data len */)
1688{ 1783{
1689 struct smb2_ioctl_req *req; 1784 struct smb2_ioctl_req *req;
1690 struct smb2_ioctl_rsp *rsp; 1785 struct smb2_ioctl_rsp *rsp;
@@ -1721,6 +1816,16 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
1721 if (rc) 1816 if (rc)
1722 return rc; 1817 return rc;
1723 1818
1819 if (use_ipc) {
1820 if (ses->ipc_tid == 0) {
1821 cifs_small_buf_release(req);
1822 return -ENOTCONN;
1823 }
1824
1825 cifs_dbg(FYI, "replacing tid 0x%x with IPC tid 0x%x\n",
1826 req->hdr.sync_hdr.TreeId, ses->ipc_tid);
1827 req->hdr.sync_hdr.TreeId = ses->ipc_tid;
1828 }
1724 if (encryption_required(tcon)) 1829 if (encryption_required(tcon))
1725 flags |= CIFS_TRANSFORM_REQ; 1830 flags |= CIFS_TRANSFORM_REQ;
1726 1831
@@ -1843,6 +1948,7 @@ SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
1843 1948
1844 rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid, 1949 rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
1845 FSCTL_SET_COMPRESSION, true /* is_fsctl */, 1950 FSCTL_SET_COMPRESSION, true /* is_fsctl */,
1951 false /* use_ipc */,
1846 (char *)&fsctl_input /* data input */, 1952 (char *)&fsctl_input /* data input */,
1847 2 /* in data len */, &ret_data /* out data */, NULL); 1953 2 /* in data len */, &ret_data /* out data */, NULL);
1848 1954
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index c03b252501a1..18700fd25a0b 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -695,6 +695,14 @@ struct fsctl_get_integrity_information_rsp {
695/* Integrity flags for above */ 695/* Integrity flags for above */
696#define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF 0x00000001 696#define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF 0x00000001
697 697
698/* See MS-DFSC 2.2.2 */
699struct fsctl_get_dfs_referral_req {
700 __le16 MaxReferralLevel;
701 __u8 RequestFileName[];
702} __packed;
703
704/* DFS response is struct get_dfs_refer_rsp */
705
698/* See MS-SMB2 2.2.31.3 */ 706/* See MS-SMB2 2.2.31.3 */
699struct network_resiliency_req { 707struct network_resiliency_req {
700 __le32 Timeout; 708 __le32 Timeout;
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 85fc7a789334..69e35873b1de 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -121,7 +121,8 @@ extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
121 struct smb2_err_rsp **err_buf); 121 struct smb2_err_rsp **err_buf);
122extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, 122extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
123 u64 persistent_fid, u64 volatile_fid, u32 opcode, 123 u64 persistent_fid, u64 volatile_fid, u32 opcode,
124 bool is_fsctl, char *in_data, u32 indatalen, 124 bool is_fsctl, bool use_ipc,
125 char *in_data, u32 indatalen,
125 char **out_data, u32 *plen /* returned data len */); 126 char **out_data, u32 *plen /* returned data len */);
126extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, 127extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
127 u64 persistent_file_id, u64 volatile_file_id); 128 u64 persistent_file_id, u64 volatile_file_id);
@@ -180,4 +181,6 @@ extern int SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
180 __u8 *lease_key, const __le32 lease_state); 181 __u8 *lease_key, const __le32 lease_state);
181extern int smb3_validate_negotiate(const unsigned int, struct cifs_tcon *); 182extern int smb3_validate_negotiate(const unsigned int, struct cifs_tcon *);
182 183
184extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *,
185 enum securityEnum);
183#endif /* _SMB2PROTO_H */ 186#endif /* _SMB2PROTO_H */