aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c92
1 files changed, 20 insertions, 72 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index dd7e2f61f607..a35aad2060c5 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -368,11 +368,12 @@ vt2_err:
368} 368}
369 369
370static int 370static int
371decode_ext_sec_blob(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr) 371decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
372{ 372{
373 int rc = 0; 373 int rc = 0;
374 u16 count; 374 u16 count;
375 char *guid = pSMBr->u.extended_response.GUID; 375 char *guid = pSMBr->u.extended_response.GUID;
376 struct TCP_Server_Info *server = ses->server;
376 377
377 count = get_bcc(&pSMBr->hdr); 378 count = get_bcc(&pSMBr->hdr);
378 if (count < SMB1_CLIENT_GUID_SIZE) 379 if (count < SMB1_CLIENT_GUID_SIZE)
@@ -391,27 +392,13 @@ decode_ext_sec_blob(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
391 } 392 }
392 393
393 if (count == SMB1_CLIENT_GUID_SIZE) { 394 if (count == SMB1_CLIENT_GUID_SIZE) {
394 server->secType = RawNTLMSSP; 395 server->sec_ntlmssp = true;
395 } else { 396 } else {
396 count -= SMB1_CLIENT_GUID_SIZE; 397 count -= SMB1_CLIENT_GUID_SIZE;
397 rc = decode_negTokenInit( 398 rc = decode_negTokenInit(
398 pSMBr->u.extended_response.SecurityBlob, count, server); 399 pSMBr->u.extended_response.SecurityBlob, count, server);
399 if (rc != 1) 400 if (rc != 1)
400 return -EINVAL; 401 return -EINVAL;
401
402 /* Make sure server supports what we want to use */
403 switch(server->secType) {
404 case Kerberos:
405 if (!server->sec_kerberos && !server->sec_mskerberos)
406 return -EOPNOTSUPP;
407 break;
408 case RawNTLMSSP:
409 if (!server->sec_ntlmssp)
410 return -EOPNOTSUPP;
411 break;
412 default:
413 return -EOPNOTSUPP;
414 }
415 } 402 }
416 403
417 return 0; 404 return 0;
@@ -462,8 +449,7 @@ cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
462 449
463#ifdef CONFIG_CIFS_WEAK_PW_HASH 450#ifdef CONFIG_CIFS_WEAK_PW_HASH
464static int 451static int
465decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr, 452decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
466 unsigned int secFlags)
467{ 453{
468 __s16 tmp; 454 __s16 tmp;
469 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr; 455 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
@@ -471,12 +457,6 @@ decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr,
471 if (server->dialect != LANMAN_PROT && server->dialect != LANMAN2_PROT) 457 if (server->dialect != LANMAN_PROT && server->dialect != LANMAN2_PROT)
472 return -EOPNOTSUPP; 458 return -EOPNOTSUPP;
473 459
474 if ((secFlags & CIFSSEC_MAY_LANMAN) || (secFlags & CIFSSEC_MAY_PLNTXT))
475 server->secType = LANMAN;
476 else {
477 cifs_dbg(VFS, "mount failed weak security disabled in /proc/fs/cifs/SecurityFlags\n");
478 return -EOPNOTSUPP;
479 }
480 server->sec_mode = le16_to_cpu(rsp->SecurityMode); 460 server->sec_mode = le16_to_cpu(rsp->SecurityMode);
481 server->maxReq = min_t(unsigned int, 461 server->maxReq = min_t(unsigned int,
482 le16_to_cpu(rsp->MaxMpxCount), 462 le16_to_cpu(rsp->MaxMpxCount),
@@ -542,8 +522,7 @@ decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr,
542} 522}
543#else 523#else
544static inline int 524static inline int
545decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr, 525decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
546 unsigned int secFlags)
547{ 526{
548 cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n"); 527 cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n");
549 return -EOPNOTSUPP; 528 return -EOPNOTSUPP;
@@ -551,17 +530,20 @@ decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr,
551#endif 530#endif
552 531
553static bool 532static bool
554should_set_ext_sec_flag(unsigned int secFlags) 533should_set_ext_sec_flag(enum securityEnum sectype)
555{ 534{
556 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) 535 switch (sectype) {
557 return true; 536 case RawNTLMSSP:
558 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) 537 case Kerberos:
559 return true;
560 else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
561 return true;
562 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP)
563 return true; 538 return true;
564 return false; 539 case Unspecified:
540 if (global_secflags &
541 (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
542 return true;
543 /* Fallthrough */
544 default:
545 return false;
546 }
565} 547}
566 548
567int 549int
@@ -574,7 +556,6 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
574 int i; 556 int i;
575 struct TCP_Server_Info *server = ses->server; 557 struct TCP_Server_Info *server = ses->server;
576 u16 count; 558 u16 count;
577 unsigned int secFlags;
578 559
579 if (!server) { 560 if (!server) {
580 WARN(1, "%s: server is NULL!\n", __func__); 561 WARN(1, "%s: server is NULL!\n", __func__);
@@ -586,18 +567,10 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
586 if (rc) 567 if (rc)
587 return rc; 568 return rc;
588 569
589 /* if any of auth flags (ie not sign or seal) are overriden use them */
590 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
591 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
592 else /* if override flags set only sign/seal OR them with global auth */
593 secFlags = global_secflags | ses->overrideSecFlg;
594
595 cifs_dbg(FYI, "secFlags 0x%x\n", secFlags);
596
597 pSMB->hdr.Mid = get_next_mid(server); 570 pSMB->hdr.Mid = get_next_mid(server);
598 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); 571 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
599 572
600 if (should_set_ext_sec_flag(secFlags)) { 573 if (should_set_ext_sec_flag(ses->sectype)) {
601 cifs_dbg(FYI, "Requesting extended security."); 574 cifs_dbg(FYI, "Requesting extended security.");
602 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 575 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
603 } 576 }
@@ -627,7 +600,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
627 goto neg_err_exit; 600 goto neg_err_exit;
628 } else if (pSMBr->hdr.WordCount == 13) { 601 } else if (pSMBr->hdr.WordCount == 13) {
629 server->negflavor = CIFS_NEGFLAVOR_LANMAN; 602 server->negflavor = CIFS_NEGFLAVOR_LANMAN;
630 rc = decode_lanman_negprot_rsp(server, pSMBr, secFlags); 603 rc = decode_lanman_negprot_rsp(server, pSMBr);
631 goto signing_check; 604 goto signing_check;
632 } else if (pSMBr->hdr.WordCount != 17) { 605 } else if (pSMBr->hdr.WordCount != 17) {
633 /* unknown wct */ 606 /* unknown wct */
@@ -640,31 +613,6 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
640 if ((server->sec_mode & SECMODE_USER) == 0) 613 if ((server->sec_mode & SECMODE_USER) == 0)
641 cifs_dbg(FYI, "share mode security\n"); 614 cifs_dbg(FYI, "share mode security\n");
642 615
643 if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0)
644#ifdef CONFIG_CIFS_WEAK_PW_HASH
645 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
646#endif /* CIFS_WEAK_PW_HASH */
647 cifs_dbg(VFS, "Server requests plain text password but client support disabled\n");
648
649 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
650 server->secType = NTLMv2;
651 else if (secFlags & CIFSSEC_MAY_NTLM)
652 server->secType = NTLM;
653 else if (secFlags & CIFSSEC_MAY_NTLMV2)
654 server->secType = NTLMv2;
655 else if (secFlags & CIFSSEC_MAY_KRB5)
656 server->secType = Kerberos;
657 else if (secFlags & CIFSSEC_MAY_NTLMSSP)
658 server->secType = RawNTLMSSP;
659 else if (secFlags & CIFSSEC_MAY_LANMAN)
660 server->secType = LANMAN;
661 else {
662 rc = -EOPNOTSUPP;
663 cifs_dbg(VFS, "Invalid security type\n");
664 goto neg_err_exit;
665 }
666 /* else ... any others ...? */
667
668 /* one byte, so no need to convert this or EncryptionKeyLen from 616 /* one byte, so no need to convert this or EncryptionKeyLen from
669 little endian */ 617 little endian */
670 server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount), 618 server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
@@ -686,7 +634,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
686 server->capabilities & CAP_EXTENDED_SECURITY) && 634 server->capabilities & CAP_EXTENDED_SECURITY) &&
687 (pSMBr->EncryptionKeyLength == 0)) { 635 (pSMBr->EncryptionKeyLength == 0)) {
688 server->negflavor = CIFS_NEGFLAVOR_EXTENDED; 636 server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
689 rc = decode_ext_sec_blob(server, pSMBr); 637 rc = decode_ext_sec_blob(ses, pSMBr);
690 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) { 638 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
691 rc = -EIO; /* no crypt key only if plain text pwd */ 639 rc = -EIO; /* no crypt key only if plain text pwd */
692 } else { 640 } else {