int (*is_transform_hdr)(void *buf);
        int (*receive_transform)(struct TCP_Server_Info *,
                                 struct mid_q_entry **);
+       enum securityEnum (*select_sectype)(struct TCP_Server_Info *,
+                           enum securityEnum);
+
 };
 
 struct smb_version_values {
 
 int __cifs_calc_signature(struct smb_rqst *rqst,
                        struct TCP_Server_Info *server, char *signature,
                        struct shash_desc *shash);
+enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
+                                       enum securityEnum);
 #endif                 /* _CIFSPROTO_H */
 
         * that was specified, or "Unspecified" if that sectype was not
         * compatible with the given NEGOTIATE request.
         */
-       if (select_sectype(server, vol->sectype) == Unspecified)
+       if (server->ops->select_sectype(server, vol->sectype)
+            == Unspecified)
                return false;
 
        /*
 
 }
 
 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) {
        case CIFS_NEGFLAVOR_EXTENDED:
 {
        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);
        if (type == Unspecified) {
                cifs_dbg(VFS,
 
        .is_read_op = cifs_is_read_op,
        .wp_retry_size = cifs_wp_retry_size,
        .dir_needs_close = cifs_dir_needs_close,
+       .select_sectype = cifs_select_sectype,
 #ifdef CONFIG_CIFS_XATTR
        .query_all_EAs = CIFSSMBQAllEAs,
        .set_EA = CIFSSMBSetEA,
 
        .wp_retry_size = smb2_wp_retry_size,
        .dir_needs_close = smb2_dir_needs_close,
        .get_dfs_refer = smb2_get_dfs_refer,
+       .select_sectype = smb2_select_sectype,
 };
 
 struct smb_version_operations smb21_operations = {
        .dir_needs_close = smb2_dir_needs_close,
        .enum_snapshots = smb3_enum_snapshots,
        .get_dfs_refer = smb2_get_dfs_refer,
+       .select_sectype = smb2_select_sectype,
 };
 
 struct smb_version_operations smb30_operations = {
        .is_transform_hdr = smb3_is_transform_hdr,
        .receive_transform = smb3_receive_transform,
        .get_dfs_refer = smb2_get_dfs_refer,
+       .select_sectype = smb2_select_sectype,
 };
 
 #ifdef CONFIG_CIFS_SMB311
        .is_transform_hdr = smb3_is_transform_hdr,
        .receive_transform = smb3_receive_transform,
        .get_dfs_refer = smb2_get_dfs_refer,
+       .select_sectype = smb2_select_sectype,
 };
 #endif /* CIFS_SMB311 */
 
 
        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 {
        unsigned int xid;
        struct cifs_ses *ses;
 static int
 SMB2_select_sec(struct cifs_ses *ses, struct SMB2_sess_data *sess_data)
 {
-       if (ses->sectype != Kerberos && ses->sectype != RawNTLMSSP)
-               ses->sectype = RawNTLMSSP;
+       int type;
+
+       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:
                sess_data->func = SMB2_auth_kerberos;
                break;
                sess_data->func = SMB2_sess_auth_rawntlmssp_negotiate;
                break;
        default:
-               cifs_dbg(VFS, "secType %d not supported!\n", ses->sectype);
+               cifs_dbg(VFS, "secType %d not supported!\n", type);
                return -EOPNOTSUPP;
        }
 
 
                            __u8 *lease_key, const __le32 lease_state);
 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 */