Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 31d9e2bd authored by Jeff Layton's avatar Jeff Layton Committed by Steve French
Browse files

cifs: break out decoding of security blob into separate function



...cleanup.

Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Acked-by: default avatarPavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent 281e2e7d
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -531,7 +531,7 @@ typedef struct lanman_neg_rsp {
#define READ_RAW_ENABLE 1
#define WRITE_RAW_ENABLE 2
#define RAW_ENABLE (READ_RAW_ENABLE | WRITE_RAW_ENABLE)

#define SMB1_CLIENT_GUID_SIZE (16)
typedef struct negotiate_rsp {
	struct smb_hdr hdr;	/* wct = 17 */
	__le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
@@ -553,7 +553,7 @@ typedef struct negotiate_rsp {
		/* followed by 16 bytes of server GUID */
		/* then security blob if cap_extended_security negotiated */
		struct {
			unsigned char GUID[16];
			unsigned char GUID[SMB1_CLIENT_GUID_SIZE];
			unsigned char SecurityBlob[1];
		} __attribute__((packed)) extended_response;
	} __attribute__((packed)) u;
+60 −49
Original line number Diff line number Diff line
@@ -367,6 +367,56 @@ static int validate_t2(struct smb_t2_rsp *pSMB)
	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
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->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)
		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)) {
		/* decode security blob */
		count = get_bcc(&pSMBr->hdr);
		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) {
				(pSMBr->EncryptionKeyLength == 0))
		rc = decode_ext_sec_blob(server, pSMBr);
	else if (server->sec_mode & SECMODE_PW_ENCRYPT)
		rc = -EIO; /* no crypt key only if plain text pwd */
		goto neg_err_exit;
	} else
	else
		server->capabilities &= ~CAP_EXTENDED_SECURITY;

	if (rc)
		goto neg_err_exit;

#ifdef CONFIG_CIFS_WEAK_PW_HASH
signing_check:
#endif