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>

+106
+1
fs/cifs/cifsglob.h
··· 676 676 unsigned int max_read; 677 677 unsigned int max_write; 678 678 #ifdef CONFIG_CIFS_SMB311 679 + __le16 cipher_type; 679 680 /* save initital negprot hash */ 680 681 __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE]; 681 682 #endif /* 3.1.1 */
+102
fs/cifs/smb2pdu.c
··· 406 406 *total_len += 4 + sizeof(struct smb2_preauth_neg_context) 407 407 + sizeof(struct smb2_encryption_neg_context); 408 408 } 409 + 410 + static 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 + 425 + static 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 + 450 + static 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 502 #else 410 503 static void assemble_neg_contexts(struct smb2_negotiate_req *req, 411 504 unsigned int *total_len) ··· 712 619 else if (rc == 0) 713 620 rc = -EIO; 714 621 } 622 + 623 + #ifdef CONFIG_CIFS_SMB311 624 + if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) { 625 + if (rsp->NegotiateContextCount) 626 + rc = smb311_decode_neg_context(rsp, server); 627 + else 628 + cifs_dbg(VFS, "Missing expected negotiate contexts\n"); 629 + } 630 + #endif /* CONFIG_CIFS_SMB311 */ 715 631 neg_exit: 716 632 free_rsp_buf(resp_buftype, rsp); 717 633 return rc;
+3
fs/cifs/smb2pdu.h
··· 275 275 #define SMB2_PREAUTH_INTEGRITY_SHA512 cpu_to_le16(0x0001) 276 276 #define SMB2_PREAUTH_HASH_SIZE 64 277 277 278 + #define MIN_PREAUTH_CTXT_DATA_LEN (SMB311_SALT_SIZE + 6) 278 279 struct smb2_preauth_neg_context { 279 280 __le16 ContextType; /* 1 */ 280 281 __le16 DataLength; ··· 290 289 #define SMB2_ENCRYPTION_AES128_CCM cpu_to_le16(0x0001) 291 290 #define SMB2_ENCRYPTION_AES128_GCM cpu_to_le16(0x0002) 292 291 292 + /* Min encrypt context data is one cipher so 2 bytes + 2 byte count field */ 293 + #define MIN_ENCRYPT_CTXT_DATA_LEN 4 293 294 struct smb2_encryption_neg_context { 294 295 __le16 ContextType; /* 2 */ 295 296 __le16 DataLength;