diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 305 |
1 files changed, 248 insertions, 57 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 4666780f315d..986709a8d903 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <asm/processor.h> | 38 | #include <asm/processor.h> |
39 | #include <linux/inet.h> | 39 | #include <linux/inet.h> |
40 | #include <linux/module.h> | 40 | #include <linux/module.h> |
41 | #include <keys/user-type.h> | ||
41 | #include <net/ipv6.h> | 42 | #include <net/ipv6.h> |
42 | #include "cifspdu.h" | 43 | #include "cifspdu.h" |
43 | #include "cifsglob.h" | 44 | #include "cifsglob.h" |
@@ -225,74 +226,90 @@ static int check2ndT2(struct smb_hdr *pSMB) | |||
225 | 226 | ||
226 | static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | 227 | static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) |
227 | { | 228 | { |
228 | struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond; | 229 | struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)psecond; |
229 | struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB; | 230 | struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB; |
230 | char *data_area_of_target; | 231 | char *data_area_of_tgt; |
231 | char *data_area_of_buf2; | 232 | char *data_area_of_src; |
232 | int remaining; | 233 | int remaining; |
233 | unsigned int byte_count, total_in_buf; | 234 | unsigned int byte_count, total_in_tgt; |
234 | __u16 total_data_size, total_in_buf2; | 235 | __u16 tgt_total_cnt, src_total_cnt, total_in_src; |
235 | 236 | ||
236 | total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); | 237 | src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount); |
238 | tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); | ||
237 | 239 | ||
238 | if (total_data_size != | 240 | if (tgt_total_cnt != src_total_cnt) |
239 | get_unaligned_le16(&pSMB2->t2_rsp.TotalDataCount)) | 241 | cFYI(1, "total data count of primary and secondary t2 differ " |
240 | cFYI(1, "total data size of primary and secondary t2 differ"); | 242 | "source=%hu target=%hu", src_total_cnt, tgt_total_cnt); |
241 | 243 | ||
242 | total_in_buf = get_unaligned_le16(&pSMBt->t2_rsp.DataCount); | 244 | total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount); |
243 | 245 | ||
244 | remaining = total_data_size - total_in_buf; | 246 | remaining = tgt_total_cnt - total_in_tgt; |
245 | 247 | ||
246 | if (remaining < 0) | 248 | if (remaining < 0) { |
249 | cFYI(1, "Server sent too much data. tgt_total_cnt=%hu " | ||
250 | "total_in_tgt=%hu", tgt_total_cnt, total_in_tgt); | ||
247 | return -EPROTO; | 251 | return -EPROTO; |
252 | } | ||
248 | 253 | ||
249 | if (remaining == 0) /* nothing to do, ignore */ | 254 | if (remaining == 0) { |
255 | /* nothing to do, ignore */ | ||
256 | cFYI(1, "no more data remains"); | ||
250 | return 0; | 257 | return 0; |
258 | } | ||
251 | 259 | ||
252 | total_in_buf2 = get_unaligned_le16(&pSMB2->t2_rsp.DataCount); | 260 | total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount); |
253 | if (remaining < total_in_buf2) { | 261 | if (remaining < total_in_src) |
254 | cFYI(1, "transact2 2nd response contains too much data"); | 262 | cFYI(1, "transact2 2nd response contains too much data"); |
255 | } | ||
256 | 263 | ||
257 | /* find end of first SMB data area */ | 264 | /* find end of first SMB data area */ |
258 | data_area_of_target = (char *)&pSMBt->hdr.Protocol + | 265 | data_area_of_tgt = (char *)&pSMBt->hdr.Protocol + |
259 | get_unaligned_le16(&pSMBt->t2_rsp.DataOffset); | 266 | get_unaligned_le16(&pSMBt->t2_rsp.DataOffset); |
260 | /* validate target area */ | ||
261 | 267 | ||
262 | data_area_of_buf2 = (char *)&pSMB2->hdr.Protocol + | 268 | /* validate target area */ |
263 | get_unaligned_le16(&pSMB2->t2_rsp.DataOffset); | 269 | data_area_of_src = (char *)&pSMBs->hdr.Protocol + |
270 | get_unaligned_le16(&pSMBs->t2_rsp.DataOffset); | ||
264 | 271 | ||
265 | data_area_of_target += total_in_buf; | 272 | data_area_of_tgt += total_in_tgt; |
266 | 273 | ||
267 | /* copy second buffer into end of first buffer */ | 274 | total_in_tgt += total_in_src; |
268 | total_in_buf += total_in_buf2; | ||
269 | /* is the result too big for the field? */ | 275 | /* is the result too big for the field? */ |
270 | if (total_in_buf > USHRT_MAX) | 276 | if (total_in_tgt > USHRT_MAX) { |
277 | cFYI(1, "coalesced DataCount too large (%u)", total_in_tgt); | ||
271 | return -EPROTO; | 278 | return -EPROTO; |
272 | put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount); | 279 | } |
280 | put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount); | ||
273 | 281 | ||
274 | /* fix up the BCC */ | 282 | /* fix up the BCC */ |
275 | byte_count = get_bcc(pTargetSMB); | 283 | byte_count = get_bcc(pTargetSMB); |
276 | byte_count += total_in_buf2; | 284 | byte_count += total_in_src; |
277 | /* is the result too big for the field? */ | 285 | /* is the result too big for the field? */ |
278 | if (byte_count > USHRT_MAX) | 286 | if (byte_count > USHRT_MAX) { |
287 | cFYI(1, "coalesced BCC too large (%u)", byte_count); | ||
279 | return -EPROTO; | 288 | return -EPROTO; |
289 | } | ||
280 | put_bcc(byte_count, pTargetSMB); | 290 | put_bcc(byte_count, pTargetSMB); |
281 | 291 | ||
282 | byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); | 292 | byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); |
283 | byte_count += total_in_buf2; | 293 | byte_count += total_in_src; |
284 | /* don't allow buffer to overflow */ | 294 | /* don't allow buffer to overflow */ |
285 | if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) | 295 | if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { |
296 | cFYI(1, "coalesced BCC exceeds buffer size (%u)", byte_count); | ||
286 | return -ENOBUFS; | 297 | return -ENOBUFS; |
298 | } | ||
287 | pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); | 299 | pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); |
288 | 300 | ||
289 | memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2); | 301 | /* copy second buffer into end of first buffer */ |
302 | memcpy(data_area_of_tgt, data_area_of_src, total_in_src); | ||
290 | 303 | ||
291 | if (remaining == total_in_buf2) { | 304 | if (remaining != total_in_src) { |
292 | cFYI(1, "found the last secondary response"); | 305 | /* more responses to go */ |
293 | return 0; /* we are done */ | 306 | cFYI(1, "waiting for more secondary responses"); |
294 | } else /* more responses to go */ | ||
295 | return 1; | 307 | return 1; |
308 | } | ||
309 | |||
310 | /* we are done */ | ||
311 | cFYI(1, "found the last secondary response"); | ||
312 | return 0; | ||
296 | } | 313 | } |
297 | 314 | ||
298 | static void | 315 | static void |
@@ -1578,11 +1595,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1578 | } | 1595 | } |
1579 | } | 1596 | } |
1580 | 1597 | ||
1581 | if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) { | 1598 | #ifndef CONFIG_KEYS |
1582 | cERROR(1, "Multiuser mounts currently require krb5 " | 1599 | /* Muliuser mounts require CONFIG_KEYS support */ |
1583 | "authentication!"); | 1600 | if (vol->multiuser) { |
1601 | cERROR(1, "Multiuser mounts require kernels with " | ||
1602 | "CONFIG_KEYS enabled."); | ||
1584 | goto cifs_parse_mount_err; | 1603 | goto cifs_parse_mount_err; |
1585 | } | 1604 | } |
1605 | #endif | ||
1586 | 1606 | ||
1587 | if (vol->UNCip == NULL) | 1607 | if (vol->UNCip == NULL) |
1588 | vol->UNCip = &vol->UNC[2]; | 1608 | vol->UNCip = &vol->UNC[2]; |
@@ -1981,10 +2001,16 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol) | |||
1981 | return 0; | 2001 | return 0; |
1982 | break; | 2002 | break; |
1983 | default: | 2003 | default: |
2004 | /* NULL username means anonymous session */ | ||
2005 | if (ses->user_name == NULL) { | ||
2006 | if (!vol->nullauth) | ||
2007 | return 0; | ||
2008 | break; | ||
2009 | } | ||
2010 | |||
1984 | /* anything else takes username/password */ | 2011 | /* anything else takes username/password */ |
1985 | if (ses->user_name == NULL) | 2012 | if (strncmp(ses->user_name, |
1986 | return 0; | 2013 | vol->username ? vol->username : "", |
1987 | if (strncmp(ses->user_name, vol->username, | ||
1988 | MAX_USERNAME_SIZE)) | 2014 | MAX_USERNAME_SIZE)) |
1989 | return 0; | 2015 | return 0; |
1990 | if (strlen(vol->username) != 0 && | 2016 | if (strlen(vol->username) != 0 && |
@@ -2039,6 +2065,132 @@ cifs_put_smb_ses(struct cifs_ses *ses) | |||
2039 | cifs_put_tcp_session(server); | 2065 | cifs_put_tcp_session(server); |
2040 | } | 2066 | } |
2041 | 2067 | ||
2068 | #ifdef CONFIG_KEYS | ||
2069 | |||
2070 | /* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */ | ||
2071 | #define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1) | ||
2072 | |||
2073 | /* Populate username and pw fields from keyring if possible */ | ||
2074 | static int | ||
2075 | cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses) | ||
2076 | { | ||
2077 | int rc = 0; | ||
2078 | char *desc, *delim, *payload; | ||
2079 | ssize_t len; | ||
2080 | struct key *key; | ||
2081 | struct TCP_Server_Info *server = ses->server; | ||
2082 | struct sockaddr_in *sa; | ||
2083 | struct sockaddr_in6 *sa6; | ||
2084 | struct user_key_payload *upayload; | ||
2085 | |||
2086 | desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL); | ||
2087 | if (!desc) | ||
2088 | return -ENOMEM; | ||
2089 | |||
2090 | /* try to find an address key first */ | ||
2091 | switch (server->dstaddr.ss_family) { | ||
2092 | case AF_INET: | ||
2093 | sa = (struct sockaddr_in *)&server->dstaddr; | ||
2094 | sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr); | ||
2095 | break; | ||
2096 | case AF_INET6: | ||
2097 | sa6 = (struct sockaddr_in6 *)&server->dstaddr; | ||
2098 | sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr); | ||
2099 | break; | ||
2100 | default: | ||
2101 | cFYI(1, "Bad ss_family (%hu)", server->dstaddr.ss_family); | ||
2102 | rc = -EINVAL; | ||
2103 | goto out_err; | ||
2104 | } | ||
2105 | |||
2106 | cFYI(1, "%s: desc=%s", __func__, desc); | ||
2107 | key = request_key(&key_type_logon, desc, ""); | ||
2108 | if (IS_ERR(key)) { | ||
2109 | if (!ses->domainName) { | ||
2110 | cFYI(1, "domainName is NULL"); | ||
2111 | rc = PTR_ERR(key); | ||
2112 | goto out_err; | ||
2113 | } | ||
2114 | |||
2115 | /* didn't work, try to find a domain key */ | ||
2116 | sprintf(desc, "cifs:d:%s", ses->domainName); | ||
2117 | cFYI(1, "%s: desc=%s", __func__, desc); | ||
2118 | key = request_key(&key_type_logon, desc, ""); | ||
2119 | if (IS_ERR(key)) { | ||
2120 | rc = PTR_ERR(key); | ||
2121 | goto out_err; | ||
2122 | } | ||
2123 | } | ||
2124 | |||
2125 | down_read(&key->sem); | ||
2126 | upayload = key->payload.data; | ||
2127 | if (IS_ERR_OR_NULL(upayload)) { | ||
2128 | rc = PTR_ERR(key); | ||
2129 | goto out_key_put; | ||
2130 | } | ||
2131 | |||
2132 | /* find first : in payload */ | ||
2133 | payload = (char *)upayload->data; | ||
2134 | delim = strnchr(payload, upayload->datalen, ':'); | ||
2135 | cFYI(1, "payload=%s", payload); | ||
2136 | if (!delim) { | ||
2137 | cFYI(1, "Unable to find ':' in payload (datalen=%d)", | ||
2138 | upayload->datalen); | ||
2139 | rc = -EINVAL; | ||
2140 | goto out_key_put; | ||
2141 | } | ||
2142 | |||
2143 | len = delim - payload; | ||
2144 | if (len > MAX_USERNAME_SIZE || len <= 0) { | ||
2145 | cFYI(1, "Bad value from username search (len=%ld)", len); | ||
2146 | rc = -EINVAL; | ||
2147 | goto out_key_put; | ||
2148 | } | ||
2149 | |||
2150 | vol->username = kstrndup(payload, len, GFP_KERNEL); | ||
2151 | if (!vol->username) { | ||
2152 | cFYI(1, "Unable to allocate %ld bytes for username", len); | ||
2153 | rc = -ENOMEM; | ||
2154 | goto out_key_put; | ||
2155 | } | ||
2156 | cFYI(1, "%s: username=%s", __func__, vol->username); | ||
2157 | |||
2158 | len = key->datalen - (len + 1); | ||
2159 | if (len > MAX_PASSWORD_SIZE || len <= 0) { | ||
2160 | cFYI(1, "Bad len for password search (len=%ld)", len); | ||
2161 | rc = -EINVAL; | ||
2162 | kfree(vol->username); | ||
2163 | vol->username = NULL; | ||
2164 | goto out_key_put; | ||
2165 | } | ||
2166 | |||
2167 | ++delim; | ||
2168 | vol->password = kstrndup(delim, len, GFP_KERNEL); | ||
2169 | if (!vol->password) { | ||
2170 | cFYI(1, "Unable to allocate %ld bytes for password", len); | ||
2171 | rc = -ENOMEM; | ||
2172 | kfree(vol->username); | ||
2173 | vol->username = NULL; | ||
2174 | goto out_key_put; | ||
2175 | } | ||
2176 | |||
2177 | out_key_put: | ||
2178 | up_read(&key->sem); | ||
2179 | key_put(key); | ||
2180 | out_err: | ||
2181 | kfree(desc); | ||
2182 | cFYI(1, "%s: returning %d", __func__, rc); | ||
2183 | return rc; | ||
2184 | } | ||
2185 | #else /* ! CONFIG_KEYS */ | ||
2186 | static inline int | ||
2187 | cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)), | ||
2188 | struct cifs_ses *ses __attribute__((unused))) | ||
2189 | { | ||
2190 | return -ENOSYS; | ||
2191 | } | ||
2192 | #endif /* CONFIG_KEYS */ | ||
2193 | |||
2042 | static bool warned_on_ntlm; /* globals init to false automatically */ | 2194 | static bool warned_on_ntlm; /* globals init to false automatically */ |
2043 | 2195 | ||
2044 | static struct cifs_ses * | 2196 | static struct cifs_ses * |
@@ -2914,18 +3066,33 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | |||
2914 | #define CIFS_DEFAULT_IOSIZE (1024 * 1024) | 3066 | #define CIFS_DEFAULT_IOSIZE (1024 * 1024) |
2915 | 3067 | ||
2916 | /* | 3068 | /* |
2917 | * Windows only supports a max of 60k reads. Default to that when posix | 3069 | * Windows only supports a max of 60kb reads and 65535 byte writes. Default to |
2918 | * extensions aren't in force. | 3070 | * those values when posix extensions aren't in force. In actuality here, we |
3071 | * use 65536 to allow for a write that is a multiple of 4k. Most servers seem | ||
3072 | * to be ok with the extra byte even though Windows doesn't send writes that | ||
3073 | * are that large. | ||
3074 | * | ||
3075 | * Citation: | ||
3076 | * | ||
3077 | * http://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx | ||
2919 | */ | 3078 | */ |
2920 | #define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024) | 3079 | #define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024) |
3080 | #define CIFS_DEFAULT_NON_POSIX_WSIZE (65536) | ||
2921 | 3081 | ||
2922 | static unsigned int | 3082 | static unsigned int |
2923 | cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) | 3083 | cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) |
2924 | { | 3084 | { |
2925 | __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability); | 3085 | __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability); |
2926 | struct TCP_Server_Info *server = tcon->ses->server; | 3086 | struct TCP_Server_Info *server = tcon->ses->server; |
2927 | unsigned int wsize = pvolume_info->wsize ? pvolume_info->wsize : | 3087 | unsigned int wsize; |
2928 | CIFS_DEFAULT_IOSIZE; | 3088 | |
3089 | /* start with specified wsize, or default */ | ||
3090 | if (pvolume_info->wsize) | ||
3091 | wsize = pvolume_info->wsize; | ||
3092 | else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) | ||
3093 | wsize = CIFS_DEFAULT_IOSIZE; | ||
3094 | else | ||
3095 | wsize = CIFS_DEFAULT_NON_POSIX_WSIZE; | ||
2929 | 3096 | ||
2930 | /* can server support 24-bit write sizes? (via UNIX extensions) */ | 3097 | /* can server support 24-bit write sizes? (via UNIX extensions) */ |
2931 | if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) | 3098 | if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) |
@@ -3136,10 +3303,9 @@ cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data, | |||
3136 | return -EINVAL; | 3303 | return -EINVAL; |
3137 | 3304 | ||
3138 | if (volume_info->nullauth) { | 3305 | if (volume_info->nullauth) { |
3139 | cFYI(1, "null user"); | 3306 | cFYI(1, "Anonymous login"); |
3140 | volume_info->username = kzalloc(1, GFP_KERNEL); | 3307 | kfree(volume_info->username); |
3141 | if (volume_info->username == NULL) | 3308 | volume_info->username = NULL; |
3142 | return -ENOMEM; | ||
3143 | } else if (volume_info->username) { | 3309 | } else if (volume_info->username) { |
3144 | /* BB fixme parse for domain name here */ | 3310 | /* BB fixme parse for domain name here */ |
3145 | cFYI(1, "Username: %s", volume_info->username); | 3311 | cFYI(1, "Username: %s", volume_info->username); |
@@ -3478,7 +3644,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses, | |||
3478 | if (ses->capabilities & CAP_UNICODE) { | 3644 | if (ses->capabilities & CAP_UNICODE) { |
3479 | smb_buffer->Flags2 |= SMBFLG2_UNICODE; | 3645 | smb_buffer->Flags2 |= SMBFLG2_UNICODE; |
3480 | length = | 3646 | length = |
3481 | cifs_strtoUCS((__le16 *) bcc_ptr, tree, | 3647 | cifs_strtoUTF16((__le16 *) bcc_ptr, tree, |
3482 | 6 /* max utf8 char length in bytes */ * | 3648 | 6 /* max utf8 char length in bytes */ * |
3483 | (/* server len*/ + 256 /* share len */), nls_codepage); | 3649 | (/* server len*/ + 256 /* share len */), nls_codepage); |
3484 | bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */ | 3650 | bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */ |
@@ -3533,7 +3699,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses, | |||
3533 | 3699 | ||
3534 | /* mostly informational -- no need to fail on error here */ | 3700 | /* mostly informational -- no need to fail on error here */ |
3535 | kfree(tcon->nativeFileSystem); | 3701 | kfree(tcon->nativeFileSystem); |
3536 | tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr, | 3702 | tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr, |
3537 | bytes_left, is_unicode, | 3703 | bytes_left, is_unicode, |
3538 | nls_codepage); | 3704 | nls_codepage); |
3539 | 3705 | ||
@@ -3657,16 +3823,38 @@ int cifs_setup_session(unsigned int xid, struct cifs_ses *ses, | |||
3657 | return rc; | 3823 | return rc; |
3658 | } | 3824 | } |
3659 | 3825 | ||
3826 | static int | ||
3827 | cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses) | ||
3828 | { | ||
3829 | switch (ses->server->secType) { | ||
3830 | case Kerberos: | ||
3831 | vol->secFlg = CIFSSEC_MUST_KRB5; | ||
3832 | return 0; | ||
3833 | case NTLMv2: | ||
3834 | vol->secFlg = CIFSSEC_MUST_NTLMV2; | ||
3835 | break; | ||
3836 | case NTLM: | ||
3837 | vol->secFlg = CIFSSEC_MUST_NTLM; | ||
3838 | break; | ||
3839 | case RawNTLMSSP: | ||
3840 | vol->secFlg = CIFSSEC_MUST_NTLMSSP; | ||
3841 | break; | ||
3842 | case LANMAN: | ||
3843 | vol->secFlg = CIFSSEC_MUST_LANMAN; | ||
3844 | break; | ||
3845 | } | ||
3846 | |||
3847 | return cifs_set_cifscreds(vol, ses); | ||
3848 | } | ||
3849 | |||
3660 | static struct cifs_tcon * | 3850 | static struct cifs_tcon * |
3661 | cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) | 3851 | cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) |
3662 | { | 3852 | { |
3853 | int rc; | ||
3663 | struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb); | 3854 | struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb); |
3664 | struct cifs_ses *ses; | 3855 | struct cifs_ses *ses; |
3665 | struct cifs_tcon *tcon = NULL; | 3856 | struct cifs_tcon *tcon = NULL; |
3666 | struct smb_vol *vol_info; | 3857 | struct smb_vol *vol_info; |
3667 | char username[28]; /* big enough for "krb50x" + hex of ULONG_MAX 6+16 */ | ||
3668 | /* We used to have this as MAX_USERNAME which is */ | ||
3669 | /* way too big now (256 instead of 32) */ | ||
3670 | 3858 | ||
3671 | vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL); | 3859 | vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL); |
3672 | if (vol_info == NULL) { | 3860 | if (vol_info == NULL) { |
@@ -3674,8 +3862,6 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) | |||
3674 | goto out; | 3862 | goto out; |
3675 | } | 3863 | } |
3676 | 3864 | ||
3677 | snprintf(username, sizeof(username), "krb50x%x", fsuid); | ||
3678 | vol_info->username = username; | ||
3679 | vol_info->local_nls = cifs_sb->local_nls; | 3865 | vol_info->local_nls = cifs_sb->local_nls; |
3680 | vol_info->linux_uid = fsuid; | 3866 | vol_info->linux_uid = fsuid; |
3681 | vol_info->cred_uid = fsuid; | 3867 | vol_info->cred_uid = fsuid; |
@@ -3685,8 +3871,11 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) | |||
3685 | vol_info->local_lease = master_tcon->local_lease; | 3871 | vol_info->local_lease = master_tcon->local_lease; |
3686 | vol_info->no_linux_ext = !master_tcon->unix_ext; | 3872 | vol_info->no_linux_ext = !master_tcon->unix_ext; |
3687 | 3873 | ||
3688 | /* FIXME: allow for other secFlg settings */ | 3874 | rc = cifs_set_vol_auth(vol_info, master_tcon->ses); |
3689 | vol_info->secFlg = CIFSSEC_MUST_KRB5; | 3875 | if (rc) { |
3876 | tcon = ERR_PTR(rc); | ||
3877 | goto out; | ||
3878 | } | ||
3690 | 3879 | ||
3691 | /* get a reference for the same TCP session */ | 3880 | /* get a reference for the same TCP session */ |
3692 | spin_lock(&cifs_tcp_ses_lock); | 3881 | spin_lock(&cifs_tcp_ses_lock); |
@@ -3709,6 +3898,8 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) | |||
3709 | if (ses->capabilities & CAP_UNIX) | 3898 | if (ses->capabilities & CAP_UNIX) |
3710 | reset_cifs_unix_caps(0, tcon, NULL, vol_info); | 3899 | reset_cifs_unix_caps(0, tcon, NULL, vol_info); |
3711 | out: | 3900 | out: |
3901 | kfree(vol_info->username); | ||
3902 | kfree(vol_info->password); | ||
3712 | kfree(vol_info); | 3903 | kfree(vol_info); |
3713 | 3904 | ||
3714 | return tcon; | 3905 | return tcon; |