diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 294 |
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 |
42 | static struct { | 43 | static 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 | |||
965 | int | 963 | int |
966 | CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, | 964 | CIFSSMBRead(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 | |||
1052 | int | 1065 | int |
1053 | CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | 1066 | CIFSSMBWrite(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 | ||
1159 | int | 1171 | int |
1160 | CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | 1172 | CIFSSMBWrite2(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 | |||
1239 | int | 1261 | int |
1240 | CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | 1262 | CIFSSMBLock(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 */ | ||
1938 | static int | ||
1939 | smb_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 | |||
1968 | static int | ||
1969 | validate_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 | |||
1909 | int | 2015 | int |
1910 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | 2016 | CIFSSMBQueryReparseLinkInfo(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 */ | ||
2501 | const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}}; | ||
2502 | /* group users */ | ||
2503 | const 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 */ | ||
2506 | static 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 */ | ||
2512 | int | ||
2513 | CIFSSMBGetCIFSACL(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 | } | ||
2575 | qsec_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 */ |
2391 | int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, | 2587 | int 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; |