• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source4/smb_server/smb/
1/*
2   Unix SMB/CIFS implementation.
3   SMBsearch handling
4   Copyright (C) Andrew Tridgell 2003
5   Copyright (C) James J Myers 2003 <myersjj@samba.org>
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 3 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program.  If not, see <http://www.gnu.org/licenses/>.
19*/
20/*
21   This file handles the parsing of transact2 requests
22*/
23
24#include "includes.h"
25#include "smb_server/smb_server.h"
26#include "ntvfs/ntvfs.h"
27
28
29/* a structure to encapsulate the state information about
30 * an in-progress search first/next operation */
31struct search_state {
32	struct smbsrv_request *req;
33	union smb_search_data *file;
34	uint16_t last_entry_offset;
35};
36
37/*
38  fill a single entry in a search find reply
39*/
40static bool find_fill_info(struct smbsrv_request *req,
41			   const union smb_search_data *file)
42{
43	uint8_t *p;
44
45	if (req->out.data_size + 43 > req_max_data(req)) {
46		return false;
47	}
48
49	req_grow_data(req, req->out.data_size + 43);
50	p = req->out.data + req->out.data_size - 43;
51
52	SCVAL(p,  0, file->search.id.reserved);
53	memcpy(p+1, file->search.id.name, 11);
54	SCVAL(p, 12, file->search.id.handle);
55	SIVAL(p, 13, file->search.id.server_cookie);
56	SIVAL(p, 17, file->search.id.client_cookie);
57	SCVAL(p, 21, file->search.attrib);
58	srv_push_dos_date(req->smb_conn, p, 22, file->search.write_time);
59	SIVAL(p, 26, file->search.size);
60	memset(p+30, ' ', 12);
61	memcpy(p+30, file->search.name, MIN(strlen(file->search.name)+1, 12));
62	SCVAL(p,42,0);
63
64	return true;
65}
66
67/* callback function for search first/next */
68static bool find_callback(void *private_data, const union smb_search_data *file)
69{
70	struct search_state *state = (struct search_state *)private_data;
71
72	return find_fill_info(state->req, file);
73}
74
75/****************************************************************************
76 Reply to a search first (async reply)
77****************************************************************************/
78static void reply_search_first_send(struct ntvfs_request *ntvfs)
79{
80	struct smbsrv_request *req;
81	union smb_search_first *sf;
82
83	SMBSRV_CHECK_ASYNC_STATUS(sf, union smb_search_first);
84
85	SSVAL(req->out.vwv, VWV(0), sf->search_first.out.count);
86
87	smbsrv_send_reply(req);
88}
89
90/****************************************************************************
91 Reply to a search next (async reply)
92****************************************************************************/
93static void reply_search_next_send(struct ntvfs_request *ntvfs)
94{
95	struct smbsrv_request *req;
96	union smb_search_next *sn;
97
98	SMBSRV_CHECK_ASYNC_STATUS(sn, union smb_search_next);
99
100	SSVAL(req->out.vwv, VWV(0), sn->search_next.out.count);
101
102	smbsrv_send_reply(req);
103}
104
105/****************************************************************************
106 Reply to a search.
107****************************************************************************/
108void smbsrv_reply_search(struct smbsrv_request *req)
109{
110	union smb_search_first *sf;
111	uint16_t resume_key_length;
112	struct search_state *state;
113	uint8_t *p;
114	enum smb_search_level level = RAW_SEARCH_SEARCH;
115	uint8_t op = CVAL(req->in.hdr,HDR_COM);
116
117	if (op == SMBffirst) {
118		level = RAW_SEARCH_FFIRST;
119	} else if (op == SMBfunique) {
120		level = RAW_SEARCH_FUNIQUE;
121	}
122
123	/* parse request */
124	if (req->in.wct != 2) {
125		smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
126		return;
127	}
128
129	SMBSRV_TALLOC_IO_PTR(sf, union smb_search_first);
130
131	p = req->in.data;
132	p += req_pull_ascii4(&req->in.bufinfo, &sf->search_first.in.pattern,
133			     p, STR_TERMINATE);
134	if (!sf->search_first.in.pattern) {
135		smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
136		return;
137	}
138
139	if (req_data_oob(&req->in.bufinfo, p, 3)) {
140		smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
141		return;
142	}
143	if (*p != 5) {
144		smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
145		return;
146	}
147	resume_key_length = SVAL(p, 1);
148	p += 3;
149
150	/* setup state for callback */
151	state = talloc(req, struct search_state);
152	if (!state) {
153		smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
154		return;
155	}
156
157	state->req = req;
158	state->file = NULL;
159	state->last_entry_offset = 0;
160
161	/* construct reply */
162	smbsrv_setup_reply(req, 1, 0);
163	SSVAL(req->out.vwv, VWV(0), 0);
164	req_append_var_block(req, NULL, 0);
165
166	if (resume_key_length != 0) {
167		union smb_search_next *sn;
168
169		if (resume_key_length != 21 ||
170		    req_data_oob(&req->in.bufinfo, p, 21) ||
171		    level == RAW_SEARCH_FUNIQUE) {
172			smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
173			return;
174		}
175
176		/* do a search next operation */
177		SMBSRV_TALLOC_IO_PTR(sn, union smb_search_next);
178		SMBSRV_SETUP_NTVFS_REQUEST(reply_search_next_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
179
180		sn->search_next.in.id.reserved      = CVAL(p, 0);
181		memcpy(sn->search_next.in.id.name,    p+1, 11);
182		sn->search_next.in.id.handle        = CVAL(p, 12);
183		sn->search_next.in.id.server_cookie = IVAL(p, 13);
184		sn->search_next.in.id.client_cookie = IVAL(p, 17);
185
186		sn->search_next.level = level;
187		sn->search_next.data_level = RAW_SEARCH_DATA_SEARCH;
188		sn->search_next.in.max_count     = SVAL(req->in.vwv, VWV(0));
189		sn->search_next.in.search_attrib = SVAL(req->in.vwv, VWV(1));
190
191		/* call backend */
192		SMBSRV_CALL_NTVFS_BACKEND(ntvfs_search_next(req->ntvfs, sn, state, find_callback));
193	} else {
194		SMBSRV_SETUP_NTVFS_REQUEST(reply_search_first_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
195
196		/* do a search first operation */
197		sf->search_first.level = level;
198		sf->search_first.data_level = RAW_SEARCH_DATA_SEARCH;
199		sf->search_first.in.search_attrib = SVAL(req->in.vwv, VWV(1));
200		sf->search_first.in.max_count     = SVAL(req->in.vwv, VWV(0));
201
202		SMBSRV_CALL_NTVFS_BACKEND(ntvfs_search_first(req->ntvfs, sf, state, find_callback));
203	}
204}
205
206
207/****************************************************************************
208 Reply to a fclose (async reply)
209****************************************************************************/
210static void reply_fclose_send(struct ntvfs_request *ntvfs)
211{
212	struct smbsrv_request *req;
213
214	SMBSRV_CHECK_ASYNC_STATUS_SIMPLE;
215
216	/* construct reply */
217	smbsrv_setup_reply(req, 1, 0);
218
219	SSVAL(req->out.vwv, VWV(0), 0);
220
221	smbsrv_send_reply(req);
222}
223
224
225/****************************************************************************
226 Reply to fclose (stop directory search).
227****************************************************************************/
228void smbsrv_reply_fclose(struct smbsrv_request *req)
229{
230	union smb_search_close *sc;
231	uint16_t resume_key_length;
232	uint8_t *p;
233	const char *pattern;
234
235	/* parse request */
236	if (req->in.wct != 2) {
237		smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
238		return;
239	}
240
241	SMBSRV_TALLOC_IO_PTR(sc, union smb_search_close);
242	SMBSRV_SETUP_NTVFS_REQUEST(reply_fclose_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
243
244	p = req->in.data;
245	p += req_pull_ascii4(&req->in.bufinfo, &pattern, p, STR_TERMINATE);
246	if (pattern && *pattern) {
247		smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
248		return;
249	}
250
251	if (req_data_oob(&req->in.bufinfo, p, 3)) {
252		smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
253		return;
254	}
255	if (*p != 5) {
256		smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
257		return;
258	}
259	resume_key_length = SVAL(p, 1);
260	p += 3;
261
262	if (resume_key_length != 21) {
263		smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
264		return;
265	}
266
267	if (req_data_oob(&req->in.bufinfo, p, 21)) {
268		smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
269		return;
270	}
271
272	sc->fclose.level               = RAW_FINDCLOSE_FCLOSE;
273	sc->fclose.in.max_count        = SVAL(req->in.vwv, VWV(0));
274	sc->fclose.in.search_attrib    = SVAL(req->in.vwv, VWV(1));
275	sc->fclose.in.id.reserved      = CVAL(p, 0);
276	memcpy(sc->fclose.in.id.name,    p+1, 11);
277	sc->fclose.in.id.handle        = CVAL(p, 12);
278	sc->fclose.in.id.server_cookie = IVAL(p, 13);
279	sc->fclose.in.id.client_cookie = IVAL(p, 17);
280
281	SMBSRV_CALL_NTVFS_BACKEND(ntvfs_search_close(req->ntvfs, sc));
282
283}
284