aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulo Alcantara <paulo@paulo.ac>2018-06-23 13:52:24 -0400
committerSteve French <stfrench@microsoft.com>2018-07-05 14:48:24 -0400
commit8de8c4608fe9edc046c31bf82b2b7ebc1daae015 (patch)
tree98f7e9f04c5334b100524ae59a89f864c9e805fe
parent27c32b49c3dbfe1e5f57d2b61823bf9474ae0875 (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.c28
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