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; \
33 Return a string representing a CIFS attribute for a file.
35 char *attrib_string(TALLOC_CTX
*mem_ctx
, uint32_t attrib
)
42 {'V', FILE_ATTRIBUTE_VOLUME
},
43 {'D', FILE_ATTRIBUTE_DIRECTORY
},
44 {'A', FILE_ATTRIBUTE_ARCHIVE
},
45 {'H', FILE_ATTRIBUTE_HIDDEN
},
46 {'S', FILE_ATTRIBUTE_SYSTEM
},
47 {'N', FILE_ATTRIBUTE_NORMAL
},
48 {'R', FILE_ATTRIBUTE_READONLY
},
49 {'d', FILE_ATTRIBUTE_DEVICE
},
50 {'t', FILE_ATTRIBUTE_TEMPORARY
},
51 {'s', FILE_ATTRIBUTE_SPARSE
},
52 {'r', FILE_ATTRIBUTE_REPARSE_POINT
},
53 {'c', FILE_ATTRIBUTE_COMPRESSED
},
54 {'o', FILE_ATTRIBUTE_OFFLINE
},
55 {'n', FILE_ATTRIBUTE_NONINDEXED
},
56 {'e', FILE_ATTRIBUTE_ENCRYPTED
}
60 ret
= talloc_array(mem_ctx
, char, ARRAY_SIZE(attr_strs
)+1);
65 for (len
=i
=0; i
<ARRAY_SIZE(attr_strs
); i
++) {
66 if (attrib
& attr_strs
[i
].attr
) {
67 ret
[len
++] = attr_strs
[i
].c
;
73 talloc_set_name_const(ret
, ret
);
78 /****************************************************************************
79 Rename a file - async interface
80 ****************************************************************************/
81 struct smbcli_request
*smb_raw_rename_send(struct smbcli_tree
*tree
,
82 union smb_rename
*parms
)
84 struct smbcli_request
*req
= NULL
;
85 struct smb_nttrans nt
;
88 switch (parms
->generic
.level
) {
89 case RAW_RENAME_RENAME
:
90 SETUP_REQUEST(SMBmv
, 1, 0);
91 SSVAL(req
->out
.vwv
, VWV(0), parms
->rename
.in
.attrib
);
92 smbcli_req_append_ascii4(req
, parms
->rename
.in
.pattern1
, STR_TERMINATE
);
93 smbcli_req_append_ascii4(req
, parms
->rename
.in
.pattern2
, STR_TERMINATE
);
96 case RAW_RENAME_NTRENAME
:
97 SETUP_REQUEST(SMBntrename
, 4, 0);
98 SSVAL(req
->out
.vwv
, VWV(0), parms
->ntrename
.in
.attrib
);
99 SSVAL(req
->out
.vwv
, VWV(1), parms
->ntrename
.in
.flags
);
100 SIVAL(req
->out
.vwv
, VWV(2), parms
->ntrename
.in
.cluster_size
);
101 smbcli_req_append_ascii4(req
, parms
->ntrename
.in
.old_name
, STR_TERMINATE
);
102 smbcli_req_append_ascii4(req
, parms
->ntrename
.in
.new_name
, STR_TERMINATE
);
105 case RAW_RENAME_NTTRANS
:
107 mem_ctx
= talloc_new(tree
);
112 nt
.in
.setup_count
= 0;
114 nt
.in
.function
= NT_TRANSACT_RENAME
;
115 nt
.in
.params
= data_blob_talloc(mem_ctx
, NULL
, 4);
116 nt
.in
.data
= data_blob(NULL
, 0);
118 SSVAL(nt
.in
.params
.data
, VWV(0), parms
->nttrans
.in
.file
.fnum
);
119 SSVAL(nt
.in
.params
.data
, VWV(1), parms
->nttrans
.in
.flags
);
121 smbcli_blob_append_string(tree
->session
, mem_ctx
,
122 &nt
.in
.params
, parms
->nttrans
.in
.new_name
,
125 req
= smb_raw_nttrans_send(tree
, &nt
);
126 talloc_free(mem_ctx
);
130 if (!smbcli_request_send(req
)) {
131 smbcli_request_destroy(req
);
138 /****************************************************************************
139 Rename a file - sync interface
140 ****************************************************************************/
141 _PUBLIC_ NTSTATUS
smb_raw_rename(struct smbcli_tree
*tree
,
142 union smb_rename
*parms
)
144 struct smbcli_request
*req
= smb_raw_rename_send(tree
, parms
);
145 return smbcli_request_simple_recv(req
);
149 /****************************************************************************
150 Delete a file - async interface
151 ****************************************************************************/
152 struct smbcli_request
*smb_raw_unlink_send(struct smbcli_tree
*tree
,
153 union smb_unlink
*parms
)
155 struct smbcli_request
*req
;
157 SETUP_REQUEST(SMBunlink
, 1, 0);
159 SSVAL(req
->out
.vwv
, VWV(0), parms
->unlink
.in
.attrib
);
160 smbcli_req_append_ascii4(req
, parms
->unlink
.in
.pattern
, STR_TERMINATE
);
162 if (!smbcli_request_send(req
)) {
163 smbcli_request_destroy(req
);
170 delete a file - sync interface
172 _PUBLIC_ NTSTATUS
smb_raw_unlink(struct smbcli_tree
*tree
,
173 union smb_unlink
*parms
)
175 struct smbcli_request
*req
= smb_raw_unlink_send(tree
, parms
);
176 return smbcli_request_simple_recv(req
);
180 /****************************************************************************
181 create a directory using TRANSACT2_MKDIR - async interface
182 ****************************************************************************/
183 static struct smbcli_request
*smb_raw_t2mkdir_send(struct smbcli_tree
*tree
,
184 union smb_mkdir
*parms
)
186 struct smb_trans2 t2
;
187 uint16_t setup
= TRANSACT2_MKDIR
;
189 struct smbcli_request
*req
;
192 mem_ctx
= talloc_init("t2mkdir");
194 data_total
= ea_list_size(parms
->t2mkdir
.in
.num_eas
, parms
->t2mkdir
.in
.eas
);
201 t2
.in
.setup_count
= 1;
202 t2
.in
.setup
= &setup
;
203 t2
.in
.params
= data_blob_talloc(mem_ctx
, NULL
, 4);
204 t2
.in
.data
= data_blob_talloc(mem_ctx
, NULL
, data_total
);
206 SIVAL(t2
.in
.params
.data
, VWV(0), 0); /* reserved */
208 smbcli_blob_append_string(tree
->session
, mem_ctx
,
209 &t2
.in
.params
, parms
->t2mkdir
.in
.path
, STR_TERMINATE
);
211 ea_put_list(t2
.in
.data
.data
, parms
->t2mkdir
.in
.num_eas
, parms
->t2mkdir
.in
.eas
);
213 req
= smb_raw_trans2_send(tree
, &t2
);
215 talloc_free(mem_ctx
);
220 /****************************************************************************
221 Create a directory - async interface
222 ****************************************************************************/
223 struct smbcli_request
*smb_raw_mkdir_send(struct smbcli_tree
*tree
,
224 union smb_mkdir
*parms
)
226 struct smbcli_request
*req
;
228 if (parms
->generic
.level
== RAW_MKDIR_T2MKDIR
) {
229 return smb_raw_t2mkdir_send(tree
, parms
);
232 if (parms
->generic
.level
!= RAW_MKDIR_MKDIR
) {
236 SETUP_REQUEST(SMBmkdir
, 0, 0);
238 smbcli_req_append_ascii4(req
, parms
->mkdir
.in
.path
, STR_TERMINATE
);
240 if (!smbcli_request_send(req
)) {
247 /****************************************************************************
248 Create a directory - sync interface
249 ****************************************************************************/
250 _PUBLIC_ NTSTATUS
smb_raw_mkdir(struct smbcli_tree
*tree
,
251 union smb_mkdir
*parms
)
253 struct smbcli_request
*req
= smb_raw_mkdir_send(tree
, parms
);
254 return smbcli_request_simple_recv(req
);
257 /****************************************************************************
258 Remove a directory - async interface
259 ****************************************************************************/
260 struct smbcli_request
*smb_raw_rmdir_send(struct smbcli_tree
*tree
,
261 struct smb_rmdir
*parms
)
263 struct smbcli_request
*req
;
265 SETUP_REQUEST(SMBrmdir
, 0, 0);
267 smbcli_req_append_ascii4(req
, parms
->in
.path
, STR_TERMINATE
);
269 if (!smbcli_request_send(req
)) {
270 smbcli_request_destroy(req
);
277 /****************************************************************************
278 Remove a directory - sync interface
279 ****************************************************************************/
280 _PUBLIC_ NTSTATUS
smb_raw_rmdir(struct smbcli_tree
*tree
,
281 struct smb_rmdir
*parms
)
283 struct smbcli_request
*req
= smb_raw_rmdir_send(tree
, parms
);
284 return smbcli_request_simple_recv(req
);
289 Open a file using TRANSACT2_OPEN - async recv
291 static NTSTATUS
smb_raw_nttrans_create_recv(struct smbcli_request
*req
,
293 union smb_open
*parms
)
296 struct smb_nttrans nt
;
299 status
= smb_raw_nttrans_recv(req
, mem_ctx
, &nt
);
300 if (!NT_STATUS_IS_OK(status
)) return status
;
302 if (nt
.out
.params
.length
< 69) {
303 return NT_STATUS_INVALID_PARAMETER
;
306 params
= nt
.out
.params
.data
;
308 parms
->ntcreatex
.out
.oplock_level
= CVAL(params
, 0);
309 parms
->ntcreatex
.out
.file
.fnum
= SVAL(params
, 2);
310 parms
->ntcreatex
.out
.create_action
= IVAL(params
, 4);
311 parms
->ntcreatex
.out
.create_time
= smbcli_pull_nttime(params
, 12);
312 parms
->ntcreatex
.out
.access_time
= smbcli_pull_nttime(params
, 20);
313 parms
->ntcreatex
.out
.write_time
= smbcli_pull_nttime(params
, 28);
314 parms
->ntcreatex
.out
.change_time
= smbcli_pull_nttime(params
, 36);
315 parms
->ntcreatex
.out
.attrib
= IVAL(params
, 44);
316 parms
->ntcreatex
.out
.alloc_size
= BVAL(params
, 48);
317 parms
->ntcreatex
.out
.size
= BVAL(params
, 56);
318 parms
->ntcreatex
.out
.file_type
= SVAL(params
, 64);
319 parms
->ntcreatex
.out
.ipc_state
= SVAL(params
, 66);
320 parms
->ntcreatex
.out
.is_directory
= CVAL(params
, 68);
327 Open a file using NTTRANS CREATE - async send
329 static struct smbcli_request
*smb_raw_nttrans_create_send(struct smbcli_tree
*tree
,
330 union smb_open
*parms
)
332 struct smb_nttrans nt
;
334 TALLOC_CTX
*mem_ctx
= talloc_new(tree
);
336 DATA_BLOB sd_blob
, ea_blob
;
337 struct smbcli_request
*req
;
340 nt
.in
.max_param
= 101;
342 nt
.in
.setup_count
= 0;
343 nt
.in
.function
= NT_TRANSACT_CREATE
;
346 sd_blob
= data_blob(NULL
, 0);
347 ea_blob
= data_blob(NULL
, 0);
349 if (parms
->ntcreatex
.in
.sec_desc
) {
350 enum ndr_err_code ndr_err
;
351 ndr_err
= ndr_push_struct_blob(&sd_blob
, mem_ctx
, NULL
,
352 parms
->ntcreatex
.in
.sec_desc
,
353 (ndr_push_flags_fn_t
)ndr_push_security_descriptor
);
354 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
355 talloc_free(mem_ctx
);
360 if (parms
->ntcreatex
.in
.ea_list
) {
361 uint32_t ea_size
= ea_list_size_chained(parms
->ntcreatex
.in
.ea_list
->num_eas
,
362 parms
->ntcreatex
.in
.ea_list
->eas
, 4);
363 ea_blob
= data_blob_talloc(mem_ctx
, NULL
, ea_size
);
364 if (ea_blob
.data
== NULL
) {
367 ea_put_list_chained(ea_blob
.data
,
368 parms
->ntcreatex
.in
.ea_list
->num_eas
,
369 parms
->ntcreatex
.in
.ea_list
->eas
, 4);
372 nt
.in
.params
= data_blob_talloc(mem_ctx
, NULL
, 53);
373 if (nt
.in
.params
.data
== NULL
) {
374 talloc_free(mem_ctx
);
378 /* build the parameter section */
379 params
= nt
.in
.params
.data
;
381 SIVAL(params
, 0, parms
->ntcreatex
.in
.flags
);
382 SIVAL(params
, 4, parms
->ntcreatex
.in
.root_fid
);
383 SIVAL(params
, 8, parms
->ntcreatex
.in
.access_mask
);
384 SBVAL(params
, 12, parms
->ntcreatex
.in
.alloc_size
);
385 SIVAL(params
, 20, parms
->ntcreatex
.in
.file_attr
);
386 SIVAL(params
, 24, parms
->ntcreatex
.in
.share_access
);
387 SIVAL(params
, 28, parms
->ntcreatex
.in
.open_disposition
);
388 SIVAL(params
, 32, parms
->ntcreatex
.in
.create_options
);
389 SIVAL(params
, 36, sd_blob
.length
);
390 SIVAL(params
, 40, ea_blob
.length
);
391 SIVAL(params
, 48, parms
->ntcreatex
.in
.impersonation
);
392 SCVAL(params
, 52, parms
->ntcreatex
.in
.security_flags
);
394 /* the empty string first forces the correct alignment */
395 smbcli_blob_append_string(tree
->session
, mem_ctx
, &nt
.in
.params
,"", 0);
396 fname_len
= smbcli_blob_append_string(tree
->session
, mem_ctx
, &nt
.in
.params
,
397 parms
->ntcreatex
.in
.fname
, STR_TERMINATE
);
399 SIVAL(nt
.in
.params
.data
, 44, fname_len
);
401 /* build the data section */
402 nt
.in
.data
= data_blob_talloc(mem_ctx
, NULL
, sd_blob
.length
+ ea_blob
.length
);
403 memcpy(nt
.in
.data
.data
, sd_blob
.data
, sd_blob
.length
);
404 memcpy(nt
.in
.data
.data
+sd_blob
.length
, ea_blob
.data
, ea_blob
.length
);
406 /* send the request on its way */
407 req
= smb_raw_nttrans_send(tree
, &nt
);
409 talloc_free(mem_ctx
);
415 /****************************************************************************
416 Open a file using TRANSACT2_OPEN - async send
417 ****************************************************************************/
418 static struct smbcli_request
*smb_raw_t2open_send(struct smbcli_tree
*tree
,
419 union smb_open
*parms
)
421 struct smb_trans2 t2
;
422 uint16_t setup
= TRANSACT2_OPEN
;
423 TALLOC_CTX
*mem_ctx
= talloc_init("smb_raw_t2open");
424 struct smbcli_request
*req
;
427 list_size
= ea_list_size(parms
->t2open
.in
.num_eas
, parms
->t2open
.in
.eas
);
429 t2
.in
.max_param
= 30;
434 t2
.in
.setup_count
= 1;
435 t2
.in
.setup
= &setup
;
436 t2
.in
.params
= data_blob_talloc(mem_ctx
, NULL
, 28);
437 t2
.in
.data
= data_blob_talloc(mem_ctx
, NULL
, list_size
);
439 SSVAL(t2
.in
.params
.data
, VWV(0), parms
->t2open
.in
.flags
);
440 SSVAL(t2
.in
.params
.data
, VWV(1), parms
->t2open
.in
.open_mode
);
441 SSVAL(t2
.in
.params
.data
, VWV(2), parms
->t2open
.in
.search_attrs
);
442 SSVAL(t2
.in
.params
.data
, VWV(3), parms
->t2open
.in
.file_attrs
);
443 raw_push_dos_date(tree
->session
->transport
,
444 t2
.in
.params
.data
, VWV(4), parms
->t2open
.in
.write_time
);
445 SSVAL(t2
.in
.params
.data
, VWV(6), parms
->t2open
.in
.open_func
);
446 SIVAL(t2
.in
.params
.data
, VWV(7), parms
->t2open
.in
.size
);
447 SIVAL(t2
.in
.params
.data
, VWV(9), parms
->t2open
.in
.timeout
);
448 SIVAL(t2
.in
.params
.data
, VWV(11), 0);
449 SSVAL(t2
.in
.params
.data
, VWV(13), 0);
451 smbcli_blob_append_string(tree
->session
, mem_ctx
,
452 &t2
.in
.params
, parms
->t2open
.in
.fname
,
455 ea_put_list(t2
.in
.data
.data
, parms
->t2open
.in
.num_eas
, parms
->t2open
.in
.eas
);
457 req
= smb_raw_trans2_send(tree
, &t2
);
459 talloc_free(mem_ctx
);
465 /****************************************************************************
466 Open a file using TRANSACT2_OPEN - async recv
467 ****************************************************************************/
468 static NTSTATUS
smb_raw_t2open_recv(struct smbcli_request
*req
, TALLOC_CTX
*mem_ctx
, union smb_open
*parms
)
470 struct smbcli_transport
*transport
= req
->transport
;
471 struct smb_trans2 t2
;
474 status
= smb_raw_trans2_recv(req
, mem_ctx
, &t2
);
475 if (!NT_STATUS_IS_OK(status
)) return status
;
477 if (t2
.out
.params
.length
< 30) {
478 return NT_STATUS_INFO_LENGTH_MISMATCH
;
481 parms
->t2open
.out
.file
.fnum
= SVAL(t2
.out
.params
.data
, VWV(0));
482 parms
->t2open
.out
.attrib
= SVAL(t2
.out
.params
.data
, VWV(1));
483 parms
->t2open
.out
.write_time
= raw_pull_dos_date3(transport
, t2
.out
.params
.data
+ VWV(2));
484 parms
->t2open
.out
.size
= IVAL(t2
.out
.params
.data
, VWV(4));
485 parms
->t2open
.out
.access
= SVAL(t2
.out
.params
.data
, VWV(6));
486 parms
->t2open
.out
.ftype
= SVAL(t2
.out
.params
.data
, VWV(7));
487 parms
->t2open
.out
.devstate
= SVAL(t2
.out
.params
.data
, VWV(8));
488 parms
->t2open
.out
.action
= SVAL(t2
.out
.params
.data
, VWV(9));
489 parms
->t2open
.out
.file_id
= SVAL(t2
.out
.params
.data
, VWV(10));
494 /****************************************************************************
495 Open a file - async send
496 ****************************************************************************/
497 _PUBLIC_
struct smbcli_request
*smb_raw_open_send(struct smbcli_tree
*tree
, union smb_open
*parms
)
500 struct smbcli_request
*req
= NULL
;
501 bool bigoffset
= false;
503 switch (parms
->generic
.level
) {
504 case RAW_OPEN_T2OPEN
:
505 return smb_raw_t2open_send(tree
, parms
);
508 SETUP_REQUEST(SMBopen
, 2, 0);
509 SSVAL(req
->out
.vwv
, VWV(0), parms
->openold
.in
.open_mode
);
510 SSVAL(req
->out
.vwv
, VWV(1), parms
->openold
.in
.search_attrs
);
511 smbcli_req_append_ascii4(req
, parms
->openold
.in
.fname
, STR_TERMINATE
);
515 SETUP_REQUEST(SMBopenX
, 15, 0);
516 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
517 SSVAL(req
->out
.vwv
, VWV(1), 0);
518 SSVAL(req
->out
.vwv
, VWV(2), parms
->openx
.in
.flags
);
519 SSVAL(req
->out
.vwv
, VWV(3), parms
->openx
.in
.open_mode
);
520 SSVAL(req
->out
.vwv
, VWV(4), parms
->openx
.in
.search_attrs
);
521 SSVAL(req
->out
.vwv
, VWV(5), parms
->openx
.in
.file_attrs
);
522 raw_push_dos_date3(tree
->session
->transport
,
523 req
->out
.vwv
, VWV(6), parms
->openx
.in
.write_time
);
524 SSVAL(req
->out
.vwv
, VWV(8), parms
->openx
.in
.open_func
);
525 SIVAL(req
->out
.vwv
, VWV(9), parms
->openx
.in
.size
);
526 SIVAL(req
->out
.vwv
, VWV(11),parms
->openx
.in
.timeout
);
527 SIVAL(req
->out
.vwv
, VWV(13),0); /* reserved */
528 smbcli_req_append_string(req
, parms
->openx
.in
.fname
, STR_TERMINATE
);
532 SETUP_REQUEST(SMBmknew
, 3, 0);
533 SSVAL(req
->out
.vwv
, VWV(0), parms
->mknew
.in
.attrib
);
534 raw_push_dos_date3(tree
->session
->transport
,
535 req
->out
.vwv
, VWV(1), parms
->mknew
.in
.write_time
);
536 smbcli_req_append_ascii4(req
, parms
->mknew
.in
.fname
, STR_TERMINATE
);
539 case RAW_OPEN_CREATE
:
540 SETUP_REQUEST(SMBcreate
, 3, 0);
541 SSVAL(req
->out
.vwv
, VWV(0), parms
->create
.in
.attrib
);
542 raw_push_dos_date3(tree
->session
->transport
,
543 req
->out
.vwv
, VWV(1), parms
->create
.in
.write_time
);
544 smbcli_req_append_ascii4(req
, parms
->create
.in
.fname
, STR_TERMINATE
);
548 SETUP_REQUEST(SMBctemp
, 3, 0);
549 SSVAL(req
->out
.vwv
, VWV(0), parms
->ctemp
.in
.attrib
);
550 raw_push_dos_date3(tree
->session
->transport
,
551 req
->out
.vwv
, VWV(1), parms
->ctemp
.in
.write_time
);
552 smbcli_req_append_ascii4(req
, parms
->ctemp
.in
.directory
, STR_TERMINATE
);
555 case RAW_OPEN_SPLOPEN
:
556 SETUP_REQUEST(SMBsplopen
, 2, 0);
557 SSVAL(req
->out
.vwv
, VWV(0), parms
->splopen
.in
.setup_length
);
558 SSVAL(req
->out
.vwv
, VWV(1), parms
->splopen
.in
.mode
);
561 case RAW_OPEN_NTCREATEX
:
562 SETUP_REQUEST(SMBntcreateX
, 24, 0);
563 SSVAL(req
->out
.vwv
, VWV(0),SMB_CHAIN_NONE
);
564 SSVAL(req
->out
.vwv
, VWV(1),0);
565 SCVAL(req
->out
.vwv
, VWV(2),0); /* padding */
566 SIVAL(req
->out
.vwv
, 7, parms
->ntcreatex
.in
.flags
);
567 SIVAL(req
->out
.vwv
, 11, parms
->ntcreatex
.in
.root_fid
);
568 SIVAL(req
->out
.vwv
, 15, parms
->ntcreatex
.in
.access_mask
);
569 SBVAL(req
->out
.vwv
, 19, parms
->ntcreatex
.in
.alloc_size
);
570 SIVAL(req
->out
.vwv
, 27, parms
->ntcreatex
.in
.file_attr
);
571 SIVAL(req
->out
.vwv
, 31, parms
->ntcreatex
.in
.share_access
);
572 SIVAL(req
->out
.vwv
, 35, parms
->ntcreatex
.in
.open_disposition
);
573 SIVAL(req
->out
.vwv
, 39, parms
->ntcreatex
.in
.create_options
);
574 SIVAL(req
->out
.vwv
, 43, parms
->ntcreatex
.in
.impersonation
);
575 SCVAL(req
->out
.vwv
, 47, parms
->ntcreatex
.in
.security_flags
);
577 smbcli_req_append_string_len(req
, parms
->ntcreatex
.in
.fname
, STR_TERMINATE
, &len
);
578 SSVAL(req
->out
.vwv
, 5, len
);
581 case RAW_OPEN_NTTRANS_CREATE
:
582 return smb_raw_nttrans_create_send(tree
, parms
);
585 case RAW_OPEN_OPENX_READX
:
586 SETUP_REQUEST(SMBopenX
, 15, 0);
587 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
588 SSVAL(req
->out
.vwv
, VWV(1), 0);
589 SSVAL(req
->out
.vwv
, VWV(2), parms
->openxreadx
.in
.flags
);
590 SSVAL(req
->out
.vwv
, VWV(3), parms
->openxreadx
.in
.open_mode
);
591 SSVAL(req
->out
.vwv
, VWV(4), parms
->openxreadx
.in
.search_attrs
);
592 SSVAL(req
->out
.vwv
, VWV(5), parms
->openxreadx
.in
.file_attrs
);
593 raw_push_dos_date3(tree
->session
->transport
,
594 req
->out
.vwv
, VWV(6), parms
->openxreadx
.in
.write_time
);
595 SSVAL(req
->out
.vwv
, VWV(8), parms
->openxreadx
.in
.open_func
);
596 SIVAL(req
->out
.vwv
, VWV(9), parms
->openxreadx
.in
.size
);
597 SIVAL(req
->out
.vwv
, VWV(11),parms
->openxreadx
.in
.timeout
);
598 SIVAL(req
->out
.vwv
, VWV(13),0);
599 smbcli_req_append_string(req
, parms
->openxreadx
.in
.fname
, STR_TERMINATE
);
601 if (tree
->session
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
605 smbcli_chained_request_setup(req
, SMBreadX
, bigoffset
? 12 : 10, 0);
607 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
608 SSVAL(req
->out
.vwv
, VWV(1), 0);
609 SSVAL(req
->out
.vwv
, VWV(2), 0);
610 SIVAL(req
->out
.vwv
, VWV(3), parms
->openxreadx
.in
.offset
);
611 SSVAL(req
->out
.vwv
, VWV(5), parms
->openxreadx
.in
.maxcnt
& 0xFFFF);
612 SSVAL(req
->out
.vwv
, VWV(6), parms
->openxreadx
.in
.mincnt
);
613 SIVAL(req
->out
.vwv
, VWV(7), parms
->openxreadx
.in
.maxcnt
>> 16);
614 SSVAL(req
->out
.vwv
, VWV(9), parms
->openxreadx
.in
.remaining
);
616 SIVAL(req
->out
.vwv
, VWV(10),parms
->openxreadx
.in
.offset
>>32);
623 if (!smbcli_request_send(req
)) {
624 smbcli_request_destroy(req
);
631 /****************************************************************************
632 Open a file - async recv
633 ****************************************************************************/
634 _PUBLIC_ NTSTATUS
smb_raw_open_recv(struct smbcli_request
*req
, TALLOC_CTX
*mem_ctx
, union smb_open
*parms
)
638 if (!smbcli_request_receive(req
) ||
639 smbcli_request_is_error(req
)) {
643 switch (parms
->openold
.level
) {
644 case RAW_OPEN_T2OPEN
:
645 return smb_raw_t2open_recv(req
, mem_ctx
, parms
);
648 SMBCLI_CHECK_WCT(req
, 7);
649 parms
->openold
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(0));
650 parms
->openold
.out
.attrib
= SVAL(req
->in
.vwv
, VWV(1));
651 parms
->openold
.out
.write_time
= raw_pull_dos_date3(req
->transport
,
652 req
->in
.vwv
+ VWV(2));
653 parms
->openold
.out
.size
= IVAL(req
->in
.vwv
, VWV(4));
654 parms
->openold
.out
.rmode
= SVAL(req
->in
.vwv
, VWV(6));
658 SMBCLI_CHECK_MIN_WCT(req
, 15);
659 parms
->openx
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(2));
660 parms
->openx
.out
.attrib
= SVAL(req
->in
.vwv
, VWV(3));
661 parms
->openx
.out
.write_time
= raw_pull_dos_date3(req
->transport
,
662 req
->in
.vwv
+ VWV(4));
663 parms
->openx
.out
.size
= IVAL(req
->in
.vwv
, VWV(6));
664 parms
->openx
.out
.access
= SVAL(req
->in
.vwv
, VWV(8));
665 parms
->openx
.out
.ftype
= SVAL(req
->in
.vwv
, VWV(9));
666 parms
->openx
.out
.devstate
= SVAL(req
->in
.vwv
, VWV(10));
667 parms
->openx
.out
.action
= SVAL(req
->in
.vwv
, VWV(11));
668 parms
->openx
.out
.unique_fid
= IVAL(req
->in
.vwv
, VWV(12));
669 if (req
->in
.wct
>= 19) {
670 parms
->openx
.out
.access_mask
= IVAL(req
->in
.vwv
, VWV(15));
671 parms
->openx
.out
.unknown
= IVAL(req
->in
.vwv
, VWV(17));
673 parms
->openx
.out
.access_mask
= 0;
674 parms
->openx
.out
.unknown
= 0;
679 SMBCLI_CHECK_WCT(req
, 1);
680 parms
->mknew
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(0));
683 case RAW_OPEN_CREATE
:
684 SMBCLI_CHECK_WCT(req
, 1);
685 parms
->create
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(0));
689 SMBCLI_CHECK_WCT(req
, 1);
690 parms
->ctemp
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(0));
691 smbcli_req_pull_string(&req
->in
.bufinfo
, mem_ctx
, &parms
->ctemp
.out
.name
, req
->in
.data
, -1, STR_TERMINATE
| STR_ASCII
);
694 case RAW_OPEN_SPLOPEN
:
695 SMBCLI_CHECK_WCT(req
, 1);
696 parms
->splopen
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(0));
699 case RAW_OPEN_NTCREATEX
:
700 SMBCLI_CHECK_MIN_WCT(req
, 34);
701 parms
->ntcreatex
.out
.oplock_level
= CVAL(req
->in
.vwv
, 4);
702 parms
->ntcreatex
.out
.file
.fnum
= SVAL(req
->in
.vwv
, 5);
703 parms
->ntcreatex
.out
.create_action
= IVAL(req
->in
.vwv
, 7);
704 parms
->ntcreatex
.out
.create_time
= smbcli_pull_nttime(req
->in
.vwv
, 11);
705 parms
->ntcreatex
.out
.access_time
= smbcli_pull_nttime(req
->in
.vwv
, 19);
706 parms
->ntcreatex
.out
.write_time
= smbcli_pull_nttime(req
->in
.vwv
, 27);
707 parms
->ntcreatex
.out
.change_time
= smbcli_pull_nttime(req
->in
.vwv
, 35);
708 parms
->ntcreatex
.out
.attrib
= IVAL(req
->in
.vwv
, 43);
709 parms
->ntcreatex
.out
.alloc_size
= BVAL(req
->in
.vwv
, 47);
710 parms
->ntcreatex
.out
.size
= BVAL(req
->in
.vwv
, 55);
711 parms
->ntcreatex
.out
.file_type
= SVAL(req
->in
.vwv
, 63);
712 parms
->ntcreatex
.out
.ipc_state
= SVAL(req
->in
.vwv
, 65);
713 parms
->ntcreatex
.out
.is_directory
= CVAL(req
->in
.vwv
, 67);
716 case RAW_OPEN_NTTRANS_CREATE
:
717 return smb_raw_nttrans_create_recv(req
, mem_ctx
, parms
);
719 case RAW_OPEN_OPENX_READX
:
720 SMBCLI_CHECK_MIN_WCT(req
, 15);
721 parms
->openxreadx
.out
.file
.fnum
= SVAL(req
->in
.vwv
, VWV(2));
722 parms
->openxreadx
.out
.attrib
= SVAL(req
->in
.vwv
, VWV(3));
723 parms
->openxreadx
.out
.write_time
= raw_pull_dos_date3(req
->transport
,
724 req
->in
.vwv
+ VWV(4));
725 parms
->openxreadx
.out
.size
= IVAL(req
->in
.vwv
, VWV(6));
726 parms
->openxreadx
.out
.access
= SVAL(req
->in
.vwv
, VWV(8));
727 parms
->openxreadx
.out
.ftype
= SVAL(req
->in
.vwv
, VWV(9));
728 parms
->openxreadx
.out
.devstate
= SVAL(req
->in
.vwv
, VWV(10));
729 parms
->openxreadx
.out
.action
= SVAL(req
->in
.vwv
, VWV(11));
730 parms
->openxreadx
.out
.unique_fid
= IVAL(req
->in
.vwv
, VWV(12));
731 if (req
->in
.wct
>= 19) {
732 parms
->openxreadx
.out
.access_mask
= IVAL(req
->in
.vwv
, VWV(15));
733 parms
->openxreadx
.out
.unknown
= IVAL(req
->in
.vwv
, VWV(17));
735 parms
->openxreadx
.out
.access_mask
= 0;
736 parms
->openxreadx
.out
.unknown
= 0;
739 status
= smbcli_chained_advance(req
);
740 if (!NT_STATUS_IS_OK(status
)) {
744 SMBCLI_CHECK_WCT(req
, 12);
745 parms
->openxreadx
.out
.remaining
= SVAL(req
->in
.vwv
, VWV(2));
746 parms
->openxreadx
.out
.compaction_mode
= SVAL(req
->in
.vwv
, VWV(3));
747 parms
->openxreadx
.out
.nread
= SVAL(req
->in
.vwv
, VWV(5));
748 if (parms
->openxreadx
.out
.nread
>
749 MAX(parms
->openxreadx
.in
.mincnt
, parms
->openxreadx
.in
.maxcnt
) ||
750 !smbcli_raw_pull_data(&req
->in
.bufinfo
, req
->in
.hdr
+ SVAL(req
->in
.vwv
, VWV(6)),
751 parms
->openxreadx
.out
.nread
,
752 parms
->openxreadx
.out
.data
)) {
753 req
->status
= NT_STATUS_BUFFER_TOO_SMALL
;
757 req
->status
= NT_STATUS_INTERNAL_ERROR
;
762 return smbcli_request_destroy(req
);
766 /****************************************************************************
767 Open a file - sync interface
768 ****************************************************************************/
769 _PUBLIC_ NTSTATUS
smb_raw_open(struct smbcli_tree
*tree
, TALLOC_CTX
*mem_ctx
, union smb_open
*parms
)
771 struct smbcli_request
*req
= smb_raw_open_send(tree
, parms
);
772 return smb_raw_open_recv(req
, mem_ctx
, parms
);
776 /****************************************************************************
777 Close a file - async send
778 ****************************************************************************/
779 _PUBLIC_
struct smbcli_request
*smb_raw_close_send(struct smbcli_tree
*tree
, union smb_close
*parms
)
781 struct smbcli_request
*req
= NULL
;
783 switch (parms
->generic
.level
) {
784 case RAW_CLOSE_CLOSE
:
785 SETUP_REQUEST(SMBclose
, 3, 0);
786 SSVAL(req
->out
.vwv
, VWV(0), parms
->close
.in
.file
.fnum
);
787 raw_push_dos_date3(tree
->session
->transport
,
788 req
->out
.vwv
, VWV(1), parms
->close
.in
.write_time
);
791 case RAW_CLOSE_SPLCLOSE
:
792 SETUP_REQUEST(SMBsplclose
, 3, 0);
793 SSVAL(req
->out
.vwv
, VWV(0), parms
->splclose
.in
.file
.fnum
);
794 SIVAL(req
->out
.vwv
, VWV(1), 0); /* reserved */
798 case RAW_CLOSE_GENERIC
:
802 if (!req
) return NULL
;
804 if (!smbcli_request_send(req
)) {
805 smbcli_request_destroy(req
);
813 /****************************************************************************
814 Close a file - sync interface
815 ****************************************************************************/
816 _PUBLIC_ NTSTATUS
smb_raw_close(struct smbcli_tree
*tree
, union smb_close
*parms
)
818 struct smbcli_request
*req
= smb_raw_close_send(tree
, parms
);
819 return smbcli_request_simple_recv(req
);
823 /****************************************************************************
824 Locking calls - async interface
825 ****************************************************************************/
826 struct smbcli_request
*smb_raw_lock_send(struct smbcli_tree
*tree
, union smb_lock
*parms
)
828 struct smbcli_request
*req
= NULL
;
830 switch (parms
->generic
.level
) {
832 SETUP_REQUEST(SMBlock
, 5, 0);
833 SSVAL(req
->out
.vwv
, VWV(0), parms
->lock
.in
.file
.fnum
);
834 SIVAL(req
->out
.vwv
, VWV(1), parms
->lock
.in
.count
);
835 SIVAL(req
->out
.vwv
, VWV(3), parms
->lock
.in
.offset
);
838 case RAW_LOCK_UNLOCK
:
839 SETUP_REQUEST(SMBunlock
, 5, 0);
840 SSVAL(req
->out
.vwv
, VWV(0), parms
->unlock
.in
.file
.fnum
);
841 SIVAL(req
->out
.vwv
, VWV(1), parms
->unlock
.in
.count
);
842 SIVAL(req
->out
.vwv
, VWV(3), parms
->unlock
.in
.offset
);
845 case RAW_LOCK_LOCKX
: {
846 struct smb_lock_entry
*lockp
;
847 uint_t lck_size
= (parms
->lockx
.in
.mode
& LOCKING_ANDX_LARGE_FILES
)? 20 : 10;
848 uint_t lock_count
= parms
->lockx
.in
.ulock_cnt
+ parms
->lockx
.in
.lock_cnt
;
851 SETUP_REQUEST(SMBlockingX
, 8, lck_size
* lock_count
);
852 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
853 SSVAL(req
->out
.vwv
, VWV(1), 0);
854 SSVAL(req
->out
.vwv
, VWV(2), parms
->lockx
.in
.file
.fnum
);
855 SSVAL(req
->out
.vwv
, VWV(3), parms
->lockx
.in
.mode
);
856 SIVAL(req
->out
.vwv
, VWV(4), parms
->lockx
.in
.timeout
);
857 SSVAL(req
->out
.vwv
, VWV(6), parms
->lockx
.in
.ulock_cnt
);
858 SSVAL(req
->out
.vwv
, VWV(7), parms
->lockx
.in
.lock_cnt
);
860 /* copy in all the locks */
861 lockp
= &parms
->lockx
.in
.locks
[0];
862 for (i
= 0; i
< lock_count
; i
++) {
863 uint8_t *p
= req
->out
.data
+ lck_size
* i
;
864 SSVAL(p
, 0, lockp
[i
].pid
);
865 if (parms
->lockx
.in
.mode
& LOCKING_ANDX_LARGE_FILES
) {
866 SSVAL(p
, 2, 0); /* reserved */
867 SIVAL(p
, 4, lockp
[i
].offset
>>32);
868 SIVAL(p
, 8, lockp
[i
].offset
);
869 SIVAL(p
, 12, lockp
[i
].count
>>32);
870 SIVAL(p
, 16, lockp
[i
].count
);
872 SIVAL(p
, 2, lockp
[i
].offset
);
873 SIVAL(p
, 6, lockp
[i
].count
);
882 if (!smbcli_request_send(req
)) {
883 smbcli_request_destroy(req
);
890 /****************************************************************************
891 Locking calls - sync interface
892 ****************************************************************************/
893 _PUBLIC_ NTSTATUS
smb_raw_lock(struct smbcli_tree
*tree
, union smb_lock
*parms
)
895 struct smbcli_request
*req
= smb_raw_lock_send(tree
, parms
);
896 return smbcli_request_simple_recv(req
);
900 /****************************************************************************
901 Check for existence of a dir - async send
902 ****************************************************************************/
903 struct smbcli_request
*smb_raw_chkpath_send(struct smbcli_tree
*tree
, union smb_chkpath
*parms
)
905 struct smbcli_request
*req
;
907 SETUP_REQUEST(SMBchkpth
, 0, 0);
909 smbcli_req_append_ascii4(req
, parms
->chkpath
.in
.path
, STR_TERMINATE
);
911 if (!smbcli_request_send(req
)) {
912 smbcli_request_destroy(req
);
919 /****************************************************************************
920 Check for existence of a dir - sync interface
921 ****************************************************************************/
922 NTSTATUS
smb_raw_chkpath(struct smbcli_tree
*tree
, union smb_chkpath
*parms
)
924 struct smbcli_request
*req
= smb_raw_chkpath_send(tree
, parms
);
925 return smbcli_request_simple_recv(req
);
928 /****************************************************************************
929 flush a file - async send
930 a flush with RAW_FLUSH_ALL will flush all files
931 ****************************************************************************/
932 struct smbcli_request
*smb_raw_flush_send(struct smbcli_tree
*tree
, union smb_flush
*parms
)
934 struct smbcli_request
*req
;
937 switch (parms
->generic
.level
) {
938 case RAW_FLUSH_FLUSH
:
939 fnum
= parms
->flush
.in
.file
.fnum
;
948 SETUP_REQUEST(SMBflush
, 1, 0);
949 SSVAL(req
->out
.vwv
, VWV(0), fnum
);
951 if (!smbcli_request_send(req
)) {
952 smbcli_request_destroy(req
);
960 /****************************************************************************
961 flush a file - sync interface
962 ****************************************************************************/
963 _PUBLIC_ NTSTATUS
smb_raw_flush(struct smbcli_tree
*tree
, union smb_flush
*parms
)
965 struct smbcli_request
*req
= smb_raw_flush_send(tree
, parms
);
966 return smbcli_request_simple_recv(req
);
970 /****************************************************************************
971 seek a file - async send
972 ****************************************************************************/
973 struct smbcli_request
*smb_raw_seek_send(struct smbcli_tree
*tree
,
974 union smb_seek
*parms
)
976 struct smbcli_request
*req
;
978 SETUP_REQUEST(SMBlseek
, 4, 0);
980 SSVAL(req
->out
.vwv
, VWV(0), parms
->lseek
.in
.file
.fnum
);
981 SSVAL(req
->out
.vwv
, VWV(1), parms
->lseek
.in
.mode
);
982 SIVALS(req
->out
.vwv
, VWV(2), parms
->lseek
.in
.offset
);
984 if (!smbcli_request_send(req
)) {
985 smbcli_request_destroy(req
);
991 /****************************************************************************
992 seek a file - async receive
993 ****************************************************************************/
994 NTSTATUS
smb_raw_seek_recv(struct smbcli_request
*req
,
995 union smb_seek
*parms
)
997 if (!smbcli_request_receive(req
) ||
998 smbcli_request_is_error(req
)) {
999 return smbcli_request_destroy(req
);
1002 SMBCLI_CHECK_WCT(req
, 2);
1003 parms
->lseek
.out
.offset
= IVAL(req
->in
.vwv
, VWV(0));
1006 return smbcli_request_destroy(req
);
1010 seek a file - sync interface
1012 _PUBLIC_ NTSTATUS
smb_raw_seek(struct smbcli_tree
*tree
,
1013 union smb_seek
*parms
)
1015 struct smbcli_request
*req
= smb_raw_seek_send(tree
, parms
);
1016 return smb_raw_seek_recv(req
, parms
);