diff options
Diffstat (limited to 'fs/cifs/smb2transport.c')
-rw-r--r-- | fs/cifs/smb2transport.c | 70 |
1 files changed, 52 insertions, 18 deletions
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 4f2300d020c7..340abca3aa52 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c | |||
@@ -114,6 +114,23 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server) | |||
114 | return 0; | 114 | return 0; |
115 | } | 115 | } |
116 | 116 | ||
117 | static struct cifs_ses * | ||
118 | smb2_find_smb_ses(struct smb2_hdr *smb2hdr, struct TCP_Server_Info *server) | ||
119 | { | ||
120 | struct cifs_ses *ses; | ||
121 | |||
122 | spin_lock(&cifs_tcp_ses_lock); | ||
123 | list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { | ||
124 | if (ses->Suid != smb2hdr->SessionId) | ||
125 | continue; | ||
126 | spin_unlock(&cifs_tcp_ses_lock); | ||
127 | return ses; | ||
128 | } | ||
129 | spin_unlock(&cifs_tcp_ses_lock); | ||
130 | |||
131 | return NULL; | ||
132 | } | ||
133 | |||
117 | 134 | ||
118 | int | 135 | int |
119 | smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | 136 | smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) |
@@ -124,6 +141,13 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
124 | struct kvec *iov = rqst->rq_iov; | 141 | struct kvec *iov = rqst->rq_iov; |
125 | int n_vec = rqst->rq_nvec; | 142 | int n_vec = rqst->rq_nvec; |
126 | struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; | 143 | struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; |
144 | struct cifs_ses *ses; | ||
145 | |||
146 | ses = smb2_find_smb_ses(smb2_pdu, server); | ||
147 | if (!ses) { | ||
148 | cifs_dbg(VFS, "%s: Could not find session\n", __func__); | ||
149 | return 0; | ||
150 | } | ||
127 | 151 | ||
128 | memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE); | 152 | memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE); |
129 | memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE); | 153 | memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE); |
@@ -135,7 +159,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
135 | } | 159 | } |
136 | 160 | ||
137 | rc = crypto_shash_setkey(server->secmech.hmacsha256, | 161 | rc = crypto_shash_setkey(server->secmech.hmacsha256, |
138 | server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE); | 162 | ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE); |
139 | if (rc) { | 163 | if (rc) { |
140 | cifs_dbg(VFS, "%s: Could not update with response\n", __func__); | 164 | cifs_dbg(VFS, "%s: Could not update with response\n", __func__); |
141 | return rc; | 165 | return rc; |
@@ -198,8 +222,8 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
198 | return rc; | 222 | return rc; |
199 | } | 223 | } |
200 | 224 | ||
201 | void | 225 | int |
202 | generate_smb3signingkey(struct TCP_Server_Info *server) | 226 | generate_smb3signingkey(struct cifs_ses *ses) |
203 | { | 227 | { |
204 | unsigned char zero = 0x0; | 228 | unsigned char zero = 0x0; |
205 | __u8 i[4] = {0, 0, 0, 1}; | 229 | __u8 i[4] = {0, 0, 0, 1}; |
@@ -209,90 +233,99 @@ generate_smb3signingkey(struct TCP_Server_Info *server) | |||
209 | unsigned char *hashptr = prfhash; | 233 | unsigned char *hashptr = prfhash; |
210 | 234 | ||
211 | memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE); | 235 | memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE); |
212 | memset(server->smb3signingkey, 0x0, SMB3_SIGNKEY_SIZE); | 236 | memset(ses->smb3signingkey, 0x0, SMB3_SIGNKEY_SIZE); |
213 | 237 | ||
214 | rc = smb3_crypto_shash_allocate(server); | 238 | rc = smb3_crypto_shash_allocate(ses->server); |
215 | if (rc) { | 239 | if (rc) { |
216 | cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__); | 240 | cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__); |
217 | goto smb3signkey_ret; | 241 | goto smb3signkey_ret; |
218 | } | 242 | } |
219 | 243 | ||
220 | rc = crypto_shash_setkey(server->secmech.hmacsha256, | 244 | rc = crypto_shash_setkey(ses->server->secmech.hmacsha256, |
221 | server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE); | 245 | ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE); |
222 | if (rc) { | 246 | if (rc) { |
223 | cifs_dbg(VFS, "%s: Could not set with session key\n", __func__); | 247 | cifs_dbg(VFS, "%s: Could not set with session key\n", __func__); |
224 | goto smb3signkey_ret; | 248 | goto smb3signkey_ret; |
225 | } | 249 | } |
226 | 250 | ||
227 | rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash); | 251 | rc = crypto_shash_init(&ses->server->secmech.sdeschmacsha256->shash); |
228 | if (rc) { | 252 | if (rc) { |
229 | cifs_dbg(VFS, "%s: Could not init sign hmac\n", __func__); | 253 | cifs_dbg(VFS, "%s: Could not init sign hmac\n", __func__); |
230 | goto smb3signkey_ret; | 254 | goto smb3signkey_ret; |
231 | } | 255 | } |
232 | 256 | ||
233 | rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, | 257 | rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, |
234 | i, 4); | 258 | i, 4); |
235 | if (rc) { | 259 | if (rc) { |
236 | cifs_dbg(VFS, "%s: Could not update with n\n", __func__); | 260 | cifs_dbg(VFS, "%s: Could not update with n\n", __func__); |
237 | goto smb3signkey_ret; | 261 | goto smb3signkey_ret; |
238 | } | 262 | } |
239 | 263 | ||
240 | rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, | 264 | rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, |
241 | "SMB2AESCMAC", 12); | 265 | "SMB2AESCMAC", 12); |
242 | if (rc) { | 266 | if (rc) { |
243 | cifs_dbg(VFS, "%s: Could not update with label\n", __func__); | 267 | cifs_dbg(VFS, "%s: Could not update with label\n", __func__); |
244 | goto smb3signkey_ret; | 268 | goto smb3signkey_ret; |
245 | } | 269 | } |
246 | 270 | ||
247 | rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, | 271 | rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, |
248 | &zero, 1); | 272 | &zero, 1); |
249 | if (rc) { | 273 | if (rc) { |
250 | cifs_dbg(VFS, "%s: Could not update with zero\n", __func__); | 274 | cifs_dbg(VFS, "%s: Could not update with zero\n", __func__); |
251 | goto smb3signkey_ret; | 275 | goto smb3signkey_ret; |
252 | } | 276 | } |
253 | 277 | ||
254 | rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, | 278 | rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, |
255 | "SmbSign", 8); | 279 | "SmbSign", 8); |
256 | if (rc) { | 280 | if (rc) { |
257 | cifs_dbg(VFS, "%s: Could not update with context\n", __func__); | 281 | cifs_dbg(VFS, "%s: Could not update with context\n", __func__); |
258 | goto smb3signkey_ret; | 282 | goto smb3signkey_ret; |
259 | } | 283 | } |
260 | 284 | ||
261 | rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, | 285 | rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, |
262 | L, 4); | 286 | L, 4); |
263 | if (rc) { | 287 | if (rc) { |
264 | cifs_dbg(VFS, "%s: Could not update with L\n", __func__); | 288 | cifs_dbg(VFS, "%s: Could not update with L\n", __func__); |
265 | goto smb3signkey_ret; | 289 | goto smb3signkey_ret; |
266 | } | 290 | } |
267 | 291 | ||
268 | rc = crypto_shash_final(&server->secmech.sdeschmacsha256->shash, | 292 | rc = crypto_shash_final(&ses->server->secmech.sdeschmacsha256->shash, |
269 | hashptr); | 293 | hashptr); |
270 | if (rc) { | 294 | if (rc) { |
271 | cifs_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__); | 295 | cifs_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__); |
272 | goto smb3signkey_ret; | 296 | goto smb3signkey_ret; |
273 | } | 297 | } |
274 | 298 | ||
275 | memcpy(server->smb3signingkey, hashptr, SMB3_SIGNKEY_SIZE); | 299 | memcpy(ses->smb3signingkey, hashptr, SMB3_SIGNKEY_SIZE); |
276 | 300 | ||
277 | smb3signkey_ret: | 301 | smb3signkey_ret: |
278 | return; | 302 | return rc; |
279 | } | 303 | } |
280 | 304 | ||
281 | int | 305 | int |
282 | smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | 306 | smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) |
283 | { | 307 | { |
284 | int i, rc; | 308 | int i; |
309 | int rc = 0; | ||
285 | unsigned char smb3_signature[SMB2_CMACAES_SIZE]; | 310 | unsigned char smb3_signature[SMB2_CMACAES_SIZE]; |
286 | unsigned char *sigptr = smb3_signature; | 311 | unsigned char *sigptr = smb3_signature; |
287 | struct kvec *iov = rqst->rq_iov; | 312 | struct kvec *iov = rqst->rq_iov; |
288 | int n_vec = rqst->rq_nvec; | 313 | int n_vec = rqst->rq_nvec; |
289 | struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; | 314 | struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; |
315 | struct cifs_ses *ses; | ||
316 | |||
317 | ses = smb2_find_smb_ses(smb2_pdu, server); | ||
318 | if (!ses) { | ||
319 | cifs_dbg(VFS, "%s: Could not find session\n", __func__); | ||
320 | return 0; | ||
321 | } | ||
290 | 322 | ||
291 | memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE); | 323 | memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE); |
292 | memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE); | 324 | memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE); |
293 | 325 | ||
294 | rc = crypto_shash_setkey(server->secmech.cmacaes, | 326 | rc = crypto_shash_setkey(server->secmech.cmacaes, |
295 | server->smb3signingkey, SMB2_CMACAES_SIZE); | 327 | ses->smb3signingkey, SMB2_CMACAES_SIZE); |
328 | |||
296 | if (rc) { | 329 | if (rc) { |
297 | cifs_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__); | 330 | cifs_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__); |
298 | return rc; | 331 | return rc; |
@@ -389,6 +422,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
389 | struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)rqst->rq_iov[0].iov_base; | 422 | struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)rqst->rq_iov[0].iov_base; |
390 | 423 | ||
391 | if ((smb2_pdu->Command == SMB2_NEGOTIATE) || | 424 | if ((smb2_pdu->Command == SMB2_NEGOTIATE) || |
425 | (smb2_pdu->Command == SMB2_SESSION_SETUP) || | ||
392 | (smb2_pdu->Command == SMB2_OPLOCK_BREAK) || | 426 | (smb2_pdu->Command == SMB2_OPLOCK_BREAK) || |
393 | (!server->session_estab)) | 427 | (!server->session_estab)) |
394 | return 0; | 428 | return 0; |