diff options
author | Jeff Layton <jlayton@redhat.com> | 2013-06-12 20:52:14 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2013-06-24 02:56:44 -0400 |
commit | 3f618223dc0bdcbc8d510350e78ee2195ff93768 (patch) | |
tree | 07b910ab18112557f897f2192d073f97553e1055 /fs | |
parent | 38d77c50b4f4e3ea1687e119871364f1c8d2f531 (diff) |
move sectype to the cifs_ses instead of TCP_Server_Info
Now that we track what sort of NEGOTIATE response was received, stop
mandating that every session on a socket use the same type of auth.
Push that decision out into the session setup code, and make the sectype
a per-session property. This should allow us to mix multiple sectypes on
a socket as long as they are compatible with the NEGOTIATE response.
With this too, we can now eliminate the ses->secFlg field since that
info is redundant and harder to work with than a securityEnum.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Acked-by: Pavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifsencrypt.c | 4 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 92 | ||||
-rw-r--r-- | fs/cifs/connect.c | 117 | ||||
-rw-r--r-- | fs/cifs/sess.c | 57 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 21 |
7 files changed, 115 insertions, 180 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index a85a83d1d00f..30bea6bd3023 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c | |||
@@ -535,7 +535,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash) | |||
535 | return rc; | 535 | return rc; |
536 | } | 536 | } |
537 | 537 | ||
538 | if (ses->server->secType == RawNTLMSSP) | 538 | if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) |
539 | memcpy(ses->auth_key.response + offset, | 539 | memcpy(ses->auth_key.response + offset, |
540 | ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); | 540 | ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); |
541 | else | 541 | else |
@@ -567,7 +567,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) | |||
567 | char ntlmv2_hash[16]; | 567 | char ntlmv2_hash[16]; |
568 | unsigned char *tiblob = NULL; /* target info blob */ | 568 | unsigned char *tiblob = NULL; /* target info blob */ |
569 | 569 | ||
570 | if (ses->server->secType == RawNTLMSSP) { | 570 | if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) { |
571 | if (!ses->domainName) { | 571 | if (!ses->domainName) { |
572 | rc = find_domain_name(ses, nls_cp); | 572 | rc = find_domain_name(ses, nls_cp); |
573 | if (rc) { | 573 | if (rc) { |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 49020ae460cf..ad3408042ff0 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -401,7 +401,6 @@ struct smb_vol { | |||
401 | kgid_t backupgid; | 401 | kgid_t backupgid; |
402 | umode_t file_mode; | 402 | umode_t file_mode; |
403 | umode_t dir_mode; | 403 | umode_t dir_mode; |
404 | unsigned secFlg; | ||
405 | enum securityEnum sectype; /* sectype requested via mnt opts */ | 404 | enum securityEnum sectype; /* sectype requested via mnt opts */ |
406 | bool sign; /* was signing requested via mnt opts? */ | 405 | bool sign; /* was signing requested via mnt opts? */ |
407 | bool retry:1; | 406 | bool retry:1; |
@@ -519,7 +518,6 @@ struct TCP_Server_Info { | |||
519 | bool echoes:1; /* enable echoes */ | 518 | bool echoes:1; /* enable echoes */ |
520 | #endif | 519 | #endif |
521 | u16 dialect; /* dialect index that server chose */ | 520 | u16 dialect; /* dialect index that server chose */ |
522 | enum securityEnum secType; | ||
523 | bool oplocks:1; /* enable oplocks */ | 521 | bool oplocks:1; /* enable oplocks */ |
524 | unsigned int maxReq; /* Clients should submit no more */ | 522 | unsigned int maxReq; /* Clients should submit no more */ |
525 | /* than maxReq distinct unanswered SMBs to the server when using */ | 523 | /* than maxReq distinct unanswered SMBs to the server when using */ |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index ede010fd046a..a82b3c09888b 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -118,6 +118,8 @@ extern void header_assemble(struct smb_hdr *, char /* command */ , | |||
118 | extern int small_smb_init_no_tc(const int smb_cmd, const int wct, | 118 | extern int small_smb_init_no_tc(const int smb_cmd, const int wct, |
119 | struct cifs_ses *ses, | 119 | struct cifs_ses *ses, |
120 | void **request_buf); | 120 | void **request_buf); |
121 | extern enum securityEnum select_sectype(struct TCP_Server_Info *server, | ||
122 | enum securityEnum requested); | ||
121 | extern int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, | 123 | extern int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, |
122 | const struct nls_table *nls_cp); | 124 | const struct nls_table *nls_cp); |
123 | extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); | 125 | extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); |
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 { |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index acbb255352af..c4c6aa99ee1c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -1033,56 +1033,40 @@ static int cifs_parse_security_flavors(char *value, | |||
1033 | vol->sign = false; | 1033 | vol->sign = false; |
1034 | 1034 | ||
1035 | switch (match_token(value, cifs_secflavor_tokens, args)) { | 1035 | switch (match_token(value, cifs_secflavor_tokens, args)) { |
1036 | case Opt_sec_krb5p: | ||
1037 | cifs_dbg(VFS, "sec=krb5p is not supported!\n"); | ||
1038 | return 1; | ||
1039 | case Opt_sec_krb5i: | ||
1040 | vol->sign = true; | ||
1041 | /* Fallthrough */ | ||
1036 | case Opt_sec_krb5: | 1042 | case Opt_sec_krb5: |
1037 | vol->sectype = Kerberos; | 1043 | vol->sectype = Kerberos; |
1038 | vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_SIGN; | ||
1039 | break; | 1044 | break; |
1040 | case Opt_sec_krb5i: | 1045 | case Opt_sec_ntlmsspi: |
1041 | vol->sectype = Kerberos; | ||
1042 | vol->sign = true; | 1046 | vol->sign = true; |
1043 | vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN; | 1047 | /* Fallthrough */ |
1044 | break; | ||
1045 | case Opt_sec_krb5p: | ||
1046 | /* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */ | ||
1047 | cifs_dbg(VFS, "Krb5 cifs privacy not supported\n"); | ||
1048 | break; | ||
1049 | case Opt_sec_ntlmssp: | 1048 | case Opt_sec_ntlmssp: |
1050 | vol->sectype = RawNTLMSSP; | 1049 | vol->sectype = RawNTLMSSP; |
1051 | vol->secFlg |= CIFSSEC_MAY_NTLMSSP; | ||
1052 | break; | 1050 | break; |
1053 | case Opt_sec_ntlmsspi: | 1051 | case Opt_sec_ntlmi: |
1054 | vol->sectype = RawNTLMSSP; | ||
1055 | vol->sign = true; | 1052 | vol->sign = true; |
1056 | vol->secFlg |= CIFSSEC_MAY_NTLMSSP | CIFSSEC_MUST_SIGN; | 1053 | /* Fallthrough */ |
1057 | break; | ||
1058 | case Opt_ntlm: | 1054 | case Opt_ntlm: |
1059 | /* ntlm is default so can be turned off too */ | ||
1060 | vol->sectype = NTLM; | 1055 | vol->sectype = NTLM; |
1061 | vol->secFlg |= CIFSSEC_MAY_NTLM; | ||
1062 | break; | 1056 | break; |
1063 | case Opt_sec_ntlmi: | 1057 | case Opt_sec_ntlmv2i: |
1064 | vol->sectype = NTLM; | ||
1065 | vol->sign = true; | 1058 | vol->sign = true; |
1066 | vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN; | 1059 | /* Fallthrough */ |
1067 | break; | ||
1068 | case Opt_sec_ntlmv2: | 1060 | case Opt_sec_ntlmv2: |
1069 | vol->sectype = NTLMv2; | 1061 | vol->sectype = NTLMv2; |
1070 | vol->secFlg |= CIFSSEC_MAY_NTLMV2; | ||
1071 | break; | ||
1072 | case Opt_sec_ntlmv2i: | ||
1073 | vol->sectype = NTLMv2; | ||
1074 | vol->sign = true; | ||
1075 | vol->secFlg |= CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN; | ||
1076 | break; | 1062 | break; |
1077 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 1063 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
1078 | case Opt_sec_lanman: | 1064 | case Opt_sec_lanman: |
1079 | vol->sectype = LANMAN; | 1065 | vol->sectype = LANMAN; |
1080 | vol->secFlg |= CIFSSEC_MAY_LANMAN; | ||
1081 | break; | 1066 | break; |
1082 | #endif | 1067 | #endif |
1083 | case Opt_sec_none: | 1068 | case Opt_sec_none: |
1084 | vol->nullauth = 1; | 1069 | vol->nullauth = 1; |
1085 | vol->secFlg |= CIFSSEC_MAY_NTLM; | ||
1086 | break; | 1070 | break; |
1087 | default: | 1071 | default: |
1088 | cifs_dbg(VFS, "bad security option: %s\n", value); | 1072 | cifs_dbg(VFS, "bad security option: %s\n", value); |
@@ -1445,7 +1429,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1445 | vol->local_lease = 1; | 1429 | vol->local_lease = 1; |
1446 | break; | 1430 | break; |
1447 | case Opt_sign: | 1431 | case Opt_sign: |
1448 | vol->secFlg |= CIFSSEC_MUST_SIGN; | ||
1449 | vol->sign = true; | 1432 | vol->sign = true; |
1450 | break; | 1433 | break; |
1451 | case Opt_seal: | 1434 | case Opt_seal: |
@@ -2003,40 +1986,19 @@ match_address(struct TCP_Server_Info *server, struct sockaddr *addr, | |||
2003 | static bool | 1986 | static bool |
2004 | match_security(struct TCP_Server_Info *server, struct smb_vol *vol) | 1987 | match_security(struct TCP_Server_Info *server, struct smb_vol *vol) |
2005 | { | 1988 | { |
2006 | unsigned int secFlags; | 1989 | /* |
2007 | 1990 | * The select_sectype function should either return the vol->sectype | |
2008 | if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL))) | 1991 | * that was specified, or "Unspecified" if that sectype was not |
2009 | secFlags = vol->secFlg; | 1992 | * compatible with the given NEGOTIATE request. |
2010 | else | 1993 | */ |
2011 | secFlags = global_secflags | vol->secFlg; | 1994 | if (select_sectype(server, vol->sectype) == Unspecified) |
2012 | |||
2013 | switch (server->secType) { | ||
2014 | case LANMAN: | ||
2015 | if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT))) | ||
2016 | return false; | ||
2017 | break; | ||
2018 | case NTLMv2: | ||
2019 | if (!(secFlags & CIFSSEC_MAY_NTLMV2)) | ||
2020 | return false; | ||
2021 | break; | ||
2022 | case NTLM: | ||
2023 | if (!(secFlags & CIFSSEC_MAY_NTLM)) | ||
2024 | return false; | ||
2025 | break; | ||
2026 | case Kerberos: | ||
2027 | if (!(secFlags & CIFSSEC_MAY_KRB5)) | ||
2028 | return false; | ||
2029 | break; | ||
2030 | case RawNTLMSSP: | ||
2031 | if (!(secFlags & CIFSSEC_MAY_NTLMSSP)) | ||
2032 | return false; | ||
2033 | break; | ||
2034 | default: | ||
2035 | /* shouldn't happen */ | ||
2036 | return false; | 1995 | return false; |
2037 | } | ||
2038 | 1996 | ||
2039 | /* now check if signing mode is acceptable */ | 1997 | /* |
1998 | * Now check if signing mode is acceptable. No need to check | ||
1999 | * global_secflags at this point since if MUST_SIGN is set then | ||
2000 | * the server->sign had better be too. | ||
2001 | */ | ||
2040 | if (vol->sign && !server->sign) | 2002 | if (vol->sign && !server->sign) |
2041 | return false; | 2003 | return false; |
2042 | 2004 | ||
@@ -2239,7 +2201,11 @@ out_err: | |||
2239 | 2201 | ||
2240 | static int match_session(struct cifs_ses *ses, struct smb_vol *vol) | 2202 | static int match_session(struct cifs_ses *ses, struct smb_vol *vol) |
2241 | { | 2203 | { |
2242 | switch (ses->server->secType) { | 2204 | if (vol->sectype != Unspecified && |
2205 | vol->sectype != ses->sectype) | ||
2206 | return 0; | ||
2207 | |||
2208 | switch (ses->sectype) { | ||
2243 | case Kerberos: | 2209 | case Kerberos: |
2244 | if (!uid_eq(vol->cred_uid, ses->cred_uid)) | 2210 | if (!uid_eq(vol->cred_uid, ses->cred_uid)) |
2245 | return 0; | 2211 | return 0; |
@@ -2516,7 +2482,6 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) | |||
2516 | ses->cred_uid = volume_info->cred_uid; | 2482 | ses->cred_uid = volume_info->cred_uid; |
2517 | ses->linux_uid = volume_info->linux_uid; | 2483 | ses->linux_uid = volume_info->linux_uid; |
2518 | 2484 | ||
2519 | ses->overrideSecFlg = volume_info->secFlg; | ||
2520 | ses->sectype = volume_info->sectype; | 2485 | ses->sectype = volume_info->sectype; |
2521 | ses->sign = volume_info->sign; | 2486 | ses->sign = volume_info->sign; |
2522 | 2487 | ||
@@ -3681,7 +3646,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, | |||
3681 | NTLMv2 password here) */ | 3646 | NTLMv2 password here) */ |
3682 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 3647 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
3683 | if ((global_secflags & CIFSSEC_MAY_LANMAN) && | 3648 | if ((global_secflags & CIFSSEC_MAY_LANMAN) && |
3684 | (ses->server->secType == LANMAN)) | 3649 | (ses->sectype == LANMAN)) |
3685 | calc_lanman_hash(tcon->password, ses->server->cryptkey, | 3650 | calc_lanman_hash(tcon->password, ses->server->cryptkey, |
3686 | ses->server->sec_mode & | 3651 | ses->server->sec_mode & |
3687 | SECMODE_PW_ENCRYPT ? true : false, | 3652 | SECMODE_PW_ENCRYPT ? true : false, |
@@ -3893,27 +3858,11 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, | |||
3893 | static int | 3858 | static int |
3894 | cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses) | 3859 | cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses) |
3895 | { | 3860 | { |
3896 | switch (ses->server->secType) { | 3861 | vol->sectype = ses->sectype; |
3897 | case Kerberos: | 3862 | |
3898 | vol->secFlg = CIFSSEC_MUST_KRB5; | 3863 | /* krb5 is special, since we don't need username or pw */ |
3864 | if (vol->sectype == Kerberos) | ||
3899 | return 0; | 3865 | return 0; |
3900 | case NTLMv2: | ||
3901 | vol->secFlg = CIFSSEC_MUST_NTLMV2; | ||
3902 | break; | ||
3903 | case NTLM: | ||
3904 | vol->secFlg = CIFSSEC_MUST_NTLM; | ||
3905 | break; | ||
3906 | case RawNTLMSSP: | ||
3907 | vol->secFlg = CIFSSEC_MUST_NTLMSSP; | ||
3908 | break; | ||
3909 | case LANMAN: | ||
3910 | vol->secFlg = CIFSSEC_MUST_LANMAN; | ||
3911 | break; | ||
3912 | default: | ||
3913 | /* should never happen */ | ||
3914 | vol->secFlg = 0; | ||
3915 | break; | ||
3916 | } | ||
3917 | 3866 | ||
3918 | return cifs_set_cifscreds(vol, ses); | 3867 | return cifs_set_cifscreds(vol, ses); |
3919 | } | 3868 | } |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 82b784a62c16..79358e341fd2 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -550,6 +550,56 @@ setup_ntlmv2_ret: | |||
550 | return rc; | 550 | return rc; |
551 | } | 551 | } |
552 | 552 | ||
553 | enum securityEnum | ||
554 | select_sectype(struct TCP_Server_Info *server, enum securityEnum requested) | ||
555 | { | ||
556 | switch (server->negflavor) { | ||
557 | case CIFS_NEGFLAVOR_EXTENDED: | ||
558 | switch (requested) { | ||
559 | case Kerberos: | ||
560 | case RawNTLMSSP: | ||
561 | return requested; | ||
562 | case Unspecified: | ||
563 | if (server->sec_ntlmssp && | ||
564 | (global_secflags & CIFSSEC_MAY_NTLMSSP)) | ||
565 | return RawNTLMSSP; | ||
566 | if ((server->sec_kerberos || server->sec_mskerberos) && | ||
567 | (global_secflags & CIFSSEC_MAY_KRB5)) | ||
568 | return Kerberos; | ||
569 | /* Fallthrough */ | ||
570 | default: | ||
571 | return Unspecified; | ||
572 | } | ||
573 | case CIFS_NEGFLAVOR_UNENCAP: | ||
574 | switch (requested) { | ||
575 | case NTLM: | ||
576 | case NTLMv2: | ||
577 | return requested; | ||
578 | case Unspecified: | ||
579 | if (global_secflags & CIFSSEC_MAY_NTLMV2) | ||
580 | return NTLMv2; | ||
581 | if (global_secflags & CIFSSEC_MAY_NTLM) | ||
582 | return NTLM; | ||
583 | /* Fallthrough */ | ||
584 | default: | ||
585 | return Unspecified; | ||
586 | } | ||
587 | case CIFS_NEGFLAVOR_LANMAN: | ||
588 | switch (requested) { | ||
589 | case LANMAN: | ||
590 | return requested; | ||
591 | case Unspecified: | ||
592 | if (global_secflags & CIFSSEC_MAY_LANMAN) | ||
593 | return LANMAN; | ||
594 | /* Fallthrough */ | ||
595 | default: | ||
596 | return Unspecified; | ||
597 | } | ||
598 | default: | ||
599 | return Unspecified; | ||
600 | } | ||
601 | } | ||
602 | |||
553 | int | 603 | int |
554 | CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, | 604 | CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, |
555 | const struct nls_table *nls_cp) | 605 | const struct nls_table *nls_cp) |
@@ -576,8 +626,13 @@ CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, | |||
576 | return -EINVAL; | 626 | return -EINVAL; |
577 | } | 627 | } |
578 | 628 | ||
579 | type = ses->server->secType; | 629 | type = select_sectype(ses->server, ses->sectype); |
580 | cifs_dbg(FYI, "sess setup type %d\n", type); | 630 | cifs_dbg(FYI, "sess setup type %d\n", type); |
631 | if (type == Unspecified) { | ||
632 | cifs_dbg(VFS, "Unable to select appropriate authentication method!"); | ||
633 | return -EINVAL; | ||
634 | } | ||
635 | |||
581 | if (type == RawNTLMSSP) { | 636 | if (type == RawNTLMSSP) { |
582 | /* if memory allocation is successful, caller of this function | 637 | /* if memory allocation is successful, caller of this function |
583 | * frees it. | 638 | * frees it. |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index ad8ef10de0bd..fd2ea4271282 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -328,7 +328,6 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
328 | int rc = 0; | 328 | int rc = 0; |
329 | int resp_buftype; | 329 | int resp_buftype; |
330 | struct TCP_Server_Info *server = ses->server; | 330 | struct TCP_Server_Info *server = ses->server; |
331 | unsigned int sec_flags; | ||
332 | int blob_offset, blob_length; | 331 | int blob_offset, blob_length; |
333 | char *security_blob; | 332 | char *security_blob; |
334 | int flags = CIFS_NEG_OP; | 333 | int flags = CIFS_NEG_OP; |
@@ -344,14 +343,6 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
344 | if (rc) | 343 | if (rc) |
345 | return rc; | 344 | return rc; |
346 | 345 | ||
347 | /* if any of auth flags (ie not sign or seal) are overriden use them */ | ||
348 | if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL))) | ||
349 | sec_flags = ses->overrideSecFlg; /* BB FIXME fix sign flags?*/ | ||
350 | else /* if override flags set only sign/seal OR them with global auth */ | ||
351 | sec_flags = global_secflags | ses->overrideSecFlg; | ||
352 | |||
353 | cifs_dbg(FYI, "sec_flags 0x%x\n", sec_flags); | ||
354 | |||
355 | req->hdr.SessionId = 0; | 346 | req->hdr.SessionId = 0; |
356 | 347 | ||
357 | req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id); | 348 | req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id); |
@@ -453,7 +444,6 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses, | |||
453 | int resp_buftype; | 444 | int resp_buftype; |
454 | __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ | 445 | __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ |
455 | struct TCP_Server_Info *server = ses->server; | 446 | struct TCP_Server_Info *server = ses->server; |
456 | unsigned int sec_flags; | ||
457 | u16 blob_length = 0; | 447 | u16 blob_length = 0; |
458 | char *security_blob; | 448 | char *security_blob; |
459 | char *ntlmssp_blob = NULL; | 449 | char *ntlmssp_blob = NULL; |
@@ -474,7 +464,8 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses, | |||
474 | if (!ses->ntlmssp) | 464 | if (!ses->ntlmssp) |
475 | return -ENOMEM; | 465 | return -ENOMEM; |
476 | 466 | ||
477 | ses->server->secType = RawNTLMSSP; | 467 | /* FIXME: allow for other auth types besides NTLMSSP (e.g. krb5) */ |
468 | ses->sectype = RawNTLMSSP; | ||
478 | 469 | ||
479 | ssetup_ntlmssp_authenticate: | 470 | ssetup_ntlmssp_authenticate: |
480 | if (phase == NtLmChallenge) | 471 | if (phase == NtLmChallenge) |
@@ -484,14 +475,6 @@ ssetup_ntlmssp_authenticate: | |||
484 | if (rc) | 475 | if (rc) |
485 | return rc; | 476 | return rc; |
486 | 477 | ||
487 | /* if any of auth flags (ie not sign or seal) are overriden use them */ | ||
488 | if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL))) | ||
489 | sec_flags = ses->overrideSecFlg; /* BB FIXME fix sign flags?*/ | ||
490 | else /* if override flags set only sign/seal OR them with global auth */ | ||
491 | sec_flags = global_secflags | ses->overrideSecFlg; | ||
492 | |||
493 | cifs_dbg(FYI, "sec_flags 0x%x\n", sec_flags); | ||
494 | |||
495 | req->hdr.SessionId = 0; /* First session, not a reauthenticate */ | 478 | req->hdr.SessionId = 0; /* First session, not a reauthenticate */ |
496 | req->VcNumber = 0; /* MBZ */ | 479 | req->VcNumber = 0; /* MBZ */ |
497 | /* to enable echos and oplocks */ | 480 | /* to enable echos and oplocks */ |