aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c294
1 files changed, 247 insertions, 47 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 6867e556d37e..217323b0c896 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -37,6 +37,7 @@
37#include "cifsproto.h" 37#include "cifsproto.h"
38#include "cifs_unicode.h" 38#include "cifs_unicode.h"
39#include "cifs_debug.h" 39#include "cifs_debug.h"
40#include "cifsacl.h"
40 41
41#ifdef CONFIG_CIFS_POSIX 42#ifdef CONFIG_CIFS_POSIX
42static struct { 43static struct {
@@ -372,8 +373,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
372 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, 373 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
373 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 374 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
374 if (rc == 0) { 375 if (rc == 0) {
375 server->secMode = pSMBr->SecurityMode; 376 server->secMode = pSMBr->SecurityMode;
376 server->secType = NTLM; /* BB override default for 377 if((server->secMode & SECMODE_USER) == 0)
378 cFYI(1,("share mode security"));
379 server->secType = NTLM; /* BB override default for
377 NTLMv2 or kerberos v5 */ 380 NTLMv2 or kerberos v5 */
378 /* one byte - no need to convert this or EncryptionKeyLen 381 /* one byte - no need to convert this or EncryptionKeyLen
379 from little endian */ 382 from little endian */
@@ -383,7 +386,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
383 min(le32_to_cpu(pSMBr->MaxBufferSize), 386 min(le32_to_cpu(pSMBr->MaxBufferSize),
384 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 387 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
385 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); 388 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
386 cFYI(0, ("Max buf = %d ", ses->server->maxBuf)); 389 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
387 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); 390 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
388 server->capabilities = le32_to_cpu(pSMBr->Capabilities); 391 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
389 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone); 392 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
@@ -411,8 +414,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
411 (server->server_GUID, 414 (server->server_GUID,
412 pSMBr->u.extended_response. 415 pSMBr->u.extended_response.
413 GUID, 16) != 0) { 416 GUID, 16) != 0) {
414 cFYI(1, 417 cFYI(1, ("server UID changed"));
415 ("UID of server does not match previous connection to same ip address"));
416 memcpy(server-> 418 memcpy(server->
417 server_GUID, 419 server_GUID,
418 pSMBr->u. 420 pSMBr->u.
@@ -958,21 +960,19 @@ openRetry:
958 return rc; 960 return rc;
959} 961}
960 962
961/* If no buffer passed in, then caller wants to do the copy
962 as in the case of readpages so the SMB buffer must be
963 freed by the caller */
964
965int 963int
966CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, 964CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
967 const int netfid, const unsigned int count, 965 const int netfid, const unsigned int count,
968 const __u64 lseek, unsigned int *nbytes, char **buf) 966 const __u64 lseek, unsigned int *nbytes, char **buf,
967 int * pbuf_type)
969{ 968{
970 int rc = -EACCES; 969 int rc = -EACCES;
971 READ_REQ *pSMB = NULL; 970 READ_REQ *pSMB = NULL;
972 READ_RSP *pSMBr = NULL; 971 READ_RSP *pSMBr = NULL;
973 char *pReadData = NULL; 972 char *pReadData = NULL;
974 int bytes_returned;
975 int wct; 973 int wct;
974 int resp_buf_type = 0;
975 struct kvec iov[1];
976 976
977 cFYI(1,("Reading %d bytes on fid %d",count,netfid)); 977 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
978 if(tcon->ses->capabilities & CAP_LARGE_FILES) 978 if(tcon->ses->capabilities & CAP_LARGE_FILES)
@@ -981,8 +981,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
981 wct = 10; /* old style read */ 981 wct = 10; /* old style read */
982 982
983 *nbytes = 0; 983 *nbytes = 0;
984 rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB, 984 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
985 (void **) &pSMBr);
986 if (rc) 985 if (rc)
987 return rc; 986 return rc;
988 987
@@ -990,13 +989,13 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
990 if (tcon->ses->server == NULL) 989 if (tcon->ses->server == NULL)
991 return -ECONNABORTED; 990 return -ECONNABORTED;
992 991
993 pSMB->AndXCommand = 0xFF; /* none */ 992 pSMB->AndXCommand = 0xFF; /* none */
994 pSMB->Fid = netfid; 993 pSMB->Fid = netfid;
995 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); 994 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
996 if(wct == 12) 995 if(wct == 12)
997 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); 996 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
998 else if((lseek >> 32) > 0) /* can not handle this big offset for old */ 997 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
999 return -EIO; 998 return -EIO;
1000 999
1001 pSMB->Remaining = 0; 1000 pSMB->Remaining = 0;
1002 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); 1001 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
@@ -1005,14 +1004,18 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1005 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */ 1004 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1006 else { 1005 else {
1007 /* old style read */ 1006 /* old style read */
1008 struct smb_com_readx_req * pSMBW = 1007 struct smb_com_readx_req * pSMBW =
1009 (struct smb_com_readx_req *)pSMB; 1008 (struct smb_com_readx_req *)pSMB;
1010 pSMBW->ByteCount = 0; 1009 pSMBW->ByteCount = 0;
1011 } 1010 }
1012 1011
1013 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1012 iov[0].iov_base = (char *)pSMB;
1014 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1013 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1014 rc = SendReceive2(xid, tcon->ses, iov,
1015 1 /* num iovecs */,
1016 &resp_buf_type, 0);
1015 cifs_stats_inc(&tcon->num_reads); 1017 cifs_stats_inc(&tcon->num_reads);
1018 pSMBr = (READ_RSP *)iov[0].iov_base;
1016 if (rc) { 1019 if (rc) {
1017 cERROR(1, ("Send error in read = %d", rc)); 1020 cERROR(1, ("Send error in read = %d", rc));
1018 } else { 1021 } else {
@@ -1022,33 +1025,43 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1022 *nbytes = data_length; 1025 *nbytes = data_length;
1023 1026
1024 /*check that DataLength would not go beyond end of SMB */ 1027 /*check that DataLength would not go beyond end of SMB */
1025 if ((data_length > CIFSMaxBufSize) 1028 if ((data_length > CIFSMaxBufSize)
1026 || (data_length > count)) { 1029 || (data_length > count)) {
1027 cFYI(1,("bad length %d for count %d",data_length,count)); 1030 cFYI(1,("bad length %d for count %d",data_length,count));
1028 rc = -EIO; 1031 rc = -EIO;
1029 *nbytes = 0; 1032 *nbytes = 0;
1030 } else { 1033 } else {
1031 pReadData = 1034 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1032 (char *) (&pSMBr->hdr.Protocol) +
1033 le16_to_cpu(pSMBr->DataOffset); 1035 le16_to_cpu(pSMBr->DataOffset);
1034/* if(rc = copy_to_user(buf, pReadData, data_length)) { 1036/* if(rc = copy_to_user(buf, pReadData, data_length)) {
1035 cERROR(1,("Faulting on read rc = %d",rc)); 1037 cERROR(1,("Faulting on read rc = %d",rc));
1036 rc = -EFAULT; 1038 rc = -EFAULT;
1037 }*/ /* can not use copy_to_user when using page cache*/ 1039 }*/ /* can not use copy_to_user when using page cache*/
1038 if(*buf) 1040 if(*buf)
1039 memcpy(*buf,pReadData,data_length); 1041 memcpy(*buf,pReadData,data_length);
1040 } 1042 }
1041 } 1043 }
1042 if(*buf)
1043 cifs_buf_release(pSMB);
1044 else
1045 *buf = (char *)pSMB;
1046 1044
1047 /* Note: On -EAGAIN error only caller can retry on handle based calls 1045 cifs_small_buf_release(pSMB);
1046 if(*buf) {
1047 if(resp_buf_type == CIFS_SMALL_BUFFER)
1048 cifs_small_buf_release(iov[0].iov_base);
1049 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1050 cifs_buf_release(iov[0].iov_base);
1051 } else /* return buffer to caller to free */ /* BB FIXME how do we tell caller if it is not a large buffer */ {
1052 *buf = iov[0].iov_base;
1053 if(resp_buf_type == CIFS_SMALL_BUFFER)
1054 *pbuf_type = CIFS_SMALL_BUFFER;
1055 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1056 *pbuf_type = CIFS_LARGE_BUFFER;
1057 }
1058
1059 /* Note: On -EAGAIN error only caller can retry on handle based calls
1048 since file handle passed in no longer valid */ 1060 since file handle passed in no longer valid */
1049 return rc; 1061 return rc;
1050} 1062}
1051 1063
1064
1052int 1065int
1053CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, 1066CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1054 const int netfid, const unsigned int count, 1067 const int netfid, const unsigned int count,
@@ -1155,7 +1168,6 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1155 return rc; 1168 return rc;
1156} 1169}
1157 1170
1158#ifdef CONFIG_CIFS_EXPERIMENTAL
1159int 1171int
1160CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 1172CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1161 const int netfid, const unsigned int count, 1173 const int netfid, const unsigned int count,
@@ -1164,10 +1176,10 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1164{ 1176{
1165 int rc = -EACCES; 1177 int rc = -EACCES;
1166 WRITE_REQ *pSMB = NULL; 1178 WRITE_REQ *pSMB = NULL;
1167 int bytes_returned, wct; 1179 int wct;
1168 int smb_hdr_len; 1180 int smb_hdr_len;
1181 int resp_buf_type = 0;
1169 1182
1170 /* BB removeme BB */
1171 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count)); 1183 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1172 1184
1173 if(tcon->ses->capabilities & CAP_LARGE_FILES) 1185 if(tcon->ses->capabilities & CAP_LARGE_FILES)
@@ -1210,22 +1222,34 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1210 pSMBW->ByteCount = cpu_to_le16(count + 5); 1222 pSMBW->ByteCount = cpu_to_le16(count + 5);
1211 } 1223 }
1212 iov[0].iov_base = pSMB; 1224 iov[0].iov_base = pSMB;
1213 iov[0].iov_len = smb_hdr_len + 4; 1225 if(wct == 14)
1226 iov[0].iov_len = smb_hdr_len + 4;
1227 else /* wct == 12 pad bigger by four bytes */
1228 iov[0].iov_len = smb_hdr_len + 8;
1229
1214 1230
1215 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &bytes_returned, 1231 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1216 long_op); 1232 long_op);
1217 cifs_stats_inc(&tcon->num_writes); 1233 cifs_stats_inc(&tcon->num_writes);
1218 if (rc) { 1234 if (rc) {
1219 cFYI(1, ("Send error Write2 = %d", rc)); 1235 cFYI(1, ("Send error Write2 = %d", rc));
1220 *nbytes = 0; 1236 *nbytes = 0;
1237 } else if(resp_buf_type == 0) {
1238 /* presumably this can not happen, but best to be safe */
1239 rc = -EIO;
1240 *nbytes = 0;
1221 } else { 1241 } else {
1222 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB; 1242 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1223 *nbytes = le16_to_cpu(pSMBr->CountHigh); 1243 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1224 *nbytes = (*nbytes) << 16; 1244 *nbytes = (*nbytes) << 16;
1225 *nbytes += le16_to_cpu(pSMBr->Count); 1245 *nbytes += le16_to_cpu(pSMBr->Count);
1226 } 1246 }
1227 1247
1228 cifs_small_buf_release(pSMB); 1248 cifs_small_buf_release(pSMB);
1249 if(resp_buf_type == CIFS_SMALL_BUFFER)
1250 cifs_small_buf_release(iov[0].iov_base);
1251 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1252 cifs_buf_release(iov[0].iov_base);
1229 1253
1230 /* Note: On -EAGAIN error only caller can retry on handle based calls 1254 /* Note: On -EAGAIN error only caller can retry on handle based calls
1231 since file handle passed in no longer valid */ 1255 since file handle passed in no longer valid */
@@ -1234,8 +1258,6 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1234} 1258}
1235 1259
1236 1260
1237#endif /* CIFS_EXPERIMENTAL */
1238
1239int 1261int
1240CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, 1262CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1241 const __u16 smb_file_id, const __u64 len, 1263 const __u16 smb_file_id, const __u64 len,
@@ -1906,6 +1928,90 @@ querySymLinkRetry:
1906 return rc; 1928 return rc;
1907} 1929}
1908 1930
1931/* Initialize NT TRANSACT SMB into small smb request buffer.
1932 This assumes that all NT TRANSACTS that we init here have
1933 total parm and data under about 400 bytes (to fit in small cifs
1934 buffer size), which is the case so far, it easily fits. NB:
1935 Setup words themselves and ByteCount
1936 MaxSetupCount (size of returned setup area) and
1937 MaxParameterCount (returned parms size) must be set by caller */
1938static int
1939smb_init_ntransact(const __u16 sub_command, const int setup_count,
1940 const int parm_len, struct cifsTconInfo *tcon,
1941 void ** ret_buf)
1942{
1943 int rc;
1944 __u32 temp_offset;
1945 struct smb_com_ntransact_req * pSMB;
1946
1947 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
1948 (void **)&pSMB);
1949 if (rc)
1950 return rc;
1951 *ret_buf = (void *)pSMB;
1952 pSMB->Reserved = 0;
1953 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
1954 pSMB->TotalDataCount = 0;
1955 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
1956 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1957 pSMB->ParameterCount = pSMB->TotalParameterCount;
1958 pSMB->DataCount = pSMB->TotalDataCount;
1959 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
1960 (setup_count * 2) - 4 /* for rfc1001 length itself */;
1961 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
1962 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
1963 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
1964 pSMB->SubCommand = cpu_to_le16(sub_command);
1965 return 0;
1966}
1967
1968static int
1969validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
1970 int * pdatalen, int * pparmlen)
1971{
1972 char * end_of_smb;
1973 __u32 data_count, data_offset, parm_count, parm_offset;
1974 struct smb_com_ntransact_rsp * pSMBr;
1975
1976 if(buf == NULL)
1977 return -EINVAL;
1978
1979 pSMBr = (struct smb_com_ntransact_rsp *)buf;
1980
1981 /* ByteCount was converted from little endian in SendReceive */
1982 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
1983 (char *)&pSMBr->ByteCount;
1984
1985
1986 data_offset = le32_to_cpu(pSMBr->DataOffset);
1987 data_count = le32_to_cpu(pSMBr->DataCount);
1988 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
1989 parm_count = le32_to_cpu(pSMBr->ParameterCount);
1990
1991 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
1992 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
1993
1994 /* should we also check that parm and data areas do not overlap? */
1995 if(*ppparm > end_of_smb) {
1996 cFYI(1,("parms start after end of smb"));
1997 return -EINVAL;
1998 } else if(parm_count + *ppparm > end_of_smb) {
1999 cFYI(1,("parm end after end of smb"));
2000 return -EINVAL;
2001 } else if(*ppdata > end_of_smb) {
2002 cFYI(1,("data starts after end of smb"));
2003 return -EINVAL;
2004 } else if(data_count + *ppdata > end_of_smb) {
2005 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2006 *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
2007 return -EINVAL;
2008 } else if(parm_count + data_count > pSMBr->ByteCount) {
2009 cFYI(1,("parm count and data count larger than SMB"));
2010 return -EINVAL;
2011 }
2012 return 0;
2013}
2014
1909int 2015int
1910CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, 2016CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1911 const unsigned char *searchName, 2017 const unsigned char *searchName,
@@ -1928,7 +2034,8 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1928 pSMB->TotalDataCount = 0; 2034 pSMB->TotalDataCount = 0;
1929 pSMB->MaxParameterCount = cpu_to_le32(2); 2035 pSMB->MaxParameterCount = cpu_to_le32(2);
1930 /* BB find exact data count max from sess structure BB */ 2036 /* BB find exact data count max from sess structure BB */
1931 pSMB->MaxDataCount = cpu_to_le32(4000); 2037 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2038 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1932 pSMB->MaxSetupCount = 4; 2039 pSMB->MaxSetupCount = 4;
1933 pSMB->Reserved = 0; 2040 pSMB->Reserved = 0;
1934 pSMB->ParameterOffset = 0; 2041 pSMB->ParameterOffset = 0;
@@ -1955,7 +2062,9 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1955 rc = -EIO; /* bad smb */ 2062 rc = -EIO; /* bad smb */
1956 else { 2063 else {
1957 if(data_count && (data_count < 2048)) { 2064 if(data_count && (data_count < 2048)) {
1958 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount; 2065 char * end_of_smb = 2 /* sizeof byte count */ +
2066 pSMBr->ByteCount +
2067 (char *)&pSMBr->ByteCount;
1959 2068
1960 struct reparse_data * reparse_buf = (struct reparse_data *) 2069 struct reparse_data * reparse_buf = (struct reparse_data *)
1961 ((char *)&pSMBr->hdr.Protocol + data_offset); 2070 ((char *)&pSMBr->hdr.Protocol + data_offset);
@@ -2199,6 +2308,7 @@ queryAclRetry:
2199 2308
2200 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 2309 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2201 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 2310 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2311 cifs_stats_inc(&tcon->num_acl_get);
2202 if (rc) { 2312 if (rc) {
2203 cFYI(1, ("Send error in Query POSIX ACL = %d", rc)); 2313 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2204 } else { 2314 } else {
@@ -2386,6 +2496,92 @@ GetExtAttrOut:
2386 2496
2387#endif /* CONFIG_POSIX */ 2497#endif /* CONFIG_POSIX */
2388 2498
2499
2500/* security id for everyone */
2501const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2502/* group users */
2503const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2504
2505/* Convert CIFS ACL to POSIX form */
2506static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
2507{
2508 return 0;
2509}
2510
2511/* Get Security Descriptor (by handle) from remote server for a file or dir */
2512int
2513CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
2514 /* BB fix up return info */ char *acl_inf, const int buflen,
2515 const int acl_type /* ACCESS/DEFAULT not sure implication */)
2516{
2517 int rc = 0;
2518 int buf_type = 0;
2519 QUERY_SEC_DESC_REQ * pSMB;
2520 struct kvec iov[1];
2521
2522 cFYI(1, ("GetCifsACL"));
2523
2524 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
2525 8 /* parm len */, tcon, (void **) &pSMB);
2526 if (rc)
2527 return rc;
2528
2529 pSMB->MaxParameterCount = cpu_to_le32(4);
2530 /* BB TEST with big acls that might need to be e.g. larger than 16K */
2531 pSMB->MaxSetupCount = 0;
2532 pSMB->Fid = fid; /* file handle always le */
2533 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
2534 CIFS_ACL_DACL);
2535 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
2536 pSMB->hdr.smb_buf_length += 11;
2537 iov[0].iov_base = (char *)pSMB;
2538 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
2539
2540 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
2541 cifs_stats_inc(&tcon->num_acl_get);
2542 if (rc) {
2543 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
2544 } else { /* decode response */
2545 struct cifs_sid * psec_desc;
2546 __le32 * parm;
2547 int parm_len;
2548 int data_len;
2549 int acl_len;
2550 struct smb_com_ntransact_rsp * pSMBr;
2551
2552/* validate_nttransact */
2553 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
2554 (char **)&psec_desc,
2555 &parm_len, &data_len);
2556
2557 if(rc)
2558 goto qsec_out;
2559 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
2560
2561 cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
2562
2563 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
2564 rc = -EIO; /* bad smb */
2565 goto qsec_out;
2566 }
2567
2568/* BB check that data area is minimum length and as big as acl_len */
2569
2570 acl_len = le32_to_cpu(*(__le32 *)parm);
2571 /* BB check if(acl_len > bufsize) */
2572
2573 parse_sec_desc(psec_desc, acl_len);
2574 }
2575qsec_out:
2576 if(buf_type == CIFS_SMALL_BUFFER)
2577 cifs_small_buf_release(iov[0].iov_base);
2578 else if(buf_type == CIFS_LARGE_BUFFER)
2579 cifs_buf_release(iov[0].iov_base);
2580 cifs_small_buf_release(pSMB);
2581 return rc;
2582}
2583
2584
2389/* Legacy Query Path Information call for lookup to old servers such 2585/* Legacy Query Path Information call for lookup to old servers such
2390 as Win9x/WinME */ 2586 as Win9x/WinME */
2391int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, 2587int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
@@ -4284,7 +4480,7 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4284{ 4480{
4285 int rc = 0; 4481 int rc = 0;
4286 struct smb_com_transaction_change_notify_req * pSMB = NULL; 4482 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4287 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL; 4483 struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
4288 struct dir_notify_req *dnotify_req; 4484 struct dir_notify_req *dnotify_req;
4289 int bytes_returned; 4485 int bytes_returned;
4290 4486
@@ -4299,6 +4495,10 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4299 pSMB->MaxParameterCount = cpu_to_le32(2); 4495 pSMB->MaxParameterCount = cpu_to_le32(2);
4300 /* BB find exact data count max from sess structure BB */ 4496 /* BB find exact data count max from sess structure BB */
4301 pSMB->MaxDataCount = 0; /* same in little endian or be */ 4497 pSMB->MaxDataCount = 0; /* same in little endian or be */
4498/* BB VERIFY verify which is correct for above BB */
4499 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
4500 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
4501
4302 pSMB->MaxSetupCount = 4; 4502 pSMB->MaxSetupCount = 4;
4303 pSMB->Reserved = 0; 4503 pSMB->Reserved = 0;
4304 pSMB->ParameterOffset = 0; 4504 pSMB->ParameterOffset = 0;