2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Jeremy Allison 2001-2002
6 Copyright (C) James Myers 2003
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/raw/raw_proto.h"
25 #include "librpc/gen_ndr/ndr_security.h"
27 #define SETUP_REQUEST(cmd, wct, buflen) do { \
28 req = smbcli_request_setup(tree, cmd, wct, buflen); \
29 if (!req) return NULL; \
32 /****************************************************************************
33 Rename a file - async interface
34 ****************************************************************************/
35 struct smbcli_request
*smb_raw_rename_send(struct smbcli_tree
*tree
,
36 union smb_rename
*parms
)
38 struct smbcli_request
*req
= NULL
;
39 struct smb_nttrans nt
;
42 switch (parms
->generic
.level
) {
43 case RAW_RENAME_RENAME
:
44 SETUP_REQUEST(SMBmv
, 1, 0);
45 SSVAL(req
->out
.vwv
, VWV(0), parms
->rename
.in
.attrib
);
46 smbcli_req_append_ascii4(req
, parms
->rename
.in
.pattern1
, STR_TERMINATE
);
47 smbcli_req_append_ascii4(req
, parms
->rename
.in
.pattern2
, STR_TERMINATE
);
50 case RAW_RENAME_NTRENAME
:
51 SETUP_REQUEST(SMBntrename
, 4, 0);
52 SSVAL(req
->out
.vwv
, VWV(0), parms
->ntrename
.in
.attrib
);
53 SSVAL(req
->out
.vwv
, VWV(1), parms
->ntrename
.in
.flags
);
54 SIVAL(req
->out
.vwv
, VWV(2), parms
->ntrename
.in
.cluster_size
);
55 smbcli_req_append_ascii4(req
, parms
->ntrename
.in
.old_name
, STR_TERMINATE
);
56 smbcli_req_append_ascii4(req
, parms
->ntrename
.in
.new_name
, STR_TERMINATE
);
59 case RAW_RENAME_NTTRANS
:
61 mem_ctx
= talloc_new(tree
);
66 nt
.in
.setup_count
= 0;
68 nt
.in
.function
= NT_TRANSACT_RENAME
;
69 nt
.in
.params
= data_blob_talloc(mem_ctx
, NULL
, 4);
70 nt
.in
.data
= data_blob(NULL
, 0);
72 SSVAL(nt
.in
.params
.data
, VWV(0), parms
->nttrans
.in
.file
.fnum
);
73 SSVAL(nt
.in
.params
.data
, VWV(1), parms
->nttrans
.in
.flags
);
75 smbcli_blob_append_string(tree
->session
, mem_ctx
,
76 &nt
.in
.params
, parms
->nttrans
.in
.new_name
,
79 req
= smb_raw_nttrans_send(tree
, &nt
);
84 if (!smbcli_request_send(req
)) {
85 smbcli_request_destroy(req
);
92 /****************************************************************************
93 Rename a file - sync interface
94 ****************************************************************************/
95 _PUBLIC_ NTSTATUS
smb_raw_rename(struct smbcli_tree
*tree
,
96 union smb_rename
*parms
)
98 struct smbcli_request
*req
= smb_raw_rename_send(tree
, parms
);
99 return smbcli_request_simple_recv(req
);
103 /****************************************************************************
104 Delete a file - async interface
105 ****************************************************************************/
106 struct smbcli_request
*smb_raw_unlink_send(struct smbcli_tree
*tree
,
107 union smb_unlink
*parms
)
109 struct smbcli_request
*req
;
111 SETUP_REQUEST(SMBunlink
, 1, 0);
113 SSVAL(req
->out
.vwv
, VWV(0), parms
->unlink
.in
.attrib
);
114 smbcli_req_append_ascii4(req
, parms
->unlink
.in
.pattern
, STR_TERMINATE
);
116 if (!smbcli_request_send(req
)) {
117 smbcli_request_destroy(req
);
124 delete a file - sync interface
126 _PUBLIC_ NTSTATUS
smb_raw_unlink(struct smbcli_tree
*tree
,
127 union smb_unlink
*parms
)
129 struct smbcli_request
*req
= smb_raw_unlink_send(tree
, parms
);
130 return smbcli_request_simple_recv(req
);
134 /****************************************************************************
135 create a directory using TRANSACT2_MKDIR - async interface
136 ****************************************************************************/
137 static struct smbcli_request
*smb_raw_t2mkdir_send(struct smbcli_tree
*tree
,
138 union smb_mkdir
*parms
)
140 struct smb_trans2 t2
;
141 uint16_t setup
= TRANSACT2_MKDIR
;
143 struct smbcli_request
*req
;
146 mem_ctx
= talloc_init("t2mkdir");
148 data_total
= ea_list_size(parms
->t2mkdir
.in
.num_eas
, parms
->t2mkdir
.in
.eas
);
155 t2
.in
.setup_count
= 1;
156 t2
.in
.setup
= &setup
;
157 t2
.in
.params
= data_blob_talloc(mem_ctx
, NULL
, 4);
158 t2
.in
.data
= data_blob_talloc(mem_ctx
, NULL
, data_total
);
160 SIVAL(t2
.in
.params
.data
, VWV(0), 0); /* reserved */
162 smbcli_blob_append_string(tree
->session
, mem_ctx
,
163 &t2
.in
.params
, parms
->t2mkdir
.in
.path
, STR_TERMINATE
);
165 ea_put_list(t2
.in
.data
.data
, parms
->t2mkdir
.in
.num_eas
, parms
->t2mkdir
.in
.eas
);
167 req
= smb_raw_trans2_send(tree
, &t2
);
169 talloc_free(mem_ctx
);
174 /****************************************************************************
175 Create a directory - async interface
176 ****************************************************************************/
177 struct smbcli_request
*smb_raw_mkdir_send(struct smbcli_tree
*tree
,
178 union smb_mkdir
*parms
)
180 struct smbcli_request
*req
;
182 if (parms
->generic
.level
== RAW_MKDIR_T2MKDIR
) {
183 return smb_raw_t2mkdir_send(tree
, parms
);
186 if (parms
->generic
.level
!= RAW_MKDIR_MKDIR
) {
190 SETUP_REQUEST(SMBmkdir
, 0, 0);
192 smbcli_req_append_ascii4(req
, parms
->mkdir
.in
.path
, STR_TERMINATE
);
194 if (!smbcli_request_send(req
)) {
201 /****************************************************************************
202 Create a directory - sync interface
203 ****************************************************************************/
204 _PUBLIC_ NTSTATUS
smb_raw_mkdir(struct smbcli_tree
*tree
,
205 union smb_mkdir
*parms
)
207 struct smbcli_request
*req
= smb_raw_mkdir_send(tree
, parms
);
208 return smbcli_request_simple_recv(req
);
211 /****************************************************************************
212 Remove a directory - async interface
213 ****************************************************************************/
214 struct smbcli_request
*smb_raw_rmdir_send(struct smbcli_tree
*tree
,
215 struct smb_rmdir
*parms
)
217 struct smbcli_request
*req
;
219 SETUP_REQUEST(SMBrmdir
, 0, 0);
221 smbcli_req_append_ascii4(req
, parms
->in
.path
, STR_TERMINATE
);
223 if (!smbcli_request_send(req
)) {
224 smbcli_request_destroy(req
);
231 /****************************************************************************
232 Remove a directory - sync interface
233 ****************************************************************************/
234 _PUBLIC_ NTSTATUS
smb_raw_rmdir(struct smbcli_tree
*tree
,
235 struct smb_rmdir
*parms
)
237 struct smbcli_request
*req
= smb_raw_rmdir_send(tree
, parms
);
238 return smbcli_request_simple_recv(req
);
243 Open a file using TRANSACT2_OPEN - async recv
245 static NTSTATUS
smb_raw_nttrans_create_recv(struct smbcli_request
*req
,
247 union smb_open
*parms
)
250 struct smb_nttrans nt
;
253 status
= smb_raw_nttrans_recv(req
, mem_ctx
, &nt
);
254 if (!NT_STATUS_IS_OK(status
)) return status
;
256 if (nt
.out
.params
.length
< 69) {
257 return NT_STATUS_INVALID_PARAMETER
;
260 params
= nt
.out
.params
.data
;
262 parms
->ntcreatex
.out
.oplock_level
= CVAL(params
, 0);
263 parms
->ntcreatex
.out
.file
.fnum
= SVAL(params
, 2);
264 parms
->ntcreatex
.out
.create_action
= IVAL(params
, 4);
265 parms
->ntcreatex
.out
.create_time
= smbcli_pull_nttime(params
, 12);
266 parms
->ntcreatex
.out
.access_time
= smbcli_pull_nttime(params
, 20);
267 parms
->ntcreatex
.out
.write_time
= smbcli_pull_nttime(params
, 28);
268 parms
->ntcreatex
.out
.change_time
= smbcli_pull_nttime(params
, 36);
269 parms
->ntcreatex
.out
.attrib
= IVAL(params
, 44);
270 parms
->ntcreatex
.out
.alloc_size
= BVAL(params
, 48);
271 parms
->ntcreatex
.out
.size
= BVAL(params
, 56);
272 parms
->ntcreatex
.out
.file_type
= SVAL(params
, 64);
273 parms
->ntcreatex
.out
.ipc_state
= SVAL(params
, 66);
274 parms
->ntcreatex
.out
.is_directory
= CVAL(params
, 68);
281 Open a file using NTTRANS CREATE - async send
283 static struct smbcli_request
*smb_raw_nttrans_create_send(struct smbcli_tree
*tree
,
284 union smb_open
*parms
)
286 struct smb_nttrans nt
;
288 TALLOC_CTX
*mem_ctx
= talloc_new(tree
);
290 DATA_BLOB sd_blob
, ea_blob
;
291 struct smbcli_request
*req
;
294 nt
.in
.max_param
= 101;
296 nt
.in
.setup_count
= 0;
297 nt
.in
.function
= NT_TRANSACT_CREATE
;
300 sd_blob
= data_blob(NULL
, 0);
301 ea_blob
= data_blob(NULL
, 0);
303 if (parms
->ntcreatex
.in
.sec_desc
) {
304 enum ndr_err_code ndr_err
;
305 ndr_err
= ndr_push_struct_blob(&sd_blob
, mem_ctx
,
306 parms
->ntcreatex
.in
.sec_desc
,
307 (ndr_push_flags_fn_t
)ndr_push_security_descriptor
);
308 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
309 talloc_free(mem_ctx
);
314 if (parms
->ntcreatex
.in
.ea_list
) {
315 uint32_t ea_size
= ea_list_size_chained(parms
->ntcreatex
.in
.ea_list
->num_eas
,
316 parms
->ntcreatex
.in
.ea_list
->eas
, 4);
317 ea_blob
= data_blob_talloc(mem_ctx
, NULL
, ea_size
);
318 if (ea_blob
.data
== NULL
) {
321 ea_put_list_chained(ea_blob
.data
,
322 parms
->ntcreatex
.in
.ea_list
->num_eas
,
323 parms
->ntcreatex
.in
.ea_list
->eas
, 4);
326 nt
.in
.params
= data_blob_talloc(mem_ctx
, NULL
, 53);
327 if (nt
.in
.params
.data
== NULL
) {
328 talloc_free(mem_ctx
);
332 /* build the parameter section */
333 params
= nt
.in
.params
.data
;
335 SIVAL(params
, 0, parms
->ntcreatex
.in
.flags
);
336 SIVAL(params
, 4, parms
->ntcreatex
.in
.root_fid
.fnum
);
337 SIVAL(params
, 8, parms
->ntcreatex
.in
.access_mask
);
338 SBVAL(params
, 12, parms
->ntcreatex
.in
.alloc_size
);
339 SIVAL(params
, 20, parms
->ntcreatex
.in
.file_attr
);
340 SIVAL(params
, 24, parms
->ntcreatex
.in
.share_access
);
341 SIVAL(params
, 28, parms
->ntcreatex
.in
.open_disposition
);
342 SIVAL(params
, 32, parms
->ntcreatex
.in
.create_options
);
343 SIVAL(params
, 36, sd_blob
.length
);
344 SIVAL(params
, 40, ea_blob
.length
);
345 SIVAL(params
, 48, parms
->ntcreatex
.in
.impersonation
);
346 SCVAL(params
, 52, parms
->ntcreatex
.in
.security_flags
);
348 /* the empty string first forces the correct alignment */
349 smbcli_blob_append_string(tree
->session
, mem_ctx
, &nt
.in
.params
,"", 0);
350 fname_len
= smbcli_blob_append_string(tree
->session
, mem_ctx
, &nt
.in
.params
,
351 parms
->ntcreatex
.in
.fname
, STR_TERMINATE
);
353 SIVAL(nt
.in
.params
.data
, 44, fname_len
);
355 /* build the data section */
356 nt
.in
.data
= data_blob_talloc(mem_ctx
, NULL
, sd_blob
.length
+ ea_blob
.length
);
357 memcpy(nt
.in
.data
.data
, sd_blob
.data
, sd_blob
.length
);
358 memcpy(nt
.in
.data
.data
+sd_blob
.length
, ea_blob
.data
, ea_blob
.length
);
360 /* send the request on its way */
361 req
= smb_raw_nttrans_send(tree
, &nt
);
363 talloc_free(mem_ctx
);
369 /****************************************************************************
370 Open a file using TRANSACT2_OPEN - async send
371 ****************************************************************************/
372 static struct smbcli_request
*smb_raw_t2open_send(struct smbcli_tree
*tree
,
373 union smb_open
*parms
)
375 struct smb_trans2 t2
;
376 uint16_t setup
= TRANSACT2_OPEN
;
377 TALLOC_CTX
*mem_ctx
= talloc_init("smb_raw_t2open");
378 struct smbcli_request
*req
;
381 list_size
= ea_list_size(parms
->t2open
.in
.num_eas
, parms
->t2open
.in
.eas
);
383 t2
.in
.max_param
= 30;
388 t2
.in
.setup_count
= 1;
389 t2
.in
.setup
= &setup
;
390 t2
.in
.params
= data_blob_talloc(mem_ctx
, NULL
, 28);
391 t2
.in
.data
= data_blob_talloc(mem_ctx
, NULL
, list_size
);
393 SSVAL(t2
.in
.params
.data
, VWV(0), parms
->t2open
.in
.flags
);
394 SSVAL(t2
.in
.params
.data
, VWV(1), parms
->t2open
.in
.open_mode
);
395 SSVAL(t2
.in
.params
.data
, VWV(2), parms
->t2open
.in
.search_attrs
);
396 SSVAL(t2
.in
.params
.data
, VWV(3), parms
->t2open
.in
.file_attrs
);
397 raw_push_dos_date(tree
->session
->transport
,
398 t2
.in
.params
.data
, VWV(4), parms
->t2open
.in
.write_time
);
399 SSVAL(t2
.in
.params
.data
, VWV(6), parms
->t2open
.in
.open_func
);
400 SIVAL(t2
.in
.params
.data
, VWV(7), parms
->t2open
.in
.size
);
401 SIVAL(t2
.in
.params
.data
, VWV(9), parms
->t2open
.in
.timeout
);
402 SIVAL(t2
.in
.params
.data
, VWV(11), 0);
403 SSVAL(t2
.in
.params
.data
, VWV(13), 0);
405 smbcli_blob_append_string(tree
->session
, mem_ctx
,
406 &t2
.in
.params
, parms
->t2open
.in
.fname
,
409 ea_put_list(t2
.in
.data
.data
, parms
->t2open
.in
.num_eas
, parms
->t2open
.in
.eas
);
411 req
= smb_raw_trans2_send(tree
, &t2
);
413 talloc_free(mem_ctx
);
419 /****************************************************************************
420 Open a file using TRANSACT2_OPEN - async recv
421 ****************************************************************************/
422 static NTSTATUS
smb_raw_t2open_recv(struct smbcli_request
*req
, TALLOC_CTX
*mem_ctx
, union smb_open
*parms
)
424 struct smbcli_transport
*transport
= req
->transport
;
425 struct smb_trans2 t2
;
428 status
= smb_raw_trans2_recv(req
, mem_ctx
, &t2
);
429 if (!NT_STATUS_IS_OK(status
)) return status
;
431 if (t2
.out
.params
.length
< 30) {
432 return NT_STATUS_INFO_LENGTH_MISMATCH
;
435 parms
->t2open
.out
.file
.fnum
= SVAL(t2
.out
.params
.data
, VWV(0));
436 parms
->t2open
.out
.attrib
= SVAL(t2
.out
.params
.data
, VWV(1));
437 parms
->t2open
.out
.write_time
= raw_pull_dos_date3(transport
, t2
.out
.params
.data
+ VWV(2));
438 parms
->t2open
.out
.size
= IVAL(t2
.out
.params
.data
, VWV(4));
439 parms
->t2open
.out
.access
= SVAL(t2
.out
.params
.data
, VWV(6));
440 parms
->t2open
.out
.ftype
= SVAL(t2
.out
.params
.data
, VWV(7));
441 parms
->t2open
.out
.devstate
= SVAL(t2
.out
.params
.data
, VWV(8));
442 parms
->t2open
.out
.action
= SVAL(t2
.out
.params
.data
, VWV(9));
443 parms
->t2open
.out
.file_id
= SVAL(t2
.out
.params
.data
, VWV(10));
448 /****************************************************************************
449 Open a file - async send
450 ****************************************************************************/
451 _PUBLIC_
struct smbcli_request
*smb_raw_open_send(struct smbcli_tree
*tree
, union smb_open
*parms
)
454 struct smbcli_request
*req
= NULL
;
455 bool bigoffset
= false;
457 switch (parms
->generic
.level
) {
458 case RAW_OPEN_T2OPEN
:
459 return smb_raw_t2open_send(tree
, parms
);
462 SETUP_REQUEST(SMBopen
, 2, 0);
463 SSVAL(req
->out
.vwv
, VWV(0), parms
->openold
.in
.open_mode
);
464 SSVAL(req
->out
.vwv
, VWV(1), parms
->openold
.in
.search_attrs
);
465 smbcli_req_append_ascii4(req
, parms
->openold
.in
.fname
, STR_TERMINATE
);
469 SETUP_REQUEST(SMBopenX
, 15, 0);
470 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
471 SSVAL(req
->out
.vwv
, VWV(1), 0);
472 SSVAL(req
->out
.vwv
, VWV(2), parms
->openx
.in
.flags
);
473 SSVAL(req
->out
.vwv
, VWV(3), parms
->openx
.in
.open_mode
);
474 SSVAL(req
->out
.vwv
, VWV(4), parms
->openx
.in
.search_attrs
);
475 SSVAL(req
->out
.vwv
, VWV(5), parms
->openx
.in
.file_attrs
);
476 raw_push_dos_date3(tree
->session
->transport
,
477 req
->out
.vwv
, VWV(6), parms
->openx
.in
.write_time
);
478 SSVAL(req
->out
.vwv
, VWV(8), parms
->openx
.in
.open_func
);
479 SIVAL(req
->out
.vwv
, VWV(9), parms
->openx
.in
.size
);
480 SIVAL(req
->out
.vwv
, VWV(11),parms
->openx
.in
.timeout
);
481 SIVAL(req
->out
.vwv
, VWV(13),0); /* reserved */
482 smbcli_req_append_string(req
, parms
->openx
.in
.fname
, STR_TERMINATE
);
486 SETUP_REQUEST(SMBmknew
, 3, 0);
487 SSVAL(req
->out
.vwv
, VWV(0), parms
->mknew
.in
.attrib
);
488 raw_push_dos_date3(tree
->session
->transport
,
489 req
->out
.vwv
, VWV(1), parms
->mknew
.in
.write_time
);
490 smbcli_req_append_ascii4(req
, parms
->mknew
.in
.fname
, STR_TERMINATE
);
493 case RAW_OPEN_CREATE
:
494 SETUP_REQUEST(SMBcreate
, 3, 0);
495 SSVAL(req
->out
.vwv
, VWV(0), parms
->create
.in
.attrib
);
496 raw_push_dos_date3(tree
->session
->transport
,
497 req
->out
.vwv
, VWV(1), parms
->create
.in
.write_time
);
498 smbcli_req_append_ascii4(req
, parms
->create
.in
.fname
, STR_TERMINATE
);
502 SETUP_REQUEST(SMBctemp
, 3, 0);
503 SSVAL(req
->out
.vwv
, VWV(0), parms
->ctemp
.in
.attrib
);
504 raw_push_dos_date3(tree
->session
->transport
,
505 req
->out
.vwv
, VWV(1), parms
->ctemp
.in
.write_time
);
506 smbcli_req_append_ascii4(req
, parms
->ctemp
.in
.directory
, STR_TERMINATE
);
509 case RAW_OPEN_SPLOPEN
:
510 SETUP_REQUEST(SMBsplopen
, 2, 0);
511 SSVAL(req
->out
.vwv
, VWV(0), parms
->splopen
.in
.setup_length
);
512 SSVAL(req
->out
.vwv
, VWV(1), parms
->splopen
.in
.mode
);
515 case RAW_OPEN_NTCREATEX
:
516 SETUP_REQUEST(SMBntcreateX
, 24, 0);
517 SSVAL(req
->out
.vwv
, VWV(0),SMB_CHAIN_NONE
);
518 SSVAL(req
->out
.vwv
, VWV(1),0);
519 SCVAL(req
->out
.vwv
, VWV(2),0); /* padding */
520 SIVAL(req
->out
.vwv
, 7, parms
->ntcreatex
.in
.flags
);
521 SIVAL(req
->out
.vwv
, 11, parms
->ntcreatex
.in
.root_fid
.fnum
);
522 SIVAL(req
->out
.vwv
, 15, parms
->ntcreatex
.in
.access_mask
);
523 SBVAL(req
->out
.vwv
, 19, parms
->ntcreatex
.in
.alloc_size
);
524 SIVAL(req
->out
.vwv
, 27, parms
->ntcreatex
.in
.file_attr
);
525 SIVAL(req
->out
.vwv
, 31, parms
->ntcreatex
.in
.share_access
);
526 SIVAL(req
->out
.vwv
, 35, parms
->ntcreatex
.in
.open_disposition
);
527 SIVAL(req
->out
.vwv
, 39, parms
->ntcreatex
.in
.create_options
);
528 SIVAL(req
->out
.vwv
, 43, parms
->ntcreatex
.in
.impersonation
);
529 SCVAL(req
->out
.vwv
, 47, parms
->ntcreatex
.in
.security_flags
);
531 smbcli_req_append_string_len(req
, parms
->ntcreatex
.in
.fname
, STR_TERMINATE
, &len
);
532 SSVAL(req
->out
.vwv
, 5, len
);
535 case RAW_OPEN_NTTRANS_CREATE
:
536 return smb_raw_nttrans_create_send(tree
, parms
);
539 case RAW_OPEN_OPENX_READX
:
540 SETUP_REQUEST(SMBopenX
, 15, 0);
541 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
542 SSVAL(req
->out
.vwv
, VWV(1), 0);
543 SSVAL(req
->out
.vwv
, VWV(2), parms
->openxreadx
.in
.flags
);
544 SSVAL(req
->out
.vwv
, VWV(3), parms
->openxreadx
.in
.open_mode
);
545 SSVAL(req
->out
.vwv
, VWV(4), parms
->openxreadx
.in
.search_attrs
);
546 SSVAL(req
->out
.vwv
, VWV(5), parms
->openxreadx
.in
.file_attrs
);
547 raw_push_dos_date3(tree
->session
->transport
,
548 req
->out
.vwv
, VWV(6), parms
->openxreadx
.in
.write_time
);
549 SSVAL(req
->out
.vwv
, VWV(8), parms
->openxreadx
.in
.open_func
);
550 SIVAL(req
->out
.vwv
, VWV(9), parms
->openxreadx
.in
.size
);
551 SIVAL(req
->out
.vwv
, VWV(11),parms
->openxreadx
.in
.timeout
);
552 SIVAL(req
->out
.vwv
, VWV(13),0);
553 smbcli_req_append_string(req
, parms
->openxreadx
.in
.fname
, STR_TERMINATE
);
555 if (tree
->session
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
559 smbcli_chained_request_setup(req
, SMBreadX
, bigoffset
? 12 : 10, 0);
561 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
562 SSVAL(req
->out
.vwv
, VWV(1), 0);
563 SSVAL(req
->out
.vwv
, VWV(2), 0);
564 SIVAL(req
->out
.vwv
, VWV(3), parms
->openxreadx
.in
.offset
);
565 SSVAL(req
->out
.vwv
, VWV(5), parms
->openxreadx
.in
.maxcnt
& 0xFFFF);
566 SSVAL(req
->out
.vwv
, VWV(6), parms
->openxreadx
.in
.mincnt
);
567 SIVAL(req
->out
.vwv
, VWV(7), parms
->openxreadx
.in
.maxcnt
>> 16);
568 SSVAL(req
->out
.vwv
, VWV(9), parms
->openxreadx
.in
.remaining
);
570 SIVAL(req
->out
.vwv
, VWV(10),parms
->openxreadx
.in
.offset
>>32);
574 case RAW_OPEN_NTCREATEX_READX
:
575 SETUP_REQUEST(SMBntcreateX
, 24, 0);
576 SSVAL(req
->out
.vwv
, VWV(0),SMB_CHAIN_NONE
);
577 SSVAL(req
->out
.vwv
, VWV(1),0);
578 SCVAL(req
->out
.vwv
, VWV(2),0); /* padding */
579 SIVAL(req
->out
.vwv
, 7, parms
->ntcreatexreadx
.in
.flags
);
580 SIVAL(req
->out
.vwv
, 11, parms
->ntcreatexreadx
.in
.root_fid
.fnum
);
581 SIVAL(req
->out
.vwv
, 15, parms
->ntcreatexreadx
.in
.access_mask
);
582 SBVAL(req
->out
.vwv
, 19, parms
->ntcreatexreadx
.in
.alloc_size
);
583 SIVAL(req
->out
.vwv
, 27, parms
->ntcreatexreadx
.in
.file_attr
);
584 SIVAL(req
->out
.vwv
, 31, parms
->ntcreatexreadx
.in
.share_access
);
585 SIVAL(req
->out
.vwv
, 35, parms
->ntcreatexreadx
.in
.open_disposition
);
586 SIVAL(req
->out
.vwv
, 39, parms
->ntcreatexreadx
.in
.create_options
);
587 SIVAL(req
->out
.vwv
, 43, parms
->ntcreatexreadx
.in
.impersonation
);
588 SCVAL(req
->out
.vwv
, 47, parms
->ntcreatexreadx
.in
.security_flags
);
590 smbcli_req_append_string_len(req
, parms
->ntcreatexreadx
.in
.fname
, STR_TERMINATE
, &len
);
591 SSVAL(req
->out
.vwv
, 5, len
);
593 if (tree
->session
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
597 smbcli_chained_request_setup(req
, SMBreadX
, bigoffset
? 12 : 10, 0);
599 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
600 SSVAL(req
->out
.vwv
, VWV(1), 0);
601 SSVAL(req
->out
.vwv
, VWV(2), 0);
602 SIVAL(req
->out
.vwv
, VWV(3), parms
->ntcreatexreadx
.in
.offset
);
603 SSVAL(req
->out
.vwv
, VWV(5), parms
->ntcreatexreadx
.in
.maxcnt
& 0xFFFF);
604 SSVAL(req
->out
.vwv
, VWV(6), parms
->ntcreatexreadx
.in
.mincnt
);
605 SIVAL(req
->out
.vwv
, VWV(7), parms
->ntcreatexreadx
.in
.maxcnt
>> 16);
606 SSVAL(req
->out
.vwv
, VWV(9), parms
->ntcreatexreadx
.in
.remaining
);
608 SIVAL(req
->out
.vwv
, VWV(10),parms
->ntcreatexreadx
.in
.offset
>>32);
616 if (!smbcli_request_send(req
)) {
617 smbcli_request_destroy(req
);
624 /****************************************************************************
625 Open a file - async recv
626 ****************************************************************************/
627 _PUBLIC_ NTSTATUS
smb_raw_open_recv(struct smbcli_request
*req
, TALLOC_CTX
*mem_ctx
, union smb_open
*parms
)
631 if (!smbcli_request_receive(req
) ||
632 smbcli_request_is_error(req
)) {
636 switch (parms
->openold
.level
) {
637 case RAW_OPEN_T2OPEN
:
638 return smb_raw_t2open_recv(req
, mem_ctx
, parms
);
641 SMBCLI_CHECK_WCT(req
, 7);
642 parms
->openold
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(0));
643 parms
->openold
.out
.attrib
= SVAL(req
->in
.vwv
, VWV(1));
644 parms
->openold
.out
.write_time
= raw_pull_dos_date3(req
->transport
,
645 req
->in
.vwv
+ VWV(2));
646 parms
->openold
.out
.size
= IVAL(req
->in
.vwv
, VWV(4));
647 parms
->openold
.out
.rmode
= SVAL(req
->in
.vwv
, VWV(6));
651 SMBCLI_CHECK_MIN_WCT(req
, 15);
652 parms
->openx
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(2));
653 parms
->openx
.out
.attrib
= SVAL(req
->in
.vwv
, VWV(3));
654 parms
->openx
.out
.write_time
= raw_pull_dos_date3(req
->transport
,
655 req
->in
.vwv
+ VWV(4));
656 parms
->openx
.out
.size
= IVAL(req
->in
.vwv
, VWV(6));
657 parms
->openx
.out
.access
= SVAL(req
->in
.vwv
, VWV(8));
658 parms
->openx
.out
.ftype
= SVAL(req
->in
.vwv
, VWV(9));
659 parms
->openx
.out
.devstate
= SVAL(req
->in
.vwv
, VWV(10));
660 parms
->openx
.out
.action
= SVAL(req
->in
.vwv
, VWV(11));
661 parms
->openx
.out
.unique_fid
= IVAL(req
->in
.vwv
, VWV(12));
662 if (req
->in
.wct
>= 19) {
663 parms
->openx
.out
.access_mask
= IVAL(req
->in
.vwv
, VWV(15));
664 parms
->openx
.out
.unknown
= IVAL(req
->in
.vwv
, VWV(17));
666 parms
->openx
.out
.access_mask
= 0;
667 parms
->openx
.out
.unknown
= 0;
672 SMBCLI_CHECK_WCT(req
, 1);
673 parms
->mknew
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(0));
676 case RAW_OPEN_CREATE
:
677 SMBCLI_CHECK_WCT(req
, 1);
678 parms
->create
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(0));
682 SMBCLI_CHECK_WCT(req
, 1);
683 parms
->ctemp
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(0));
684 smbcli_req_pull_string(&req
->in
.bufinfo
, mem_ctx
, &parms
->ctemp
.out
.name
, req
->in
.data
, -1, STR_TERMINATE
| STR_ASCII
);
687 case RAW_OPEN_SPLOPEN
:
688 SMBCLI_CHECK_WCT(req
, 1);
689 parms
->splopen
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(0));
692 case RAW_OPEN_NTCREATEX
:
693 SMBCLI_CHECK_MIN_WCT(req
, 34);
694 parms
->ntcreatex
.out
.oplock_level
= CVAL(req
->in
.vwv
, 4);
695 parms
->ntcreatex
.out
.file
.fnum
= SVAL(req
->in
.vwv
, 5);
696 parms
->ntcreatex
.out
.create_action
= IVAL(req
->in
.vwv
, 7);
697 parms
->ntcreatex
.out
.create_time
= smbcli_pull_nttime(req
->in
.vwv
, 11);
698 parms
->ntcreatex
.out
.access_time
= smbcli_pull_nttime(req
->in
.vwv
, 19);
699 parms
->ntcreatex
.out
.write_time
= smbcli_pull_nttime(req
->in
.vwv
, 27);
700 parms
->ntcreatex
.out
.change_time
= smbcli_pull_nttime(req
->in
.vwv
, 35);
701 parms
->ntcreatex
.out
.attrib
= IVAL(req
->in
.vwv
, 43);
702 parms
->ntcreatex
.out
.alloc_size
= BVAL(req
->in
.vwv
, 47);
703 parms
->ntcreatex
.out
.size
= BVAL(req
->in
.vwv
, 55);
704 parms
->ntcreatex
.out
.file_type
= SVAL(req
->in
.vwv
, 63);
705 parms
->ntcreatex
.out
.ipc_state
= SVAL(req
->in
.vwv
, 65);
706 parms
->ntcreatex
.out
.is_directory
= CVAL(req
->in
.vwv
, 67);
709 case RAW_OPEN_NTTRANS_CREATE
:
710 return smb_raw_nttrans_create_recv(req
, mem_ctx
, parms
);
712 case RAW_OPEN_OPENX_READX
:
713 SMBCLI_CHECK_MIN_WCT(req
, 15);
714 parms
->openxreadx
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(2));
715 parms
->openxreadx
.out
.attrib
= SVAL(req
->in
.vwv
, VWV(3));
716 parms
->openxreadx
.out
.write_time
= raw_pull_dos_date3(req
->transport
,
717 req
->in
.vwv
+ VWV(4));
718 parms
->openxreadx
.out
.size
= IVAL(req
->in
.vwv
, VWV(6));
719 parms
->openxreadx
.out
.access
= SVAL(req
->in
.vwv
, VWV(8));
720 parms
->openxreadx
.out
.ftype
= SVAL(req
->in
.vwv
, VWV(9));
721 parms
->openxreadx
.out
.devstate
= SVAL(req
->in
.vwv
, VWV(10));
722 parms
->openxreadx
.out
.action
= SVAL(req
->in
.vwv
, VWV(11));
723 parms
->openxreadx
.out
.unique_fid
= IVAL(req
->in
.vwv
, VWV(12));
724 if (req
->in
.wct
>= 19) {
725 parms
->openxreadx
.out
.access_mask
= IVAL(req
->in
.vwv
, VWV(15));
726 parms
->openxreadx
.out
.unknown
= IVAL(req
->in
.vwv
, VWV(17));
728 parms
->openxreadx
.out
.access_mask
= 0;
729 parms
->openxreadx
.out
.unknown
= 0;
732 status
= smbcli_chained_advance(req
);
733 if (!NT_STATUS_IS_OK(status
)) {
737 SMBCLI_CHECK_WCT(req
, 12);
738 parms
->openxreadx
.out
.remaining
= SVAL(req
->in
.vwv
, VWV(2));
739 parms
->openxreadx
.out
.compaction_mode
= SVAL(req
->in
.vwv
, VWV(3));
740 parms
->openxreadx
.out
.nread
= SVAL(req
->in
.vwv
, VWV(5));
741 if (parms
->openxreadx
.out
.nread
>
742 MAX(parms
->openxreadx
.in
.mincnt
, parms
->openxreadx
.in
.maxcnt
) ||
743 !smbcli_raw_pull_data(&req
->in
.bufinfo
, req
->in
.hdr
+ SVAL(req
->in
.vwv
, VWV(6)),
744 parms
->openxreadx
.out
.nread
,
745 parms
->openxreadx
.out
.data
)) {
746 req
->status
= NT_STATUS_BUFFER_TOO_SMALL
;
750 case RAW_OPEN_NTCREATEX_READX
:
751 SMBCLI_CHECK_MIN_WCT(req
, 34);
752 parms
->ntcreatexreadx
.out
.oplock_level
= CVAL(req
->in
.vwv
, 4);
753 parms
->ntcreatexreadx
.out
.file
.fnum
= SVAL(req
->in
.vwv
, 5);
754 parms
->ntcreatexreadx
.out
.create_action
= IVAL(req
->in
.vwv
, 7);
755 parms
->ntcreatexreadx
.out
.create_time
= smbcli_pull_nttime(req
->in
.vwv
, 11);
756 parms
->ntcreatexreadx
.out
.access_time
= smbcli_pull_nttime(req
->in
.vwv
, 19);
757 parms
->ntcreatexreadx
.out
.write_time
= smbcli_pull_nttime(req
->in
.vwv
, 27);
758 parms
->ntcreatexreadx
.out
.change_time
= smbcli_pull_nttime(req
->in
.vwv
, 35);
759 parms
->ntcreatexreadx
.out
.attrib
= IVAL(req
->in
.vwv
, 43);
760 parms
->ntcreatexreadx
.out
.alloc_size
= BVAL(req
->in
.vwv
, 47);
761 parms
->ntcreatexreadx
.out
.size
= BVAL(req
->in
.vwv
, 55);
762 parms
->ntcreatexreadx
.out
.file_type
= SVAL(req
->in
.vwv
, 63);
763 parms
->ntcreatexreadx
.out
.ipc_state
= SVAL(req
->in
.vwv
, 65);
764 parms
->ntcreatexreadx
.out
.is_directory
= CVAL(req
->in
.vwv
, 67);
766 status
= smbcli_chained_advance(req
);
767 if (!NT_STATUS_IS_OK(status
)) {
771 SMBCLI_CHECK_WCT(req
, 12);
772 parms
->ntcreatexreadx
.out
.remaining
= SVAL(req
->in
.vwv
, VWV(2));
773 parms
->ntcreatexreadx
.out
.compaction_mode
= SVAL(req
->in
.vwv
, VWV(3));
774 parms
->ntcreatexreadx
.out
.nread
= SVAL(req
->in
.vwv
, VWV(5));
775 if (parms
->ntcreatexreadx
.out
.nread
>
776 MAX(parms
->ntcreatexreadx
.in
.mincnt
, parms
->ntcreatexreadx
.in
.maxcnt
) ||
777 !smbcli_raw_pull_data(&req
->in
.bufinfo
, req
->in
.hdr
+ SVAL(req
->in
.vwv
, VWV(6)),
778 parms
->ntcreatexreadx
.out
.nread
,
779 parms
->ntcreatexreadx
.out
.data
)) {
780 req
->status
= NT_STATUS_BUFFER_TOO_SMALL
;
785 req
->status
= NT_STATUS_INTERNAL_ERROR
;
790 return smbcli_request_destroy(req
);
794 /****************************************************************************
795 Open a file - sync interface
796 ****************************************************************************/
797 _PUBLIC_ NTSTATUS
smb_raw_open(struct smbcli_tree
*tree
, TALLOC_CTX
*mem_ctx
, union smb_open
*parms
)
799 struct smbcli_request
*req
= smb_raw_open_send(tree
, parms
);
800 return smb_raw_open_recv(req
, mem_ctx
, parms
);
804 /****************************************************************************
805 Close a file - async send
806 ****************************************************************************/
807 _PUBLIC_
struct smbcli_request
*smb_raw_close_send(struct smbcli_tree
*tree
, union smb_close
*parms
)
809 struct smbcli_request
*req
= NULL
;
811 switch (parms
->generic
.level
) {
812 case RAW_CLOSE_CLOSE
:
813 SETUP_REQUEST(SMBclose
, 3, 0);
814 SSVAL(req
->out
.vwv
, VWV(0), parms
->close
.in
.file
.fnum
);
815 raw_push_dos_date3(tree
->session
->transport
,
816 req
->out
.vwv
, VWV(1), parms
->close
.in
.write_time
);
819 case RAW_CLOSE_SPLCLOSE
:
820 SETUP_REQUEST(SMBsplclose
, 3, 0);
821 SSVAL(req
->out
.vwv
, VWV(0), parms
->splclose
.in
.file
.fnum
);
822 SIVAL(req
->out
.vwv
, VWV(1), 0); /* reserved */
826 case RAW_CLOSE_GENERIC
:
830 if (!req
) return NULL
;
832 if (!smbcli_request_send(req
)) {
833 smbcli_request_destroy(req
);
841 /****************************************************************************
842 Close a file - sync interface
843 ****************************************************************************/
844 _PUBLIC_ NTSTATUS
smb_raw_close(struct smbcli_tree
*tree
, union smb_close
*parms
)
846 struct smbcli_request
*req
= smb_raw_close_send(tree
, parms
);
847 return smbcli_request_simple_recv(req
);
851 /****************************************************************************
852 Locking calls - async interface
853 ****************************************************************************/
854 struct smbcli_request
*smb_raw_lock_send(struct smbcli_tree
*tree
, union smb_lock
*parms
)
856 struct smbcli_request
*req
= NULL
;
858 switch (parms
->generic
.level
) {
860 SETUP_REQUEST(SMBlock
, 5, 0);
861 SSVAL(req
->out
.vwv
, VWV(0), parms
->lock
.in
.file
.fnum
);
862 SIVAL(req
->out
.vwv
, VWV(1), parms
->lock
.in
.count
);
863 SIVAL(req
->out
.vwv
, VWV(3), parms
->lock
.in
.offset
);
866 case RAW_LOCK_UNLOCK
:
867 SETUP_REQUEST(SMBunlock
, 5, 0);
868 SSVAL(req
->out
.vwv
, VWV(0), parms
->unlock
.in
.file
.fnum
);
869 SIVAL(req
->out
.vwv
, VWV(1), parms
->unlock
.in
.count
);
870 SIVAL(req
->out
.vwv
, VWV(3), parms
->unlock
.in
.offset
);
873 case RAW_LOCK_LOCKX
: {
874 struct smb_lock_entry
*lockp
;
875 unsigned int lck_size
= (parms
->lockx
.in
.mode
& LOCKING_ANDX_LARGE_FILES
)? 20 : 10;
876 unsigned int lock_count
= parms
->lockx
.in
.ulock_cnt
+ parms
->lockx
.in
.lock_cnt
;
879 SETUP_REQUEST(SMBlockingX
, 8, lck_size
* lock_count
);
880 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
881 SSVAL(req
->out
.vwv
, VWV(1), 0);
882 SSVAL(req
->out
.vwv
, VWV(2), parms
->lockx
.in
.file
.fnum
);
883 SSVAL(req
->out
.vwv
, VWV(3), parms
->lockx
.in
.mode
);
884 SIVAL(req
->out
.vwv
, VWV(4), parms
->lockx
.in
.timeout
);
885 SSVAL(req
->out
.vwv
, VWV(6), parms
->lockx
.in
.ulock_cnt
);
886 SSVAL(req
->out
.vwv
, VWV(7), parms
->lockx
.in
.lock_cnt
);
888 /* copy in all the locks */
889 lockp
= &parms
->lockx
.in
.locks
[0];
890 for (i
= 0; i
< lock_count
; i
++) {
891 uint8_t *p
= req
->out
.data
+ lck_size
* i
;
892 SSVAL(p
, 0, lockp
[i
].pid
);
893 if (parms
->lockx
.in
.mode
& LOCKING_ANDX_LARGE_FILES
) {
894 SSVAL(p
, 2, 0); /* reserved */
895 SIVAL(p
, 4, lockp
[i
].offset
>>32);
896 SIVAL(p
, 8, lockp
[i
].offset
);
897 SIVAL(p
, 12, lockp
[i
].count
>>32);
898 SIVAL(p
, 16, lockp
[i
].count
);
900 SIVAL(p
, 2, lockp
[i
].offset
);
901 SIVAL(p
, 6, lockp
[i
].count
);
907 case RAW_LOCK_SMB2_BREAK
:
911 if (!smbcli_request_send(req
)) {
912 smbcli_request_destroy(req
);
919 /****************************************************************************
920 Locking calls - sync interface
921 ****************************************************************************/
922 _PUBLIC_ NTSTATUS
smb_raw_lock(struct smbcli_tree
*tree
, union smb_lock
*parms
)
924 struct smbcli_request
*req
= smb_raw_lock_send(tree
, parms
);
925 return smbcli_request_simple_recv(req
);
929 /****************************************************************************
930 Check for existence of a dir - async send
931 ****************************************************************************/
932 struct smbcli_request
*smb_raw_chkpath_send(struct smbcli_tree
*tree
, union smb_chkpath
*parms
)
934 struct smbcli_request
*req
;
936 SETUP_REQUEST(SMBcheckpath
, 0, 0);
938 smbcli_req_append_ascii4(req
, parms
->chkpath
.in
.path
, STR_TERMINATE
);
940 if (!smbcli_request_send(req
)) {
941 smbcli_request_destroy(req
);
948 /****************************************************************************
949 Check for existence of a dir - sync interface
950 ****************************************************************************/
951 NTSTATUS
smb_raw_chkpath(struct smbcli_tree
*tree
, union smb_chkpath
*parms
)
953 struct smbcli_request
*req
= smb_raw_chkpath_send(tree
, parms
);
954 return smbcli_request_simple_recv(req
);
957 /****************************************************************************
958 flush a file - async send
959 a flush with RAW_FLUSH_ALL will flush all files
960 ****************************************************************************/
961 struct smbcli_request
*smb_raw_flush_send(struct smbcli_tree
*tree
, union smb_flush
*parms
)
963 struct smbcli_request
*req
;
966 switch (parms
->generic
.level
) {
967 case RAW_FLUSH_FLUSH
:
968 fnum
= parms
->flush
.in
.file
.fnum
;
977 SETUP_REQUEST(SMBflush
, 1, 0);
978 SSVAL(req
->out
.vwv
, VWV(0), fnum
);
980 if (!smbcli_request_send(req
)) {
981 smbcli_request_destroy(req
);
989 /****************************************************************************
990 flush a file - sync interface
991 ****************************************************************************/
992 _PUBLIC_ NTSTATUS
smb_raw_flush(struct smbcli_tree
*tree
, union smb_flush
*parms
)
994 struct smbcli_request
*req
= smb_raw_flush_send(tree
, parms
);
995 return smbcli_request_simple_recv(req
);
999 /****************************************************************************
1000 seek a file - async send
1001 ****************************************************************************/
1002 struct smbcli_request
*smb_raw_seek_send(struct smbcli_tree
*tree
,
1003 union smb_seek
*parms
)
1005 struct smbcli_request
*req
;
1007 SETUP_REQUEST(SMBlseek
, 4, 0);
1009 SSVAL(req
->out
.vwv
, VWV(0), parms
->lseek
.in
.file
.fnum
);
1010 SSVAL(req
->out
.vwv
, VWV(1), parms
->lseek
.in
.mode
);
1011 SIVALS(req
->out
.vwv
, VWV(2), parms
->lseek
.in
.offset
);
1013 if (!smbcli_request_send(req
)) {
1014 smbcli_request_destroy(req
);
1020 /****************************************************************************
1021 seek a file - async receive
1022 ****************************************************************************/
1023 NTSTATUS
smb_raw_seek_recv(struct smbcli_request
*req
,
1024 union smb_seek
*parms
)
1026 if (!smbcli_request_receive(req
) ||
1027 smbcli_request_is_error(req
)) {
1028 return smbcli_request_destroy(req
);
1031 SMBCLI_CHECK_WCT(req
, 2);
1032 parms
->lseek
.out
.offset
= IVAL(req
->in
.vwv
, VWV(0));
1035 return smbcli_request_destroy(req
);
1039 seek a file - sync interface
1041 _PUBLIC_ NTSTATUS
smb_raw_seek(struct smbcli_tree
*tree
,
1042 union smb_seek
*parms
)
1044 struct smbcli_request
*req
= smb_raw_seek_send(tree
, parms
);
1045 return smb_raw_seek_recv(req
, parms
);