summaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2013-06-12 19:52:14 -0500
committerSteve French <smfrench@gmail.com>2013-06-24 01:56:44 -0500
commit3f618223dc0bdcbc8d510350e78ee2195ff93768 (patch)
tree07b910ab18112557f897f2192d073f97553e1055 /fs/cifs/connect.c
parent38d77c50b4f4e3ea1687e119871364f1c8d2f531 (diff)
downloadlinux-3f618223dc0bdcbc8d510350e78ee2195ff93768.tar.gz
linux-3f618223dc0bdcbc8d510350e78ee2195ff93768.tar.bz2
linux-3f618223dc0bdcbc8d510350e78ee2195ff93768.zip
move sectype to the cifs_ses instead of TCP_Server_Info
Now that we track what sort of NEGOTIATE response was received, stop mandating that every session on a socket use the same type of auth. Push that decision out into the session setup code, and make the sectype a per-session property. This should allow us to mix multiple sectypes on a socket as long as they are compatible with the NEGOTIATE response. With this too, we can now eliminate the ses->secFlg field since that info is redundant and harder to work with than a securityEnum. Signed-off-by: Jeff Layton <jlayton@redhat.com> Acked-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c117
1 files changed, 33 insertions, 84 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index acbb255352af..c4c6aa99ee1c 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1033,56 +1033,40 @@ static int cifs_parse_security_flavors(char *value,
vol->sign = false;
switch (match_token(value, cifs_secflavor_tokens, args)) {
+ case Opt_sec_krb5p:
+ cifs_dbg(VFS, "sec=krb5p is not supported!\n");
+ return 1;
+ case Opt_sec_krb5i:
+ vol->sign = true;
+ /* Fallthrough */
case Opt_sec_krb5:
vol->sectype = Kerberos;
- vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_SIGN;
break;
- case Opt_sec_krb5i:
- vol->sectype = Kerberos;
+ case Opt_sec_ntlmsspi:
vol->sign = true;
- vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN;
- break;
- case Opt_sec_krb5p:
- /* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */
- cifs_dbg(VFS, "Krb5 cifs privacy not supported\n");
- break;
+ /* Fallthrough */
case Opt_sec_ntlmssp:
vol->sectype = RawNTLMSSP;
- vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
break;
- case Opt_sec_ntlmsspi:
- vol->sectype = RawNTLMSSP;
+ case Opt_sec_ntlmi:
vol->sign = true;
- vol->secFlg |= CIFSSEC_MAY_NTLMSSP | CIFSSEC_MUST_SIGN;
- break;
+ /* Fallthrough */
case Opt_ntlm:
- /* ntlm is default so can be turned off too */
vol->sectype = NTLM;
- vol->secFlg |= CIFSSEC_MAY_NTLM;
break;
- case Opt_sec_ntlmi:
- vol->sectype = NTLM;
+ case Opt_sec_ntlmv2i:
vol->sign = true;
- vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN;
- break;
+ /* Fallthrough */
case Opt_sec_ntlmv2:
vol->sectype = NTLMv2;
- vol->secFlg |= CIFSSEC_MAY_NTLMV2;
- break;
- case Opt_sec_ntlmv2i:
- vol->sectype = NTLMv2;
- vol->sign = true;
- vol->secFlg |= CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN;
break;
#ifdef CONFIG_CIFS_WEAK_PW_HASH
case Opt_sec_lanman:
vol->sectype = LANMAN;
- vol->secFlg |= CIFSSEC_MAY_LANMAN;
break;
#endif
case Opt_sec_none:
vol->nullauth = 1;
- vol->secFlg |= CIFSSEC_MAY_NTLM;
break;
default:
cifs_dbg(VFS, "bad security option: %s\n", value);
@@ -1445,7 +1429,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
vol->local_lease = 1;
break;
case Opt_sign:
- vol->secFlg |= CIFSSEC_MUST_SIGN;
vol->sign = true;
break;
case Opt_seal:
@@ -2003,40 +1986,19 @@ match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
static bool
match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
{
- unsigned int secFlags;
-
- if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
- secFlags = vol->secFlg;
- else
- secFlags = global_secflags | vol->secFlg;
-
- switch (server->secType) {
- case LANMAN:
- if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT)))
- return false;
- break;
- case NTLMv2:
- if (!(secFlags & CIFSSEC_MAY_NTLMV2))
- return false;
- break;
- case NTLM:
- if (!(secFlags & CIFSSEC_MAY_NTLM))
- return false;
- break;
- case Kerberos:
- if (!(secFlags & CIFSSEC_MAY_KRB5))
- return false;
- break;
- case RawNTLMSSP:
- if (!(secFlags & CIFSSEC_MAY_NTLMSSP))
- return false;
- break;
- default:
- /* shouldn't happen */
+ /*
+ * The select_sectype function should either return the vol->sectype
+ * that was specified, or "Unspecified" if that sectype was not
+ * compatible with the given NEGOTIATE request.
+ */
+ if (select_sectype(server, vol->sectype) == Unspecified)
return false;
- }
- /* now check if signing mode is acceptable */
+ /*
+ * Now check if signing mode is acceptable. No need to check
+ * global_secflags at this point since if MUST_SIGN is set then
+ * the server->sign had better be too.
+ */
if (vol->sign && !server->sign)
return false;
@@ -2239,7 +2201,11 @@ out_err:
static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
{
- switch (ses->server->secType) {
+ if (vol->sectype != Unspecified &&
+ vol->sectype != ses->sectype)
+ return 0;
+
+ switch (ses->sectype) {
case Kerberos:
if (!uid_eq(vol->cred_uid, ses->cred_uid))
return 0;
@@ -2516,7 +2482,6 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
ses->cred_uid = volume_info->cred_uid;
ses->linux_uid = volume_info->linux_uid;
- ses->overrideSecFlg = volume_info->secFlg;
ses->sectype = volume_info->sectype;
ses->sign = volume_info->sign;
@@ -3681,7 +3646,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
NTLMv2 password here) */
#ifdef CONFIG_CIFS_WEAK_PW_HASH
if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
- (ses->server->secType == LANMAN))
+ (ses->sectype == LANMAN))
calc_lanman_hash(tcon->password, ses->server->cryptkey,
ses->server->sec_mode &
SECMODE_PW_ENCRYPT ? true : false,
@@ -3893,27 +3858,11 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
static int
cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
{
- switch (ses->server->secType) {
- case Kerberos:
- vol->secFlg = CIFSSEC_MUST_KRB5;
+ vol->sectype = ses->sectype;
+
+ /* krb5 is special, since we don't need username or pw */
+ if (vol->sectype == Kerberos)
return 0;
- case NTLMv2:
- vol->secFlg = CIFSSEC_MUST_NTLMV2;
- break;
- case NTLM:
- vol->secFlg = CIFSSEC_MUST_NTLM;
- break;
- case RawNTLMSSP:
- vol->secFlg = CIFSSEC_MUST_NTLMSSP;
- break;
- case LANMAN:
- vol->secFlg = CIFSSEC_MUST_LANMAN;
- break;
- default:
- /* should never happen */
- vol->secFlg = 0;
- break;
- }
return cifs_set_cifscreds(vol, ses);
}