diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 92 |
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 | ||
370 | static int | 370 | static int |
371 | decode_ext_sec_blob(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr) | 371 | decode_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 |
464 | static int | 451 | static int |
465 | decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr, | 452 | decode_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 |
544 | static inline int | 524 | static inline int |
545 | decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr, | 525 | decode_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 | ||
553 | static bool | 532 | static bool |
554 | should_set_ext_sec_flag(unsigned int secFlags) | 533 | should_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 | ||
567 | int | 549 | int |
@@ -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 { |