2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 2008
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.
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.
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/>.
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
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"
35 continue after a SMB2 close
37 static void continue_close(struct smb2_request
*req
)
39 struct composite_context
*ctx
= talloc_get_type(req
->async
.private_data
,
40 struct composite_context
);
42 struct smb2_close close_parm
;
44 status
= smb2_close_recv(req
, &close_parm
);
45 composite_error(ctx
, status
);
49 continue after the create in a composite unlink
51 static void continue_unlink(struct smb2_request
*req
)
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
;
60 status
= smb2_create_recv(req
, ctx
, &create_parm
);
61 if (!NT_STATUS_IS_OK(status
)) {
62 composite_error(ctx
, status
);
66 ZERO_STRUCT(close_parm
);
67 close_parm
.in
.file
.handle
= create_parm
.out
.file
.handle
;
69 req
= smb2_close_send(tree
, &close_parm
);
70 composite_continue_smb2(ctx
, req
, continue_close
, ctx
);
74 composite SMB2 unlink call
76 struct composite_context
*smb2_composite_unlink_send(struct smb2_tree
*tree
,
79 struct composite_context
*ctx
;
80 struct smb2_create create_parm
;
81 struct smb2_request
*req
;
83 ctx
= composite_create(tree
, tree
->session
->transport
->socket
->event
.ctx
);
84 if (ctx
== NULL
) return NULL
;
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
);
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
++;
108 req
= smb2_create_send(tree
, &create_parm
);
110 composite_continue_smb2(ctx
, req
, continue_unlink
, ctx
);
116 composite unlink call - sync interface
118 NTSTATUS
smb2_composite_unlink(struct smb2_tree
*tree
, union smb_unlink
*io
)
120 struct composite_context
*c
= smb2_composite_unlink_send(tree
, io
);
121 return composite_wait_free(c
);
128 continue after the create in a composite mkdir
130 static void continue_mkdir(struct smb2_request
*req
)
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
;
139 status
= smb2_create_recv(req
, ctx
, &create_parm
);
140 if (!NT_STATUS_IS_OK(status
)) {
141 composite_error(ctx
, status
);
145 ZERO_STRUCT(close_parm
);
146 close_parm
.in
.file
.handle
= create_parm
.out
.file
.handle
;
148 req
= smb2_close_send(tree
, &close_parm
);
149 composite_continue_smb2(ctx
, req
, continue_close
, ctx
);
153 composite SMB2 mkdir call
155 struct composite_context
*smb2_composite_mkdir_send(struct smb2_tree
*tree
,
158 struct composite_context
*ctx
;
159 struct smb2_create create_parm
;
160 struct smb2_request
*req
;
162 ctx
= composite_create(tree
, tree
->session
->transport
->socket
->event
.ctx
);
163 if (ctx
== NULL
) return NULL
;
165 ZERO_STRUCT(create_parm
);
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
++;
179 req
= smb2_create_send(tree
, &create_parm
);
181 composite_continue_smb2(ctx
, req
, continue_mkdir
, ctx
);
188 composite mkdir call - sync interface
190 NTSTATUS
smb2_composite_mkdir(struct smb2_tree
*tree
, union smb_mkdir
*io
)
192 struct composite_context
*c
= smb2_composite_mkdir_send(tree
, io
);
193 return composite_wait_free(c
);
199 continue after the create in a composite rmdir
201 static void continue_rmdir(struct smb2_request
*req
)
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
;
210 status
= smb2_create_recv(req
, ctx
, &create_parm
);
211 if (!NT_STATUS_IS_OK(status
)) {
212 composite_error(ctx
, status
);
216 ZERO_STRUCT(close_parm
);
217 close_parm
.in
.file
.handle
= create_parm
.out
.file
.handle
;
219 req
= smb2_close_send(tree
, &close_parm
);
220 composite_continue_smb2(ctx
, req
, continue_close
, ctx
);
224 composite SMB2 rmdir call
226 struct composite_context
*smb2_composite_rmdir_send(struct smb2_tree
*tree
,
227 struct smb_rmdir
*io
)
229 struct composite_context
*ctx
;
230 struct smb2_create create_parm
;
231 struct smb2_request
*req
;
233 ctx
= composite_create(tree
, tree
->session
->transport
->socket
->event
.ctx
);
234 if (ctx
== NULL
) return NULL
;
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
++;
251 req
= smb2_create_send(tree
, &create_parm
);
253 composite_continue_smb2(ctx
, req
, continue_rmdir
, ctx
);
259 composite rmdir call - sync interface
261 NTSTATUS
smb2_composite_rmdir(struct smb2_tree
*tree
, struct smb_rmdir
*io
)
263 struct composite_context
*c
= smb2_composite_rmdir_send(tree
, io
);
264 return composite_wait_free(c
);
269 continue after the setfileinfo in a composite setpathinfo
271 static void continue_setpathinfo_close(struct smb2_request
*req
)
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
;
278 union smb_setfileinfo
*io2
= talloc_get_type(ctx
->private_data
,
279 union smb_setfileinfo
);
281 status
= smb2_setinfo_recv(req
);
282 if (!NT_STATUS_IS_OK(status
)) {
283 composite_error(ctx
, status
);
287 ZERO_STRUCT(close_parm
);
288 close_parm
.in
.file
.handle
= io2
->generic
.in
.file
.handle
;
290 req
= smb2_close_send(tree
, &close_parm
);
291 composite_continue_smb2(ctx
, req
, continue_close
, ctx
);
296 continue after the create in a composite setpathinfo
298 static void continue_setpathinfo(struct smb2_request
*req
)
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
;
305 union smb_setfileinfo
*io2
= talloc_get_type(ctx
->private_data
,
306 union smb_setfileinfo
);
308 status
= smb2_create_recv(req
, ctx
, &create_parm
);
309 if (!NT_STATUS_IS_OK(status
)) {
310 composite_error(ctx
, status
);
314 io2
->generic
.in
.file
.handle
= create_parm
.out
.file
.handle
;
316 req
= smb2_setinfo_file_send(tree
, io2
);
317 composite_continue_smb2(ctx
, req
, continue_setpathinfo_close
, ctx
);
322 composite SMB2 setpathinfo call
324 struct composite_context
*smb2_composite_setpathinfo_send(struct smb2_tree
*tree
,
325 union smb_setfileinfo
*io
)
327 struct composite_context
*ctx
;
328 struct smb2_create create_parm
;
329 struct smb2_request
*req
;
330 union smb_setfileinfo
*io2
;
332 ctx
= composite_create(tree
, tree
->session
->transport
->socket
->event
.ctx
);
333 if (ctx
== NULL
) return NULL
;
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
++;
348 req
= smb2_create_send(tree
, &create_parm
);
350 io2
= talloc(ctx
, union smb_setfileinfo
);
351 if (composite_nomem(io2
, ctx
)) {
356 ctx
->private_data
= io2
;
358 composite_continue_smb2(ctx
, req
, continue_setpathinfo
, ctx
);
364 composite setpathinfo call
366 NTSTATUS
smb2_composite_setpathinfo(struct smb2_tree
*tree
, union smb_setfileinfo
*io
)
368 struct composite_context
*c
= smb2_composite_setpathinfo_send(tree
, io
);
369 return composite_wait_free(c
);