• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.5.8/source4/libcli/smb_composite/
1/*
2   Unix SMB/CIFS implementation.
3
4   Copyright (C) Andrew Tridgell 2008
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 3 of the License, or
9   (at your option) any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18*/
19/*
20  a composite API for making SMB-like calls using SMB2. This is useful
21  as SMB2 often requires more than one requests where a single SMB
22  request would do. In converting code that uses SMB to use SMB2,
23  these routines make life a lot easier
24*/
25
26
27#include "includes.h"
28#include "libcli/raw/libcliraw.h"
29#include "libcli/raw/raw_proto.h"
30#include "libcli/composite/composite.h"
31#include "libcli/smb_composite/smb_composite.h"
32#include "libcli/smb2/smb2_calls.h"
33
34/*
35  continue after a SMB2 close
36 */
37static void continue_close(struct smb2_request *req)
38{
39	struct composite_context *ctx = talloc_get_type(req->async.private_data,
40							struct composite_context);
41	NTSTATUS status;
42	struct smb2_close close_parm;
43
44	status = smb2_close_recv(req, &close_parm);
45	composite_error(ctx, status);
46}
47
48/*
49  continue after the create in a composite unlink
50 */
51static void continue_unlink(struct smb2_request *req)
52{
53	struct composite_context *ctx = talloc_get_type(req->async.private_data,
54							struct composite_context);
55	struct smb2_tree *tree = req->tree;
56	struct smb2_create create_parm;
57	struct smb2_close close_parm;
58	NTSTATUS status;
59
60	status = smb2_create_recv(req, ctx, &create_parm);
61	if (!NT_STATUS_IS_OK(status)) {
62		composite_error(ctx, status);
63		return;
64	}
65
66	ZERO_STRUCT(close_parm);
67	close_parm.in.file.handle = create_parm.out.file.handle;
68
69	req = smb2_close_send(tree, &close_parm);
70	composite_continue_smb2(ctx, req, continue_close, ctx);
71}
72
73/*
74  composite SMB2 unlink call
75*/
76struct composite_context *smb2_composite_unlink_send(struct smb2_tree *tree,
77						     union smb_unlink *io)
78{
79	struct composite_context *ctx;
80	struct smb2_create create_parm;
81	struct smb2_request *req;
82
83	ctx = composite_create(tree, tree->session->transport->socket->event.ctx);
84	if (ctx == NULL) return NULL;
85
86	/* check for wildcards - we could support these with a
87	   search, but for now they aren't necessary */
88	if (strpbrk(io->unlink.in.pattern, "*?<>") != NULL) {
89		composite_error(ctx, NT_STATUS_NOT_SUPPORTED);
90		return ctx;
91	}
92
93	ZERO_STRUCT(create_parm);
94	create_parm.in.desired_access     = SEC_STD_DELETE;
95	create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
96	create_parm.in.share_access =
97		NTCREATEX_SHARE_ACCESS_DELETE|
98		NTCREATEX_SHARE_ACCESS_READ|
99		NTCREATEX_SHARE_ACCESS_WRITE;
100	create_parm.in.create_options =
101		NTCREATEX_OPTIONS_DELETE_ON_CLOSE |
102		NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
103	create_parm.in.fname = io->unlink.in.pattern;
104	if (create_parm.in.fname[0] == '\\') {
105		create_parm.in.fname++;
106	}
107
108	req = smb2_create_send(tree, &create_parm);
109
110	composite_continue_smb2(ctx, req, continue_unlink, ctx);
111	return ctx;
112}
113
114
115/*
116  composite unlink call - sync interface
117*/
118NTSTATUS smb2_composite_unlink(struct smb2_tree *tree, union smb_unlink *io)
119{
120	struct composite_context *c = smb2_composite_unlink_send(tree, io);
121	return composite_wait_free(c);
122}
123
124
125
126
127/*
128  continue after the create in a composite mkdir
129 */
130static void continue_mkdir(struct smb2_request *req)
131{
132	struct composite_context *ctx = talloc_get_type(req->async.private_data,
133							struct composite_context);
134	struct smb2_tree *tree = req->tree;
135	struct smb2_create create_parm;
136	struct smb2_close close_parm;
137	NTSTATUS status;
138
139	status = smb2_create_recv(req, ctx, &create_parm);
140	if (!NT_STATUS_IS_OK(status)) {
141		composite_error(ctx, status);
142		return;
143	}
144
145	ZERO_STRUCT(close_parm);
146	close_parm.in.file.handle = create_parm.out.file.handle;
147
148	req = smb2_close_send(tree, &close_parm);
149	composite_continue_smb2(ctx, req, continue_close, ctx);
150}
151
152/*
153  composite SMB2 mkdir call
154*/
155struct composite_context *smb2_composite_mkdir_send(struct smb2_tree *tree,
156						     union smb_mkdir *io)
157{
158	struct composite_context *ctx;
159	struct smb2_create create_parm;
160	struct smb2_request *req;
161
162	ctx = composite_create(tree, tree->session->transport->socket->event.ctx);
163	if (ctx == NULL) return NULL;
164
165	ZERO_STRUCT(create_parm);
166
167	create_parm.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
168	create_parm.in.share_access =
169		NTCREATEX_SHARE_ACCESS_READ|
170		NTCREATEX_SHARE_ACCESS_WRITE;
171	create_parm.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
172	create_parm.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
173	create_parm.in.create_disposition = NTCREATEX_DISP_CREATE;
174	create_parm.in.fname = io->mkdir.in.path;
175	if (create_parm.in.fname[0] == '\\') {
176		create_parm.in.fname++;
177	}
178
179	req = smb2_create_send(tree, &create_parm);
180
181	composite_continue_smb2(ctx, req, continue_mkdir, ctx);
182
183	return ctx;
184}
185
186
187/*
188  composite mkdir call - sync interface
189*/
190NTSTATUS smb2_composite_mkdir(struct smb2_tree *tree, union smb_mkdir *io)
191{
192	struct composite_context *c = smb2_composite_mkdir_send(tree, io);
193	return composite_wait_free(c);
194}
195
196
197
198/*
199  continue after the create in a composite rmdir
200 */
201static void continue_rmdir(struct smb2_request *req)
202{
203	struct composite_context *ctx = talloc_get_type(req->async.private_data,
204							struct composite_context);
205	struct smb2_tree *tree = req->tree;
206	struct smb2_create create_parm;
207	struct smb2_close close_parm;
208	NTSTATUS status;
209
210	status = smb2_create_recv(req, ctx, &create_parm);
211	if (!NT_STATUS_IS_OK(status)) {
212		composite_error(ctx, status);
213		return;
214	}
215
216	ZERO_STRUCT(close_parm);
217	close_parm.in.file.handle = create_parm.out.file.handle;
218
219	req = smb2_close_send(tree, &close_parm);
220	composite_continue_smb2(ctx, req, continue_close, ctx);
221}
222
223/*
224  composite SMB2 rmdir call
225*/
226struct composite_context *smb2_composite_rmdir_send(struct smb2_tree *tree,
227						    struct smb_rmdir *io)
228{
229	struct composite_context *ctx;
230	struct smb2_create create_parm;
231	struct smb2_request *req;
232
233	ctx = composite_create(tree, tree->session->transport->socket->event.ctx);
234	if (ctx == NULL) return NULL;
235
236	ZERO_STRUCT(create_parm);
237	create_parm.in.desired_access     = SEC_STD_DELETE;
238	create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
239	create_parm.in.share_access =
240		NTCREATEX_SHARE_ACCESS_DELETE|
241		NTCREATEX_SHARE_ACCESS_READ|
242		NTCREATEX_SHARE_ACCESS_WRITE;
243	create_parm.in.create_options =
244		NTCREATEX_OPTIONS_DIRECTORY |
245		NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
246	create_parm.in.fname = io->in.path;
247	if (create_parm.in.fname[0] == '\\') {
248		create_parm.in.fname++;
249	}
250
251	req = smb2_create_send(tree, &create_parm);
252
253	composite_continue_smb2(ctx, req, continue_rmdir, ctx);
254	return ctx;
255}
256
257
258/*
259  composite rmdir call - sync interface
260*/
261NTSTATUS smb2_composite_rmdir(struct smb2_tree *tree, struct smb_rmdir *io)
262{
263	struct composite_context *c = smb2_composite_rmdir_send(tree, io);
264	return composite_wait_free(c);
265}
266
267
268/*
269  continue after the setfileinfo in a composite setpathinfo
270 */
271static void continue_setpathinfo_close(struct smb2_request *req)
272{
273	struct composite_context *ctx = talloc_get_type(req->async.private_data,
274							struct composite_context);
275	struct smb2_tree *tree = req->tree;
276	struct smb2_close close_parm;
277	NTSTATUS status;
278	union smb_setfileinfo *io2 = talloc_get_type(ctx->private_data,
279						     union smb_setfileinfo);
280
281	status = smb2_setinfo_recv(req);
282	if (!NT_STATUS_IS_OK(status)) {
283		composite_error(ctx, status);
284		return;
285	}
286
287	ZERO_STRUCT(close_parm);
288	close_parm.in.file.handle = io2->generic.in.file.handle;
289
290	req = smb2_close_send(tree, &close_parm);
291	composite_continue_smb2(ctx, req, continue_close, ctx);
292}
293
294
295/*
296  continue after the create in a composite setpathinfo
297 */
298static void continue_setpathinfo(struct smb2_request *req)
299{
300	struct composite_context *ctx = talloc_get_type(req->async.private_data,
301							struct composite_context);
302	struct smb2_tree *tree = req->tree;
303	struct smb2_create create_parm;
304	NTSTATUS status;
305	union smb_setfileinfo *io2 = talloc_get_type(ctx->private_data,
306						     union smb_setfileinfo);
307
308	status = smb2_create_recv(req, ctx, &create_parm);
309	if (!NT_STATUS_IS_OK(status)) {
310		composite_error(ctx, status);
311		return;
312	}
313
314	io2->generic.in.file.handle = create_parm.out.file.handle;
315
316	req = smb2_setinfo_file_send(tree, io2);
317	composite_continue_smb2(ctx, req, continue_setpathinfo_close, ctx);
318}
319
320
321/*
322  composite SMB2 setpathinfo call
323*/
324struct composite_context *smb2_composite_setpathinfo_send(struct smb2_tree *tree,
325							  union smb_setfileinfo *io)
326{
327	struct composite_context *ctx;
328	struct smb2_create create_parm;
329	struct smb2_request *req;
330	union smb_setfileinfo *io2;
331
332	ctx = composite_create(tree, tree->session->transport->socket->event.ctx);
333	if (ctx == NULL) return NULL;
334
335	ZERO_STRUCT(create_parm);
336	create_parm.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
337	create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
338	create_parm.in.share_access =
339		NTCREATEX_SHARE_ACCESS_DELETE|
340		NTCREATEX_SHARE_ACCESS_READ|
341		NTCREATEX_SHARE_ACCESS_WRITE;
342	create_parm.in.create_options = 0;
343	create_parm.in.fname = io->generic.in.file.path;
344	if (create_parm.in.fname[0] == '\\') {
345		create_parm.in.fname++;
346	}
347
348	req = smb2_create_send(tree, &create_parm);
349
350	io2 = talloc(ctx, union smb_setfileinfo);
351	if (composite_nomem(io2, ctx)) {
352		return ctx;
353	}
354	*io2 = *io;
355
356	ctx->private_data = io2;
357
358	composite_continue_smb2(ctx, req, continue_setpathinfo, ctx);
359	return ctx;
360}
361
362
363/*
364  composite setpathinfo call
365 */
366NTSTATUS smb2_composite_setpathinfo(struct smb2_tree *tree, union smb_setfileinfo *io)
367{
368	struct composite_context *c = smb2_composite_setpathinfo_send(tree, io);
369	return composite_wait_free(c);
370}
371