summaryrefslogtreecommitdiff
path: root/source4/smb_server
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-09-21 08:46:47 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:58:56 -0500
commit23ba434b017d61f397befe9808fa3214c3964355 (patch)
tree6b44688395804faba93febbcd0411c221481b98f /source4/smb_server
parentd9e43bc8834d797a2f5a7d39342f4083a3bc8239 (diff)
downloadsamba-23ba434b017d61f397befe9808fa3214c3964355.tar.gz
samba-23ba434b017d61f397befe9808fa3214c3964355.tar.bz2
samba-23ba434b017d61f397befe9808fa3214c3964355.zip
r2469: complete overhaul of the old-style RAW_SEARCH_ calls (the OS/2 and
original core level calls). The old code was completely wrong in many respects. also fixed the EA_SIZE level in the server extended the RAW-SEARCH test suite to test the new code properly (This used to be commit 71480271ad84b57fcdde264a54bb2408cf783255)
Diffstat (limited to 'source4/smb_server')
-rw-r--r--source4/smb_server/reply.c2
-rw-r--r--source4/smb_server/request.c2
-rw-r--r--source4/smb_server/search.c160
-rw-r--r--source4/smb_server/trans2.c4
4 files changed, 110 insertions, 58 deletions
diff --git a/source4/smb_server/reply.c b/source4/smb_server/reply.c
index 5827d64bcd..a1922d54c1 100644
--- a/source4/smb_server/reply.c
+++ b/source4/smb_server/reply.c
@@ -2136,7 +2136,7 @@ void reply_findclose(struct smbsrv_request *req)
NTSTATUS status;
union smb_search_close io;
- io.findclose.level = RAW_FINDCLOSE_CLOSE;
+ io.findclose.level = RAW_FINDCLOSE_FINDCLOSE;
/* parse request */
REQ_CHECK_WCT(req, 1);
diff --git a/source4/smb_server/request.c b/source4/smb_server/request.c
index 80663b9ccc..07b2ee0575 100644
--- a/source4/smb_server/request.c
+++ b/source4/smb_server/request.c
@@ -395,7 +395,7 @@ size_t req_push_str(struct smbsrv_request *req, char *dest, const char *str, int
return the number of bytes added
*/
size_t req_append_bytes(struct smbsrv_request *req,
- const uint8_t *bytes, size_t byte_len)
+ const uint8_t *bytes, size_t byte_len)
{
req_grow_allocation(req, byte_len + req->out.data_size);
memcpy(req->out.data + req->out.data_size, bytes, byte_len);
diff --git a/source4/smb_server/search.c b/source4/smb_server/search.c
index e18ecda887..a99958d6c6 100644
--- a/source4/smb_server/search.c
+++ b/source4/smb_server/search.c
@@ -42,8 +42,8 @@
}} while (0)
/* useful wrapper for talloc with NO_MEMORY reply */
-#define REQ_TALLOC(ptr, size) do { \
- ptr = talloc(req, size); \
+#define REQ_TALLOC(ptr) do { \
+ ptr = talloc(req, sizeof(*(ptr))); \
if (!ptr) { \
req_reply_error(req, NT_STATUS_NO_MEMORY); \
return; \
@@ -68,23 +68,21 @@ struct search_state {
static void find_fill_info(struct smbsrv_request *req,
union smb_search_data *file)
{
- char *p = req->out.data + req->out.data_size;
- uint32_t dos_date;
- char search_name[13];
+ char *p;
- DEBUG(9,("find_fill_info: input file data: attr=0x%x size=%u time=0x%x name=%13s\n",
- file->search.attrib, file->search.size,
- (uint32_t)file->search.write_time, file->search.name));
-
- p += req_append_bytes(req, file->search.search_id.data, 21);
- p += req_append_bytes(req, (char*)&file->search.attrib, 1);
- srv_push_dos_date(req->smb_conn, (uint8_t *)&dos_date, 0, file->search.write_time);
- p += req_append_bytes(req, (char*)&dos_date, 4);
- p += req_append_bytes(req, (char*)&file->search.size, 4);
- memset(&search_name[0], ' ', 13);
- memcpy(&search_name[0], file->search.name,
- MAX(13, strlen(file->search.name)));
- p += req_append_bytes(req, &search_name[0], 13);
+ req_grow_data(req, req->out.data_size + 43);
+ p = req->out.data + req->out.data_size - 43;
+
+ SCVAL(p, 0, file->search.id.reserved);
+ memcpy(p+1, file->search.id.name, 11);
+ SCVAL(p, 12, file->search.id.handle);
+ SIVAL(p, 13, file->search.id.server_cookie);
+ SIVAL(p, 17, file->search.id.client_cookie);
+ SCVAL(p, 21, file->search.attrib);
+ srv_push_dos_date(req->smb_conn, p, 22, file->search.write_time);
+ SIVAL(p, 26, file->search.size);
+ memset(p+30, ' ', 13);
+ memcpy(p+30, file->search.name, MIN(strlen(file->search.name)+1, 13));
}
/* callback function for search first/next */
@@ -104,12 +102,20 @@ void reply_search(struct smbsrv_request *req)
{
union smb_search_first *sf;
union smb_search_next *sn;
- DATA_BLOB resume_key;
uint16_t resume_key_length;
struct search_state state;
char *p;
+ NTSTATUS status;
+ enum smb_search_level level = RAW_SEARCH_SEARCH;
+ uint8_t op = CVAL(req->in.hdr,HDR_COM);
+
+ if (op == SMBffirst) {
+ level = RAW_SEARCH_FFIRST;
+ } else if (op == SMBfunique) {
+ level = RAW_SEARCH_FUNIQUE;
+ }
- REQ_TALLOC(sf, sizeof(*sf));
+ REQ_TALLOC(sf);
/* parse request */
if (req->in.wct != 2) {
@@ -119,18 +125,22 @@ void reply_search(struct smbsrv_request *req)
p = req->in.data;
p += req_pull_ascii4(req, &sf->search_first.in.pattern,
- p, STR_TERMINATE);
+ p, STR_TERMINATE);
if (!sf->search_first.in.pattern) {
req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
return;
}
- /* pull in type 5 byte and length */
- if (!req_pull_blob(req, p, 3, &resume_key))
+
+ if (req_data_oob(req, p, 3)) {
req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
- resume_key_length = SVAL(resume_key.data, 1);
+ return;
+ }
+ if (*p != 5) {
+ req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+ resume_key_length = SVAL(p, 1);
p += 3;
- DEBUG(19,("reply_search: pattern=%s, key_length=%d\n",
- sf->search_first.in.pattern, resume_key_length));
/* setup state for callback */
state.req = req;
@@ -141,34 +151,46 @@ void reply_search(struct smbsrv_request *req)
req_setup_reply(req, 1, 0);
req_append_var_block(req, NULL, 0);
- if (resume_key_length > 0) {
- /* do a search next operation */
- REQ_TALLOC(sn, sizeof(*sn));
- sn->search_next.level = RAW_SEARCH_SEARCH;
- req->async.private = sn;
- if (!req_pull_blob(req, req->in.data, resume_key_length,
- &(sn->search_next.in.search_id)))
+ if (resume_key_length != 0) {
+ if (resume_key_length != 21 ||
+ req_data_oob(req, p, 21) ||
+ level == RAW_SEARCH_FUNIQUE) {
req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
- sn->search_next.in.search_attrib = SVAL(req->in.vwv, VWV(1));
+ return;
+ }
+
+ /* do a search next operation */
+ REQ_TALLOC(sn);
+
+ sn->search_next.in.id.reserved = CVAL(p, 0);
+ memcpy(sn->search_next.in.id.name, p+1, 11);
+ sn->search_next.in.id.handle = CVAL(p, 12);
+ sn->search_next.in.id.server_cookie = IVAL(p, 13);
+ sn->search_next.in.id.client_cookie = IVAL(p, 17);
+
+ sn->search_next.level = level;
sn->search_next.in.max_count = SVAL(req->in.vwv, VWV(0));
+ sn->search_next.in.search_attrib = SVAL(req->in.vwv, VWV(1));
/* call backend */
- req->async.status = req->tcon->ntvfs_ops->search_next(req,
- sn, &state, find_callback);
+ status = req->tcon->ntvfs_ops->search_next(req, sn, &state, find_callback);
SSVAL(req->out.vwv, VWV(0), sn->search_next.out.count);
} else {
/* do a search first operation */
- req->async.private = sf;
- sf->search_first.level = RAW_SEARCH_SEARCH;
+ sf->search_first.level = level;
sf->search_first.in.search_attrib = SVAL(req->in.vwv, VWV(1));
sf->search_first.in.max_count = SVAL(req->in.vwv, VWV(0));
/* call backend */
- req->async.status = req->tcon->ntvfs_ops->search_first(req,
- sf, &state, find_callback);
+ status = req->tcon->ntvfs_ops->search_first(req, sf, &state, find_callback);
SSVAL(req->out.vwv, VWV(0), sf->search_first.out.count);
}
+ if (!NT_STATUS_IS_OK(status)) {
+ req_reply_error(req, status);
+ return;
+ }
+
req_send_reply(req);
}
@@ -183,6 +205,8 @@ static void reply_fclose_send(struct smbsrv_request *req)
/* construct reply */
req_setup_reply(req, 1, 0);
+ SSVAL(req->out.vwv, VWV(0), 0);
+
req_send_reply(req);
}
@@ -192,11 +216,12 @@ static void reply_fclose_send(struct smbsrv_request *req)
****************************************************************************/
void reply_fclose(struct smbsrv_request *req)
{
- union smb_search_next *sn;
- DATA_BLOB resume_key;
+ union smb_search_close *sc;
uint16_t resume_key_length;
+ char *p;
+ const char *pattern;
- REQ_TALLOC(sn, sizeof(*sn));
+ REQ_TALLOC(sc);
/* parse request */
if (req->in.wct != 2) {
@@ -204,26 +229,49 @@ void reply_fclose(struct smbsrv_request *req)
return;
}
- sn->search_next.level = RAW_SEARCH_FCLOSE;
+ p = req->in.data;
+ p += req_pull_ascii4(req, &pattern, p, STR_TERMINATE);
+ if (pattern && *pattern) {
+ req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
- /* pull in type 5 byte and length */
- if (!req_pull_blob(req, req->in.data, 3, &resume_key))
+ if (req_data_oob(req, p, 3)) {
req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
- resume_key_length = SVAL(resume_key.data, 1);
- if (resume_key_length > 0) {
- /* do a search close operation */
- if (!req_pull_blob(req, req->in.data, resume_key_length,
- &(sn->search_next.in.search_id)))
- req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
- } else
+ return;
+ }
+ if (*p != 5) {
req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+ resume_key_length = SVAL(p, 1);
+ p += 3;
+
+ if (resume_key_length != 21) {
+ req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+
+ if (req_data_oob(req, p, 21)) {
+ req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+
+ sc->fclose.level = RAW_FINDCLOSE_FCLOSE;
+ sc->fclose.in.max_count = SVAL(req->in.vwv, VWV(0));
+ sc->fclose.in.search_attrib = SVAL(req->in.vwv, VWV(1));
+ sc->fclose.in.id.reserved = CVAL(p, 0);
+ memcpy(sc->fclose.in.id.name, p+1, 11);
+ sc->fclose.in.id.handle = CVAL(p, 12);
+ sc->fclose.in.id.server_cookie = IVAL(p, 13);
+ sc->fclose.in.id.client_cookie = IVAL(p, 17);
+ /* do a search close operation */
req->async.send_fn = reply_fclose_send;
- req->async.private = sn;
+ req->async.private = sc;
/* call backend */
- req->async.status = req->tcon->ntvfs_ops->search_next(req, sn,
- NULL, NULL);
+ req->async.status = req->tcon->ntvfs_ops->search_close(req, sc);
REQ_ASYNC_TAIL;
}
diff --git a/source4/smb_server/trans2.c b/source4/smb_server/trans2.c
index 57a385fe27..6e02ddc90d 100644
--- a/source4/smb_server/trans2.c
+++ b/source4/smb_server/trans2.c
@@ -885,6 +885,8 @@ static void find_fill_info(struct smbsrv_request *req,
switch (state->level) {
case RAW_SEARCH_SEARCH:
+ case RAW_SEARCH_FFIRST:
+ case RAW_SEARCH_FUNIQUE:
case RAW_SEARCH_GENERIC:
/* handled elsewhere */
break;
@@ -926,6 +928,8 @@ static void find_fill_info(struct smbsrv_request *req,
SIVAL(data, 22, file->ea_size.ea_size);
trans2_append_data_string(req, trans, &file->ea_size.name,
ofs + 26, STR_LEN8BIT | STR_NOALIGN);
+ trans2_grow_data(req, trans, trans->out.data.length + 1);
+ trans->out.data.data[trans->out.data.length-1] = 0;
break;
case RAW_SEARCH_DIRECTORY_INFO: