cifs: match secType when searching for existing tcp session
Jeff Layton [Wed, 7 Jul 2010 00:43:02 +0000 (20:43 -0400)]
The secType is a per-tcp session entity, but the current routine doesn't
verify that it is acceptible when attempting to match an existing TCP
session.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>

fs/cifs/cifsglob.h
fs/cifs/connect.c

index 06b4899..8fb1d10 100644 (file)
@@ -83,8 +83,7 @@ enum statusEnum {
 };
 
 enum securityEnum {
-       PLAINTXT = 0,           /* Legacy with Plaintext passwords */
-       LANMAN,                 /* Legacy LANMAN auth */
+       LANMAN = 0,                     /* Legacy LANMAN auth */
        NTLM,                   /* Legacy NTLM012 auth with NTLM hash */
        NTLMv2,                 /* Legacy NTLM auth with NTLMv2 hash */
        RawNTLMSSP,             /* NTLMSSP without SPNEGO, NTLMv2 hash */
index 65e760b..b24e4ce 100644 (file)
@@ -1412,8 +1412,56 @@ match_address(struct TCP_Server_Info *server, struct sockaddr *addr)
        return true;
 }
 
+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 */
+               return false;
+       }
+
+       /* now check if signing mode is acceptible */
+       if ((secFlags & CIFSSEC_MAY_SIGN) == 0 &&
+           (server->secMode & SECMODE_SIGN_REQUIRED))
+                       return false;
+       else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) &&
+                (server->secMode &
+                 (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0)
+                       return false;
+
+       return true;
+}
+
 static struct TCP_Server_Info *
-cifs_find_tcp_session(struct sockaddr *addr)
+cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol)
 {
        struct TCP_Server_Info *server;
 
@@ -1431,6 +1479,9 @@ cifs_find_tcp_session(struct sockaddr *addr)
                if (!match_address(server, addr))
                        continue;
 
+               if (!match_security(server, vol))
+                       continue;
+
                ++server->srv_count;
                write_unlock(&cifs_tcp_ses_lock);
                cFYI(1, "Existing tcp session with server found");
@@ -1501,7 +1552,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
        }
 
        /* see if we already have a matching tcp_ses */
-       tcp_ses = cifs_find_tcp_session((struct sockaddr *)&addr);
+       tcp_ses = cifs_find_tcp_session((struct sockaddr *)&addr, volume_info);
        if (tcp_ses)
                return tcp_ses;