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

Commit 8de8c460 authored by Paulo Alcantara's avatar Paulo Alcantara Committed by Steve French
Browse files

cifs: Fix validation of signed data in smb2



Fixes: c713c877 ("cifs: push rfc1002 generation down the stack")

We failed to validate signed data returned by the server because
__cifs_calc_signature() now expects to sign the actual data in iov but
we were also passing down the rfc1002 length.

Fix smb3_calc_signature() to calculate signature of rfc1002 length prior
to passing only the actual data iov[1-N] to __cifs_calc_signature(). In
addition, there are a few cases where no rfc1002 length is passed so we
make sure there's one (iov_len == 4).

Signed-off-by: default avatarPaulo Alcantara <palcantara@suse.de>
Reviewed-by: default avatarRonnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 27c32b49
Loading
Loading
Loading
Loading
+24 −4
Original line number Diff line number Diff line
@@ -173,6 +173,8 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
	struct kvec *iov = rqst->rq_iov;
	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base;
	struct cifs_ses *ses;
	struct shash_desc *shash = &server->secmech.sdeschmacsha256->shash;
	struct smb_rqst drqst;

	ses = smb2_find_smb_ses(server, shdr->SessionId);
	if (!ses) {
@@ -196,15 +198,33 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
		return rc;
	}

	rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash);
	rc = crypto_shash_init(shash);
	if (rc) {
		cifs_dbg(VFS, "%s: Could not init sha256", __func__);
		return rc;
	}

	rc = __cifs_calc_signature(rqst, server, sigptr,
		&server->secmech.sdeschmacsha256->shash);
	/*
	 * For SMB2+, __cifs_calc_signature() expects to sign only the actual
	 * data, that is, iov[0] should not contain a rfc1002 length.
	 *
	 * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to
	 * __cifs_calc_signature().
	 */
	drqst = *rqst;
	if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {
		rc = crypto_shash_update(shash, iov[0].iov_base,
					 iov[0].iov_len);
		if (rc) {
			cifs_dbg(VFS, "%s: Could not update with payload\n",
				 __func__);
			return rc;
		}
		drqst.rq_iov++;
		drqst.rq_nvec--;
	}

	rc = __cifs_calc_signature(&drqst, server, sigptr, shash);
	if (!rc)
		memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);