aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <smfrench@gmail.com>2018-04-09 11:47:14 -0400
committerSteve French <smfrench@gmail.com>2018-04-12 17:54:06 -0400
commit5100d8a3fe034845926266a4e7f5bdcbb859088b (patch)
tree350de14c3b16b0657664b18e4c045a96a4f574c6
parent136ff1b4b65edf09b6b7173ba94ad53347d3aa83 (diff)
SMB311: Improve checking of negotiate security contexts
SMB3.11 crypto and hash contexts were not being checked strictly enough. Add parsing and validity checking for the security contexts in the SMB3.11 negotiate response. Signed-off-by: Steve French <smfrench@gmail.com> CC: Stable <stable@vger.kernel.org> Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
-rw-r--r--fs/cifs/cifsglob.h1
-rw-r--r--fs/cifs/smb2pdu.c102
-rw-r--r--fs/cifs/smb2pdu.h3
3 files changed, 106 insertions, 0 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 2282562e78a1..56fee0330afc 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -676,6 +676,7 @@ struct TCP_Server_Info {
676 unsigned int max_read; 676 unsigned int max_read;
677 unsigned int max_write; 677 unsigned int max_write;
678#ifdef CONFIG_CIFS_SMB311 678#ifdef CONFIG_CIFS_SMB311
679 __le16 cipher_type;
679 /* save initital negprot hash */ 680 /* save initital negprot hash */
680 __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE]; 681 __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
681#endif /* 3.1.1 */ 682#endif /* 3.1.1 */
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 6c2910e6c984..e01be06d588e 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -406,6 +406,99 @@ assemble_neg_contexts(struct smb2_negotiate_req *req,
406 *total_len += 4 + sizeof(struct smb2_preauth_neg_context) 406 *total_len += 4 + sizeof(struct smb2_preauth_neg_context)
407 + sizeof(struct smb2_encryption_neg_context); 407 + sizeof(struct smb2_encryption_neg_context);
408} 408}
409
410static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt)
411{
412 unsigned int len = le16_to_cpu(ctxt->DataLength);
413
414 /* If invalid preauth context warn but use what we requested, SHA-512 */
415 if (len < MIN_PREAUTH_CTXT_DATA_LEN) {
416 printk_once(KERN_WARNING "server sent bad preauth context\n");
417 return;
418 }
419 if (le16_to_cpu(ctxt->HashAlgorithmCount) != 1)
420 printk_once(KERN_WARNING "illegal SMB3 hash algorithm count\n");
421 if (ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512)
422 printk_once(KERN_WARNING "unknown SMB3 hash algorithm\n");
423}
424
425static int decode_encrypt_ctx(struct TCP_Server_Info *server,
426 struct smb2_encryption_neg_context *ctxt)
427{
428 unsigned int len = le16_to_cpu(ctxt->DataLength);
429
430 cifs_dbg(FYI, "decode SMB3.11 encryption neg context of len %d\n", len);
431 if (len < MIN_ENCRYPT_CTXT_DATA_LEN) {
432 printk_once(KERN_WARNING "server sent bad crypto ctxt len\n");
433 return -EINVAL;
434 }
435
436 if (le16_to_cpu(ctxt->CipherCount) != 1) {
437 printk_once(KERN_WARNING "illegal SMB3.11 cipher count\n");
438 return -EINVAL;
439 }
440 cifs_dbg(FYI, "SMB311 cipher type:%d\n", le16_to_cpu(ctxt->Ciphers[0]));
441 if ((ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_CCM) &&
442 (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_GCM)) {
443 printk_once(KERN_WARNING "invalid SMB3.11 cipher returned\n");
444 return -EINVAL;
445 }
446 server->cipher_type = ctxt->Ciphers[0];
447 return 0;
448}
449
450static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
451 struct TCP_Server_Info *server)
452{
453 struct smb2_neg_context *pctx;
454 unsigned int offset = le32_to_cpu(rsp->NegotiateContextOffset);
455 unsigned int ctxt_cnt = le16_to_cpu(rsp->NegotiateContextCount);
456 unsigned int len_of_smb = be32_to_cpu(rsp->hdr.smb2_buf_length);
457 unsigned int len_of_ctxts, i;
458 int rc = 0;
459
460 cifs_dbg(FYI, "decoding %d negotiate contexts\n", ctxt_cnt);
461 if (len_of_smb <= offset) {
462 cifs_dbg(VFS, "Invalid response: negotiate context offset\n");
463 return -EINVAL;
464 }
465
466 len_of_ctxts = len_of_smb - offset;
467
468 for (i = 0; i < ctxt_cnt; i++) {
469 int clen;
470 /* check that offset is not beyond end of SMB */
471 if (len_of_ctxts == 0)
472 break;
473
474 if (len_of_ctxts < sizeof(struct smb2_neg_context))
475 break;
476
477 pctx = (struct smb2_neg_context *)(offset + 4 + (char *)rsp);
478 clen = le16_to_cpu(pctx->DataLength);
479 if (clen > len_of_ctxts)
480 break;
481
482 if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES)
483 decode_preauth_context(
484 (struct smb2_preauth_neg_context *)pctx);
485 else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES)
486 rc = decode_encrypt_ctx(server,
487 (struct smb2_encryption_neg_context *)pctx);
488 else
489 cifs_dbg(VFS, "unknown negcontext of type %d ignored\n",
490 le16_to_cpu(pctx->ContextType));
491
492 if (rc)
493 break;
494 /* offsets must be 8 byte aligned */
495 clen = (clen + 7) & ~0x7;
496 offset += clen + sizeof(struct smb2_neg_context);
497 len_of_ctxts -= clen;
498 }
499 return rc;
500}
501
409#else 502#else
410static void assemble_neg_contexts(struct smb2_negotiate_req *req, 503static void assemble_neg_contexts(struct smb2_negotiate_req *req,
411 unsigned int *total_len) 504 unsigned int *total_len)
@@ -619,6 +712,15 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
619 else if (rc == 0) 712 else if (rc == 0)
620 rc = -EIO; 713 rc = -EIO;
621 } 714 }
715
716#ifdef CONFIG_CIFS_SMB311
717 if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) {
718 if (rsp->NegotiateContextCount)
719 rc = smb311_decode_neg_context(rsp, server);
720 else
721 cifs_dbg(VFS, "Missing expected negotiate contexts\n");
722 }
723#endif /* CONFIG_CIFS_SMB311 */
622neg_exit: 724neg_exit:
623 free_rsp_buf(resp_buftype, rsp); 725 free_rsp_buf(resp_buftype, rsp);
624 return rc; 726 return rc;
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 0e0a0af89e4d..6093e5142b2b 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -275,6 +275,7 @@ struct smb2_neg_context {
275#define SMB2_PREAUTH_INTEGRITY_SHA512 cpu_to_le16(0x0001) 275#define SMB2_PREAUTH_INTEGRITY_SHA512 cpu_to_le16(0x0001)
276#define SMB2_PREAUTH_HASH_SIZE 64 276#define SMB2_PREAUTH_HASH_SIZE 64
277 277
278#define MIN_PREAUTH_CTXT_DATA_LEN (SMB311_SALT_SIZE + 6)
278struct smb2_preauth_neg_context { 279struct smb2_preauth_neg_context {
279 __le16 ContextType; /* 1 */ 280 __le16 ContextType; /* 1 */
280 __le16 DataLength; 281 __le16 DataLength;
@@ -289,6 +290,8 @@ struct smb2_preauth_neg_context {
289#define SMB2_ENCRYPTION_AES128_CCM cpu_to_le16(0x0001) 290#define SMB2_ENCRYPTION_AES128_CCM cpu_to_le16(0x0001)
290#define SMB2_ENCRYPTION_AES128_GCM cpu_to_le16(0x0002) 291#define SMB2_ENCRYPTION_AES128_GCM cpu_to_le16(0x0002)
291 292
293/* Min encrypt context data is one cipher so 2 bytes + 2 byte count field */
294#define MIN_ENCRYPT_CTXT_DATA_LEN 4
292struct smb2_encryption_neg_context { 295struct smb2_encryption_neg_context {
293 __le16 ContextType; /* 2 */ 296 __le16 ContextType; /* 2 */
294 __le16 DataLength; 297 __le16 DataLength;