diff options
author | Paulo Alcantara <paulo@paulo.ac> | 2018-06-23 13:52:24 -0400 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2018-07-05 14:48:24 -0400 |
commit | 8de8c4608fe9edc046c31bf82b2b7ebc1daae015 (patch) | |
tree | 98f7e9f04c5334b100524ae59a89f864c9e805fe | |
parent | 27c32b49c3dbfe1e5f57d2b61823bf9474ae0875 (diff) |
cifs: Fix validation of signed data in smb2
Fixes: c713c8770fa5 ("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: Paulo Alcantara <palcantara@suse.de>
Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
-rw-r--r-- | fs/cifs/smb2transport.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 1af46ca5a951..719d55e63d88 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c | |||
@@ -173,6 +173,8 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
173 | struct kvec *iov = rqst->rq_iov; | 173 | struct kvec *iov = rqst->rq_iov; |
174 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base; | 174 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base; |
175 | struct cifs_ses *ses; | 175 | struct cifs_ses *ses; |
176 | struct shash_desc *shash = &server->secmech.sdeschmacsha256->shash; | ||
177 | struct smb_rqst drqst; | ||
176 | 178 | ||
177 | ses = smb2_find_smb_ses(server, shdr->SessionId); | 179 | ses = smb2_find_smb_ses(server, shdr->SessionId); |
178 | if (!ses) { | 180 | if (!ses) { |
@@ -190,21 +192,39 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
190 | } | 192 | } |
191 | 193 | ||
192 | rc = crypto_shash_setkey(server->secmech.hmacsha256, | 194 | rc = crypto_shash_setkey(server->secmech.hmacsha256, |
193 | ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE); | 195 | ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE); |
194 | if (rc) { | 196 | if (rc) { |
195 | cifs_dbg(VFS, "%s: Could not update with response\n", __func__); | 197 | cifs_dbg(VFS, "%s: Could not update with response\n", __func__); |
196 | return rc; | 198 | return rc; |
197 | } | 199 | } |
198 | 200 | ||
199 | rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash); | 201 | rc = crypto_shash_init(shash); |
200 | if (rc) { | 202 | if (rc) { |
201 | cifs_dbg(VFS, "%s: Could not init sha256", __func__); | 203 | cifs_dbg(VFS, "%s: Could not init sha256", __func__); |
202 | return rc; | 204 | return rc; |
203 | } | 205 | } |
204 | 206 | ||
205 | rc = __cifs_calc_signature(rqst, server, sigptr, | 207 | /* |
206 | &server->secmech.sdeschmacsha256->shash); | 208 | * For SMB2+, __cifs_calc_signature() expects to sign only the actual |
209 | * data, that is, iov[0] should not contain a rfc1002 length. | ||
210 | * | ||
211 | * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to | ||
212 | * __cifs_calc_signature(). | ||
213 | */ | ||
214 | drqst = *rqst; | ||
215 | if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) { | ||
216 | rc = crypto_shash_update(shash, iov[0].iov_base, | ||
217 | iov[0].iov_len); | ||
218 | if (rc) { | ||
219 | cifs_dbg(VFS, "%s: Could not update with payload\n", | ||
220 | __func__); | ||
221 | return rc; | ||
222 | } | ||
223 | drqst.rq_iov++; | ||
224 | drqst.rq_nvec--; | ||
225 | } | ||
207 | 226 | ||
227 | rc = __cifs_calc_signature(&drqst, server, sigptr, shash); | ||
208 | if (!rc) | 228 | if (!rc) |
209 | memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE); | 229 | memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE); |
210 | 230 | ||