From 23ba434b017d61f397befe9808fa3214c3964355 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Sep 2004 08:46:47 +0000 Subject: 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) --- source4/smb_server/reply.c | 2 +- source4/smb_server/request.c | 2 +- source4/smb_server/search.c | 160 ++++++++++++++++++++++++++++--------------- source4/smb_server/trans2.c | 4 ++ 4 files changed, 110 insertions(+), 58 deletions(-) (limited to 'source4/smb_server') 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: -- cgit