cifs: break out decoding of security blob into separate function
...cleanup. Signed-off-by: Jeff Layton <jlayton@redhat.com> Acked-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
parent
281e2e7d06
commit
31d9e2bd5f
2 changed files with 62 additions and 51 deletions
|
@ -531,7 +531,7 @@ typedef struct lanman_neg_rsp {
|
||||||
#define READ_RAW_ENABLE 1
|
#define READ_RAW_ENABLE 1
|
||||||
#define WRITE_RAW_ENABLE 2
|
#define WRITE_RAW_ENABLE 2
|
||||||
#define RAW_ENABLE (READ_RAW_ENABLE | WRITE_RAW_ENABLE)
|
#define RAW_ENABLE (READ_RAW_ENABLE | WRITE_RAW_ENABLE)
|
||||||
|
#define SMB1_CLIENT_GUID_SIZE (16)
|
||||||
typedef struct negotiate_rsp {
|
typedef struct negotiate_rsp {
|
||||||
struct smb_hdr hdr; /* wct = 17 */
|
struct smb_hdr hdr; /* wct = 17 */
|
||||||
__le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
|
__le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
|
||||||
|
@ -553,7 +553,7 @@ typedef struct negotiate_rsp {
|
||||||
/* followed by 16 bytes of server GUID */
|
/* followed by 16 bytes of server GUID */
|
||||||
/* then security blob if cap_extended_security negotiated */
|
/* then security blob if cap_extended_security negotiated */
|
||||||
struct {
|
struct {
|
||||||
unsigned char GUID[16];
|
unsigned char GUID[SMB1_CLIENT_GUID_SIZE];
|
||||||
unsigned char SecurityBlob[1];
|
unsigned char SecurityBlob[1];
|
||||||
} __attribute__((packed)) extended_response;
|
} __attribute__((packed)) extended_response;
|
||||||
} __attribute__((packed)) u;
|
} __attribute__((packed)) u;
|
||||||
|
|
|
@ -367,6 +367,56 @@ vt2_err:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
decode_ext_sec_blob(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
u16 count;
|
||||||
|
char *guid = pSMBr->u.extended_response.GUID;
|
||||||
|
|
||||||
|
count = get_bcc(&pSMBr->hdr);
|
||||||
|
if (count < SMB1_CLIENT_GUID_SIZE)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
spin_lock(&cifs_tcp_ses_lock);
|
||||||
|
if (server->srv_count > 1) {
|
||||||
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
|
if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
|
||||||
|
cifs_dbg(FYI, "server UID changed\n");
|
||||||
|
memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
|
memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == SMB1_CLIENT_GUID_SIZE) {
|
||||||
|
server->secType = RawNTLMSSP;
|
||||||
|
} else {
|
||||||
|
count -= SMB1_CLIENT_GUID_SIZE;
|
||||||
|
rc = decode_negTokenInit(
|
||||||
|
pSMBr->u.extended_response.SecurityBlob, count, server);
|
||||||
|
if (rc != 1)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Make sure server supports what we want to use */
|
||||||
|
switch(server->secType) {
|
||||||
|
case Kerberos:
|
||||||
|
if (!server->sec_kerberos && !server->sec_mskerberos)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
break;
|
||||||
|
case RawNTLMSSP:
|
||||||
|
if (!server->sec_ntlmssp)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
|
CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
|
||||||
{
|
{
|
||||||
|
@ -568,61 +618,22 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
|
||||||
server->capabilities = le32_to_cpu(pSMBr->Capabilities);
|
server->capabilities = le32_to_cpu(pSMBr->Capabilities);
|
||||||
server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
|
server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
|
||||||
server->timeAdj *= 60;
|
server->timeAdj *= 60;
|
||||||
if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
|
|
||||||
|
if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE)
|
||||||
memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
|
memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
|
||||||
CIFS_CRYPTO_KEY_SIZE);
|
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) &&
|
server->capabilities & CAP_EXTENDED_SECURITY) &&
|
||||||
(pSMBr->EncryptionKeyLength == 0)) {
|
(pSMBr->EncryptionKeyLength == 0))
|
||||||
/* decode security blob */
|
rc = decode_ext_sec_blob(server, pSMBr);
|
||||||
count = get_bcc(&pSMBr->hdr);
|
else if (server->sec_mode & SECMODE_PW_ENCRYPT)
|
||||||
if (count < 16) {
|
|
||||||
rc = -EIO;
|
|
||||||
goto neg_err_exit;
|
|
||||||
}
|
|
||||||
spin_lock(&cifs_tcp_ses_lock);
|
|
||||||
if (server->srv_count > 1) {
|
|
||||||
spin_unlock(&cifs_tcp_ses_lock);
|
|
||||||
if (memcmp(server->server_GUID,
|
|
||||||
pSMBr->u.extended_response.
|
|
||||||
GUID, 16) != 0) {
|
|
||||||
cifs_dbg(FYI, "server UID changed\n");
|
|
||||||
memcpy(server->server_GUID,
|
|
||||||
pSMBr->u.extended_response.GUID,
|
|
||||||
16);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
spin_unlock(&cifs_tcp_ses_lock);
|
|
||||||
memcpy(server->server_GUID,
|
|
||||||
pSMBr->u.extended_response.GUID, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 16) {
|
|
||||||
server->secType = RawNTLMSSP;
|
|
||||||
} else {
|
|
||||||
rc = decode_negTokenInit(pSMBr->u.extended_response.
|
|
||||||
SecurityBlob, count - 16,
|
|
||||||
server);
|
|
||||||
if (rc == 1)
|
|
||||||
rc = 0;
|
|
||||||
else
|
|
||||||
rc = -EINVAL;
|
|
||||||
if (server->secType == Kerberos) {
|
|
||||||
if (!server->sec_kerberos &&
|
|
||||||
!server->sec_mskerberos)
|
|
||||||
rc = -EOPNOTSUPP;
|
|
||||||
} else if (server->secType == RawNTLMSSP) {
|
|
||||||
if (!server->sec_ntlmssp)
|
|
||||||
rc = -EOPNOTSUPP;
|
|
||||||
} else
|
|
||||||
rc = -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
|
|
||||||
rc = -EIO; /* no crypt key only if plain text pwd */
|
rc = -EIO; /* no crypt key only if plain text pwd */
|
||||||
goto neg_err_exit;
|
else
|
||||||
} else
|
|
||||||
server->capabilities &= ~CAP_EXTENDED_SECURITY;
|
server->capabilities &= ~CAP_EXTENDED_SECURITY;
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
goto neg_err_exit;
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||||
signing_check:
|
signing_check:
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue