summaryrefslogtreecommitdiff
path: root/source4/smb_server/search.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/smb_server/search.c')
-rw-r--r--source4/smb_server/search.c160
1 files changed, 104 insertions, 56 deletions
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;
}