/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- continue_close
- continue_unlink
- smb2_composite_unlink_send
- smb2_composite_unlink
- continue_mkdir
- smb2_composite_mkdir_send
- smb2_composite_mkdir
- continue_rmdir
- smb2_composite_rmdir_send
- smb2_composite_rmdir
- continue_setpathinfo_close
- continue_setpathinfo
- smb2_composite_setpathinfo_send
- smb2_composite_setpathinfo
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 */
37 static void continue_close(struct smb2_request *req)
/* [<][>][^][v][top][bottom][index][help] */
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 */
51 static void continue_unlink(struct smb2_request *req)
/* [<][>][^][v][top][bottom][index][help] */
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 */
76 struct composite_context *smb2_composite_unlink_send(struct smb2_tree *tree,
/* [<][>][^][v][top][bottom][index][help] */
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 */
118 NTSTATUS smb2_composite_unlink(struct smb2_tree *tree, union smb_unlink *io)
/* [<][>][^][v][top][bottom][index][help] */
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 */
130 static void continue_mkdir(struct smb2_request *req)
/* [<][>][^][v][top][bottom][index][help] */
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 */
155 struct composite_context *smb2_composite_mkdir_send(struct smb2_tree *tree,
/* [<][>][^][v][top][bottom][index][help] */
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 */
190 NTSTATUS smb2_composite_mkdir(struct smb2_tree *tree, union smb_mkdir *io)
/* [<][>][^][v][top][bottom][index][help] */
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 */
201 static void continue_rmdir(struct smb2_request *req)
/* [<][>][^][v][top][bottom][index][help] */
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 */
226 struct composite_context *smb2_composite_rmdir_send(struct smb2_tree *tree,
/* [<][>][^][v][top][bottom][index][help] */
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 */
261 NTSTATUS smb2_composite_rmdir(struct smb2_tree *tree, struct smb_rmdir *io)
/* [<][>][^][v][top][bottom][index][help] */
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 */
271 static void continue_setpathinfo_close(struct smb2_request *req)
/* [<][>][^][v][top][bottom][index][help] */
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 */
298 static void continue_setpathinfo(struct smb2_request *req)
/* [<][>][^][v][top][bottom][index][help] */
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 */
324 struct composite_context *smb2_composite_setpathinfo_send(struct smb2_tree *tree,
/* [<][>][^][v][top][bottom][index][help] */
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 */
366 NTSTATUS smb2_composite_setpathinfo(struct smb2_tree *tree, union smb_setfileinfo *io)
/* [<][>][^][v][top][bottom][index][help] */
367 {
368 struct composite_context *c = smb2_composite_setpathinfo_send(tree, io);
369 return composite_wait_free(c);
370 }