aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-05-11 08:44:27 -0400
committerIngo Molnar <mingo@elte.hu>2009-05-11 08:44:31 -0400
commit41fb454ebe6024f5c1e3b3cbc0abc0da762e7b51 (patch)
tree51c50bcb67a5039448ddfa1869d7948cab1217e9 /fs/cifs
parent19c1a6f5764d787113fa323ffb18be7991208f82 (diff)
parent091bf7624d1c90cec9e578a18529f615213ff847 (diff)
Merge commit 'v2.6.30-rc5' into core/iommu
Merge reason: core/iommu was on an .30-rc1 base, update it to .30-rc5 to refresh. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/CHANGES16
-rw-r--r--fs/cifs/README10
-rw-r--r--fs/cifs/cifs_dfs_ref.c32
-rw-r--r--fs/cifs/cifs_spnego.c2
-rw-r--r--fs/cifs/cifs_unicode.c198
-rw-r--r--fs/cifs/cifs_unicode.h23
-rw-r--r--fs/cifs/cifsfs.c48
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsglob.h19
-rw-r--r--fs/cifs/cifspdu.h8
-rw-r--r--fs/cifs/cifsproto.h5
-rw-r--r--fs/cifs/cifssmb.c223
-rw-r--r--fs/cifs/connect.c1357
-rw-r--r--fs/cifs/dir.c160
-rw-r--r--fs/cifs/dns_resolve.c2
-rw-r--r--fs/cifs/file.c141
-rw-r--r--fs/cifs/inode.c98
-rw-r--r--fs/cifs/link.c114
-rw-r--r--fs/cifs/misc.c71
-rw-r--r--fs/cifs/netmisc.c2
-rw-r--r--fs/cifs/nterr.h9
-rw-r--r--fs/cifs/ntlmssp.h68
-rw-r--r--fs/cifs/readdir.c78
-rw-r--r--fs/cifs/sess.c373
-rw-r--r--fs/cifs/smberr.h1
25 files changed, 1172 insertions, 1888 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 65984006192c..f20c4069c220 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,16 @@
1Version 1.58
2------------
3Guard against buffer overruns in various UCS-2 to UTF-8 string conversions
4when the UTF-8 string is composed of unusually long (more than 4 byte) converted
5characters. Add support for mounting root of a share which redirects immediately
6to DFS target. Convert string conversion functions from Unicode to more
7accurately mark string length before allocating memory (which may help the
8rare cases where a UTF-8 string is much larger than the UCS2 string that
9we converted from). Fix endianness of the vcnum field used during
10session setup to distinguish multiple mounts to same server from different
11userids. Raw NTLMSSP fixed (it requires /proc/fs/cifs/experimental
12flag to be set to 2, and mount must enable krb5 to turn on extended security).
13
1Version 1.57 14Version 1.57
2------------ 15------------
3Improve support for multiple security contexts to the same server. We 16Improve support for multiple security contexts to the same server. We
@@ -15,7 +28,8 @@ Posix file open support added (turned off after one attempt if server
15fails to support it properly, as with Samba server versions prior to 3.3.2) 28fails to support it properly, as with Samba server versions prior to 3.3.2)
16Fix "redzone overwritten" bug in cifs_put_tcon (CIFSTcon may allocate too 29Fix "redzone overwritten" bug in cifs_put_tcon (CIFSTcon may allocate too
17little memory for the "nativeFileSystem" field returned by the server 30little memory for the "nativeFileSystem" field returned by the server
18during mount). 31during mount). Endian convert inode numbers if necessary (makes it easier
32to compare inode numbers on network files from big endian systems).
19 33
20Version 1.56 34Version 1.56
21------------ 35------------
diff --git a/fs/cifs/README b/fs/cifs/README
index 07434181623b..db208ddb9899 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -651,7 +651,15 @@ Experimental When set to 1 used to enable certain experimental
651 signing turned on in case buffer was modified 651 signing turned on in case buffer was modified
652 just before it was sent, also this flag will 652 just before it was sent, also this flag will
653 be used to use the new experimental directory change 653 be used to use the new experimental directory change
654 notification code). 654 notification code). When set to 2 enables
655 an additional experimental feature, "raw ntlmssp"
656 session establishment support (which allows
657 specifying "sec=ntlmssp" on mount). The Linux cifs
658 module will use ntlmv2 authentication encapsulated
659 in "raw ntlmssp" (not using SPNEGO) when
660 "sec=ntlmssp" is specified on mount.
661 This support also requires building cifs with
662 the CONFIG_CIFS_EXPERIMENTAL configuration flag.
655 663
656These experimental features and tracing can be enabled by changing flags in 664These experimental features and tracing can be enabled by changing flags in
657/proc/fs/cifs (after the cifs module has been installed or built into the 665/proc/fs/cifs (after the cifs module has been installed or built into the
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index 5fdbf8a14472..83d62759c7c7 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -340,28 +340,24 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
340 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 340 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
341 341
342 for (i = 0; i < num_referrals; i++) { 342 for (i = 0; i < num_referrals; i++) {
343 int len;
343 dump_referral(referrals+i); 344 dump_referral(referrals+i);
344 /* connect to a storage node */ 345 /* connect to a node */
345 if (referrals[i].flags & DFSREF_STORAGE_SERVER) { 346 len = strlen(referrals[i].node_name);
346 int len; 347 if (len < 2) {
347 len = strlen(referrals[i].node_name); 348 cERROR(1, ("%s: Net Address path too short: %s",
348 if (len < 2) {
349 cERROR(1, ("%s: Net Address path too short: %s",
350 __func__, referrals[i].node_name)); 349 __func__, referrals[i].node_name));
351 rc = -EINVAL; 350 rc = -EINVAL;
352 goto out_err; 351 goto out_err;
353 } 352 }
354 mnt = cifs_dfs_do_refmount(nd->path.mnt, 353 mnt = cifs_dfs_do_refmount(nd->path.mnt,
355 nd->path.dentry, 354 nd->path.dentry, referrals + i);
356 referrals + i); 355 cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__,
357 cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p",
358 __func__,
359 referrals[i].node_name, mnt)); 356 referrals[i].node_name, mnt));
360 357
361 /* complete mount procedure if we accured submount */ 358 /* complete mount procedure if we accured submount */
362 if (!IS_ERR(mnt)) 359 if (!IS_ERR(mnt))
363 break; 360 break;
364 }
365 } 361 }
366 362
367 /* we need it cause for() above could exit without valid submount */ 363 /* we need it cause for() above could exit without valid submount */
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index 3fd3a9df043a..67bf93a40d2e 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -41,7 +41,7 @@ cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen)
41 41
42 /* attach the data */ 42 /* attach the data */
43 memcpy(payload, data, datalen); 43 memcpy(payload, data, datalen);
44 rcu_assign_pointer(key->payload.data, payload); 44 key->payload.data = payload;
45 ret = 0; 45 ret = 0;
46 46
47error: 47error:
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 7d75272a6b3f..60e3c4253de0 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifs_unicode.c 2 * fs/cifs/cifs_unicode.c
3 * 3 *
4 * Copyright (c) International Business Machines Corp., 2000,2005 4 * Copyright (c) International Business Machines Corp., 2000,2009
5 * Modified by Steve French (sfrench@us.ibm.com) 5 * Modified by Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -26,31 +26,157 @@
26#include "cifs_debug.h" 26#include "cifs_debug.h"
27 27
28/* 28/*
29 * NAME: cifs_strfromUCS() 29 * cifs_ucs2_bytes - how long will a string be after conversion?
30 * 30 * @ucs - pointer to input string
31 * FUNCTION: Convert little-endian unicode string to character string 31 * @maxbytes - don't go past this many bytes of input string
32 * @codepage - destination codepage
32 * 33 *
34 * Walk a ucs2le string and return the number of bytes that the string will
35 * be after being converted to the given charset, not including any null
36 * termination required. Don't walk past maxbytes in the source buffer.
33 */ 37 */
34int 38int
35cifs_strfromUCS_le(char *to, const __le16 *from, 39cifs_ucs2_bytes(const __le16 *from, int maxbytes,
36 int len, const struct nls_table *codepage) 40 const struct nls_table *codepage)
37{ 41{
38 int i; 42 int i;
39 int outlen = 0; 43 int charlen, outlen = 0;
44 int maxwords = maxbytes / 2;
45 char tmp[NLS_MAX_CHARSET_SIZE];
40 46
41 for (i = 0; (i < len) && from[i]; i++) { 47 for (i = 0; from[i] && i < maxwords; i++) {
42 int charlen; 48 charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp,
43 /* 2.4.0 kernel or greater */ 49 NLS_MAX_CHARSET_SIZE);
44 charlen = 50 if (charlen > 0)
45 codepage->uni2char(le16_to_cpu(from[i]), &to[outlen],
46 NLS_MAX_CHARSET_SIZE);
47 if (charlen > 0) {
48 outlen += charlen; 51 outlen += charlen;
49 } else { 52 else
50 to[outlen++] = '?'; 53 outlen++;
54 }
55
56 return outlen;
57}
58
59/*
60 * cifs_mapchar - convert a little-endian char to proper char in codepage
61 * @target - where converted character should be copied
62 * @src_char - 2 byte little-endian source character
63 * @cp - codepage to which character should be converted
64 * @mapchar - should character be mapped according to mapchars mount option?
65 *
66 * This function handles the conversion of a single character. It is the
67 * responsibility of the caller to ensure that the target buffer is large
68 * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE).
69 */
70static int
71cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp,
72 bool mapchar)
73{
74 int len = 1;
75
76 if (!mapchar)
77 goto cp_convert;
78
79 /*
80 * BB: Cannot handle remapping UNI_SLASH until all the calls to
81 * build_path_from_dentry are modified, as they use slash as
82 * separator.
83 */
84 switch (le16_to_cpu(src_char)) {
85 case UNI_COLON:
86 *target = ':';
87 break;
88 case UNI_ASTERIK:
89 *target = '*';
90 break;
91 case UNI_QUESTION:
92 *target = '?';
93 break;
94 case UNI_PIPE:
95 *target = '|';
96 break;
97 case UNI_GRTRTHAN:
98 *target = '>';
99 break;
100 case UNI_LESSTHAN:
101 *target = '<';
102 break;
103 default:
104 goto cp_convert;
105 }
106
107out:
108 return len;
109
110cp_convert:
111 len = cp->uni2char(le16_to_cpu(src_char), target,
112 NLS_MAX_CHARSET_SIZE);
113 if (len <= 0) {
114 *target = '?';
115 len = 1;
116 }
117 goto out;
118}
119
120/*
121 * cifs_from_ucs2 - convert utf16le string to local charset
122 * @to - destination buffer
123 * @from - source buffer
124 * @tolen - destination buffer size (in bytes)
125 * @fromlen - source buffer size (in bytes)
126 * @codepage - codepage to which characters should be converted
127 * @mapchar - should characters be remapped according to the mapchars option?
128 *
129 * Convert a little-endian ucs2le string (as sent by the server) to a string
130 * in the provided codepage. The tolen and fromlen parameters are to ensure
131 * that the code doesn't walk off of the end of the buffer (which is always
132 * a danger if the alignment of the source buffer is off). The destination
133 * string is always properly null terminated and fits in the destination
134 * buffer. Returns the length of the destination string in bytes (including
135 * null terminator).
136 *
137 * Note that some windows versions actually send multiword UTF-16 characters
138 * instead of straight UCS-2. The linux nls routines however aren't able to
139 * deal with those characters properly. In the event that we get some of
140 * those characters, they won't be translated properly.
141 */
142int
143cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
144 const struct nls_table *codepage, bool mapchar)
145{
146 int i, charlen, safelen;
147 int outlen = 0;
148 int nullsize = nls_nullsize(codepage);
149 int fromwords = fromlen / 2;
150 char tmp[NLS_MAX_CHARSET_SIZE];
151
152 /*
153 * because the chars can be of varying widths, we need to take care
154 * not to overflow the destination buffer when we get close to the
155 * end of it. Until we get to this offset, we don't need to check
156 * for overflow however.
157 */
158 safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize);
159
160 for (i = 0; i < fromwords && from[i]; i++) {
161 /*
162 * check to see if converting this character might make the
163 * conversion bleed into the null terminator
164 */
165 if (outlen >= safelen) {
166 charlen = cifs_mapchar(tmp, from[i], codepage, mapchar);
167 if ((outlen + charlen) > (tolen - nullsize))
168 break;
51 } 169 }
170
171 /* put converted char into 'to' buffer */
172 charlen = cifs_mapchar(&to[outlen], from[i], codepage, mapchar);
173 outlen += charlen;
52 } 174 }
53 to[outlen] = 0; 175
176 /* properly null-terminate string */
177 for (i = 0; i < nullsize; i++)
178 to[outlen++] = 0;
179
54 return outlen; 180 return outlen;
55} 181}
56 182
@@ -88,3 +214,41 @@ cifs_strtoUCS(__le16 *to, const char *from, int len,
88 return i; 214 return i;
89} 215}
90 216
217/*
218 * cifs_strndup_from_ucs - copy a string from wire format to the local codepage
219 * @src - source string
220 * @maxlen - don't walk past this many bytes in the source string
221 * @is_unicode - is this a unicode string?
222 * @codepage - destination codepage
223 *
224 * Take a string given by the server, convert it to the local codepage and
225 * put it in a new buffer. Returns a pointer to the new string or NULL on
226 * error.
227 */
228char *
229cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode,
230 const struct nls_table *codepage)
231{
232 int len;
233 char *dst;
234
235 if (is_unicode) {
236 len = cifs_ucs2_bytes((__le16 *) src, maxlen, codepage);
237 len += nls_nullsize(codepage);
238 dst = kmalloc(len, GFP_KERNEL);
239 if (!dst)
240 return NULL;
241 cifs_from_ucs2(dst, (__le16 *) src, len, maxlen, codepage,
242 false);
243 } else {
244 len = strnlen(src, maxlen);
245 len++;
246 dst = kmalloc(len, GFP_KERNEL);
247 if (!dst)
248 return NULL;
249 strlcpy(dst, src, len);
250 }
251
252 return dst;
253}
254
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
index 14eb9a2395d3..650638275a6f 100644
--- a/fs/cifs/cifs_unicode.h
+++ b/fs/cifs/cifs_unicode.h
@@ -5,7 +5,7 @@
5 * Convert a unicode character to upper or lower case using 5 * Convert a unicode character to upper or lower case using
6 * compressed tables. 6 * compressed tables.
7 * 7 *
8 * Copyright (c) International Business Machines Corp., 2000,2007 8 * Copyright (c) International Business Machines Corp., 2000,2009
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -37,6 +37,19 @@
37 37
38#define UNIUPR_NOLOWER /* Example to not expand lower case tables */ 38#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
39 39
40/*
41 * Windows maps these to the user defined 16 bit Unicode range since they are
42 * reserved symbols (along with \ and /), otherwise illegal to store
43 * in filenames in NTFS
44 */
45#define UNI_ASTERIK (__u16) ('*' + 0xF000)
46#define UNI_QUESTION (__u16) ('?' + 0xF000)
47#define UNI_COLON (__u16) (':' + 0xF000)
48#define UNI_GRTRTHAN (__u16) ('>' + 0xF000)
49#define UNI_LESSTHAN (__u16) ('<' + 0xF000)
50#define UNI_PIPE (__u16) ('|' + 0xF000)
51#define UNI_SLASH (__u16) ('\\' + 0xF000)
52
40/* Just define what we want from uniupr.h. We don't want to define the tables 53/* Just define what we want from uniupr.h. We don't want to define the tables
41 * in each source file. 54 * in each source file.
42 */ 55 */
@@ -59,8 +72,14 @@ extern struct UniCaseRange UniLowerRange[];
59#endif /* UNIUPR_NOLOWER */ 72#endif /* UNIUPR_NOLOWER */
60 73
61#ifdef __KERNEL__ 74#ifdef __KERNEL__
62int cifs_strfromUCS_le(char *, const __le16 *, int, const struct nls_table *); 75int cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
76 const struct nls_table *codepage, bool mapchar);
77int cifs_ucs2_bytes(const __le16 *from, int maxbytes,
78 const struct nls_table *codepage);
63int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *); 79int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
80char *cifs_strndup_from_ucs(const char *src, const int maxlen,
81 const bool is_unicode,
82 const struct nls_table *codepage);
64#endif 83#endif
65 84
66/* 85/*
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 38491fd3871d..0d6d8b573652 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -66,9 +66,6 @@ unsigned int sign_CIFS_PDUs = 1;
66extern struct task_struct *oplockThread; /* remove sparse warning */ 66extern struct task_struct *oplockThread; /* remove sparse warning */
67struct task_struct *oplockThread = NULL; 67struct task_struct *oplockThread = NULL;
68/* extern struct task_struct * dnotifyThread; remove sparse warning */ 68/* extern struct task_struct * dnotifyThread; remove sparse warning */
69#ifdef CONFIG_CIFS_EXPERIMENTAL
70static struct task_struct *dnotifyThread = NULL;
71#endif
72static const struct super_operations cifs_super_ops; 69static const struct super_operations cifs_super_ops;
73unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; 70unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
74module_param(CIFSMaxBufSize, int, 0); 71module_param(CIFSMaxBufSize, int, 0);
@@ -316,6 +313,7 @@ cifs_alloc_inode(struct super_block *sb)
316 cifs_inode->clientCanCacheAll = false; 313 cifs_inode->clientCanCacheAll = false;
317 cifs_inode->delete_pending = false; 314 cifs_inode->delete_pending = false;
318 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ 315 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
316 cifs_inode->server_eof = 0;
319 317
320 /* Can not set i_flags here - they get immediately overwritten 318 /* Can not set i_flags here - they get immediately overwritten
321 to zero by the VFS */ 319 to zero by the VFS */
@@ -1040,34 +1038,6 @@ static int cifs_oplock_thread(void *dummyarg)
1040 return 0; 1038 return 0;
1041} 1039}
1042 1040
1043#ifdef CONFIG_CIFS_EXPERIMENTAL
1044static int cifs_dnotify_thread(void *dummyarg)
1045{
1046 struct list_head *tmp;
1047 struct TCP_Server_Info *server;
1048
1049 do {
1050 if (try_to_freeze())
1051 continue;
1052 set_current_state(TASK_INTERRUPTIBLE);
1053 schedule_timeout(15*HZ);
1054 /* check if any stuck requests that need
1055 to be woken up and wakeq so the
1056 thread can wake up and error out */
1057 read_lock(&cifs_tcp_ses_lock);
1058 list_for_each(tmp, &cifs_tcp_ses_list) {
1059 server = list_entry(tmp, struct TCP_Server_Info,
1060 tcp_ses_list);
1061 if (atomic_read(&server->inFlight))
1062 wake_up_all(&server->response_q);
1063 }
1064 read_unlock(&cifs_tcp_ses_lock);
1065 } while (!kthread_should_stop());
1066
1067 return 0;
1068}
1069#endif
1070
1071static int __init 1041static int __init
1072init_cifs(void) 1042init_cifs(void)
1073{ 1043{
@@ -1144,21 +1114,8 @@ init_cifs(void)
1144 goto out_unregister_dfs_key_type; 1114 goto out_unregister_dfs_key_type;
1145 } 1115 }
1146 1116
1147#ifdef CONFIG_CIFS_EXPERIMENTAL
1148 dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
1149 if (IS_ERR(dnotifyThread)) {
1150 rc = PTR_ERR(dnotifyThread);
1151 cERROR(1, ("error %d create dnotify thread", rc));
1152 goto out_stop_oplock_thread;
1153 }
1154#endif
1155
1156 return 0; 1117 return 0;
1157 1118
1158#ifdef CONFIG_CIFS_EXPERIMENTAL
1159 out_stop_oplock_thread:
1160#endif
1161 kthread_stop(oplockThread);
1162 out_unregister_dfs_key_type: 1119 out_unregister_dfs_key_type:
1163#ifdef CONFIG_CIFS_DFS_UPCALL 1120#ifdef CONFIG_CIFS_DFS_UPCALL
1164 unregister_key_type(&key_type_dns_resolver); 1121 unregister_key_type(&key_type_dns_resolver);
@@ -1196,9 +1153,6 @@ exit_cifs(void)
1196 cifs_destroy_inodecache(); 1153 cifs_destroy_inodecache();
1197 cifs_destroy_mids(); 1154 cifs_destroy_mids();
1198 cifs_destroy_request_bufs(); 1155 cifs_destroy_request_bufs();
1199#ifdef CONFIG_CIFS_EXPERIMENTAL
1200 kthread_stop(dnotifyThread);
1201#endif
1202 kthread_stop(oplockThread); 1156 kthread_stop(oplockThread);
1203} 1157}
1204 1158
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 77e190dc2883..051b71cfdea9 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -100,5 +100,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
100extern const struct export_operations cifs_export_ops; 100extern const struct export_operations cifs_export_ops;
101#endif /* EXPERIMENTAL */ 101#endif /* EXPERIMENTAL */
102 102
103#define CIFS_VERSION "1.57" 103#define CIFS_VERSION "1.58"
104#endif /* _CIFSFS_H */ 104#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 9fbf4dff5da6..a61ab772c6f6 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -82,8 +82,8 @@ enum securityEnum {
82 LANMAN, /* Legacy LANMAN auth */ 82 LANMAN, /* Legacy LANMAN auth */
83 NTLM, /* Legacy NTLM012 auth with NTLM hash */ 83 NTLM, /* Legacy NTLM012 auth with NTLM hash */
84 NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ 84 NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
85 RawNTLMSSP, /* NTLMSSP without SPNEGO */ 85 RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */
86 NTLMSSP, /* NTLMSSP via SPNEGO */ 86 NTLMSSP, /* NTLMSSP via SPNEGO, NTLMv2 hash */
87 Kerberos, /* Kerberos via SPNEGO */ 87 Kerberos, /* Kerberos via SPNEGO */
88 MSKerberos, /* MS Kerberos via SPNEGO */ 88 MSKerberos, /* MS Kerberos via SPNEGO */
89}; 89};
@@ -350,7 +350,7 @@ struct cifsFileInfo {
350 bool invalidHandle:1; /* file closed via session abend */ 350 bool invalidHandle:1; /* file closed via session abend */
351 bool messageMode:1; /* for pipes: message vs byte mode */ 351 bool messageMode:1; /* for pipes: message vs byte mode */
352 atomic_t wrtPending; /* handle in use - defer close */ 352 atomic_t wrtPending; /* handle in use - defer close */
353 struct semaphore fh_sem; /* prevents reopen race after dead ses*/ 353 struct mutex fh_mutex; /* prevents reopen race after dead ses*/
354 struct cifs_search_info srch_inf; 354 struct cifs_search_info srch_inf;
355}; 355};
356 356
@@ -370,6 +370,7 @@ struct cifsInodeInfo {
370 bool clientCanCacheAll:1; /* read and writebehind oplock */ 370 bool clientCanCacheAll:1; /* read and writebehind oplock */
371 bool oplockPending:1; 371 bool oplockPending:1;
372 bool delete_pending:1; /* DELETE_ON_CLOSE is set */ 372 bool delete_pending:1; /* DELETE_ON_CLOSE is set */
373 u64 server_eof; /* current file size on server */
373 struct inode vfs_inode; 374 struct inode vfs_inode;
374}; 375};
375 376
@@ -530,6 +531,7 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
530#define CIFSSEC_MAY_PLNTXT 0 531#define CIFSSEC_MAY_PLNTXT 0
531#endif /* weak passwords */ 532#endif /* weak passwords */
532#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */ 533#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
534#define CIFSSEC_MAY_NTLMSSP 0x00080 /* raw ntlmssp with ntlmv2 */
533 535
534#define CIFSSEC_MUST_SIGN 0x01001 536#define CIFSSEC_MUST_SIGN 0x01001
535/* note that only one of the following can be set so the 537/* note that only one of the following can be set so the
@@ -542,22 +544,23 @@ require use of the stronger protocol */
542#define CIFSSEC_MUST_LANMAN 0x10010 544#define CIFSSEC_MUST_LANMAN 0x10010
543#define CIFSSEC_MUST_PLNTXT 0x20020 545#define CIFSSEC_MUST_PLNTXT 0x20020
544#ifdef CONFIG_CIFS_UPCALL 546#ifdef CONFIG_CIFS_UPCALL
545#define CIFSSEC_MASK 0x3F03F /* allows weak security but also krb5 */ 547#define CIFSSEC_MASK 0xAF0AF /* allows weak security but also krb5 */
546#else 548#else
547#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */ 549#define CIFSSEC_MASK 0xA70A7 /* current flags supported if weak */
548#endif /* UPCALL */ 550#endif /* UPCALL */
549#else /* do not allow weak pw hash */ 551#else /* do not allow weak pw hash */
550#ifdef CONFIG_CIFS_UPCALL 552#ifdef CONFIG_CIFS_UPCALL
551#define CIFSSEC_MASK 0x0F00F /* flags supported if no weak allowed */ 553#define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */
552#else 554#else
553#define CIFSSEC_MASK 0x07007 /* flags supported if no weak allowed */ 555#define CIFSSEC_MASK 0x87087 /* flags supported if no weak allowed */
554#endif /* UPCALL */ 556#endif /* UPCALL */
555#endif /* WEAK_PW_HASH */ 557#endif /* WEAK_PW_HASH */
556#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */ 558#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
559#define CIFSSEC_MUST_NTLMSSP 0x80080 /* raw ntlmssp with ntlmv2 */
557 560
558#define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2) 561#define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2)
559#define CIFSSEC_MAX (CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2) 562#define CIFSSEC_MAX (CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2)
560#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5) 563#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP)
561/* 564/*
562 ***************************************************************** 565 *****************************************************************
563 * All constants go here 566 * All constants go here
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index b370489c8da5..a785f69dbc9f 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -2163,7 +2163,7 @@ typedef struct {
2163 __le32 Type; 2163 __le32 Type;
2164 __le64 DevMajor; 2164 __le64 DevMajor;
2165 __le64 DevMinor; 2165 __le64 DevMinor;
2166 __u64 UniqueId; 2166 __le64 UniqueId;
2167 __le64 Permissions; 2167 __le64 Permissions;
2168 __le64 Nlinks; 2168 __le64 Nlinks;
2169} __attribute__((packed)) FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */ 2169} __attribute__((packed)) FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */
@@ -2308,7 +2308,7 @@ struct unlink_psx_rq { /* level 0x20a SetPathInfo */
2308} __attribute__((packed)); 2308} __attribute__((packed));
2309 2309
2310struct file_internal_info { 2310struct file_internal_info {
2311 __u64 UniqueId; /* inode number */ 2311 __le64 UniqueId; /* inode number */
2312} __attribute__((packed)); /* level 0x3ee */ 2312} __attribute__((packed)); /* level 0x3ee */
2313 2313
2314struct file_mode_info { 2314struct file_mode_info {
@@ -2338,7 +2338,7 @@ typedef struct {
2338 __le32 Type; 2338 __le32 Type;
2339 __le64 DevMajor; 2339 __le64 DevMajor;
2340 __le64 DevMinor; 2340 __le64 DevMinor;
2341 __u64 UniqueId; 2341 __le64 UniqueId;
2342 __le64 Permissions; 2342 __le64 Permissions;
2343 __le64 Nlinks; 2343 __le64 Nlinks;
2344 char FileName[1]; 2344 char FileName[1];
@@ -2386,7 +2386,7 @@ typedef struct {
2386 __le32 FileNameLength; 2386 __le32 FileNameLength;
2387 __le32 EaSize; /* EA size */ 2387 __le32 EaSize; /* EA size */
2388 __le32 Reserved; 2388 __le32 Reserved;
2389 __u64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/ 2389 __le64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
2390 char FileName[1]; 2390 char FileName[1];
2391} __attribute__((packed)) SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF rsp data */ 2391} __attribute__((packed)) SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF rsp data */
2392 2392
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 4167716d32f2..fae083930eee 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -260,8 +260,7 @@ extern int CIFSUnixCreateSymLink(const int xid,
260 const struct nls_table *nls_codepage); 260 const struct nls_table *nls_codepage);
261extern int CIFSSMBUnixQuerySymLink(const int xid, 261extern int CIFSSMBUnixQuerySymLink(const int xid,
262 struct cifsTconInfo *tcon, 262 struct cifsTconInfo *tcon,
263 const unsigned char *searchName, 263 const unsigned char *searchName, char **syminfo,
264 char *syminfo, const int buflen,
265 const struct nls_table *nls_codepage); 264 const struct nls_table *nls_codepage);
266extern int CIFSSMBQueryReparseLinkInfo(const int xid, 265extern int CIFSSMBQueryReparseLinkInfo(const int xid,
267 struct cifsTconInfo *tcon, 266 struct cifsTconInfo *tcon,
@@ -307,8 +306,6 @@ extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
307 const unsigned char *searchName, __u64 *inode_number, 306 const unsigned char *searchName, __u64 *inode_number,
308 const struct nls_table *nls_codepage, 307 const struct nls_table *nls_codepage,
309 int remap_special_chars); 308 int remap_special_chars);
310extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
311 const struct nls_table *codepage);
312extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen, 309extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
313 const struct nls_table *cp, int mapChars); 310 const struct nls_table *cp, int mapChars);
314 311
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index bc09c998631f..75e6623a8635 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifssmb.c 2 * fs/cifs/cifssmb.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2008 4 * Copyright (C) International Business Machines Corp., 2002,2009
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * Contains the routines for constructing the SMB PDUs themselves 7 * Contains the routines for constructing the SMB PDUs themselves
@@ -81,41 +81,6 @@ static struct {
81#endif /* CONFIG_CIFS_WEAK_PW_HASH */ 81#endif /* CONFIG_CIFS_WEAK_PW_HASH */
82#endif /* CIFS_POSIX */ 82#endif /* CIFS_POSIX */
83 83
84/* Allocates buffer into dst and copies smb string from src to it.
85 * caller is responsible for freeing dst if function returned 0.
86 * returns:
87 * on success - 0
88 * on failure - errno
89 */
90static int
91cifs_strncpy_to_host(char **dst, const char *src, const int maxlen,
92 const bool is_unicode, const struct nls_table *nls_codepage)
93{
94 int plen;
95
96 if (is_unicode) {
97 plen = UniStrnlen((wchar_t *)src, maxlen);
98 *dst = kmalloc(plen + 2, GFP_KERNEL);
99 if (!*dst)
100 goto cifs_strncpy_to_host_ErrExit;
101 cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
102 } else {
103 plen = strnlen(src, maxlen);
104 *dst = kmalloc(plen + 2, GFP_KERNEL);
105 if (!*dst)
106 goto cifs_strncpy_to_host_ErrExit;
107 strncpy(*dst, src, plen);
108 }
109 (*dst)[plen] = 0;
110 (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */
111 return 0;
112
113cifs_strncpy_to_host_ErrExit:
114 cERROR(1, ("Failed to allocate buffer for string\n"));
115 return -ENOMEM;
116}
117
118
119/* Mark as invalid, all open files on tree connections since they 84/* Mark as invalid, all open files on tree connections since they
120 were closed when session to server was lost */ 85 were closed when session to server was lost */
121static void mark_open_files_invalid(struct cifsTconInfo *pTcon) 86static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
@@ -484,6 +449,14 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
484 cFYI(1, ("Kerberos only mechanism, enable extended security")); 449 cFYI(1, ("Kerberos only mechanism, enable extended security"));
485 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 450 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
486 } 451 }
452#ifdef CONFIG_CIFS_EXPERIMENTAL
453 else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
454 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
455 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
456 cFYI(1, ("NTLMSSP only mechanism, enable extended security"));
457 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
458 }
459#endif
487 460
488 count = 0; 461 count = 0;
489 for (i = 0; i < CIFS_NUM_PROT; i++) { 462 for (i = 0; i < CIFS_NUM_PROT; i++) {
@@ -620,6 +593,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
620 server->secType = NTLMv2; 593 server->secType = NTLMv2;
621 else if (secFlags & CIFSSEC_MAY_KRB5) 594 else if (secFlags & CIFSSEC_MAY_KRB5)
622 server->secType = Kerberos; 595 server->secType = Kerberos;
596 else if (secFlags & CIFSSEC_MAY_NTLMSSP)
597 server->secType = NTLMSSP;
623 else if (secFlags & CIFSSEC_MAY_LANMAN) 598 else if (secFlags & CIFSSEC_MAY_LANMAN)
624 server->secType = LANMAN; 599 server->secType = LANMAN;
625/* #ifdef CONFIG_CIFS_EXPERIMENTAL 600/* #ifdef CONFIG_CIFS_EXPERIMENTAL
@@ -1626,6 +1601,8 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1626 int smb_hdr_len; 1601 int smb_hdr_len;
1627 int resp_buf_type = 0; 1602 int resp_buf_type = 0;
1628 1603
1604 *nbytes = 0;
1605
1629 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count)); 1606 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1630 1607
1631 if (tcon->ses->capabilities & CAP_LARGE_FILES) { 1608 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
@@ -1682,11 +1659,9 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1682 cifs_stats_inc(&tcon->num_writes); 1659 cifs_stats_inc(&tcon->num_writes);
1683 if (rc) { 1660 if (rc) {
1684 cFYI(1, ("Send error Write2 = %d", rc)); 1661 cFYI(1, ("Send error Write2 = %d", rc));
1685 *nbytes = 0;
1686 } else if (resp_buf_type == 0) { 1662 } else if (resp_buf_type == 0) {
1687 /* presumably this can not happen, but best to be safe */ 1663 /* presumably this can not happen, but best to be safe */
1688 rc = -EIO; 1664 rc = -EIO;
1689 *nbytes = 0;
1690 } else { 1665 } else {
1691 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base; 1666 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1692 *nbytes = le16_to_cpu(pSMBr->CountHigh); 1667 *nbytes = le16_to_cpu(pSMBr->CountHigh);
@@ -2417,8 +2392,7 @@ winCreateHardLinkRetry:
2417 2392
2418int 2393int
2419CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon, 2394CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2420 const unsigned char *searchName, 2395 const unsigned char *searchName, char **symlinkinfo,
2421 char *symlinkinfo, const int buflen,
2422 const struct nls_table *nls_codepage) 2396 const struct nls_table *nls_codepage)
2423{ 2397{
2424/* SMB_QUERY_FILE_UNIX_LINK */ 2398/* SMB_QUERY_FILE_UNIX_LINK */
@@ -2428,6 +2402,7 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2428 int bytes_returned; 2402 int bytes_returned;
2429 int name_len; 2403 int name_len;
2430 __u16 params, byte_count; 2404 __u16 params, byte_count;
2405 char *data_start;
2431 2406
2432 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName)); 2407 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2433 2408
@@ -2482,30 +2457,26 @@ querySymLinkRetry:
2482 /* decode response */ 2457 /* decode response */
2483 2458
2484 rc = validate_t2((struct smb_t2_rsp *)pSMBr); 2459 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2485 if (rc || (pSMBr->ByteCount < 2))
2486 /* BB also check enough total bytes returned */ 2460 /* BB also check enough total bytes returned */
2487 rc = -EIO; /* bad smb */ 2461 if (rc || (pSMBr->ByteCount < 2))
2462 rc = -EIO;
2488 else { 2463 else {
2489 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); 2464 bool is_unicode;
2490 __u16 count = le16_to_cpu(pSMBr->t2.DataCount); 2465 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2466
2467 data_start = ((char *) &pSMBr->hdr.Protocol) +
2468 le16_to_cpu(pSMBr->t2.DataOffset);
2469
2470 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2471 is_unicode = true;
2472 else
2473 is_unicode = false;
2491 2474
2492 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2493 name_len = UniStrnlen((wchar_t *) ((char *)
2494 &pSMBr->hdr.Protocol + data_offset),
2495 min_t(const int, buflen, count) / 2);
2496 /* BB FIXME investigate remapping reserved chars here */ 2475 /* BB FIXME investigate remapping reserved chars here */
2497 cifs_strfromUCS_le(symlinkinfo, 2476 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2498 (__le16 *) ((char *)&pSMBr->hdr.Protocol 2477 is_unicode, nls_codepage);
2499 + data_offset), 2478 if (!symlinkinfo)
2500 name_len, nls_codepage); 2479 rc = -ENOMEM;
2501 } else {
2502 strncpy(symlinkinfo,
2503 (char *) &pSMBr->hdr.Protocol +
2504 data_offset,
2505 min_t(const int, buflen, count));
2506 }
2507 symlinkinfo[buflen] = 0;
2508 /* just in case so calling code does not go off the end of buffer */
2509 } 2480 }
2510 } 2481 }
2511 cifs_buf_release(pSMB); 2482 cifs_buf_release(pSMB);
@@ -2603,7 +2574,6 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata,
2603 *pparmlen = parm_count; 2574 *pparmlen = parm_count;
2604 return 0; 2575 return 0;
2605} 2576}
2606#endif /* CIFS_EXPERIMENTAL */
2607 2577
2608int 2578int
2609CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, 2579CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
@@ -2613,7 +2583,6 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2613{ 2583{
2614 int rc = 0; 2584 int rc = 0;
2615 int bytes_returned; 2585 int bytes_returned;
2616 int name_len;
2617 struct smb_com_transaction_ioctl_req *pSMB; 2586 struct smb_com_transaction_ioctl_req *pSMB;
2618 struct smb_com_transaction_ioctl_rsp *pSMBr; 2587 struct smb_com_transaction_ioctl_rsp *pSMBr;
2619 2588
@@ -2650,59 +2619,55 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2650 } else { /* decode response */ 2619 } else { /* decode response */
2651 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset); 2620 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2652 __u32 data_count = le32_to_cpu(pSMBr->DataCount); 2621 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2653 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) 2622 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2654 /* BB also check enough total bytes returned */ 2623 /* BB also check enough total bytes returned */
2655 rc = -EIO; /* bad smb */ 2624 rc = -EIO; /* bad smb */
2656 else { 2625 goto qreparse_out;
2657 if (data_count && (data_count < 2048)) { 2626 }
2658 char *end_of_smb = 2 /* sizeof byte count */ + 2627 if (data_count && (data_count < 2048)) {
2659 pSMBr->ByteCount + 2628 char *end_of_smb = 2 /* sizeof byte count */ +
2660 (char *)&pSMBr->ByteCount; 2629 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2661 2630
2662 struct reparse_data *reparse_buf = 2631 struct reparse_data *reparse_buf =
2663 (struct reparse_data *) 2632 (struct reparse_data *)
2664 ((char *)&pSMBr->hdr.Protocol 2633 ((char *)&pSMBr->hdr.Protocol
2665 + data_offset); 2634 + data_offset);
2666 if ((char *)reparse_buf >= end_of_smb) { 2635 if ((char *)reparse_buf >= end_of_smb) {
2667 rc = -EIO; 2636 rc = -EIO;
2668 goto qreparse_out; 2637 goto qreparse_out;
2669 } 2638 }
2670 if ((reparse_buf->LinkNamesBuf + 2639 if ((reparse_buf->LinkNamesBuf +
2671 reparse_buf->TargetNameOffset + 2640 reparse_buf->TargetNameOffset +
2672 reparse_buf->TargetNameLen) > 2641 reparse_buf->TargetNameLen) > end_of_smb) {
2673 end_of_smb) { 2642 cFYI(1, ("reparse buf beyond SMB"));
2674 cFYI(1, ("reparse buf beyond SMB")); 2643 rc = -EIO;
2675 rc = -EIO; 2644 goto qreparse_out;
2676 goto qreparse_out; 2645 }
2677 }
2678 2646
2679 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { 2647 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2680 name_len = UniStrnlen((wchar_t *) 2648 cifs_from_ucs2(symlinkinfo, (__le16 *)
2681 (reparse_buf->LinkNamesBuf + 2649 (reparse_buf->LinkNamesBuf +
2682 reparse_buf->TargetNameOffset), 2650 reparse_buf->TargetNameOffset),
2683 min(buflen/2, 2651 buflen,
2684 reparse_buf->TargetNameLen / 2)); 2652 reparse_buf->TargetNameLen,
2685 cifs_strfromUCS_le(symlinkinfo, 2653 nls_codepage, 0);
2686 (__le16 *) (reparse_buf->LinkNamesBuf + 2654 } else { /* ASCII names */
2687 reparse_buf->TargetNameOffset), 2655 strncpy(symlinkinfo,
2688 name_len, nls_codepage); 2656 reparse_buf->LinkNamesBuf +
2689 } else { /* ASCII names */ 2657 reparse_buf->TargetNameOffset,
2690 strncpy(symlinkinfo, 2658 min_t(const int, buflen,
2691 reparse_buf->LinkNamesBuf + 2659 reparse_buf->TargetNameLen));
2692 reparse_buf->TargetNameOffset,
2693 min_t(const int, buflen,
2694 reparse_buf->TargetNameLen));
2695 }
2696 } else {
2697 rc = -EIO;
2698 cFYI(1, ("Invalid return data count on "
2699 "get reparse info ioctl"));
2700 } 2660 }
2701 symlinkinfo[buflen] = 0; /* just in case so the caller 2661 } else {
2702 does not go off the end of the buffer */ 2662 rc = -EIO;
2703 cFYI(1, ("readlink result - %s", symlinkinfo)); 2663 cFYI(1, ("Invalid return data count on "
2664 "get reparse info ioctl"));
2704 } 2665 }
2666 symlinkinfo[buflen] = 0; /* just in case so the caller
2667 does not go off the end of the buffer */
2668 cFYI(1, ("readlink result - %s", symlinkinfo));
2705 } 2669 }
2670
2706qreparse_out: 2671qreparse_out:
2707 cifs_buf_release(pSMB); 2672 cifs_buf_release(pSMB);
2708 2673
@@ -2711,6 +2676,7 @@ qreparse_out:
2711 2676
2712 return rc; 2677 return rc;
2713} 2678}
2679#endif /* CIFS_EXPERIMENTAL */
2714 2680
2715#ifdef CONFIG_CIFS_POSIX 2681#ifdef CONFIG_CIFS_POSIX
2716 2682
@@ -3918,7 +3884,7 @@ GetInodeNumberRetry:
3918 } 3884 }
3919 pfinfo = (struct file_internal_info *) 3885 pfinfo = (struct file_internal_info *)
3920 (data_offset + (char *) &pSMBr->hdr.Protocol); 3886 (data_offset + (char *) &pSMBr->hdr.Protocol);
3921 *inode_number = pfinfo->UniqueId; 3887 *inode_number = le64_to_cpu(pfinfo->UniqueId);
3922 } 3888 }
3923 } 3889 }
3924GetInodeNumOut: 3890GetInodeNumOut:
@@ -3928,27 +3894,6 @@ GetInodeNumOut:
3928 return rc; 3894 return rc;
3929} 3895}
3930 3896
3931/* computes length of UCS string converted to host codepage
3932 * @src: UCS string
3933 * @maxlen: length of the input string in UCS characters
3934 * (not in bytes)
3935 *
3936 * return: size of input string in host codepage
3937 */
3938static int hostlen_fromUCS(const __le16 *src, const int maxlen,
3939 const struct nls_table *nls_codepage) {
3940 int i;
3941 int hostlen = 0;
3942 char to[4];
3943 int charlen;
3944 for (i = 0; (i < maxlen) && src[i]; ++i) {
3945 charlen = nls_codepage->uni2char(le16_to_cpu(src[i]),
3946 to, NLS_MAX_CHARSET_SIZE);
3947 hostlen += charlen > 0 ? charlen : 1;
3948 }
3949 return hostlen;
3950}
3951
3952/* parses DFS refferal V3 structure 3897/* parses DFS refferal V3 structure
3953 * caller is responsible for freeing target_nodes 3898 * caller is responsible for freeing target_nodes
3954 * returns: 3899 * returns:
@@ -3994,7 +3939,7 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3994 3939
3995 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n", 3940 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3996 *num_of_nodes, 3941 *num_of_nodes,
3997 le16_to_cpu(pSMBr->DFSFlags))); 3942 le32_to_cpu(pSMBr->DFSFlags)));
3998 3943
3999 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) * 3944 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4000 *num_of_nodes, GFP_KERNEL); 3945 *num_of_nodes, GFP_KERNEL);
@@ -4010,14 +3955,14 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4010 int max_len; 3955 int max_len;
4011 struct dfs_info3_param *node = (*target_nodes)+i; 3956 struct dfs_info3_param *node = (*target_nodes)+i;
4012 3957
4013 node->flags = le16_to_cpu(pSMBr->DFSFlags); 3958 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4014 if (is_unicode) { 3959 if (is_unicode) {
4015 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2, 3960 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4016 GFP_KERNEL); 3961 GFP_KERNEL);
4017 cifsConvertToUCS((__le16 *) tmp, searchName, 3962 cifsConvertToUCS((__le16 *) tmp, searchName,
4018 PATH_MAX, nls_codepage, remap); 3963 PATH_MAX, nls_codepage, remap);
4019 node->path_consumed = hostlen_fromUCS(tmp, 3964 node->path_consumed = cifs_ucs2_bytes(tmp,
4020 le16_to_cpu(pSMBr->PathConsumed)/2, 3965 le16_to_cpu(pSMBr->PathConsumed),
4021 nls_codepage); 3966 nls_codepage);
4022 kfree(tmp); 3967 kfree(tmp);
4023 } else 3968 } else
@@ -4029,20 +3974,24 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4029 /* copy DfsPath */ 3974 /* copy DfsPath */
4030 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset); 3975 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4031 max_len = data_end - temp; 3976 max_len = data_end - temp;
4032 rc = cifs_strncpy_to_host(&(node->path_name), temp, 3977 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4033 max_len, is_unicode, nls_codepage); 3978 is_unicode, nls_codepage);
4034 if (rc) 3979 if (IS_ERR(node->path_name)) {
3980 rc = PTR_ERR(node->path_name);
3981 node->path_name = NULL;
4035 goto parse_DFS_referrals_exit; 3982 goto parse_DFS_referrals_exit;
3983 }
4036 3984
4037 /* copy link target UNC */ 3985 /* copy link target UNC */
4038 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset); 3986 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4039 max_len = data_end - temp; 3987 max_len = data_end - temp;
4040 rc = cifs_strncpy_to_host(&(node->node_name), temp, 3988 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4041 max_len, is_unicode, nls_codepage); 3989 is_unicode, nls_codepage);
4042 if (rc) 3990 if (IS_ERR(node->node_name)) {
3991 rc = PTR_ERR(node->node_name);
3992 node->node_name = NULL;
4043 goto parse_DFS_referrals_exit; 3993 goto parse_DFS_referrals_exit;
4044 3994 }
4045 ref += le16_to_cpu(ref->Size);
4046 } 3995 }
4047 3996
4048parse_DFS_referrals_exit: 3997parse_DFS_referrals_exit:
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 0de3b5615a22..4aa81a507b74 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/connect.c 2 * fs/cifs/connect.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2008 4 * Copyright (C) International Business Machines Corp., 2002,2009
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -32,6 +32,7 @@
32#include <linux/kthread.h> 32#include <linux/kthread.h>
33#include <linux/pagevec.h> 33#include <linux/pagevec.h>
34#include <linux/freezer.h> 34#include <linux/freezer.h>
35#include <linux/namei.h>
35#include <asm/uaccess.h> 36#include <asm/uaccess.h>
36#include <asm/processor.h> 37#include <asm/processor.h>
37#include <net/ipv6.h> 38#include <net/ipv6.h>
@@ -978,6 +979,13 @@ cifs_parse_mount_options(char *options, const char *devname,
978 return 1; 979 return 1;
979 } else if (strnicmp(value, "krb5", 4) == 0) { 980 } else if (strnicmp(value, "krb5", 4) == 0) {
980 vol->secFlg |= CIFSSEC_MAY_KRB5; 981 vol->secFlg |= CIFSSEC_MAY_KRB5;
982#ifdef CONFIG_CIFS_EXPERIMENTAL
983 } else if (strnicmp(value, "ntlmsspi", 8) == 0) {
984 vol->secFlg |= CIFSSEC_MAY_NTLMSSP |
985 CIFSSEC_MUST_SIGN;
986 } else if (strnicmp(value, "ntlmssp", 7) == 0) {
987 vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
988#endif
981 } else if (strnicmp(value, "ntlmv2i", 7) == 0) { 989 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
982 vol->secFlg |= CIFSSEC_MAY_NTLMV2 | 990 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
983 CIFSSEC_MUST_SIGN; 991 CIFSSEC_MUST_SIGN;
@@ -2214,9 +2222,58 @@ is_path_accessible(int xid, struct cifsTconInfo *tcon,
2214 return rc; 2222 return rc;
2215} 2223}
2216 2224
2225static void
2226cleanup_volume_info(struct smb_vol **pvolume_info)
2227{
2228 struct smb_vol *volume_info;
2229
2230 if (!pvolume_info && !*pvolume_info)
2231 return;
2232
2233 volume_info = *pvolume_info;
2234 kzfree(volume_info->password);
2235 kfree(volume_info->UNC);
2236 kfree(volume_info->prepath);
2237 kfree(volume_info);
2238 *pvolume_info = NULL;
2239 return;
2240}
2241
2242#ifdef CONFIG_CIFS_DFS_UPCALL
2243/* build_path_to_root returns full path to root when
2244 * we do not have an exiting connection (tcon) */
2245static char *
2246build_unc_path_to_root(const struct smb_vol *volume_info,
2247 const struct cifs_sb_info *cifs_sb)
2248{
2249 char *full_path;
2250
2251 int unc_len = strnlen(volume_info->UNC, MAX_TREE_SIZE + 1);
2252 full_path = kmalloc(unc_len + cifs_sb->prepathlen + 1, GFP_KERNEL);
2253 if (full_path == NULL)
2254 return ERR_PTR(-ENOMEM);
2255
2256 strncpy(full_path, volume_info->UNC, unc_len);
2257 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
2258 int i;
2259 for (i = 0; i < unc_len; i++) {
2260 if (full_path[i] == '\\')
2261 full_path[i] = '/';
2262 }
2263 }
2264
2265 if (cifs_sb->prepathlen)
2266 strncpy(full_path + unc_len, cifs_sb->prepath,
2267 cifs_sb->prepathlen);
2268
2269 full_path[unc_len + cifs_sb->prepathlen] = 0; /* add trailing null */
2270 return full_path;
2271}
2272#endif
2273
2217int 2274int
2218cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, 2275cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2219 char *mount_data, const char *devname) 2276 char *mount_data_global, const char *devname)
2220{ 2277{
2221 int rc = 0; 2278 int rc = 0;
2222 int xid; 2279 int xid;
@@ -2225,6 +2282,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2225 struct cifsTconInfo *tcon = NULL; 2282 struct cifsTconInfo *tcon = NULL;
2226 struct TCP_Server_Info *srvTcp = NULL; 2283 struct TCP_Server_Info *srvTcp = NULL;
2227 char *full_path; 2284 char *full_path;
2285 char *mount_data = mount_data_global;
2286#ifdef CONFIG_CIFS_DFS_UPCALL
2287 struct dfs_info3_param *referrals = NULL;
2288 unsigned int num_referrals = 0;
2289 int referral_walks_count = 0;
2290try_mount_again:
2291#endif
2292 full_path = NULL;
2228 2293
2229 xid = GetXid(); 2294 xid = GetXid();
2230 2295
@@ -2371,11 +2436,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2371 } 2436 }
2372 } 2437 }
2373 2438
2374 /* check for null share name ie connect to dfs root */
2375 if ((strchr(volume_info->UNC + 3, '\\') == NULL) 2439 if ((strchr(volume_info->UNC + 3, '\\') == NULL)
2376 && (strchr(volume_info->UNC + 3, '/') == NULL)) { 2440 && (strchr(volume_info->UNC + 3, '/') == NULL)) {
2377 /* rc = connect_to_dfs_path(...) */ 2441 cERROR(1, ("Missing share name"));
2378 cFYI(1, ("DFS root not supported"));
2379 rc = -ENODEV; 2442 rc = -ENODEV;
2380 goto mount_fail_check; 2443 goto mount_fail_check;
2381 } else { 2444 } else {
@@ -2392,7 +2455,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2392 } 2455 }
2393 } 2456 }
2394 if (rc) 2457 if (rc)
2395 goto mount_fail_check; 2458 goto remote_path_check;
2396 tcon->seal = volume_info->seal; 2459 tcon->seal = volume_info->seal;
2397 write_lock(&cifs_tcp_ses_lock); 2460 write_lock(&cifs_tcp_ses_lock);
2398 list_add(&tcon->tcon_list, &pSesInfo->tcon_list); 2461 list_add(&tcon->tcon_list, &pSesInfo->tcon_list);
@@ -2417,19 +2480,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2417 /* BB FIXME fix time_gran to be larger for LANMAN sessions */ 2480 /* BB FIXME fix time_gran to be larger for LANMAN sessions */
2418 sb->s_time_gran = 100; 2481 sb->s_time_gran = 100;
2419 2482
2420mount_fail_check: 2483 if (rc)
2421 /* on error free sesinfo and tcon struct if needed */ 2484 goto remote_path_check;
2422 if (rc) { 2485
2423 /* If find_unc succeeded then rc == 0 so we can not end */
2424 /* up accidently freeing someone elses tcon struct */
2425 if (tcon)
2426 cifs_put_tcon(tcon);
2427 else if (pSesInfo)
2428 cifs_put_smb_ses(pSesInfo);
2429 else
2430 cifs_put_tcp_session(srvTcp);
2431 goto out;
2432 }
2433 cifs_sb->tcon = tcon; 2486 cifs_sb->tcon = tcon;
2434 2487
2435 /* do not care if following two calls succeed - informational */ 2488 /* do not care if following two calls succeed - informational */
@@ -2461,7 +2514,9 @@ mount_fail_check:
2461 cifs_sb->rsize = min(cifs_sb->rsize, 2514 cifs_sb->rsize = min(cifs_sb->rsize,
2462 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); 2515 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
2463 2516
2464 if (!rc && cifs_sb->prepathlen) { 2517remote_path_check:
2518 /* check if a whole path (including prepath) is not remote */
2519 if (!rc && cifs_sb->prepathlen && tcon) {
2465 /* build_path_to_root works only when we have a valid tcon */ 2520 /* build_path_to_root works only when we have a valid tcon */
2466 full_path = cifs_build_path_to_root(cifs_sb); 2521 full_path = cifs_build_path_to_root(cifs_sb);
2467 if (full_path == NULL) { 2522 if (full_path == NULL) {
@@ -2469,1079 +2524,91 @@ mount_fail_check:
2469 goto mount_fail_check; 2524 goto mount_fail_check;
2470 } 2525 }
2471 rc = is_path_accessible(xid, tcon, cifs_sb, full_path); 2526 rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
2472 if (rc) { 2527 if (rc != -EREMOTE) {
2473 cERROR(1, ("Path %s in not accessible: %d",
2474 full_path, rc));
2475 kfree(full_path); 2528 kfree(full_path);
2476 goto mount_fail_check; 2529 goto mount_fail_check;
2477 } 2530 }
2478 kfree(full_path); 2531 kfree(full_path);
2479 } 2532 }
2480 2533
2481 /* volume_info->password is freed above when existing session found 2534 /* get referral if needed */
2482 (in which case it is not needed anymore) but when new sesion is created 2535 if (rc == -EREMOTE) {
2483 the password ptr is put in the new session structure (in which case the 2536#ifdef CONFIG_CIFS_DFS_UPCALL
2484 password will be freed at unmount time) */ 2537 if (referral_walks_count > MAX_NESTED_LINKS) {
2485out: 2538 /*
2486 /* zero out password before freeing */ 2539 * BB: when we implement proper loop detection,
2487 if (volume_info) { 2540 * we will remove this check. But now we need it
2488 if (volume_info->password != NULL) { 2541 * to prevent an indefinite loop if 'DFS tree' is
2489 memset(volume_info->password, 0, 2542 * misconfigured (i.e. has loops).
2490 strlen(volume_info->password)); 2543 */
2491 kfree(volume_info->password); 2544 rc = -ELOOP;
2492 } 2545 goto mount_fail_check;
2493 kfree(volume_info->UNC);
2494 kfree(volume_info->prepath);
2495 kfree(volume_info);
2496 }
2497 FreeXid(xid);
2498 return rc;
2499}
2500
2501static int
2502CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2503 char session_key[CIFS_SESS_KEY_SIZE],
2504 const struct nls_table *nls_codepage)
2505{
2506 struct smb_hdr *smb_buffer;
2507 struct smb_hdr *smb_buffer_response;
2508 SESSION_SETUP_ANDX *pSMB;
2509 SESSION_SETUP_ANDX *pSMBr;
2510 char *bcc_ptr;
2511 char *user;
2512 char *domain;
2513 int rc = 0;
2514 int remaining_words = 0;
2515 int bytes_returned = 0;
2516 int len;
2517 __u32 capabilities;
2518 __u16 count;
2519
2520 cFYI(1, ("In sesssetup"));
2521 if (ses == NULL)
2522 return -EINVAL;
2523 user = ses->userName;
2524 domain = ses->domainName;
2525 smb_buffer = cifs_buf_get();
2526
2527 if (smb_buffer == NULL)
2528 return -ENOMEM;
2529
2530 smb_buffer_response = smb_buffer;
2531 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2532
2533 /* send SMBsessionSetup here */
2534 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2535 NULL /* no tCon exists yet */ , 13 /* wct */ );
2536
2537 smb_buffer->Mid = GetNextMid(ses->server);
2538 pSMB->req_no_secext.AndXCommand = 0xFF;
2539 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2540 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2541
2542 if (ses->server->secMode &
2543 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2544 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2545
2546 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2547 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
2548 if (ses->capabilities & CAP_UNICODE) {
2549 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2550 capabilities |= CAP_UNICODE;
2551 }
2552 if (ses->capabilities & CAP_STATUS32) {
2553 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2554 capabilities |= CAP_STATUS32;
2555 }
2556 if (ses->capabilities & CAP_DFS) {
2557 smb_buffer->Flags2 |= SMBFLG2_DFS;
2558 capabilities |= CAP_DFS;
2559 }
2560 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
2561
2562 pSMB->req_no_secext.CaseInsensitivePasswordLength =
2563 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2564
2565 pSMB->req_no_secext.CaseSensitivePasswordLength =
2566 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2567 bcc_ptr = pByteArea(smb_buffer);
2568 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2569 bcc_ptr += CIFS_SESS_KEY_SIZE;
2570 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2571 bcc_ptr += CIFS_SESS_KEY_SIZE;
2572
2573 if (ses->capabilities & CAP_UNICODE) {
2574 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
2575 *bcc_ptr = 0;
2576 bcc_ptr++;
2577 }
2578 if (user == NULL)
2579 bytes_returned = 0; /* skip null user */
2580 else
2581 bytes_returned =
2582 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
2583 nls_codepage);
2584 /* convert number of 16 bit words to bytes */
2585 bcc_ptr += 2 * bytes_returned;
2586 bcc_ptr += 2; /* trailing null */
2587 if (domain == NULL)
2588 bytes_returned =
2589 cifs_strtoUCS((__le16 *) bcc_ptr,
2590 "CIFS_LINUX_DOM", 32, nls_codepage);
2591 else
2592 bytes_returned =
2593 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2594 nls_codepage);
2595 bcc_ptr += 2 * bytes_returned;
2596 bcc_ptr += 2;
2597 bytes_returned =
2598 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2599 32, nls_codepage);
2600 bcc_ptr += 2 * bytes_returned;
2601 bytes_returned =
2602 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release,
2603 32, nls_codepage);
2604 bcc_ptr += 2 * bytes_returned;
2605 bcc_ptr += 2;
2606 bytes_returned =
2607 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2608 64, nls_codepage);
2609 bcc_ptr += 2 * bytes_returned;
2610 bcc_ptr += 2;
2611 } else {
2612 if (user != NULL) {
2613 strncpy(bcc_ptr, user, 200);
2614 bcc_ptr += strnlen(user, 200);
2615 }
2616 *bcc_ptr = 0;
2617 bcc_ptr++;
2618 if (domain == NULL) {
2619 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2620 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2621 } else {
2622 strncpy(bcc_ptr, domain, 64);
2623 bcc_ptr += strnlen(domain, 64);
2624 *bcc_ptr = 0;
2625 bcc_ptr++;
2626 }
2627 strcpy(bcc_ptr, "Linux version ");
2628 bcc_ptr += strlen("Linux version ");
2629 strcpy(bcc_ptr, utsname()->release);
2630 bcc_ptr += strlen(utsname()->release) + 1;
2631 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2632 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2633 }
2634 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2635 smb_buffer->smb_buf_length += count;
2636 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
2637
2638 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2639 &bytes_returned, CIFS_LONG_OP);
2640 if (rc) {
2641/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
2642 } else if ((smb_buffer_response->WordCount == 3)
2643 || (smb_buffer_response->WordCount == 4)) {
2644 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2645 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2646 if (action & GUEST_LOGIN)
2647 cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */
2648 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format
2649 (little endian) */
2650 cFYI(1, ("UID = %d ", ses->Suid));
2651 /* response can have either 3 or 4 word count - Samba sends 3 */
2652 bcc_ptr = pByteArea(smb_buffer_response);
2653 if ((pSMBr->resp.hdr.WordCount == 3)
2654 || ((pSMBr->resp.hdr.WordCount == 4)
2655 && (blob_len < pSMBr->resp.ByteCount))) {
2656 if (pSMBr->resp.hdr.WordCount == 4)
2657 bcc_ptr += blob_len;
2658
2659 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2660 if ((long) (bcc_ptr) % 2) {
2661 remaining_words =
2662 (BCC(smb_buffer_response) - 1) / 2;
2663 /* Unicode strings must be word
2664 aligned */
2665 bcc_ptr++;
2666 } else {
2667 remaining_words =
2668 BCC(smb_buffer_response) / 2;
2669 }
2670 len =
2671 UniStrnlen((wchar_t *) bcc_ptr,
2672 remaining_words - 1);
2673/* We look for obvious messed up bcc or strings in response so we do not go off
2674 the end since (at least) WIN2K and Windows XP have a major bug in not null
2675 terminating last Unicode string in response */
2676 if (ses->serverOS)
2677 kfree(ses->serverOS);
2678 ses->serverOS = kzalloc(2 * (len + 1),
2679 GFP_KERNEL);
2680 if (ses->serverOS == NULL)
2681 goto sesssetup_nomem;
2682 cifs_strfromUCS_le(ses->serverOS,
2683 (__le16 *)bcc_ptr,
2684 len, nls_codepage);
2685 bcc_ptr += 2 * (len + 1);
2686 remaining_words -= len + 1;
2687 ses->serverOS[2 * len] = 0;
2688 ses->serverOS[1 + (2 * len)] = 0;
2689 if (remaining_words > 0) {
2690 len = UniStrnlen((wchar_t *)bcc_ptr,
2691 remaining_words-1);
2692 kfree(ses->serverNOS);
2693 ses->serverNOS = kzalloc(2 * (len + 1),
2694 GFP_KERNEL);
2695 if (ses->serverNOS == NULL)
2696 goto sesssetup_nomem;
2697 cifs_strfromUCS_le(ses->serverNOS,
2698 (__le16 *)bcc_ptr,
2699 len, nls_codepage);
2700 bcc_ptr += 2 * (len + 1);
2701 ses->serverNOS[2 * len] = 0;
2702 ses->serverNOS[1 + (2 * len)] = 0;
2703 if (strncmp(ses->serverNOS,
2704 "NT LAN Manager 4", 16) == 0) {
2705 cFYI(1, ("NT4 server"));
2706 ses->flags |= CIFS_SES_NT4;
2707 }
2708 remaining_words -= len + 1;
2709 if (remaining_words > 0) {
2710 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2711 /* last string is not always null terminated
2712 (for e.g. for Windows XP & 2000) */
2713 if (ses->serverDomain)
2714 kfree(ses->serverDomain);
2715 ses->serverDomain =
2716 kzalloc(2*(len+1),
2717 GFP_KERNEL);
2718 if (ses->serverDomain == NULL)
2719 goto sesssetup_nomem;
2720 cifs_strfromUCS_le(ses->serverDomain,
2721 (__le16 *)bcc_ptr,
2722 len, nls_codepage);
2723 bcc_ptr += 2 * (len + 1);
2724 ses->serverDomain[2*len] = 0;
2725 ses->serverDomain[1+(2*len)] = 0;
2726 } else { /* else no more room so create
2727 dummy domain string */
2728 if (ses->serverDomain)
2729 kfree(ses->serverDomain);
2730 ses->serverDomain =
2731 kzalloc(2, GFP_KERNEL);
2732 }
2733 } else { /* no room so create dummy domain
2734 and NOS string */
2735
2736 /* if these kcallocs fail not much we
2737 can do, but better to not fail the
2738 sesssetup itself */
2739 kfree(ses->serverDomain);
2740 ses->serverDomain =
2741 kzalloc(2, GFP_KERNEL);
2742 kfree(ses->serverNOS);
2743 ses->serverNOS =
2744 kzalloc(2, GFP_KERNEL);
2745 }
2746 } else { /* ASCII */
2747 len = strnlen(bcc_ptr, 1024);
2748 if (((long) bcc_ptr + len) - (long)
2749 pByteArea(smb_buffer_response)
2750 <= BCC(smb_buffer_response)) {
2751 kfree(ses->serverOS);
2752 ses->serverOS = kzalloc(len + 1,
2753 GFP_KERNEL);
2754 if (ses->serverOS == NULL)
2755 goto sesssetup_nomem;
2756 strncpy(ses->serverOS, bcc_ptr, len);
2757
2758 bcc_ptr += len;
2759 /* null terminate the string */
2760 bcc_ptr[0] = 0;
2761 bcc_ptr++;
2762
2763 len = strnlen(bcc_ptr, 1024);
2764 kfree(ses->serverNOS);
2765 ses->serverNOS = kzalloc(len + 1,
2766 GFP_KERNEL);
2767 if (ses->serverNOS == NULL)
2768 goto sesssetup_nomem;
2769 strncpy(ses->serverNOS, bcc_ptr, len);
2770 bcc_ptr += len;
2771 bcc_ptr[0] = 0;
2772 bcc_ptr++;
2773
2774 len = strnlen(bcc_ptr, 1024);
2775 if (ses->serverDomain)
2776 kfree(ses->serverDomain);
2777 ses->serverDomain = kzalloc(len + 1,
2778 GFP_KERNEL);
2779 if (ses->serverDomain == NULL)
2780 goto sesssetup_nomem;
2781 strncpy(ses->serverDomain, bcc_ptr,
2782 len);
2783 bcc_ptr += len;
2784 bcc_ptr[0] = 0;
2785 bcc_ptr++;
2786 } else
2787 cFYI(1,
2788 ("Variable field of length %d "
2789 "extends beyond end of smb ",
2790 len));
2791 }
2792 } else {
2793 cERROR(1, ("Security Blob Length extends beyond "
2794 "end of SMB"));
2795 } 2546 }
2796 } else { 2547 /* convert forward to back slashes in prepath here if needed */
2797 cERROR(1, ("Invalid Word count %d: ", 2548 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
2798 smb_buffer_response->WordCount)); 2549 convert_delimiter(cifs_sb->prepath,
2799 rc = -EIO; 2550 CIFS_DIR_SEP(cifs_sb));
2800 } 2551 full_path = build_unc_path_to_root(volume_info, cifs_sb);
2801sesssetup_nomem: /* do not return an error on nomem for the info strings, 2552 if (IS_ERR(full_path)) {
2802 since that could make reconnection harder, and 2553 rc = PTR_ERR(full_path);
2803 reconnection might be needed to free memory */ 2554 goto mount_fail_check;
2804 cifs_buf_release(smb_buffer);
2805
2806 return rc;
2807}
2808
2809static int
2810CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2811 struct cifsSesInfo *ses, bool *pNTLMv2_flag,
2812 const struct nls_table *nls_codepage)
2813{
2814 struct smb_hdr *smb_buffer;
2815 struct smb_hdr *smb_buffer_response;
2816 SESSION_SETUP_ANDX *pSMB;
2817 SESSION_SETUP_ANDX *pSMBr;
2818 char *bcc_ptr;
2819 char *domain;
2820 int rc = 0;
2821 int remaining_words = 0;
2822 int bytes_returned = 0;
2823 int len;
2824 int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
2825 PNEGOTIATE_MESSAGE SecurityBlob;
2826 PCHALLENGE_MESSAGE SecurityBlob2;
2827 __u32 negotiate_flags, capabilities;
2828 __u16 count;
2829
2830 cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
2831 if (ses == NULL)
2832 return -EINVAL;
2833 domain = ses->domainName;
2834 *pNTLMv2_flag = false;
2835 smb_buffer = cifs_buf_get();
2836 if (smb_buffer == NULL) {
2837 return -ENOMEM;
2838 }
2839 smb_buffer_response = smb_buffer;
2840 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2841 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2842
2843 /* send SMBsessionSetup here */
2844 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2845 NULL /* no tCon exists yet */ , 12 /* wct */ );
2846
2847 smb_buffer->Mid = GetNextMid(ses->server);
2848 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2849 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2850
2851 pSMB->req.AndXCommand = 0xFF;
2852 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2853 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2854
2855 if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2856 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2857
2858 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2859 CAP_EXTENDED_SECURITY;
2860 if (ses->capabilities & CAP_UNICODE) {
2861 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2862 capabilities |= CAP_UNICODE;
2863 }
2864 if (ses->capabilities & CAP_STATUS32) {
2865 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2866 capabilities |= CAP_STATUS32;
2867 }
2868 if (ses->capabilities & CAP_DFS) {
2869 smb_buffer->Flags2 |= SMBFLG2_DFS;
2870 capabilities |= CAP_DFS;
2871 }
2872 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2873
2874 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2875 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2876 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2877 SecurityBlob->MessageType = NtLmNegotiate;
2878 negotiate_flags =
2879 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2880 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
2881 NTLMSSP_NEGOTIATE_56 |
2882 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2883 if (sign_CIFS_PDUs)
2884 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2885/* if (ntlmv2_support)
2886 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
2887 /* setup pointers to domain name and workstation name */
2888 bcc_ptr += SecurityBlobLength;
2889
2890 SecurityBlob->WorkstationName.Buffer = 0;
2891 SecurityBlob->WorkstationName.Length = 0;
2892 SecurityBlob->WorkstationName.MaximumLength = 0;
2893
2894 /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
2895 along with username on auth request (ie the response to challenge) */
2896 SecurityBlob->DomainName.Buffer = 0;
2897 SecurityBlob->DomainName.Length = 0;
2898 SecurityBlob->DomainName.MaximumLength = 0;
2899 if (ses->capabilities & CAP_UNICODE) {
2900 if ((long) bcc_ptr % 2) {
2901 *bcc_ptr = 0;
2902 bcc_ptr++;
2903 } 2555 }
2904 2556
2905 bytes_returned = 2557 cFYI(1, ("Getting referral for: %s", full_path));
2906 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ", 2558 rc = get_dfs_path(xid, pSesInfo , full_path + 1,
2907 32, nls_codepage); 2559 cifs_sb->local_nls, &num_referrals, &referrals,
2908 bcc_ptr += 2 * bytes_returned; 2560 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
2909 bytes_returned = 2561 if (!rc && num_referrals > 0) {
2910 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32, 2562 char *fake_devname = NULL;
2911 nls_codepage); 2563
2912 bcc_ptr += 2 * bytes_returned; 2564 if (mount_data != mount_data_global)
2913 bcc_ptr += 2; /* null terminate Linux version */ 2565 kfree(mount_data);
2914 bytes_returned = 2566 mount_data = cifs_compose_mount_options(
2915 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, 2567 cifs_sb->mountdata, full_path + 1,
2916 64, nls_codepage); 2568 referrals, &fake_devname);
2917 bcc_ptr += 2 * bytes_returned; 2569 kfree(fake_devname);
2918 *(bcc_ptr + 1) = 0; 2570 free_dfs_info_array(referrals, num_referrals);
2919 *(bcc_ptr + 2) = 0; 2571
2920 bcc_ptr += 2; /* null terminate network opsys string */ 2572 if (tcon)
2921 *(bcc_ptr + 1) = 0; 2573 cifs_put_tcon(tcon);
2922 *(bcc_ptr + 2) = 0; 2574 else if (pSesInfo)
2923 bcc_ptr += 2; /* null domain */ 2575 cifs_put_smb_ses(pSesInfo);
2924 } else { /* ASCII */ 2576
2925 strcpy(bcc_ptr, "Linux version "); 2577 cleanup_volume_info(&volume_info);
2926 bcc_ptr += strlen("Linux version "); 2578 FreeXid(xid);
2927 strcpy(bcc_ptr, utsname()->release); 2579 kfree(full_path);
2928 bcc_ptr += strlen(utsname()->release) + 1; 2580 referral_walks_count++;
2929 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); 2581 goto try_mount_again;
2930 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2931 bcc_ptr++; /* empty domain field */
2932 *bcc_ptr = 0;
2933 }
2934 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2935 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2936 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2937 smb_buffer->smb_buf_length += count;
2938 pSMB->req.ByteCount = cpu_to_le16(count);
2939
2940 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2941 &bytes_returned, CIFS_LONG_OP);
2942
2943 if (smb_buffer_response->Status.CifsError ==
2944 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2945 rc = 0;
2946
2947 if (rc) {
2948/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2949 } else if ((smb_buffer_response->WordCount == 3)
2950 || (smb_buffer_response->WordCount == 4)) {
2951 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2952 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2953
2954 if (action & GUEST_LOGIN)
2955 cFYI(1, ("Guest login"));
2956 /* Do we want to set anything in SesInfo struct when guest login? */
2957
2958 bcc_ptr = pByteArea(smb_buffer_response);
2959 /* response can have either 3 or 4 word count - Samba sends 3 */
2960
2961 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2962 if (SecurityBlob2->MessageType != NtLmChallenge) {
2963 cFYI(1, ("Unexpected NTLMSSP message type received %d",
2964 SecurityBlob2->MessageType));
2965 } else if (ses) {
2966 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2967 cFYI(1, ("UID = %d", ses->Suid));
2968 if ((pSMBr->resp.hdr.WordCount == 3)
2969 || ((pSMBr->resp.hdr.WordCount == 4)
2970 && (blob_len <
2971 pSMBr->resp.ByteCount))) {
2972
2973 if (pSMBr->resp.hdr.WordCount == 4) {
2974 bcc_ptr += blob_len;
2975 cFYI(1, ("Security Blob Length %d",
2976 blob_len));
2977 }
2978
2979 cFYI(1, ("NTLMSSP Challenge rcvd"));
2980
2981 memcpy(ses->server->cryptKey,
2982 SecurityBlob2->Challenge,
2983 CIFS_CRYPTO_KEY_SIZE);
2984 if (SecurityBlob2->NegotiateFlags &
2985 cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2986 *pNTLMv2_flag = true;
2987
2988 if ((SecurityBlob2->NegotiateFlags &
2989 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2990 || (sign_CIFS_PDUs > 1))
2991 ses->server->secMode |=
2992 SECMODE_SIGN_REQUIRED;
2993 if ((SecurityBlob2->NegotiateFlags &
2994 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2995 ses->server->secMode |=
2996 SECMODE_SIGN_ENABLED;
2997
2998 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2999 if ((long) (bcc_ptr) % 2) {
3000 remaining_words =
3001 (BCC(smb_buffer_response)
3002 - 1) / 2;
3003 /* Must word align unicode strings */
3004 bcc_ptr++;
3005 } else {
3006 remaining_words =
3007 BCC
3008 (smb_buffer_response) / 2;
3009 }
3010 len =
3011 UniStrnlen((wchar_t *) bcc_ptr,
3012 remaining_words - 1);
3013/* We look for obvious messed up bcc or strings in response so we do not go off
3014 the end since (at least) WIN2K and Windows XP have a major bug in not null
3015 terminating last Unicode string in response */
3016 if (ses->serverOS)
3017 kfree(ses->serverOS);
3018 ses->serverOS =
3019 kzalloc(2 * (len + 1), GFP_KERNEL);
3020 cifs_strfromUCS_le(ses->serverOS,
3021 (__le16 *)
3022 bcc_ptr, len,
3023 nls_codepage);
3024 bcc_ptr += 2 * (len + 1);
3025 remaining_words -= len + 1;
3026 ses->serverOS[2 * len] = 0;
3027 ses->serverOS[1 + (2 * len)] = 0;
3028 if (remaining_words > 0) {
3029 len = UniStrnlen((wchar_t *)
3030 bcc_ptr,
3031 remaining_words
3032 - 1);
3033 kfree(ses->serverNOS);
3034 ses->serverNOS =
3035 kzalloc(2 * (len + 1),
3036 GFP_KERNEL);
3037 cifs_strfromUCS_le(ses->
3038 serverNOS,
3039 (__le16 *)
3040 bcc_ptr,
3041 len,
3042 nls_codepage);
3043 bcc_ptr += 2 * (len + 1);
3044 ses->serverNOS[2 * len] = 0;
3045 ses->serverNOS[1 +
3046 (2 * len)] = 0;
3047 remaining_words -= len + 1;
3048 if (remaining_words > 0) {
3049 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3050 /* last string not always null terminated
3051 (for e.g. for Windows XP & 2000) */
3052 kfree(ses->serverDomain);
3053 ses->serverDomain =
3054 kzalloc(2 *
3055 (len +
3056 1),
3057 GFP_KERNEL);
3058 cifs_strfromUCS_le
3059 (ses->serverDomain,
3060 (__le16 *)bcc_ptr,
3061 len, nls_codepage);
3062 bcc_ptr +=
3063 2 * (len + 1);
3064 ses->serverDomain[2*len]
3065 = 0;
3066 ses->serverDomain
3067 [1 + (2 * len)]
3068 = 0;
3069 } /* else no more room so create dummy domain string */
3070 else {
3071 kfree(ses->serverDomain);
3072 ses->serverDomain =
3073 kzalloc(2,
3074 GFP_KERNEL);
3075 }
3076 } else { /* no room so create dummy domain and NOS string */
3077 kfree(ses->serverDomain);
3078 ses->serverDomain =
3079 kzalloc(2, GFP_KERNEL);
3080 kfree(ses->serverNOS);
3081 ses->serverNOS =
3082 kzalloc(2, GFP_KERNEL);
3083 }
3084 } else { /* ASCII */
3085 len = strnlen(bcc_ptr, 1024);
3086 if (((long) bcc_ptr + len) - (long)
3087 pByteArea(smb_buffer_response)
3088 <= BCC(smb_buffer_response)) {
3089 if (ses->serverOS)
3090 kfree(ses->serverOS);
3091 ses->serverOS =
3092 kzalloc(len + 1,
3093 GFP_KERNEL);
3094 strncpy(ses->serverOS,
3095 bcc_ptr, len);
3096
3097 bcc_ptr += len;
3098 bcc_ptr[0] = 0; /* null terminate string */
3099 bcc_ptr++;
3100
3101 len = strnlen(bcc_ptr, 1024);
3102 kfree(ses->serverNOS);
3103 ses->serverNOS =
3104 kzalloc(len + 1,
3105 GFP_KERNEL);
3106 strncpy(ses->serverNOS, bcc_ptr, len);
3107 bcc_ptr += len;
3108 bcc_ptr[0] = 0;
3109 bcc_ptr++;
3110
3111 len = strnlen(bcc_ptr, 1024);
3112 kfree(ses->serverDomain);
3113 ses->serverDomain =
3114 kzalloc(len + 1,
3115 GFP_KERNEL);
3116 strncpy(ses->serverDomain,
3117 bcc_ptr, len);
3118 bcc_ptr += len;
3119 bcc_ptr[0] = 0;
3120 bcc_ptr++;
3121 } else
3122 cFYI(1,
3123 ("field of length %d "
3124 "extends beyond end of smb",
3125 len));
3126 }
3127 } else {
3128 cERROR(1, ("Security Blob Length extends beyond"
3129 " end of SMB"));
3130 }
3131 } else {
3132 cERROR(1, ("No session structure passed in."));
3133 } 2582 }
3134 } else { 2583#else /* No DFS support, return error on mount */
3135 cERROR(1, ("Invalid Word count %d:", 2584 rc = -EOPNOTSUPP;
3136 smb_buffer_response->WordCount)); 2585#endif
3137 rc = -EIO;
3138 }
3139
3140 cifs_buf_release(smb_buffer);
3141
3142 return rc;
3143}
3144static int
3145CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3146 char *ntlm_session_key, bool ntlmv2_flag,
3147 const struct nls_table *nls_codepage)
3148{
3149 struct smb_hdr *smb_buffer;
3150 struct smb_hdr *smb_buffer_response;
3151 SESSION_SETUP_ANDX *pSMB;
3152 SESSION_SETUP_ANDX *pSMBr;
3153 char *bcc_ptr;
3154 char *user;
3155 char *domain;
3156 int rc = 0;
3157 int remaining_words = 0;
3158 int bytes_returned = 0;
3159 int len;
3160 int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
3161 PAUTHENTICATE_MESSAGE SecurityBlob;
3162 __u32 negotiate_flags, capabilities;
3163 __u16 count;
3164
3165 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
3166 if (ses == NULL)
3167 return -EINVAL;
3168 user = ses->userName;
3169 domain = ses->domainName;
3170 smb_buffer = cifs_buf_get();
3171 if (smb_buffer == NULL) {
3172 return -ENOMEM;
3173 }
3174 smb_buffer_response = smb_buffer;
3175 pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
3176 pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
3177
3178 /* send SMBsessionSetup here */
3179 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
3180 NULL /* no tCon exists yet */ , 12 /* wct */ );
3181
3182 smb_buffer->Mid = GetNextMid(ses->server);
3183 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
3184 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
3185 pSMB->req.AndXCommand = 0xFF;
3186 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
3187 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
3188
3189 pSMB->req.hdr.Uid = ses->Suid;
3190
3191 if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3192 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3193
3194 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
3195 CAP_EXTENDED_SECURITY;
3196 if (ses->capabilities & CAP_UNICODE) {
3197 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3198 capabilities |= CAP_UNICODE;
3199 }
3200 if (ses->capabilities & CAP_STATUS32) {
3201 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3202 capabilities |= CAP_STATUS32;
3203 } 2586 }
3204 if (ses->capabilities & CAP_DFS) {
3205 smb_buffer->Flags2 |= SMBFLG2_DFS;
3206 capabilities |= CAP_DFS;
3207 }
3208 pSMB->req.Capabilities = cpu_to_le32(capabilities);
3209
3210 bcc_ptr = (char *)&pSMB->req.SecurityBlob;
3211 SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
3212 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
3213 SecurityBlob->MessageType = NtLmAuthenticate;
3214 bcc_ptr += SecurityBlobLength;
3215 negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
3216 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
3217 0x80000000 | NTLMSSP_NEGOTIATE_128;
3218 if (sign_CIFS_PDUs)
3219 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
3220 if (ntlmv2_flag)
3221 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
3222
3223/* setup pointers to domain name and workstation name */
3224
3225 SecurityBlob->WorkstationName.Buffer = 0;
3226 SecurityBlob->WorkstationName.Length = 0;
3227 SecurityBlob->WorkstationName.MaximumLength = 0;
3228 SecurityBlob->SessionKey.Length = 0;
3229 SecurityBlob->SessionKey.MaximumLength = 0;
3230 SecurityBlob->SessionKey.Buffer = 0;
3231
3232 SecurityBlob->LmChallengeResponse.Length = 0;
3233 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
3234 SecurityBlob->LmChallengeResponse.Buffer = 0;
3235
3236 SecurityBlob->NtChallengeResponse.Length =
3237 cpu_to_le16(CIFS_SESS_KEY_SIZE);
3238 SecurityBlob->NtChallengeResponse.MaximumLength =
3239 cpu_to_le16(CIFS_SESS_KEY_SIZE);
3240 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
3241 SecurityBlob->NtChallengeResponse.Buffer =
3242 cpu_to_le32(SecurityBlobLength);
3243 SecurityBlobLength += CIFS_SESS_KEY_SIZE;
3244 bcc_ptr += CIFS_SESS_KEY_SIZE;
3245 2587
3246 if (ses->capabilities & CAP_UNICODE) { 2588mount_fail_check:
3247 if (domain == NULL) { 2589 /* on error free sesinfo and tcon struct if needed */
3248 SecurityBlob->DomainName.Buffer = 0;
3249 SecurityBlob->DomainName.Length = 0;
3250 SecurityBlob->DomainName.MaximumLength = 0;
3251 } else {
3252 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
3253 nls_codepage);
3254 ln *= 2;
3255 SecurityBlob->DomainName.MaximumLength =
3256 cpu_to_le16(ln);
3257 SecurityBlob->DomainName.Buffer =
3258 cpu_to_le32(SecurityBlobLength);
3259 bcc_ptr += ln;
3260 SecurityBlobLength += ln;
3261 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
3262 }
3263 if (user == NULL) {
3264 SecurityBlob->UserName.Buffer = 0;
3265 SecurityBlob->UserName.Length = 0;
3266 SecurityBlob->UserName.MaximumLength = 0;
3267 } else {
3268 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
3269 nls_codepage);
3270 ln *= 2;
3271 SecurityBlob->UserName.MaximumLength =
3272 cpu_to_le16(ln);
3273 SecurityBlob->UserName.Buffer =
3274 cpu_to_le32(SecurityBlobLength);
3275 bcc_ptr += ln;
3276 SecurityBlobLength += ln;
3277 SecurityBlob->UserName.Length = cpu_to_le16(ln);
3278 }
3279
3280 /* SecurityBlob->WorkstationName.Length =
3281 cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
3282 SecurityBlob->WorkstationName.Length *= 2;
3283 SecurityBlob->WorkstationName.MaximumLength =
3284 cpu_to_le16(SecurityBlob->WorkstationName.Length);
3285 SecurityBlob->WorkstationName.Buffer =
3286 cpu_to_le32(SecurityBlobLength);
3287 bcc_ptr += SecurityBlob->WorkstationName.Length;
3288 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
3289 SecurityBlob->WorkstationName.Length =
3290 cpu_to_le16(SecurityBlob->WorkstationName.Length); */
3291
3292 if ((long) bcc_ptr % 2) {
3293 *bcc_ptr = 0;
3294 bcc_ptr++;
3295 }
3296 bytes_returned =
3297 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
3298 32, nls_codepage);
3299 bcc_ptr += 2 * bytes_returned;
3300 bytes_returned =
3301 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
3302 nls_codepage);
3303 bcc_ptr += 2 * bytes_returned;
3304 bcc_ptr += 2; /* null term version string */
3305 bytes_returned =
3306 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
3307 64, nls_codepage);
3308 bcc_ptr += 2 * bytes_returned;
3309 *(bcc_ptr + 1) = 0;
3310 *(bcc_ptr + 2) = 0;
3311 bcc_ptr += 2; /* null terminate network opsys string */
3312 *(bcc_ptr + 1) = 0;
3313 *(bcc_ptr + 2) = 0;
3314 bcc_ptr += 2; /* null domain */
3315 } else { /* ASCII */
3316 if (domain == NULL) {
3317 SecurityBlob->DomainName.Buffer = 0;
3318 SecurityBlob->DomainName.Length = 0;
3319 SecurityBlob->DomainName.MaximumLength = 0;
3320 } else {
3321 __u16 ln;
3322 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
3323 strncpy(bcc_ptr, domain, 63);
3324 ln = strnlen(domain, 64);
3325 SecurityBlob->DomainName.MaximumLength =
3326 cpu_to_le16(ln);
3327 SecurityBlob->DomainName.Buffer =
3328 cpu_to_le32(SecurityBlobLength);
3329 bcc_ptr += ln;
3330 SecurityBlobLength += ln;
3331 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
3332 }
3333 if (user == NULL) {
3334 SecurityBlob->UserName.Buffer = 0;
3335 SecurityBlob->UserName.Length = 0;
3336 SecurityBlob->UserName.MaximumLength = 0;
3337 } else {
3338 __u16 ln;
3339 strncpy(bcc_ptr, user, 63);
3340 ln = strnlen(user, 64);
3341 SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
3342 SecurityBlob->UserName.Buffer =
3343 cpu_to_le32(SecurityBlobLength);
3344 bcc_ptr += ln;
3345 SecurityBlobLength += ln;
3346 SecurityBlob->UserName.Length = cpu_to_le16(ln);
3347 }
3348 /* BB fill in our workstation name if known BB */
3349
3350 strcpy(bcc_ptr, "Linux version ");
3351 bcc_ptr += strlen("Linux version ");
3352 strcpy(bcc_ptr, utsname()->release);
3353 bcc_ptr += strlen(utsname()->release) + 1;
3354 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
3355 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
3356 bcc_ptr++; /* null domain */
3357 *bcc_ptr = 0;
3358 }
3359 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
3360 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
3361 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
3362 smb_buffer->smb_buf_length += count;
3363 pSMB->req.ByteCount = cpu_to_le16(count);
3364
3365 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3366 &bytes_returned, CIFS_LONG_OP);
3367 if (rc) { 2590 if (rc) {
3368/* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */ 2591 if (mount_data != mount_data_global)
3369 } else if ((smb_buffer_response->WordCount == 3) || 2592 kfree(mount_data);
3370 (smb_buffer_response->WordCount == 4)) { 2593 /* If find_unc succeeded then rc == 0 so we can not end */
3371 __u16 action = le16_to_cpu(pSMBr->resp.Action); 2594 /* up accidently freeing someone elses tcon struct */
3372 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); 2595 if (tcon)
3373 if (action & GUEST_LOGIN) 2596 cifs_put_tcon(tcon);
3374 cFYI(1, ("Guest login")); /* BB Should we set anything 2597 else if (pSesInfo)
3375 in SesInfo struct ? */ 2598 cifs_put_smb_ses(pSesInfo);
3376/* if (SecurityBlob2->MessageType != NtLm??) { 2599 else
3377 cFYI("Unexpected message type on auth response is %d")); 2600 cifs_put_tcp_session(srvTcp);
3378 } */ 2601 goto out;
3379
3380 if (ses) {
3381 cFYI(1,
3382 ("Check challenge UID %d vs auth response UID %d",
3383 ses->Suid, smb_buffer_response->Uid));
3384 /* UID left in wire format */
3385 ses->Suid = smb_buffer_response->Uid;
3386 bcc_ptr = pByteArea(smb_buffer_response);
3387 /* response can have either 3 or 4 word count - Samba sends 3 */
3388 if ((pSMBr->resp.hdr.WordCount == 3)
3389 || ((pSMBr->resp.hdr.WordCount == 4)
3390 && (blob_len <
3391 pSMBr->resp.ByteCount))) {
3392 if (pSMBr->resp.hdr.WordCount == 4) {
3393 bcc_ptr +=
3394 blob_len;
3395 cFYI(1,
3396 ("Security Blob Length %d ",
3397 blob_len));
3398 }
3399
3400 cFYI(1,
3401 ("NTLMSSP response to Authenticate "));
3402
3403 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3404 if ((long) (bcc_ptr) % 2) {
3405 remaining_words =
3406 (BCC(smb_buffer_response)
3407 - 1) / 2;
3408 bcc_ptr++; /* Unicode strings must be word aligned */
3409 } else {
3410 remaining_words = BCC(smb_buffer_response) / 2;
3411 }
3412 len = UniStrnlen((wchar_t *) bcc_ptr,
3413 remaining_words - 1);
3414/* We look for obvious messed up bcc or strings in response so we do not go off
3415 the end since (at least) WIN2K and Windows XP have a major bug in not null
3416 terminating last Unicode string in response */
3417 if (ses->serverOS)
3418 kfree(ses->serverOS);
3419 ses->serverOS =
3420 kzalloc(2 * (len + 1), GFP_KERNEL);
3421 cifs_strfromUCS_le(ses->serverOS,
3422 (__le16 *)
3423 bcc_ptr, len,
3424 nls_codepage);
3425 bcc_ptr += 2 * (len + 1);
3426 remaining_words -= len + 1;
3427 ses->serverOS[2 * len] = 0;
3428 ses->serverOS[1 + (2 * len)] = 0;
3429 if (remaining_words > 0) {
3430 len = UniStrnlen((wchar_t *)
3431 bcc_ptr,
3432 remaining_words
3433 - 1);
3434 kfree(ses->serverNOS);
3435 ses->serverNOS =
3436 kzalloc(2 * (len + 1),
3437 GFP_KERNEL);
3438 cifs_strfromUCS_le(ses->
3439 serverNOS,
3440 (__le16 *)
3441 bcc_ptr,
3442 len,
3443 nls_codepage);
3444 bcc_ptr += 2 * (len + 1);
3445 ses->serverNOS[2 * len] = 0;
3446 ses->serverNOS[1+(2*len)] = 0;
3447 remaining_words -= len + 1;
3448 if (remaining_words > 0) {
3449 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3450 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3451 if (ses->serverDomain)
3452 kfree(ses->serverDomain);
3453 ses->serverDomain =
3454 kzalloc(2 *
3455 (len +
3456 1),
3457 GFP_KERNEL);
3458 cifs_strfromUCS_le
3459 (ses->
3460 serverDomain,
3461 (__le16 *)
3462 bcc_ptr, len,
3463 nls_codepage);
3464 bcc_ptr +=
3465 2 * (len + 1);
3466 ses->
3467 serverDomain[2
3468 * len]
3469 = 0;
3470 ses->
3471 serverDomain[1
3472 +
3473 (2
3474 *
3475 len)]
3476 = 0;
3477 } /* else no more room so create dummy domain string */
3478 else {
3479 if (ses->serverDomain)
3480 kfree(ses->serverDomain);
3481 ses->serverDomain = kzalloc(2,GFP_KERNEL);
3482 }
3483 } else { /* no room so create dummy domain and NOS string */
3484 if (ses->serverDomain)
3485 kfree(ses->serverDomain);
3486 ses->serverDomain = kzalloc(2, GFP_KERNEL);
3487 kfree(ses->serverNOS);
3488 ses->serverNOS = kzalloc(2, GFP_KERNEL);
3489 }
3490 } else { /* ASCII */
3491 len = strnlen(bcc_ptr, 1024);
3492 if (((long) bcc_ptr + len) -
3493 (long) pByteArea(smb_buffer_response)
3494 <= BCC(smb_buffer_response)) {
3495 if (ses->serverOS)
3496 kfree(ses->serverOS);
3497 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
3498 strncpy(ses->serverOS,bcc_ptr, len);
3499
3500 bcc_ptr += len;
3501 bcc_ptr[0] = 0; /* null terminate the string */
3502 bcc_ptr++;
3503
3504 len = strnlen(bcc_ptr, 1024);
3505 kfree(ses->serverNOS);
3506 ses->serverNOS = kzalloc(len+1,
3507 GFP_KERNEL);
3508 strncpy(ses->serverNOS,
3509 bcc_ptr, len);
3510 bcc_ptr += len;
3511 bcc_ptr[0] = 0;
3512 bcc_ptr++;
3513
3514 len = strnlen(bcc_ptr, 1024);
3515 if (ses->serverDomain)
3516 kfree(ses->serverDomain);
3517 ses->serverDomain =
3518 kzalloc(len+1,
3519 GFP_KERNEL);
3520 strncpy(ses->serverDomain,
3521 bcc_ptr, len);
3522 bcc_ptr += len;
3523 bcc_ptr[0] = 0;
3524 bcc_ptr++;
3525 } else
3526 cFYI(1, ("field of length %d "
3527 "extends beyond end of smb ",
3528 len));
3529 }
3530 } else {
3531 cERROR(1, ("Security Blob extends beyond end "
3532 "of SMB"));
3533 }
3534 } else {
3535 cERROR(1, ("No session structure passed in."));
3536 }
3537 } else {
3538 cERROR(1, ("Invalid Word count %d: ",
3539 smb_buffer_response->WordCount));
3540 rc = -EIO;
3541 } 2602 }
3542 2603
3543 cifs_buf_release(smb_buffer); 2604 /* volume_info->password is freed above when existing session found
3544 2605 (in which case it is not needed anymore) but when new sesion is created
2606 the password ptr is put in the new session structure (in which case the
2607 password will be freed at unmount time) */
2608out:
2609 /* zero out password before freeing */
2610 cleanup_volume_info(&volume_info);
2611 FreeXid(xid);
3545 return rc; 2612 return rc;
3546} 2613}
3547 2614
@@ -3556,7 +2623,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3556 TCONX_RSP *pSMBr; 2623 TCONX_RSP *pSMBr;
3557 unsigned char *bcc_ptr; 2624 unsigned char *bcc_ptr;
3558 int rc = 0; 2625 int rc = 0;
3559 int length; 2626 int length, bytes_left;
3560 __u16 count; 2627 __u16 count;
3561 2628
3562 if (ses == NULL) 2629 if (ses == NULL)
@@ -3644,14 +2711,22 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3644 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 2711 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
3645 CIFS_STD_OP); 2712 CIFS_STD_OP);
3646 2713
3647 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3648 /* above now done in SendReceive */ 2714 /* above now done in SendReceive */
3649 if ((rc == 0) && (tcon != NULL)) { 2715 if ((rc == 0) && (tcon != NULL)) {
2716 bool is_unicode;
2717
3650 tcon->tidStatus = CifsGood; 2718 tcon->tidStatus = CifsGood;
3651 tcon->need_reconnect = false; 2719 tcon->need_reconnect = false;
3652 tcon->tid = smb_buffer_response->Tid; 2720 tcon->tid = smb_buffer_response->Tid;
3653 bcc_ptr = pByteArea(smb_buffer_response); 2721 bcc_ptr = pByteArea(smb_buffer_response);
3654 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); 2722 bytes_left = BCC(smb_buffer_response);
2723 length = strnlen(bcc_ptr, bytes_left - 2);
2724 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
2725 is_unicode = true;
2726 else
2727 is_unicode = false;
2728
2729
3655 /* skip service field (NB: this field is always ASCII) */ 2730 /* skip service field (NB: this field is always ASCII) */
3656 if (length == 3) { 2731 if (length == 3) {
3657 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') && 2732 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
@@ -3666,40 +2741,16 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3666 } 2741 }
3667 } 2742 }
3668 bcc_ptr += length + 1; 2743 bcc_ptr += length + 1;
2744 bytes_left -= (length + 1);
3669 strncpy(tcon->treeName, tree, MAX_TREE_SIZE); 2745 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3670 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { 2746
3671 length = UniStrnlen((wchar_t *) bcc_ptr, 512); 2747 /* mostly informational -- no need to fail on error here */
3672 if ((bcc_ptr + (2 * length)) - 2748 tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
3673 pByteArea(smb_buffer_response) <= 2749 bytes_left, is_unicode,
3674 BCC(smb_buffer_response)) { 2750 nls_codepage);
3675 kfree(tcon->nativeFileSystem); 2751
3676 tcon->nativeFileSystem = 2752 cFYI(1, ("nativeFileSystem=%s", tcon->nativeFileSystem));
3677 kzalloc(2*(length + 1), GFP_KERNEL); 2753
3678 if (tcon->nativeFileSystem)
3679 cifs_strfromUCS_le(
3680 tcon->nativeFileSystem,
3681 (__le16 *) bcc_ptr,
3682 length, nls_codepage);
3683 bcc_ptr += 2 * length;
3684 bcc_ptr[0] = 0; /* null terminate the string */
3685 bcc_ptr[1] = 0;
3686 bcc_ptr += 2;
3687 }
3688 /* else do not bother copying these information fields*/
3689 } else {
3690 length = strnlen(bcc_ptr, 1024);
3691 if ((bcc_ptr + length) -
3692 pByteArea(smb_buffer_response) <=
3693 BCC(smb_buffer_response)) {
3694 kfree(tcon->nativeFileSystem);
3695 tcon->nativeFileSystem =
3696 kzalloc(length + 1, GFP_KERNEL);
3697 if (tcon->nativeFileSystem)
3698 strncpy(tcon->nativeFileSystem, bcc_ptr,
3699 length);
3700 }
3701 /* else do not bother copying these information fields*/
3702 }
3703 if ((smb_buffer_response->WordCount == 3) || 2754 if ((smb_buffer_response->WordCount == 3) ||
3704 (smb_buffer_response->WordCount == 7)) 2755 (smb_buffer_response->WordCount == 7))
3705 /* field is in same location */ 2756 /* field is in same location */
@@ -3738,8 +2789,6 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3738 struct nls_table *nls_info) 2789 struct nls_table *nls_info)
3739{ 2790{
3740 int rc = 0; 2791 int rc = 0;
3741 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
3742 bool ntlmv2_flag = false;
3743 int first_time = 0; 2792 int first_time = 0;
3744 struct TCP_Server_Info *server = pSesInfo->server; 2793 struct TCP_Server_Info *server = pSesInfo->server;
3745 2794
@@ -3771,83 +2820,19 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3771 pSesInfo->capabilities = server->capabilities; 2820 pSesInfo->capabilities = server->capabilities;
3772 if (linuxExtEnabled == 0) 2821 if (linuxExtEnabled == 0)
3773 pSesInfo->capabilities &= (~CAP_UNIX); 2822 pSesInfo->capabilities &= (~CAP_UNIX);
3774 /* pSesInfo->sequence_number = 0;*/ 2823
3775 cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", 2824 cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
3776 server->secMode, server->capabilities, server->timeAdj)); 2825 server->secMode, server->capabilities, server->timeAdj));
3777 2826
3778 if (experimEnabled < 2) 2827 rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
3779 rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
3780 else if (extended_security
3781 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3782 && (server->secType == NTLMSSP)) {
3783 rc = -EOPNOTSUPP;
3784 } else if (extended_security
3785 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3786 && (server->secType == RawNTLMSSP)) {
3787 cFYI(1, ("NTLMSSP sesssetup"));
3788 rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag,
3789 nls_info);
3790 if (!rc) {
3791 if (ntlmv2_flag) {
3792 char *v2_response;
3793 cFYI(1, ("more secure NTLM ver2 hash"));
3794 if (CalcNTLMv2_partial_mac_key(pSesInfo,
3795 nls_info)) {
3796 rc = -ENOMEM;
3797 goto ss_err_exit;
3798 } else
3799 v2_response = kmalloc(16 + 64 /* blob*/,
3800 GFP_KERNEL);
3801 if (v2_response) {
3802 CalcNTLMv2_response(pSesInfo,
3803 v2_response);
3804 /* if (first_time)
3805 cifs_calculate_ntlmv2_mac_key */
3806 kfree(v2_response);
3807 /* BB Put dummy sig in SessSetup PDU? */
3808 } else {
3809 rc = -ENOMEM;
3810 goto ss_err_exit;
3811 }
3812
3813 } else {
3814 SMBNTencrypt(pSesInfo->password,
3815 server->cryptKey,
3816 ntlm_session_key);
3817
3818 if (first_time)
3819 cifs_calculate_mac_key(
3820 &server->mac_signing_key,
3821 ntlm_session_key,
3822 pSesInfo->password);
3823 }
3824 /* for better security the weaker lanman hash not sent
3825 in AuthSessSetup so we no longer calculate it */
3826
3827 rc = CIFSNTLMSSPAuthSessSetup(xid, pSesInfo,
3828 ntlm_session_key,
3829 ntlmv2_flag,
3830 nls_info);
3831 }
3832 } else { /* old style NTLM 0.12 session setup */
3833 SMBNTencrypt(pSesInfo->password, server->cryptKey,
3834 ntlm_session_key);
3835
3836 if (first_time)
3837 cifs_calculate_mac_key(&server->mac_signing_key,
3838 ntlm_session_key,
3839 pSesInfo->password);
3840
3841 rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info);
3842 }
3843 if (rc) { 2828 if (rc) {
3844 cERROR(1, ("Send error in SessSetup = %d", rc)); 2829 cERROR(1, ("Send error in SessSetup = %d", rc));
3845 } else { 2830 } else {
3846 cFYI(1, ("CIFS Session Established successfully")); 2831 cFYI(1, ("CIFS Session Established successfully"));
3847 spin_lock(&GlobalMid_Lock); 2832 spin_lock(&GlobalMid_Lock);
3848 pSesInfo->status = CifsGood; 2833 pSesInfo->status = CifsGood;
3849 pSesInfo->need_reconnect = false; 2834 pSesInfo->need_reconnect = false;
3850 spin_unlock(&GlobalMid_Lock); 2835 spin_unlock(&GlobalMid_Lock);
3851 } 2836 }
3852 2837
3853ss_err_exit: 2838ss_err_exit:
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 54dce78fbb73..11431ed72a7f 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -129,12 +129,62 @@ cifs_bp_rename_retry:
129 return full_path; 129 return full_path;
130} 130}
131 131
132static void
133cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle,
134 struct cifsTconInfo *tcon, bool write_only)
135{
136 int oplock = 0;
137 struct cifsFileInfo *pCifsFile;
138 struct cifsInodeInfo *pCifsInode;
139
140 pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
141
142 if (pCifsFile == NULL)
143 return;
144
145 if (oplockEnabled)
146 oplock = REQ_OPLOCK;
147
148 pCifsFile->netfid = fileHandle;
149 pCifsFile->pid = current->tgid;
150 pCifsFile->pInode = newinode;
151 pCifsFile->invalidHandle = false;
152 pCifsFile->closePend = false;
153 mutex_init(&pCifsFile->fh_mutex);
154 mutex_init(&pCifsFile->lock_mutex);
155 INIT_LIST_HEAD(&pCifsFile->llist);
156 atomic_set(&pCifsFile->wrtPending, 0);
157
158 /* set the following in open now
159 pCifsFile->pfile = file; */
160 write_lock(&GlobalSMBSeslock);
161 list_add(&pCifsFile->tlist, &tcon->openFileList);
162 pCifsInode = CIFS_I(newinode);
163 if (pCifsInode) {
164 /* if readable file instance put first in list*/
165 if (write_only)
166 list_add_tail(&pCifsFile->flist,
167 &pCifsInode->openFileList);
168 else
169 list_add(&pCifsFile->flist, &pCifsInode->openFileList);
170
171 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
172 pCifsInode->clientCanCacheAll = true;
173 pCifsInode->clientCanCacheRead = true;
174 cFYI(1, ("Exclusive Oplock inode %p", newinode));
175 } else if ((oplock & 0xF) == OPLOCK_READ)
176 pCifsInode->clientCanCacheRead = true;
177 }
178 write_unlock(&GlobalSMBSeslock);
179}
180
132int cifs_posix_open(char *full_path, struct inode **pinode, 181int cifs_posix_open(char *full_path, struct inode **pinode,
133 struct super_block *sb, int mode, int oflags, 182 struct super_block *sb, int mode, int oflags,
134 int *poplock, __u16 *pnetfid, int xid) 183 int *poplock, __u16 *pnetfid, int xid)
135{ 184{
136 int rc; 185 int rc;
137 __u32 oplock; 186 __u32 oplock;
187 bool write_only = false;
138 FILE_UNIX_BASIC_INFO *presp_data; 188 FILE_UNIX_BASIC_INFO *presp_data;
139 __u32 posix_flags = 0; 189 __u32 posix_flags = 0;
140 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 190 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
@@ -172,6 +222,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
172 if (oflags & O_DIRECT) 222 if (oflags & O_DIRECT)
173 posix_flags |= SMB_O_DIRECT; 223 posix_flags |= SMB_O_DIRECT;
174 224
225 if (!(oflags & FMODE_READ))
226 write_only = true;
175 227
176 rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode, 228 rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
177 pnetfid, presp_data, &oplock, full_path, 229 pnetfid, presp_data, &oplock, full_path,
@@ -187,8 +239,10 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
187 if (!pinode) 239 if (!pinode)
188 goto posix_open_ret; /* caller does not need info */ 240 goto posix_open_ret; /* caller does not need info */
189 241
190 if (*pinode == NULL) 242 if (*pinode == NULL) {
191 *pinode = cifs_new_inode(sb, &presp_data->UniqueId); 243 __u64 unique_id = le64_to_cpu(presp_data->UniqueId);
244 *pinode = cifs_new_inode(sb, &unique_id);
245 }
192 /* else an inode was passed in. Update its info, don't create one */ 246 /* else an inode was passed in. Update its info, don't create one */
193 247
194 /* We do not need to close the file if new_inode fails since 248 /* We do not need to close the file if new_inode fails since
@@ -198,6 +252,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
198 252
199 posix_fill_in_inode(*pinode, presp_data, 1); 253 posix_fill_in_inode(*pinode, presp_data, 1);
200 254
255 cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only);
256
201posix_open_ret: 257posix_open_ret:
202 kfree(presp_data); 258 kfree(presp_data);
203 return rc; 259 return rc;
@@ -225,6 +281,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
225 int create_options = CREATE_NOT_DIR; 281 int create_options = CREATE_NOT_DIR;
226 int oplock = 0; 282 int oplock = 0;
227 int oflags; 283 int oflags;
284 bool posix_create = false;
228 /* 285 /*
229 * BB below access is probably too much for mknod to request 286 * BB below access is probably too much for mknod to request
230 * but we have to do query and setpathinfo so requesting 287 * but we have to do query and setpathinfo so requesting
@@ -239,7 +296,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
239 char *full_path = NULL; 296 char *full_path = NULL;
240 FILE_ALL_INFO *buf = NULL; 297 FILE_ALL_INFO *buf = NULL;
241 struct inode *newinode = NULL; 298 struct inode *newinode = NULL;
242 struct cifsInodeInfo *pCifsInode;
243 int disposition = FILE_OVERWRITE_IF; 299 int disposition = FILE_OVERWRITE_IF;
244 bool write_only = false; 300 bool write_only = false;
245 301
@@ -273,11 +329,13 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
273 negotation. EREMOTE indicates DFS junction, which is not 329 negotation. EREMOTE indicates DFS junction, which is not
274 handled in posix open */ 330 handled in posix open */
275 331
276 if ((rc == 0) && (newinode == NULL)) 332 if (rc == 0) {
277 goto cifs_create_get_file_info; /* query inode info */ 333 posix_create = true;
278 else if (rc == 0) /* success, no need to query */ 334 if (newinode == NULL) /* query inode info */
279 goto cifs_create_set_dentry; 335 goto cifs_create_get_file_info;
280 else if ((rc != -EIO) && (rc != -EREMOTE) && 336 else /* success, no need to query */
337 goto cifs_create_set_dentry;
338 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
281 (rc != -EOPNOTSUPP)) /* path not found or net err */ 339 (rc != -EOPNOTSUPP)) /* path not found or net err */
282 goto cifs_create_out; 340 goto cifs_create_out;
283 /* else fallthrough to retry, using older open call, this is 341 /* else fallthrough to retry, using older open call, this is
@@ -409,45 +467,9 @@ cifs_create_set_dentry:
409 if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) { 467 if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
410 /* mknod case - do not leave file open */ 468 /* mknod case - do not leave file open */
411 CIFSSMBClose(xid, tcon, fileHandle); 469 CIFSSMBClose(xid, tcon, fileHandle);
412 } else if (newinode) { 470 } else if (!(posix_create) && (newinode)) {
413 struct cifsFileInfo *pCifsFile = 471 cifs_fill_fileinfo(newinode, fileHandle,
414 kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 472 cifs_sb->tcon, write_only);
415
416 if (pCifsFile == NULL)
417 goto cifs_create_out;
418 pCifsFile->netfid = fileHandle;
419 pCifsFile->pid = current->tgid;
420 pCifsFile->pInode = newinode;
421 pCifsFile->invalidHandle = false;
422 pCifsFile->closePend = false;
423 init_MUTEX(&pCifsFile->fh_sem);
424 mutex_init(&pCifsFile->lock_mutex);
425 INIT_LIST_HEAD(&pCifsFile->llist);
426 atomic_set(&pCifsFile->wrtPending, 0);
427
428 /* set the following in open now
429 pCifsFile->pfile = file; */
430 write_lock(&GlobalSMBSeslock);
431 list_add(&pCifsFile->tlist, &tcon->openFileList);
432 pCifsInode = CIFS_I(newinode);
433 if (pCifsInode) {
434 /* if readable file instance put first in list*/
435 if (write_only) {
436 list_add_tail(&pCifsFile->flist,
437 &pCifsInode->openFileList);
438 } else {
439 list_add(&pCifsFile->flist,
440 &pCifsInode->openFileList);
441 }
442 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
443 pCifsInode->clientCanCacheAll = true;
444 pCifsInode->clientCanCacheRead = true;
445 cFYI(1, ("Exclusive Oplock inode %p",
446 newinode));
447 } else if ((oplock & 0xF) == OPLOCK_READ)
448 pCifsInode->clientCanCacheRead = true;
449 }
450 write_unlock(&GlobalSMBSeslock);
451 } 473 }
452cifs_create_out: 474cifs_create_out:
453 kfree(buf); 475 kfree(buf);
@@ -580,17 +602,21 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
580 return rc; 602 return rc;
581} 603}
582 604
583
584struct dentry * 605struct dentry *
585cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, 606cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
586 struct nameidata *nd) 607 struct nameidata *nd)
587{ 608{
588 int xid; 609 int xid;
589 int rc = 0; /* to get around spurious gcc warning, set to zero here */ 610 int rc = 0; /* to get around spurious gcc warning, set to zero here */
611 int oplock = 0;
612 int mode;
613 __u16 fileHandle = 0;
614 bool posix_open = false;
590 struct cifs_sb_info *cifs_sb; 615 struct cifs_sb_info *cifs_sb;
591 struct cifsTconInfo *pTcon; 616 struct cifsTconInfo *pTcon;
592 struct inode *newInode = NULL; 617 struct inode *newInode = NULL;
593 char *full_path = NULL; 618 char *full_path = NULL;
619 struct file *filp;
594 620
595 xid = GetXid(); 621 xid = GetXid();
596 622
@@ -632,12 +658,37 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
632 } 658 }
633 cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode)); 659 cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode));
634 660
635 if (pTcon->unix_ext) 661 if (pTcon->unix_ext) {
636 rc = cifs_get_inode_info_unix(&newInode, full_path, 662 if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
637 parent_dir_inode->i_sb, xid); 663 (nd->flags & LOOKUP_OPEN)) {
638 else 664 if (!((nd->intent.open.flags & O_CREAT) &&
665 (nd->intent.open.flags & O_EXCL))) {
666 mode = nd->intent.open.create_mode &
667 ~current_umask();
668 rc = cifs_posix_open(full_path, &newInode,
669 parent_dir_inode->i_sb, mode,
670 nd->intent.open.flags, &oplock,
671 &fileHandle, xid);
672 /*
673 * This code works around a bug in
674 * samba posix open in samba versions 3.3.1
675 * and earlier where create works
676 * but open fails with invalid parameter.
677 * If either of these error codes are
678 * returned, follow the normal lookup.
679 * Otherwise, the error during posix open
680 * is handled.
681 */
682 if ((rc != -EINVAL) && (rc != -EOPNOTSUPP))
683 posix_open = true;
684 }
685 }
686 if (!posix_open)
687 rc = cifs_get_inode_info_unix(&newInode, full_path,
688 parent_dir_inode->i_sb, xid);
689 } else
639 rc = cifs_get_inode_info(&newInode, full_path, NULL, 690 rc = cifs_get_inode_info(&newInode, full_path, NULL,
640 parent_dir_inode->i_sb, xid, NULL); 691 parent_dir_inode->i_sb, xid, NULL);
641 692
642 if ((rc == 0) && (newInode != NULL)) { 693 if ((rc == 0) && (newInode != NULL)) {
643 if (pTcon->nocase) 694 if (pTcon->nocase)
@@ -645,7 +696,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
645 else 696 else
646 direntry->d_op = &cifs_dentry_ops; 697 direntry->d_op = &cifs_dentry_ops;
647 d_add(direntry, newInode); 698 d_add(direntry, newInode);
648 699 if (posix_open)
700 filp = lookup_instantiate_filp(nd, direntry, NULL);
649 /* since paths are not looked up by component - the parent 701 /* since paths are not looked up by component - the parent
650 directories are presumed to be good here */ 702 directories are presumed to be good here */
651 renew_parental_timestamps(direntry); 703 renew_parental_timestamps(direntry);
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c
index 1e0c1bd8f2e4..df4a306f697e 100644
--- a/fs/cifs/dns_resolve.c
+++ b/fs/cifs/dns_resolve.c
@@ -78,7 +78,7 @@ dns_resolver_instantiate(struct key *key, const void *data,
78 } 78 }
79 79
80 key->type_data.x[0] = datalen; 80 key->type_data.x[0] = datalen;
81 rcu_assign_pointer(key->payload.data, ip); 81 key->payload.data = ip;
82 82
83 return rc; 83 return rc;
84} 84}
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 81747acca4c4..38c06f826575 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -46,7 +46,7 @@ static inline struct cifsFileInfo *cifs_init_private(
46 memset(private_data, 0, sizeof(struct cifsFileInfo)); 46 memset(private_data, 0, sizeof(struct cifsFileInfo));
47 private_data->netfid = netfid; 47 private_data->netfid = netfid;
48 private_data->pid = current->tgid; 48 private_data->pid = current->tgid;
49 init_MUTEX(&private_data->fh_sem); 49 mutex_init(&private_data->fh_mutex);
50 mutex_init(&private_data->lock_mutex); 50 mutex_init(&private_data->lock_mutex);
51 INIT_LIST_HEAD(&private_data->llist); 51 INIT_LIST_HEAD(&private_data->llist);
52 private_data->pfile = file; /* needed for writepage */ 52 private_data->pfile = file; /* needed for writepage */
@@ -129,15 +129,12 @@ static inline int cifs_posix_open_inode_helper(struct inode *inode,
129 struct file *file, struct cifsInodeInfo *pCifsInode, 129 struct file *file, struct cifsInodeInfo *pCifsInode,
130 struct cifsFileInfo *pCifsFile, int oplock, u16 netfid) 130 struct cifsFileInfo *pCifsFile, int oplock, u16 netfid)
131{ 131{
132 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
133/* struct timespec temp; */ /* BB REMOVEME BB */
134 132
135 file->private_data = kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 133 file->private_data = kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
136 if (file->private_data == NULL) 134 if (file->private_data == NULL)
137 return -ENOMEM; 135 return -ENOMEM;
138 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid); 136 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
139 write_lock(&GlobalSMBSeslock); 137 write_lock(&GlobalSMBSeslock);
140 list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
141 138
142 pCifsInode = CIFS_I(file->f_path.dentry->d_inode); 139 pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
143 if (pCifsInode == NULL) { 140 if (pCifsInode == NULL) {
@@ -145,17 +142,6 @@ static inline int cifs_posix_open_inode_helper(struct inode *inode,
145 return -EINVAL; 142 return -EINVAL;
146 } 143 }
147 144
148 /* want handles we can use to read with first
149 in the list so we do not have to walk the
150 list to search for one in write_begin */
151 if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
152 list_add_tail(&pCifsFile->flist,
153 &pCifsInode->openFileList);
154 } else {
155 list_add(&pCifsFile->flist,
156 &pCifsInode->openFileList);
157 }
158
159 if (pCifsInode->clientCanCacheRead) { 145 if (pCifsInode->clientCanCacheRead) {
160 /* we have the inode open somewhere else 146 /* we have the inode open somewhere else
161 no need to discard cache data */ 147 no need to discard cache data */
@@ -284,35 +270,32 @@ int cifs_open(struct inode *inode, struct file *file)
284 cifs_sb = CIFS_SB(inode->i_sb); 270 cifs_sb = CIFS_SB(inode->i_sb);
285 tcon = cifs_sb->tcon; 271 tcon = cifs_sb->tcon;
286 272
287 if (file->f_flags & O_CREAT) { 273 /* search inode for this file and fill in file->private_data */
288 /* search inode for this file and fill in file->private_data */ 274 pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
289 pCifsInode = CIFS_I(file->f_path.dentry->d_inode); 275 read_lock(&GlobalSMBSeslock);
290 read_lock(&GlobalSMBSeslock); 276 list_for_each(tmp, &pCifsInode->openFileList) {
291 list_for_each(tmp, &pCifsInode->openFileList) { 277 pCifsFile = list_entry(tmp, struct cifsFileInfo,
292 pCifsFile = list_entry(tmp, struct cifsFileInfo, 278 flist);
293 flist); 279 if ((pCifsFile->pfile == NULL) &&
294 if ((pCifsFile->pfile == NULL) && 280 (pCifsFile->pid == current->tgid)) {
295 (pCifsFile->pid == current->tgid)) { 281 /* mode set in cifs_create */
296 /* mode set in cifs_create */ 282
297 283 /* needed for writepage */
298 /* needed for writepage */ 284 pCifsFile->pfile = file;
299 pCifsFile->pfile = file; 285
300 286 file->private_data = pCifsFile;
301 file->private_data = pCifsFile; 287 break;
302 break;
303 }
304 }
305 read_unlock(&GlobalSMBSeslock);
306 if (file->private_data != NULL) {
307 rc = 0;
308 FreeXid(xid);
309 return rc;
310 } else {
311 if (file->f_flags & O_EXCL)
312 cERROR(1, ("could not find file instance for "
313 "new file %p", file));
314 } 288 }
315 } 289 }
290 read_unlock(&GlobalSMBSeslock);
291
292 if (file->private_data != NULL) {
293 rc = 0;
294 FreeXid(xid);
295 return rc;
296 } else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL))
297 cERROR(1, ("could not find file instance for "
298 "new file %p", file));
316 299
317 full_path = build_path_from_dentry(file->f_path.dentry); 300 full_path = build_path_from_dentry(file->f_path.dentry);
318 if (full_path == NULL) { 301 if (full_path == NULL) {
@@ -500,9 +483,9 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
500 return -EBADF; 483 return -EBADF;
501 484
502 xid = GetXid(); 485 xid = GetXid();
503 down(&pCifsFile->fh_sem); 486 mutex_unlock(&pCifsFile->fh_mutex);
504 if (!pCifsFile->invalidHandle) { 487 if (!pCifsFile->invalidHandle) {
505 up(&pCifsFile->fh_sem); 488 mutex_lock(&pCifsFile->fh_mutex);
506 FreeXid(xid); 489 FreeXid(xid);
507 return 0; 490 return 0;
508 } 491 }
@@ -533,7 +516,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
533 if (full_path == NULL) { 516 if (full_path == NULL) {
534 rc = -ENOMEM; 517 rc = -ENOMEM;
535reopen_error_exit: 518reopen_error_exit:
536 up(&pCifsFile->fh_sem); 519 mutex_lock(&pCifsFile->fh_mutex);
537 FreeXid(xid); 520 FreeXid(xid);
538 return rc; 521 return rc;
539 } 522 }
@@ -575,14 +558,14 @@ reopen_error_exit:
575 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 558 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
576 CIFS_MOUNT_MAP_SPECIAL_CHR); 559 CIFS_MOUNT_MAP_SPECIAL_CHR);
577 if (rc) { 560 if (rc) {
578 up(&pCifsFile->fh_sem); 561 mutex_lock(&pCifsFile->fh_mutex);
579 cFYI(1, ("cifs_open returned 0x%x", rc)); 562 cFYI(1, ("cifs_open returned 0x%x", rc));
580 cFYI(1, ("oplock: %d", oplock)); 563 cFYI(1, ("oplock: %d", oplock));
581 } else { 564 } else {
582reopen_success: 565reopen_success:
583 pCifsFile->netfid = netfid; 566 pCifsFile->netfid = netfid;
584 pCifsFile->invalidHandle = false; 567 pCifsFile->invalidHandle = false;
585 up(&pCifsFile->fh_sem); 568 mutex_lock(&pCifsFile->fh_mutex);
586 pCifsInode = CIFS_I(inode); 569 pCifsInode = CIFS_I(inode);
587 if (pCifsInode) { 570 if (pCifsInode) {
588 if (can_flush) { 571 if (can_flush) {
@@ -971,6 +954,40 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
971 return rc; 954 return rc;
972} 955}
973 956
957/*
958 * Set the timeout on write requests past EOF. For some servers (Windows)
959 * these calls can be very long.
960 *
961 * If we're writing >10M past the EOF we give a 180s timeout. Anything less
962 * than that gets a 45s timeout. Writes not past EOF get 15s timeouts.
963 * The 10M cutoff is totally arbitrary. A better scheme for this would be
964 * welcome if someone wants to suggest one.
965 *
966 * We may be able to do a better job with this if there were some way to
967 * declare that a file should be sparse.
968 */
969static int
970cifs_write_timeout(struct cifsInodeInfo *cifsi, loff_t offset)
971{
972 if (offset <= cifsi->server_eof)
973 return CIFS_STD_OP;
974 else if (offset > (cifsi->server_eof + (10 * 1024 * 1024)))
975 return CIFS_VLONG_OP;
976 else
977 return CIFS_LONG_OP;
978}
979
980/* update the file size (if needed) after a write */
981static void
982cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
983 unsigned int bytes_written)
984{
985 loff_t end_of_write = offset + bytes_written;
986
987 if (end_of_write > cifsi->server_eof)
988 cifsi->server_eof = end_of_write;
989}
990
974ssize_t cifs_user_write(struct file *file, const char __user *write_data, 991ssize_t cifs_user_write(struct file *file, const char __user *write_data,
975 size_t write_size, loff_t *poffset) 992 size_t write_size, loff_t *poffset)
976{ 993{
@@ -981,6 +998,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
981 struct cifsTconInfo *pTcon; 998 struct cifsTconInfo *pTcon;
982 int xid, long_op; 999 int xid, long_op;
983 struct cifsFileInfo *open_file; 1000 struct cifsFileInfo *open_file;
1001 struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode);
984 1002
985 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 1003 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
986 1004
@@ -1000,11 +1018,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
1000 1018
1001 xid = GetXid(); 1019 xid = GetXid();
1002 1020
1003 if (*poffset > file->f_path.dentry->d_inode->i_size) 1021 long_op = cifs_write_timeout(cifsi, *poffset);
1004 long_op = CIFS_VLONG_OP; /* writes past EOF take long time */
1005 else
1006 long_op = CIFS_LONG_OP;
1007
1008 for (total_written = 0; write_size > total_written; 1022 for (total_written = 0; write_size > total_written;
1009 total_written += bytes_written) { 1023 total_written += bytes_written) {
1010 rc = -EAGAIN; 1024 rc = -EAGAIN;
@@ -1048,8 +1062,10 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
1048 FreeXid(xid); 1062 FreeXid(xid);
1049 return rc; 1063 return rc;
1050 } 1064 }
1051 } else 1065 } else {
1066 cifs_update_eof(cifsi, *poffset, bytes_written);
1052 *poffset += bytes_written; 1067 *poffset += bytes_written;
1068 }
1053 long_op = CIFS_STD_OP; /* subsequent writes fast - 1069 long_op = CIFS_STD_OP; /* subsequent writes fast -
1054 15 seconds is plenty */ 1070 15 seconds is plenty */
1055 } 1071 }
@@ -1085,6 +1101,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
1085 struct cifsTconInfo *pTcon; 1101 struct cifsTconInfo *pTcon;
1086 int xid, long_op; 1102 int xid, long_op;
1087 struct cifsFileInfo *open_file; 1103 struct cifsFileInfo *open_file;
1104 struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode);
1088 1105
1089 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 1106 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
1090 1107
@@ -1099,11 +1116,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
1099 1116
1100 xid = GetXid(); 1117 xid = GetXid();
1101 1118
1102 if (*poffset > file->f_path.dentry->d_inode->i_size) 1119 long_op = cifs_write_timeout(cifsi, *poffset);
1103 long_op = CIFS_VLONG_OP; /* writes past EOF can be slow */
1104 else
1105 long_op = CIFS_LONG_OP;
1106
1107 for (total_written = 0; write_size > total_written; 1120 for (total_written = 0; write_size > total_written;
1108 total_written += bytes_written) { 1121 total_written += bytes_written) {
1109 rc = -EAGAIN; 1122 rc = -EAGAIN;
@@ -1166,8 +1179,10 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
1166 FreeXid(xid); 1179 FreeXid(xid);
1167 return rc; 1180 return rc;
1168 } 1181 }
1169 } else 1182 } else {
1183 cifs_update_eof(cifsi, *poffset, bytes_written);
1170 *poffset += bytes_written; 1184 *poffset += bytes_written;
1185 }
1171 long_op = CIFS_STD_OP; /* subsequent writes fast - 1186 long_op = CIFS_STD_OP; /* subsequent writes fast -
1172 15 seconds is plenty */ 1187 15 seconds is plenty */
1173 } 1188 }
@@ -1380,11 +1395,12 @@ static int cifs_writepages(struct address_space *mapping,
1380 int nr_pages; 1395 int nr_pages;
1381 __u64 offset = 0; 1396 __u64 offset = 0;
1382 struct cifsFileInfo *open_file; 1397 struct cifsFileInfo *open_file;
1398 struct cifsInodeInfo *cifsi = CIFS_I(mapping->host);
1383 struct page *page; 1399 struct page *page;
1384 struct pagevec pvec; 1400 struct pagevec pvec;
1385 int rc = 0; 1401 int rc = 0;
1386 int scanned = 0; 1402 int scanned = 0;
1387 int xid; 1403 int xid, long_op;
1388 1404
1389 cifs_sb = CIFS_SB(mapping->host->i_sb); 1405 cifs_sb = CIFS_SB(mapping->host->i_sb);
1390 1406
@@ -1528,12 +1544,15 @@ retry:
1528 cERROR(1, ("No writable handles for inode")); 1544 cERROR(1, ("No writable handles for inode"));
1529 rc = -EBADF; 1545 rc = -EBADF;
1530 } else { 1546 } else {
1547 long_op = cifs_write_timeout(cifsi, offset);
1531 rc = CIFSSMBWrite2(xid, cifs_sb->tcon, 1548 rc = CIFSSMBWrite2(xid, cifs_sb->tcon,
1532 open_file->netfid, 1549 open_file->netfid,
1533 bytes_to_write, offset, 1550 bytes_to_write, offset,
1534 &bytes_written, iov, n_iov, 1551 &bytes_written, iov, n_iov,
1535 CIFS_LONG_OP); 1552 long_op);
1536 atomic_dec(&open_file->wrtPending); 1553 atomic_dec(&open_file->wrtPending);
1554 cifs_update_eof(cifsi, offset, bytes_written);
1555
1537 if (rc || bytes_written < bytes_to_write) { 1556 if (rc || bytes_written < bytes_to_write) {
1538 cERROR(1, ("Write2 ret %d, wrote %d", 1557 cERROR(1, ("Write2 ret %d, wrote %d",
1539 rc, bytes_written)); 1558 rc, bytes_written));
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index f121a80fdd6f..9c869a6dcba1 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -143,6 +143,7 @@ static void cifs_unix_info_to_inode(struct inode *inode,
143 143
144 inode->i_nlink = le64_to_cpu(info->Nlinks); 144 inode->i_nlink = le64_to_cpu(info->Nlinks);
145 145
146 cifsInfo->server_eof = end_of_file;
146 spin_lock(&inode->i_lock); 147 spin_lock(&inode->i_lock);
147 if (is_size_safe_to_change(cifsInfo, end_of_file)) { 148 if (is_size_safe_to_change(cifsInfo, end_of_file)) {
148 /* 149 /*
@@ -276,7 +277,8 @@ int cifs_get_inode_info_unix(struct inode **pinode,
276 277
277 /* get new inode */ 278 /* get new inode */
278 if (*pinode == NULL) { 279 if (*pinode == NULL) {
279 *pinode = cifs_new_inode(sb, &find_data.UniqueId); 280 __u64 unique_id = le64_to_cpu(find_data.UniqueId);
281 *pinode = cifs_new_inode(sb, &unique_id);
280 if (*pinode == NULL) { 282 if (*pinode == NULL) {
281 rc = -ENOMEM; 283 rc = -ENOMEM;
282 goto cgiiu_exit; 284 goto cgiiu_exit;
@@ -605,12 +607,12 @@ int cifs_get_inode_info(struct inode **pinode,
605 inode->i_mode |= S_IFREG; 607 inode->i_mode |= S_IFREG;
606 } 608 }
607 609
610 cifsInfo->server_eof = le64_to_cpu(pfindData->EndOfFile);
608 spin_lock(&inode->i_lock); 611 spin_lock(&inode->i_lock);
609 if (is_size_safe_to_change(cifsInfo, 612 if (is_size_safe_to_change(cifsInfo, cifsInfo->server_eof)) {
610 le64_to_cpu(pfindData->EndOfFile))) {
611 /* can not safely shrink the file size here if the 613 /* can not safely shrink the file size here if the
612 client is writing to it due to potential races */ 614 client is writing to it due to potential races */
613 i_size_write(inode, le64_to_cpu(pfindData->EndOfFile)); 615 i_size_write(inode, cifsInfo->server_eof);
614 616
615 /* 512 bytes (2**9) is the fake blocksize that must be 617 /* 512 bytes (2**9) is the fake blocksize that must be
616 used for this calculation */ 618 used for this calculation */
@@ -960,13 +962,21 @@ undo_setattr:
960 goto out_close; 962 goto out_close;
961} 963}
962 964
965
966/*
967 * If dentry->d_inode is null (usually meaning the cached dentry
968 * is a negative dentry) then we would attempt a standard SMB delete, but
969 * if that fails we can not attempt the fall back mechanisms on EACESS
970 * but will return the EACESS to the caller. Note that the VFS does not call
971 * unlink on negative dentries currently.
972 */
963int cifs_unlink(struct inode *dir, struct dentry *dentry) 973int cifs_unlink(struct inode *dir, struct dentry *dentry)
964{ 974{
965 int rc = 0; 975 int rc = 0;
966 int xid; 976 int xid;
967 char *full_path = NULL; 977 char *full_path = NULL;
968 struct inode *inode = dentry->d_inode; 978 struct inode *inode = dentry->d_inode;
969 struct cifsInodeInfo *cifsInode = CIFS_I(inode); 979 struct cifsInodeInfo *cifs_inode;
970 struct super_block *sb = dir->i_sb; 980 struct super_block *sb = dir->i_sb;
971 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 981 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
972 struct cifsTconInfo *tcon = cifs_sb->tcon; 982 struct cifsTconInfo *tcon = cifs_sb->tcon;
@@ -1010,7 +1020,7 @@ psx_del_no_retry:
1010 rc = cifs_rename_pending_delete(full_path, dentry, xid); 1020 rc = cifs_rename_pending_delete(full_path, dentry, xid);
1011 if (rc == 0) 1021 if (rc == 0)
1012 drop_nlink(inode); 1022 drop_nlink(inode);
1013 } else if (rc == -EACCES && dosattr == 0) { 1023 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
1014 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); 1024 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1015 if (attrs == NULL) { 1025 if (attrs == NULL) {
1016 rc = -ENOMEM; 1026 rc = -ENOMEM;
@@ -1018,7 +1028,8 @@ psx_del_no_retry:
1018 } 1028 }
1019 1029
1020 /* try to reset dos attributes */ 1030 /* try to reset dos attributes */
1021 origattr = cifsInode->cifsAttrs; 1031 cifs_inode = CIFS_I(inode);
1032 origattr = cifs_inode->cifsAttrs;
1022 if (origattr == 0) 1033 if (origattr == 0)
1023 origattr |= ATTR_NORMAL; 1034 origattr |= ATTR_NORMAL;
1024 dosattr = origattr & ~ATTR_READONLY; 1035 dosattr = origattr & ~ATTR_READONLY;
@@ -1039,13 +1050,13 @@ psx_del_no_retry:
1039 1050
1040out_reval: 1051out_reval:
1041 if (inode) { 1052 if (inode) {
1042 cifsInode = CIFS_I(inode); 1053 cifs_inode = CIFS_I(inode);
1043 cifsInode->time = 0; /* will force revalidate to get info 1054 cifs_inode->time = 0; /* will force revalidate to get info
1044 when needed */ 1055 when needed */
1045 inode->i_ctime = current_fs_time(sb); 1056 inode->i_ctime = current_fs_time(sb);
1046 } 1057 }
1047 dir->i_ctime = dir->i_mtime = current_fs_time(sb); 1058 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
1048 cifsInode = CIFS_I(dir); 1059 cifs_inode = CIFS_I(dir);
1049 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ 1060 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
1050 1061
1051 kfree(full_path); 1062 kfree(full_path);
@@ -1138,6 +1149,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
1138 cFYI(1, ("posix mkdir returned 0x%x", rc)); 1149 cFYI(1, ("posix mkdir returned 0x%x", rc));
1139 d_drop(direntry); 1150 d_drop(direntry);
1140 } else { 1151 } else {
1152 __u64 unique_id;
1141 if (pInfo->Type == cpu_to_le32(-1)) { 1153 if (pInfo->Type == cpu_to_le32(-1)) {
1142 /* no return info, go query for it */ 1154 /* no return info, go query for it */
1143 kfree(pInfo); 1155 kfree(pInfo);
@@ -1151,8 +1163,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
1151 else 1163 else
1152 direntry->d_op = &cifs_dentry_ops; 1164 direntry->d_op = &cifs_dentry_ops;
1153 1165
1154 newinode = cifs_new_inode(inode->i_sb, 1166 unique_id = le64_to_cpu(pInfo->UniqueId);
1155 &pInfo->UniqueId); 1167 newinode = cifs_new_inode(inode->i_sb, &unique_id);
1156 if (newinode == NULL) { 1168 if (newinode == NULL) {
1157 kfree(pInfo); 1169 kfree(pInfo);
1158 goto mkdir_get_info; 1170 goto mkdir_get_info;
@@ -1450,7 +1462,8 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
1450 checking the UniqueId via FILE_INTERNAL_INFO */ 1462 checking the UniqueId via FILE_INTERNAL_INFO */
1451 1463
1452unlink_target: 1464unlink_target:
1453 if ((rc == -EACCES) || (rc == -EEXIST)) { 1465 /* Try unlinking the target dentry if it's not negative */
1466 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
1454 tmprc = cifs_unlink(target_dir, target_dentry); 1467 tmprc = cifs_unlink(target_dir, target_dentry);
1455 if (tmprc) 1468 if (tmprc)
1456 goto cifs_rename_exit; 1469 goto cifs_rename_exit;
@@ -1753,6 +1766,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
1753 } 1766 }
1754 1767
1755 if (rc == 0) { 1768 if (rc == 0) {
1769 cifsInode->server_eof = attrs->ia_size;
1756 rc = cifs_vmtruncate(inode, attrs->ia_size); 1770 rc = cifs_vmtruncate(inode, attrs->ia_size);
1757 cifs_truncate_page(inode->i_mapping, inode->i_size); 1771 cifs_truncate_page(inode->i_mapping, inode->i_size);
1758 } 1772 }
@@ -1792,20 +1806,21 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1792 goto out; 1806 goto out;
1793 } 1807 }
1794 1808
1795 if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { 1809 /*
1796 /* 1810 * Attempt to flush data before changing attributes. We need to do
1797 Flush data before changing file size or changing the last 1811 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
1798 write time of the file on the server. If the 1812 * ownership or mode then we may also need to do this. Here, we take
1799 flush returns error, store it to report later and continue. 1813 * the safe way out and just do the flush on all setattr requests. If
1800 BB: This should be smarter. Why bother flushing pages that 1814 * the flush returns error, store it to report later and continue.
1801 will be truncated anyway? Also, should we error out here if 1815 *
1802 the flush returns error? 1816 * BB: This should be smarter. Why bother flushing pages that
1803 */ 1817 * will be truncated anyway? Also, should we error out here if
1804 rc = filemap_write_and_wait(inode->i_mapping); 1818 * the flush returns error?
1805 if (rc != 0) { 1819 */
1806 cifsInode->write_behind_rc = rc; 1820 rc = filemap_write_and_wait(inode->i_mapping);
1807 rc = 0; 1821 if (rc != 0) {
1808 } 1822 cifsInode->write_behind_rc = rc;
1823 rc = 0;
1809 } 1824 }
1810 1825
1811 if (attrs->ia_valid & ATTR_SIZE) { 1826 if (attrs->ia_valid & ATTR_SIZE) {
@@ -1903,20 +1918,21 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
1903 return -ENOMEM; 1918 return -ENOMEM;
1904 } 1919 }
1905 1920
1906 if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { 1921 /*
1907 /* 1922 * Attempt to flush data before changing attributes. We need to do
1908 Flush data before changing file size or changing the last 1923 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
1909 write time of the file on the server. If the 1924 * ownership or mode then we may also need to do this. Here, we take
1910 flush returns error, store it to report later and continue. 1925 * the safe way out and just do the flush on all setattr requests. If
1911 BB: This should be smarter. Why bother flushing pages that 1926 * the flush returns error, store it to report later and continue.
1912 will be truncated anyway? Also, should we error out here if 1927 *
1913 the flush returns error? 1928 * BB: This should be smarter. Why bother flushing pages that
1914 */ 1929 * will be truncated anyway? Also, should we error out here if
1915 rc = filemap_write_and_wait(inode->i_mapping); 1930 * the flush returns error?
1916 if (rc != 0) { 1931 */
1917 cifsInode->write_behind_rc = rc; 1932 rc = filemap_write_and_wait(inode->i_mapping);
1918 rc = 0; 1933 if (rc != 0) {
1919 } 1934 cifsInode->write_behind_rc = rc;
1935 rc = 0;
1920 } 1936 }
1921 1937
1922 if (attrs->ia_valid & ATTR_SIZE) { 1938 if (attrs->ia_valid & ATTR_SIZE) {
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 63f644000ce5..ea9d11e3dcbb 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -119,16 +119,11 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
119 full_path = build_path_from_dentry(direntry); 119 full_path = build_path_from_dentry(direntry);
120 120
121 if (!full_path) 121 if (!full_path)
122 goto out_no_free; 122 goto out;
123 123
124 cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode)); 124 cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
125 cifs_sb = CIFS_SB(inode->i_sb); 125 cifs_sb = CIFS_SB(inode->i_sb);
126 pTcon = cifs_sb->tcon; 126 pTcon = cifs_sb->tcon;
127 target_path = kmalloc(PATH_MAX, GFP_KERNEL);
128 if (!target_path) {
129 target_path = ERR_PTR(-ENOMEM);
130 goto out;
131 }
132 127
133 /* We could change this to: 128 /* We could change this to:
134 if (pTcon->unix_ext) 129 if (pTcon->unix_ext)
@@ -138,8 +133,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
138 133
139 if (pTcon->ses->capabilities & CAP_UNIX) 134 if (pTcon->ses->capabilities & CAP_UNIX)
140 rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path, 135 rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
141 target_path, 136 &target_path,
142 PATH_MAX-1,
143 cifs_sb->local_nls); 137 cifs_sb->local_nls);
144 else { 138 else {
145 /* BB add read reparse point symlink code here */ 139 /* BB add read reparse point symlink code here */
@@ -148,22 +142,16 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
148 /* BB Add MAC style xsymlink check here if enabled */ 142 /* BB Add MAC style xsymlink check here if enabled */
149 } 143 }
150 144
151 if (rc == 0) { 145 if (rc != 0) {
152
153/* BB Add special case check for Samba DFS symlinks */
154
155 target_path[PATH_MAX-1] = 0;
156 } else {
157 kfree(target_path); 146 kfree(target_path);
158 target_path = ERR_PTR(rc); 147 target_path = ERR_PTR(rc);
159 } 148 }
160 149
161out:
162 kfree(full_path); 150 kfree(full_path);
163out_no_free: 151out:
164 FreeXid(xid); 152 FreeXid(xid);
165 nd_set_link(nd, target_path); 153 nd_set_link(nd, target_path);
166 return NULL; /* No cookie */ 154 return NULL;
167} 155}
168 156
169int 157int
@@ -224,98 +212,6 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
224 return rc; 212 return rc;
225} 213}
226 214
227int
228cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
229{
230 struct inode *inode = direntry->d_inode;
231 int rc = -EACCES;
232 int xid;
233 int oplock = 0;
234 struct cifs_sb_info *cifs_sb;
235 struct cifsTconInfo *pTcon;
236 char *full_path = NULL;
237 char *tmpbuffer;
238 int len;
239 __u16 fid;
240
241 xid = GetXid();
242 cifs_sb = CIFS_SB(inode->i_sb);
243 pTcon = cifs_sb->tcon;
244
245/* BB would it be safe against deadlock to grab this sem
246 even though rename itself grabs the sem and calls lookup? */
247/* mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/
248 full_path = build_path_from_dentry(direntry);
249/* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/
250
251 if (full_path == NULL) {
252 FreeXid(xid);
253 return -ENOMEM;
254 }
255
256 cFYI(1,
257 ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
258 full_path, inode, pBuffer, buflen));
259 if (buflen > PATH_MAX)
260 len = PATH_MAX;
261 else
262 len = buflen;
263 tmpbuffer = kmalloc(len, GFP_KERNEL);
264 if (tmpbuffer == NULL) {
265 kfree(full_path);
266 FreeXid(xid);
267 return -ENOMEM;
268 }
269
270/* BB add read reparse point symlink code and
271 Unix extensions symlink code here BB */
272/* We could disable this based on pTcon->unix_ext flag instead ... but why? */
273 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
274 rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
275 tmpbuffer,
276 len - 1,
277 cifs_sb->local_nls);
278 else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
279 cERROR(1, ("SFU style symlinks not implemented yet"));
280 /* add open and read as in fs/cifs/inode.c */
281 } else {
282 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
283 OPEN_REPARSE_POINT, &fid, &oplock, NULL,
284 cifs_sb->local_nls,
285 cifs_sb->mnt_cifs_flags &
286 CIFS_MOUNT_MAP_SPECIAL_CHR);
287 if (!rc) {
288 rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
289 tmpbuffer,
290 len - 1,
291 fid,
292 cifs_sb->local_nls);
293 if (CIFSSMBClose(xid, pTcon, fid)) {
294 cFYI(1, ("Error closing junction point "
295 "(open for ioctl)"));
296 }
297 /* If it is a DFS junction earlier we would have gotten
298 PATH_NOT_COVERED returned from server so we do
299 not need to request the DFS info here */
300 }
301 }
302 /* BB Anything else to do to handle recursive links? */
303 /* BB Should we be using page ops here? */
304
305 /* BB null terminate returned string in pBuffer? BB */
306 if (rc == 0) {
307 rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer);
308 cFYI(1,
309 ("vfs_readlink called from cifs_readlink returned %d",
310 rc));
311 }
312
313 kfree(tmpbuffer);
314 kfree(full_path);
315 FreeXid(xid);
316 return rc;
317}
318
319void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie) 215void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie)
320{ 216{
321 char *p = nd_get_link(nd); 217 char *p = nd_get_link(nd);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 4c89c572891a..e079a9190ec4 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -635,77 +635,6 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
635 return; 635 return;
636} 636}
637 637
638/* Windows maps these to the user defined 16 bit Unicode range since they are
639 reserved symbols (along with \ and /), otherwise illegal to store
640 in filenames in NTFS */
641#define UNI_ASTERIK (__u16) ('*' + 0xF000)
642#define UNI_QUESTION (__u16) ('?' + 0xF000)
643#define UNI_COLON (__u16) (':' + 0xF000)
644#define UNI_GRTRTHAN (__u16) ('>' + 0xF000)
645#define UNI_LESSTHAN (__u16) ('<' + 0xF000)
646#define UNI_PIPE (__u16) ('|' + 0xF000)
647#define UNI_SLASH (__u16) ('\\' + 0xF000)
648
649/* Convert 16 bit Unicode pathname from wire format to string in current code
650 page. Conversion may involve remapping up the seven characters that are
651 only legal in POSIX-like OS (if they are present in the string). Path
652 names are little endian 16 bit Unicode on the wire */
653int
654cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
655 const struct nls_table *cp)
656{
657 int i, j, len;
658 __u16 src_char;
659
660 for (i = 0, j = 0; i < maxlen; i++) {
661 src_char = le16_to_cpu(source[i]);
662 switch (src_char) {
663 case 0:
664 goto cUCS_out; /* BB check this BB */
665 case UNI_COLON:
666 target[j] = ':';
667 break;
668 case UNI_ASTERIK:
669 target[j] = '*';
670 break;
671 case UNI_QUESTION:
672 target[j] = '?';
673 break;
674 /* BB We can not handle remapping slash until
675 all the calls to build_path_from_dentry
676 are modified, as they use slash as separator BB */
677 /* case UNI_SLASH:
678 target[j] = '\\';
679 break;*/
680 case UNI_PIPE:
681 target[j] = '|';
682 break;
683 case UNI_GRTRTHAN:
684 target[j] = '>';
685 break;
686 case UNI_LESSTHAN:
687 target[j] = '<';
688 break;
689 default:
690 len = cp->uni2char(src_char, &target[j],
691 NLS_MAX_CHARSET_SIZE);
692 if (len > 0) {
693 j += len;
694 continue;
695 } else {
696 target[j] = '?';
697 }
698 }
699 j++;
700 /* make sure we do not overrun callers allocated temp buffer */
701 if (j >= (2 * NAME_MAX))
702 break;
703 }
704cUCS_out:
705 target[j] = 0;
706 return j;
707}
708
709/* Convert 16 bit Unicode pathname to wire format from string in current code 638/* Convert 16 bit Unicode pathname to wire format from string in current code
710 page. Conversion may involve remapping up the seven characters that are 639 page. Conversion may involve remapping up the seven characters that are
711 only legal in POSIX-like OS (if they are present in the string). Path 640 only legal in POSIX-like OS (if they are present in the string). Path
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 8703d68f5b20..e2fe998989a3 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -79,6 +79,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
79 {ErrQuota, -EDQUOT}, 79 {ErrQuota, -EDQUOT},
80 {ErrNotALink, -ENOLINK}, 80 {ErrNotALink, -ENOLINK},
81 {ERRnetlogonNotStarted, -ENOPROTOOPT}, 81 {ERRnetlogonNotStarted, -ENOPROTOOPT},
82 {ERRsymlink, -EOPNOTSUPP},
82 {ErrTooManyLinks, -EMLINK}, 83 {ErrTooManyLinks, -EMLINK},
83 {0, 0} 84 {0, 0}
84}; 85};
@@ -714,6 +715,7 @@ static const struct {
714 ERRDOS, ERRnoaccess, 0xc000028f}, { 715 ERRDOS, ERRnoaccess, 0xc000028f}, {
715 ERRDOS, ERRnoaccess, 0xc0000290}, { 716 ERRDOS, ERRnoaccess, 0xc0000290}, {
716 ERRDOS, ERRbadfunc, 0xc000029c}, { 717 ERRDOS, ERRbadfunc, 0xc000029c}, {
718 ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, {
717 ERRDOS, ERRinvlevel, 0x007c0001}, }; 719 ERRDOS, ERRinvlevel, 0x007c0001}, };
718 720
719/***************************************************************************** 721/*****************************************************************************
diff --git a/fs/cifs/nterr.h b/fs/cifs/nterr.h
index 588abbb9d08c..257267367d41 100644
--- a/fs/cifs/nterr.h
+++ b/fs/cifs/nterr.h
@@ -35,8 +35,6 @@ struct nt_err_code_struct {
35extern const struct nt_err_code_struct nt_errs[]; 35extern const struct nt_err_code_struct nt_errs[];
36 36
37/* Win32 Status codes. */ 37/* Win32 Status codes. */
38
39#define STATUS_BUFFER_OVERFLOW 0x80000005
40#define STATUS_MORE_ENTRIES 0x0105 38#define STATUS_MORE_ENTRIES 0x0105
41#define ERROR_INVALID_PARAMETER 0x0057 39#define ERROR_INVALID_PARAMETER 0x0057
42#define ERROR_INSUFFICIENT_BUFFER 0x007a 40#define ERROR_INSUFFICIENT_BUFFER 0x007a
@@ -50,6 +48,13 @@ extern const struct nt_err_code_struct nt_errs[];
50#define STATUS_SOME_UNMAPPED 0x0107 48#define STATUS_SOME_UNMAPPED 0x0107
51#define STATUS_BUFFER_OVERFLOW 0x80000005 49#define STATUS_BUFFER_OVERFLOW 0x80000005
52#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a 50#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a
51#define NT_STATUS_MEDIA_CHANGED 0x8000001c
52#define NT_STATUS_END_OF_MEDIA 0x8000001e
53#define NT_STATUS_MEDIA_CHECK 0x80000020
54#define NT_STATUS_NO_DATA_DETECTED 0x8000001c
55#define NT_STATUS_STOPPED_ON_SYMLINK 0x8000002d
56#define NT_STATUS_DEVICE_REQUIRES_CLEANING 0x80000288
57#define NT_STATUS_DEVICE_DOOR_OPEN 0x80000288
53#define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001 58#define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001
54#define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002 59#define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002
55#define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003 60#define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
index c377d8065d99..49c9a4e75319 100644
--- a/fs/cifs/ntlmssp.h
+++ b/fs/cifs/ntlmssp.h
@@ -27,29 +27,39 @@
27#define UnknownMessage cpu_to_le32(8) 27#define UnknownMessage cpu_to_le32(8)
28 28
29/* Negotiate Flags */ 29/* Negotiate Flags */
30#define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are in unicode */ 30#define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are unicode */
31#define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */ 31#define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */
32#define NTLMSSP_REQUEST_TARGET 0x04 /* Server return its auth realm */ 32#define NTLMSSP_REQUEST_TARGET 0x04 /* Srv returns its auth realm */
33#define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signature capability */ 33/* define reserved9 0x08 */
34#define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */ 34#define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signing capability */
35#define NTLMSSP_NEGOTIATE_DGRAM 0x0040 35#define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */
36#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Sign/seal use LM session key */ 36#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
37#define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */ 37#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Use LM session key */
38#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 38/* defined reserved 8 0x0100 */
39#define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */
40#define NTLMSSP_NEGOTIATE_NT_ONLY 0x0400 /* Lanman not allowed */
41#define NTLMSSP_ANONYMOUS 0x0800
42#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 /* reserved6 */
39#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000 43#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
40#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server on same machine */ 44#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server same machine */
41#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign for all security levels */ 45#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign. All security levels */
42#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000 46#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
43#define NTLMSSP_TARGET_TYPE_SERVER 0x20000 47#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
44#define NTLMSSP_TARGET_TYPE_SHARE 0x40000 48#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
45#define NTLMSSP_NEGOTIATE_NTLMV2 0x80000 49#define NTLMSSP_NEGOTIATE_EXTENDED_SEC 0x80000 /* NB:not related to NTLMv2 pwd*/
46#define NTLMSSP_REQUEST_INIT_RESP 0x100000 50/* #define NTLMSSP_REQUEST_INIT_RESP 0x100000 */
47#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000 51#define NTLMSSP_NEGOTIATE_IDENTIFY 0x100000
48#define NTLMSSP_REQUEST_NOT_NT_KEY 0x400000 52#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000 /* reserved5 */
53#define NTLMSSP_REQUEST_NON_NT_KEY 0x400000
49#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000 54#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
50#define NTLMSSP_NEGOTIATE_128 0x20000000 55/* #define reserved4 0x1000000 */
51#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000 56#define NTLMSSP_NEGOTIATE_VERSION 0x2000000 /* we do not set */
52#define NTLMSSP_NEGOTIATE_56 0x80000000 57/* #define reserved3 0x4000000 */
58/* #define reserved2 0x8000000 */
59/* #define reserved1 0x10000000 */
60#define NTLMSSP_NEGOTIATE_128 0x20000000
61#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
62#define NTLMSSP_NEGOTIATE_56 0x80000000
53 63
54/* Although typedefs are not commonly used for structure definitions */ 64/* Although typedefs are not commonly used for structure definitions */
55/* in the Linux kernel, in this particular case they are useful */ 65/* in the Linux kernel, in this particular case they are useful */
@@ -60,32 +70,36 @@
60typedef struct _SECURITY_BUFFER { 70typedef struct _SECURITY_BUFFER {
61 __le16 Length; 71 __le16 Length;
62 __le16 MaximumLength; 72 __le16 MaximumLength;
63 __le32 Buffer; /* offset to buffer */ 73 __le32 BufferOffset; /* offset to buffer */
64} __attribute__((packed)) SECURITY_BUFFER; 74} __attribute__((packed)) SECURITY_BUFFER;
65 75
66typedef struct _NEGOTIATE_MESSAGE { 76typedef struct _NEGOTIATE_MESSAGE {
67 __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; 77 __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
68 __le32 MessageType; /* 1 */ 78 __le32 MessageType; /* NtLmNegotiate = 1 */
69 __le32 NegotiateFlags; 79 __le32 NegotiateFlags;
70 SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */ 80 SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */
71 SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */ 81 SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
82 /* SECURITY_BUFFER for version info not present since we
83 do not set the version is present flag */
72 char DomainString[0]; 84 char DomainString[0];
73 /* followed by WorkstationString */ 85 /* followed by WorkstationString */
74} __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE; 86} __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
75 87
76typedef struct _CHALLENGE_MESSAGE { 88typedef struct _CHALLENGE_MESSAGE {
77 __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; 89 __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
78 __le32 MessageType; /* 2 */ 90 __le32 MessageType; /* NtLmChallenge = 2 */
79 SECURITY_BUFFER TargetName; 91 SECURITY_BUFFER TargetName;
80 __le32 NegotiateFlags; 92 __le32 NegotiateFlags;
81 __u8 Challenge[CIFS_CRYPTO_KEY_SIZE]; 93 __u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
82 __u8 Reserved[8]; 94 __u8 Reserved[8];
83 SECURITY_BUFFER TargetInfoArray; 95 SECURITY_BUFFER TargetInfoArray;
96 /* SECURITY_BUFFER for version info not present since we
97 do not set the version is present flag */
84} __attribute__((packed)) CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE; 98} __attribute__((packed)) CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
85 99
86typedef struct _AUTHENTICATE_MESSAGE { 100typedef struct _AUTHENTICATE_MESSAGE {
87 __u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; 101 __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
88 __le32 MessageType; /* 3 */ 102 __le32 MessageType; /* NtLmsAuthenticate = 3 */
89 SECURITY_BUFFER LmChallengeResponse; 103 SECURITY_BUFFER LmChallengeResponse;
90 SECURITY_BUFFER NtChallengeResponse; 104 SECURITY_BUFFER NtChallengeResponse;
91 SECURITY_BUFFER DomainName; 105 SECURITY_BUFFER DomainName;
@@ -93,5 +107,7 @@ typedef struct _AUTHENTICATE_MESSAGE {
93 SECURITY_BUFFER WorkstationName; 107 SECURITY_BUFFER WorkstationName;
94 SECURITY_BUFFER SessionKey; 108 SECURITY_BUFFER SessionKey;
95 __le32 NegotiateFlags; 109 __le32 NegotiateFlags;
110 /* SECURITY_BUFFER for version info not present since we
111 do not set the version is present flag */
96 char UserString[0]; 112 char UserString[0];
97} __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE; 113} __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index c2c01ff4c32c..964e097c8203 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -31,6 +31,13 @@
31#include "cifs_fs_sb.h" 31#include "cifs_fs_sb.h"
32#include "cifsfs.h" 32#include "cifsfs.h"
33 33
34/*
35 * To be safe - for UCS to UTF-8 with strings loaded with the rare long
36 * characters alloc more to account for such multibyte target UTF-8
37 * characters.
38 */
39#define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2)
40
34#ifdef CONFIG_CIFS_DEBUG2 41#ifdef CONFIG_CIFS_DEBUG2
35static void dump_cifs_file_struct(struct file *file, char *label) 42static void dump_cifs_file_struct(struct file *file, char *label)
36{ 43{
@@ -239,6 +246,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
239 if (atomic_read(&cifsInfo->inUse) == 0) 246 if (atomic_read(&cifsInfo->inUse) == 0)
240 atomic_set(&cifsInfo->inUse, 1); 247 atomic_set(&cifsInfo->inUse, 1);
241 248
249 cifsInfo->server_eof = end_of_file;
242 spin_lock(&tmp_inode->i_lock); 250 spin_lock(&tmp_inode->i_lock);
243 if (is_size_safe_to_change(cifsInfo, end_of_file)) { 251 if (is_size_safe_to_change(cifsInfo, end_of_file)) {
244 /* can not safely change the file size here if the 252 /* can not safely change the file size here if the
@@ -375,6 +383,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
375 tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); 383 tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
376 tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); 384 tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
377 385
386 cifsInfo->server_eof = end_of_file;
378 spin_lock(&tmp_inode->i_lock); 387 spin_lock(&tmp_inode->i_lock);
379 if (is_size_safe_to_change(cifsInfo, end_of_file)) { 388 if (is_size_safe_to_change(cifsInfo, end_of_file)) {
380 /* can not safely change the file size here if the 389 /* can not safely change the file size here if the
@@ -436,6 +445,38 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
436 } 445 }
437} 446}
438 447
448/* BB eventually need to add the following helper function to
449 resolve NT_STATUS_STOPPED_ON_SYMLINK return code when
450 we try to do FindFirst on (NTFS) directory symlinks */
451/*
452int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
453 int xid)
454{
455 __u16 fid;
456 int len;
457 int oplock = 0;
458 int rc;
459 struct cifsTconInfo *ptcon = cifs_sb->tcon;
460 char *tmpbuffer;
461
462 rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ,
463 OPEN_REPARSE_POINT, &fid, &oplock, NULL,
464 cifs_sb->local_nls,
465 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
466 if (!rc) {
467 tmpbuffer = kmalloc(maxpath);
468 rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path,
469 tmpbuffer,
470 maxpath -1,
471 fid,
472 cifs_sb->local_nls);
473 if (CIFSSMBClose(xid, ptcon, fid)) {
474 cFYI(1, ("Error closing temporary reparsepoint open)"));
475 }
476 }
477}
478 */
479
439static int initiate_cifs_search(const int xid, struct file *file) 480static int initiate_cifs_search(const int xid, struct file *file)
440{ 481{
441 int rc = 0; 482 int rc = 0;
@@ -491,7 +532,10 @@ ffirst_retry:
491 CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); 532 CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
492 if (rc == 0) 533 if (rc == 0)
493 cifsFile->invalidHandle = false; 534 cifsFile->invalidHandle = false;
494 if ((rc == -EOPNOTSUPP) && 535 /* BB add following call to handle readdir on new NTFS symlink errors
536 else if STATUS_STOPPED_ON_SYMLINK
537 call get_symlink_reparse_path and retry with new path */
538 else if ((rc == -EOPNOTSUPP) &&
495 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { 539 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
496 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; 540 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
497 goto ffirst_retry; 541 goto ffirst_retry;
@@ -820,7 +864,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
820/* inode num, inode type and filename returned */ 864/* inode num, inode type and filename returned */
821static int cifs_get_name_from_search_buf(struct qstr *pqst, 865static int cifs_get_name_from_search_buf(struct qstr *pqst,
822 char *current_entry, __u16 level, unsigned int unicode, 866 char *current_entry, __u16 level, unsigned int unicode,
823 struct cifs_sb_info *cifs_sb, int max_len, __u64 *pinum) 867 struct cifs_sb_info *cifs_sb, unsigned int max_len, __u64 *pinum)
824{ 868{
825 int rc = 0; 869 int rc = 0;
826 unsigned int len = 0; 870 unsigned int len = 0;
@@ -840,7 +884,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
840 len = strnlen(filename, PATH_MAX); 884 len = strnlen(filename, PATH_MAX);
841 } 885 }
842 886
843 *pinum = pFindData->UniqueId; 887 *pinum = le64_to_cpu(pFindData->UniqueId);
844 } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { 888 } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
845 FILE_DIRECTORY_INFO *pFindData = 889 FILE_DIRECTORY_INFO *pFindData =
846 (FILE_DIRECTORY_INFO *)current_entry; 890 (FILE_DIRECTORY_INFO *)current_entry;
@@ -856,7 +900,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
856 (SEARCH_ID_FULL_DIR_INFO *)current_entry; 900 (SEARCH_ID_FULL_DIR_INFO *)current_entry;
857 filename = &pFindData->FileName[0]; 901 filename = &pFindData->FileName[0];
858 len = le32_to_cpu(pFindData->FileNameLength); 902 len = le32_to_cpu(pFindData->FileNameLength);
859 *pinum = pFindData->UniqueId; 903 *pinum = le64_to_cpu(pFindData->UniqueId);
860 } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { 904 } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
861 FILE_BOTH_DIRECTORY_INFO *pFindData = 905 FILE_BOTH_DIRECTORY_INFO *pFindData =
862 (FILE_BOTH_DIRECTORY_INFO *)current_entry; 906 (FILE_BOTH_DIRECTORY_INFO *)current_entry;
@@ -879,14 +923,12 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
879 } 923 }
880 924
881 if (unicode) { 925 if (unicode) {
882 /* BB fixme - test with long names */ 926 pqst->len = cifs_from_ucs2((char *) pqst->name,
883 /* Note converted filename can be longer than in unicode */ 927 (__le16 *) filename,
884 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) 928 UNICODE_NAME_MAX,
885 pqst->len = cifs_convertUCSpath((char *)pqst->name, 929 min(len, max_len), nlt,
886 (__le16 *)filename, len/2, nlt); 930 cifs_sb->mnt_cifs_flags &
887 else 931 CIFS_MOUNT_MAP_SPECIAL_CHR);
888 pqst->len = cifs_strfromUCS_le((char *)pqst->name,
889 (__le16 *)filename, len/2, nlt);
890 } else { 932 } else {
891 pqst->name = filename; 933 pqst->name = filename;
892 pqst->len = len; 934 pqst->len = len;
@@ -896,8 +938,8 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
896 return rc; 938 return rc;
897} 939}
898 940
899static int cifs_filldir(char *pfindEntry, struct file *file, 941static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
900 filldir_t filldir, void *direntry, char *scratch_buf, int max_len) 942 void *direntry, char *scratch_buf, unsigned int max_len)
901{ 943{
902 int rc = 0; 944 int rc = 0;
903 struct qstr qstring; 945 struct qstr qstring;
@@ -994,7 +1036,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
994 int num_to_fill = 0; 1036 int num_to_fill = 0;
995 char *tmp_buf = NULL; 1037 char *tmp_buf = NULL;
996 char *end_of_smb; 1038 char *end_of_smb;
997 int max_len; 1039 unsigned int max_len;
998 1040
999 xid = GetXid(); 1041 xid = GetXid();
1000 1042
@@ -1068,11 +1110,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
1068 cifsFile->srch_inf.ntwrk_buf_start); 1110 cifsFile->srch_inf.ntwrk_buf_start);
1069 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; 1111 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
1070 1112
1071 /* To be safe - for UCS to UTF-8 with strings loaded 1113 tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
1072 with the rare long characters alloc more to account for
1073 such multibyte target UTF-8 characters. cifs_unicode.c,
1074 which actually does the conversion, has the same limit */
1075 tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL);
1076 for (i = 0; (i < num_to_fill) && (rc == 0); i++) { 1114 for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
1077 if (current_entry == NULL) { 1115 if (current_entry == NULL) {
1078 /* evaluate whether this case is an error */ 1116 /* evaluate whether this case is an error */
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 5c68b4282be9..897a052270f9 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * SMB/CIFS session setup handling routines 4 * SMB/CIFS session setup handling routines
5 * 5 *
6 * Copyright (c) International Business Machines Corp., 2006, 2007 6 * Copyright (c) International Business Machines Corp., 2006, 2009
7 * Author(s): Steve French (sfrench@us.ibm.com) 7 * Author(s): Steve French (sfrench@us.ibm.com)
8 * 8 *
9 * This library is free software; you can redistribute it and/or modify 9 * This library is free software; you can redistribute it and/or modify
@@ -111,7 +111,7 @@ static __le16 get_next_vcnum(struct cifsSesInfo *ses)
111get_vc_num_exit: 111get_vc_num_exit:
112 write_unlock(&cifs_tcp_ses_lock); 112 write_unlock(&cifs_tcp_ses_lock);
113 113
114 return le16_to_cpu(vcnum); 114 return cpu_to_le16(vcnum);
115} 115}
116 116
117static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) 117static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
@@ -277,85 +277,51 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
277 *pbcc_area = bcc_ptr; 277 *pbcc_area = bcc_ptr;
278} 278}
279 279
280static int decode_unicode_ssetup(char **pbcc_area, int bleft, 280static void
281 struct cifsSesInfo *ses, 281decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses,
282 const struct nls_table *nls_cp) 282 const struct nls_table *nls_cp)
283{ 283{
284 int rc = 0; 284 int len;
285 int words_left, len;
286 char *data = *pbcc_area; 285 char *data = *pbcc_area;
287 286
288
289
290 cFYI(1, ("bleft %d", bleft)); 287 cFYI(1, ("bleft %d", bleft));
291 288
292 289 /*
293 /* SMB header is unaligned, so cifs servers word align start of 290 * Windows servers do not always double null terminate their final
294 Unicode strings */ 291 * Unicode string. Check to see if there are an uneven number of bytes
295 data++; 292 * left. If so, then add an extra NULL pad byte to the end of the
296 bleft--; /* Windows servers do not always double null terminate 293 * response.
297 their final Unicode string - in which case we 294 *
298 now will not attempt to decode the byte of junk 295 * See section 2.7.2 in "Implementing CIFS" for details
299 which follows it */ 296 */
300 297 if (bleft % 2) {
301 words_left = bleft / 2; 298 data[bleft] = 0;
302 299 ++bleft;
303 /* save off server operating system */ 300 }
304 len = UniStrnlen((wchar_t *) data, words_left);
305
306/* We look for obvious messed up bcc or strings in response so we do not go off
307 the end since (at least) WIN2K and Windows XP have a major bug in not null
308 terminating last Unicode string in response */
309 if (len >= words_left)
310 return rc;
311 301
312 kfree(ses->serverOS); 302 kfree(ses->serverOS);
313 /* UTF-8 string will not grow more than four times as big as UCS-16 */ 303 ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
314 ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL); 304 cFYI(1, ("serverOS=%s", ses->serverOS));
315 if (ses->serverOS != NULL) 305 len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
316 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp); 306 data += len;
317 data += 2 * (len + 1); 307 bleft -= len;
318 words_left -= len + 1; 308 if (bleft <= 0)
319 309 return;
320 /* save off server network operating system */
321 len = UniStrnlen((wchar_t *) data, words_left);
322
323 if (len >= words_left)
324 return rc;
325 310
326 kfree(ses->serverNOS); 311 kfree(ses->serverNOS);
327 ses->serverNOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL); 312 ses->serverNOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
328 if (ses->serverNOS != NULL) { 313 cFYI(1, ("serverNOS=%s", ses->serverNOS));
329 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, 314 len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
330 nls_cp); 315 data += len;
331 if (strncmp(ses->serverNOS, "NT LAN Manager 4", 16) == 0) { 316 bleft -= len;
332 cFYI(1, ("NT4 server")); 317 if (bleft <= 0)
333 ses->flags |= CIFS_SES_NT4; 318 return;
334 }
335 }
336 data += 2 * (len + 1);
337 words_left -= len + 1;
338
339 /* save off server domain */
340 len = UniStrnlen((wchar_t *) data, words_left);
341
342 if (len > words_left)
343 return rc;
344 319
345 kfree(ses->serverDomain); 320 kfree(ses->serverDomain);
346 ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */ 321 ses->serverDomain = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
347 if (ses->serverDomain != NULL) { 322 cFYI(1, ("serverDomain=%s", ses->serverDomain));
348 cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
349 nls_cp);
350 ses->serverDomain[2*len] = 0;
351 ses->serverDomain[(2*len) + 1] = 0;
352 }
353 data += 2 * (len + 1);
354 words_left -= len + 1;
355 323
356 cFYI(1, ("words left: %d", words_left)); 324 return;
357
358 return rc;
359} 325}
360 326
361static int decode_ascii_ssetup(char **pbcc_area, int bleft, 327static int decode_ascii_ssetup(char **pbcc_area, int bleft,
@@ -412,6 +378,186 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
412 return rc; 378 return rc;
413} 379}
414 380
381static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
382 struct cifsSesInfo *ses)
383{
384 CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
385
386 if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
387 cERROR(1, ("challenge blob len %d too small", blob_len));
388 return -EINVAL;
389 }
390
391 if (memcmp(pblob->Signature, "NTLMSSP", 8)) {
392 cERROR(1, ("blob signature incorrect %s", pblob->Signature));
393 return -EINVAL;
394 }
395 if (pblob->MessageType != NtLmChallenge) {
396 cERROR(1, ("Incorrect message type %d", pblob->MessageType));
397 return -EINVAL;
398 }
399
400 memcpy(ses->server->cryptKey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
401 /* BB we could decode pblob->NegotiateFlags; some may be useful */
402 /* In particular we can examine sign flags */
403 /* BB spec says that if AvId field of MsvAvTimestamp is populated then
404 we must set the MIC field of the AUTHENTICATE_MESSAGE */
405
406 return 0;
407}
408
409#ifdef CONFIG_CIFS_EXPERIMENTAL
410/* BB Move to ntlmssp.c eventually */
411
412/* We do not malloc the blob, it is passed in pbuffer, because
413 it is fixed size, and small, making this approach cleaner */
414static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
415 struct cifsSesInfo *ses)
416{
417 NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer;
418 __u32 flags;
419
420 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
421 sec_blob->MessageType = NtLmNegotiate;
422
423 /* BB is NTLMV2 session security format easier to use here? */
424 flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
425 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
426 NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM;
427 if (ses->server->secMode &
428 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
429 flags |= NTLMSSP_NEGOTIATE_SIGN;
430 if (ses->server->secMode & SECMODE_SIGN_REQUIRED)
431 flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
432
433 sec_blob->NegotiateFlags |= cpu_to_le32(flags);
434
435 sec_blob->WorkstationName.BufferOffset = 0;
436 sec_blob->WorkstationName.Length = 0;
437 sec_blob->WorkstationName.MaximumLength = 0;
438
439 /* Domain name is sent on the Challenge not Negotiate NTLMSSP request */
440 sec_blob->DomainName.BufferOffset = 0;
441 sec_blob->DomainName.Length = 0;
442 sec_blob->DomainName.MaximumLength = 0;
443}
444
445/* We do not malloc the blob, it is passed in pbuffer, because its
446 maximum possible size is fixed and small, making this approach cleaner.
447 This function returns the length of the data in the blob */
448static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
449 struct cifsSesInfo *ses,
450 const struct nls_table *nls_cp, int first)
451{
452 AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;
453 __u32 flags;
454 unsigned char *tmp;
455 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
456
457 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
458 sec_blob->MessageType = NtLmAuthenticate;
459
460 flags = NTLMSSP_NEGOTIATE_56 |
461 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
462 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
463 NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM;
464 if (ses->server->secMode &
465 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
466 flags |= NTLMSSP_NEGOTIATE_SIGN;
467 if (ses->server->secMode & SECMODE_SIGN_REQUIRED)
468 flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
469
470 tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE);
471 sec_blob->NegotiateFlags |= cpu_to_le32(flags);
472
473 sec_blob->LmChallengeResponse.BufferOffset =
474 cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE));
475 sec_blob->LmChallengeResponse.Length = 0;
476 sec_blob->LmChallengeResponse.MaximumLength = 0;
477
478 /* calculate session key, BB what about adding similar ntlmv2 path? */
479 SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key);
480 if (first)
481 cifs_calculate_mac_key(&ses->server->mac_signing_key,
482 ntlm_session_key, ses->password);
483
484 memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE);
485 sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
486 sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE);
487 sec_blob->NtChallengeResponse.MaximumLength =
488 cpu_to_le16(CIFS_SESS_KEY_SIZE);
489
490 tmp += CIFS_SESS_KEY_SIZE;
491
492 if (ses->domainName == NULL) {
493 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
494 sec_blob->DomainName.Length = 0;
495 sec_blob->DomainName.MaximumLength = 0;
496 tmp += 2;
497 } else {
498 int len;
499 len = cifs_strtoUCS((__le16 *)tmp, ses->domainName,
500 MAX_USERNAME_SIZE, nls_cp);
501 len *= 2; /* unicode is 2 bytes each */
502 len += 2; /* trailing null */
503 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
504 sec_blob->DomainName.Length = cpu_to_le16(len);
505 sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
506 tmp += len;
507 }
508
509 if (ses->userName == NULL) {
510 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
511 sec_blob->UserName.Length = 0;
512 sec_blob->UserName.MaximumLength = 0;
513 tmp += 2;
514 } else {
515 int len;
516 len = cifs_strtoUCS((__le16 *)tmp, ses->userName,
517 MAX_USERNAME_SIZE, nls_cp);
518 len *= 2; /* unicode is 2 bytes each */
519 len += 2; /* trailing null */
520 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
521 sec_blob->UserName.Length = cpu_to_le16(len);
522 sec_blob->UserName.MaximumLength = cpu_to_le16(len);
523 tmp += len;
524 }
525
526 sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - pbuffer);
527 sec_blob->WorkstationName.Length = 0;
528 sec_blob->WorkstationName.MaximumLength = 0;
529 tmp += 2;
530
531 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
532 sec_blob->SessionKey.Length = 0;
533 sec_blob->SessionKey.MaximumLength = 0;
534 return tmp - pbuffer;
535}
536
537
538static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB,
539 struct cifsSesInfo *ses)
540{
541 build_ntlmssp_negotiate_blob(&pSMB->req.SecurityBlob[0], ses);
542 pSMB->req.SecurityBlobLength = cpu_to_le16(sizeof(NEGOTIATE_MESSAGE));
543
544 return;
545}
546
547static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB,
548 struct cifsSesInfo *ses,
549 const struct nls_table *nls, int first_time)
550{
551 int bloblen;
552
553 bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls,
554 first_time);
555 pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen);
556
557 return bloblen;
558}
559#endif
560
415int 561int
416CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, 562CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
417 const struct nls_table *nls_cp) 563 const struct nls_table *nls_cp)
@@ -430,6 +576,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
430 __u16 action; 576 __u16 action;
431 int bytes_remaining; 577 int bytes_remaining;
432 struct key *spnego_key = NULL; 578 struct key *spnego_key = NULL;
579 __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
433 580
434 if (ses == NULL) 581 if (ses == NULL)
435 return -EINVAL; 582 return -EINVAL;
@@ -437,6 +584,10 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
437 type = ses->server->secType; 584 type = ses->server->secType;
438 585
439 cFYI(1, ("sess setup type %d", type)); 586 cFYI(1, ("sess setup type %d", type));
587ssetup_ntlmssp_authenticate:
588 if (phase == NtLmChallenge)
589 phase = NtLmAuthenticate; /* if ntlmssp, now final phase */
590
440 if (type == LANMAN) { 591 if (type == LANMAN) {
441#ifndef CONFIG_CIFS_WEAK_PW_HASH 592#ifndef CONFIG_CIFS_WEAK_PW_HASH
442 /* LANMAN and plaintext are less secure and off by default. 593 /* LANMAN and plaintext are less secure and off by default.
@@ -650,9 +801,53 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
650 goto ssetup_exit; 801 goto ssetup_exit;
651#endif /* CONFIG_CIFS_UPCALL */ 802#endif /* CONFIG_CIFS_UPCALL */
652 } else { 803 } else {
804#ifdef CONFIG_CIFS_EXPERIMENTAL
805 if ((experimEnabled > 1) && (type == RawNTLMSSP)) {
806 if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
807 cERROR(1, ("NTLMSSP requires Unicode support"));
808 rc = -ENOSYS;
809 goto ssetup_exit;
810 }
811
812 cFYI(1, ("ntlmssp session setup phase %d", phase));
813 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
814 capabilities |= CAP_EXTENDED_SECURITY;
815 pSMB->req.Capabilities |= cpu_to_le32(capabilities);
816 if (phase == NtLmNegotiate) {
817 setup_ntlmssp_neg_req(pSMB, ses);
818 iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
819 } else if (phase == NtLmAuthenticate) {
820 int blob_len;
821 blob_len = setup_ntlmssp_auth_req(pSMB, ses,
822 nls_cp,
823 first_time);
824 iov[1].iov_len = blob_len;
825 /* Make sure that we tell the server that we
826 are using the uid that it just gave us back
827 on the response (challenge) */
828 smb_buf->Uid = ses->Suid;
829 } else {
830 cERROR(1, ("invalid phase %d", phase));
831 rc = -ENOSYS;
832 goto ssetup_exit;
833 }
834 iov[1].iov_base = &pSMB->req.SecurityBlob[0];
835 /* unicode strings must be word aligned */
836 if ((iov[0].iov_len + iov[1].iov_len) % 2) {
837 *bcc_ptr = 0;
838 bcc_ptr++;
839 }
840 unicode_oslm_strings(&bcc_ptr, nls_cp);
841 } else {
842 cERROR(1, ("secType %d not supported!", type));
843 rc = -ENOSYS;
844 goto ssetup_exit;
845 }
846#else
653 cERROR(1, ("secType %d not supported!", type)); 847 cERROR(1, ("secType %d not supported!", type));
654 rc = -ENOSYS; 848 rc = -ENOSYS;
655 goto ssetup_exit; 849 goto ssetup_exit;
850#endif
656 } 851 }
657 852
658 iov[2].iov_base = str_area; 853 iov[2].iov_base = str_area;
@@ -668,12 +863,23 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
668 /* SMB request buf freed in SendReceive2 */ 863 /* SMB request buf freed in SendReceive2 */
669 864
670 cFYI(1, ("ssetup rc from sendrecv2 is %d", rc)); 865 cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
671 if (rc)
672 goto ssetup_exit;
673 866
674 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base; 867 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
675 smb_buf = (struct smb_hdr *)iov[0].iov_base; 868 smb_buf = (struct smb_hdr *)iov[0].iov_base;
676 869
870 if ((type == RawNTLMSSP) && (smb_buf->Status.CifsError ==
871 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))) {
872 if (phase != NtLmNegotiate) {
873 cERROR(1, ("Unexpected more processing error"));
874 goto ssetup_exit;
875 }
876 /* NTLMSSP Negotiate sent now processing challenge (response) */
877 phase = NtLmChallenge; /* process ntlmssp challenge */
878 rc = 0; /* MORE_PROC rc is not an error here, but expected */
879 }
880 if (rc)
881 goto ssetup_exit;
882
677 if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) { 883 if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
678 rc = -EIO; 884 rc = -EIO;
679 cERROR(1, ("bad word count %d", smb_buf->WordCount)); 885 cERROR(1, ("bad word count %d", smb_buf->WordCount));
@@ -692,22 +898,33 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
692 if (smb_buf->WordCount == 4) { 898 if (smb_buf->WordCount == 4) {
693 __u16 blob_len; 899 __u16 blob_len;
694 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength); 900 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
695 bcc_ptr += blob_len;
696 if (blob_len > bytes_remaining) { 901 if (blob_len > bytes_remaining) {
697 cERROR(1, ("bad security blob length %d", blob_len)); 902 cERROR(1, ("bad security blob length %d", blob_len));
698 rc = -EINVAL; 903 rc = -EINVAL;
699 goto ssetup_exit; 904 goto ssetup_exit;
700 } 905 }
906 if (phase == NtLmChallenge) {
907 rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses);
908 /* now goto beginning for ntlmssp authenticate phase */
909 if (rc)
910 goto ssetup_exit;
911 }
912 bcc_ptr += blob_len;
701 bytes_remaining -= blob_len; 913 bytes_remaining -= blob_len;
702 } 914 }
703 915
704 /* BB check if Unicode and decode strings */ 916 /* BB check if Unicode and decode strings */
705 if (smb_buf->Flags2 & SMBFLG2_UNICODE) 917 if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
706 rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining, 918 /* unicode string area must be word-aligned */
707 ses, nls_cp); 919 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
708 else 920 ++bcc_ptr;
921 --bytes_remaining;
922 }
923 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses, nls_cp);
924 } else {
709 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, 925 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining,
710 ses, nls_cp); 926 ses, nls_cp);
927 }
711 928
712ssetup_exit: 929ssetup_exit:
713 if (spnego_key) { 930 if (spnego_key) {
@@ -721,5 +938,9 @@ ssetup_exit:
721 } else if (resp_buf_type == CIFS_LARGE_BUFFER) 938 } else if (resp_buf_type == CIFS_LARGE_BUFFER)
722 cifs_buf_release(iov[0].iov_base); 939 cifs_buf_release(iov[0].iov_base);
723 940
941 /* if ntlmssp, and negotiate succeeded, proceed to authenticate phase */
942 if ((phase == NtLmChallenge) && (rc == 0))
943 goto ssetup_ntlmssp_authenticate;
944
724 return rc; 945 return rc;
725} 946}
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
index 7f50e8577c1c..c5084d27db7c 100644
--- a/fs/cifs/smberr.h
+++ b/fs/cifs/smberr.h
@@ -110,6 +110,7 @@
110 110
111/* Below errors are used internally (do not come over the wire) for passthrough 111/* Below errors are used internally (do not come over the wire) for passthrough
112 from STATUS codes to POSIX only */ 112 from STATUS codes to POSIX only */
113#define ERRsymlink 0xFFFD
113#define ErrTooManyLinks 0xFFFE 114#define ErrTooManyLinks 0xFFFE
114 115
115/* Following error codes may be generated with the ERRSRV error class.*/ 116/* Following error codes may be generated with the ERRSRV error class.*/