aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2012-01-18 16:12:04 -0500
committerSteve French <sfrench@us.ibm.com>2012-01-18 16:12:04 -0500
commit34f598ca0803f399da3438df46c7f56bfe423789 (patch)
treeafea2105e4f057722792a72db49aa21457ad65c8 /fs
parentdcd169b761d52e3f9122e30442b83863bdf1d9d9 (diff)
parent789b4588da40cf572ef982bdc5d590ec1b0386fe (diff)
Merge branch 'master' of git+ssh://git.samba.org/data/git/sfrench/cifs-2.6
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifs_debug.c11
-rw-r--r--fs/cifs/cifs_spnego.c10
-rw-r--r--fs/cifs/cifsencrypt.c11
-rw-r--r--fs/cifs/connect.c301
4 files changed, 271 insertions, 62 deletions
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 84e8c072470..24b3dfc0528 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -676,14 +676,23 @@ static ssize_t cifs_multiuser_mount_proc_write(struct file *file,
676{ 676{
677 char c; 677 char c;
678 int rc; 678 int rc;
679 static bool warned;
679 680
680 rc = get_user(c, buffer); 681 rc = get_user(c, buffer);
681 if (rc) 682 if (rc)
682 return rc; 683 return rc;
683 if (c == '0' || c == 'n' || c == 'N') 684 if (c == '0' || c == 'n' || c == 'N')
684 multiuser_mount = 0; 685 multiuser_mount = 0;
685 else if (c == '1' || c == 'y' || c == 'Y') 686 else if (c == '1' || c == 'y' || c == 'Y') {
686 multiuser_mount = 1; 687 multiuser_mount = 1;
688 if (!warned) {
689 warned = true;
690 printk(KERN_WARNING "CIFS VFS: The legacy multiuser "
691 "mount code is scheduled to be deprecated in "
692 "3.5. Please switch to using the multiuser "
693 "mount option.");
694 }
695 }
687 696
688 return count; 697 return count;
689} 698}
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index 2272fd5fe5b..e622863b292 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -113,9 +113,11 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
113 MAX_MECH_STR_LEN + 113 MAX_MECH_STR_LEN +
114 UID_KEY_LEN + (sizeof(uid_t) * 2) + 114 UID_KEY_LEN + (sizeof(uid_t) * 2) +
115 CREDUID_KEY_LEN + (sizeof(uid_t) * 2) + 115 CREDUID_KEY_LEN + (sizeof(uid_t) * 2) +
116 USER_KEY_LEN + strlen(sesInfo->user_name) +
117 PID_KEY_LEN + (sizeof(pid_t) * 2) + 1; 116 PID_KEY_LEN + (sizeof(pid_t) * 2) + 1;
118 117
118 if (sesInfo->user_name)
119 desc_len += USER_KEY_LEN + strlen(sesInfo->user_name);
120
119 spnego_key = ERR_PTR(-ENOMEM); 121 spnego_key = ERR_PTR(-ENOMEM);
120 description = kzalloc(desc_len, GFP_KERNEL); 122 description = kzalloc(desc_len, GFP_KERNEL);
121 if (description == NULL) 123 if (description == NULL)
@@ -152,8 +154,10 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
152 dp = description + strlen(description); 154 dp = description + strlen(description);
153 sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid); 155 sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid);
154 156
155 dp = description + strlen(description); 157 if (sesInfo->user_name) {
156 sprintf(dp, ";user=%s", sesInfo->user_name); 158 dp = description + strlen(description);
159 sprintf(dp, ";user=%s", sesInfo->user_name);
160 }
157 161
158 dp = description + strlen(description); 162 dp = description + strlen(description);
159 sprintf(dp, ";pid=0x%x", current->pid); 163 sprintf(dp, ";pid=0x%x", current->pid);
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 5d9b9acc5fc..bce99e6a495 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -420,15 +420,20 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
420 } 420 }
421 421
422 /* convert ses->user_name to unicode and uppercase */ 422 /* convert ses->user_name to unicode and uppercase */
423 len = strlen(ses->user_name); 423 len = ses->user_name ? strlen(ses->user_name) : 0;
424 user = kmalloc(2 + (len * 2), GFP_KERNEL); 424 user = kmalloc(2 + (len * 2), GFP_KERNEL);
425 if (user == NULL) { 425 if (user == NULL) {
426 cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n"); 426 cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n");
427 rc = -ENOMEM; 427 rc = -ENOMEM;
428 return rc; 428 return rc;
429 } 429 }
430 len = cifs_strtoUCS((__le16 *)user, ses->user_name, len, nls_cp); 430
431 UniStrupr(user); 431 if (len) {
432 len = cifs_strtoUCS((__le16 *)user, ses->user_name, len, nls_cp);
433 UniStrupr(user);
434 } else {
435 memset(user, '\0', 2);
436 }
432 437
433 rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, 438 rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
434 (char *)user, 2 * len); 439 (char *)user, 2 * len);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 4666780f315..28f23c03da5 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
226static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) 227static 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
298static void 315static 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 */
2074static int
2075cifs_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
2177out_key_put:
2178 up_read(&key->sem);
2179 key_put(key);
2180out_err:
2181 kfree(desc);
2182 cFYI(1, "%s: returning %d", __func__, rc);
2183 return rc;
2184}
2185#else /* ! CONFIG_KEYS */
2186static inline int
2187cifs_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
2042static bool warned_on_ntlm; /* globals init to false automatically */ 2194static bool warned_on_ntlm; /* globals init to false automatically */
2043 2195
2044static struct cifs_ses * 2196static 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
2922static unsigned int 3082static unsigned int
2923cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) 3083cifs_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);
@@ -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
3826static int
3827cifs_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
3660static struct cifs_tcon * 3850static struct cifs_tcon *
3661cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) 3851cifs_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);
3711out: 3900out:
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;