diff options
| -rw-r--r-- | fs/cifs/connect.c | 41 | ||||
| -rw-r--r-- | fs/cifs/smb2pdu.c | 33 |
2 files changed, 43 insertions, 31 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 325e3cb17c4c..777ad9f4fc3c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -2630,12 +2630,18 @@ get_ses_fail: | |||
| 2630 | return ERR_PTR(rc); | 2630 | return ERR_PTR(rc); |
| 2631 | } | 2631 | } |
| 2632 | 2632 | ||
| 2633 | static int match_tcon(struct cifs_tcon *tcon, const char *unc) | 2633 | static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info) |
| 2634 | { | 2634 | { |
| 2635 | if (tcon->tidStatus == CifsExiting) | 2635 | if (tcon->tidStatus == CifsExiting) |
| 2636 | return 0; | 2636 | return 0; |
| 2637 | if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE)) | 2637 | if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE)) |
| 2638 | return 0; | 2638 | return 0; |
| 2639 | if (tcon->seal != volume_info->seal) | ||
| 2640 | return 0; | ||
| 2641 | #ifdef CONFIG_CIFS_SMB2 | ||
| 2642 | if (tcon->snapshot_time != volume_info->snapshot_time) | ||
| 2643 | return 0; | ||
| 2644 | #endif /* CONFIG_CIFS_SMB2 */ | ||
| 2639 | return 1; | 2645 | return 1; |
| 2640 | } | 2646 | } |
| 2641 | 2647 | ||
| @@ -2648,14 +2654,8 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
| 2648 | spin_lock(&cifs_tcp_ses_lock); | 2654 | spin_lock(&cifs_tcp_ses_lock); |
| 2649 | list_for_each(tmp, &ses->tcon_list) { | 2655 | list_for_each(tmp, &ses->tcon_list) { |
| 2650 | tcon = list_entry(tmp, struct cifs_tcon, tcon_list); | 2656 | tcon = list_entry(tmp, struct cifs_tcon, tcon_list); |
| 2651 | if (!match_tcon(tcon, volume_info->UNC)) | 2657 | if (!match_tcon(tcon, volume_info)) |
| 2652 | continue; | ||
| 2653 | |||
| 2654 | #ifdef CONFIG_CIFS_SMB2 | ||
| 2655 | if (tcon->snapshot_time != volume_info->snapshot_time) | ||
| 2656 | continue; | 2658 | continue; |
| 2657 | #endif /* CONFIG_CIFS_SMB2 */ | ||
| 2658 | |||
| 2659 | ++tcon->tc_count; | 2659 | ++tcon->tc_count; |
| 2660 | spin_unlock(&cifs_tcp_ses_lock); | 2660 | spin_unlock(&cifs_tcp_ses_lock); |
| 2661 | return tcon; | 2661 | return tcon; |
| @@ -2701,8 +2701,6 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
| 2701 | cifs_dbg(FYI, "Found match on UNC path\n"); | 2701 | cifs_dbg(FYI, "Found match on UNC path\n"); |
| 2702 | /* existing tcon already has a reference */ | 2702 | /* existing tcon already has a reference */ |
| 2703 | cifs_put_smb_ses(ses); | 2703 | cifs_put_smb_ses(ses); |
| 2704 | if (tcon->seal != volume_info->seal) | ||
| 2705 | cifs_dbg(VFS, "transport encryption setting conflicts with existing tid\n"); | ||
| 2706 | return tcon; | 2704 | return tcon; |
| 2707 | } | 2705 | } |
| 2708 | 2706 | ||
| @@ -2758,7 +2756,6 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
| 2758 | tcon->Flags &= ~SMB_SHARE_IS_IN_DFS; | 2756 | tcon->Flags &= ~SMB_SHARE_IS_IN_DFS; |
| 2759 | cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags); | 2757 | cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags); |
| 2760 | } | 2758 | } |
| 2761 | tcon->seal = volume_info->seal; | ||
| 2762 | tcon->use_persistent = false; | 2759 | tcon->use_persistent = false; |
| 2763 | /* check if SMB2 or later, CIFS does not support persistent handles */ | 2760 | /* check if SMB2 or later, CIFS does not support persistent handles */ |
| 2764 | if (volume_info->persistent) { | 2761 | if (volume_info->persistent) { |
| @@ -2795,6 +2792,24 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
| 2795 | tcon->use_resilient = true; | 2792 | tcon->use_resilient = true; |
| 2796 | } | 2793 | } |
| 2797 | 2794 | ||
| 2795 | if (volume_info->seal) { | ||
| 2796 | if (ses->server->vals->protocol_id == 0) { | ||
| 2797 | cifs_dbg(VFS, | ||
| 2798 | "SMB3 or later required for encryption\n"); | ||
| 2799 | rc = -EOPNOTSUPP; | ||
| 2800 | goto out_fail; | ||
| 2801 | #ifdef CONFIG_CIFS_SMB2 | ||
| 2802 | } else if (tcon->ses->server->capabilities & | ||
| 2803 | SMB2_GLOBAL_CAP_ENCRYPTION) | ||
| 2804 | tcon->seal = true; | ||
| 2805 | else { | ||
| 2806 | cifs_dbg(VFS, "Encryption is not supported on share\n"); | ||
| 2807 | rc = -EOPNOTSUPP; | ||
| 2808 | goto out_fail; | ||
| 2809 | #endif /* CONFIG_CIFS_SMB2 */ | ||
| 2810 | } | ||
| 2811 | } | ||
| 2812 | |||
| 2798 | /* | 2813 | /* |
| 2799 | * We can have only one retry value for a connection to a share so for | 2814 | * We can have only one retry value for a connection to a share so for |
| 2800 | * resources mounted more than once to the same server share the last | 2815 | * resources mounted more than once to the same server share the last |
| @@ -2926,7 +2941,7 @@ cifs_match_super(struct super_block *sb, void *data) | |||
| 2926 | 2941 | ||
| 2927 | if (!match_server(tcp_srv, volume_info) || | 2942 | if (!match_server(tcp_srv, volume_info) || |
| 2928 | !match_session(ses, volume_info) || | 2943 | !match_session(ses, volume_info) || |
| 2929 | !match_tcon(tcon, volume_info->UNC) || | 2944 | !match_tcon(tcon, volume_info) || |
| 2930 | !match_prepath(sb, mnt_data)) { | 2945 | !match_prepath(sb, mnt_data)) { |
| 2931 | rc = 0; | 2946 | rc = 0; |
| 2932 | goto out; | 2947 | goto out; |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 0abeb5fb452f..ad83b3db2840 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
| @@ -79,9 +79,14 @@ static const int smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = { | |||
| 79 | 79 | ||
| 80 | static int encryption_required(const struct cifs_tcon *tcon) | 80 | static int encryption_required(const struct cifs_tcon *tcon) |
| 81 | { | 81 | { |
| 82 | if (!tcon) | ||
| 83 | return 0; | ||
| 82 | if ((tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) || | 84 | if ((tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) || |
| 83 | (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA)) | 85 | (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA)) |
| 84 | return 1; | 86 | return 1; |
| 87 | if (tcon->seal && | ||
| 88 | (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) | ||
| 89 | return 1; | ||
| 85 | return 0; | 90 | return 0; |
| 86 | } | 91 | } |
| 87 | 92 | ||
| @@ -835,8 +840,6 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data) | |||
| 835 | ses->Suid = rsp->hdr.sync_hdr.SessionId; | 840 | ses->Suid = rsp->hdr.sync_hdr.SessionId; |
| 836 | 841 | ||
| 837 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); | 842 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
| 838 | if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) | ||
| 839 | cifs_dbg(VFS, "SMB3 encryption not supported yet\n"); | ||
| 840 | 843 | ||
| 841 | rc = SMB2_sess_establish_session(sess_data); | 844 | rc = SMB2_sess_establish_session(sess_data); |
| 842 | out_put_spnego_key: | 845 | out_put_spnego_key: |
| @@ -933,8 +936,6 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data) | |||
| 933 | 936 | ||
| 934 | ses->Suid = rsp->hdr.sync_hdr.SessionId; | 937 | ses->Suid = rsp->hdr.sync_hdr.SessionId; |
| 935 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); | 938 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
| 936 | if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) | ||
| 937 | cifs_dbg(VFS, "SMB3 encryption not supported yet\n"); | ||
| 938 | 939 | ||
| 939 | out: | 940 | out: |
| 940 | kfree(ntlmssp_blob); | 941 | kfree(ntlmssp_blob); |
| @@ -993,8 +994,6 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data) | |||
| 993 | 994 | ||
| 994 | ses->Suid = rsp->hdr.sync_hdr.SessionId; | 995 | ses->Suid = rsp->hdr.sync_hdr.SessionId; |
| 995 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); | 996 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
| 996 | if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) | ||
| 997 | cifs_dbg(VFS, "SMB3 encryption not supported yet\n"); | ||
| 998 | 997 | ||
| 999 | rc = SMB2_sess_establish_session(sess_data); | 998 | rc = SMB2_sess_establish_session(sess_data); |
| 1000 | out: | 999 | out: |
| @@ -1145,12 +1144,6 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
| 1145 | if (tcon && tcon->bad_network_name) | 1144 | if (tcon && tcon->bad_network_name) |
| 1146 | return -ENOENT; | 1145 | return -ENOENT; |
| 1147 | 1146 | ||
| 1148 | if ((tcon && tcon->seal) && | ||
| 1149 | ((ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) == 0)) { | ||
| 1150 | cifs_dbg(VFS, "encryption requested but no server support"); | ||
| 1151 | return -EOPNOTSUPP; | ||
| 1152 | } | ||
| 1153 | |||
| 1154 | unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL); | 1147 | unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL); |
| 1155 | if (unc_path == NULL) | 1148 | if (unc_path == NULL) |
| 1156 | return -ENOMEM; | 1149 | return -ENOMEM; |
| @@ -1168,15 +1161,16 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
| 1168 | return rc; | 1161 | return rc; |
| 1169 | } | 1162 | } |
| 1170 | 1163 | ||
| 1171 | if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) | ||
| 1172 | flags |= CIFS_TRANSFORM_REQ; | ||
| 1173 | |||
| 1174 | if (tcon == NULL) { | 1164 | if (tcon == NULL) { |
| 1165 | if ((ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)) | ||
| 1166 | flags |= CIFS_TRANSFORM_REQ; | ||
| 1167 | |||
| 1175 | /* since no tcon, smb2_init can not do this, so do here */ | 1168 | /* since no tcon, smb2_init can not do this, so do here */ |
| 1176 | req->hdr.sync_hdr.SessionId = ses->Suid; | 1169 | req->hdr.sync_hdr.SessionId = ses->Suid; |
| 1177 | /* if (ses->server->sec_mode & SECMODE_SIGN_REQUIRED) | 1170 | /* if (ses->server->sec_mode & SECMODE_SIGN_REQUIRED) |
| 1178 | req->hdr.Flags |= SMB2_FLAGS_SIGNED; */ | 1171 | req->hdr.Flags |= SMB2_FLAGS_SIGNED; */ |
| 1179 | } | 1172 | } else if (encryption_required(tcon)) |
| 1173 | flags |= CIFS_TRANSFORM_REQ; | ||
| 1180 | 1174 | ||
| 1181 | iov[0].iov_base = (char *)req; | 1175 | iov[0].iov_base = (char *)req; |
| 1182 | /* 4 for rfc1002 length field and 1 for pad */ | 1176 | /* 4 for rfc1002 length field and 1 for pad */ |
| @@ -1233,9 +1227,12 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
| 1233 | if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && | 1227 | if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && |
| 1234 | ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) | 1228 | ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) |
| 1235 | cifs_dbg(VFS, "DFS capability contradicts DFS flag\n"); | 1229 | cifs_dbg(VFS, "DFS capability contradicts DFS flag\n"); |
| 1230 | |||
| 1231 | if (tcon->seal && | ||
| 1232 | !(tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) | ||
| 1233 | cifs_dbg(VFS, "Encryption is requested but not supported\n"); | ||
