diff options
Diffstat (limited to 'fs/cifs/connect.c')
| -rw-r--r-- | fs/cifs/connect.c | 159 |
1 files changed, 72 insertions, 87 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e3bc39bb9d12..afcb8a1a33b7 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -85,7 +85,7 @@ enum { | |||
| 85 | Opt_acl, Opt_noacl, Opt_locallease, | 85 | Opt_acl, Opt_noacl, Opt_locallease, |
| 86 | Opt_sign, Opt_seal, Opt_noac, | 86 | Opt_sign, Opt_seal, Opt_noac, |
| 87 | Opt_fsc, Opt_mfsymlinks, | 87 | Opt_fsc, Opt_mfsymlinks, |
| 88 | Opt_multiuser, Opt_sloppy, | 88 | Opt_multiuser, Opt_sloppy, Opt_nosharesock, |
| 89 | 89 | ||
| 90 | /* Mount options which take numeric value */ | 90 | /* Mount options which take numeric value */ |
| 91 | Opt_backupuid, Opt_backupgid, Opt_uid, | 91 | Opt_backupuid, Opt_backupgid, Opt_uid, |
| @@ -165,6 +165,7 @@ static const match_table_t cifs_mount_option_tokens = { | |||
| 165 | { Opt_mfsymlinks, "mfsymlinks" }, | 165 | { Opt_mfsymlinks, "mfsymlinks" }, |
| 166 | { Opt_multiuser, "multiuser" }, | 166 | { Opt_multiuser, "multiuser" }, |
| 167 | { Opt_sloppy, "sloppy" }, | 167 | { Opt_sloppy, "sloppy" }, |
| 168 | { Opt_nosharesock, "nosharesock" }, | ||
| 168 | 169 | ||
| 169 | { Opt_backupuid, "backupuid=%s" }, | 170 | { Opt_backupuid, "backupuid=%s" }, |
| 170 | { Opt_backupgid, "backupgid=%s" }, | 171 | { Opt_backupgid, "backupgid=%s" }, |
| @@ -275,6 +276,7 @@ static const match_table_t cifs_smb_version_tokens = { | |||
| 275 | { Smb_20, SMB20_VERSION_STRING}, | 276 | { Smb_20, SMB20_VERSION_STRING}, |
| 276 | { Smb_21, SMB21_VERSION_STRING }, | 277 | { Smb_21, SMB21_VERSION_STRING }, |
| 277 | { Smb_30, SMB30_VERSION_STRING }, | 278 | { Smb_30, SMB30_VERSION_STRING }, |
| 279 | { Smb_302, SMB302_VERSION_STRING }, | ||
| 278 | }; | 280 | }; |
| 279 | 281 | ||
| 280 | static int ip_connect(struct TCP_Server_Info *server); | 282 | static int ip_connect(struct TCP_Server_Info *server); |
| @@ -1024,44 +1026,48 @@ static int cifs_parse_security_flavors(char *value, | |||
| 1024 | 1026 | ||
| 1025 | substring_t args[MAX_OPT_ARGS]; | 1027 | substring_t args[MAX_OPT_ARGS]; |
| 1026 | 1028 | ||
| 1029 | /* | ||
| 1030 | * With mount options, the last one should win. Reset any existing | ||
| 1031 | * settings back to default. | ||
| 1032 | */ | ||
| 1033 | vol->sectype = Unspecified; | ||
| 1034 | vol->sign = false; | ||
| 1035 | |||
| 1027 | switch (match_token(value, cifs_secflavor_tokens, args)) { | 1036 | switch (match_token(value, cifs_secflavor_tokens, args)) { |
| 1028 | case Opt_sec_krb5: | ||
| 1029 | vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_SIGN; | ||
| 1030 | break; | ||
| 1031 | case Opt_sec_krb5i: | ||
| 1032 | vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN; | ||
| 1033 | break; | ||
| 1034 | case Opt_sec_krb5p: | 1037 | case Opt_sec_krb5p: |
| 1035 | /* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */ | 1038 | cifs_dbg(VFS, "sec=krb5p is not supported!\n"); |
| 1036 | cifs_dbg(VFS, "Krb5 cifs privacy not supported\n"); | 1039 | return 1; |
| 1037 | break; | 1040 | case Opt_sec_krb5i: |
| 1038 | case Opt_sec_ntlmssp: | 1041 | vol->sign = true; |
| 1039 | vol->secFlg |= CIFSSEC_MAY_NTLMSSP; | 1042 | /* Fallthrough */ |
| 1043 | case Opt_sec_krb5: | ||
| 1044 | vol->sectype = Kerberos; | ||
| 1040 | break; | 1045 | break; |
| 1041 | case Opt_sec_ntlmsspi: | 1046 | case Opt_sec_ntlmsspi: |
| 1042 | vol->secFlg |= CIFSSEC_MAY_NTLMSSP | CIFSSEC_MUST_SIGN; | 1047 | vol->sign = true; |
| 1043 | break; | 1048 | /* Fallthrough */ |
| 1044 | case Opt_ntlm: | 1049 | case Opt_sec_ntlmssp: |
| 1045 | /* ntlm is default so can be turned off too */ | 1050 | vol->sectype = RawNTLMSSP; |
| 1046 | vol->secFlg |= CIFSSEC_MAY_NTLM; | ||
| 1047 | break; | 1051 | break; |
| 1048 | case Opt_sec_ntlmi: | 1052 | case Opt_sec_ntlmi: |
| 1049 | vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN; | 1053 | vol->sign = true; |
| 1050 | break; | 1054 | /* Fallthrough */ |
| 1051 | case Opt_sec_ntlmv2: | 1055 | case Opt_ntlm: |
| 1052 | vol->secFlg |= CIFSSEC_MAY_NTLMV2; | 1056 | vol->sectype = NTLM; |
| 1053 | break; | 1057 | break; |
| 1054 | case Opt_sec_ntlmv2i: | 1058 | case Opt_sec_ntlmv2i: |
| 1055 | vol->secFlg |= CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN; | 1059 | vol->sign = true; |
| 1060 | /* Fallthrough */ | ||
| 1061 | case Opt_sec_ntlmv2: | ||
| 1062 | vol->sectype = NTLMv2; | ||
| 1056 | break; | 1063 | break; |
| 1057 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 1064 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
| 1058 | case Opt_sec_lanman: | 1065 | case Opt_sec_lanman: |
| 1059 | vol->secFlg |= CIFSSEC_MAY_LANMAN; | 1066 | vol->sectype = LANMAN; |
| 1060 | break; | 1067 | break; |
| 1061 | #endif | 1068 | #endif |
| 1062 | case Opt_sec_none: | 1069 | case Opt_sec_none: |
| 1063 | vol->nullauth = 1; | 1070 | vol->nullauth = 1; |
| 1064 | vol->secFlg |= CIFSSEC_MAY_NTLM; | ||
| 1065 | break; | 1071 | break; |
| 1066 | default: | 1072 | default: |
| 1067 | cifs_dbg(VFS, "bad security option: %s\n", value); | 1073 | cifs_dbg(VFS, "bad security option: %s\n", value); |
| @@ -1119,6 +1125,10 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol) | |||
| 1119 | vol->ops = &smb30_operations; | 1125 | vol->ops = &smb30_operations; |
| 1120 | vol->vals = &smb30_values; | 1126 | vol->vals = &smb30_values; |
| 1121 | break; | 1127 | break; |
| 1128 | case Smb_302: | ||
| 1129 | vol->ops = &smb30_operations; /* currently identical with 3.0 */ | ||
| 1130 | vol->vals = &smb302_values; | ||
| 1131 | break; | ||
| 1122 | #endif | 1132 | #endif |
| 1123 | default: | 1133 | default: |
| 1124 | cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value); | 1134 | cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value); |
| @@ -1424,7 +1434,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
| 1424 | vol->local_lease = 1; | 1434 | vol->local_lease = 1; |
| 1425 | break; | 1435 | break; |
| 1426 | case Opt_sign: | 1436 | case Opt_sign: |
| 1427 | vol->secFlg |= CIFSSEC_MUST_SIGN; | 1437 | vol->sign = true; |
| 1428 | break; | 1438 | break; |
| 1429 | case Opt_seal: | 1439 | case Opt_seal: |
| 1430 | /* we do not do the following in secFlags because seal | 1440 | /* we do not do the following in secFlags because seal |
| @@ -1455,6 +1465,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
| 1455 | case Opt_sloppy: | 1465 | case Opt_sloppy: |
| 1456 | sloppy = true; | 1466 | sloppy = true; |
| 1457 | break; | 1467 | break; |
| 1468 | case Opt_nosharesock: | ||
| 1469 | vol->nosharesock = true; | ||
| 1470 | break; | ||
| 1458 | 1471 | ||
| 1459 | /* Numeric Values */ | 1472 | /* Numeric Values */ |
| 1460 | case Opt_backupuid: | 1473 | case Opt_backupuid: |
| @@ -1978,47 +1991,21 @@ match_address(struct TCP_Server_Info *server, struct sockaddr *addr, | |||
| 1978 | static bool | 1991 | static bool |
| 1979 | match_security(struct TCP_Server_Info *server, struct smb_vol *vol) | 1992 | match_security(struct TCP_Server_Info *server, struct smb_vol *vol) |
| 1980 | { | 1993 | { |
| 1981 | unsigned int secFlags; | 1994 | /* |
| 1982 | 1995 | * The select_sectype function should either return the vol->sectype | |
| 1983 | if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL))) | 1996 | * that was specified, or "Unspecified" if that sectype was not |
| 1984 | secFlags = vol->secFlg; | 1997 | * compatible with the given NEGOTIATE request. |
| 1985 | else | 1998 | */ |
| 1986 | secFlags = global_secflags | vol->secFlg; | 1999 | if (select_sectype(server, vol->sectype) == Unspecified) |
| 1987 | |||
| 1988 | switch (server->secType) { | ||
| 1989 | case LANMAN: | ||
| 1990 | if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT))) | ||
| 1991 | return false; | ||
| 1992 | break; | ||
| 1993 | case NTLMv2: | ||
| 1994 | if (!(secFlags & CIFSSEC_MAY_NTLMV2)) | ||
| 1995 | return false; | ||
| 1996 | break; | ||
| 1997 | case NTLM: | ||
| 1998 | if (!(secFlags & CIFSSEC_MAY_NTLM)) | ||
| 1999 | return false; | ||
| 2000 | break; | ||
| 2001 | case Kerberos: | ||
| 2002 | if (!(secFlags & CIFSSEC_MAY_KRB5)) | ||
| 2003 | return false; | ||
| 2004 | break; | ||
| 2005 | case RawNTLMSSP: | ||
| 2006 | if (!(secFlags & CIFSSEC_MAY_NTLMSSP)) | ||
| 2007 | return false; | ||
| 2008 | break; | ||
| 2009 | default: | ||
| 2010 | /* shouldn't happen */ | ||
| 2011 | return false; | 2000 | return false; |
| 2012 | } | ||
| 2013 | 2001 | ||
| 2014 | /* now check if signing mode is acceptable */ | 2002 | /* |
| 2015 | if ((secFlags & CIFSSEC_MAY_SIGN) == 0 && | 2003 | * Now check if signing mode is acceptable. No need to check |
| 2016 | (server->sec_mode & SECMODE_SIGN_REQUIRED)) | 2004 | * global_secflags at this point since if MUST_SIGN is set then |
| 2017 | return false; | 2005 | * the server->sign had better be too. |
| 2018 | else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) && | 2006 | */ |
| 2019 | (server->sec_mode & | 2007 | if (vol->sign && !server->sign) |
| 2020 | (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0) | 2008 | return false; |
| 2021 | return false; | ||
| 2022 | 2009 | ||
| 2023 | return true; | 2010 | return true; |
| 2024 | } | 2011 | } |
| @@ -2027,6 +2014,9 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol) | |||
| 2027 | { | 2014 | { |
| 2028 | struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr; | 2015 | struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr; |
| 2029 | 2016 | ||
| 2017 | if (vol->nosharesock) | ||
| 2018 | return 0; | ||
| 2019 | |||
| 2030 | if ((server->vals != vol->vals) || (server->ops != vol->ops)) | 2020 | if ((server->vals != vol->vals) || (server->ops != vol->ops)) |
| 2031 | return 0; | 2021 | return 0; |
| 2032 | 2022 | ||
| @@ -2216,7 +2206,11 @@ out_err: | |||
| 2216 | 2206 | ||
| 2217 | static int match_session(struct cifs_ses *ses, struct smb_vol *vol) | 2207 | static int match_session(struct cifs_ses *ses, struct smb_vol *vol) |
| 2218 | { | 2208 | { |
| 2219 | switch (ses->server->secType) { | 2209 | if (vol->sectype != Unspecified && |
| 2210 | vol->sectype != ses->sectype) | ||
| 2211 | return 0; | ||
| 2212 | |||
| 2213 | switch (ses->sectype) { | ||
| 2220 | case Kerberos: | 2214 | case Kerberos: |
| 2221 | if (!uid_eq(vol->cred_uid, ses->cred_uid)) | 2215 | if (!uid_eq(vol->cred_uid, ses->cred_uid)) |
| 2222 | return 0; | 2216 | return 0; |
| @@ -2493,7 +2487,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) | |||
| 2493 | ses->cred_uid = volume_info->cred_uid; | 2487 | ses->cred_uid = volume_info->cred_uid; |
| 2494 | ses->linux_uid = volume_info->linux_uid; | 2488 | ses->linux_uid = volume_info->linux_uid; |
| 2495 | 2489 | ||
| 2496 | ses->overrideSecFlg = volume_info->secFlg; | 2490 | ses->sectype = volume_info->sectype; |
| 2491 | ses->sign = volume_info->sign; | ||
| 2497 | 2492 | ||
| 2498 | mutex_lock(&ses->session_mutex); | 2493 | mutex_lock(&ses->session_mutex); |
| 2499 | rc = cifs_negotiate_protocol(xid, ses); | 2494 | rc = cifs_negotiate_protocol(xid, ses); |
| @@ -3656,7 +3651,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, | |||
| 3656 | NTLMv2 password here) */ | 3651 | NTLMv2 password here) */ |
| 3657 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 3652 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
| 3658 | if ((global_secflags & CIFSSEC_MAY_LANMAN) && | 3653 | if ((global_secflags & CIFSSEC_MAY_LANMAN) && |
| 3659 | (ses->server->secType == LANMAN)) | 3654 | (ses->sectype == LANMAN)) |
| 3660 | calc_lanman_hash(tcon->password, ses->server->cryptkey, | 3655 | calc_lanman_hash(tcon->password, ses->server->cryptkey, |
| 3661 | ses->server->sec_mode & | 3656 | ses->server->sec_mode & |
| 3662 | SECMODE_PW_ENCRYPT ? true : false, | 3657 | SECMODE_PW_ENCRYPT ? true : false, |
| @@ -3674,8 +3669,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, | |||
| 3674 | } | 3669 | } |
| 3675 | } | 3670 | } |
| 3676 | 3671 | ||
| 3677 | if (ses->server->sec_mode & | 3672 | if (ses->server->sign) |
| 3678 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
| 3679 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 3673 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
| 3680 | 3674 | ||
| 3681 | if (ses->capabilities & CAP_STATUS32) { | 3675 | if (ses->capabilities & CAP_STATUS32) { |
| @@ -3738,7 +3732,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, | |||
| 3738 | } | 3732 | } |
| 3739 | bcc_ptr += length + 1; | 3733 | bcc_ptr += length + 1; |
| 3740 | bytes_left -= (length + 1); | 3734 | bytes_left -= (length + 1); |
| 3741 | strncpy(tcon->treeName, tree, MAX_TREE_SIZE); | 3735 | strlcpy(tcon->treeName, tree, sizeof(tcon->treeName)); |
| 3742 | 3736 | ||
| 3743 | /* mostly informational -- no need to fail on error here */ | 3737 | /* mostly informational -- no need to fail on error here */ |
| 3744 | kfree(tcon->nativeFileSystem); | 3738 | kfree(tcon->nativeFileSystem); |
| @@ -3827,7 +3821,6 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, | |||
| 3827 | int rc = -ENOSYS; | 3821 | int rc = -ENOSYS; |
| 3828 | struct TCP_Server_Info *server = ses->server; | 3822 | struct TCP_Server_Info *server = ses->server; |
| 3829 | 3823 | ||
| 3830 | ses->flags = 0; | ||
| 3831 | ses->capabilities = server->capabilities; | 3824 | ses->capabilities = server->capabilities; |
| 3832 | if (linuxExtEnabled == 0) | 3825 | if (linuxExtEnabled == 0) |
| 3833 | ses->capabilities &= (~server->vals->cap_unix); | 3826 | ses->capabilities &= (~server->vals->cap_unix); |
| @@ -3848,6 +3841,8 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, | |||
| 3848 | server->sequence_number = 0x2; | 3841 | server->sequence_number = 0x2; |
| 3849 | server->session_estab = true; | 3842 | server->session_estab = true; |
| 3850 | ses->auth_key.response = NULL; | 3843 | ses->auth_key.response = NULL; |
| 3844 | if (server->ops->generate_signingkey) | ||
| 3845 | server->ops->generate_signingkey(server); | ||
| 3851 | } | 3846 | } |
| 3852 | mutex_unlock(&server->srv_mutex); | 3847 | mutex_unlock(&server->srv_mutex); |
| 3853 | 3848 | ||
| @@ -3870,23 +3865,11 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, | |||
| 3870 | static int | 3865 | static int |
| 3871 | cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses) | 3866 | cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses) |
| 3872 | { | 3867 | { |
| 3873 | switch (ses->server->secType) { | 3868 | vol->sectype = ses->sectype; |
| 3874 | case Kerberos: | 3869 | |
| 3875 | vol->secFlg = CIFSSEC_MUST_KRB5; | 3870 | /* krb5 is special, since we don't need username or pw */ |
| 3871 | if (vol->sectype == Kerberos) | ||
| 3876 | return 0; | 3872 | return 0; |
| 3877 | case NTLMv2: | ||
| 3878 | vol->secFlg = CIFSSEC_MUST_NTLMV2; | ||
| 3879 | break; | ||
| 3880 | case NTLM: | ||
| 3881 | vol->secFlg = CIFSSEC_MUST_NTLM; | ||
| 3882 | break; | ||
| 3883 | case RawNTLMSSP: | ||
| 3884 | vol->secFlg = CIFSSEC_MUST_NTLMSSP; | ||
| 3885 | break; | ||
| 3886 | case LANMAN: | ||
| 3887 | vol->secFlg = CIFSSEC_MUST_LANMAN; | ||
| 3888 | break; | ||
| 3889 | } | ||
| 3890 | 3873 | ||
| 3891 | return cifs_set_cifscreds(vol, ses); | 3874 | return cifs_set_cifscreds(vol, ses); |
| 3892 | } | 3875 | } |
| @@ -3912,6 +3895,8 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid) | |||
| 3912 | vol_info->nocase = master_tcon->nocase; | 3895 | vol_info->nocase = master_tcon->nocase; |
| 3913 | vol_info->local_lease = master_tcon->local_lease; | 3896 | vol_info->local_lease = master_tcon->local_lease; |
| 3914 | vol_info->no_linux_ext = !master_tcon->unix_ext; | 3897 | vol_info->no_linux_ext = !master_tcon->unix_ext; |
| 3898 | vol_info->sectype = master_tcon->ses->sectype; | ||
| 3899 | vol_info->sign = master_tcon->ses->sign; | ||
| 3915 | 3900 | ||
| 3916 | rc = cifs_set_vol_auth(vol_info, master_tcon->ses); | 3901 | rc = cifs_set_vol_auth(vol_info, master_tcon->ses); |
| 3917 | if (rc) { | 3902 | if (rc) { |
