diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 172 |
1 files changed, 76 insertions, 96 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e3bc39bb9d12..d67c550c4980 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: |
@@ -1662,7 +1675,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1662 | if (string == NULL) | 1675 | if (string == NULL) |
1663 | goto out_nomem; | 1676 | goto out_nomem; |
1664 | 1677 | ||
1665 | if (strnlen(string, 256) == 256) { | 1678 | if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN) |
1679 | == CIFS_MAX_DOMAINNAME_LEN) { | ||
1666 | printk(KERN_WARNING "CIFS: domain name too" | 1680 | printk(KERN_WARNING "CIFS: domain name too" |
1667 | " long\n"); | 1681 | " long\n"); |
1668 | goto cifs_parse_mount_err; | 1682 | goto cifs_parse_mount_err; |
@@ -1978,47 +1992,21 @@ match_address(struct TCP_Server_Info *server, struct sockaddr *addr, | |||
1978 | static bool | 1992 | static bool |
1979 | match_security(struct TCP_Server_Info *server, struct smb_vol *vol) | 1993 | match_security(struct TCP_Server_Info *server, struct smb_vol *vol) |
1980 | { | 1994 | { |
1981 | unsigned int secFlags; | 1995 | /* |
1982 | 1996 | * The select_sectype function should either return the vol->sectype | |
1983 | if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL))) | 1997 | * that was specified, or "Unspecified" if that sectype was not |
1984 | secFlags = vol->secFlg; | 1998 | * compatible with the given NEGOTIATE request. |
1985 | else | 1999 | */ |
1986 | secFlags = global_secflags | vol->secFlg; | 2000 | 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; | 2001 | return false; |
2012 | } | ||
2013 | 2002 | ||
2014 | /* now check if signing mode is acceptable */ | 2003 | /* |
2015 | if ((secFlags & CIFSSEC_MAY_SIGN) == 0 && | 2004 | * Now check if signing mode is acceptable. No need to check |
2016 | (server->sec_mode & SECMODE_SIGN_REQUIRED)) | 2005 | * global_secflags at this point since if MUST_SIGN is set then |
2017 | return false; | 2006 | * the server->sign had better be too. |
2018 | else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) && | 2007 | */ |
2019 | (server->sec_mode & | 2008 | if (vol->sign && !server->sign) |
2020 | (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0) | 2009 | return false; |
2021 | return false; | ||
2022 | 2010 | ||
2023 | return true; | 2011 | return true; |
2024 | } | 2012 | } |
@@ -2027,6 +2015,9 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol) | |||
2027 | { | 2015 | { |
2028 | struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr; | 2016 | struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr; |
2029 | 2017 | ||
2018 | if (vol->nosharesock) | ||
2019 | return 0; | ||
2020 | |||
2030 | if ((server->vals != vol->vals) || (server->ops != vol->ops)) | 2021 | if ((server->vals != vol->vals) || (server->ops != vol->ops)) |
2031 | return 0; | 2022 | return 0; |
2032 | 2023 | ||
@@ -2118,12 +2109,6 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
2118 | goto out_err; | 2109 | goto out_err; |
2119 | } | 2110 | } |
2120 | 2111 | ||
2121 | rc = cifs_crypto_shash_allocate(tcp_ses); | ||
2122 | if (rc) { | ||
2123 | cifs_dbg(VFS, "could not setup hash structures rc %d\n", rc); | ||
2124 | goto out_err; | ||
2125 | } | ||
2126 | |||
2127 | tcp_ses->ops = volume_info->ops; | 2112 | tcp_ses->ops = volume_info->ops; |
2128 | tcp_ses->vals = volume_info->vals; | 2113 | tcp_ses->vals = volume_info->vals; |
2129 | cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns)); | 2114 | cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns)); |
@@ -2216,7 +2201,11 @@ out_err: | |||
2216 | 2201 | ||
2217 | 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) |
2218 | { | 2203 | { |
2219 | switch (ses->server->secType) { | 2204 | if (vol->sectype != Unspecified && |
2205 | vol->sectype != ses->sectype) | ||
2206 | return 0; | ||
2207 | |||
2208 | switch (ses->sectype) { | ||
2220 | case Kerberos: | 2209 | case Kerberos: |
2221 | if (!uid_eq(vol->cred_uid, ses->cred_uid)) | 2210 | if (!uid_eq(vol->cred_uid, ses->cred_uid)) |
2222 | return 0; | 2211 | return 0; |
@@ -2288,8 +2277,8 @@ cifs_put_smb_ses(struct cifs_ses *ses) | |||
2288 | 2277 | ||
2289 | #ifdef CONFIG_KEYS | 2278 | #ifdef CONFIG_KEYS |
2290 | 2279 | ||
2291 | /* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */ | 2280 | /* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */ |
2292 | #define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1) | 2281 | #define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1) |
2293 | 2282 | ||
2294 | /* Populate username and pw fields from keyring if possible */ | 2283 | /* Populate username and pw fields from keyring if possible */ |
2295 | static int | 2284 | static int |
@@ -2493,7 +2482,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) | |||
2493 | ses->cred_uid = volume_info->cred_uid; | 2482 | ses->cred_uid = volume_info->cred_uid; |
2494 | ses->linux_uid = volume_info->linux_uid; | 2483 | ses->linux_uid = volume_info->linux_uid; |
2495 | 2484 | ||
2496 | ses->overrideSecFlg = volume_info->secFlg; | 2485 | ses->sectype = volume_info->sectype; |
2486 | ses->sign = volume_info->sign; | ||
2497 | 2487 | ||
2498 | mutex_lock(&ses->session_mutex); | 2488 | mutex_lock(&ses->session_mutex); |
2499 | rc = cifs_negotiate_protocol(xid, ses); | 2489 | rc = cifs_negotiate_protocol(xid, ses); |
@@ -3656,7 +3646,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, | |||
3656 | NTLMv2 password here) */ | 3646 | NTLMv2 password here) */ |
3657 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 3647 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
3658 | if ((global_secflags & CIFSSEC_MAY_LANMAN) && | 3648 | if ((global_secflags & CIFSSEC_MAY_LANMAN) && |
3659 | (ses->server->secType == LANMAN)) | 3649 | (ses->sectype == LANMAN)) |
3660 | calc_lanman_hash(tcon->password, ses->server->cryptkey, | 3650 | calc_lanman_hash(tcon->password, ses->server->cryptkey, |
3661 | ses->server->sec_mode & | 3651 | ses->server->sec_mode & |
3662 | SECMODE_PW_ENCRYPT ? true : false, | 3652 | SECMODE_PW_ENCRYPT ? true : false, |
@@ -3674,8 +3664,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, | |||
3674 | } | 3664 | } |
3675 | } | 3665 | } |
3676 | 3666 | ||
3677 | if (ses->server->sec_mode & | 3667 | if (ses->server->sign) |
3678 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
3679 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 3668 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
3680 | 3669 | ||
3681 | if (ses->capabilities & CAP_STATUS32) { | 3670 | if (ses->capabilities & CAP_STATUS32) { |
@@ -3738,7 +3727,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, | |||
3738 | } | 3727 | } |
3739 | bcc_ptr += length + 1; | 3728 | bcc_ptr += length + 1; |
3740 | bytes_left -= (length + 1); | 3729 | bytes_left -= (length + 1); |
3741 | strncpy(tcon->treeName, tree, MAX_TREE_SIZE); | 3730 | strlcpy(tcon->treeName, tree, sizeof(tcon->treeName)); |
3742 | 3731 | ||
3743 | /* mostly informational -- no need to fail on error here */ | 3732 | /* mostly informational -- no need to fail on error here */ |
3744 | kfree(tcon->nativeFileSystem); | 3733 | kfree(tcon->nativeFileSystem); |
@@ -3827,7 +3816,6 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, | |||
3827 | int rc = -ENOSYS; | 3816 | int rc = -ENOSYS; |
3828 | struct TCP_Server_Info *server = ses->server; | 3817 | struct TCP_Server_Info *server = ses->server; |
3829 | 3818 | ||
3830 | ses->flags = 0; | ||
3831 | ses->capabilities = server->capabilities; | 3819 | ses->capabilities = server->capabilities; |
3832 | if (linuxExtEnabled == 0) | 3820 | if (linuxExtEnabled == 0) |
3833 | ses->capabilities &= (~server->vals->cap_unix); | 3821 | ses->capabilities &= (~server->vals->cap_unix); |
@@ -3848,6 +3836,8 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, | |||
3848 | server->sequence_number = 0x2; | 3836 | server->sequence_number = 0x2; |
3849 | server->session_estab = true; | 3837 | server->session_estab = true; |
3850 | ses->auth_key.response = NULL; | 3838 | ses->auth_key.response = NULL; |
3839 | if (server->ops->generate_signingkey) | ||
3840 | server->ops->generate_signingkey(server); | ||
3851 | } | 3841 | } |
3852 | mutex_unlock(&server->srv_mutex); | 3842 | mutex_unlock(&server->srv_mutex); |
3853 | 3843 | ||
@@ -3870,23 +3860,11 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, | |||
3870 | static int | 3860 | static int |
3871 | cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses) | 3861 | cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses) |
3872 | { | 3862 | { |
3873 | switch (ses->server->secType) { | 3863 | vol->sectype = ses->sectype; |
3874 | case Kerberos: | 3864 | |
3875 | vol->secFlg = CIFSSEC_MUST_KRB5; | 3865 | /* krb5 is special, since we don't need username or pw */ |
3866 | if (vol->sectype == Kerberos) | ||
3876 | return 0; | 3867 | 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 | 3868 | ||
3891 | return cifs_set_cifscreds(vol, ses); | 3869 | return cifs_set_cifscreds(vol, ses); |
3892 | } | 3870 | } |
@@ -3912,6 +3890,8 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid) | |||
3912 | vol_info->nocase = master_tcon->nocase; | 3890 | vol_info->nocase = master_tcon->nocase; |
3913 | vol_info->local_lease = master_tcon->local_lease; | 3891 | vol_info->local_lease = master_tcon->local_lease; |
3914 | vol_info->no_linux_ext = !master_tcon->unix_ext; | 3892 | vol_info->no_linux_ext = !master_tcon->unix_ext; |
3893 | vol_info->sectype = master_tcon->ses->sectype; | ||
3894 | vol_info->sign = master_tcon->ses->sign; | ||
3915 | 3895 | ||
3916 | rc = cifs_set_vol_auth(vol_info, master_tcon->ses); | 3896 | rc = cifs_set_vol_auth(vol_info, master_tcon->ses); |
3917 | if (rc) { | 3897 | if (rc) { |