cifs: track the flavor of the NEGOTIATE reponse
authorJeff Layton <jlayton@redhat.com>
Sun, 26 May 2013 11:00:59 +0000 (07:00 -0400)
committerSteve French <smfrench@gmail.com>
Mon, 24 Jun 2013 06:56:42 +0000 (01:56 -0500)
Track what sort of NEGOTIATE response we get from the server, as that
will govern what sort of authentication types this socket will support.

There are three possibilities:

LANMAN: server sent legacy LANMAN-type response

UNENCAP: server sent a newer-style response, but extended security bit
wasn't set. This socket will only support unencapsulated auth types.

EXTENDED: server sent a newer-style response with the extended security
bit set. This is necessary to support krb5 and ntlmssp auth types.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Reviewed-by: Pavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: Steve French <smfrench@gmail.com>
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/smb2pdu.c

index 9f8dc3da5f3b7262c22ca771f2b5ec0c6d53f4e0..82ba4b9748949b9326648e8f8e5421bc46476547 100644 (file)
@@ -541,6 +541,10 @@ struct TCP_Server_Info {
        struct session_key session_key;
        unsigned long lstrp; /* when we got last response from this server */
        struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */
+#define        CIFS_NEGFLAVOR_LANMAN   0       /* wct == 13, LANMAN */
+#define        CIFS_NEGFLAVOR_UNENCAP  1       /* wct == 17, but no ext_sec */
+#define        CIFS_NEGFLAVOR_EXTENDED 2       /* wct == 17, ext_sec bit set */
+       char    negflavor;      /* NEGOTIATE response flavor */
        /* extended security flavors that server supports */
        bool    sec_ntlmssp;            /* supports NTLMSSP */
        bool    sec_kerberosu2u;        /* supports U2U Kerberos */
index e63961086752fc28bdcd4281aeb9dfb305fd7823..80ca6886a8166310635a1855da9b4e4204a14504 100644 (file)
@@ -615,6 +615,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
                rc = -EOPNOTSUPP;
                goto neg_err_exit;
        } else if (pSMBr->hdr.WordCount == 13) {
+               server->negflavor = CIFS_NEGFLAVOR_LANMAN;
                rc = decode_lanman_negprot_rsp(server, pSMBr, secFlags);
                goto signing_check;
        } else if (pSMBr->hdr.WordCount != 17) {
@@ -666,17 +667,21 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
        server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
        server->timeAdj *= 60;
 
-       if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE)
+       if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
+               server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
                memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
                       CIFS_CRYPTO_KEY_SIZE);
-       else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
+       else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
                        server->capabilities & CAP_EXTENDED_SECURITY) &&
-                               (pSMBr->EncryptionKeyLength == 0))
+                               (pSMBr->EncryptionKeyLength == 0)) {
+               server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
                rc = decode_ext_sec_blob(server, pSMBr);
-       else if (server->sec_mode & SECMODE_PW_ENCRYPT)
+       } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
                rc = -EIO; /* no crypt key only if plain text pwd */
-       else
+       } else {
+               server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
                server->capabilities &= ~CAP_EXTENDED_SECURITY;
+       }
 
 signing_check:
        if (!rc)
index ebb97b484ab1dbf340455523b393d7655fe219a8..1609699e7bec3a6ae4b1912df4af9dbe77de3059 100644 (file)
@@ -405,6 +405,8 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
        }
        server->dialect = le16_to_cpu(rsp->DialectRevision);
 
+       /* SMB2 only has an extended negflavor */
+       server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
        server->maxBuf = le32_to_cpu(rsp->MaxTransactSize);
        server->max_read = le32_to_cpu(rsp->MaxReadSize);
        server->max_write = le32_to_cpu(rsp->MaxWriteSize);