GIT 88274815f7477dc7550439413ab87c5ce4c5a623 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git commit 88274815f7477dc7550439413ab87c5ce4c5a623 Author: Steve French Date: Thu Mar 9 22:21:45 2006 +0000 [CIFS] Fix two remaining coverity scan tool warnings. Signed-off-by: Steve French commit f6e77c94796edad172602234826a022d463d910e Merge: beb84dc... d0b0048... Author: Steve French Date: Tue Mar 7 21:47:30 2006 +0000 Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git Signed-off-by: Steve French commit beb84dc8186662b17d5ea510fabb85cb7e266d33 Author: Steve French Date: Fri Mar 3 23:36:34 2006 +0000 [CIFS] Set correct lock type on new posix unlock call Signed-off-by: Steve French commit c6ee60b7c8bbc78e3b1776b2820a7e7f95f8996a Merge: 13298de... c499ec2... Author: Steve French Date: Fri Mar 3 11:27:25 2006 +0000 Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git Signed-off-by: Steve French commit 13298defe5323c7fdcac268f588d8d1090758fb8 Author: Steve French Date: Fri Mar 3 10:45:19 2006 +0000 [CIFS] Upate cifs change log Signed-off-by: Steve French commit d7c8c94d3e4c1cab7feedbb34297caa5babe1a7f Author: Steve French Date: Fri Mar 3 10:43:49 2006 +0000 [CIFS] Fix slow oplock break response when mounts to different servers have same tid and we try to match oplock break to wrong tid. Signed-off-by: Steve French commit 083d3a2cff514c5301f3a043642940d4d5371b22 Author: Steve French Date: Fri Mar 3 09:53:36 2006 +0000 [CIFS] Workaround various server bugs found in testing at connectathon - slow down negprot 1ms during mount when RFC1001 over port 139 to give buggy servers time to clear sess_init - remap some plausible but incorrect SMB return codes to the right ones in truncate and hardlink paths Signed-off-by: Steve French commit a4e85b5f620f59bd9308e29f833648f792d422f7 Author: Steve French Date: Thu Mar 2 03:53:17 2006 +0000 [CIFS] Allow fallback for setting file size to Procom SMB server when returns error invalid level Signed-off-by: Steve French commit 82940a465829b0c757dea45889aa150c8083e3d9 Author: Steve French Date: Thu Mar 2 03:24:57 2006 +0000 [CIFS] Make POSIX CIFS Extensions SetFSInfo match exactly what we want not just the posix path feature. Signed-off-by: Steve French commit 46c79a645a00e71dbbfd5f52abe0ea7cf2d5daa3 Author: Steve French Date: Thu Mar 2 00:07:08 2006 +0000 [CIFS] Move noisy debug message (triggerred by some older servers) from error to informational unless frame is rejected. Signed-off-by: Steve French commit f26282c9af43c1aff3f448af61429625174ddf06 Author: Steve French Date: Wed Mar 1 09:17:37 2006 +0000 [CIFS] Use correct pid on new cifs posix byte range lock call Signed-off-by: Steve French commit 08547b036b8445e2318e14f1f03308105b01fc5b Author: Steve French Date: Tue Feb 28 22:39:25 2006 +0000 [CIFS] Add posix (advisory) byte range locking support to cifs client Samba (version 3) server support for this is also currently being done. This client code is in an experimental path (requires enabling /proc/fs/cifs/Experimental) while it is being tested. Signed-off-by: Steve French commit d47d7c1a850b867047fe17140fabd0376894e849 Author: Steve French Date: Tue Feb 28 03:45:48 2006 +0000 [CIFS] CIFS readdir perf optimizations part 1 Signed-off-by: Steve French commit 4b8f930ff83aaed39fd5f935aeacc25f2549a51e Author: Steve French Date: Sun Feb 26 16:41:18 2006 +0000 [CIFS] Free small buffers earlier so we exceed the cifs small req buffer pool less often. Signed-off-by: Steve French commit 184ed2110ae6bfdb8dc91085149f04f2f4d2169e Author: Steve French Date: Fri Feb 24 06:15:11 2006 +0000 [CIFS] Fix large (ie over 64K for MaxCIFSBufSize) buffer case for wrapping bcc on read response and for wrapping sessionsetup maxbufsize field Signed-off-by: Steve French commit 5d2f248a5f3acac4b763439327c92091be7abb1c Merge: a048d7a... 9e956c2... Author: Steve French Date: Wed Feb 22 23:38:53 2006 +0000 Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git Signed-off-by: Steve French commit a048d7a8704b35ff6372fdf5eedd4533f37b1885 Author: Eric Sesterhenn Date: Tue Feb 21 22:33:09 2006 +0000 [CIFS] Convert remaining places in fs/cifs from kmalloc/memset to simpler kzalloc usage Signed-off-by: Eric Sesterhenn Signed-off-by: Steve French commit e601ef22bc5ec9332c8d785533895ee81c834b8a Merge: 27754b3... bd71c2b... Author: Steve French Date: Sat Feb 18 15:07:18 2006 +0000 Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git Signed-off-by: Steve French commit 27754b34600770beb38e3ae12cb3f345f02e3797 Merge: 0ed3f64... 5ecfbae... Author: Steve French Date: Wed Feb 15 20:13:52 2006 +0000 Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git Signed-off-by: Steve French commit 0ed3f64ec3a7ad29e83e03607115eeffa32f553c Merge: 5815449... 10ee39f... Author: Steve French Date: Wed Feb 15 03:36:31 2006 +0000 Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git Signed-off-by: Steve French commit 5815449d1bfcb22f74b0e36a8b0631d6584cb7fc Author: Steve French Date: Tue Feb 14 01:36:20 2006 +0000 [CIFS] SessionSetup cleanup part 2 The cifs session setup code has three cases, and a fourth for backlevel LANMAN2 style session setup needed to be added. This new session setup implmentation will eventually replace the other three and should be easier to read while fixing a few minor problems (not setting the LARGE READ/WRITEX flags when NTLMSSP was negotiated for example) and adding support for NTLMv2 (which will be added with the next patch. In the meantime, this code is marked in an CONFIG_CIFS_EXPERIMENTAL block and will not be turned on by default until it is tested against more server types. Signed-off-by: Steve French commit b580513e841d81eebf0d7b02f412be0882c2ce5f Merge: 04fdabe... 418aade... Author: Steve French Date: Fri Feb 10 16:53:29 2006 +0000 Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git Signed-off-by: Steve French commit 04fdabe17c4840a4cd84c3589f20f5d4689b1ec5 Author: Steve French Date: Fri Feb 10 05:52:50 2006 +0000 [CIFS] fix compile error (typo) and warning in cifssmb.c Signed-off-by: Steve French commit 12b3b8ffb5fd591df41f658d6068b76f7a58e710 Author: Steve French Date: Thu Feb 9 21:12:47 2006 +0000 [CIFS] Cleanup NTLMSSP session setup handling Fix to hash NTLMv2 properly will follow. Signed-off-by: Steve French --- diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index d335015..3e0fcc3 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,3 +1,21 @@ +Version 1.42 +------------ +Fix slow oplock break when mounted to different servers at the same time and +the tids match and we try to find matching fid on wrong server. + +Version 1.41 +------------ +Fix NTLMv2 security (can be enabled in /proc/fs/cifs) so customers can +configure stronger authentication. Fix sfu symlinks so they can +be followed (not just recognized). Fix wraparound of bcc on +read responses when buffer size over 64K and also fix wrap of +max smb buffer size when CIFSMaxBufSize over 64K. Fix oops in +cifs_user_read and cifs_readpages (when EAGAIN on send of smb +on socket is returned over and over). Add POSIX (advisory) byte range +locking support (requires server with newest CIFS UNIX Extensions +to the protocol implemented). Slow down negprot slightly in port 139 +RFC1001 case to give session_init time on buggy servers. + Version 1.40 ------------ Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index 7384947..58c7725 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile @@ -3,4 +3,4 @@ # obj-$(CONFIG_CIFS) += cifs.o -cifs-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 +cifs-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 b0070d1..b2b4d08 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -422,6 +422,13 @@ A partial list of the supported mount op nomapchars Do not translate any of these seven characters (default). nocase Request case insensitive path name matching (case sensitive is the default if the server suports it). + posixpaths If CIFS Unix extensions are supported, attempt to + negotiate posix path name support which allows certain + characters forbidden in typical CIFS filenames, without + requiring remapping. (default) + noposixpaths If CIFS Unix extensions are supported, do not request + posix path name support (this may cause servers to + reject creatingfile with certain reserved characters). nobrl Do not send byte range lock requests to the server. This is necessary for certain applications that break with cifs style mandatory byte range locks (and most diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index a2c2485..c2cbe0e 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -1,7 +1,7 @@ /* * fs/cifs/cifsencrypt.c * - * Copyright (C) International Business Machines Corp., 2005 + * Copyright (C) International Business Machines Corp., 2005,2006 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -36,7 +36,8 @@ extern void mdfour(unsigned char *out, unsigned char *in, int n); extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); -static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature) +static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, + const char * key, char * signature) { struct MD5Context context; @@ -259,4 +260,5 @@ void CalcNTLMv2_response(const struct ci /* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */ hmac_md5_final(v2_session_response,&context); + cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); /* BB removeme BB */ } diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 79eeccd..8219c02 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -93,13 +93,10 @@ cifs_read_super(struct super_block *sb, int rc = 0; sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */ - sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL); + sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL); cifs_sb = CIFS_SB(sb); if(cifs_sb == NULL) return -ENOMEM; - else - memset(cifs_sb,0,sizeof(struct cifs_sb_info)); - rc = cifs_mount(sb, cifs_sb, data, devname); diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 821a8eb..b4dcdc2 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -99,5 +99,5 @@ extern ssize_t cifs_getxattr(struct dent extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg); -#define CIFS_VERSION "1.40" +#define CIFS_VERSION "1.42" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 7bed276..006eb33 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1,7 +1,7 @@ /* * fs/cifs/cifsglob.h * - * Copyright (C) International Business Machines Corp., 2002,2005 + * Copyright (C) International Business Machines Corp., 2002,2006 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -430,6 +430,15 @@ struct dir_notify_req { #define CIFS_LARGE_BUFFER 2 #define CIFS_IOVEC 4 /* array of response buffers */ +/* Type of session setup needed */ +#define CIFS_PLAINTEXT 0 +#define CIFS_LANMAN 1 +#define CIFS_NTLM 2 +#define CIFS_NTLMSSP_NEG 3 +#define CIFS_NTLMSSP_AUTH 4 +#define CIFS_SPNEGO_INIT 5 +#define CIFS_SPNEGO_TARG 6 + /* ***************************************************************** * All constants go here diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index cc24710..b2233ac 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -859,7 +859,10 @@ typedef struct smb_com_lock_req { LOCKING_ANDX_RANGE Locks[1]; } __attribute__((packed)) LOCK_REQ; - +/* lock type */ +#define CIFS_RDLCK 0 +#define CIFS_WRLCK 1 +#define CIFS_UNLCK 2 typedef struct cifs_posix_lock { __le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */ __le16 lock_flags; /* 1 = Wait (only valid for setlock) */ @@ -1786,7 +1789,13 @@ typedef struct { #define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */ #define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ #define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ -#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Use POSIX pathnames on the wire. */ +#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */ +#ifdef CONFIG_CIFS_POSIX +#define CIFS_UNIX_CAP_MASK 0x0000001b +#else +#define CIFS_UNIX_CAP_MASK 0x00000013 +#endif /* CONFIG_CIFS_POSIX */ + #define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7b25463..2879ba3 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -1,7 +1,7 @@ /* * fs/cifs/cifsproto.h * - * Copyright (c) International Business Machines Corp., 2002,2005 + * Copyright (c) International Business Machines Corp., 2002,2006 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -64,6 +64,14 @@ extern int map_smb_to_linux_error(struct extern void header_assemble(struct smb_hdr *, char /* command */ , const struct cifsTconInfo *, int /* length of fixed section (word count) in two byte units */); +#ifdef CONFIG_CIFS_EXPERIMENTAL +extern int small_smb_init_no_tc(const int smb_cmd, const int wct, + struct cifsSesInfo *ses, + void ** request_buf); +extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, + const int stage, int * pNTLMv2_flg, + const struct nls_table *nls_cp); +#endif extern __u16 GetNextMid(struct TCP_Server_Info *server); extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *); @@ -257,7 +265,10 @@ extern int CIFSSMBLock(const int xid, st const __u64 offset, const __u32 numUnlock, const __u32 numLock, const __u8 lockType, const int waitFlag); - +extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, + const __u16 smb_file_id, const int get_flag, + const __u64 len, const __u64 offset, + const __u16 lock_type, const int waitFlag); extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon); extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index b41e8b3..a594187 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1,7 +1,7 @@ /* * fs/cifs/cifssmb.c * - * Copyright (C) International Business Machines Corp., 2002,2005 + * Copyright (C) International Business Machines Corp., 2002,2006 * Author(s): Steve French (sfrench@us.ibm.com) * * Contains the routines for constructing the SMB PDUs themselves @@ -186,7 +186,35 @@ small_smb_init(int smb_command, int wct, cifs_stats_inc(&tcon->num_smbs_sent); return rc; -} +} + +#ifdef CONFIG_CIFS_EXPERIMENTAL +int +small_smb_init_no_tc(const int smb_command, const int wct, + struct cifsSesInfo *ses, void **request_buf) +{ + int rc; + struct smb_hdr * buffer; + + rc = small_smb_init(smb_command, wct, NULL, request_buf); + if(rc) + return rc; + + buffer = (struct smb_hdr *)*request_buf; + buffer->Mid = GetNextMid(ses->server); + if (ses->capabilities & CAP_UNICODE) + buffer->Flags2 |= SMBFLG2_UNICODE; + if (ses->capabilities & CAP_STATUS32) + buffer->Flags2 |= SMBFLG2_ERR_STATUS; + + /* uid, tid can stay at zero as set in header assemble */ + + /* BB add support for turning on the signing when + this function is used after 1st of session setup requests */ + + return rc; +} +#endif /* CONFIG_CIFS_EXPERIMENTAL */ /* If the return code is zero, this function must fill in request_buf pointer */ static int @@ -1042,7 +1070,7 @@ CIFSSMBRead(const int xid, struct cifsTc } } - cifs_small_buf_release(pSMB); +/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ if(*buf) { if(resp_buf_type == CIFS_SMALL_BUFFER) cifs_small_buf_release(iov[0].iov_base); @@ -1246,7 +1274,7 @@ CIFSSMBWrite2(const int xid, struct cifs *nbytes += le16_to_cpu(pSMBr->Count); } - cifs_small_buf_release(pSMB); +/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ if(resp_buf_type == CIFS_SMALL_BUFFER) cifs_small_buf_release(iov[0].iov_base); else if(resp_buf_type == CIFS_LARGE_BUFFER) @@ -1325,6 +1353,85 @@ CIFSSMBLock(const int xid, struct cifsTc } int +CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, + const __u16 smb_file_id, const int get_flag, const __u64 len, + const __u64 lkoffset, const __u16 lock_type, const int waitFlag) +{ + struct smb_com_transaction2_sfi_req *pSMB = NULL; + struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; + char *data_offset; + struct cifs_posix_lock *parm_data; + int rc = 0; + int bytes_returned = 0; + __u16 params, param_offset, offset, byte_count, count; + + cFYI(1, ("Posix Lock")); + rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); + + if (rc) + return rc; + + pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB; + + params = 6; + pSMB->MaxSetupCount = 0; + pSMB->Reserved = 0; + pSMB->Flags = 0; + pSMB->Timeout = 0; + pSMB->Reserved2 = 0; + param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; + offset = param_offset + params; + + data_offset = (char *) (&pSMB->hdr.Protocol) + offset; + + count = sizeof(struct cifs_posix_lock); + pSMB->MaxParameterCount = cpu_to_le16(2); + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ + pSMB->SetupCount = 1; + pSMB->Reserved3 = 0; + if(get_flag) + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION); + else + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); + byte_count = 3 /* pad */ + params + count; + pSMB->DataCount = cpu_to_le16(count); + pSMB->ParameterCount = cpu_to_le16(params); + pSMB->TotalDataCount = pSMB->DataCount; + pSMB->TotalParameterCount = pSMB->ParameterCount; + pSMB->ParameterOffset = cpu_to_le16(param_offset); + parm_data = (struct cifs_posix_lock *) + (((char *) &pSMB->hdr.Protocol) + offset); + + parm_data->lock_type = cpu_to_le16(lock_type); + if(waitFlag) + parm_data->lock_flags = 1; + parm_data->pid = cpu_to_le32(current->tgid); + parm_data->start = lkoffset; + parm_data->length = len; /* normalize negative numbers */ + + pSMB->DataOffset = cpu_to_le16(offset); + pSMB->Fid = smb_file_id; + pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK); + pSMB->Reserved4 = 0; + pSMB->hdr.smb_buf_length += byte_count; + pSMB->ByteCount = cpu_to_le16(byte_count); + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, &bytes_returned, 0); + if (rc) { + cFYI(1, ("Send error in Posix Lock = %d", rc)); + } + + if (pSMB) + cifs_small_buf_release(pSMB); + + /* Note: On -EAGAIN error only caller can retry on handle based calls + since file handle passed in no longer valid */ + + return rc; +} + + +int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) { int rc = 0; @@ -2578,7 +2685,7 @@ qsec_out: cifs_small_buf_release(iov[0].iov_base); else if(buf_type == CIFS_LARGE_BUFFER) cifs_buf_release(iov[0].iov_base); - cifs_small_buf_release(pSMB); +/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ return rc; } @@ -2954,7 +3061,8 @@ findFirstRetry: pSMB->TotalParameterCount = cpu_to_le16(params); pSMB->ParameterCount = pSMB->TotalParameterCount; pSMB->ParameterOffset = cpu_to_le16( - offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4); + offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) + - 4); pSMB->DataCount = 0; pSMB->DataOffset = 0; pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */ @@ -2977,12 +3085,12 @@ findFirstRetry: (struct smb_hdr *) pSMBr, &bytes_returned, 0); cifs_stats_inc(&tcon->num_ffirst); - if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ + if (rc) {/* BB add logic to retry regular search if Unix search + rejected unexpectedly by server */ /* BB Add code to handle unsupported level rc */ cFYI(1, ("Error in FindFirst = %d", rc)); - if (pSMB) - cifs_buf_release(pSMB); + cifs_buf_release(pSMB); /* BB eventually could optimize out free and realloc of buf */ /* for this case */ @@ -2998,6 +3106,7 @@ findFirstRetry: psrch_inf->unicode = FALSE; psrch_inf->ntwrk_buf_start = (char *)pSMBr; + psrch_inf->smallBuf = 0; psrch_inf->srch_entries_start = (char *) &pSMBr->hdr.Protocol + le16_to_cpu(pSMBr->t2.DataOffset); @@ -3118,9 +3227,14 @@ int CIFSFindNext(const int xid, struct c parms = (T2_FNEXT_RSP_PARMS *)response_data; response_data = (char *)&pSMBr->hdr.Protocol + le16_to_cpu(pSMBr->t2.DataOffset); - cifs_buf_release(psrch_inf->ntwrk_buf_start); + if(psrch_inf->smallBuf) + cifs_small_buf_release( + psrch_inf->ntwrk_buf_start); + else + cifs_buf_release(psrch_inf->ntwrk_buf_start); psrch_inf->srch_entries_start = response_data; psrch_inf->ntwrk_buf_start = (char *)pSMB; + psrch_inf->smallBuf = 0; if(parms->EndofSearch) psrch_inf->endOfSearch = TRUE; else @@ -3834,6 +3948,7 @@ CIFSSMBSetFSUnixInfo(const int xid, stru cFYI(1, ("In SETFSUnixInfo")); SETFSUnixRetry: + /* BB switch to small buf init to save memory */ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 2a0c1f4..0b86d5c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1,7 +1,7 @@ /* * fs/cifs/connect.c * - * Copyright (C) International Business Machines Corp., 2002,2005 + * Copyright (C) International Business Machines Corp., 2002,2006 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -564,7 +564,7 @@ cifs_demultiplex_thread(struct TCP_Serve dump_smb(smb_buffer, length); - if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) { + if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) { cifs_dump_mem("Bad SMB: ", smb_buffer, 48); continue; } @@ -1476,6 +1476,14 @@ ipv4_connect(struct sockaddr_in *psin_se rc = smb_send(*csocket, smb_buf, 0x44, (struct sockaddr *)psin_server); kfree(ses_init_buf); + msleep(1); /* RFC1001 layer in at least one server + requires very short break before negprot + presumably because not expecting negprot + to follow so fast. This is a simple + solution that works without + complicating the code and causes no + significant slowing down on mount + for everyone else */ } /* else the negprot may still work without this even though malloc failed */ @@ -1920,27 +1928,34 @@ cifs_mount(struct super_block *sb, struc cifs_sb->tcon = tcon; tcon->ses = pSesInfo; - /* do not care if following two calls succeed - informational only */ + /* do not care if following two calls succeed - informational */ CIFSSMBQFSDeviceInfo(xid, tcon); CIFSSMBQFSAttributeInfo(xid, tcon); + if (tcon->ses->capabilities & CAP_UNIX) { if(!CIFSSMBQFSUnixInfo(xid, tcon)) { - if(!volume_info.no_psx_acl) { - if(CIFS_UNIX_POSIX_ACL_CAP & - le64_to_cpu(tcon->fsUnixInfo.Capability)) - cFYI(1,("server negotiated posix acl support")); - sb->s_flags |= MS_POSIXACL; + __u64 cap = + le64_to_cpu(tcon->fsUnixInfo.Capability); + cap &= CIFS_UNIX_CAP_MASK; + if(volume_info.no_psx_acl) + cap &= ~CIFS_UNIX_POSIX_ACL_CAP; + else if(CIFS_UNIX_POSIX_ACL_CAP & cap) { + cFYI(1,("negotiated posix acl support")); + sb->s_flags |= MS_POSIXACL; + } + + if(volume_info.posix_paths == 0) + cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; + else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) { + cFYI(1,("negotiate posix pathnames")); + cifs_sb->mnt_cifs_flags |= + CIFS_MOUNT_POSIX_PATHS; } + + cFYI(1,("Negotiate caps 0x%x",(int)cap)); - /* Try and negotiate POSIX pathnames if we can. */ - if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP & - le64_to_cpu(tcon->fsUnixInfo.Capability))) { - if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) { - cFYI(1,("negotiated posix pathnames support")); - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; - } else { - cFYI(1,("posix pathnames support requested but not supported")); - } + if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { + cFYI(1,("setting capabilities failed")); } } } @@ -2278,6 +2293,8 @@ CIFSSpnegoSessSetup(unsigned int xid, st smb_buffer->Mid = GetNextMid(ses->server); pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; pSMB->req.AndXCommand = 0xFF; + if(ses->server->maxBuf > 64*1024) + ses->server->maxBuf = (64*1023); pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); @@ -2525,7 +2542,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned i __u32 negotiate_flags, capabilities; __u16 count; - cFYI(1, ("In NTLMSSP sesssetup (negotiate) ")); + cFYI(1, ("In NTLMSSP sesssetup (negotiate)")); if(ses == NULL) return -EINVAL; domain = ses->domainName; @@ -2575,7 +2592,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned i SecurityBlob->MessageType = NtLmNegotiate; negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM | - NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 | + NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | + NTLMSSP_NEGOTIATE_56 | /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; if(sign_CIFS_PDUs) negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; @@ -2588,26 +2606,11 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned i SecurityBlob->WorkstationName.Length = 0; SecurityBlob->WorkstationName.MaximumLength = 0; - if (domain == NULL) { - SecurityBlob->DomainName.Buffer = 0; - SecurityBlob->DomainName.Length = 0; - SecurityBlob->DomainName.MaximumLength = 0; - } else { - __u16 len; - negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; - strncpy(bcc_ptr, domain, 63); - len = strnlen(domain, 64); - SecurityBlob->DomainName.MaximumLength = - cpu_to_le16(len); - SecurityBlob->DomainName.Buffer = - cpu_to_le32((long) &SecurityBlob-> - DomainString - - (long) &SecurityBlob->Signature); - bcc_ptr += len; - SecurityBlobLength += len; - SecurityBlob->DomainName.Length = - cpu_to_le16(len); - } + /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent + along with username on auth request (ie the response to challenge) */ + SecurityBlob->DomainName.Buffer = 0; + SecurityBlob->DomainName.Length = 0; + SecurityBlob->DomainName.MaximumLength = 0; if (ses->capabilities & CAP_UNICODE) { if ((long) bcc_ptr % 2) { *bcc_ptr = 0; @@ -2677,7 +2680,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned i SecurityBlob2->MessageType)); } else if (ses) { ses->Suid = smb_buffer_response->Uid; /* UID left in le format */ - cFYI(1, ("UID = %d ", ses->Suid)); + cFYI(1, ("UID = %d", ses->Suid)); if ((pSMBr->resp.hdr.WordCount == 3) || ((pSMBr->resp.hdr.WordCount == 4) && (blob_len < @@ -2685,17 +2688,17 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned i if (pSMBr->resp.hdr.WordCount == 4) { bcc_ptr += blob_len; - cFYI(1, - ("Security Blob Length %d ", + cFYI(1, ("Security Blob Length %d", blob_len)); } - cFYI(1, ("NTLMSSP Challenge rcvd ")); + cFYI(1, ("NTLMSSP Challenge rcvd")); memcpy(ses->server->cryptKey, SecurityBlob2->Challenge, CIFS_CRYPTO_KEY_SIZE); - if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2)) + if(SecurityBlob2->NegotiateFlags & + cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2)) *pNTLMv2_flag = TRUE; if((SecurityBlob2->NegotiateFlags & @@ -2818,7 +2821,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned i bcc_ptr++; } else cFYI(1, - ("Variable field of length %d extends beyond end of smb ", + ("Variable field of length %d extends beyond end of smb", len)); } } else { @@ -2830,7 +2833,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned i } } else { cERROR(1, - (" Invalid Word count %d: ", + (" Invalid Word count %d:", smb_buffer_response->WordCount)); rc = -EIO; } @@ -3447,7 +3450,7 @@ int cifs_setup_session(unsigned int xid, if (extended_security && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) && (pSesInfo->server->secType == NTLMSSP)) { - cFYI(1, ("New style sesssetup ")); + cFYI(1, ("New style sesssetup")); rc = CIFSSpnegoSessSetup(xid, pSesInfo, NULL /* security blob */, 0 /* blob length */, @@ -3455,7 +3458,7 @@ int cifs_setup_session(unsigned int xid, } else if (extended_security && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) && (pSesInfo->server->secType == RawNTLMSSP)) { - cFYI(1, ("NTLMSSP sesssetup ")); + cFYI(1, ("NTLMSSP sesssetup")); rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag, diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index fed55e3..ddd11fa 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -48,13 +48,14 @@ build_path_from_dentry(struct dentry *di struct dentry *temp; int namelen = 0; char *full_path; - char dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); + char dirsep; if(direntry == NULL) return NULL; /* not much we can do if dentry is freed and we need to reopen the file after it was closed implicitly when the server crashed */ + dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); cifs_bp_rename_retry: for (temp = direntry; !IS_ROOT(temp);) { namelen += (1 + temp->d_name.len); @@ -255,12 +256,10 @@ cifs_create(struct inode *inode, struct CIFSSMBClose(xid, pTcon, fileHandle); } else if(newinode) { pCifsFile = - kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); + kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); if(pCifsFile == NULL) goto cifs_create_out; - memset((char *)pCifsFile, 0, - sizeof (struct cifsFileInfo)); pCifsFile->netfid = fileHandle; pCifsFile->pid = current->tgid; pCifsFile->pInode = newinode; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 675bd25..2c093de 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -555,7 +555,10 @@ int cifs_closedir(struct inode *inode, s if (ptmp) { cFYI(1, ("closedir free smb buf in srch struct")); pCFileStruct->srch_inf.ntwrk_buf_start = NULL; - cifs_buf_release(ptmp); + if(pCFileStruct->srch_inf.smallBuf) + cifs_small_buf_release(ptmp); + else + cifs_buf_release(ptmp); } ptmp = pCFileStruct->search_resume_name; if (ptmp) { @@ -574,13 +577,14 @@ int cifs_closedir(struct inode *inode, s int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) { int rc, xid; - __u32 lockType = LOCKING_ANDX_LARGE_FILES; __u32 numLock = 0; __u32 numUnlock = 0; __u64 length; int wait_flag = FALSE; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; + __u16 netfid; + __u8 lockType = LOCKING_ANDX_LARGE_FILES; length = 1 + pfLock->fl_end - pfLock->fl_start; rc = -EACCES; @@ -592,11 +596,11 @@ int cifs_lock(struct file *file, int cmd pfLock->fl_end)); if (pfLock->fl_flags & FL_POSIX) - cFYI(1, ("Posix ")); + cFYI(1, ("Posix")); if (pfLock->fl_flags & FL_FLOCK) - cFYI(1, ("Flock ")); + cFYI(1, ("Flock")); if (pfLock->fl_flags & FL_SLEEP) { - cFYI(1, ("Blocking lock ")); + cFYI(1, ("Blocking lock")); wait_flag = TRUE; } if (pfLock->fl_flags & FL_ACCESS) @@ -612,21 +616,23 @@ int cifs_lock(struct file *file, int cmd cFYI(1, ("F_WRLCK ")); numLock = 1; } else if (pfLock->fl_type == F_UNLCK) { - cFYI(1, ("F_UNLCK ")); + cFYI(1, ("F_UNLCK")); numUnlock = 1; + /* Check if unlock includes more than + one lock range */ } else if (pfLock->fl_type == F_RDLCK) { - cFYI(1, ("F_RDLCK ")); + cFYI(1, ("F_RDLCK")); lockType |= LOCKING_ANDX_SHARED_LOCK; numLock = 1; } else if (pfLock->fl_type == F_EXLCK) { - cFYI(1, ("F_EXLCK ")); + cFYI(1, ("F_EXLCK")); numLock = 1; } else if (pfLock->fl_type == F_SHLCK) { - cFYI(1, ("F_SHLCK ")); + cFYI(1, ("F_SHLCK")); lockType |= LOCKING_ANDX_SHARED_LOCK; numLock = 1; } else - cFYI(1, ("Unknown type of lock ")); + cFYI(1, ("Unknown type of lock")); cifs_sb = CIFS_SB(file->f_dentry->d_sb); pTcon = cifs_sb->tcon; @@ -635,27 +641,41 @@ int cifs_lock(struct file *file, int cmd FreeXid(xid); return -EBADF; } + netfid = ((struct cifsFileInfo *)file->private_data)->netfid; + + /* BB add code here to normalize offset and length to + account for negative length which we can not accept over the + wire */ if (IS_GETLK(cmd)) { - rc = CIFSSMBLock(xid, pTcon, - ((struct cifsFileInfo *)file-> - private_data)->netfid, - length, - pfLock->fl_start, 0, 1, lockType, - 0 /* wait flag */ ); + if(experimEnabled && + (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && + (CIFS_UNIX_FCNTL_CAP & + le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { + int posix_lock_type; + if(lockType & LOCKING_ANDX_SHARED_LOCK) + posix_lock_type = CIFS_RDLCK; + else + posix_lock_type = CIFS_WRLCK; + rc = CIFSSMBPosixLock(xid, pTcon, netfid, 1 /* get */, + length, pfLock->fl_start, + posix_lock_type, wait_flag); + FreeXid(xid); + return rc; + } + + /* BB we could chain these into one lock request BB */ + rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, + 0, 1, lockType, 0 /* wait flag */ ); if (rc == 0) { - rc = CIFSSMBLock(xid, pTcon, - ((struct cifsFileInfo *) file-> - private_data)->netfid, - length, + rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, 1 /* numUnlock */ , 0 /* numLock */ , lockType, 0 /* wait flag */ ); pfLock->fl_type = F_UNLCK; if (rc != 0) cERROR(1, ("Error unlocking previously locked " - "range %d during test of lock ", - rc)); + "range %d during test of lock", rc)); rc = 0; } else { @@ -667,12 +687,30 @@ int cifs_lock(struct file *file, int cmd FreeXid(xid); return rc; } - - rc = CIFSSMBLock(xid, pTcon, - ((struct cifsFileInfo *) file->private_data)-> - netfid, length, - pfLock->fl_start, numUnlock, numLock, lockType, - wait_flag); + if (experimEnabled && + (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && + (CIFS_UNIX_FCNTL_CAP & + le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { + int posix_lock_type; + if(lockType & LOCKING_ANDX_SHARED_LOCK) + posix_lock_type = CIFS_RDLCK; + else + posix_lock_type = CIFS_WRLCK; + + if(numUnlock == 1) + posix_lock_type = CIFS_UNLCK; + else if(numLock == 0) { + /* if no lock or unlock then nothing + to do since we do not know what it is */ + FreeXid(xid); + return -EOPNOTSUPP; + } + rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, + length, pfLock->fl_start, + posix_lock_type, wait_flag); + } else + rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, + numUnlock, numLock, lockType, wait_flag); if (pfLock->fl_flags & FL_POSIX) posix_lock_file_wait(file, pfLock); FreeXid(xid); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 5935991..b21038b 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -609,9 +609,8 @@ int cifs_unlink(struct inode *inode, str } } else if (rc == -EACCES) { /* try only if r/o attribute set in local lookup data? */ - pinfo_buf = kmalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL); + pinfo_buf = kzalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL); if (pinfo_buf) { - memset(pinfo_buf, 0, sizeof(FILE_BASIC_INFO)); /* ATTRS set to normal clears r/o bit */ pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL); if (!(pTcon->ses->flags & CIFS_SES_NT4)) @@ -1167,7 +1166,7 @@ int cifs_setattr(struct dentry *direntry nfid, npid, FALSE); atomic_dec(&open_file->wrtPending); cFYI(1,("SetFSize for attrs rc = %d", rc)); - if(rc == -EINVAL) { + if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { int bytes_written; rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size, @@ -1189,7 +1188,7 @@ int cifs_setattr(struct dentry *direntry cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc)); - if(rc == -EINVAL) { + if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { __u16 netfid; int oplock = FALSE; diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 0f99aae..ce86ec6 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -67,7 +67,7 @@ cifs_hardlink(struct dentry *old_file, s cifs_sb_target->local_nls, cifs_sb_target->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if(rc == -EIO) + if((rc == -EIO) || (rc == -EINVAL)) rc = -EOPNOTSUPP; } diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 432ba15..fafd056 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -72,10 +72,9 @@ sesInfoAlloc(void) struct cifsSesInfo *ret_buf; ret_buf = - (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo), + (struct cifsSesInfo *) kzalloc(sizeof (struct cifsSesInfo), GFP_KERNEL); if (ret_buf) { - memset(ret_buf, 0, sizeof (struct cifsSesInfo)); write_lock(&GlobalSMBSeslock); atomic_inc(&sesInfoAllocCount); ret_buf->status = CifsNew; @@ -110,10 +109,9 @@ tconInfoAlloc(void) { struct cifsTconInfo *ret_buf; ret_buf = - (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo), + (struct cifsTconInfo *) kzalloc(sizeof (struct cifsTconInfo), GFP_KERNEL); if (ret_buf) { - memset(ret_buf, 0, sizeof (struct cifsTconInfo)); write_lock(&GlobalSMBSeslock); atomic_inc(&tconInfoAllocCount); list_add(&ret_buf->cifsConnectionList, @@ -423,9 +421,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, { __u32 len = smb->smb_buf_length; __u32 clc_len; /* calculated length */ - cFYI(0, - ("Entering checkSMB with Length: %x, smb_buf_length: %x", - length, len)); + cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len)); if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) { @@ -433,29 +429,36 @@ checkSMB(struct smb_hdr *smb, __u16 mid, sizeof (struct smb_hdr) - 1) && (smb->Status.CifsError != 0)) { smb->WordCount = 0; - return 0; /* some error cases do not return wct and bcc */ + /* some error cases do not return wct and bcc */ + return 0; } else { cERROR(1, ("Length less than smb header size")); } - } if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) - cERROR(1, - ("smb_buf_length greater than MaxBufSize")); - cERROR(1, - ("bad smb detected. Illegal length. mid=%d", - smb->Mid)); + cERROR(1, ("smb length greater than MaxBufSize, mid=%d", + smb->Mid)); return 1; } if (checkSMBhdr(smb, mid)) return 1; clc_len = smbCalcSize_LE(smb); - if ((4 + len != clc_len) - || (4 + len != (unsigned int)length)) { - cERROR(1, ("Calculated size 0x%x vs actual length 0x%x", - clc_len, 4 + len)); - cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid)); + + if(4 + len != (unsigned int)length) { + cERROR(1, ("Length read does not match RFC1001 length %d",len)); + return 1; + } + + if (4 + len != clc_len) { + /* check if bcc wrapped around for large read responses */ + if((len > 64 * 1024) && (len > clc_len)) { + /* check if lengths match mod 64K */ + if(((4 + len) & 0xFFFF) == (clc_len & 0xFFFF)) + return 0; /* bcc wrapped */ + } + cFYI(1, ("Calculated size %d vs length %d mismatch for mid %d", + clc_len, 4 + len, smb->Mid)); /* Windows XP can return a few bytes too much, presumably an illegal pad, at the end of byte range lock responses so we allow for that three byte pad, as long as actual @@ -469,8 +472,11 @@ checkSMB(struct smb_hdr *smb, __u16 mid, wct and bcc to minimum size and drop the t2 parms and data */ if((4+len > clc_len) && (len <= clc_len + 512)) return 0; - else + else { + cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d", + len, smb->Mid)); return 1; + } } return 0; } diff --git a/fs/cifs/ntlmssp.c b/fs/cifs/ntlmssp.c new file mode 100644 index 0000000..78866f9 --- /dev/null +++ b/fs/cifs/ntlmssp.c @@ -0,0 +1,129 @@ +/* + * fs/cifs/ntlmssp.h + * + * Copyright (c) International Business Machines Corp., 2006 + * Author(s): Steve French (sfrench@us.ibm.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "cifspdu.h" +#include "cifsglob.h" +#include "cifsproto.h" +#include "cifs_unicode.h" +#include "cifs_debug.h" +#include "ntlmssp.h" +#include "nterr.h" + +#ifdef CONFIG_CIFS_EXPERIMENTAL +static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) +{ + __u32 capabilities = 0; + + /* init fields common to all four types of SessSetup */ + /* note that header is initialized to zero in header_assemble */ + pSMB->req.AndXCommand = 0xFF; + pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); + pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); + + /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ + + /* BB verify whether signing required on neg or just on auth frame + (and NTLM case) */ + + capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | + CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; + + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; + + if (ses->capabilities & CAP_UNICODE) { + pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE; + capabilities |= CAP_UNICODE; + } + if (ses->capabilities & CAP_STATUS32) { + pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS; + capabilities |= CAP_STATUS32; + } + if (ses->capabilities & CAP_DFS) { + pSMB->req.hdr.Flags2 |= SMBFLG2_DFS; + capabilities |= CAP_DFS; + } + + /* BB check whether to init vcnum BB */ + return capabilities; +} +int +CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, const int type, + int * pNTLMv2_flg, const struct nls_table *nls_cp) +{ + int rc = 0; + int wct; + struct smb_hdr *smb_buffer; + char *bcc_ptr; + SESSION_SETUP_ANDX *pSMB; + __u32 capabilities; + + if(ses == NULL) + return -EINVAL; + + cFYI(1,("SStp type: %d",type)); + if(type < CIFS_NTLM) { +#ifndef CONFIG_CIFS_WEAK_PW_HASH + /* LANMAN and plaintext are less secure and off by default. + So we make this explicitly be turned on in kconfig (in the + build) and turned on at runtime (changed from the default) + in proc/fs/cifs or via mount parm. Unfortunately this is + needed for old Win (e.g. Win95), some obscure NAS and OS/2 */ + return -EOPNOTSUPP; +#endif + wct = 10; /* lanman 2 style sessionsetup */ + } else if(type < CIFS_NTLMSSP_NEG) + wct = 13; /* old style NTLM sessionsetup */ + else /* same size for negotiate or auth, NTLMSSP or extended security */ + wct = 12; + + rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses, + (void **)&smb_buffer); + if(rc) + return rc; + + pSMB = (SESSION_SETUP_ANDX *)smb_buffer; + + capabilities = cifs_ssetup_hdr(ses, pSMB); + bcc_ptr = pByteArea(smb_buffer); + if(type > CIFS_NTLM) { + pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; + capabilities |= CAP_EXTENDED_SECURITY; + pSMB->req.Capabilities = cpu_to_le32(capabilities); + /* BB set password lengths */ + } else if(type < CIFS_NTLM) /* lanman */ { + /* no capabilities flags in old lanman negotiation */ + /* pSMB->old_req.PasswordLength = */ /* BB fixme BB */ + } else /* type CIFS_NTLM */ { + pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); + pSMB->req_no_secext.CaseInsensitivePasswordLength = + cpu_to_le16(CIFS_SESSION_KEY_SIZE); + pSMB->req_no_secext.CaseSensitivePasswordLength = + cpu_to_le16(CIFS_SESSION_KEY_SIZE); + } + + +/* rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buf_type, 0); */ + /* SMB request buf freed in SendReceive2 */ + + return rc; +} +#endif /* CONFIG_CIFS_EXPERIMENTAL */ diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h index 803389b..d39b712 100644 --- a/fs/cifs/ntlmssp.h +++ b/fs/cifs/ntlmssp.h @@ -1,7 +1,7 @@ /* * fs/cifs/ntlmssp.h * - * Copyright (c) International Business Machines Corp., 2002 + * Copyright (c) International Business Machines Corp., 2002,2006 * Author(s): Steve French (sfrench@us.ibm.com) * * 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 288cc04..405d4b7 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -604,7 +604,12 @@ static int find_cifs_entry(const int xid cifsFile->search_resume_name = NULL; if(cifsFile->srch_inf.ntwrk_buf_start) { cFYI(1,("freeing SMB ff cache buf on search rewind")); - cifs_buf_release(cifsFile->srch_inf.ntwrk_buf_start); + if(cifsFile->srch_inf.smallBuf) + cifs_small_buf_release(cifsFile->srch_inf. + ntwrk_buf_start); + else + cifs_buf_release(cifsFile->srch_inf. + ntwrk_buf_start); } rc = initiate_cifs_search(xid,file); if(rc) { diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index b12cb8a..3da8040 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -309,17 +309,16 @@ SendReceive2(const unsigned int xid, str *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ - if (ses == NULL) { - cERROR(1,("Null smb session")); - return -EIO; - } - if(ses->server == NULL) { - cERROR(1,("Null tcp session")); + if ((ses == NULL) || (ses->server == NULL)) { + cifs_small_buf_release(in_buf); + cERROR(1,("Null session")); return -EIO; } - if(ses->server->tcpStatus == CifsExiting) + if(ses->server->tcpStatus == CifsExiting) { + cifs_small_buf_release(in_buf); return -ENOENT; + } /* Ensure that we do not send more than 50 overlapping requests to the same server. We may make this configurable later or @@ -346,6 +345,7 @@ SendReceive2(const unsigned int xid, str } else { if(ses->server->tcpStatus == CifsExiting) { spin_unlock(&GlobalMid_Lock); + cifs_small_buf_release(in_buf); return -ENOENT; } @@ -385,6 +385,7 @@ SendReceive2(const unsigned int xid, str midQ = AllocMidQEntry(in_buf, ses); if (midQ == NULL) { up(&ses->server->tcpSem); + cifs_small_buf_release(in_buf); /* If not lock req, update # of requests on wire to server */ if(long_op < 3) { atomic_dec(&ses->server->inFlight); @@ -408,14 +409,18 @@ SendReceive2(const unsigned int xid, str if(rc < 0) { DeleteMidQEntry(midQ); up(&ses->server->tcpSem); + cifs_small_buf_release(in_buf); /* If not lock req, update # of requests on wire to server */ if(long_op < 3) { atomic_dec(&ses->server->inFlight); wake_up(&ses->server->request_q); } return rc; - } else + } else { up(&ses->server->tcpSem); + cifs_small_buf_release(in_buf); + } + if (long_op == -1) goto cifs_no_response_exit2; else if (long_op == 2) /* writes past end of file can take loong time */ @@ -543,6 +548,7 @@ cifs_no_response_exit2: out_unlock2: up(&ses->server->tcpSem); + cifs_small_buf_release(in_buf); /* If not lock req, update # of requests on wire to server */ if(long_op < 3) { atomic_dec(&ses->server->inFlight);