Commit ef65aaed authored by Sachin Prabhu's avatar Sachin Prabhu Committed by Steve French

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: default avatarSachin Prabhu <sprabhu@redhat.com>
Acked-by: default avatarPavel Shilovsky <pshilov@microsoft.com>
Acked-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <smfrench@gmail.com>
parent 284316dd
...@@ -443,6 +443,9 @@ struct smb_version_operations { ...@@ -443,6 +443,9 @@ struct smb_version_operations {
int (*is_transform_hdr)(void *buf); int (*is_transform_hdr)(void *buf);
int (*receive_transform)(struct TCP_Server_Info *, int (*receive_transform)(struct TCP_Server_Info *,
struct mid_q_entry **); struct mid_q_entry **);
enum securityEnum (*select_sectype)(struct TCP_Server_Info *,
enum securityEnum);
}; };
struct smb_version_values { struct smb_version_values {
......
...@@ -533,4 +533,6 @@ int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, ...@@ -533,4 +533,6 @@ int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
int __cifs_calc_signature(struct smb_rqst *rqst, int __cifs_calc_signature(struct smb_rqst *rqst,
struct TCP_Server_Info *server, char *signature, struct TCP_Server_Info *server, char *signature,
struct shash_desc *shash); struct shash_desc *shash);
enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
enum securityEnum);
#endif /* _CIFSPROTO_H */ #endif /* _CIFSPROTO_H */
...@@ -2073,7 +2073,8 @@ match_security(struct TCP_Server_Info *server, struct smb_vol *vol) ...@@ -2073,7 +2073,8 @@ match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
* that was specified, or "Unspecified" if that sectype was not * that was specified, or "Unspecified" if that sectype was not
* compatible with the given NEGOTIATE request. * compatible with the given NEGOTIATE request.
*/ */
if (select_sectype(server, vol->sectype) == Unspecified) if (server->ops->select_sectype(server, vol->sectype)
== Unspecified)
return false; return false;
/* /*
......
...@@ -498,7 +498,7 @@ int build_ntlmssp_auth_blob(unsigned char **pbuffer, ...@@ -498,7 +498,7 @@ int build_ntlmssp_auth_blob(unsigned char **pbuffer,
} }
enum securityEnum enum securityEnum
select_sectype(struct TCP_Server_Info *server, enum securityEnum requested) cifs_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
{ {
switch (server->negflavor) { switch (server->negflavor) {
case CIFS_NEGFLAVOR_EXTENDED: case CIFS_NEGFLAVOR_EXTENDED:
...@@ -1391,7 +1391,7 @@ static int select_sec(struct cifs_ses *ses, struct sess_data *sess_data) ...@@ -1391,7 +1391,7 @@ static int select_sec(struct cifs_ses *ses, struct sess_data *sess_data)
{ {
int type; int type;
type = select_sectype(ses->server, ses->sectype); type = cifs_select_sectype(ses->server, ses->sectype);
cifs_dbg(FYI, "sess setup type %d\n", type); cifs_dbg(FYI, "sess setup type %d\n", type);
if (type == Unspecified) { if (type == Unspecified) {
cifs_dbg(VFS, cifs_dbg(VFS,
......
...@@ -1087,6 +1087,7 @@ struct smb_version_operations smb1_operations = { ...@@ -1087,6 +1087,7 @@ struct smb_version_operations smb1_operations = {
.is_read_op = cifs_is_read_op, .is_read_op = cifs_is_read_op,
.wp_retry_size = cifs_wp_retry_size, .wp_retry_size = cifs_wp_retry_size,
.dir_needs_close = cifs_dir_needs_close, .dir_needs_close = cifs_dir_needs_close,
.select_sectype = cifs_select_sectype,
#ifdef CONFIG_CIFS_XATTR #ifdef CONFIG_CIFS_XATTR
.query_all_EAs = CIFSSMBQAllEAs, .query_all_EAs = CIFSSMBQAllEAs,
.set_EA = CIFSSMBSetEA, .set_EA = CIFSSMBSetEA,
......
...@@ -2381,6 +2381,7 @@ struct smb_version_operations smb20_operations = { ...@@ -2381,6 +2381,7 @@ struct smb_version_operations smb20_operations = {
.wp_retry_size = smb2_wp_retry_size, .wp_retry_size = smb2_wp_retry_size,
.dir_needs_close = smb2_dir_needs_close, .dir_needs_close = smb2_dir_needs_close,
.get_dfs_refer = smb2_get_dfs_refer, .get_dfs_refer = smb2_get_dfs_refer,
.select_sectype = smb2_select_sectype,
}; };
struct smb_version_operations smb21_operations = { struct smb_version_operations smb21_operations = {
...@@ -2463,6 +2464,7 @@ struct smb_version_operations smb21_operations = { ...@@ -2463,6 +2464,7 @@ struct smb_version_operations smb21_operations = {
.dir_needs_close = smb2_dir_needs_close, .dir_needs_close = smb2_dir_needs_close,
.enum_snapshots = smb3_enum_snapshots, .enum_snapshots = smb3_enum_snapshots,
.get_dfs_refer = smb2_get_dfs_refer, .get_dfs_refer = smb2_get_dfs_refer,
.select_sectype = smb2_select_sectype,
}; };
struct smb_version_operations smb30_operations = { struct smb_version_operations smb30_operations = {
...@@ -2555,6 +2557,7 @@ struct smb_version_operations smb30_operations = { ...@@ -2555,6 +2557,7 @@ struct smb_version_operations smb30_operations = {
.is_transform_hdr = smb3_is_transform_hdr, .is_transform_hdr = smb3_is_transform_hdr,
.receive_transform = smb3_receive_transform, .receive_transform = smb3_receive_transform,
.get_dfs_refer = smb2_get_dfs_refer, .get_dfs_refer = smb2_get_dfs_refer,
.select_sectype = smb2_select_sectype,
}; };
#ifdef CONFIG_CIFS_SMB311 #ifdef CONFIG_CIFS_SMB311
...@@ -2648,6 +2651,7 @@ struct smb_version_operations smb311_operations = { ...@@ -2648,6 +2651,7 @@ struct smb_version_operations smb311_operations = {
.is_transform_hdr = smb3_is_transform_hdr, .is_transform_hdr = smb3_is_transform_hdr,
.receive_transform = smb3_receive_transform, .receive_transform = smb3_receive_transform,
.get_dfs_refer = smb2_get_dfs_refer, .get_dfs_refer = smb2_get_dfs_refer,
.select_sectype = smb2_select_sectype,
}; };
#endif /* CIFS_SMB311 */ #endif /* CIFS_SMB311 */
......
...@@ -657,6 +657,28 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) ...@@ -657,6 +657,28 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
return -EIO; return -EIO;
} }
enum securityEnum
smb2_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
{
switch (requested) {
case Kerberos:
case RawNTLMSSP:
return requested;
case NTLMv2:
return RawNTLMSSP;
case Unspecified:
if (server->sec_ntlmssp &&
(global_secflags & CIFSSEC_MAY_NTLMSSP))
return RawNTLMSSP;
if ((server->sec_kerberos || server->sec_mskerberos) &&
(global_secflags & CIFSSEC_MAY_KRB5))
return Kerberos;
/* Fallthrough */
default:
return Unspecified;
}
}
struct SMB2_sess_data { struct SMB2_sess_data {
unsigned int xid; unsigned int xid;
struct cifs_ses *ses; struct cifs_ses *ses;
...@@ -1009,10 +1031,17 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data) ...@@ -1009,10 +1031,17 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
static int static int
SMB2_select_sec(struct cifs_ses *ses, struct SMB2_sess_data *sess_data) SMB2_select_sec(struct cifs_ses *ses, struct SMB2_sess_data *sess_data)
{ {
if (ses->sectype != Kerberos && ses->sectype != RawNTLMSSP) int type;
ses->sectype = RawNTLMSSP;
type = smb2_select_sectype(ses->server, ses->sectype);
cifs_dbg(FYI, "sess setup type %d\n", type);
if (type == Unspecified) {
cifs_dbg(VFS,
"Unable to select appropriate authentication method!");
return -EINVAL;
}
switch (ses->sectype) { switch (type) {
case Kerberos: case Kerberos:
sess_data->func = SMB2_auth_kerberos; sess_data->func = SMB2_auth_kerberos;
break; break;
...@@ -1020,7 +1049,7 @@ SMB2_select_sec(struct cifs_ses *ses, struct SMB2_sess_data *sess_data) ...@@ -1020,7 +1049,7 @@ SMB2_select_sec(struct cifs_ses *ses, struct SMB2_sess_data *sess_data)
sess_data->func = SMB2_sess_auth_rawntlmssp_negotiate; sess_data->func = SMB2_sess_auth_rawntlmssp_negotiate;
break; break;
default: default:
cifs_dbg(VFS, "secType %d not supported!\n", ses->sectype); cifs_dbg(VFS, "secType %d not supported!\n", type);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
...@@ -181,4 +181,6 @@ extern int SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -181,4 +181,6 @@ extern int SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
__u8 *lease_key, const __le32 lease_state); __u8 *lease_key, const __le32 lease_state);
extern int smb3_validate_negotiate(const unsigned int, struct cifs_tcon *); extern int smb3_validate_negotiate(const unsigned int, struct cifs_tcon *);
extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *,
enum securityEnum);
#endif /* _SMB2PROTO_H */ #endif /* _SMB2PROTO_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment