aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-04-01 00:27:53 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-01 00:27:53 -0500
commit547a77ae62091449e23b64a75b9c69e373613608 (patch)
tree63e1f03203570a9a7e9266ac10befc1716b256bd
parent4b75679f60d0ce780609cbff249769b669f4fb69 (diff)
parent06bcfedd05448e63cae8924074bfacdf82bb17d4 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6: [CIFS] Fix typo in earlier cifs_unlink change and protect one [CIFS] Incorrect signature sent on SMB Read [CIFS] Fix unlink oops when indirectly called in rename error path [CIFS] Fix two remaining coverity scan tool warnings. [CIFS] Set correct lock type on new posix unlock call [CIFS] Upate cifs change log [CIFS] Fix slow oplock break response when mounts to different [CIFS] Workaround various server bugs found in testing at connectathon [CIFS] Allow fallback for setting file size to Procom SMB server when [CIFS] Make POSIX CIFS Extensions SetFSInfo match exactly what we want [CIFS] Move noisy debug message (triggerred by some older servers) from [CIFS] Use correct pid on new cifs posix byte range lock call [CIFS] Add posix (advisory) byte range locking support to cifs client [CIFS] CIFS readdir perf optimizations part 1 [CIFS] Free small buffers earlier so we exceed the cifs [CIFS] Fix large (ie over 64K for MaxCIFSBufSize) buffer case for wrapping [CIFS] Convert remaining places in fs/cifs from [CIFS] SessionSetup cleanup part 2 [CIFS] fix compile error (typo) and warning in cifssmb.c [CIFS] Cleanup NTLMSSP session setup handling
-rw-r--r--fs/cifs/CHANGES18
-rw-r--r--fs/cifs/Makefile2
-rw-r--r--fs/cifs/README7
-rw-r--r--fs/cifs/cifsencrypt.c42
-rw-r--r--fs/cifs/cifsfs.c5
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsglob.h11
-rw-r--r--fs/cifs/cifspdu.h13
-rw-r--r--fs/cifs/cifsproto.h15
-rw-r--r--fs/cifs/cifssmb.c135
-rw-r--r--fs/cifs/connect.c99
-rw-r--r--fs/cifs/dir.c7
-rw-r--r--fs/cifs/file.c94
-rw-r--r--fs/cifs/inode.c22
-rw-r--r--fs/cifs/link.c2
-rw-r--r--fs/cifs/misc.c46
-rw-r--r--fs/cifs/ntlmssp.c129
-rw-r--r--fs/cifs/ntlmssp.h2
-rw-r--r--fs/cifs/readdir.c7
-rw-r--r--fs/cifs/transport.c22
20 files changed, 524 insertions, 156 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index cb68efba35db..8a2de038882e 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,21 @@
1Version 1.42
2------------
3Fix slow oplock break when mounted to different servers at the same time and
4the tids match and we try to find matching fid on wrong server.
5
6Version 1.41
7------------
8Fix NTLMv2 security (can be enabled in /proc/fs/cifs) so customers can
9configure stronger authentication. Fix sfu symlinks so they can
10be followed (not just recognized). Fix wraparound of bcc on
11read responses when buffer size over 64K and also fix wrap of
12max smb buffer size when CIFSMaxBufSize over 64K. Fix oops in
13cifs_user_read and cifs_readpages (when EAGAIN on send of smb
14on socket is returned over and over). Add POSIX (advisory) byte range
15locking support (requires server with newest CIFS UNIX Extensions
16to the protocol implemented). Slow down negprot slightly in port 139
17RFC1001 case to give session_init time on buggy servers.
18
1Version 1.40 19Version 1.40
2------------ 20------------
3Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance 21Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index 7384947a0f93..58c77254a23b 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -3,4 +3,4 @@
3# 3#
4obj-$(CONFIG_CIFS) += cifs.o 4obj-$(CONFIG_CIFS) += cifs.o
5 5
6cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o 6cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o ntlmssp.o
diff --git a/fs/cifs/README b/fs/cifs/README
index b0070d1b149d..b2b4d0803761 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -422,6 +422,13 @@ A partial list of the supported mount options follows:
422 nomapchars Do not translate any of these seven characters (default). 422 nomapchars Do not translate any of these seven characters (default).
423 nocase Request case insensitive path name matching (case 423 nocase Request case insensitive path name matching (case
424 sensitive is the default if the server suports it). 424 sensitive is the default if the server suports it).
425 posixpaths If CIFS Unix extensions are supported, attempt to
426 negotiate posix path name support which allows certain
427 characters forbidden in typical CIFS filenames, without
428 requiring remapping. (default)
429 noposixpaths If CIFS Unix extensions are supported, do not request
430 posix path name support (this may cause servers to
431 reject creatingfile with certain reserved characters).
425 nobrl Do not send byte range lock requests to the server. 432 nobrl Do not send byte range lock requests to the server.
426 This is necessary for certain applications that break 433 This is necessary for certain applications that break
427 with cifs style mandatory byte range locks (and most 434 with cifs style mandatory byte range locks (and most
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index a2c24858d40f..e7d63737e651 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifsencrypt.c 2 * fs/cifs/cifsencrypt.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2005 4 * Copyright (C) International Business Machines Corp., 2005,2006
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
@@ -36,7 +36,8 @@
36extern void mdfour(unsigned char *out, unsigned char *in, int n); 36extern void mdfour(unsigned char *out, unsigned char *in, int n);
37extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); 37extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
38 38
39static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature) 39static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu,
40 const char * key, char * signature)
40{ 41{
41 struct MD5Context context; 42 struct MD5Context context;
42 43
@@ -56,9 +57,6 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
56 int rc = 0; 57 int rc = 0;
57 char smb_signature[20]; 58 char smb_signature[20];
58 59
59 /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
60 /* BB remember to add code to save expected sequence number in midQ entry BB */
61
62 if((cifs_pdu == NULL) || (server == NULL)) 60 if((cifs_pdu == NULL) || (server == NULL))
63 return -EINVAL; 61 return -EINVAL;
64 62
@@ -85,20 +83,33 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
85static int cifs_calc_signature2(const struct kvec * iov, int n_vec, 83static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
86 const char * key, char * signature) 84 const char * key, char * signature)
87{ 85{
88 struct MD5Context context; 86 struct MD5Context context;
89 87 int i;
90 if((iov == NULL) || (signature == NULL))
91 return -EINVAL;
92 88
93 MD5Init(&context); 89 if((iov == NULL) || (signature == NULL))
94 MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16); 90 return -EINVAL;
95 91
96/* MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); */ /* BB FIXME BB */ 92 MD5Init(&context);
93 MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
94 for(i=0;i<n_vec;i++) {
95 if(iov[i].iov_base == NULL) {
96 cERROR(1,("null iovec entry"));
97 return -EIO;
98 } else if(iov[i].iov_len == 0)
99 break; /* bail out if we are sent nothing to sign */
100 /* The first entry includes a length field (which does not get
101 signed that occupies the first 4 bytes before the header */
102 if(i==0) {
103 if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */
104 break; /* nothing to sign or corrupt header */
105 MD5Update(&context,iov[0].iov_base+4, iov[0].iov_len-4);
106 } else
107 MD5Update(&context,iov[i].iov_base, iov[i].iov_len);
108 }
97 109
98 MD5Final(signature,&context); 110 MD5Final(signature,&context);
99 111
100 return -EOPNOTSUPP; 112 return 0;
101/* return 0; */
102} 113}
103 114
104 115
@@ -259,4 +270,5 @@ void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_respon
259/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */ 270/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
260 271
261 hmac_md5_final(v2_session_response,&context); 272 hmac_md5_final(v2_session_response,&context);
273 cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); /* BB removeme BB */
262} 274}
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 4bbc544857bc..d4b713e5affb 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -93,13 +93,10 @@ cifs_read_super(struct super_block *sb, void *data,
93 int rc = 0; 93 int rc = 0;
94 94
95 sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */ 95 sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
96 sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL); 96 sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
97 cifs_sb = CIFS_SB(sb); 97 cifs_sb = CIFS_SB(sb);
98 if(cifs_sb == NULL) 98 if(cifs_sb == NULL)
99 return -ENOMEM; 99 return -ENOMEM;
100 else
101 memset(cifs_sb,0,sizeof(struct cifs_sb_info));
102
103 100
104 rc = cifs_mount(sb, cifs_sb, data, devname); 101 rc = cifs_mount(sb, cifs_sb, data, devname);
105 102
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 74f405ae4da3..4e829dc672a6 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -99,5 +99,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
99extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 99extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
100extern int cifs_ioctl (struct inode * inode, struct file * filep, 100extern int cifs_ioctl (struct inode * inode, struct file * filep,
101 unsigned int command, unsigned long arg); 101 unsigned int command, unsigned long arg);
102#define CIFS_VERSION "1.40" 102#define CIFS_VERSION "1.42"
103#endif /* _CIFSFS_H */ 103#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 7bed27601ce5..006eb33bff5f 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifsglob.h 2 * fs/cifs/cifsglob.h
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2005 4 * Copyright (C) International Business Machines Corp., 2002,2006
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
@@ -430,6 +430,15 @@ struct dir_notify_req {
430#define CIFS_LARGE_BUFFER 2 430#define CIFS_LARGE_BUFFER 2
431#define CIFS_IOVEC 4 /* array of response buffers */ 431#define CIFS_IOVEC 4 /* array of response buffers */
432 432
433/* Type of session setup needed */
434#define CIFS_PLAINTEXT 0
435#define CIFS_LANMAN 1
436#define CIFS_NTLM 2
437#define CIFS_NTLMSSP_NEG 3
438#define CIFS_NTLMSSP_AUTH 4
439#define CIFS_SPNEGO_INIT 5
440#define CIFS_SPNEGO_TARG 6
441
433/* 442/*
434 ***************************************************************** 443 *****************************************************************
435 * All constants go here 444 * All constants go here
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index cc2471094ca5..b2233ac05bd2 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -859,7 +859,10 @@ typedef struct smb_com_lock_req {
859 LOCKING_ANDX_RANGE Locks[1]; 859 LOCKING_ANDX_RANGE Locks[1];
860} __attribute__((packed)) LOCK_REQ; 860} __attribute__((packed)) LOCK_REQ;
861 861
862 862/* lock type */
863#define CIFS_RDLCK 0
864#define CIFS_WRLCK 1
865#define CIFS_UNLCK 2
863typedef struct cifs_posix_lock { 866typedef struct cifs_posix_lock {
864 __le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */ 867 __le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */
865 __le16 lock_flags; /* 1 = Wait (only valid for setlock) */ 868 __le16 lock_flags; /* 1 = Wait (only valid for setlock) */
@@ -1786,7 +1789,13 @@ typedef struct {
1786#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */ 1789#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */
1787#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ 1790#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
1788#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ 1791#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
1789#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Use POSIX pathnames on the wire. */ 1792#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */
1793#ifdef CONFIG_CIFS_POSIX
1794#define CIFS_UNIX_CAP_MASK 0x0000001b
1795#else
1796#define CIFS_UNIX_CAP_MASK 0x00000013
1797#endif /* CONFIG_CIFS_POSIX */
1798
1790 1799
1791#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */ 1800#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */
1792 1801
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 7b25463d3c14..2879ba343ca7 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifsproto.h 2 * fs/cifs/cifsproto.h
3 * 3 *
4 * Copyright (c) International Business Machines Corp., 2002,2005 4 * Copyright (c) International Business Machines Corp., 2002,2006
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
@@ -64,6 +64,14 @@ extern int map_smb_to_linux_error(struct smb_hdr *smb);
64extern void header_assemble(struct smb_hdr *, char /* command */ , 64extern void header_assemble(struct smb_hdr *, char /* command */ ,
65 const struct cifsTconInfo *, int /* length of 65 const struct cifsTconInfo *, int /* length of
66 fixed section (word count) in two byte units */); 66 fixed section (word count) in two byte units */);
67#ifdef CONFIG_CIFS_EXPERIMENTAL
68extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
69 struct cifsSesInfo *ses,
70 void ** request_buf);
71extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
72 const int stage, int * pNTLMv2_flg,
73 const struct nls_table *nls_cp);
74#endif
67extern __u16 GetNextMid(struct TCP_Server_Info *server); 75extern __u16 GetNextMid(struct TCP_Server_Info *server);
68extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, 76extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16,
69 struct cifsTconInfo *); 77 struct cifsTconInfo *);
@@ -257,7 +265,10 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
257 const __u64 offset, const __u32 numUnlock, 265 const __u64 offset, const __u32 numUnlock,
258 const __u32 numLock, const __u8 lockType, 266 const __u32 numLock, const __u8 lockType,
259 const int waitFlag); 267 const int waitFlag);
260 268extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
269 const __u16 smb_file_id, const int get_flag,
270 const __u64 len, const __u64 offset,
271 const __u16 lock_type, const int waitFlag);
261extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon); 272extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
262extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses); 273extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
263 274
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index a243fe2792d5..d705500aa283 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,2005 4 * Copyright (C) International Business Machines Corp., 2002,2006
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
@@ -186,7 +186,35 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
186 cifs_stats_inc(&tcon->num_smbs_sent); 186 cifs_stats_inc(&tcon->num_smbs_sent);
187 187
188 return rc; 188 return rc;
189} 189}
190
191#ifdef CONFIG_CIFS_EXPERIMENTAL
192int
193small_smb_init_no_tc(const int smb_command, const int wct,
194 struct cifsSesInfo *ses, void **request_buf)
195{
196 int rc;
197 struct smb_hdr * buffer;
198
199 rc = small_smb_init(smb_command, wct, NULL, request_buf);
200 if(rc)
201 return rc;
202
203 buffer = (struct smb_hdr *)*request_buf;
204 buffer->Mid = GetNextMid(ses->server);
205 if (ses->capabilities & CAP_UNICODE)
206 buffer->Flags2 |= SMBFLG2_UNICODE;
207 if (ses->capabilities & CAP_STATUS32)
208 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
209
210 /* uid, tid can stay at zero as set in header assemble */
211
212 /* BB add support for turning on the signing when
213 this function is used after 1st of session setup requests */
214
215 return rc;
216}
217#endif /* CONFIG_CIFS_EXPERIMENTAL */
190 218
191/* If the return code is zero, this function must fill in request_buf pointer */ 219/* If the return code is zero, this function must fill in request_buf pointer */
192static int 220static int
@@ -1042,7 +1070,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1042 } 1070 }
1043 } 1071 }
1044 1072
1045 cifs_small_buf_release(pSMB); 1073/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1046 if(*buf) { 1074 if(*buf) {
1047 if(resp_buf_type == CIFS_SMALL_BUFFER) 1075 if(resp_buf_type == CIFS_SMALL_BUFFER)
1048 cifs_small_buf_release(iov[0].iov_base); 1076 cifs_small_buf_release(iov[0].iov_base);
@@ -1246,7 +1274,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1246 *nbytes += le16_to_cpu(pSMBr->Count); 1274 *nbytes += le16_to_cpu(pSMBr->Count);
1247 } 1275 }
1248 1276
1249 cifs_small_buf_release(pSMB); 1277/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1250 if(resp_buf_type == CIFS_SMALL_BUFFER) 1278 if(resp_buf_type == CIFS_SMALL_BUFFER)
1251 cifs_small_buf_release(iov[0].iov_base); 1279 cifs_small_buf_release(iov[0].iov_base);
1252 else if(resp_buf_type == CIFS_LARGE_BUFFER) 1280 else if(resp_buf_type == CIFS_LARGE_BUFFER)
@@ -1325,6 +1353,85 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1325} 1353}
1326 1354
1327int 1355int
1356CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1357 const __u16 smb_file_id, const int get_flag, const __u64 len,
1358 const __u64 lkoffset, const __u16 lock_type, const int waitFlag)
1359{
1360 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1361 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1362 char *data_offset;
1363 struct cifs_posix_lock *parm_data;
1364 int rc = 0;
1365 int bytes_returned = 0;
1366 __u16 params, param_offset, offset, byte_count, count;
1367
1368 cFYI(1, ("Posix Lock"));
1369 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1370
1371 if (rc)
1372 return rc;
1373
1374 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1375
1376 params = 6;
1377 pSMB->MaxSetupCount = 0;
1378 pSMB->Reserved = 0;
1379 pSMB->Flags = 0;
1380 pSMB->Timeout = 0;
1381 pSMB->Reserved2 = 0;
1382 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1383 offset = param_offset + params;
1384
1385 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1386
1387 count = sizeof(struct cifs_posix_lock);
1388 pSMB->MaxParameterCount = cpu_to_le16(2);
1389 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1390 pSMB->SetupCount = 1;
1391 pSMB->Reserved3 = 0;
1392 if(get_flag)
1393 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1394 else
1395 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1396 byte_count = 3 /* pad */ + params + count;
1397 pSMB->DataCount = cpu_to_le16(count);
1398 pSMB->ParameterCount = cpu_to_le16(params);
1399 pSMB->TotalDataCount = pSMB->DataCount;
1400 pSMB->TotalParameterCount = pSMB->ParameterCount;
1401 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1402 parm_data = (struct cifs_posix_lock *)
1403 (((char *) &pSMB->hdr.Protocol) + offset);
1404
1405 parm_data->lock_type = cpu_to_le16(lock_type);
1406 if(waitFlag)
1407 parm_data->lock_flags = 1;
1408 parm_data->pid = cpu_to_le32(current->tgid);
1409 parm_data->start = lkoffset;
1410 parm_data->length = len; /* normalize negative numbers */
1411
1412 pSMB->DataOffset = cpu_to_le16(offset);
1413 pSMB->Fid = smb_file_id;
1414 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1415 pSMB->Reserved4 = 0;
1416 pSMB->hdr.smb_buf_length += byte_count;
1417 pSMB->ByteCount = cpu_to_le16(byte_count);
1418 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1419 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1420 if (rc) {
1421 cFYI(1, ("Send error in Posix Lock = %d", rc));
1422 }
1423
1424 if (pSMB)
1425 cifs_small_buf_release(pSMB);
1426
1427 /* Note: On -EAGAIN error only caller can retry on handle based calls
1428 since file handle passed in no longer valid */
1429
1430 return rc;
1431}
1432
1433
1434int
1328CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) 1435CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1329{ 1436{
1330 int rc = 0; 1437 int rc = 0;
@@ -2578,7 +2685,7 @@ qsec_out:
2578 cifs_small_buf_release(iov[0].iov_base); 2685 cifs_small_buf_release(iov[0].iov_base);
2579 else if(buf_type == CIFS_LARGE_BUFFER) 2686 else if(buf_type == CIFS_LARGE_BUFFER)
2580 cifs_buf_release(iov[0].iov_base); 2687 cifs_buf_release(iov[0].iov_base);
2581 cifs_small_buf_release(pSMB); 2688/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2582 return rc; 2689 return rc;
2583} 2690}
2584 2691
@@ -2954,7 +3061,8 @@ findFirstRetry:
2954 pSMB->TotalParameterCount = cpu_to_le16(params); 3061 pSMB->TotalParameterCount = cpu_to_le16(params);
2955 pSMB->ParameterCount = pSMB->TotalParameterCount; 3062 pSMB->ParameterCount = pSMB->TotalParameterCount;
2956 pSMB->ParameterOffset = cpu_to_le16( 3063 pSMB->ParameterOffset = cpu_to_le16(
2957 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4); 3064 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3065 - 4);
2958 pSMB->DataCount = 0; 3066 pSMB->DataCount = 0;
2959 pSMB->DataOffset = 0; 3067 pSMB->DataOffset = 0;
2960 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */ 3068 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
@@ -2977,12 +3085,12 @@ findFirstRetry:
2977 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 3085 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2978 cifs_stats_inc(&tcon->num_ffirst); 3086 cifs_stats_inc(&tcon->num_ffirst);
2979 3087
2980 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ 3088 if (rc) {/* BB add logic to retry regular search if Unix search
3089 rejected unexpectedly by server */
2981 /* BB Add code to handle unsupported level rc */ 3090 /* BB Add code to handle unsupported level rc */
2982 cFYI(1, ("Error in FindFirst = %d", rc)); 3091 cFYI(1, ("Error in FindFirst = %d", rc));
2983 3092
2984 if (pSMB) 3093 cifs_buf_release(pSMB);
2985 cifs_buf_release(pSMB);
2986 3094
2987 /* BB eventually could optimize out free and realloc of buf */ 3095 /* BB eventually could optimize out free and realloc of buf */
2988 /* for this case */ 3096 /* for this case */
@@ -2998,6 +3106,7 @@ findFirstRetry:
2998 psrch_inf->unicode = FALSE; 3106 psrch_inf->unicode = FALSE;
2999 3107
3000 psrch_inf->ntwrk_buf_start = (char *)pSMBr; 3108 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3109 psrch_inf->smallBuf = 0;
3001 psrch_inf->srch_entries_start = 3110 psrch_inf->srch_entries_start =
3002 (char *) &pSMBr->hdr.Protocol + 3111 (char *) &pSMBr->hdr.Protocol +
3003 le16_to_cpu(pSMBr->t2.DataOffset); 3112 le16_to_cpu(pSMBr->t2.DataOffset);
@@ -3118,9 +3227,14 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3118 parms = (T2_FNEXT_RSP_PARMS *)response_data; 3227 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3119 response_data = (char *)&pSMBr->hdr.Protocol + 3228 response_data = (char *)&pSMBr->hdr.Protocol +
3120 le16_to_cpu(pSMBr->t2.DataOffset); 3229 le16_to_cpu(pSMBr->t2.DataOffset);
3121 cifs_buf_release(psrch_inf->ntwrk_buf_start); 3230 if(psrch_inf->smallBuf)
3231 cifs_small_buf_release(
3232 psrch_inf->ntwrk_buf_start);
3233 else
3234 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3122 psrch_inf->srch_entries_start = response_data; 3235 psrch_inf->srch_entries_start = response_data;
3123 psrch_inf->ntwrk_buf_start = (char *)pSMB; 3236 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3237 psrch_inf->smallBuf = 0;
3124 if(parms->EndofSearch) 3238 if(parms->EndofSearch)
3125 psrch_inf->endOfSearch = TRUE; 3239 psrch_inf->endOfSearch = TRUE;
3126 else 3240 else
@@ -3834,6 +3948,7 @@ CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3834 3948
3835 cFYI(1, ("In SETFSUnixInfo")); 3949 cFYI(1, ("In SETFSUnixInfo"));
3836SETFSUnixRetry: 3950SETFSUnixRetry:
3951 /* BB switch to small buf init to save memory */
3837 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, 3952 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3838 (void **) &pSMBr); 3953 (void **) &pSMBr);
3839 if (rc) 3954 if (rc)
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2a0c1f4ca0ae..0b86d5ca9014 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,2005 4 * Copyright (C) International Business Machines Corp., 2002,2006
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
@@ -564,7 +564,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
564 564
565 565
566 dump_smb(smb_buffer, length); 566 dump_smb(smb_buffer, length);
567 if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) { 567 if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {
568 cifs_dump_mem("Bad SMB: ", smb_buffer, 48); 568 cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
569 continue; 569 continue;
570 } 570 }
@@ -1476,6 +1476,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1476 rc = smb_send(*csocket, smb_buf, 0x44, 1476 rc = smb_send(*csocket, smb_buf, 0x44,
1477 (struct sockaddr *)psin_server); 1477 (struct sockaddr *)psin_server);
1478 kfree(ses_init_buf); 1478 kfree(ses_init_buf);
1479 msleep(1); /* RFC1001 layer in at least one server
1480 requires very short break before negprot
1481 presumably because not expecting negprot
1482 to follow so fast. This is a simple
1483 solution that works without
1484 complicating the code and causes no
1485 significant slowing down on mount
1486 for everyone else */
1479 } 1487 }
1480 /* else the negprot may still work without this 1488 /* else the negprot may still work without this
1481 even though malloc failed */ 1489 even though malloc failed */
@@ -1920,27 +1928,34 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1920 cifs_sb->tcon = tcon; 1928 cifs_sb->tcon = tcon;
1921 tcon->ses = pSesInfo; 1929 tcon->ses = pSesInfo;
1922 1930
1923 /* do not care if following two calls succeed - informational only */ 1931 /* do not care if following two calls succeed - informational */
1924 CIFSSMBQFSDeviceInfo(xid, tcon); 1932 CIFSSMBQFSDeviceInfo(xid, tcon);
1925 CIFSSMBQFSAttributeInfo(xid, tcon); 1933 CIFSSMBQFSAttributeInfo(xid, tcon);
1934
1926 if (tcon->ses->capabilities & CAP_UNIX) { 1935 if (tcon->ses->capabilities & CAP_UNIX) {
1927 if(!CIFSSMBQFSUnixInfo(xid, tcon)) { 1936 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1928 if(!volume_info.no_psx_acl) { 1937 __u64 cap =
1929 if(CIFS_UNIX_POSIX_ACL_CAP & 1938 le64_to_cpu(tcon->fsUnixInfo.Capability);
1930 le64_to_cpu(tcon->fsUnixInfo.Capability)) 1939 cap &= CIFS_UNIX_CAP_MASK;
1931 cFYI(1,("server negotiated posix acl support")); 1940 if(volume_info.no_psx_acl)
1932 sb->s_flags |= MS_POSIXACL; 1941 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1942 else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
1943 cFYI(1,("negotiated posix acl support"));
1944 sb->s_flags |= MS_POSIXACL;
1933 } 1945 }
1934 1946
1935 /* Try and negotiate POSIX pathnames if we can. */ 1947 if(volume_info.posix_paths == 0)
1936 if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP & 1948 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1937 le64_to_cpu(tcon->fsUnixInfo.Capability))) { 1949 else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
1938 if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) { 1950 cFYI(1,("negotiate posix pathnames"));
1939 cFYI(1,("negotiated posix pathnames support")); 1951 cifs_sb->mnt_cifs_flags |=
1940 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; 1952 CIFS_MOUNT_POSIX_PATHS;
1941 } else { 1953 }
1942 cFYI(1,("posix pathnames support requested but not supported")); 1954
1943 } 1955 cFYI(1,("Negotiate caps 0x%x",(int)cap));
1956
1957 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
1958 cFYI(1,("setting capabilities failed"));
1944 } 1959 }
1945 } 1960 }
1946 } 1961 }
@@ -2278,6 +2293,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2278 smb_buffer->Mid = GetNextMid(ses->server); 2293 smb_buffer->Mid = GetNextMid(ses->server);
2279 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 2294 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2280 pSMB->req.AndXCommand = 0xFF; 2295 pSMB->req.AndXCommand = 0xFF;
2296 if(ses->server->maxBuf > 64*1024)
2297 ses->server->maxBuf = (64*1023);
2281 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); 2298 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2282 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); 2299 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2283 2300
@@ -2525,7 +2542,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2525 __u32 negotiate_flags, capabilities; 2542 __u32 negotiate_flags, capabilities;
2526 __u16 count; 2543 __u16 count;
2527 2544
2528 cFYI(1, ("In NTLMSSP sesssetup (negotiate) ")); 2545 cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
2529 if(ses == NULL) 2546 if(ses == NULL)
2530 return -EINVAL; 2547 return -EINVAL;
2531 domain = ses->domainName; 2548 domain = ses->domainName;
@@ -2575,7 +2592,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2575 SecurityBlob->MessageType = NtLmNegotiate; 2592 SecurityBlob->MessageType = NtLmNegotiate;
2576 negotiate_flags = 2593 negotiate_flags =
2577 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM | 2594 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2578 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 | 2595 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
2596 NTLMSSP_NEGOTIATE_56 |
2579 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; 2597 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2580 if(sign_CIFS_PDUs) 2598 if(sign_CIFS_PDUs)
2581 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; 2599 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
@@ -2588,26 +2606,11 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2588 SecurityBlob->WorkstationName.Length = 0; 2606 SecurityBlob->WorkstationName.Length = 0;
2589 SecurityBlob->WorkstationName.MaximumLength = 0; 2607 SecurityBlob->WorkstationName.MaximumLength = 0;
2590 2608
2591 if (domain == NULL) { 2609 /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
2592 SecurityBlob->DomainName.Buffer = 0; 2610 along with username on auth request (ie the response to challenge) */
2593 SecurityBlob->DomainName.Length = 0; 2611 SecurityBlob->DomainName.Buffer = 0;
2594 SecurityBlob->DomainName.MaximumLength = 0; 2612 SecurityBlob->DomainName.Length = 0;
2595 } else { 2613 SecurityBlob->DomainName.MaximumLength = 0;
2596 __u16 len;
2597 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2598 strncpy(bcc_ptr, domain, 63);
2599 len = strnlen(domain, 64);
2600 SecurityBlob->DomainName.MaximumLength =
2601 cpu_to_le16(len);
2602 SecurityBlob->DomainName.Buffer =
2603 cpu_to_le32((long) &SecurityBlob->
2604 DomainString -
2605 (long) &SecurityBlob->Signature);
2606 bcc_ptr += len;
2607 SecurityBlobLength += len;
2608 SecurityBlob->DomainName.Length =
2609 cpu_to_le16(len);
2610 }
2611 if (ses->capabilities & CAP_UNICODE) { 2614 if (ses->capabilities & CAP_UNICODE) {
2612 if ((long) bcc_ptr % 2) { 2615 if ((long) bcc_ptr % 2) {
2613 *bcc_ptr = 0; 2616 *bcc_ptr = 0;
@@ -2677,7 +2680,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2677 SecurityBlob2->MessageType)); 2680 SecurityBlob2->MessageType));
2678 } else if (ses) { 2681 } else if (ses) {
2679 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */ 2682 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2680 cFYI(1, ("UID = %d ", ses->Suid)); 2683 cFYI(1, ("UID = %d", ses->Suid));
2681 if ((pSMBr->resp.hdr.WordCount == 3) 2684 if ((pSMBr->resp.hdr.WordCount == 3)
2682 || ((pSMBr->resp.hdr.WordCount == 4) 2685 || ((pSMBr->resp.hdr.WordCount == 4)
2683 && (blob_len < 2686 && (blob_len <
@@ -2685,17 +2688,17 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2685 2688
2686 if (pSMBr->resp.hdr.WordCount == 4) { 2689 if (pSMBr->resp.hdr.WordCount == 4) {
2687 bcc_ptr += blob_len; 2690 bcc_ptr += blob_len;
2688 cFYI(1, 2691 cFYI(1, ("Security Blob Length %d",
2689 ("Security Blob Length %d ",
2690 blob_len)); 2692 blob_len));
2691 } 2693 }
2692 2694
2693 cFYI(1, ("NTLMSSP Challenge rcvd ")); 2695 cFYI(1, ("NTLMSSP Challenge rcvd"));
2694 2696
2695 memcpy(ses->server->cryptKey, 2697 memcpy(ses->server->cryptKey,
2696 SecurityBlob2->Challenge, 2698 SecurityBlob2->Challenge,
2697 CIFS_CRYPTO_KEY_SIZE); 2699 CIFS_CRYPTO_KEY_SIZE);
2698 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2)) 2700 if(SecurityBlob2->NegotiateFlags &
2701 cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2699 *pNTLMv2_flag = TRUE; 2702 *pNTLMv2_flag = TRUE;
2700 2703
2701 if((SecurityBlob2->NegotiateFlags & 2704 if((SecurityBlob2->NegotiateFlags &
@@ -2818,7 +2821,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2818 bcc_ptr++; 2821 bcc_ptr++;
2819 } else 2822 } else
2820 cFYI(1, 2823 cFYI(1,
2821 ("Variable field of length %d extends beyond end of smb ", 2824 ("Variable field of length %d extends beyond end of smb",
2822 len)); 2825 len));
2823 } 2826 }
2824 } else { 2827 } else {
@@ -2830,7 +2833,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2830 } 2833 }
2831 } else { 2834 } else {
2832 cERROR(1, 2835 cERROR(1,
2833 (" Invalid Word count %d: ", 2836 (" Invalid Word count %d:",
2834 smb_buffer_response->WordCount)); 2837 smb_buffer_response->WordCount));
2835 rc = -EIO; 2838 rc = -EIO;
2836 } 2839 }
@@ -3447,7 +3450,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3447 if (extended_security 3450 if (extended_security
3448 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 3451 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3449 && (pSesInfo->server->secType == NTLMSSP)) { 3452 && (pSesInfo->server->secType == NTLMSSP)) {
3450 cFYI(1, ("New style sesssetup ")); 3453 cFYI(1, ("New style sesssetup"));
3451 rc = CIFSSpnegoSessSetup(xid, pSesInfo, 3454 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3452 NULL /* security blob */, 3455 NULL /* security blob */,
3453 0 /* blob length */, 3456 0 /* blob length */,
@@ -3455,7 +3458,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3455 } else if (extended_security 3458 } else if (extended_security
3456 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 3459 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3457 && (pSesInfo->server->secType == RawNTLMSSP)) { 3460 && (pSesInfo->server->secType == RawNTLMSSP)) {
3458 cFYI(1, ("NTLMSSP sesssetup ")); 3461 cFYI(1, ("NTLMSSP sesssetup"));
3459 rc = CIFSNTLMSSPNegotiateSessSetup(xid, 3462 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3460 pSesInfo, 3463 pSesInfo,
3461 &ntlmv2_flag, 3464 &ntlmv2_flag,
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 632561dd9c50..1d0ca3eaaca5 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -48,13 +48,14 @@ build_path_from_dentry(struct dentry *direntry)
48 struct dentry *temp; 48 struct dentry *temp;
49 int namelen = 0; 49 int namelen = 0;
50 char *full_path; 50 char *full_path;
51 char dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); 51 char dirsep;
52 52
53 if(direntry == NULL) 53 if(direntry == NULL)
54 return NULL; /* not much we can do if dentry is freed and 54 return NULL; /* not much we can do if dentry is freed and
55 we need to reopen the file after it was closed implicitly 55 we need to reopen the file after it was closed implicitly
56 when the server crashed */ 56 when the server crashed */
57 57
58 dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
58cifs_bp_rename_retry: 59cifs_bp_rename_retry:
59 for (temp = direntry; !IS_ROOT(temp);) { 60 for (temp = direntry; !IS_ROOT(temp);) {
60 namelen += (1 + temp->d_name.len); 61 namelen += (1 + temp->d_name.len);
@@ -255,12 +256,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
255 CIFSSMBClose(xid, pTcon, fileHandle); 256 CIFSSMBClose(xid, pTcon, fileHandle);
256 } else if(newinode) { 257 } else if(newinode) {
257 pCifsFile = 258 pCifsFile =
258 kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); 259 kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
259 260
260 if(pCifsFile == NULL) 261 if(pCifsFile == NULL)
261 goto cifs_create_out; 262 goto cifs_create_out;
262 memset((char *)pCifsFile, 0,
263 sizeof (struct cifsFileInfo));
264 pCifsFile->netfid = fileHandle; 263 pCifsFile->netfid = fileHandle;
265 pCifsFile->pid = current->tgid; 264 pCifsFile->pid = current->tgid;
266 pCifsFile->pInode = newinode; 265 pCifsFile->pInode = newinode;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index fb49aef1f2ec..5c497c529772 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -555,7 +555,10 @@ int cifs_closedir(struct inode *inode, struct file *file)
555 if (ptmp) { 555 if (ptmp) {
556 cFYI(1, ("closedir free smb buf in srch struct")); 556 cFYI(1, ("closedir free smb buf in srch struct"));
557 pCFileStruct->srch_inf.ntwrk_buf_start = NULL; 557 pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
558 cifs_buf_release(ptmp); 558 if(pCFileStruct->srch_inf.smallBuf)
559 cifs_small_buf_release(ptmp);
560 else
561 cifs_buf_release(ptmp);
559 } 562 }
560 ptmp = pCFileStruct->search_resume_name; 563 ptmp = pCFileStruct->search_resume_name;
561 if (ptmp) { 564 if (ptmp) {
@@ -574,13 +577,14 @@ int cifs_closedir(struct inode *inode, struct file *file)
574int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) 577int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
575{ 578{
576 int rc, xid; 579 int rc, xid;
577 __u32 lockType = LOCKING_ANDX_LARGE_FILES;
578 __u32 numLock = 0; 580 __u32 numLock = 0;
579 __u32 numUnlock = 0; 581 __u32 numUnlock = 0;
580 __u64 length; 582 __u64 length;
581 int wait_flag = FALSE; 583 int wait_flag = FALSE;
582 struct cifs_sb_info *cifs_sb; 584 struct cifs_sb_info *cifs_sb;
583 struct cifsTconInfo *pTcon; 585 struct cifsTconInfo *pTcon;
586 __u16 netfid;
587 __u8 lockType = LOCKING_ANDX_LARGE_FILES;
584 588
585 length = 1 + pfLock->fl_end - pfLock->fl_start; 589 length = 1 + pfLock->fl_end - pfLock->fl_start;
586 rc = -EACCES; 590 rc = -EACCES;
@@ -592,11 +596,11 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
592 pfLock->fl_end)); 596 pfLock->fl_end));
593 597
594 if (pfLock->fl_flags & FL_POSIX) 598 if (pfLock->fl_flags & FL_POSIX)
595 cFYI(1, ("Posix ")); 599 cFYI(1, ("Posix"));
596 if (pfLock->fl_flags & FL_FLOCK) 600 if (pfLock->fl_flags & FL_FLOCK)
597 cFYI(1, ("Flock ")); 601 cFYI(1, ("Flock"));
598 if (pfLock->fl_flags & FL_SLEEP) { 602 if (pfLock->fl_flags & FL_SLEEP) {
599 cFYI(1, ("Blocking lock ")); 603 cFYI(1, ("Blocking lock"));
600 wait_flag = TRUE; 604 wait_flag = TRUE;
601 } 605 }
602 if (pfLock->fl_flags & FL_ACCESS) 606 if (pfLock->fl_flags & FL_ACCESS)
@@ -612,21 +616,23 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
612 cFYI(1, ("F_WRLCK ")); 616 cFYI(1, ("F_WRLCK "));
613 numLock = 1; 617 numLock = 1;
614 } else if (pfLock->fl_type == F_UNLCK) { 618 } else if (pfLock->fl_type == F_UNLCK) {
615 cFYI(1, ("F_UNLCK ")); 619 cFYI(1, ("F_UNLCK"));
616 numUnlock = 1; 620 numUnlock = 1;
621 /* Check if unlock includes more than
622 one lock range */
617 } else if (pfLock->fl_type == F_RDLCK) { 623 } else if (pfLock->fl_type == F_RDLCK) {
618 cFYI(1, ("F_RDLCK ")); 624 cFYI(1, ("F_RDLCK"));
619 lockType |= LOCKING_ANDX_SHARED_LOCK; 625 lockType |= LOCKING_ANDX_SHARED_LOCK;
620 numLock = 1; 626 numLock = 1;
621 } else if (pfLock->fl_type == F_EXLCK) { 627 } else if (pfLock->fl_type == F_EXLCK) {
622 cFYI(1, ("F_EXLCK ")); 628 cFYI(1, ("F_EXLCK"));
623 numLock = 1; 629 numLock = 1;
624 } else if (pfLock->fl_type == F_SHLCK) { 630 } else if (pfLock->fl_type == F_SHLCK) {
625 cFYI(1, ("F_SHLCK ")); 631 cFYI(1, ("F_SHLCK"));
626 lockType |= LOCKING_ANDX_SHARED_LOCK; 632 lockType |= LOCKING_ANDX_SHARED_LOCK;
627 numLock = 1; 633 numLock = 1;
628 } else 634 } else
629 cFYI(1, ("Unknown type of lock ")); 635 cFYI(1, ("Unknown type of lock"));
630 636
631 cifs_sb = CIFS_SB(file->f_dentry->d_sb); 637 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
632 pTcon = cifs_sb->tcon; 638 pTcon = cifs_sb->tcon;
@@ -635,27 +641,41 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
635 FreeXid(xid); 641 FreeXid(xid);
636 return -EBADF; 642 return -EBADF;
637 } 643 }
644 netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
645
638 646
647 /* BB add code here to normalize offset and length to
648 account for negative length which we can not accept over the
649 wire */
639 if (IS_GETLK(cmd)) { 650 if (IS_GETLK(cmd)) {
640 rc = CIFSSMBLock(xid, pTcon, 651 if(experimEnabled &&
641 ((struct cifsFileInfo *)file-> 652 (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
642 private_data)->netfid, 653 (CIFS_UNIX_FCNTL_CAP &
643 length, 654 le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
644 pfLock->fl_start, 0, 1, lockType, 655 int posix_lock_type;
645 0 /* wait flag */ ); 656 if(lockType & LOCKING_ANDX_SHARED_LOCK)
657 posix_lock_type = CIFS_RDLCK;
658 else
659 posix_lock_type = CIFS_WRLCK;
660 rc = CIFSSMBPosixLock(xid, pTcon, netfid, 1 /* get */,
661 length, pfLock->fl_start,
662 posix_lock_type, wait_flag);
663 FreeXid(xid);
664 return rc;
665 }
666
667 /* BB we could chain these into one lock request BB */
668 rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
669 0, 1, lockType, 0 /* wait flag */ );
646 if (rc == 0) { 670 if (rc == 0) {
647 rc = CIFSSMBLock(xid, pTcon, 671 rc = CIFSSMBLock(xid, pTcon, netfid, length,
648 ((struct cifsFileInfo *) file->
649 private_data)->netfid,
650 length,
651 pfLock->fl_start, 1 /* numUnlock */ , 672 pfLock->fl_start, 1 /* numUnlock */ ,
652 0 /* numLock */ , lockType, 673 0 /* numLock */ , lockType,
653 0 /* wait flag */ ); 674 0 /* wait flag */ );
654 pfLock->fl_type = F_UNLCK; 675 pfLock->fl_type = F_UNLCK;
655 if (rc != 0) 676 if (rc != 0)
656 cERROR(1, ("Error unlocking previously locked " 677 cERROR(1, ("Error unlocking previously locked "
657 "range %d during test of lock ", 678 "range %d during test of lock", rc));
658 rc));
659 rc = 0; 679 rc = 0;
660 680
661 } else { 681 } else {
@@ -667,12 +687,30 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
667 FreeXid(xid); 687 FreeXid(xid);
668 return rc; 688 return rc;
669 } 689 }
670 690 if (experimEnabled &&
671 rc = CIFSSMBLock(xid, pTcon, 691 (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
672 ((struct cifsFileInfo *) file->private_data)-> 692 (CIFS_UNIX_FCNTL_CAP &
673 netfid, length, 693 le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
674 pfLock->fl_start, numUnlock, numLock, lockType, 694 int posix_lock_type;
675 wait_flag); 695 if(lockType & LOCKING_ANDX_SHARED_LOCK)
696 posix_lock_type = CIFS_RDLCK;
697 else
698 posix_lock_type = CIFS_WRLCK;
699
700 if(numUnlock == 1)
701 posix_lock_type = CIFS_UNLCK;
702 else if(numLock == 0) {
703 /* if no lock or unlock then nothing
704 to do since we do not know what it is */
705 FreeXid(xid);
706 return -EOPNOTSUPP;
707 }
708 rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
709 length, pfLock->fl_start,
710 posix_lock_type, wait_flag);
711 } else
712 rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
713 numUnlock, numLock, lockType, wait_flag);
676 if (pfLock->fl_flags & FL_POSIX) 714 if (pfLock->fl_flags & FL_POSIX)
677 posix_lock_file_wait(file, pfLock); 715 posix_lock_file_wait(file, pfLock);
678 FreeXid(xid); 716 FreeXid(xid);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 598eec9778f6..957ddd1571c6 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -565,11 +565,14 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
565 struct cifsInodeInfo *cifsInode; 565 struct cifsInodeInfo *cifsInode;
566 FILE_BASIC_INFO *pinfo_buf; 566 FILE_BASIC_INFO *pinfo_buf;
567 567
568 cFYI(1, ("cifs_unlink, inode = 0x%p with ", inode)); 568 cFYI(1, ("cifs_unlink, inode = 0x%p", inode));
569 569
570 xid = GetXid(); 570 xid = GetXid();
571 571
572 cifs_sb = CIFS_SB(inode->i_sb); 572 if(inode)
573 cifs_sb = CIFS_SB(inode->i_sb);
574 else
575 cifs_sb = CIFS_SB(direntry->d_sb);
573 pTcon = cifs_sb->tcon; 576 pTcon = cifs_sb->tcon;
574 577
575 /* Unlink can be called from rename so we can not grab the sem here 578 /* Unlink can be called from rename so we can not grab the sem here
@@ -609,9 +612,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
609 } 612 }
610 } else if (rc == -EACCES) { 613 } else if (rc == -EACCES) {
611 /* try only if r/o attribute set in local lookup data? */ 614 /* try only if r/o attribute set in local lookup data? */
612 pinfo_buf = kmalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL); 615 pinfo_buf = kzalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);
613 if (pinfo_buf) { 616 if (pinfo_buf) {
614 memset(pinfo_buf, 0, sizeof(FILE_BASIC_INFO));
615 /* ATTRS set to normal clears r/o bit */ 617 /* ATTRS set to normal clears r/o bit */
616 pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL); 618 pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
617 if (!(pTcon->ses->flags & CIFS_SES_NT4)) 619 if (!(pTcon->ses->flags & CIFS_SES_NT4))
@@ -693,9 +695,11 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
693 when needed */ 695 when needed */
694 direntry->d_inode->i_ctime = current_fs_time(inode->i_sb); 696 direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
695 } 697 }
696 inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb); 698 if(inode) {
697 cifsInode = CIFS_I(inode); 699 inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
698 cifsInode->time = 0; /* force revalidate of dir as well */ 700 cifsInode = CIFS_I(inode);
701 cifsInode->time = 0; /* force revalidate of dir as well */
702 }
699 703
700 kfree(full_path); 704 kfree(full_path);
701 FreeXid(xid); 705 FreeXid(xid);
@@ -1167,7 +1171,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1167 nfid, npid, FALSE); 1171 nfid, npid, FALSE);
1168 atomic_dec(&open_file->wrtPending); 1172 atomic_dec(&open_file->wrtPending);
1169 cFYI(1,("SetFSize for attrs rc = %d", rc)); 1173 cFYI(1,("SetFSize for attrs rc = %d", rc));
1170 if(rc == -EINVAL) { 1174 if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1171 int bytes_written; 1175 int bytes_written;
1172 rc = CIFSSMBWrite(xid, pTcon, 1176 rc = CIFSSMBWrite(xid, pTcon,
1173 nfid, 0, attrs->ia_size, 1177 nfid, 0, attrs->ia_size,
@@ -1189,7 +1193,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1189 cifs_sb->mnt_cifs_flags & 1193 cifs_sb->mnt_cifs_flags &
1190 CIFS_MOUNT_MAP_SPECIAL_CHR); 1194 CIFS_MOUNT_MAP_SPECIAL_CHR);
1191 cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc)); 1195 cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
1192 if(rc == -EINVAL) { 1196 if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1193 __u16 netfid; 1197 __u16 netfid;
1194 int oplock = FALSE; 1198 int oplock = FALSE;
1195 1199
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 8d0da7c87c7b..9562f5bba65c 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -67,7 +67,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
67 cifs_sb_target->local_nls, 67 cifs_sb_target->local_nls,
68 cifs_sb_target->mnt_cifs_flags & 68 cifs_sb_target->mnt_cifs_flags &
69 CIFS_MOUNT_MAP_SPECIAL_CHR); 69 CIFS_MOUNT_MAP_SPECIAL_CHR);
70 if(rc == -EIO) 70 if((rc == -EIO) || (rc == -EINVAL))
71 rc = -EOPNOTSUPP; 71 rc = -EOPNOTSUPP;
72 } 72 }
73 73
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 432ba15e2c2d..fafd056426e4 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -72,10 +72,9 @@ sesInfoAlloc(void)
72 struct cifsSesInfo *ret_buf; 72 struct cifsSesInfo *ret_buf;
73 73
74 ret_buf = 74 ret_buf =
75 (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo), 75 (struct cifsSesInfo *) kzalloc(sizeof (struct cifsSesInfo),
76 GFP_KERNEL); 76 GFP_KERNEL);
77 if (ret_buf) { 77 if (ret_buf) {
78 memset(ret_buf, 0, sizeof (struct cifsSesInfo));
79 write_lock(&GlobalSMBSeslock); 78 write_lock(&GlobalSMBSeslock);
80 atomic_inc(&sesInfoAllocCount); 79 atomic_inc(&sesInfoAllocCount);
81 ret_buf->status = CifsNew; 80 ret_buf->status = CifsNew;
@@ -110,10 +109,9 @@ tconInfoAlloc(void)
110{ 109{
111 struct cifsTconInfo *ret_buf; 110 struct cifsTconInfo *ret_buf;
112 ret_buf = 111 ret_buf =
113 (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo), 112 (struct cifsTconInfo *) kzalloc(sizeof (struct cifsTconInfo),
114 GFP_KERNEL); 113 GFP_KERNEL);
115 if (ret_buf) { 114 if (ret_buf) {
116 memset(ret_buf, 0, sizeof (struct cifsTconInfo));
117 write_lock(&GlobalSMBSeslock); 115 write_lock(&GlobalSMBSeslock);
118 atomic_inc(&tconInfoAllocCount); 116 atomic_inc(&tconInfoAllocCount);
119 list_add(&ret_buf->cifsConnectionList, 117 list_add(&ret_buf->cifsConnectionList,
@@ -423,9 +421,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
423{ 421{
424 __u32 len = smb->smb_buf_length; 422 __u32 len = smb->smb_buf_length;
425 __u32 clc_len; /* calculated length */ 423 __u32 clc_len; /* calculated length */
426 cFYI(0, 424 cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len));
427 ("Entering checkSMB with Length: %x, smb_buf_length: %x",
428 length, len));
429 if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || 425 if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
430 (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { 426 (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
431 if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) { 427 if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
@@ -433,29 +429,36 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
433 sizeof (struct smb_hdr) - 1) 429 sizeof (struct smb_hdr) - 1)
434 && (smb->Status.CifsError != 0)) { 430 && (smb->Status.CifsError != 0)) {
435 smb->WordCount = 0; 431 smb->WordCount = 0;
436 return 0; /* some error cases do not return wct and bcc */ 432 /* some error cases do not return wct and bcc */
433 return 0;
437 } else { 434 } else {
438 cERROR(1, ("Length less than smb header size")); 435 cERROR(1, ("Length less than smb header size"));
439 } 436 }
440
441 } 437 }
442 if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) 438 if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
443 cERROR(1, 439 cERROR(1, ("smb length greater than MaxBufSize, mid=%d",
444 ("smb_buf_length greater than MaxBufSize")); 440 smb->Mid));
445 cERROR(1,
446 ("bad smb detected. Illegal length. mid=%d",
447 smb->Mid));
448 return 1; 441 return 1;
449 } 442 }
450 443
451 if (checkSMBhdr(smb, mid)) 444 if (checkSMBhdr(smb, mid))
452 return 1; 445 return 1;
453 clc_len = smbCalcSize_LE(smb); 446 clc_len = smbCalcSize_LE(smb);
454 if ((4 + len != clc_len) 447
455 || (4 + len != (unsigned int)length)) { 448 if(4 + len != (unsigned int)length) {
456 cERROR(1, ("Calculated size 0x%x vs actual length 0x%x", 449 cERROR(1, ("Length read does not match RFC1001 length %d",len));
457 clc_len, 4 + len)); 450 return 1;
458 cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid)); 451 }
452
453 if (4 + len != clc_len) {
454 /* check if bcc wrapped around for large read responses */
455 if((len > 64 * 1024) && (len > clc_len)) {
456 /* check if lengths match mod 64K */
457 if(((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))
458 return 0; /* bcc wrapped */
459 }
460 cFYI(1, ("Calculated size %d vs length %d mismatch for mid %d",
461 clc_len, 4 + len, smb->Mid));
459 /* Windows XP can return a few bytes too much, presumably 462 /* Windows XP can return a few bytes too much, presumably
460 an illegal pad, at the end of byte range lock responses 463 an illegal pad, at the end of byte range lock responses
461 so we allow for that three byte pad, as long as actual 464 so we allow for that three byte pad, as long as actual
@@ -469,8 +472,11 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
469 wct and bcc to minimum size and drop the t2 parms and data */ 472 wct and bcc to minimum size and drop the t2 parms and data */
470 if((4+len > clc_len) && (len <= clc_len + 512)) 473 if((4+len > clc_len) && (len <= clc_len + 512))
471 return 0; 474 return 0;
472 else 475 else {
476 cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d",
477 len, smb->Mid));
473 return 1; 478 return 1;
479 }
474 } 480 }
475 return 0; 481 return 0;
476} 482}
diff --git a/fs/cifs/ntlmssp.c b/fs/cifs/ntlmssp.c
new file mode 100644
index 000000000000..78866f925747
--- /dev/null
+++ b/fs/cifs/ntlmssp.c
@@ -0,0 +1,129 @@
1/*
2 * fs/cifs/ntlmssp.h
3 *
4 * Copyright (c) International Business Machines Corp., 2006
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include "cifspdu.h"
23#include "cifsglob.h"
24#include "cifsproto.h"
25#include "cifs_unicode.h"
26#include "cifs_debug.h"
27#include "ntlmssp.h"
28#include "nterr.h"
29
30#ifdef CONFIG_CIFS_EXPERIMENTAL
31static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
32{
33 __u32 capabilities = 0;
34
35 /* init fields common to all four types of SessSetup */
36 /* note that header is initialized to zero in header_assemble */
37 pSMB->req.AndXCommand = 0xFF;
38 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
39 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
40
41 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
42
43 /* BB verify whether signing required on neg or just on auth frame
44 (and NTLM case) */
45
46 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
47 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
48
49 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
50 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
51
52 if (ses->capabilities & CAP_UNICODE) {
53 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
54 capabilities |= CAP_UNICODE;
55 }
56 if (ses->capabilities & CAP_STATUS32) {
57 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
58 capabilities |= CAP_STATUS32;
59 }
60 if (ses->capabilities & CAP_DFS) {
61 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
62 capabilities |= CAP_DFS;
63 }
64
65 /* BB check whether to init vcnum BB */
66 return capabilities;
67}
68int
69CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, const int type,
70 int * pNTLMv2_flg, const struct nls_table *nls_cp)
71{
72 int rc = 0;
73 int wct;
74 struct smb_hdr *smb_buffer;
75 char *bcc_ptr;
76 SESSION_SETUP_ANDX *pSMB;
77 __u32 capabilities;
78
79 if(ses == NULL)
80 return -EINVAL;
81
82 cFYI(1,("SStp type: %d",type));
83 if(type < CIFS_NTLM) {
84#ifndef CONFIG_CIFS_WEAK_PW_HASH
85 /* LANMAN and plaintext are less secure and off by default.
86 So we make this explicitly be turned on in kconfig (in the
87 build) and turned on at runtime (changed from the default)
88 in proc/fs/cifs or via mount parm. Unfortunately this is
89 needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
90 return -EOPNOTSUPP;
91#endif
92 wct = 10; /* lanman 2 style sessionsetup */
93 } else if(type < CIFS_NTLMSSP_NEG)
94 wct = 13; /* old style NTLM sessionsetup */
95 else /* same size for negotiate or auth, NTLMSSP or extended security */
96 wct = 12;
97
98 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
99 (void **)&smb_buffer);
100 if(rc)
101 return rc;
102
103 pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
104
105 capabilities = cifs_ssetup_hdr(ses, pSMB);
106 bcc_ptr = pByteArea(smb_buffer);
107 if(type > CIFS_NTLM) {
108 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
109 capabilities |= CAP_EXTENDED_SECURITY;
110 pSMB->req.Capabilities = cpu_to_le32(capabilities);
111 /* BB set password lengths */
112 } else if(type < CIFS_NTLM) /* lanman */ {
113 /* no capabilities flags in old lanman negotiation */
114 /* pSMB->old_req.PasswordLength = */ /* BB fixme BB */
115 } else /* type CIFS_NTLM */ {
116 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
117 pSMB->req_no_secext.CaseInsensitivePasswordLength =
118 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
119 pSMB->req_no_secext.CaseSensitivePasswordLength =
120 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
121 }
122
123
124/* rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buf_type, 0); */
125 /* SMB request buf freed in SendReceive2 */
126
127 return rc;
128}
129#endif /* CONFIG_CIFS_EXPERIMENTAL */
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
index 803389b64a2c..d39b712a11c5 100644
--- a/fs/cifs/ntlmssp.h
+++ b/fs/cifs/ntlmssp.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/ntlmssp.h 2 * fs/cifs/ntlmssp.h
3 * 3 *
4 * Copyright (c) International Business Machines Corp., 2002 4 * Copyright (c) International Business Machines Corp., 2002,2006
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
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 488bd0d81dcf..2f6e2825571e 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -604,7 +604,12 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
604 cifsFile->search_resume_name = NULL; 604 cifsFile->search_resume_name = NULL;
605 if(cifsFile->srch_inf.ntwrk_buf_start) { 605 if(cifsFile->srch_inf.ntwrk_buf_start) {
606 cFYI(1,("freeing SMB ff cache buf on search rewind")); 606 cFYI(1,("freeing SMB ff cache buf on search rewind"));
607 cifs_buf_release(cifsFile->srch_inf.ntwrk_buf_start); 607 if(cifsFile->srch_inf.smallBuf)
608 cifs_small_buf_release(cifsFile->srch_inf.
609 ntwrk_buf_start);
610 else
611 cifs_buf_release(cifsFile->srch_inf.
612 ntwrk_buf_start);
608 } 613 }
609 rc = initiate_cifs_search(xid,file); 614 rc = initiate_cifs_search(xid,file);
610 if(rc) { 615 if(rc) {
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index b12cb8a7da7c..3da80409466c 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -309,17 +309,16 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
309 309
310 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ 310 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
311 311
312 if (ses == NULL) { 312 if ((ses == NULL) || (ses->server == NULL)) {
313 cERROR(1,("Null smb session")); 313 cifs_small_buf_release(in_buf);
314 return -EIO; 314 cERROR(1,("Null session"));
315 }
316 if(ses->server == NULL) {
317 cERROR(1,("Null tcp session"));
318 return -EIO; 315 return -EIO;
319 } 316 }
320 317
321 if(ses->server->tcpStatus == CifsExiting) 318 if(ses->server->tcpStatus == CifsExiting) {
319 cifs_small_buf_release(in_buf);
322 return -ENOENT; 320 return -ENOENT;
321 }
323 322
324 /* Ensure that we do not send more than 50 overlapping requests 323 /* Ensure that we do not send more than 50 overlapping requests
325 to the same server. We may make this configurable later or 324 to the same server. We may make this configurable later or
@@ -346,6 +345,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
346 } else { 345 } else {
347 if(ses->server->tcpStatus == CifsExiting) { 346 if(ses->server->tcpStatus == CifsExiting) {
348 spin_unlock(&GlobalMid_Lock); 347 spin_unlock(&GlobalMid_Lock);
348 cifs_small_buf_release(in_buf);
349 return -ENOENT; 349 return -ENOENT;
350 } 350 }
351 351
@@ -385,6 +385,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
385 midQ = AllocMidQEntry(in_buf, ses); 385 midQ = AllocMidQEntry(in_buf, ses);
386 if (midQ == NULL) { 386 if (midQ == NULL) {
387 up(&ses->server->tcpSem); 387 up(&ses->server->tcpSem);
388 cifs_small_buf_release(in_buf);
388 /* If not lock req, update # of requests on wire to server */ 389 /* If not lock req, update # of requests on wire to server */
389 if(long_op < 3) { 390 if(long_op < 3) {
390 atomic_dec(&ses->server->inFlight); 391 atomic_dec(&ses->server->inFlight);
@@ -408,14 +409,18 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
408 if(rc < 0) { 409 if(rc < 0) {
409 DeleteMidQEntry(midQ); 410 DeleteMidQEntry(midQ);
410 up(&ses->server->tcpSem); 411 up(&ses->server->tcpSem);
412 cifs_small_buf_release(in_buf);
411 /* If not lock req, update # of requests on wire to server */ 413 /* If not lock req, update # of requests on wire to server */
412 if(long_op < 3) { 414 if(long_op < 3) {
413 atomic_dec(&ses->server->inFlight); 415 atomic_dec(&ses->server->inFlight);
414 wake_up(&ses->server->request_q); 416 wake_up(&ses->server->request_q);
415 } 417 }
416 return rc; 418 return rc;
417 } else 419 } else {
418 up(&ses->server->tcpSem); 420 up(&ses->server->tcpSem);
421 cifs_small_buf_release(in_buf);
422 }
423
419 if (long_op == -1) 424 if (long_op == -1)
420 goto cifs_no_response_exit2; 425 goto cifs_no_response_exit2;
421 else if (long_op == 2) /* writes past end of file can take loong time */ 426 else if (long_op == 2) /* writes past end of file can take loong time */
@@ -543,6 +548,7 @@ cifs_no_response_exit2:
543 548
544out_unlock2: 549out_unlock2:
545 up(&ses->server->tcpSem); 550 up(&ses->server->tcpSem);
551 cifs_small_buf_release(in_buf);
546 /* If not lock req, update # of requests on wire to server */ 552 /* If not lock req, update # of requests on wire to server */
547 if(long_op < 3) { 553 if(long_op < 3) {
548 atomic_dec(&ses->server->inFlight); 554 atomic_dec(&ses->server->inFlight);