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 if (sd_blob
.length
> 0) {
358 memcpy(nt
.in
.data
.data
, sd_blob
.data
, sd_blob
.length
);
360 if (ea_blob
.length
> 0) {
361 memcpy(nt
.in
.data
.data
+ sd_blob
.length
,
366 /* send the request on its way */
367 req
= smb_raw_nttrans_send(tree
, &nt
);
369 talloc_free(mem_ctx
);
375 /****************************************************************************
376 Open a file using TRANSACT2_OPEN - async send
377 ****************************************************************************/
378 static struct smbcli_request
*smb_raw_t2open_send(struct smbcli_tree
*tree
,
379 union smb_open
*parms
)
381 struct smb_trans2 t2
;
382 uint16_t setup
= TRANSACT2_OPEN
;
383 TALLOC_CTX
*mem_ctx
= talloc_init("smb_raw_t2open");
384 struct smbcli_request
*req
;
387 list_size
= ea_list_size(parms
->t2open
.in
.num_eas
, parms
->t2open
.in
.eas
);
389 t2
.in
.max_param
= 30;
394 t2
.in
.setup_count
= 1;
395 t2
.in
.setup
= &setup
;
396 t2
.in
.params
= data_blob_talloc(mem_ctx
, NULL
, 28);
397 t2
.in
.data
= data_blob_talloc(mem_ctx
, NULL
, list_size
);
399 SSVAL(t2
.in
.params
.data
, VWV(0), parms
->t2open
.in
.flags
);
400 SSVAL(t2
.in
.params
.data
, VWV(1), parms
->t2open
.in
.open_mode
);
401 SSVAL(t2
.in
.params
.data
, VWV(2), parms
->t2open
.in
.search_attrs
);
402 SSVAL(t2
.in
.params
.data
, VWV(3), parms
->t2open
.in
.file_attrs
);
403 raw_push_dos_date(tree
->session
->transport
,
404 t2
.in
.params
.data
, VWV(4), parms
->t2open
.in
.write_time
);
405 SSVAL(t2
.in
.params
.data
, VWV(6), parms
->t2open
.in
.open_func
);
406 SIVAL(t2
.in
.params
.data
, VWV(7), parms
->t2open
.in
.size
);
407 SIVAL(t2
.in
.params
.data
, VWV(9), parms
->t2open
.in
.timeout
);
408 SIVAL(t2
.in
.params
.data
, VWV(11), 0);
409 SSVAL(t2
.in
.params
.data
, VWV(13), 0);
411 smbcli_blob_append_string(tree
->session
, mem_ctx
,
412 &t2
.in
.params
, parms
->t2open
.in
.fname
,
415 ea_put_list(t2
.in
.data
.data
, parms
->t2open
.in
.num_eas
, parms
->t2open
.in
.eas
);
417 req
= smb_raw_trans2_send(tree
, &t2
);
419 talloc_free(mem_ctx
);
425 /****************************************************************************
426 Open a file using TRANSACT2_OPEN - async recv
427 ****************************************************************************/
428 static NTSTATUS
smb_raw_t2open_recv(struct smbcli_request
*req
, TALLOC_CTX
*mem_ctx
, union smb_open
*parms
)
430 struct smbcli_transport
*transport
= req
->transport
;
431 struct smb_trans2 t2
;
434 status
= smb_raw_trans2_recv(req
, mem_ctx
, &t2
);
435 if (!NT_STATUS_IS_OK(status
)) return status
;
437 if (t2
.out
.params
.length
< 30) {
438 return NT_STATUS_INFO_LENGTH_MISMATCH
;
441 parms
->t2open
.out
.file
.fnum
= SVAL(t2
.out
.params
.data
, VWV(0));
442 parms
->t2open
.out
.attrib
= SVAL(t2
.out
.params
.data
, VWV(1));
443 parms
->t2open
.out
.write_time
= raw_pull_dos_date3(transport
, t2
.out
.params
.data
+ VWV(2));
444 parms
->t2open
.out
.size
= IVAL(t2
.out
.params
.data
, VWV(4));
445 parms
->t2open
.out
.access
= SVAL(t2
.out
.params
.data
, VWV(6));
446 parms
->t2open
.out
.ftype
= SVAL(t2
.out
.params
.data
, VWV(7));
447 parms
->t2open
.out
.devstate
= SVAL(t2
.out
.params
.data
, VWV(8));
448 parms
->t2open
.out
.action
= SVAL(t2
.out
.params
.data
, VWV(9));
449 parms
->t2open
.out
.file_id
= SVAL(t2
.out
.params
.data
, VWV(10));
454 /****************************************************************************
455 Open a file - async send
456 ****************************************************************************/
457 _PUBLIC_
struct smbcli_request
*smb_raw_open_send(struct smbcli_tree
*tree
, union smb_open
*parms
)
460 struct smbcli_request
*req
= NULL
;
461 bool bigoffset
= false;
463 switch (parms
->generic
.level
) {
464 case RAW_OPEN_T2OPEN
:
465 return smb_raw_t2open_send(tree
, parms
);
468 SETUP_REQUEST(SMBopen
, 2, 0);
469 SSVAL(req
->out
.vwv
, VWV(0), parms
->openold
.in
.open_mode
);
470 SSVAL(req
->out
.vwv
, VWV(1), parms
->openold
.in
.search_attrs
);
471 smbcli_req_append_ascii4(req
, parms
->openold
.in
.fname
, STR_TERMINATE
);
475 SETUP_REQUEST(SMBopenX
, 15, 0);
476 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
477 SSVAL(req
->out
.vwv
, VWV(1), 0);
478 SSVAL(req
->out
.vwv
, VWV(2), parms
->openx
.in
.flags
);
479 SSVAL(req
->out
.vwv
, VWV(3), parms
->openx
.in
.open_mode
);
480 SSVAL(req
->out
.vwv
, VWV(4), parms
->openx
.in
.search_attrs
);
481 SSVAL(req
->out
.vwv
, VWV(5), parms
->openx
.in
.file_attrs
);
482 raw_push_dos_date3(tree
->session
->transport
,
483 req
->out
.vwv
, VWV(6), parms
->openx
.in
.write_time
);
484 SSVAL(req
->out
.vwv
, VWV(8), parms
->openx
.in
.open_func
);
485 SIVAL(req
->out
.vwv
, VWV(9), parms
->openx
.in
.size
);
486 SIVAL(req
->out
.vwv
, VWV(11),parms
->openx
.in
.timeout
);
487 SIVAL(req
->out
.vwv
, VWV(13),0); /* reserved */
488 smbcli_req_append_string(req
, parms
->openx
.in
.fname
, STR_TERMINATE
);
492 SETUP_REQUEST(SMBmknew
, 3, 0);
493 SSVAL(req
->out
.vwv
, VWV(0), parms
->mknew
.in
.attrib
);
494 raw_push_dos_date3(tree
->session
->transport
,
495 req
->out
.vwv
, VWV(1), parms
->mknew
.in
.write_time
);
496 smbcli_req_append_ascii4(req
, parms
->mknew
.in
.fname
, STR_TERMINATE
);
499 case RAW_OPEN_CREATE
:
500 SETUP_REQUEST(SMBcreate
, 3, 0);
501 SSVAL(req
->out
.vwv
, VWV(0), parms
->create
.in
.attrib
);
502 raw_push_dos_date3(tree
->session
->transport
,
503 req
->out
.vwv
, VWV(1), parms
->create
.in
.write_time
);
504 smbcli_req_append_ascii4(req
, parms
->create
.in
.fname
, STR_TERMINATE
);
508 SETUP_REQUEST(SMBctemp
, 3, 0);
509 SSVAL(req
->out
.vwv
, VWV(0), parms
->ctemp
.in
.attrib
);
510 raw_push_dos_date3(tree
->session
->transport
,
511 req
->out
.vwv
, VWV(1), parms
->ctemp
.in
.write_time
);
512 smbcli_req_append_ascii4(req
, parms
->ctemp
.in
.directory
, STR_TERMINATE
);
515 case RAW_OPEN_SPLOPEN
:
516 SETUP_REQUEST(SMBsplopen
, 2, 0);
517 SSVAL(req
->out
.vwv
, VWV(0), parms
->splopen
.in
.setup_length
);
518 SSVAL(req
->out
.vwv
, VWV(1), parms
->splopen
.in
.mode
);
521 case RAW_OPEN_NTCREATEX
:
522 SETUP_REQUEST(SMBntcreateX
, 24, 0);
523 SSVAL(req
->out
.vwv
, VWV(0),SMB_CHAIN_NONE
);
524 SSVAL(req
->out
.vwv
, VWV(1),0);
525 SCVAL(req
->out
.vwv
, VWV(2),0); /* padding */
526 SIVAL(req
->out
.vwv
, 7, parms
->ntcreatex
.in
.flags
);
527 SIVAL(req
->out
.vwv
, 11, parms
->ntcreatex
.in
.root_fid
.fnum
);
528 SIVAL(req
->out
.vwv
, 15, parms
->ntcreatex
.in
.access_mask
);
529 SBVAL(req
->out
.vwv
, 19, parms
->ntcreatex
.in
.alloc_size
);
530 SIVAL(req
->out
.vwv
, 27, parms
->ntcreatex
.in
.file_attr
);
531 SIVAL(req
->out
.vwv
, 31, parms
->ntcreatex
.in
.share_access
);
532 SIVAL(req
->out
.vwv
, 35, parms
->ntcreatex
.in
.open_disposition
);
533 SIVAL(req
->out
.vwv
, 39, parms
->ntcreatex
.in
.create_options
);
534 SIVAL(req
->out
.vwv
, 43, parms
->ntcreatex
.in
.impersonation
);
535 SCVAL(req
->out
.vwv
, 47, parms
->ntcreatex
.in
.security_flags
);
537 smbcli_req_append_string_len(req
, parms
->ntcreatex
.in
.fname
, STR_TERMINATE
, &len
);
538 SSVAL(req
->out
.vwv
, 5, len
);
541 case RAW_OPEN_NTTRANS_CREATE
:
542 return smb_raw_nttrans_create_send(tree
, parms
);
545 case RAW_OPEN_OPENX_READX
:
546 SETUP_REQUEST(SMBopenX
, 15, 0);
547 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
548 SSVAL(req
->out
.vwv
, VWV(1), 0);
549 SSVAL(req
->out
.vwv
, VWV(2), parms
->openxreadx
.in
.flags
);
550 SSVAL(req
->out
.vwv
, VWV(3), parms
->openxreadx
.in
.open_mode
);
551 SSVAL(req
->out
.vwv
, VWV(4), parms
->openxreadx
.in
.search_attrs
);
552 SSVAL(req
->out
.vwv
, VWV(5), parms
->openxreadx
.in
.file_attrs
);
553 raw_push_dos_date3(tree
->session
->transport
,
554 req
->out
.vwv
, VWV(6), parms
->openxreadx
.in
.write_time
);
555 SSVAL(req
->out
.vwv
, VWV(8), parms
->openxreadx
.in
.open_func
);
556 SIVAL(req
->out
.vwv
, VWV(9), parms
->openxreadx
.in
.size
);
557 SIVAL(req
->out
.vwv
, VWV(11),parms
->openxreadx
.in
.timeout
);
558 SIVAL(req
->out
.vwv
, VWV(13),0);
559 smbcli_req_append_string(req
, parms
->openxreadx
.in
.fname
, STR_TERMINATE
);
561 if (tree
->session
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
565 smbcli_chained_request_setup(req
, SMBreadX
, bigoffset
? 12 : 10, 0);
567 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
568 SSVAL(req
->out
.vwv
, VWV(1), 0);
569 SSVAL(req
->out
.vwv
, VWV(2), 0);
570 SIVAL(req
->out
.vwv
, VWV(3), parms
->openxreadx
.in
.offset
);
571 SSVAL(req
->out
.vwv
, VWV(5), parms
->openxreadx
.in
.maxcnt
& 0xFFFF);
572 SSVAL(req
->out
.vwv
, VWV(6), parms
->openxreadx
.in
.mincnt
);
573 SIVAL(req
->out
.vwv
, VWV(7), parms
->openxreadx
.in
.maxcnt
>> 16);
574 SSVAL(req
->out
.vwv
, VWV(9), parms
->openxreadx
.in
.remaining
);
576 SIVAL(req
->out
.vwv
, VWV(10),parms
->openxreadx
.in
.offset
>>32);
580 case RAW_OPEN_NTCREATEX_READX
:
581 SETUP_REQUEST(SMBntcreateX
, 24, 0);
582 SSVAL(req
->out
.vwv
, VWV(0),SMB_CHAIN_NONE
);
583 SSVAL(req
->out
.vwv
, VWV(1),0);
584 SCVAL(req
->out
.vwv
, VWV(2),0); /* padding */
585 SIVAL(req
->out
.vwv
, 7, parms
->ntcreatexreadx
.in
.flags
);
586 SIVAL(req
->out
.vwv
, 11, parms
->ntcreatexreadx
.in
.root_fid
.fnum
);
587 SIVAL(req
->out
.vwv
, 15, parms
->ntcreatexreadx
.in
.access_mask
);
588 SBVAL(req
->out
.vwv
, 19, parms
->ntcreatexreadx
.in
.alloc_size
);
589 SIVAL(req
->out
.vwv
, 27, parms
->ntcreatexreadx
.in
.file_attr
);
590 SIVAL(req
->out
.vwv
, 31, parms
->ntcreatexreadx
.in
.share_access
);
591 SIVAL(req
->out
.vwv
, 35, parms
->ntcreatexreadx
.in
.open_disposition
);
592 SIVAL(req
->out
.vwv
, 39, parms
->ntcreatexreadx
.in
.create_options
);
593 SIVAL(req
->out
.vwv
, 43, parms
->ntcreatexreadx
.in
.impersonation
);
594 SCVAL(req
->out
.vwv
, 47, parms
->ntcreatexreadx
.in
.security_flags
);
596 smbcli_req_append_string_len(req
, parms
->ntcreatexreadx
.in
.fname
, STR_TERMINATE
, &len
);
597 SSVAL(req
->out
.vwv
, 5, len
);
599 if (tree
->session
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
603 smbcli_chained_request_setup(req
, SMBreadX
, bigoffset
? 12 : 10, 0);
605 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
606 SSVAL(req
->out
.vwv
, VWV(1), 0);
607 SSVAL(req
->out
.vwv
, VWV(2), 0);
608 SIVAL(req
->out
.vwv
, VWV(3), parms
->ntcreatexreadx
.in
.offset
);
609 SSVAL(req
->out
.vwv
, VWV(5), parms
->ntcreatexreadx
.in
.maxcnt
& 0xFFFF);
610 SSVAL(req
->out
.vwv
, VWV(6), parms
->ntcreatexreadx
.in
.mincnt
);
611 SIVAL(req
->out
.vwv
, VWV(7), parms
->ntcreatexreadx
.in
.maxcnt
>> 16);
612 SSVAL(req
->out
.vwv
, VWV(9), parms
->ntcreatexreadx
.in
.remaining
);
614 SIVAL(req
->out
.vwv
, VWV(10),parms
->ntcreatexreadx
.in
.offset
>>32);
622 if (!smbcli_request_send(req
)) {
623 smbcli_request_destroy(req
);
630 /****************************************************************************
631 Open a file - async recv
632 ****************************************************************************/
633 _PUBLIC_ NTSTATUS
smb_raw_open_recv(struct smbcli_request
*req
, TALLOC_CTX
*mem_ctx
, union smb_open
*parms
)
637 if (!smbcli_request_receive(req
) ||
638 smbcli_request_is_error(req
)) {
642 switch (parms
->openold
.level
) {
643 case RAW_OPEN_T2OPEN
:
644 return smb_raw_t2open_recv(req
, mem_ctx
, parms
);
647 SMBCLI_CHECK_WCT(req
, 7);
648 parms
->openold
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(0));
649 parms
->openold
.out
.attrib
= SVAL(req
->in
.vwv
, VWV(1));
650 parms
->openold
.out
.write_time
= raw_pull_dos_date3(req
->transport
,
651 req
->in
.vwv
+ VWV(2));
652 parms
->openold
.out
.size
= IVAL(req
->in
.vwv
, VWV(4));
653 parms
->openold
.out
.rmode
= SVAL(req
->in
.vwv
, VWV(6));
657 SMBCLI_CHECK_MIN_WCT(req
, 15);
658 parms
->openx
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(2));
659 parms
->openx
.out
.attrib
= SVAL(req
->in
.vwv
, VWV(3));
660 parms
->openx
.out
.write_time
= raw_pull_dos_date3(req
->transport
,
661 req
->in
.vwv
+ VWV(4));
662 parms
->openx
.out
.size
= IVAL(req
->in
.vwv
, VWV(6));
663 parms
->openx
.out
.access
= SVAL(req
->in
.vwv
, VWV(8));
664 parms
->openx
.out
.ftype
= SVAL(req
->in
.vwv
, VWV(9));
665 parms
->openx
.out
.devstate
= SVAL(req
->in
.vwv
, VWV(10));
666 parms
->openx
.out
.action
= SVAL(req
->in
.vwv
, VWV(11));
667 parms
->openx
.out
.unique_fid
= IVAL(req
->in
.vwv
, VWV(12));
668 if (req
->in
.wct
>= 19) {
669 parms
->openx
.out
.access_mask
= IVAL(req
->in
.vwv
, VWV(15));
670 parms
->openx
.out
.unknown
= IVAL(req
->in
.vwv
, VWV(17));
672 parms
->openx
.out
.access_mask
= 0;
673 parms
->openx
.out
.unknown
= 0;
678 SMBCLI_CHECK_WCT(req
, 1);
679 parms
->mknew
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(0));
682 case RAW_OPEN_CREATE
:
683 SMBCLI_CHECK_WCT(req
, 1);
684 parms
->create
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(0));
688 SMBCLI_CHECK_WCT(req
, 1);
689 parms
->ctemp
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(0));
690 smbcli_req_pull_string(&req
->in
.bufinfo
, mem_ctx
, &parms
->ctemp
.out
.name
, req
->in
.data
, -1, STR_TERMINATE
| STR_ASCII
);
693 case RAW_OPEN_SPLOPEN
:
694 SMBCLI_CHECK_WCT(req
, 1);
695 parms
->splopen
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(0));
698 case RAW_OPEN_NTCREATEX
:
699 SMBCLI_CHECK_MIN_WCT(req
, 34);
700 parms
->ntcreatex
.out
.oplock_level
= CVAL(req
->in
.vwv
, 4);
701 parms
->ntcreatex
.out
.file
.fnum
= SVAL(req
->in
.vwv
, 5);
702 parms
->ntcreatex
.out
.create_action
= IVAL(req
->in
.vwv
, 7);
703 parms
->ntcreatex
.out
.create_time
= smbcli_pull_nttime(req
->in
.vwv
, 11);
704 parms
->ntcreatex
.out
.access_time
= smbcli_pull_nttime(req
->in
.vwv
, 19);
705 parms
->ntcreatex
.out
.write_time
= smbcli_pull_nttime(req
->in
.vwv
, 27);
706 parms
->ntcreatex
.out
.change_time
= smbcli_pull_nttime(req
->in
.vwv
, 35);
707 parms
->ntcreatex
.out
.attrib
= IVAL(req
->in
.vwv
, 43);
708 parms
->ntcreatex
.out
.alloc_size
= BVAL(req
->in
.vwv
, 47);
709 parms
->ntcreatex
.out
.size
= BVAL(req
->in
.vwv
, 55);
710 parms
->ntcreatex
.out
.file_type
= SVAL(req
->in
.vwv
, 63);
711 parms
->ntcreatex
.out
.ipc_state
= SVAL(req
->in
.vwv
, 65);
712 parms
->ntcreatex
.out
.is_directory
= CVAL(req
->in
.vwv
, 67);
715 case RAW_OPEN_NTTRANS_CREATE
:
716 return smb_raw_nttrans_create_recv(req
, mem_ctx
, parms
);
718 case RAW_OPEN_OPENX_READX
:
719 SMBCLI_CHECK_MIN_WCT(req
, 15);
720 parms
->openxreadx
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(2));
721 parms
->openxreadx
.out
.attrib
= SVAL(req
->in
.vwv
, VWV(3));
722 parms
->openxreadx
.out
.write_time
= raw_pull_dos_date3(req
->transport
,
723 req
->in
.vwv
+ VWV(4));
724 parms
->openxreadx
.out
.size
= IVAL(req
->in
.vwv
, VWV(6));
725 parms
->openxreadx
.out
.access
= SVAL(req
->in
.vwv
, VWV(8));
726 parms
->openxreadx
.out
.ftype
= SVAL(req
->in
.vwv
, VWV(9));
727 parms
->openxreadx
.out
.devstate
= SVAL(req
->in
.vwv
, VWV(10));
728 parms
->openxreadx
.out
.action
= SVAL(req
->in
.vwv
, VWV(11));
729 parms
->openxreadx
.out
.unique_fid
= IVAL(req
->in
.vwv
, VWV(12));
730 if (req
->in
.wct
>= 19) {
731 parms
->openxreadx
.out
.access_mask
= IVAL(req
->in
.vwv
, VWV(15));
732 parms
->openxreadx
.out
.unknown
= IVAL(req
->in
.vwv
, VWV(17));
734 parms
->openxreadx
.out
.access_mask
= 0;
735 parms
->openxreadx
.out
.unknown
= 0;
738 status
= smbcli_chained_advance(req
);
739 if (!NT_STATUS_IS_OK(status
)) {
743 SMBCLI_CHECK_WCT(req
, 12);
744 parms
->openxreadx
.out
.remaining
= SVAL(req
->in
.vwv
, VWV(2));
745 parms
->openxreadx
.out
.compaction_mode
= SVAL(req
->in
.vwv
, VWV(3));
746 parms
->openxreadx
.out
.nread
= SVAL(req
->in
.vwv
, VWV(5));
747 if (parms
->openxreadx
.out
.nread
>
748 MAX(parms
->openxreadx
.in
.mincnt
, parms
->openxreadx
.in
.maxcnt
) ||
749 !smbcli_raw_pull_data(&req
->in
.bufinfo
, req
->in
.hdr
+ SVAL(req
->in
.vwv
, VWV(6)),
750 parms
->openxreadx
.out
.nread
,
751 parms
->openxreadx
.out
.data
)) {
752 req
->status
= NT_STATUS_BUFFER_TOO_SMALL
;
756 case RAW_OPEN_NTCREATEX_READX
:
757 SMBCLI_CHECK_MIN_WCT(req
, 34);
758 parms
->ntcreatexreadx
.out
.oplock_level
= CVAL(req
->in
.vwv
, 4);
759 parms
->ntcreatexreadx
.out
.file
.fnum
= SVAL(req
->in
.vwv
, 5);
760 parms
->ntcreatexreadx
.out
.create_action
= IVAL(req
->in
.vwv
, 7);
761 parms
->ntcreatexreadx
.out
.create_time
= smbcli_pull_nttime(req
->in
.vwv
, 11);
762 parms
->ntcreatexreadx
.out
.access_time
= smbcli_pull_nttime(req
->in
.vwv
, 19);
763 parms
->ntcreatexreadx
.out
.write_time
= smbcli_pull_nttime(req
->in
.vwv
, 27);
764 parms
->ntcreatexreadx
.out
.change_time
= smbcli_pull_nttime(req
->in
.vwv
, 35);
765 parms
->ntcreatexreadx
.out
.attrib
= IVAL(req
->in
.vwv
, 43);
766 parms
->ntcreatexreadx
.out
.alloc_size
= BVAL(req
->in
.vwv
, 47);
767 parms
->ntcreatexreadx
.out
.size
= BVAL(req
->in
.vwv
, 55);
768 parms
->ntcreatexreadx
.out
.file_type
= SVAL(req
->in
.vwv
, 63);
769 parms
->ntcreatexreadx
.out
.ipc_state
= SVAL(req
->in
.vwv
, 65);
770 parms
->ntcreatexreadx
.out
.is_directory
= CVAL(req
->in
.vwv
, 67);
772 status
= smbcli_chained_advance(req
);
773 if (!NT_STATUS_IS_OK(status
)) {
777 SMBCLI_CHECK_WCT(req
, 12);
778 parms
->ntcreatexreadx
.out
.remaining
= SVAL(req
->in
.vwv
, VWV(2));
779 parms
->ntcreatexreadx
.out
.compaction_mode
= SVAL(req
->in
.vwv
, VWV(3));
780 parms
->ntcreatexreadx
.out
.nread
= SVAL(req
->in
.vwv
, VWV(5));
781 if (parms
->ntcreatexreadx
.out
.nread
>
782 MAX(parms
->ntcreatexreadx
.in
.mincnt
, parms
->ntcreatexreadx
.in
.maxcnt
) ||
783 !smbcli_raw_pull_data(&req
->in
.bufinfo
, req
->in
.hdr
+ SVAL(req
->in
.vwv
, VWV(6)),
784 parms
->ntcreatexreadx
.out
.nread
,
785 parms
->ntcreatexreadx
.out
.data
)) {
786 req
->status
= NT_STATUS_BUFFER_TOO_SMALL
;
791 req
->status
= NT_STATUS_INTERNAL_ERROR
;
796 return smbcli_request_destroy(req
);
800 /****************************************************************************
801 Open a file - sync interface
802 ****************************************************************************/
803 _PUBLIC_ NTSTATUS
smb_raw_open(struct smbcli_tree
*tree
, TALLOC_CTX
*mem_ctx
, union smb_open
*parms
)
805 struct smbcli_request
*req
= smb_raw_open_send(tree
, parms
);
806 return smb_raw_open_recv(req
, mem_ctx
, parms
);
810 /****************************************************************************
811 Close a file - async send
812 ****************************************************************************/
813 _PUBLIC_
struct smbcli_request
*smb_raw_close_send(struct smbcli_tree
*tree
, union smb_close
*parms
)
815 struct smbcli_request
*req
= NULL
;
817 switch (parms
->generic
.level
) {
818 case RAW_CLOSE_CLOSE
:
819 SETUP_REQUEST(SMBclose
, 3, 0);
820 SSVAL(req
->out
.vwv
, VWV(0), parms
->close
.in
.file
.fnum
);
821 raw_push_dos_date3(tree
->session
->transport
,
822 req
->out
.vwv
, VWV(1), parms
->close
.in
.write_time
);
825 case RAW_CLOSE_SPLCLOSE
:
826 SETUP_REQUEST(SMBsplclose
, 3, 0);
827 SSVAL(req
->out
.vwv
, VWV(0), parms
->splclose
.in
.file
.fnum
);
828 SIVAL(req
->out
.vwv
, VWV(1), 0); /* reserved */
832 case RAW_CLOSE_GENERIC
:
836 if (!req
) return NULL
;
838 if (!smbcli_request_send(req
)) {
839 smbcli_request_destroy(req
);
847 /****************************************************************************
848 Close a file - sync interface
849 ****************************************************************************/
850 _PUBLIC_ NTSTATUS
smb_raw_close(struct smbcli_tree
*tree
, union smb_close
*parms
)
852 struct smbcli_request
*req
= smb_raw_close_send(tree
, parms
);
853 return smbcli_request_simple_recv(req
);
857 /****************************************************************************
858 Locking calls - async interface
859 ****************************************************************************/
860 struct smbcli_request
*smb_raw_lock_send(struct smbcli_tree
*tree
, union smb_lock
*parms
)
862 struct smbcli_request
*req
= NULL
;
864 switch (parms
->generic
.level
) {
866 SETUP_REQUEST(SMBlock
, 5, 0);
867 SSVAL(req
->out
.vwv
, VWV(0), parms
->lock
.in
.file
.fnum
);
868 SIVAL(req
->out
.vwv
, VWV(1), parms
->lock
.in
.count
);
869 SIVAL(req
->out
.vwv
, VWV(3), parms
->lock
.in
.offset
);
872 case RAW_LOCK_UNLOCK
:
873 SETUP_REQUEST(SMBunlock
, 5, 0);
874 SSVAL(req
->out
.vwv
, VWV(0), parms
->unlock
.in
.file
.fnum
);
875 SIVAL(req
->out
.vwv
, VWV(1), parms
->unlock
.in
.count
);
876 SIVAL(req
->out
.vwv
, VWV(3), parms
->unlock
.in
.offset
);
879 case RAW_LOCK_LOCKX
: {
880 struct smb_lock_entry
*lockp
;
881 unsigned int lck_size
= (parms
->lockx
.in
.mode
& LOCKING_ANDX_LARGE_FILES
)? 20 : 10;
882 unsigned int lock_count
= parms
->lockx
.in
.ulock_cnt
+ parms
->lockx
.in
.lock_cnt
;
885 SETUP_REQUEST(SMBlockingX
, 8, lck_size
* lock_count
);
886 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
887 SSVAL(req
->out
.vwv
, VWV(1), 0);
888 SSVAL(req
->out
.vwv
, VWV(2), parms
->lockx
.in
.file
.fnum
);
889 SSVAL(req
->out
.vwv
, VWV(3), parms
->lockx
.in
.mode
);
890 SIVAL(req
->out
.vwv
, VWV(4), parms
->lockx
.in
.timeout
);
891 SSVAL(req
->out
.vwv
, VWV(6), parms
->lockx
.in
.ulock_cnt
);
892 SSVAL(req
->out
.vwv
, VWV(7), parms
->lockx
.in
.lock_cnt
);
894 /* copy in all the locks */
895 lockp
= &parms
->lockx
.in
.locks
[0];
896 for (i
= 0; i
< lock_count
; i
++) {
897 uint8_t *p
= req
->out
.data
+ lck_size
* i
;
898 SSVAL(p
, 0, lockp
[i
].pid
);
899 if (parms
->lockx
.in
.mode
& LOCKING_ANDX_LARGE_FILES
) {
900 SSVAL(p
, 2, 0); /* reserved */
901 SIVAL(p
, 4, lockp
[i
].offset
>>32);
902 SIVAL(p
, 8, lockp
[i
].offset
);
903 SIVAL(p
, 12, lockp
[i
].count
>>32);
904 SIVAL(p
, 16, lockp
[i
].count
);
906 SIVAL(p
, 2, lockp
[i
].offset
);
907 SIVAL(p
, 6, lockp
[i
].count
);
913 case RAW_LOCK_SMB2_BREAK
:
917 if (!smbcli_request_send(req
)) {
918 smbcli_request_destroy(req
);
925 /****************************************************************************
926 Locking calls - sync interface
927 ****************************************************************************/
928 _PUBLIC_ NTSTATUS
smb_raw_lock(struct smbcli_tree
*tree
, union smb_lock
*parms
)
930 struct smbcli_request
*req
= smb_raw_lock_send(tree
, parms
);
931 return smbcli_request_simple_recv(req
);
935 /****************************************************************************
936 Check for existence of a dir - async send
937 ****************************************************************************/
938 struct smbcli_request
*smb_raw_chkpath_send(struct smbcli_tree
*tree
, union smb_chkpath
*parms
)
940 struct smbcli_request
*req
;
942 SETUP_REQUEST(SMBcheckpath
, 0, 0);
944 smbcli_req_append_ascii4(req
, parms
->chkpath
.in
.path
, STR_TERMINATE
);
946 if (!smbcli_request_send(req
)) {
947 smbcli_request_destroy(req
);
954 /****************************************************************************
955 Check for existence of a dir - sync interface
956 ****************************************************************************/
957 NTSTATUS
smb_raw_chkpath(struct smbcli_tree
*tree
, union smb_chkpath
*parms
)
959 struct smbcli_request
*req
= smb_raw_chkpath_send(tree
, parms
);
960 return smbcli_request_simple_recv(req
);
963 /****************************************************************************
964 flush a file - async send
965 a flush with RAW_FLUSH_ALL will flush all files
966 ****************************************************************************/
967 struct smbcli_request
*smb_raw_flush_send(struct smbcli_tree
*tree
, union smb_flush
*parms
)
969 struct smbcli_request
*req
;
972 switch (parms
->generic
.level
) {
973 case RAW_FLUSH_FLUSH
:
974 fnum
= parms
->flush
.in
.file
.fnum
;
983 SETUP_REQUEST(SMBflush
, 1, 0);
984 SSVAL(req
->out
.vwv
, VWV(0), fnum
);
986 if (!smbcli_request_send(req
)) {
987 smbcli_request_destroy(req
);
995 /****************************************************************************
996 flush a file - sync interface
997 ****************************************************************************/
998 _PUBLIC_ NTSTATUS
smb_raw_flush(struct smbcli_tree
*tree
, union smb_flush
*parms
)
1000 struct smbcli_request
*req
= smb_raw_flush_send(tree
, parms
);
1001 return smbcli_request_simple_recv(req
);
1005 /****************************************************************************
1006 seek a file - async send
1007 ****************************************************************************/
1008 struct smbcli_request
*smb_raw_seek_send(struct smbcli_tree
*tree
,
1009 union smb_seek
*parms
)
1011 struct smbcli_request
*req
;
1013 SETUP_REQUEST(SMBlseek
, 4, 0);
1015 SSVAL(req
->out
.vwv
, VWV(0), parms
->lseek
.in
.file
.fnum
);
1016 SSVAL(req
->out
.vwv
, VWV(1), parms
->lseek
.in
.mode
);
1017 SIVALS(req
->out
.vwv
, VWV(2), parms
->lseek
.in
.offset
);
1019 if (!smbcli_request_send(req
)) {
1020 smbcli_request_destroy(req
);
1026 /****************************************************************************
1027 seek a file - async receive
1028 ****************************************************************************/
1029 NTSTATUS
smb_raw_seek_recv(struct smbcli_request
*req
,
1030 union smb_seek
*parms
)
1032 if (!smbcli_request_receive(req
) ||
1033 smbcli_request_is_error(req
)) {
1034 return smbcli_request_destroy(req
);
1037 SMBCLI_CHECK_WCT(req
, 2);
1038 parms
->lseek
.out
.offset
= IVAL(req
->in
.vwv
, VWV(0));
1041 return smbcli_request_destroy(req
);
1045 seek a file - sync interface
1047 _PUBLIC_ NTSTATUS
smb_raw_seek(struct smbcli_tree
*tree
,
1048 union smb_seek
*parms
)
1050 struct smbcli_request
*req
= smb_raw_seek_send(tree
, parms
);
1051 return smb_raw_seek_recv(req
, parms
);