diff options
author | Jeff Layton <jlayton@redhat.com> | 2013-06-12 19:52:14 -0500 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2013-06-24 01:56:44 -0500 |
commit | 3f618223dc0bdcbc8d510350e78ee2195ff93768 (patch) | |
tree | 07b910ab18112557f897f2192d073f97553e1055 /fs/cifs/connect.c | |
parent | 38d77c50b4f4e3ea1687e119871364f1c8d2f531 (diff) |
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.c | 117 |
1 files changed, 33 insertions, 84 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index acbb255352a..c4c6aa99ee1 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); } |