aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSachin Prabhu <sprabhu@redhat.com>2017-01-18 05:05:57 -0500
committerSteve French <smfrench@gmail.com>2017-03-03 00:13:37 -0500
commitef65aaede23f75977af56a8c330bb9be8c6e125c (patch)
tree6c7c8bc54081d74d2e4e579639af6f4f528eaf50
parent284316dd42a2027afe37df34c5199eb4eabed8fd (diff)
smb2: Enforce sec= mount option
If the security type specified using a mount option is not supported, the SMB2 session setup code changes the security type to RawNTLMSSP. We should instead fail the mount and return an error. The patch changes the code for SMB2 to make it similar to the code used for SMB1. Like in SMB1, we now use the global security flags to select the security method to be used when no security method is specified and to return an error when the requested auth method is not available. For SMB2, we also use ntlmv2 as a synonym for nltmssp. Signed-off-by: Sachin Prabhu <sprabhu@redhat.com> Acked-by: Pavel Shilovsky <pshilov@microsoft.com> Acked-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <smfrench@gmail.com>
-rw-r--r--fs/cifs/cifsglob.h3
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/connect.c3
-rw-r--r--fs/cifs/sess.c4
-rw-r--r--fs/cifs/smb1ops.c1
-rw-r--r--fs/cifs/smb2ops.c4
-rw-r--r--fs/cifs/smb2pdu.c37
-rw-r--r--fs/cifs/smb2proto.h2
8 files changed, 49 insertions, 7 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index af224cda8697..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 {
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 9ee46c1c3ebd..97e5d236d265 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -533,4 +533,6 @@ int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
533int __cifs_calc_signature(struct smb_rqst *rqst, 533int __cifs_calc_signature(struct smb_rqst *rqst,
534 struct TCP_Server_Info *server, char *signature, 534 struct TCP_Server_Info *server, char *signature,
535 struct shash_desc *shash); 535 struct shash_desc *shash);
536enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
537 enum securityEnum);
536#endif /* _CIFSPROTO_H */ 538#endif /* _CIFSPROTO_H */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 777ad9f4fc3c..de4c56e8fb37 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2073,7 +2073,8 @@ match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2073 * that was specified, or "Unspecified" if that sectype was not 2073 * that was specified, or "Unspecified" if that sectype was not
2074 * compatible with the given NEGOTIATE request. 2074 * compatible with the given NEGOTIATE request.
2075 */ 2075 */
2076 if (select_sectype(server, vol->sectype) == Unspecified) 2076 if (server->ops->select_sectype(server, vol->sectype)
2077 == Unspecified)
2077 return false; 2078 return false;
2078 2079
2079 /* 2080 /*
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/smb2ops.c b/fs/cifs/smb2ops.c
index b360c381b00e..0231108d9387 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -2381,6 +2381,7 @@ struct smb_version_operations smb20_operations = {
2381 .wp_retry_size = smb2_wp_retry_size, 2381 .wp_retry_size = smb2_wp_retry_size,
2382 .dir_needs_close = smb2_dir_needs_close, 2382 .dir_needs_close = smb2_dir_needs_close,
2383 .get_dfs_refer = smb2_get_dfs_refer, 2383 .get_dfs_refer = smb2_get_dfs_refer,
2384 .select_sectype = smb2_select_sectype,
2384}; 2385};
2385 2386
2386struct smb_version_operations smb21_operations = { 2387struct smb_version_operations smb21_operations = {
@@ -2463,6 +2464,7 @@ struct smb_version_operations smb21_operations = {
2463 .dir_needs_close = smb2_dir_needs_close, 2464 .dir_needs_close = smb2_dir_needs_close,
2464 .enum_snapshots = smb3_enum_snapshots, 2465 .enum_snapshots = smb3_enum_snapshots,
2465 .get_dfs_refer = smb2_get_dfs_refer, 2466 .get_dfs_refer = smb2_get_dfs_refer,
2467 .select_sectype = smb2_select_sectype,
2466}; 2468};
2467 2469
2468struct smb_version_operations smb30_operations = { 2470struct smb_version_operations smb30_operations = {
@@ -2555,6 +2557,7 @@ struct smb_version_operations smb30_operations = {
2555 .is_transform_hdr = smb3_is_transform_hdr, 2557 .is_transform_hdr = smb3_is_transform_hdr,
2556 .receive_transform = smb3_receive_transform, 2558 .receive_transform = smb3_receive_transform,
2557 .get_dfs_refer = smb2_get_dfs_refer, 2559 .get_dfs_refer = smb2_get_dfs_refer,
2560 .select_sectype = smb2_select_sectype,
2558}; 2561};
2559 2562
2560#ifdef CONFIG_CIFS_SMB311 2563#ifdef CONFIG_CIFS_SMB311
@@ -2648,6 +2651,7 @@ struct smb_version_operations smb311_operations = {
2648 .is_transform_hdr = smb3_is_transform_hdr, 2651 .is_transform_hdr = smb3_is_transform_hdr,
2649 .receive_transform = smb3_receive_transform, 2652 .receive_transform = smb3_receive_transform,
2650 .get_dfs_refer = smb2_get_dfs_refer, 2653 .get_dfs_refer = smb2_get_dfs_refer,
2654 .select_sectype = smb2_select_sectype,
2651}; 2655};
2652#endif /* CIFS_SMB311 */ 2656#endif /* CIFS_SMB311 */
2653 2657
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 2069431b32e3..7446496850a3 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -657,6 +657,28 @@ vneg_out:
657 return -EIO; 657 return -EIO;
658} 658}
659 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
660struct SMB2_sess_data { 682struct SMB2_sess_data {
661 unsigned int xid; 683 unsigned int xid;
662 struct cifs_ses *ses; 684 struct cifs_ses *ses;
@@ -1009,10 +1031,17 @@ out:
1009static int 1031static int
1010SMB2_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)
1011{ 1033{
1012 if (ses->sectype != Kerberos && ses->sectype != RawNTLMSSP) 1034 int type;
1013 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 }
1014 1043
1015 switch (ses->sectype) { 1044 switch (type) {
1016 case Kerberos: 1045 case Kerberos:
1017 sess_data->func = SMB2_auth_kerberos; 1046 sess_data->func = SMB2_auth_kerberos;
1018 break; 1047 break;
@@ -1020,7 +1049,7 @@ SMB2_select_sec(struct cifs_ses *ses, struct SMB2_sess_data *sess_data)
1020 sess_data->func = SMB2_sess_auth_rawntlmssp_negotiate; 1049 sess_data->func = SMB2_sess_auth_rawntlmssp_negotiate;
1021 break; 1050 break;
1022 default: 1051 default:
1023 cifs_dbg(VFS, "secType %d not supported!\n", ses->sectype); 1052 cifs_dbg(VFS, "secType %d not supported!\n", type);
1024 return -EOPNOTSUPP; 1053 return -EOPNOTSUPP;
1025 } 1054 }
1026 1055
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 11d9f3013db8..69e35873b1de 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -181,4 +181,6 @@ extern int SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
181 __u8 *lease_key, const __le32 lease_state); 181 __u8 *lease_key, const __le32 lease_state);
182extern int smb3_validate_negotiate(const unsigned int, struct cifs_tcon *); 182extern int smb3_validate_negotiate(const unsigned int, struct cifs_tcon *);
183 183
184extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *,
185 enum securityEnum);
184#endif /* _SMB2PROTO_H */ 186#endif /* _SMB2PROTO_H */