2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "../libcli/auth/libcli_auth.h"
34 #include "../librpc/gen_ndr/xattr.h"
35 #include "../librpc/gen_ndr/ndr_security.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #include "libcli/smb/smb2_posix.h"
46 #include "lib/util/string_wrappers.h"
47 #include "source3/lib/substitute.h"
48 #include "source3/lib/adouble.h"
50 #define DIR_ENTRY_SAFETY_MARGIN 4096
52 /****************************************************************************
53 Send the required number of replies back.
54 We assume all fields other than the data fields are
55 set correctly for the type of call.
56 HACK ! Always assumes smb_setup field is zero.
57 ****************************************************************************/
59 static void send_trans2_replies(connection_struct
*conn
,
60 struct smb_request
*req
,
68 /* As we are using a protocol > LANMAN1 then the max_send
69 variable must have been set in the sessetupX call.
70 This takes precedence over the max_xmit field in the
71 global struct. These different max_xmit variables should
72 be merged as this is now too confusing */
74 int data_to_send
= datasize
;
75 int params_to_send
= paramsize
;
77 const char *pp
= params
;
78 const char *pd
= pdata
;
79 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
80 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
81 int data_alignment_offset
= 0;
82 bool overflow
= False
;
83 struct smbXsrv_connection
*xconn
= req
->xconn
;
84 int max_send
= xconn
->smb1
.sessions
.max_send
;
86 /* Modify the data_to_send and datasize and set the error if
87 we're trying to send more than max_data_bytes. We still send
88 the part of the packet(s) that fit. Strange, but needed
91 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
92 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
93 max_data_bytes
, datasize
));
94 datasize
= data_to_send
= max_data_bytes
;
98 /* If there genuinely are no parameters or data to send just send the empty packet */
100 if(params_to_send
== 0 && data_to_send
== 0) {
101 reply_smb1_outbuf(req
, 10, 0);
102 if (NT_STATUS_V(status
)) {
105 ntstatus_to_dos(status
, &eclass
, &ecode
);
106 error_packet_set((char *)req
->outbuf
,
107 eclass
, ecode
, status
,
110 show_msg((char *)req
->outbuf
);
111 if (!smb1_srv_send(xconn
,
115 IS_CONN_ENCRYPTED(conn
))) {
116 exit_server_cleanly("send_trans2_replies: smb1_srv_send failed.");
118 TALLOC_FREE(req
->outbuf
);
122 /* When sending params and data ensure that both are nicely aligned */
123 /* Only do this alignment when there is also data to send - else
124 can cause NT redirector problems. */
126 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
127 data_alignment_offset
= 4 - (params_to_send
% 4);
129 /* Space is bufsize minus Netbios over TCP header minus SMB header */
130 /* The alignment_offset is to align the param bytes on an even byte
131 boundary. NT 4.0 Beta needs this to work correctly. */
133 useable_space
= max_send
- (smb_size
136 + data_alignment_offset
);
138 if (useable_space
< 0) {
139 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
140 "= %d!!!\n", useable_space
));
141 exit_server_cleanly("send_trans2_replies: Not enough space");
144 while (params_to_send
|| data_to_send
) {
145 /* Calculate whether we will totally or partially fill this packet */
147 total_sent_thistime
= params_to_send
+ data_to_send
;
149 /* We can never send more than useable_space */
151 * Note that 'useable_space' does not include the alignment offsets,
152 * but we must include the alignment offsets in the calculation of
153 * the length of the data we send over the wire, as the alignment offsets
154 * are sent here. Fix from Marc_Jacobsen@hp.com.
157 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
159 reply_smb1_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
160 + data_alignment_offset
);
162 /* Set total params and data to be sent */
163 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
164 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
166 /* Calculate how many parameters and data we can fit into
167 * this packet. Parameters get precedence
170 params_sent_thistime
= MIN(params_to_send
,useable_space
);
171 data_sent_thistime
= useable_space
- params_sent_thistime
;
172 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
174 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
176 /* smb_proff is the offset from the start of the SMB header to the
177 parameter bytes, however the first 4 bytes of outbuf are
178 the Netbios over TCP header. Thus use smb_base() to subtract
179 them from the calculation */
181 SSVAL(req
->outbuf
,smb_proff
,
182 ((smb_buf(req
->outbuf
)+alignment_offset
)
183 - smb_base(req
->outbuf
)));
185 if(params_sent_thistime
== 0)
186 SSVAL(req
->outbuf
,smb_prdisp
,0);
188 /* Absolute displacement of param bytes sent in this packet */
189 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
191 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
192 if(data_sent_thistime
== 0) {
193 SSVAL(req
->outbuf
,smb_droff
,0);
194 SSVAL(req
->outbuf
,smb_drdisp
, 0);
196 /* The offset of the data bytes is the offset of the
197 parameter bytes plus the number of parameters being sent this time */
198 SSVAL(req
->outbuf
, smb_droff
,
199 ((smb_buf(req
->outbuf
)+alignment_offset
)
200 - smb_base(req
->outbuf
))
201 + params_sent_thistime
+ data_alignment_offset
);
202 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
205 /* Initialize the padding for alignment */
207 if (alignment_offset
!= 0) {
208 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
211 /* Copy the param bytes into the packet */
213 if(params_sent_thistime
) {
214 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
215 params_sent_thistime
);
218 /* Copy in the data bytes */
219 if(data_sent_thistime
) {
220 if (data_alignment_offset
!= 0) {
221 memset((smb_buf(req
->outbuf
)+alignment_offset
+
222 params_sent_thistime
), 0,
223 data_alignment_offset
);
225 memcpy(smb_buf(req
->outbuf
)+alignment_offset
226 +params_sent_thistime
+data_alignment_offset
,
227 pd
,data_sent_thistime
);
230 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
231 params_sent_thistime
, data_sent_thistime
, useable_space
));
232 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
233 params_to_send
, data_to_send
, paramsize
, datasize
));
236 error_packet_set((char *)req
->outbuf
,
237 ERRDOS
,ERRbufferoverflow
,
238 STATUS_BUFFER_OVERFLOW
,
240 } else if (NT_STATUS_V(status
)) {
243 ntstatus_to_dos(status
, &eclass
, &ecode
);
244 error_packet_set((char *)req
->outbuf
,
245 eclass
, ecode
, status
,
249 /* Send the packet */
250 show_msg((char *)req
->outbuf
);
251 if (!smb1_srv_send(xconn
,
255 IS_CONN_ENCRYPTED(conn
))) {
256 exit_server_cleanly("send_trans2_replies: smb1_srv_send failed.");
259 TALLOC_FREE(req
->outbuf
);
261 pp
+= params_sent_thistime
;
262 pd
+= data_sent_thistime
;
264 params_to_send
-= params_sent_thistime
;
265 data_to_send
-= data_sent_thistime
;
268 if(params_to_send
< 0 || data_to_send
< 0) {
269 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
270 params_to_send
, data_to_send
));
278 /****************************************************************************
279 Deal with SMB_SET_POSIX_LOCK.
280 ****************************************************************************/
282 static void smb_set_posix_lock_done(struct tevent_req
*subreq
);
284 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
285 struct smb_request
*req
,
290 struct tevent_req
*subreq
= NULL
;
291 struct smbd_lock_element
*lck
= NULL
;
295 bool blocking_lock
= False
;
296 enum brl_type lock_type
;
298 NTSTATUS status
= NT_STATUS_OK
;
300 if (!CAN_WRITE(conn
)) {
301 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
305 fsp
->fsp_flags
.is_pathref
||
306 fsp_get_io_fd(fsp
) == -1)
308 return NT_STATUS_INVALID_HANDLE
;
311 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
312 return NT_STATUS_INVALID_PARAMETER
;
315 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
316 case POSIX_LOCK_TYPE_READ
:
317 lock_type
= READ_LOCK
;
319 case POSIX_LOCK_TYPE_WRITE
:
320 /* Return the right POSIX-mappable error code for files opened read-only. */
321 if (!fsp
->fsp_flags
.can_write
) {
322 return NT_STATUS_INVALID_HANDLE
;
324 lock_type
= WRITE_LOCK
;
326 case POSIX_LOCK_TYPE_UNLOCK
:
327 lock_type
= UNLOCK_LOCK
;
330 return NT_STATUS_INVALID_PARAMETER
;
333 switch (SVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
)) {
334 case POSIX_LOCK_FLAG_NOWAIT
:
335 blocking_lock
= false;
337 case POSIX_LOCK_FLAG_WAIT
:
338 blocking_lock
= true;
341 return NT_STATUS_INVALID_PARAMETER
;
344 if (!lp_blocking_locks(SNUM(conn
))) {
345 blocking_lock
= False
;
348 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
349 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
350 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
351 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
352 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
354 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64
", "
355 "count = %"PRIu64
", offset = %"PRIu64
"\n",
357 (unsigned int)lock_type
,
362 if (lock_type
== UNLOCK_LOCK
) {
363 struct smbd_lock_element l
= {
364 .req_guid
= smbd_request_guid(req
, 0),
366 .brltype
= UNLOCK_LOCK
,
367 .lock_flav
= POSIX_LOCK
,
371 status
= smbd_do_unlocking(req
, fsp
, 1, &l
);
375 lck
= talloc(req
, struct smbd_lock_element
);
377 return NT_STATUS_NO_MEMORY
;
380 *lck
= (struct smbd_lock_element
) {
381 .req_guid
= smbd_request_guid(req
, 0),
383 .brltype
= lock_type
,
384 .lock_flav
= POSIX_LOCK
,
389 subreq
= smbd_smb1_do_locks_send(
394 blocking_lock
? UINT32_MAX
: 0,
395 true, /* large_offset */
398 if (subreq
== NULL
) {
400 return NT_STATUS_NO_MEMORY
;
402 tevent_req_set_callback(subreq
, smb_set_posix_lock_done
, req
);
403 return NT_STATUS_EVENT_PENDING
;
406 static void smb_set_posix_lock_done(struct tevent_req
*subreq
)
408 struct smb_request
*req
= NULL
;
412 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
415 status
= smbd_smb1_do_locks_recv(subreq
);
418 if (NT_STATUS_IS_OK(status
)) {
419 char params
[2] = {0};
420 /* Fake up max_data_bytes here - we know it fits. */
431 reply_nterror(req
, status
);
432 ok
= smb1_srv_send(req
->xconn
,
436 IS_CONN_ENCRYPTED(req
->conn
));
438 exit_server_cleanly("smb_set_posix_lock_done: "
439 "smb1_srv_send failed.");
447 /****************************************************************************
448 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
449 ****************************************************************************/
451 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
453 struct ea_list
*ea_list_head
= NULL
;
454 size_t converted_size
, offset
= 0;
456 while (offset
+ 2 < data_size
) {
457 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
458 unsigned int namelen
= CVAL(pdata
,offset
);
460 offset
++; /* Go past the namelen byte. */
462 /* integer wrap paranioa. */
463 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
464 (offset
> data_size
) || (namelen
> data_size
) ||
465 (offset
+ namelen
>= data_size
)) {
468 /* Ensure the name is null terminated. */
469 if (pdata
[offset
+ namelen
] != '\0') {
472 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
474 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
475 "failed: %s\n", strerror(errno
)));
481 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
482 DLIST_ADD_END(ea_list_head
, eal
);
483 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
489 /****************************************************************************
490 Reply to a TRANSACT2_OPEN.
491 ****************************************************************************/
493 static void call_trans2open(connection_struct
*conn
,
494 struct smb_request
*req
,
495 char **pparams
, int total_params
,
496 char **ppdata
, int total_data
,
497 unsigned int max_data_bytes
)
499 struct smb_filename
*smb_fname
= NULL
;
500 char *params
= *pparams
;
501 char *pdata
= *ppdata
;
506 bool return_additional_info
;
518 struct files_struct
*dirfsp
= NULL
;
520 struct ea_list
*ea_list
= NULL
;
523 uint32_t access_mask
;
525 uint32_t create_disposition
;
526 uint32_t create_options
= 0;
527 uint32_t private_flags
= 0;
529 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
530 TALLOC_CTX
*ctx
= talloc_tos();
533 * Ensure we have enough parameters to perform the operation.
536 if (total_params
< 29) {
537 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
541 flags
= SVAL(params
, 0);
542 deny_mode
= SVAL(params
, 2);
543 open_attr
= SVAL(params
,6);
544 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
545 if (oplock_request
) {
546 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
550 return_additional_info
= BITSETW(params
,0);
551 open_sattr
= SVAL(params
, 4);
552 open_time
= make_unix_date3(params
+8);
554 open_ofun
= SVAL(params
,12);
555 open_size
= IVAL(params
,14);
559 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
563 if (req
->posix_pathnames
) {
564 srvstr_get_path_posix(ctx
,
582 if (!NT_STATUS_IS_OK(status
)) {
583 reply_nterror(req
, status
);
587 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
588 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
589 (unsigned int)open_ofun
, open_size
));
591 if (ucf_flags
& UCF_GMT_PATHNAME
) {
592 extract_snapshot_token(fname
, &twrp
);
594 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &fname
);
595 if (!NT_STATUS_IS_OK(status
)) {
596 reply_nterror(req
, status
);
599 status
= filename_convert_dirfsp(ctx
,
606 if (!NT_STATUS_IS_OK(status
)) {
607 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
609 NT_STATUS_PATH_NOT_COVERED
,
613 reply_nterror(req
, status
);
617 if (open_ofun
== 0) {
618 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
622 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
624 &access_mask
, &share_mode
,
628 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
632 /* Any data in this call is an EA list. */
633 if (total_data
&& (total_data
!= 4)) {
634 if (total_data
< 10) {
635 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
639 if (IVAL(pdata
,0) > total_data
) {
640 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
641 IVAL(pdata
,0), (unsigned int)total_data
));
642 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
646 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
649 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
653 if (!lp_ea_support(SNUM(conn
))) {
654 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
658 if (!req
->posix_pathnames
&&
659 ea_list_has_invalid_name(ea_list
)) {
661 *pparams
= (char *)SMB_REALLOC(*pparams
, param_len
);
662 if(*pparams
== NULL
) {
663 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
667 memset(params
, '\0', param_len
);
668 send_trans2_replies(conn
, req
, STATUS_INVALID_EA_NAME
,
669 params
, param_len
, NULL
, 0, max_data_bytes
);
674 status
= SMB_VFS_CREATE_FILE(
678 smb_fname
, /* fname */
679 access_mask
, /* access_mask */
680 share_mode
, /* share_access */
681 create_disposition
, /* create_disposition*/
682 create_options
, /* create_options */
683 open_attr
, /* file_attributes */
684 oplock_request
, /* oplock_request */
686 open_size
, /* allocation_size */
689 ea_list
, /* ea_list */
691 &smb_action
, /* psbuf */
692 NULL
, NULL
); /* create context */
694 if (!NT_STATUS_IS_OK(status
)) {
695 if (open_was_deferred(req
->xconn
, req
->mid
)) {
696 /* We have re-scheduled this call. */
700 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
701 reply_openerror(req
, status
);
705 fsp
= fcb_or_dos_open(
712 bool ok
= defer_smb1_sharing_violation(req
);
716 reply_openerror(req
, status
);
720 smb_action
= FILE_WAS_OPENED
;
723 size
= get_file_size_stat(&smb_fname
->st
);
724 fattr
= fdos_mode(fsp
);
725 inode
= smb_fname
->st
.st_ex_ino
;
726 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
727 close_file_free(req
, &fsp
, ERROR_CLOSE
);
728 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
732 /* Realloc the size of parameters and data we will return */
733 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
734 if(*pparams
== NULL
) {
735 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
740 SSVAL(params
,0,fsp
->fnum
);
741 SSVAL(params
,2,fattr
);
742 srv_put_dos_date2_ts(params
, 4, smb_fname
->st
.st_ex_mtime
);
743 SIVAL(params
,8, (uint32_t)size
);
744 SSVAL(params
,12,deny_mode
);
745 SSVAL(params
,14,0); /* open_type - file or directory. */
746 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
748 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
749 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
752 SSVAL(params
,18,smb_action
);
755 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
757 SIVAL(params
,20,inode
);
758 SSVAL(params
,24,0); /* Padding. */
760 uint32_t ea_size
= estimate_ea_size(smb_fname
->fsp
);
761 SIVAL(params
, 26, ea_size
);
763 SIVAL(params
, 26, 0);
766 /* Send the required number of replies */
767 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 30, *ppdata
, 0, max_data_bytes
);
769 TALLOC_FREE(smb_fname
);
772 static NTSTATUS
get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
773 connection_struct
*conn
,
774 struct dptr_struct
*dirptr
,
776 const char *path_mask
,
779 bool requires_resume_key
,
787 struct ea_list
*name_list
)
790 const bool do_pad
= true;
792 if (info_level
>= 1 && info_level
<= 3) {
793 /* No alignment on earlier info levels. */
797 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
798 path_mask
, dirtype
, info_level
,
799 requires_resume_key
, dont_descend
, ask_sharemode
,
801 ppdata
, base_data
, end_data
,
804 last_entry_off
, name_list
, NULL
);
807 /****************************************************************************
808 Reply to a TRANS2_FINDFIRST.
809 ****************************************************************************/
811 static void call_trans2findfirst(connection_struct
*conn
,
812 struct smb_request
*req
,
813 char **pparams
, int total_params
,
814 char **ppdata
, int total_data
,
815 unsigned int max_data_bytes
)
817 /* We must be careful here that we don't return more than the
818 allowed number of data bytes. If this means returning fewer than
819 maxentries then so be it. We assume that the redirector has
820 enough room for the fixed number of parameter bytes it has
822 struct smb_filename
*smb_dname
= NULL
;
823 char *params
= *pparams
;
824 char *pdata
= *ppdata
;
828 uint16_t findfirst_flags
;
829 bool close_after_first
;
831 bool requires_resume_key
;
833 char *directory
= NULL
;
836 int last_entry_off
=0;
840 bool finished
= False
;
841 bool dont_descend
= False
;
842 bool out_of_space
= False
;
844 struct ea_list
*ea_list
= NULL
;
845 NTSTATUS ntstatus
= NT_STATUS_OK
;
847 struct smbXsrv_connection
*xconn
= req
->xconn
;
848 struct smbd_server_connection
*sconn
= req
->sconn
;
849 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
850 bool backup_priv
= false;
851 bool as_root
= false;
852 files_struct
*fsp
= NULL
;
853 struct files_struct
*dirfsp
= NULL
;
854 const struct loadparm_substitution
*lp_sub
=
855 loadparm_s3_global_substitution();
857 if (total_params
< 13) {
858 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
862 dirtype
= SVAL(params
,0);
863 maxentries
= SVAL(params
,2);
864 findfirst_flags
= SVAL(params
,4);
865 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
866 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
867 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
868 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
869 security_token_has_privilege(get_current_nttok(conn
),
872 info_level
= SVAL(params
,6);
874 DBG_NOTICE("dirtype = %"PRIx32
", maxentries = %d, "
875 "close_after_first=%d, close_if_end = %d "
876 "requires_resume_key = %d backup_priv = %d level = 0x%x, "
877 "max_data_bytes = %d\n",
888 /* W2K3 seems to treat zero as 1. */
892 switch (info_level
) {
893 case SMB_FIND_INFO_STANDARD
:
894 case SMB_FIND_EA_SIZE
:
895 case SMB_FIND_EA_LIST
:
896 case SMB_FIND_FILE_DIRECTORY_INFO
:
897 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
898 case SMB_FIND_FILE_NAMES_INFO
:
899 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
900 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
901 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
903 case SMB_FIND_FILE_UNIX
:
904 case SMB_FIND_FILE_UNIX_INFO2
:
905 if (!lp_smb1_unix_extensions()) {
906 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
909 if (!req
->posix_pathnames
) {
910 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
915 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
919 if (req
->posix_pathnames
) {
920 srvstr_get_path_posix(talloc_tos(),
929 srvstr_get_path(talloc_tos(),
938 if (!NT_STATUS_IS_OK(ntstatus
)) {
939 reply_nterror(req
, ntstatus
);
947 ntstatus
= smb1_strip_dfs_path(talloc_tos(), &ucf_flags
, &directory
);
948 if (!NT_STATUS_IS_OK(ntstatus
)) {
949 reply_nterror(req
, ntstatus
);
953 ntstatus
= filename_convert_smb1_search_path(talloc_tos(),
961 if (!NT_STATUS_IS_OK(ntstatus
)) {
962 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
963 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
967 reply_nterror(req
, ntstatus
);
971 TALLOC_FREE(directory
);
972 directory
= smb_dname
->base_name
;
974 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
976 if (info_level
== SMB_FIND_EA_LIST
) {
979 if (total_data
< 4) {
980 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
984 ea_size
= IVAL(pdata
,0);
985 if (ea_size
!= total_data
) {
986 DBG_NOTICE("Rejecting EA request with incorrect "
987 "total_data=%d (should be %" PRIu32
")\n",
990 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
994 if (!lp_ea_support(SNUM(conn
))) {
995 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
999 /* Pull out the list of names. */
1000 ea_list
= read_ea_name_list(talloc_tos(), pdata
+ 4, ea_size
- 4);
1002 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1007 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
1008 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1012 *ppdata
= (char *)SMB_REALLOC(
1013 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
1014 if(*ppdata
== NULL
) {
1015 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1019 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
1021 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
1024 memset(pdata
+ total_data
, 0, ((max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
) - total_data
));
1025 /* Realloc the params space */
1026 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
1027 if (*pparams
== NULL
) {
1028 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1034 * Open an fsp on this directory for the dptr.
1036 ntstatus
= SMB_VFS_CREATE_FILE(
1039 dirfsp
, /* dirfsp */
1040 smb_dname
, /* dname */
1041 FILE_LIST_DIRECTORY
, /* access_mask */
1043 FILE_SHARE_WRITE
, /* share_access */
1044 FILE_OPEN
, /* create_disposition*/
1045 FILE_DIRECTORY_FILE
, /* create_options */
1046 FILE_ATTRIBUTE_DIRECTORY
,/* file_attributes */
1047 NO_OPLOCK
, /* oplock_request */
1049 0, /* allocation_size */
1050 0, /* private_flags */
1055 NULL
, /* in_context */
1056 NULL
);/* out_context */
1058 if (!NT_STATUS_IS_OK(ntstatus
)) {
1059 DBG_ERR("failed to open directory %s\n",
1060 smb_fname_str_dbg(smb_dname
));
1061 reply_nterror(req
, ntstatus
);
1065 /* Save the wildcard match and attribs we are using on this directory -
1066 needed as lanman2 assumes these are being saved between calls */
1068 ntstatus
= dptr_create(conn
,
1076 if (!NT_STATUS_IS_OK(ntstatus
)) {
1078 * Use NULL here for the first parameter (req)
1079 * as this is not a client visible handle so
1080 * can't be part of an SMB1 chain.
1082 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1083 reply_nterror(req
, ntstatus
);
1088 /* Remember this in case we have
1089 to do a findnext. */
1090 dptr_set_priv(fsp
->dptr
);
1093 dptr_num
= dptr_dnum(fsp
->dptr
);
1094 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
1096 /* We don't need to check for VOL here as this is returned by
1097 a different TRANS2 call. */
1099 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1100 directory
,lp_dont_descend(talloc_tos(), lp_sub
, SNUM(conn
))));
1101 if (in_list(directory
,
1102 lp_dont_descend(talloc_tos(), lp_sub
, SNUM(conn
)),
1103 dptr_case_sensitive(fsp
->dptr
))) {
1104 dont_descend
= True
;
1108 space_remaining
= max_data_bytes
;
1109 out_of_space
= False
;
1111 ask_sharemode
= fsp_search_ask_sharemode(fsp
);
1113 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
1115 ntstatus
= get_lanman2_dir_entry(talloc_tos(),
1122 requires_resume_key
,
1131 if (NT_STATUS_EQUAL(ntstatus
, NT_STATUS_ILLEGAL_CHARACTER
)) {
1133 * Bad character conversion on name. Ignore
1138 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
1139 out_of_space
= true;
1141 finished
= !NT_STATUS_IS_OK(ntstatus
);
1144 if (!finished
&& !out_of_space
) {
1148 /* Ensure space_remaining never goes -ve. */
1149 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
1150 space_remaining
= 0;
1151 out_of_space
= true;
1153 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
1157 /* Check if we can close the dirptr */
1158 if(close_after_first
|| (finished
&& close_if_end
)) {
1159 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
1161 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1165 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1166 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1167 * the protocol level is less than NT1. Tested with smbclient. JRA.
1168 * This should fix the OS/2 client bug #2335.
1171 if(numentries
== 0) {
1174 * We may have already closed the file in the
1175 * close_after_first or finished case above.
1178 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1180 if (xconn
->protocol
< PROTOCOL_NT1
) {
1181 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
1184 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
1185 ERRDOS
, ERRbadfile
);
1190 /* At this point pdata points to numentries directory entries. */
1192 /* Set up the return parameter block */
1193 SSVAL(params
,0,dptr_num
);
1194 SSVAL(params
,2,numentries
);
1195 SSVAL(params
,4,finished
);
1196 SSVAL(params
,6,0); /* Never an EA error */
1197 SSVAL(params
,8,last_entry_off
);
1199 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
1202 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
1203 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
1205 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1209 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1210 smb_fn_name(req
->cmd
),
1211 mask
, directory
, dirtype
, numentries
) );
1214 * Force a name mangle here to ensure that the
1215 * mask as an 8.3 name is top of the mangled cache.
1216 * The reasons for this are subtle. Don't remove
1217 * this code unless you know what you are doing
1218 * (see PR#13758). JRA.
1221 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
1222 char mangled_name
[13];
1223 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
1231 TALLOC_FREE(smb_dname
);
1235 static bool smbd_dptr_name_equal(struct dptr_struct
*dptr
,
1241 if (dptr_case_sensitive(dptr
)) {
1242 equal
= (strcmp(name1
, name2
) == 0);
1244 equal
= strequal(name1
, name2
);
1250 /****************************************************************************
1251 Reply to a TRANS2_FINDNEXT.
1252 ****************************************************************************/
1254 static void call_trans2findnext(connection_struct
*conn
,
1255 struct smb_request
*req
,
1256 char **pparams
, int total_params
,
1257 char **ppdata
, int total_data
,
1258 unsigned int max_data_bytes
)
1260 /* We must be careful here that we don't return more than the
1261 allowed number of data bytes. If this means returning fewer than
1262 maxentries then so be it. We assume that the redirector has
1263 enough room for the fixed number of parameter bytes it has
1265 char *params
= *pparams
;
1266 char *pdata
= *ppdata
;
1270 uint16_t info_level
;
1271 uint32_t resume_key
;
1272 uint16_t findnext_flags
;
1273 bool close_after_request
;
1275 bool requires_resume_key
;
1277 char *resume_name
= NULL
;
1278 const char *mask
= NULL
;
1279 const char *directory
= NULL
;
1283 int i
, last_entry_off
=0;
1284 bool finished
= False
;
1285 bool dont_descend
= False
;
1286 bool out_of_space
= False
;
1287 int space_remaining
;
1288 struct ea_list
*ea_list
= NULL
;
1289 NTSTATUS ntstatus
= NT_STATUS_OK
;
1291 TALLOC_CTX
*ctx
= talloc_tos();
1292 struct smbd_server_connection
*sconn
= req
->sconn
;
1293 bool backup_priv
= false;
1294 bool as_root
= false;
1295 files_struct
*fsp
= NULL
;
1296 const struct loadparm_substitution
*lp_sub
=
1297 loadparm_s3_global_substitution();
1299 if (total_params
< 13) {
1300 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1304 dptr_num
= SVAL(params
,0);
1305 maxentries
= SVAL(params
,2);
1306 info_level
= SVAL(params
,4);
1307 resume_key
= IVAL(params
,6);
1308 findnext_flags
= SVAL(params
,10);
1309 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
1310 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
1311 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
1312 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
1314 if (!continue_bit
) {
1315 /* We only need resume_name if continue_bit is zero. */
1316 if (req
->posix_pathnames
) {
1317 srvstr_get_path_posix(ctx
,
1326 srvstr_get_path(ctx
,
1335 if (!NT_STATUS_IS_OK(ntstatus
)) {
1336 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1337 complain (it thinks we're asking for the directory above the shared
1338 path or an invalid name). Catch this as the resume name is only compared, never used in
1339 a file access. JRA. */
1340 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
1341 &resume_name
, params
+12,
1345 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
1346 reply_nterror(req
, ntstatus
);
1352 DBG_NOTICE("dirhandle = %d, max_data_bytes = %u, maxentries = %d, "
1353 "close_after_request=%d, close_if_end = %d "
1354 "requires_resume_key = %d resume_key = %d "
1355 "resume name = %s continue=%d level = %d\n",
1359 close_after_request
,
1361 requires_resume_key
,
1363 resume_name
? resume_name
: "(NULL)",
1368 /* W2K3 seems to treat zero as 1. */
1372 switch (info_level
) {
1373 case SMB_FIND_INFO_STANDARD
:
1374 case SMB_FIND_EA_SIZE
:
1375 case SMB_FIND_EA_LIST
:
1376 case SMB_FIND_FILE_DIRECTORY_INFO
:
1377 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1378 case SMB_FIND_FILE_NAMES_INFO
:
1379 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1380 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1381 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1383 case SMB_FIND_FILE_UNIX
:
1384 case SMB_FIND_FILE_UNIX_INFO2
:
1385 if (!lp_smb1_unix_extensions()) {
1386 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1389 if (!req
->posix_pathnames
) {
1390 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1395 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1399 if (info_level
== SMB_FIND_EA_LIST
) {
1402 if (total_data
< 4) {
1403 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1407 ea_size
= IVAL(pdata
,0);
1408 if (ea_size
!= total_data
) {
1409 DBG_NOTICE("Rejecting EA request with incorrect "
1410 "total_data=%d (should be %" PRIu32
")\n",
1413 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1417 if (!lp_ea_support(SNUM(conn
))) {
1418 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1422 /* Pull out the list of names. */
1423 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
1425 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1430 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
1431 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1435 *ppdata
= (char *)SMB_REALLOC(
1436 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
1437 if(*ppdata
== NULL
) {
1438 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1443 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
1446 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
1449 memset(pdata
+ total_data
, 0, (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
) - total_data
);
1450 /* Realloc the params space */
1451 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
1452 if(*pparams
== NULL
) {
1453 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1459 /* Check that the dptr is valid */
1460 fsp
= dptr_fetch_lanman2_fsp(sconn
, dptr_num
);
1462 reply_nterror(req
, STATUS_NO_MORE_FILES
);
1466 directory
= dptr_path(sconn
, dptr_num
);
1468 /* Get the wildcard mask from the dptr */
1469 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
1470 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
1471 reply_nterror(req
, STATUS_NO_MORE_FILES
);
1475 /* Get the attr mask from the dptr */
1476 dirtype
= dptr_attr(sconn
, dptr_num
);
1478 backup_priv
= dptr_get_priv(fsp
->dptr
);
1480 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX) "
1481 "backup_priv = %d\n",
1482 dptr_num
, mask
, dirtype
,
1486 /* We don't need to check for VOL here as this is returned by
1487 a different TRANS2 call. */
1489 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1490 directory
,lp_dont_descend(ctx
, lp_sub
, SNUM(conn
))));
1491 if (in_list(directory
,lp_dont_descend(ctx
, lp_sub
, SNUM(conn
)),
1492 dptr_case_sensitive(fsp
->dptr
)))
1493 dont_descend
= True
;
1496 space_remaining
= max_data_bytes
;
1497 out_of_space
= False
;
1505 * Seek to the correct position. We no longer use the resume key but
1506 * depend on the last file name instead.
1509 if(!continue_bit
&& resume_name
&& *resume_name
) {
1510 bool posix_open
= (fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
);
1511 char *last_name_sent
= NULL
;
1515 * Remember, name_to_8_3 is called by
1516 * get_lanman2_dir_entry(), so the resume name
1517 * could be mangled. Ensure we check the unmangled name.
1521 mangle_is_mangled(resume_name
, conn
->params
)) {
1522 char *new_resume_name
= NULL
;
1523 mangle_lookup_name_from_8_3(ctx
,
1527 if (new_resume_name
) {
1528 resume_name
= new_resume_name
;
1533 * Fix for NT redirector problem triggered by resume key indexes
1534 * changing between directory scans. We now return a resume key of 0
1535 * and instead look for the filename to continue from (also given
1536 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1537 * findfirst/findnext (as is usual) then the directory pointer
1538 * should already be at the correct place.
1541 last_name_sent
= smbd_dirptr_get_last_name_sent(fsp
->dptr
);
1542 sequential
= smbd_dptr_name_equal(fsp
->dptr
,
1549 dptr_RewindDir(fsp
->dptr
);
1551 while ((name
= dptr_ReadDirName(talloc_tos(),
1552 fsp
->dptr
)) != NULL
) {
1553 found
= smbd_dptr_name_equal(fsp
->dptr
,
1564 * We got a name that used to exist
1565 * but does not anymore. Just start
1566 * from the beginning. Shown by the
1567 * "raw.search.os2 delete" smbtorture
1570 dptr_RewindDir(fsp
->dptr
);
1573 } /* end if resume_name && !continue_bit */
1575 ask_sharemode
= fsp_search_ask_sharemode(fsp
);
1577 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
1579 ntstatus
= get_lanman2_dir_entry(ctx
,
1586 requires_resume_key
,
1595 if (NT_STATUS_EQUAL(ntstatus
, NT_STATUS_ILLEGAL_CHARACTER
)) {
1597 * Bad character conversion on name. Ignore
1602 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
1603 out_of_space
= true;
1605 finished
= !NT_STATUS_IS_OK(ntstatus
);
1608 if (!finished
&& !out_of_space
) {
1612 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
1615 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1616 smb_fn_name(req
->cmd
),
1617 mask
, directory
, dirtype
, numentries
) );
1619 /* Check if we can close the fsp->dptr */
1620 if(close_after_request
|| (finished
&& close_if_end
)) {
1621 DBG_INFO("closing dptr_num = %d\n", dptr_num
);
1623 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1630 /* Set up the return parameter block */
1631 SSVAL(params
,0,numentries
);
1632 SSVAL(params
,2,finished
);
1633 SSVAL(params
,4,0); /* Never an EA error */
1634 SSVAL(params
,6,last_entry_off
);
1636 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
1642 /****************************************************************************
1643 Reply to a TRANS2_QFSINFO (query filesystem info).
1644 ****************************************************************************/
1646 static void call_trans2qfsinfo(connection_struct
*conn
,
1647 struct smb_request
*req
,
1648 char **pparams
, int total_params
,
1649 char **ppdata
, int total_data
,
1650 unsigned int max_data_bytes
)
1652 char *params
= *pparams
;
1653 uint16_t info_level
;
1655 size_t fixed_portion
;
1658 if (total_params
< 2) {
1659 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1663 info_level
= SVAL(params
,0);
1665 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
1666 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
1667 DEBUG(0,("call_trans2qfsinfo: encryption required "
1668 "and info level 0x%x sent.\n",
1669 (unsigned int)info_level
));
1670 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1675 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
1677 status
= smbd_do_qfsinfo(req
->xconn
, conn
, req
,
1685 if (!NT_STATUS_IS_OK(status
)) {
1686 reply_nterror(req
, status
);
1690 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
1693 DEBUG( 4, ( "%s info_level = %d\n",
1694 smb_fn_name(req
->cmd
), info_level
) );
1699 /****************************************************************************
1700 Reply to a TRANS2_SETFSINFO (set filesystem info).
1701 ****************************************************************************/
1703 static void call_trans2setfsinfo(connection_struct
*conn
,
1704 struct smb_request
*req
,
1705 char **pparams
, int total_params
,
1706 char **ppdata
, int total_data
,
1707 unsigned int max_data_bytes
)
1709 const struct loadparm_substitution
*lp_sub
=
1710 loadparm_s3_global_substitution();
1711 struct smbXsrv_connection
*xconn
= req
->xconn
;
1712 char *pdata
= *ppdata
;
1713 char *params
= *pparams
;
1714 uint16_t info_level
;
1716 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
1717 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
1720 if (total_params
< 4) {
1721 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1723 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1727 info_level
= SVAL(params
,2);
1730 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
1731 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
1732 DEBUG(0,("call_trans2setfsinfo: not an allowed "
1733 "info level (0x%x) on IPC$.\n",
1734 (unsigned int)info_level
));
1735 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1740 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
1741 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
1742 DEBUG(0,("call_trans2setfsinfo: encryption required "
1743 "and info level 0x%x sent.\n",
1744 (unsigned int)info_level
));
1745 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1750 switch(info_level
) {
1751 case SMB_SET_CIFS_UNIX_INFO
:
1752 if (!lp_smb1_unix_extensions()) {
1753 DEBUG(2,("call_trans2setfsinfo: "
1754 "SMB_SET_CIFS_UNIX_INFO is invalid with "
1755 "unix extensions off\n"));
1757 NT_STATUS_INVALID_LEVEL
);
1761 /* There should be 12 bytes of capabilities set. */
1762 if (total_data
< 12) {
1765 NT_STATUS_INVALID_PARAMETER
);
1768 xconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
1769 xconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
1770 xconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
1771 xconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
1773 /* Just print these values for now. */
1774 DBG_DEBUG("set unix_info info. "
1775 "major = %"PRIu16
", minor = %"PRIu16
1776 "cap_low = 0x%"PRIx32
", "
1777 "cap_high = 0x%"PRIx32
"\n",
1778 xconn
->smb1
.unix_info
.client_major
,
1779 xconn
->smb1
.unix_info
.client_minor
,
1780 xconn
->smb1
.unix_info
.client_cap_low
,
1781 xconn
->smb1
.unix_info
.client_cap_high
);
1784 * Here is where we must switch to posix
1785 * pathname processing...
1787 if (xconn
->smb1
.unix_info
.client_cap_low
&
1788 CIFS_UNIX_POSIX_PATHNAMES_CAP
)
1790 lp_set_posix_pathnames();
1791 mangle_change_to_posix();
1794 if ((xconn
->smb1
.unix_info
.client_cap_low
&
1795 CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
1796 !(xconn
->smb1
.unix_info
.client_cap_low
&
1797 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
))
1799 /* Client that knows how to do posix locks,
1800 * but not posix open/mkdir operations. Set a
1801 * default type for read/write checks. */
1803 lp_set_posix_default_cifsx_readwrite_locktype(
1809 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
1812 size_t param_len
= 0;
1813 size_t data_len
= total_data
;
1815 if (!lp_smb1_unix_extensions()) {
1818 NT_STATUS_INVALID_LEVEL
);
1822 if (lp_server_smb_encrypt(SNUM(conn
)) ==
1823 SMB_ENCRYPTION_OFF
) {
1826 NT_STATUS_NOT_SUPPORTED
);
1830 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
1831 DEBUG( 2,("call_trans2setfsinfo: "
1832 "request transport encryption disabled"
1833 "with 'fork echo handler = yes'\n"));
1836 NT_STATUS_NOT_SUPPORTED
);
1840 DEBUG( 4,("call_trans2setfsinfo: "
1841 "request transport encryption.\n"));
1843 status
= srv_request_encryption_setup(conn
,
1844 (unsigned char **)ppdata
,
1846 (unsigned char **)pparams
,
1849 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
1850 !NT_STATUS_IS_OK(status
)) {
1851 reply_nterror(req
, status
);
1855 send_trans2_replies(conn
, req
,
1863 if (NT_STATUS_IS_OK(status
)) {
1864 /* Server-side transport
1865 * encryption is now *on*. */
1866 status
= srv_encryption_start(conn
);
1867 if (!NT_STATUS_IS_OK(status
)) {
1868 char *reason
= talloc_asprintf(talloc_tos(),
1869 "Failure in setting "
1870 "up encrypted transport: %s",
1872 exit_server_cleanly(reason
);
1878 case SMB_FS_QUOTA_INFORMATION
:
1882 .data
= (uint8_t *)pdata
,
1883 .length
= total_data
1885 files_struct
*fsp
= NULL
;
1886 fsp
= file_fsp(req
, SVAL(params
,0));
1888 status
= smb_set_fsquota(conn
,
1892 if (!NT_STATUS_IS_OK(status
)) {
1893 reply_nterror(req
, status
);
1899 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1901 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1907 * sending this reply works fine,
1908 * but I'm not sure it's the same
1909 * like windows do...
1912 reply_smb1_outbuf(req
, 10, 0);
1915 /****************************************************************************
1916 Reply to a TRANSACT2_QFILEINFO on a PIPE !
1917 ****************************************************************************/
1919 static void call_trans2qpipeinfo(connection_struct
*conn
,
1920 struct smb_request
*req
,
1922 uint16_t info_level
,
1923 unsigned int tran_call
,
1924 char **pparams
, int total_params
,
1925 char **ppdata
, int total_data
,
1926 unsigned int max_data_bytes
)
1928 char *params
= *pparams
;
1929 char *pdata
= *ppdata
;
1930 unsigned int data_size
= 0;
1931 unsigned int param_size
= 2;
1933 if (!fsp_is_np(fsp
)) {
1934 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1938 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
1939 if (*pparams
== NULL
) {
1940 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1945 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
1946 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1949 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
1950 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
1951 if (*ppdata
== NULL
) {
1952 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1957 switch (info_level
) {
1958 case SMB_FILE_STANDARD_INFORMATION
:
1960 SOFF_T(pdata
,0,4096LL);
1967 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1971 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
1975 static void handle_trans2qfilepathinfo_result(
1976 connection_struct
*conn
,
1977 struct smb_request
*req
,
1978 uint16_t info_level
,
1981 int data_return_size
,
1982 size_t fixed_portion
,
1983 unsigned int max_data_bytes
)
1985 char params
[2] = { 0, 0, };
1989 * draft-leach-cifs-v1-spec-02.txt
1990 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
1993 * The requested information is placed in the Data portion of the
1994 * transaction response. For the information levels greater than 0x100,
1995 * the transaction response has 1 parameter word which should be
1996 * ignored by the client.
1998 * However Windows only follows this rule for the IS_NAME_VALID call.
2000 switch (info_level
) {
2001 case SMB_INFO_IS_NAME_VALID
:
2006 if (!NT_STATUS_IS_OK(status
)) {
2007 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2008 /* We have re-scheduled this call. */
2011 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2012 bool ok
= defer_smb1_sharing_violation(req
);
2017 reply_nterror(req
, status
);
2021 if (fixed_portion
> max_data_bytes
) {
2022 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
2026 send_trans2_replies(
2037 /****************************************************************************
2038 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2039 file name or file id).
2040 ****************************************************************************/
2042 static void call_trans2qfilepathinfo(connection_struct
*conn
,
2043 struct smb_request
*req
,
2044 unsigned int tran_call
,
2045 uint16_t info_level
,
2046 struct smb_filename
*smb_fname
,
2047 struct files_struct
*fsp
,
2048 bool delete_pending
,
2049 struct timespec write_time_ts
,
2050 char **pparams
, int total_params
,
2051 char **ppdata
, int total_data
,
2052 unsigned int max_data_bytes
)
2054 char *params
= *pparams
;
2055 char *pdata
= *ppdata
;
2056 unsigned int data_size
= 0;
2057 struct ea_list
*ea_list
= NULL
;
2058 size_t fixed_portion
;
2059 NTSTATUS status
= NT_STATUS_OK
;
2061 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
2062 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
2064 info_level
,tran_call
,total_data
));
2066 /* Pull out any data sent here before we realloc. */
2067 switch (info_level
) {
2068 case SMB_INFO_QUERY_EAS_FROM_LIST
:
2070 /* Pull any EA list from the data portion. */
2073 if (total_data
< 4) {
2075 req
, NT_STATUS_INVALID_PARAMETER
);
2078 ea_size
= IVAL(pdata
,0);
2080 if (total_data
> 0 && ea_size
!= total_data
) {
2081 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2082 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2084 req
, NT_STATUS_INVALID_PARAMETER
);
2088 if (!lp_ea_support(SNUM(conn
))) {
2089 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2093 /* Pull out the list of names. */
2094 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
2097 req
, NT_STATUS_INVALID_PARAMETER
);
2107 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
2108 if (*pparams
== NULL
) {
2109 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2115 if ((info_level
& SMB2_INFO_SPECIAL
) == SMB2_INFO_SPECIAL
) {
2117 * We use levels that start with 0xFF00
2118 * internally to represent SMB2 specific levels
2120 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2124 status
= smbd_do_qfilepathinfo(conn
, req
, req
, info_level
,
2126 delete_pending
, write_time_ts
,
2128 req
->flags2
, max_data_bytes
,
2130 ppdata
, &data_size
);
2132 handle_trans2qfilepathinfo_result(
2143 static NTSTATUS
smb_q_unix_basic(
2144 struct connection_struct
*conn
,
2145 struct smb_request
*req
,
2146 struct smb_filename
*smb_fname
,
2147 struct files_struct
*fsp
,
2151 const int total_data
= 100;
2153 *ppdata
= SMB_REALLOC(*ppdata
, total_data
);
2154 if (*ppdata
== NULL
) {
2155 return NT_STATUS_NO_MEMORY
;
2157 store_file_unix_basic(conn
, *ppdata
, fsp
, &smb_fname
->st
);
2159 *ptotal_data
= total_data
;
2161 return NT_STATUS_OK
;
2164 static NTSTATUS
smb_q_unix_info2(
2165 struct connection_struct
*conn
,
2166 struct smb_request
*req
,
2167 struct smb_filename
*smb_fname
,
2168 struct files_struct
*fsp
,
2172 const int total_data
= 116;
2174 *ppdata
= SMB_REALLOC(*ppdata
, total_data
);
2175 if (*ppdata
== NULL
) {
2176 return NT_STATUS_NO_MEMORY
;
2178 store_file_unix_basic_info2(conn
, *ppdata
, fsp
, &smb_fname
->st
);
2180 *ptotal_data
= total_data
;
2182 return NT_STATUS_OK
;
2185 #if defined(HAVE_POSIX_ACLS)
2186 /****************************************************************************
2187 Utility function to open a fsp for a POSIX handle operation.
2188 ****************************************************************************/
2190 static NTSTATUS
get_posix_fsp(connection_struct
*conn
,
2191 struct smb_request
*req
,
2192 struct smb_filename
*smb_fname
,
2193 uint32_t access_mask
,
2194 files_struct
**ret_fsp
)
2197 uint32_t create_disposition
= FILE_OPEN
;
2198 uint32_t share_access
= FILE_SHARE_READ
|
2201 struct smb2_create_blobs
*posx
= NULL
;
2204 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
2205 * but set reasonable defaults.
2207 uint32_t file_attributes
= 0664;
2208 uint32_t oplock
= NO_OPLOCK
;
2209 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
2211 /* File or directory must exist. */
2212 if (!VALID_STAT(smb_fname
->st
)) {
2213 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
2215 /* Cannot be a symlink. */
2216 if (S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
2217 return NT_STATUS_ACCESS_DENIED
;
2219 /* Set options correctly for directory open. */
2220 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
2222 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
2223 * directories, but set reasonable defaults.
2225 file_attributes
= 0775;
2226 create_options
= FILE_DIRECTORY_FILE
;
2229 status
= make_smb2_posix_create_ctx(
2230 talloc_tos(), &posx
, file_attributes
);
2231 if (!NT_STATUS_IS_OK(status
)) {
2232 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
2237 status
= SMB_VFS_CREATE_FILE(
2241 smb_fname
, /* fname */
2242 access_mask
, /* access_mask */
2243 share_access
, /* share_access */
2244 create_disposition
,/* create_disposition*/
2245 create_options
, /* create_options */
2246 file_attributes
,/* file_attributes */
2247 oplock
, /* oplock_request */
2249 0, /* allocation_size */
2250 0, /* private_flags */
2253 ret_fsp
, /* result */
2255 posx
, /* in_context */
2256 NULL
); /* out_context */
2263 /****************************************************************************
2264 Utility function to count the number of entries in a POSIX acl.
2265 ****************************************************************************/
2267 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
2269 unsigned int ace_count
= 0;
2270 int entry_id
= SMB_ACL_FIRST_ENTRY
;
2271 SMB_ACL_ENTRY_T entry
;
2273 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
2274 entry_id
= SMB_ACL_NEXT_ENTRY
;
2280 /****************************************************************************
2281 Utility function to marshall a POSIX acl into wire format.
2282 ****************************************************************************/
2284 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
2286 int entry_id
= SMB_ACL_FIRST_ENTRY
;
2287 SMB_ACL_ENTRY_T entry
;
2289 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
2290 SMB_ACL_TAG_T tagtype
;
2291 SMB_ACL_PERMSET_T permset
;
2292 unsigned char perms
= 0;
2293 unsigned int own_grp
;
2295 entry_id
= SMB_ACL_NEXT_ENTRY
;
2297 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
2298 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2302 if (sys_acl_get_permset(entry
, &permset
) == -1) {
2303 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2307 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
2308 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
2309 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
2311 SCVAL(pdata
,1,perms
);
2314 case SMB_ACL_USER_OBJ
:
2315 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
2316 own_grp
= (unsigned int)pst
->st_ex_uid
;
2317 SIVAL(pdata
,2,own_grp
);
2322 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
2324 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2327 own_grp
= (unsigned int)*puid
;
2328 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
2329 SIVAL(pdata
,2,own_grp
);
2333 case SMB_ACL_GROUP_OBJ
:
2334 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
2335 own_grp
= (unsigned int)pst
->st_ex_gid
;
2336 SIVAL(pdata
,2,own_grp
);
2341 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
2343 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2346 own_grp
= (unsigned int)*pgid
;
2347 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
2348 SIVAL(pdata
,2,own_grp
);
2353 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
2354 SIVAL(pdata
,2,0xFFFFFFFF);
2355 SIVAL(pdata
,6,0xFFFFFFFF);
2358 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
2359 SIVAL(pdata
,2,0xFFFFFFFF);
2360 SIVAL(pdata
,6,0xFFFFFFFF);
2363 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2366 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
2373 static NTSTATUS
smb_q_posix_acl(
2374 struct connection_struct
*conn
,
2375 struct smb_request
*req
,
2376 struct smb_filename
*smb_fname
,
2377 struct files_struct
*fsp
,
2381 #if !defined(HAVE_POSIX_ACLS)
2382 return NT_STATUS_INVALID_LEVEL
;
2385 SMB_ACL_T file_acl
= NULL
;
2386 SMB_ACL_T def_acl
= NULL
;
2387 uint16_t num_file_acls
= 0;
2388 uint16_t num_def_acls
= 0;
2389 unsigned int size_needed
= 0;
2392 bool close_fsp
= false;
2395 * Ensure we always operate on a file descriptor, not just
2398 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
2399 uint32_t access_mask
= SEC_STD_READ_CONTROL
|
2400 FILE_READ_ATTRIBUTES
|
2401 FILE_WRITE_ATTRIBUTES
;
2403 status
= get_posix_fsp(conn
,
2409 if (!NT_STATUS_IS_OK(status
)) {
2415 SMB_ASSERT(fsp
!= NULL
);
2417 status
= refuse_symlink_fsp(fsp
);
2418 if (!NT_STATUS_IS_OK(status
)) {
2422 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
, SMB_ACL_TYPE_ACCESS
,
2425 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
2426 DBG_INFO("ACLs not implemented on "
2427 "filesystem containing %s\n",
2429 status
= NT_STATUS_NOT_IMPLEMENTED
;
2433 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2435 * We can only have default POSIX ACLs on
2438 if (!fsp
->fsp_flags
.is_directory
) {
2439 DBG_INFO("Non-directory open %s\n",
2441 status
= NT_STATUS_INVALID_HANDLE
;
2444 def_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
2445 SMB_ACL_TYPE_DEFAULT
,
2447 def_acl
= free_empty_sys_acl(conn
, def_acl
);
2450 num_file_acls
= count_acl_entries(conn
, file_acl
);
2451 num_def_acls
= count_acl_entries(conn
, def_acl
);
2454 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
2455 status
= NT_STATUS_INVALID_PARAMETER
;
2459 size_needed
= num_file_acls
+ num_def_acls
;
2462 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
2463 * than UINT_MAX, so check by division.
2465 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
2466 status
= NT_STATUS_INVALID_PARAMETER
;
2470 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
2471 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
2472 status
= NT_STATUS_INVALID_PARAMETER
;
2475 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
2477 *ppdata
= SMB_REALLOC(*ppdata
, size_needed
);
2478 if (*ppdata
== NULL
) {
2479 status
= NT_STATUS_NO_MEMORY
;
2484 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
2485 SSVAL(pdata
,2,num_file_acls
);
2486 SSVAL(pdata
,4,num_def_acls
);
2487 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
2489 ok
= marshall_posix_acl(conn
,
2494 status
= NT_STATUS_INTERNAL_ERROR
;
2497 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
2499 ok
= marshall_posix_acl(conn
,
2504 status
= NT_STATUS_INTERNAL_ERROR
;
2508 *ptotal_data
= size_needed
;
2509 status
= NT_STATUS_OK
;
2515 * Ensure the stat struct in smb_fname is up to
2516 * date. Structure copy.
2518 smb_fname
->st
= fsp
->fsp_name
->st
;
2519 (void)close_file_free(req
, &fsp
, NORMAL_CLOSE
);
2522 TALLOC_FREE(file_acl
);
2523 TALLOC_FREE(def_acl
);
2528 static NTSTATUS
smb_q_posix_symlink(
2529 struct connection_struct
*conn
,
2530 struct smb_request
*req
,
2531 struct smb_filename
*smb_fname
,
2535 char buffer
[PATH_MAX
+1];
2539 struct smb_filename
*parent_fname
= NULL
;
2540 struct smb_filename
*base_name
= NULL
;
2543 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
2544 smb_fname_str_dbg(smb_fname
));
2546 if (!S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
2547 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
2550 status
= parent_pathref(
2557 if (!NT_STATUS_IS_OK(status
)) {
2558 DBG_DEBUG("parent_pathref failed: %s\n", nt_errstr(status
));
2562 link_len
= SMB_VFS_READLINKAT(
2568 TALLOC_FREE(parent_fname
);
2570 if (link_len
== -1) {
2571 status
= map_nt_error_from_unix(errno
);
2572 DBG_DEBUG("READLINKAT failed: %s\n", nt_errstr(status
));
2575 if (link_len
>= sizeof(buffer
)) {
2576 return NT_STATUS_INTERNAL_ERROR
;
2578 buffer
[link_len
] = 0;
2580 needed
= (link_len
+1)*2;
2582 *ppdata
= SMB_REALLOC(*ppdata
, needed
);
2583 if (*ppdata
== NULL
) {
2584 return NT_STATUS_NO_MEMORY
;
2588 status
= srvstr_push(
2596 if (!NT_STATUS_IS_OK(status
)) {
2601 return NT_STATUS_OK
;
2604 static void call_trans2qpathinfo(
2605 connection_struct
*conn
,
2606 struct smb_request
*req
,
2611 unsigned int max_data_bytes
)
2613 char *params
= *pparams
;
2614 uint16_t info_level
;
2615 struct smb_filename
*smb_fname
= NULL
;
2616 bool delete_pending
= False
;
2617 struct timespec write_time_ts
= { .tv_sec
= 0, };
2618 struct files_struct
*dirfsp
= NULL
;
2619 files_struct
*fsp
= NULL
;
2620 struct file_id fileid
;
2623 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
2625 bool info_level_handled
;
2626 NTSTATUS status
= NT_STATUS_OK
;
2630 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2636 if (total_params
< 7) {
2637 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2641 info_level
= SVAL(params
,0);
2643 DBG_NOTICE("TRANSACT2_QPATHINFO: level = %d\n", info_level
);
2645 if (INFO_LEVEL_IS_UNIX(info_level
)) {
2646 if (!lp_smb1_unix_extensions()) {
2647 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2650 if (!req
->posix_pathnames
) {
2651 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2656 if (req
->posix_pathnames
) {
2657 srvstr_get_path_posix(req
,
2666 srvstr_get_path(req
,
2675 if (!NT_STATUS_IS_OK(status
)) {
2676 reply_nterror(req
, status
);
2680 if (ucf_flags
& UCF_GMT_PATHNAME
) {
2681 extract_snapshot_token(fname
, &twrp
);
2683 status
= smb1_strip_dfs_path(req
, &ucf_flags
, &fname
);
2684 if (!NT_STATUS_IS_OK(status
)) {
2685 reply_nterror(req
, status
);
2688 status
= filename_convert_dirfsp(req
,
2695 if (!NT_STATUS_IS_OK(status
)) {
2696 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2697 reply_botherror(req
,
2698 NT_STATUS_PATH_NOT_COVERED
,
2699 ERRSRV
, ERRbadpath
);
2702 reply_nterror(req
, status
);
2707 * qpathinfo must operate on an existing file, so we
2708 * can exit early if filename_convert_dirfsp() returned the
2709 * "new file" NT_STATUS_OK, !VALID_STAT case.
2712 if (!VALID_STAT(smb_fname
->st
)) {
2713 reply_nterror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2718 * smb_fname->fsp may be NULL if smb_fname points at a symlink
2719 * and we're in POSIX context, so be careful when using fsp
2720 * below, it can still be NULL.
2722 fsp
= smb_fname
->fsp
;
2724 /* If this is a stream, check if there is a delete_pending. */
2725 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
2726 && is_ntfs_stream_smb_fname(smb_fname
)) {
2727 struct smb_filename
*smb_fname_base
;
2729 /* Create an smb_filename with stream_name == NULL. */
2730 smb_fname_base
= synthetic_smb_fname(
2732 smb_fname
->base_name
,
2737 if (smb_fname_base
== NULL
) {
2738 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2742 ret
= vfs_stat(conn
, smb_fname_base
);
2744 DBG_NOTICE("vfs_stat of %s failed "
2746 smb_fname_str_dbg(smb_fname_base
),
2748 TALLOC_FREE(smb_fname_base
);
2750 map_nt_error_from_unix(errno
));
2754 status
= file_name_hash(conn
,
2755 smb_fname_str_dbg(smb_fname_base
),
2757 if (!NT_STATUS_IS_OK(status
)) {
2758 TALLOC_FREE(smb_fname_base
);
2759 reply_nterror(req
, status
);
2763 fileid
= vfs_file_id_from_sbuf(conn
,
2764 &smb_fname_base
->st
);
2765 TALLOC_FREE(smb_fname_base
);
2766 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
2767 if (delete_pending
) {
2768 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
2773 status
= file_name_hash(conn
,
2774 smb_fname_str_dbg(smb_fname
),
2776 if (!NT_STATUS_IS_OK(status
)) {
2777 reply_nterror(req
, status
);
2781 if (fsp_getinfo_ask_sharemode(fsp
)) {
2782 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
2783 get_file_infos(fileid
, name_hash
, &delete_pending
,
2787 if (delete_pending
) {
2788 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
2792 info_level_handled
= true; /* Untouched in switch cases below */
2794 switch (info_level
) {
2797 info_level_handled
= false;
2800 case SMB_QUERY_FILE_UNIX_BASIC
:
2801 status
= smb_q_unix_basic(
2810 case SMB_QUERY_FILE_UNIX_INFO2
:
2811 status
= smb_q_unix_info2(
2820 case SMB_QUERY_POSIX_ACL
:
2821 status
= smb_q_posix_acl(
2830 case SMB_QUERY_FILE_UNIX_LINK
:
2831 status
= smb_q_posix_symlink(
2840 if (info_level_handled
) {
2841 handle_trans2qfilepathinfo_result(
2853 call_trans2qfilepathinfo(
2856 TRANSACT2_QPATHINFO
,
2869 static NTSTATUS
smb_q_posix_lock(
2870 struct connection_struct
*conn
,
2871 struct smb_request
*req
,
2872 struct files_struct
*fsp
,
2876 char *pdata
= *ppdata
;
2877 int total_data
= *ptotal_data
;
2881 enum brl_type lock_type
;
2884 if (fsp
->fsp_flags
.is_pathref
|| (fsp_get_io_fd(fsp
) == -1)) {
2885 return NT_STATUS_INVALID_HANDLE
;
2888 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
2889 return NT_STATUS_INVALID_PARAMETER
;
2892 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
2893 case POSIX_LOCK_TYPE_READ
:
2894 lock_type
= READ_LOCK
;
2896 case POSIX_LOCK_TYPE_WRITE
:
2897 lock_type
= WRITE_LOCK
;
2899 case POSIX_LOCK_TYPE_UNLOCK
:
2901 /* There's no point in asking for an unlock... */
2902 return NT_STATUS_INVALID_PARAMETER
;
2905 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
2906 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
2907 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
2909 status
= query_lock(
2917 if (NT_STATUS_IS_OK(status
)) {
2919 * For success we just return a copy of what we sent
2920 * with the lock type set to POSIX_LOCK_TYPE_UNLOCK.
2922 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
2923 return NT_STATUS_OK
;
2926 if (!ERROR_WAS_LOCK_DENIED(status
)) {
2927 DBG_DEBUG("query_lock() failed: %s\n", nt_errstr(status
));
2932 * Here we need to report who has it locked.
2935 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
2936 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
2937 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
2938 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
2939 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
2941 return NT_STATUS_OK
;
2944 static void call_trans2qfileinfo(
2945 connection_struct
*conn
,
2946 struct smb_request
*req
,
2951 unsigned int max_data_bytes
)
2953 char *params
= *pparams
;
2954 uint16_t info_level
;
2955 struct smb_filename
*smb_fname
= NULL
;
2956 bool delete_pending
= False
;
2957 struct timespec write_time_ts
= { .tv_sec
= 0, };
2958 files_struct
*fsp
= NULL
;
2959 struct file_id fileid
;
2960 bool info_level_handled
;
2961 NTSTATUS status
= NT_STATUS_OK
;
2964 if (params
== NULL
) {
2965 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2969 if (total_params
< 4) {
2970 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2974 fsp
= file_fsp(req
, SVAL(params
,0));
2975 info_level
= SVAL(params
,2);
2978 call_trans2qpipeinfo(
2983 TRANSACT2_QFILEINFO
,
2992 DBG_NOTICE("TRANSACT2_QFILEINFO: level = %d\n", info_level
);
2994 if (INFO_LEVEL_IS_UNIX(info_level
)) {
2995 if (!lp_smb1_unix_extensions()) {
2996 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2999 if (!req
->posix_pathnames
) {
3000 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3005 /* Initial check for valid fsp ptr. */
3006 if (!check_fsp_open(conn
, req
, fsp
)) {
3010 smb_fname
= fsp
->fsp_name
;
3012 if(fsp
->fake_file_handle
) {
3014 * This is actually for the QUOTA_FAKE_FILE --metze
3017 /* We know this name is ok, it's already passed the checks. */
3019 } else if(fsp_get_pathref_fd(fsp
) == -1) {
3021 * This is actually a QFILEINFO on a directory
3022 * handle (returned from an NT SMB). NT5.0 seems
3023 * to do this call. JRA.
3025 ret
= vfs_stat(conn
, smb_fname
);
3027 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
3028 smb_fname_str_dbg(smb_fname
),
3031 map_nt_error_from_unix(errno
));
3035 if (fsp_getinfo_ask_sharemode(fsp
)) {
3036 fileid
= vfs_file_id_from_sbuf(
3037 conn
, &smb_fname
->st
);
3038 get_file_infos(fileid
, fsp
->name_hash
,
3044 * Original code - this is an open file.
3046 status
= vfs_stat_fsp(fsp
);
3047 if (!NT_STATUS_IS_OK(status
)) {
3048 DEBUG(3, ("fstat of %s failed (%s)\n",
3049 fsp_fnum_dbg(fsp
), nt_errstr(status
)));
3050 reply_nterror(req
, status
);
3053 if (fsp_getinfo_ask_sharemode(fsp
)) {
3054 fileid
= vfs_file_id_from_sbuf(
3055 conn
, &smb_fname
->st
);
3056 get_file_infos(fileid
, fsp
->name_hash
,
3062 info_level_handled
= true; /* Untouched in switch cases below */
3064 switch (info_level
) {
3067 info_level_handled
= false;
3070 case SMB_QUERY_POSIX_LOCK
:
3071 status
= smb_q_posix_lock(conn
, req
, fsp
, ppdata
, &total_data
);
3074 case SMB_QUERY_FILE_UNIX_BASIC
:
3075 status
= smb_q_unix_basic(
3076 conn
, req
, fsp
->fsp_name
, fsp
, ppdata
, &total_data
);
3079 case SMB_QUERY_FILE_UNIX_INFO2
:
3080 status
= smb_q_unix_info2(
3081 conn
, req
, fsp
->fsp_name
, fsp
, ppdata
, &total_data
);
3084 case SMB_QUERY_POSIX_ACL
:
3085 status
= smb_q_posix_acl(
3086 conn
, req
, fsp
->fsp_name
, fsp
, ppdata
, &total_data
);
3090 if (info_level_handled
) {
3091 handle_trans2qfilepathinfo_result(
3103 call_trans2qfilepathinfo(
3106 TRANSACT2_QFILEINFO
,
3119 static void handle_trans2setfilepathinfo_result(
3120 connection_struct
*conn
,
3121 struct smb_request
*req
,
3122 uint16_t info_level
,
3125 int data_return_size
,
3126 unsigned int max_data_bytes
)
3128 char params
[2] = { 0, 0, };
3130 if (NT_STATUS_IS_OK(status
)) {
3131 send_trans2_replies(
3143 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3144 /* We have re-scheduled this call. */
3148 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
3149 bool ok
= defer_smb1_sharing_violation(req
);
3155 if (NT_STATUS_EQUAL(status
, NT_STATUS_EVENT_PENDING
)) {
3156 /* We have re-scheduled this call. */
3160 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3163 NT_STATUS_PATH_NOT_COVERED
,
3169 if (info_level
== SMB_POSIX_PATH_OPEN
) {
3170 reply_openerror(req
, status
);
3174 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
3176 * Invalid EA name needs to return 2 param bytes,
3177 * not a zero-length error packet.
3180 send_trans2_replies(
3192 reply_nterror(req
, status
);
3195 /****************************************************************************
3196 Create a directory with POSIX semantics.
3197 ****************************************************************************/
3199 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
3200 struct smb_request
*req
,
3203 struct smb_filename
*smb_fname
,
3204 int *pdata_return_size
)
3206 NTSTATUS status
= NT_STATUS_OK
;
3207 uint32_t raw_unixmode
= 0;
3208 mode_t unixmode
= (mode_t
)0;
3209 files_struct
*fsp
= NULL
;
3210 uint16_t info_level_return
= 0;
3212 char *pdata
= *ppdata
;
3213 struct smb2_create_blobs
*posx
= NULL
;
3215 if (total_data
< 18) {
3216 return NT_STATUS_INVALID_PARAMETER
;
3219 raw_unixmode
= IVAL(pdata
,8);
3220 /* Next 4 bytes are not yet defined. */
3222 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
3223 PERM_NEW_DIR
, &unixmode
);
3224 if (!NT_STATUS_IS_OK(status
)) {
3228 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, unixmode
);
3229 if (!NT_STATUS_IS_OK(status
)) {
3230 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3235 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
3236 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
3238 status
= SMB_VFS_CREATE_FILE(
3242 smb_fname
, /* fname */
3243 FILE_READ_ATTRIBUTES
, /* access_mask */
3244 FILE_SHARE_NONE
, /* share_access */
3245 FILE_CREATE
, /* create_disposition*/
3246 FILE_DIRECTORY_FILE
, /* create_options */
3247 0, /* file_attributes */
3248 0, /* oplock_request */
3250 0, /* allocation_size */
3251 0, /* private_flags */
3256 posx
, /* in_context_blobs */
3257 NULL
); /* out_context_blobs */
3261 if (NT_STATUS_IS_OK(status
)) {
3262 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3265 info_level_return
= SVAL(pdata
,16);
3267 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
3268 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
3269 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
3270 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
3272 *pdata_return_size
= 12;
3275 /* Realloc the data size */
3276 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
3277 if (*ppdata
== NULL
) {
3278 *pdata_return_size
= 0;
3279 return NT_STATUS_NO_MEMORY
;
3283 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
3284 SSVAL(pdata
,2,0); /* No fnum. */
3285 SIVAL(pdata
,4,info
); /* Was directory created. */
3287 switch (info_level_return
) {
3288 case SMB_QUERY_FILE_UNIX_BASIC
:
3289 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
3290 SSVAL(pdata
,10,0); /* Padding. */
3291 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
3294 case SMB_QUERY_FILE_UNIX_INFO2
:
3295 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
3296 SSVAL(pdata
,10,0); /* Padding. */
3297 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
3301 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
3302 SSVAL(pdata
,10,0); /* Padding. */
3309 /****************************************************************************
3310 Open/Create a file with POSIX semantics.
3311 ****************************************************************************/
3313 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
3314 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
3316 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
3317 struct smb_request
*req
,
3320 struct files_struct
*dirfsp
,
3321 struct smb_filename
*smb_fname
,
3322 int *pdata_return_size
)
3324 bool extended_oplock_granted
= False
;
3325 char *pdata
= *ppdata
;
3327 uint32_t wire_open_mode
= 0;
3328 uint32_t raw_unixmode
= 0;
3329 uint32_t attributes
= 0;
3330 uint32_t create_disp
= 0;
3331 uint32_t access_mask
= 0;
3332 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
3333 NTSTATUS status
= NT_STATUS_OK
;
3334 mode_t unixmode
= (mode_t
)0;
3335 files_struct
*fsp
= NULL
;
3336 int oplock_request
= 0;
3338 uint16_t info_level_return
= 0;
3339 struct smb2_create_blobs
*posx
= NULL
;
3341 if (total_data
< 18) {
3342 return NT_STATUS_INVALID_PARAMETER
;
3345 flags
= IVAL(pdata
,0);
3346 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
3347 if (oplock_request
) {
3348 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
3351 wire_open_mode
= IVAL(pdata
,4);
3353 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
3354 return smb_posix_mkdir(conn
, req
,
3361 switch (wire_open_mode
& SMB_ACCMODE
) {
3363 access_mask
= SMB_O_RDONLY_MAPPING
;
3366 access_mask
= SMB_O_WRONLY_MAPPING
;
3369 access_mask
= (SMB_O_RDONLY_MAPPING
|
3370 SMB_O_WRONLY_MAPPING
);
3373 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
3374 (unsigned int)wire_open_mode
));
3375 return NT_STATUS_INVALID_PARAMETER
;
3378 wire_open_mode
&= ~SMB_ACCMODE
;
3380 /* First take care of O_CREAT|O_EXCL interactions. */
3381 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
3382 case (SMB_O_CREAT
| SMB_O_EXCL
):
3383 /* File exists fail. File not exist create. */
3384 create_disp
= FILE_CREATE
;
3387 /* File exists open. File not exist create. */
3388 create_disp
= FILE_OPEN_IF
;
3391 /* O_EXCL on its own without O_CREAT is undefined.
3392 We deliberately ignore it as some versions of
3393 Linux CIFSFS can send a bare O_EXCL on the
3394 wire which other filesystems in the kernel
3395 ignore. See bug 9519 for details. */
3400 /* File exists open. File not exist fail. */
3401 create_disp
= FILE_OPEN
;
3404 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
3405 (unsigned int)wire_open_mode
));
3406 return NT_STATUS_INVALID_PARAMETER
;
3409 /* Next factor in the effects of O_TRUNC. */
3410 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
3412 if (wire_open_mode
& SMB_O_TRUNC
) {
3413 switch (create_disp
) {
3415 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
3416 /* Leave create_disp alone as
3417 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
3419 /* File exists fail. File not exist create. */
3422 /* SMB_O_CREAT | SMB_O_TRUNC */
3423 /* File exists overwrite. File not exist create. */
3424 create_disp
= FILE_OVERWRITE_IF
;
3428 /* File exists overwrite. File not exist fail. */
3429 create_disp
= FILE_OVERWRITE
;
3432 /* Cannot get here. */
3433 smb_panic("smb_posix_open: logic error");
3434 return NT_STATUS_INVALID_PARAMETER
;
3438 raw_unixmode
= IVAL(pdata
,8);
3439 /* Next 4 bytes are not yet defined. */
3441 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
3442 (VALID_STAT(smb_fname
->st
) ?
3443 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
3446 if (!NT_STATUS_IS_OK(status
)) {
3450 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, unixmode
);
3451 if (!NT_STATUS_IS_OK(status
)) {
3452 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3457 if (wire_open_mode
& SMB_O_SYNC
) {
3458 create_options
|= FILE_WRITE_THROUGH
;
3460 if (wire_open_mode
& SMB_O_APPEND
) {
3461 access_mask
|= FILE_APPEND_DATA
;
3463 if (wire_open_mode
& SMB_O_DIRECT
) {
3465 * BUG: this doesn't work anymore since
3466 * e0814dc5082dd4ecca8a155e0ce24b073158fd92. But since
3467 * FILE_FLAG_NO_BUFFERING isn't used at all in the IO codepath,
3468 * it doesn't really matter.
3470 attributes
|= FILE_FLAG_NO_BUFFERING
;
3473 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
3474 VALID_STAT_OF_DIR(smb_fname
->st
)) {
3475 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
3476 return NT_STATUS_FILE_IS_A_DIRECTORY
;
3478 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
3479 create_options
|= FILE_DIRECTORY_FILE
;
3482 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
3483 smb_fname_str_dbg(smb_fname
),
3484 (unsigned int)wire_open_mode
,
3485 (unsigned int)unixmode
));
3487 status
= SMB_VFS_CREATE_FILE(
3490 dirfsp
, /* dirfsp */
3491 smb_fname
, /* fname */
3492 access_mask
, /* access_mask */
3493 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
3495 create_disp
, /* create_disposition*/
3496 create_options
, /* create_options */
3497 attributes
, /* file_attributes */
3498 oplock_request
, /* oplock_request */
3500 0, /* allocation_size */
3501 0, /* private_flags */
3506 posx
, /* in_context_blobs */
3507 NULL
); /* out_context_blobs */
3511 if (!NT_STATUS_IS_OK(status
)) {
3515 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
3516 extended_oplock_granted
= True
;
3519 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
3520 extended_oplock_granted
= True
;
3523 info_level_return
= SVAL(pdata
,16);
3525 /* Allocate the correct return size. */
3527 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
3528 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
3529 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
3530 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
3532 *pdata_return_size
= 12;
3535 /* Realloc the data size */
3536 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
3537 if (*ppdata
== NULL
) {
3538 close_file_free(req
, &fsp
, ERROR_CLOSE
);
3539 *pdata_return_size
= 0;
3540 return NT_STATUS_NO_MEMORY
;
3544 if (extended_oplock_granted
) {
3545 if (flags
& REQUEST_BATCH_OPLOCK
) {
3546 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
3548 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
3550 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
3551 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
3553 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
3556 SSVAL(pdata
,2,fsp
->fnum
);
3557 SIVAL(pdata
,4,info
); /* Was file created etc. */
3559 switch (info_level_return
) {
3560 case SMB_QUERY_FILE_UNIX_BASIC
:
3561 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
3562 SSVAL(pdata
,10,0); /* padding. */
3563 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
3566 case SMB_QUERY_FILE_UNIX_INFO2
:
3567 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
3568 SSVAL(pdata
,10,0); /* padding. */
3569 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
3573 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
3574 SSVAL(pdata
,10,0); /* padding. */
3577 return NT_STATUS_OK
;
3580 /****************************************************************************
3581 Delete a file with POSIX semantics.
3582 ****************************************************************************/
3584 struct smb_posix_unlink_state
{
3585 struct smb_filename
*smb_fname
;
3586 struct files_struct
*fsp
;
3590 static void smb_posix_unlink_locked(struct share_mode_lock
*lck
,
3593 struct smb_posix_unlink_state
*state
= private_data
;
3595 bool other_nonposix_opens
;
3597 other_nonposix_opens
= has_other_nonposix_opens(lck
, state
->fsp
);
3598 if (other_nonposix_opens
) {
3599 /* Fail with sharing violation. */
3600 state
->status
= NT_STATUS_SHARING_VIOLATION
;
3605 * Set the delete on close.
3607 state
->status
= smb_set_file_disposition_info(state
->fsp
->conn
,
3614 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
3615 struct smb_request
*req
,
3618 struct files_struct
*dirfsp
,
3619 struct smb_filename
*smb_fname
)
3621 struct smb_posix_unlink_state state
= {};
3622 NTSTATUS status
= NT_STATUS_OK
;
3623 files_struct
*fsp
= NULL
;
3626 int create_options
= FILE_OPEN_REPARSE_POINT
;
3627 struct smb2_create_blobs
*posx
= NULL
;
3629 if (!CAN_WRITE(conn
)) {
3630 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
3633 if (total_data
< 2) {
3634 return NT_STATUS_INVALID_PARAMETER
;
3637 flags
= SVAL(pdata
,0);
3639 if (!VALID_STAT(smb_fname
->st
)) {
3640 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3643 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
3644 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
3645 return NT_STATUS_NOT_A_DIRECTORY
;
3648 DEBUG(10,("smb_posix_unlink: %s %s\n",
3649 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
3650 smb_fname_str_dbg(smb_fname
)));
3652 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
3653 create_options
|= FILE_DIRECTORY_FILE
;
3656 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, 0777);
3657 if (!NT_STATUS_IS_OK(status
)) {
3658 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3663 status
= SMB_VFS_CREATE_FILE(
3666 dirfsp
, /* dirfsp */
3667 smb_fname
, /* fname */
3668 DELETE_ACCESS
, /* access_mask */
3669 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
3671 FILE_OPEN
, /* create_disposition*/
3672 create_options
, /* create_options */
3673 0, /* file_attributes */
3674 0, /* oplock_request */
3676 0, /* allocation_size */
3677 0, /* private_flags */
3682 posx
, /* in_context_blobs */
3683 NULL
); /* out_context_blobs */
3687 if (!NT_STATUS_IS_OK(status
)) {
3692 * Don't lie to client. If we can't really delete due to
3693 * non-POSIX opens return SHARING_VIOLATION.
3696 state
= (struct smb_posix_unlink_state
) {
3697 .smb_fname
= smb_fname
,
3701 status
= share_mode_do_locked_vfs_allowed(fsp
->file_id
,
3702 smb_posix_unlink_locked
,
3704 if (!NT_STATUS_IS_OK(status
)) {
3705 DBG_ERR("share_mode_do_locked_vfs_allowed(%s) failed - %s\n",
3706 fsp_str_dbg(fsp
), nt_errstr(status
));
3707 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3708 return NT_STATUS_INVALID_PARAMETER
;
3711 status
= state
.status
;
3712 if (!NT_STATUS_IS_OK(status
)) {
3713 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3716 return close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3719 /****************************************************************************
3720 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
3721 ****************************************************************************/
3723 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
3724 struct smb_request
*req
,
3727 struct smb_filename
*new_smb_fname
)
3729 char *link_target
= NULL
;
3730 struct smb_filename target_fname
;
3731 TALLOC_CTX
*ctx
= talloc_tos();
3734 struct smb_filename
*parent_fname
= NULL
;
3735 struct smb_filename
*base_name
= NULL
;
3737 if (!CAN_WRITE(conn
)) {
3738 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
3741 /* Set a symbolic link. */
3742 /* Don't allow this if follow links is false. */
3744 if (total_data
== 0) {
3745 return NT_STATUS_INVALID_PARAMETER
;
3748 if (!lp_follow_symlinks(SNUM(conn
))) {
3749 return NT_STATUS_ACCESS_DENIED
;
3752 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
3753 total_data
, STR_TERMINATE
);
3756 return NT_STATUS_INVALID_PARAMETER
;
3759 target_fname
= (struct smb_filename
) {
3760 .base_name
= link_target
,
3763 /* Removes @GMT tokens if any */
3764 status
= canonicalize_snapshot_path(&target_fname
, UCF_GMT_PATHNAME
, 0);
3765 if (!NT_STATUS_IS_OK(status
)) {
3769 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3770 new_smb_fname
->base_name
, link_target
));
3772 status
= parent_pathref(talloc_tos(),
3777 if (!NT_STATUS_IS_OK(status
)) {
3781 ret
= SMB_VFS_SYMLINKAT(conn
,
3786 TALLOC_FREE(parent_fname
);
3787 return map_nt_error_from_unix(errno
);
3790 TALLOC_FREE(parent_fname
);
3791 return NT_STATUS_OK
;
3794 /****************************************************************************
3795 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
3796 ****************************************************************************/
3798 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
3799 struct smb_request
*req
,
3800 const char *pdata
, int total_data
,
3801 struct smb_filename
*smb_fname_new
)
3803 char *oldname
= NULL
;
3804 struct files_struct
*src_dirfsp
= NULL
;
3805 struct smb_filename
*smb_fname_old
= NULL
;
3806 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
3807 NTTIME old_twrp
= 0;
3808 TALLOC_CTX
*ctx
= talloc_tos();
3809 NTSTATUS status
= NT_STATUS_OK
;
3811 if (!CAN_WRITE(conn
)) {
3812 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
3815 /* Set a hard link. */
3816 if (total_data
== 0) {
3817 return NT_STATUS_INVALID_PARAMETER
;
3820 if (req
->posix_pathnames
) {
3821 srvstr_get_path_posix(ctx
,
3830 srvstr_get_path(ctx
,
3839 if (!NT_STATUS_IS_OK(status
)) {
3843 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3844 smb_fname_str_dbg(smb_fname_new
), oldname
));
3846 if (ucf_flags
& UCF_GMT_PATHNAME
) {
3847 extract_snapshot_token(oldname
, &old_twrp
);
3849 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &oldname
);
3850 if (!NT_STATUS_IS_OK(status
)) {
3853 status
= filename_convert_dirfsp(ctx
,
3860 if (!NT_STATUS_IS_OK(status
)) {
3864 return hardlink_internals(ctx
,
3872 /****************************************************************************
3873 Allow a UNIX info mknod.
3874 ****************************************************************************/
3876 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
3879 struct files_struct
*dirfsp
,
3880 const struct smb_filename
*smb_fname
)
3882 uint32_t file_type
= IVAL(pdata
,56);
3883 #if defined(HAVE_MAKEDEV)
3884 uint32_t dev_major
= IVAL(pdata
,60);
3885 uint32_t dev_minor
= IVAL(pdata
,68);
3887 SMB_DEV_T dev
= (SMB_DEV_T
)0;
3888 uint32_t raw_unixmode
= IVAL(pdata
,84);
3892 struct smb_filename
*parent_fname
= NULL
;
3893 struct smb_filename
*atname
= NULL
;
3895 if (total_data
< 100) {
3896 return NT_STATUS_INVALID_PARAMETER
;
3899 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
3900 PERM_NEW_FILE
, &unixmode
);
3901 if (!NT_STATUS_IS_OK(status
)) {
3905 #if defined(HAVE_MAKEDEV)
3906 dev
= makedev(dev_major
, dev_minor
);
3909 switch (file_type
) {
3910 /* We can't create other objects here. */
3911 case UNIX_TYPE_FILE
:
3913 case UNIX_TYPE_SYMLINK
:
3914 return NT_STATUS_ACCESS_DENIED
;
3915 #if defined(S_IFIFO)
3916 case UNIX_TYPE_FIFO
:
3917 unixmode
|= S_IFIFO
;
3920 #if defined(S_IFSOCK)
3921 case UNIX_TYPE_SOCKET
:
3922 unixmode
|= S_IFSOCK
;
3925 #if defined(S_IFCHR)
3926 case UNIX_TYPE_CHARDEV
:
3927 /* This is only allowed for root. */
3928 if (get_current_uid(conn
) != sec_initial_uid()) {
3929 return NT_STATUS_ACCESS_DENIED
;
3931 unixmode
|= S_IFCHR
;
3934 #if defined(S_IFBLK)
3935 case UNIX_TYPE_BLKDEV
:
3936 if (get_current_uid(conn
) != sec_initial_uid()) {
3937 return NT_STATUS_ACCESS_DENIED
;
3939 unixmode
|= S_IFBLK
;
3943 return NT_STATUS_INVALID_PARAMETER
;
3946 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
3947 "%.0f mode 0%o for file %s\n", (double)dev
,
3948 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
3950 status
= SMB_VFS_PARENT_PATHNAME(dirfsp
->conn
,
3955 if (!NT_STATUS_IS_OK(status
)) {
3959 /* Ok - do the mknod. */
3960 ret
= SMB_VFS_MKNODAT(conn
,
3967 TALLOC_FREE(parent_fname
);
3968 return map_nt_error_from_unix(errno
);
3971 /* If any of the other "set" calls fail we
3972 * don't want to end up with a half-constructed mknod.
3975 if (lp_inherit_permissions(SNUM(conn
))) {
3976 inherit_access_posix_acl(conn
,
3981 TALLOC_FREE(parent_fname
);
3983 return NT_STATUS_OK
;
3986 /****************************************************************************
3987 Deal with SMB_SET_FILE_UNIX_BASIC.
3988 ****************************************************************************/
3990 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
3991 struct smb_request
*req
,
3994 struct files_struct
*dirfsp
,
3996 struct smb_filename
*smb_fname
)
3998 struct smb_file_time ft
;
3999 uint32_t raw_unixmode
;
4002 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
4003 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
4004 NTSTATUS status
= NT_STATUS_OK
;
4005 enum perm_type ptype
;
4006 files_struct
*all_fsps
= NULL
;
4007 bool modify_mtime
= true;
4009 SMB_STRUCT_STAT sbuf
;
4011 if (!CAN_WRITE(conn
)) {
4012 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
4015 init_smb_file_time(&ft
);
4017 if (total_data
< 100) {
4018 return NT_STATUS_INVALID_PARAMETER
;
4021 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
4022 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
4023 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
4024 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
4027 ft
.atime
= pull_long_date_full_timespec(pdata
+24); /* access_time */
4028 ft
.mtime
= pull_long_date_full_timespec(pdata
+32); /* modification_time */
4029 set_owner
= (uid_t
)IVAL(pdata
,40);
4030 set_grp
= (gid_t
)IVAL(pdata
,48);
4031 raw_unixmode
= IVAL(pdata
,84);
4033 if (VALID_STAT(smb_fname
->st
)) {
4034 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
4035 ptype
= PERM_EXISTING_DIR
;
4037 ptype
= PERM_EXISTING_FILE
;
4040 ptype
= PERM_NEW_FILE
;
4043 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
4045 if (!NT_STATUS_IS_OK(status
)) {
4049 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
4050 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4051 smb_fname_str_dbg(smb_fname
), (double)size
,
4052 (unsigned int)set_owner
, (unsigned int)set_grp
,
4053 (int)raw_unixmode
));
4055 sbuf
= smb_fname
->st
;
4057 if (!VALID_STAT(sbuf
)) {
4059 * The only valid use of this is to create character and block
4060 * devices, and named pipes. This is deprecated (IMHO) and
4061 * a new info level should be used for mknod. JRA.
4064 if (dirfsp
== NULL
) {
4065 return NT_STATUS_INVALID_PARAMETER
;
4068 return smb_unix_mknod(conn
,
4076 /* Horrible backwards compatibility hack as an old server bug
4077 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
4081 size
= get_file_size_stat(&sbuf
);
4086 * Deal with the UNIX specific mode set.
4089 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
4092 if (fsp
== NULL
|| S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
4093 DBG_WARNING("Can't set mode on symlink %s\n",
4094 smb_fname_str_dbg(smb_fname
));
4095 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4098 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4099 "setting mode 0%o for file %s\n",
4100 (unsigned int)unixmode
,
4101 smb_fname_str_dbg(smb_fname
)));
4102 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
4104 return map_nt_error_from_unix(errno
);
4109 * Deal with the UNIX specific uid set.
4112 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
4113 (sbuf
.st_ex_uid
!= set_owner
)) {
4116 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4117 "changing owner %u for path %s\n",
4118 (unsigned int)set_owner
,
4119 smb_fname_str_dbg(smb_fname
)));
4122 !fsp
->fsp_flags
.is_pathref
&&
4123 fsp_get_io_fd(fsp
) != -1)
4125 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
4128 * UNIX extensions calls must always operate
4131 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
,
4132 set_owner
, (gid_t
)-1);
4136 status
= map_nt_error_from_unix(errno
);
4142 * Deal with the UNIX specific gid set.
4145 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
4146 (sbuf
.st_ex_gid
!= set_grp
)) {
4149 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4150 "changing group %u for file %s\n",
4151 (unsigned int)set_grp
,
4152 smb_fname_str_dbg(smb_fname
)));
4154 !fsp
->fsp_flags
.is_pathref
&&
4155 fsp_get_io_fd(fsp
) != -1)
4157 ret
= SMB_VFS_FCHOWN(fsp
, (uid_t
)-1, set_grp
);
4160 * UNIX extensions calls must always operate
4163 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
, (uid_t
)-1,
4167 status
= map_nt_error_from_unix(errno
);
4172 /* Deal with any size changes. */
4174 if (S_ISREG(sbuf
.st_ex_mode
)) {
4175 status
= smb_set_file_size(conn
, req
,
4181 if (!NT_STATUS_IS_OK(status
)) {
4186 /* Deal with any time changes. */
4187 if (is_omit_timespec(&ft
.mtime
) && is_omit_timespec(&ft
.atime
)) {
4188 /* No change, don't cancel anything. */
4192 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4193 for(all_fsps
= file_find_di_first(conn
->sconn
, id
, true); all_fsps
;
4194 all_fsps
= file_find_di_next(all_fsps
, true)) {
4196 * We're setting the time explicitly for UNIX.
4197 * Cancel any pending changes over all handles.
4199 all_fsps
->fsp_flags
.update_write_time_on_close
= false;
4200 TALLOC_FREE(all_fsps
->update_write_time_event
);
4204 * Override the "setting_write_time"
4205 * parameter here as it almost does what
4206 * we need. Just remember if we modified
4207 * mtime and send the notify ourselves.
4209 if (is_omit_timespec(&ft
.mtime
)) {
4210 modify_mtime
= false;
4213 status
= smb_set_file_time(conn
,
4219 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
4220 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
4225 /****************************************************************************
4226 Deal with SMB_SET_FILE_UNIX_INFO2.
4227 ****************************************************************************/
4229 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
4230 struct smb_request
*req
,
4233 struct files_struct
*dirfsp
,
4235 struct smb_filename
*smb_fname
)
4238 uint32_t smb_fflags
;
4241 if (!CAN_WRITE(conn
)) {
4242 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
4245 if (total_data
< 116) {
4246 return NT_STATUS_INVALID_PARAMETER
;
4249 /* Start by setting all the fields that are common between UNIX_BASIC
4252 status
= smb_set_file_unix_basic(conn
,
4259 if (!NT_STATUS_IS_OK(status
)) {
4263 smb_fflags
= IVAL(pdata
, 108);
4264 smb_fmask
= IVAL(pdata
, 112);
4266 /* NB: We should only attempt to alter the file flags if the client
4267 * sends a non-zero mask.
4269 if (smb_fmask
!= 0) {
4270 int stat_fflags
= 0;
4272 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
4273 smb_fmask
, &stat_fflags
)) {
4274 /* Client asked to alter a flag we don't understand. */
4275 return NT_STATUS_INVALID_PARAMETER
;
4278 if (fsp
== NULL
|| S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
4279 DBG_WARNING("Can't change flags on symlink %s\n",
4280 smb_fname_str_dbg(smb_fname
));
4281 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4283 if (SMB_VFS_FCHFLAGS(fsp
, stat_fflags
) != 0) {
4284 return map_nt_error_from_unix(errno
);
4288 /* XXX: need to add support for changing the create_time here. You
4289 * can do this for paths on Darwin with setattrlist(2). The right way
4290 * to hook this up is probably by extending the VFS utimes interface.
4293 return NT_STATUS_OK
;
4296 /****************************************************************************
4297 Deal with SMB_SET_POSIX_ACL.
4298 ****************************************************************************/
4300 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
4301 struct smb_request
*req
,
4305 struct smb_filename
*smb_fname
)
4307 #if !defined(HAVE_POSIX_ACLS)
4308 return NT_STATUS_INVALID_LEVEL
;
4310 uint16_t posix_acl_version
;
4311 uint16_t num_file_acls
;
4312 uint16_t num_def_acls
;
4313 bool valid_file_acls
= true;
4314 bool valid_def_acls
= true;
4316 unsigned int size_needed
;
4317 unsigned int total_data
;
4318 bool close_fsp
= false;
4320 if (total_data_in
< 0) {
4321 status
= NT_STATUS_INVALID_PARAMETER
;
4325 total_data
= total_data_in
;
4327 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
4328 status
= NT_STATUS_INVALID_PARAMETER
;
4331 posix_acl_version
= SVAL(pdata
,0);
4332 num_file_acls
= SVAL(pdata
,2);
4333 num_def_acls
= SVAL(pdata
,4);
4335 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
4336 valid_file_acls
= false;
4340 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
4341 valid_def_acls
= false;
4345 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
4346 status
= NT_STATUS_INVALID_PARAMETER
;
4351 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
4352 status
= NT_STATUS_INVALID_PARAMETER
;
4356 size_needed
= num_file_acls
+ num_def_acls
;
4359 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4360 * than UINT_MAX, so check by division.
4362 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
4363 status
= NT_STATUS_INVALID_PARAMETER
;
4367 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
4368 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
4369 status
= NT_STATUS_INVALID_PARAMETER
;
4372 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
4374 if (total_data
< size_needed
) {
4375 status
= NT_STATUS_INVALID_PARAMETER
;
4380 * Ensure we always operate on a file descriptor, not just
4383 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
4384 uint32_t access_mask
= SEC_STD_WRITE_OWNER
|
4386 SEC_STD_READ_CONTROL
|
4387 FILE_READ_ATTRIBUTES
|
4388 FILE_WRITE_ATTRIBUTES
;
4390 status
= get_posix_fsp(conn
,
4396 if (!NT_STATUS_IS_OK(status
)) {
4402 /* Here we know fsp != NULL */
4403 SMB_ASSERT(fsp
!= NULL
);
4405 status
= refuse_symlink_fsp(fsp
);
4406 if (!NT_STATUS_IS_OK(status
)) {
4410 /* If we have a default acl, this *must* be a directory. */
4411 if (valid_def_acls
&& !fsp
->fsp_flags
.is_directory
) {
4412 DBG_INFO("Can't set default acls on "
4413 "non-directory %s\n",
4415 return NT_STATUS_INVALID_HANDLE
;
4418 DBG_DEBUG("file %s num_file_acls = %"PRIu16
", "
4419 "num_def_acls = %"PRIu16
"\n",
4424 /* Move pdata to the start of the file ACL entries. */
4425 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
4427 if (valid_file_acls
) {
4428 status
= set_unix_posix_acl(conn
,
4432 if (!NT_STATUS_IS_OK(status
)) {
4437 /* Move pdata to the start of the default ACL entries. */
4438 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
4440 if (valid_def_acls
) {
4441 status
= set_unix_posix_default_acl(conn
,
4445 if (!NT_STATUS_IS_OK(status
)) {
4450 status
= NT_STATUS_OK
;
4455 (void)close_file_free(req
, &fsp
, NORMAL_CLOSE
);
4461 static void call_trans2setpathinfo(
4462 connection_struct
*conn
,
4463 struct smb_request
*req
,
4468 unsigned int max_data_bytes
)
4470 uint16_t info_level
;
4471 struct smb_filename
*smb_fname
= NULL
;
4472 struct files_struct
*dirfsp
= NULL
;
4473 struct files_struct
*fsp
= NULL
;
4474 char *params
= *pparams
;
4475 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4478 bool info_level_handled
;
4479 int data_return_size
= 0;
4482 if (params
== NULL
) {
4483 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4488 if (total_params
< 7) {
4489 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4493 info_level
= SVAL(params
,0);
4495 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4496 if (!lp_smb1_unix_extensions()) {
4497 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4500 if (!req
->posix_pathnames
) {
4501 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4506 if (req
->posix_pathnames
) {
4507 srvstr_get_path_posix(req
,
4516 srvstr_get_path(req
,
4525 if (!NT_STATUS_IS_OK(status
)) {
4526 reply_nterror(req
, status
);
4530 DBG_NOTICE("fname=%s info_level=%d totdata=%d\n",
4535 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4536 extract_snapshot_token(fname
, &twrp
);
4538 status
= smb1_strip_dfs_path(req
, &ucf_flags
, &fname
);
4539 if (!NT_STATUS_IS_OK(status
)) {
4540 reply_nterror(req
, status
);
4543 status
= filename_convert_dirfsp(req
,
4550 if (!NT_STATUS_IS_OK(status
)) {
4551 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
4552 reply_botherror(req
,
4553 NT_STATUS_PATH_NOT_COVERED
,
4554 ERRSRV
, ERRbadpath
);
4557 reply_nterror(req
, status
);
4561 info_level_handled
= true; /* Untouched in switch cases below */
4563 switch (info_level
) {
4566 info_level_handled
= false;
4569 case SMB_POSIX_PATH_OPEN
:
4570 status
= smb_posix_open(conn
,
4579 case SMB_POSIX_PATH_UNLINK
:
4580 status
= smb_posix_unlink(conn
,
4588 case SMB_SET_FILE_UNIX_LINK
:
4589 status
= smb_set_file_unix_link(
4590 conn
, req
, *ppdata
, total_data
, smb_fname
);
4593 case SMB_SET_FILE_UNIX_HLINK
:
4594 status
= smb_set_file_unix_hlink(
4595 conn
, req
, *ppdata
, total_data
, smb_fname
);
4598 case SMB_SET_FILE_UNIX_BASIC
:
4599 status
= smb_set_file_unix_basic(conn
,
4608 case SMB_SET_FILE_UNIX_INFO2
:
4609 status
= smb_set_file_unix_info2(conn
,
4617 case SMB_SET_POSIX_ACL
:
4618 status
= smb_set_posix_acl(
4619 conn
, req
, *ppdata
, total_data
, NULL
, smb_fname
);
4623 if (info_level_handled
) {
4624 handle_trans2setfilepathinfo_result(
4636 * smb_fname->fsp may be NULL if smb_fname points at a symlink
4637 * and we're in POSIX context, so be careful when using fsp
4638 * below, it can still be NULL.
4640 fsp
= smb_fname
->fsp
;
4642 status
= smbd_do_setfilepathinfo(
4653 handle_trans2setfilepathinfo_result(
4663 static void call_trans2setfileinfo(
4664 connection_struct
*conn
,
4665 struct smb_request
*req
,
4670 unsigned int max_data_bytes
)
4672 char *pdata
= *ppdata
;
4673 uint16_t info_level
;
4674 struct smb_filename
*smb_fname
= NULL
;
4675 struct files_struct
*fsp
= NULL
;
4676 char *params
= *pparams
;
4677 int data_return_size
= 0;
4678 bool info_level_handled
;
4682 if (params
== NULL
) {
4683 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4686 if (total_params
< 4) {
4687 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4691 fsp
= file_fsp(req
, SVAL(params
,0));
4692 /* Basic check for non-null fsp. */
4693 if (!check_fsp_open(conn
, req
, fsp
)) {
4696 info_level
= SVAL(params
,2);
4698 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4699 if (!lp_smb1_unix_extensions()) {
4700 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4703 if (!req
->posix_pathnames
) {
4704 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4709 smb_fname
= fsp
->fsp_name
;
4711 DBG_NOTICE("fnum=%s fname=%s info_level=%d totdata=%d\n",
4717 if (fsp_get_pathref_fd(fsp
) == -1) {
4719 * This is actually a SETFILEINFO on a directory
4720 * handle (returned from an NT SMB). NT5.0 seems
4721 * to do this call. JRA.
4723 ret
= vfs_stat(conn
, smb_fname
);
4725 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
4726 smb_fname_str_dbg(smb_fname
),
4728 reply_nterror(req
, map_nt_error_from_unix(errno
));
4731 } else if (fsp
->print_file
) {
4733 * Doing a DELETE_ON_CLOSE should cancel a print job.
4735 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) &&
4738 fsp
->fsp_flags
.delete_on_close
= true;
4740 DBG_NOTICE("Cancelling print job (%s)\n",
4744 send_trans2_replies(
4754 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
4759 * Original code - this is an open file.
4761 status
= vfs_stat_fsp(fsp
);
4762 if (!NT_STATUS_IS_OK(status
)) {
4763 DBG_NOTICE("fstat of %s failed (%s)\n",
4766 reply_nterror(req
, status
);
4771 info_level_handled
= true; /* Untouched in switch cases below */
4773 switch (info_level
) {
4776 info_level_handled
= false;
4779 case SMB_SET_FILE_UNIX_BASIC
:
4780 status
= smb_set_file_unix_basic(conn
,
4789 case SMB_SET_FILE_UNIX_INFO2
:
4790 status
= smb_set_file_unix_info2(conn
,
4799 case SMB_SET_POSIX_LOCK
:
4800 status
= smb_set_posix_lock(
4801 conn
, req
, *ppdata
, total_data
, fsp
);
4805 if (info_level_handled
) {
4806 handle_trans2setfilepathinfo_result(
4817 status
= smbd_do_setfilepathinfo(
4828 handle_trans2setfilepathinfo_result(
4838 /****************************************************************************
4839 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4840 ****************************************************************************/
4842 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
4843 char **pparams
, int total_params
,
4844 char **ppdata
, int total_data
,
4845 unsigned int max_data_bytes
)
4847 struct files_struct
*dirfsp
= NULL
;
4848 struct files_struct
*fsp
= NULL
;
4849 struct smb_filename
*smb_dname
= NULL
;
4850 char *params
= *pparams
;
4851 char *pdata
= *ppdata
;
4852 char *directory
= NULL
;
4853 NTSTATUS status
= NT_STATUS_OK
;
4854 struct ea_list
*ea_list
= NULL
;
4855 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4857 TALLOC_CTX
*ctx
= talloc_tos();
4859 if (!CAN_WRITE(conn
)) {
4860 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4864 if (total_params
< 5) {
4865 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4869 if (req
->posix_pathnames
) {
4870 srvstr_get_path_posix(ctx
,
4879 srvstr_get_path(ctx
,
4888 if (!NT_STATUS_IS_OK(status
)) {
4889 reply_nterror(req
, status
);
4893 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
4895 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4896 extract_snapshot_token(directory
, &twrp
);
4898 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &directory
);
4899 if (!NT_STATUS_IS_OK(status
)) {
4900 reply_nterror(req
, status
);
4903 status
= filename_convert_dirfsp(ctx
,
4910 if (!NT_STATUS_IS_OK(status
)) {
4911 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
4912 reply_botherror(req
,
4913 NT_STATUS_PATH_NOT_COVERED
,
4914 ERRSRV
, ERRbadpath
);
4917 reply_nterror(req
, status
);
4922 * OS/2 workplace shell seems to send SET_EA requests of "null"
4923 * length (4 bytes containing IVAL 4).
4924 * They seem to have no effect. Bug #3212. JRA.
4927 if (total_data
&& (total_data
!= 4)) {
4928 /* Any data in this call is an EA list. */
4929 if (total_data
< 10) {
4930 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4934 if (IVAL(pdata
,0) > total_data
) {
4935 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4936 IVAL(pdata
,0), (unsigned int)total_data
));
4937 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4941 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
4944 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4948 if (!lp_ea_support(SNUM(conn
))) {
4949 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
4953 /* If total_data == 4 Windows doesn't care what values
4954 * are placed in that field, it just ignores them.
4955 * The System i QNTC IBM SMB client puts bad values here,
4956 * so ignore them. */
4958 status
= SMB_VFS_CREATE_FILE(
4961 dirfsp
, /* dirfsp */
4962 smb_dname
, /* fname */
4963 MAXIMUM_ALLOWED_ACCESS
, /* access_mask */
4964 FILE_SHARE_NONE
, /* share_access */
4965 FILE_CREATE
, /* create_disposition*/
4966 FILE_DIRECTORY_FILE
, /* create_options */
4967 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
4968 0, /* oplock_request */
4970 0, /* allocation_size */
4971 0, /* private_flags */
4976 NULL
, NULL
); /* create context */
4977 if (!NT_STATUS_IS_OK(status
)) {
4978 reply_nterror(req
, status
);
4982 /* Try and set any given EA. */
4984 status
= set_ea(conn
, fsp
, ea_list
);
4985 if (!NT_STATUS_IS_OK(status
)) {
4986 reply_nterror(req
, status
);
4991 /* Realloc the parameter and data sizes */
4992 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4993 if(*pparams
== NULL
) {
4994 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5001 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
5005 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
5007 TALLOC_FREE(smb_dname
);
5010 /****************************************************************************
5011 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
5012 We don't actually do this - we just send a null response.
5013 ****************************************************************************/
5015 static void call_trans2findnotifyfirst(connection_struct
*conn
,
5016 struct smb_request
*req
,
5017 char **pparams
, int total_params
,
5018 char **ppdata
, int total_data
,
5019 unsigned int max_data_bytes
)
5021 char *params
= *pparams
;
5022 uint16_t info_level
;
5024 if (total_params
< 6) {
5025 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5029 info_level
= SVAL(params
,4);
5030 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
5032 switch (info_level
) {
5037 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5041 /* Realloc the parameter and data sizes */
5042 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
5043 if (*pparams
== NULL
) {
5044 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5049 SSVAL(params
,0,fnf_handle
);
5050 SSVAL(params
,2,0); /* No changes */
5051 SSVAL(params
,4,0); /* No EA errors */
5058 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
5061 /****************************************************************************
5062 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
5063 changes). Currently this does nothing.
5064 ****************************************************************************/
5066 static void call_trans2findnotifynext(connection_struct
*conn
,
5067 struct smb_request
*req
,
5068 char **pparams
, int total_params
,
5069 char **ppdata
, int total_data
,
5070 unsigned int max_data_bytes
)
5072 char *params
= *pparams
;
5074 DEBUG(3,("call_trans2findnotifynext\n"));
5076 /* Realloc the parameter and data sizes */
5077 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
5078 if (*pparams
== NULL
) {
5079 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5084 SSVAL(params
,0,0); /* No changes */
5085 SSVAL(params
,2,0); /* No EA errors */
5087 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
5090 /****************************************************************************
5091 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5092 ****************************************************************************/
5094 static void call_trans2getdfsreferral(connection_struct
*conn
,
5095 struct smb_request
*req
,
5096 char **pparams
, int total_params
,
5097 char **ppdata
, int total_data
,
5098 unsigned int max_data_bytes
)
5100 char *params
= *pparams
;
5101 char *pathname
= NULL
;
5103 int max_referral_level
;
5104 NTSTATUS status
= NT_STATUS_OK
;
5105 TALLOC_CTX
*ctx
= talloc_tos();
5107 DEBUG(10,("call_trans2getdfsreferral\n"));
5109 if (!IS_IPC(conn
)) {
5110 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5114 if (total_params
< 3) {
5115 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5119 max_referral_level
= SVAL(params
,0);
5121 if(!lp_host_msdfs()) {
5122 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
5126 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
5127 total_params
- 2, STR_TERMINATE
);
5129 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
5132 reply_size
= setup_dfs_referral(
5133 conn
, pathname
, max_referral_level
, ppdata
, &status
);
5134 if (reply_size
< 0) {
5135 reply_nterror(req
, status
);
5139 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
5140 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
5141 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
5144 #define LMCAT_SPL 0x53
5145 #define LMFUNC_GETJOBID 0x60
5147 /****************************************************************************
5148 Reply to a TRANS2_IOCTL - used for OS/2 printing.
5149 ****************************************************************************/
5151 static void call_trans2ioctl(connection_struct
*conn
,
5152 struct smb_request
*req
,
5153 char **pparams
, int total_params
,
5154 char **ppdata
, int total_data
,
5155 unsigned int max_data_bytes
)
5157 const struct loadparm_substitution
*lp_sub
=
5158 loadparm_s3_global_substitution();
5159 char *pdata
= *ppdata
;
5160 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
5164 /* check for an invalid fid before proceeding */
5167 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5171 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
5172 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
5173 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
5174 if (*ppdata
== NULL
) {
5175 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5180 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5181 CAN ACCEPT THIS IN UNICODE. JRA. */
5184 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
5186 status
= srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
5187 lp_netbios_name(), 15,
5188 STR_ASCII
|STR_TERMINATE
, &len
); /* Our NetBIOS name */
5189 if (!NT_STATUS_IS_OK(status
)) {
5190 reply_nterror(req
, status
);
5193 status
= srvstr_push(pdata
, req
->flags2
, pdata
+18,
5194 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)), 13,
5195 STR_ASCII
|STR_TERMINATE
, &len
); /* Service name */
5196 if (!NT_STATUS_IS_OK(status
)) {
5197 reply_nterror(req
, status
);
5200 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
5205 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5206 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
5209 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
5210 struct trans_state
*state
)
5212 struct smbXsrv_connection
*xconn
= req
->xconn
;
5214 if (xconn
->protocol
>= PROTOCOL_NT1
) {
5215 req
->flags2
|= 0x40; /* IS_LONG_NAME */
5216 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
5219 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
5220 if (state
->call
!= TRANSACT2_QFSINFO
&&
5221 state
->call
!= TRANSACT2_SETFSINFO
) {
5222 DEBUG(0,("handle_trans2: encryption required "
5224 (unsigned int)state
->call
));
5225 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5230 /* Now we must call the relevant TRANS2 function */
5231 switch(state
->call
) {
5232 case TRANSACT2_OPEN
:
5234 START_PROFILE(Trans2_open
);
5235 call_trans2open(conn
, req
,
5236 &state
->param
, state
->total_param
,
5237 &state
->data
, state
->total_data
,
5238 state
->max_data_return
);
5239 END_PROFILE(Trans2_open
);
5243 case TRANSACT2_FINDFIRST
:
5245 START_PROFILE(Trans2_findfirst
);
5246 call_trans2findfirst(conn
, req
,
5247 &state
->param
, state
->total_param
,
5248 &state
->data
, state
->total_data
,
5249 state
->max_data_return
);
5250 END_PROFILE(Trans2_findfirst
);
5254 case TRANSACT2_FINDNEXT
:
5256 START_PROFILE(Trans2_findnext
);
5257 call_trans2findnext(conn
, req
,
5258 &state
->param
, state
->total_param
,
5259 &state
->data
, state
->total_data
,
5260 state
->max_data_return
);
5261 END_PROFILE(Trans2_findnext
);
5265 case TRANSACT2_QFSINFO
:
5267 START_PROFILE(Trans2_qfsinfo
);
5268 call_trans2qfsinfo(conn
, req
,
5269 &state
->param
, state
->total_param
,
5270 &state
->data
, state
->total_data
,
5271 state
->max_data_return
);
5272 END_PROFILE(Trans2_qfsinfo
);
5276 case TRANSACT2_SETFSINFO
:
5278 START_PROFILE(Trans2_setfsinfo
);
5279 call_trans2setfsinfo(conn
, req
,
5280 &state
->param
, state
->total_param
,
5281 &state
->data
, state
->total_data
,
5282 state
->max_data_return
);
5283 END_PROFILE(Trans2_setfsinfo
);
5287 case TRANSACT2_QPATHINFO
:
5289 START_PROFILE(Trans2_qpathinfo
);
5290 call_trans2qpathinfo(
5297 state
->max_data_return
);
5298 END_PROFILE(Trans2_qpathinfo
);
5302 case TRANSACT2_QFILEINFO
:
5304 START_PROFILE(Trans2_qfileinfo
);
5305 call_trans2qfileinfo(
5312 state
->max_data_return
);
5313 END_PROFILE(Trans2_qfileinfo
);
5317 case TRANSACT2_SETPATHINFO
:
5319 START_PROFILE(Trans2_setpathinfo
);
5320 call_trans2setpathinfo(
5327 state
->max_data_return
);
5328 END_PROFILE(Trans2_setpathinfo
);
5332 case TRANSACT2_SETFILEINFO
:
5334 START_PROFILE(Trans2_setfileinfo
);
5335 call_trans2setfileinfo(
5342 state
->max_data_return
);
5343 END_PROFILE(Trans2_setfileinfo
);
5347 case TRANSACT2_FINDNOTIFYFIRST
:
5349 START_PROFILE(Trans2_findnotifyfirst
);
5350 call_trans2findnotifyfirst(conn
, req
,
5351 &state
->param
, state
->total_param
,
5352 &state
->data
, state
->total_data
,
5353 state
->max_data_return
);
5354 END_PROFILE(Trans2_findnotifyfirst
);
5358 case TRANSACT2_FINDNOTIFYNEXT
:
5360 START_PROFILE(Trans2_findnotifynext
);
5361 call_trans2findnotifynext(conn
, req
,
5362 &state
->param
, state
->total_param
,
5363 &state
->data
, state
->total_data
,
5364 state
->max_data_return
);
5365 END_PROFILE(Trans2_findnotifynext
);
5369 case TRANSACT2_MKDIR
:
5371 START_PROFILE(Trans2_mkdir
);
5372 call_trans2mkdir(conn
, req
,
5373 &state
->param
, state
->total_param
,
5374 &state
->data
, state
->total_data
,
5375 state
->max_data_return
);
5376 END_PROFILE(Trans2_mkdir
);
5380 case TRANSACT2_GET_DFS_REFERRAL
:
5382 START_PROFILE(Trans2_get_dfs_referral
);
5383 call_trans2getdfsreferral(conn
, req
,
5384 &state
->param
, state
->total_param
,
5385 &state
->data
, state
->total_data
,
5386 state
->max_data_return
);
5387 END_PROFILE(Trans2_get_dfs_referral
);
5391 case TRANSACT2_IOCTL
:
5393 START_PROFILE(Trans2_ioctl
);
5394 call_trans2ioctl(conn
, req
,
5395 &state
->param
, state
->total_param
,
5396 &state
->data
, state
->total_data
,
5397 state
->max_data_return
);
5398 END_PROFILE(Trans2_ioctl
);
5403 /* Error in request */
5404 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
5405 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
5409 /****************************************************************************
5410 Reply to a SMBtrans2.
5411 ****************************************************************************/
5413 void reply_trans2(struct smb_request
*req
)
5415 connection_struct
*conn
= req
->conn
;
5420 unsigned int tran_call
;
5421 struct trans_state
*state
;
5424 START_PROFILE(SMBtrans2
);
5426 if (req
->wct
< 14) {
5427 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5428 END_PROFILE(SMBtrans2
);
5432 dsoff
= SVAL(req
->vwv
+12, 0);
5433 dscnt
= SVAL(req
->vwv
+11, 0);
5434 psoff
= SVAL(req
->vwv
+10, 0);
5435 pscnt
= SVAL(req
->vwv
+9, 0);
5436 tran_call
= SVAL(req
->vwv
+14, 0);
5438 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
5439 if (!NT_STATUS_IS_OK(result
)) {
5440 DEBUG(2, ("Got invalid trans2 request: %s\n",
5441 nt_errstr(result
)));
5442 reply_nterror(req
, result
);
5443 END_PROFILE(SMBtrans2
);
5448 switch (tran_call
) {
5449 /* List the allowed trans2 calls on IPC$ */
5450 case TRANSACT2_OPEN
:
5451 case TRANSACT2_GET_DFS_REFERRAL
:
5452 case TRANSACT2_QFILEINFO
:
5453 case TRANSACT2_QFSINFO
:
5454 case TRANSACT2_SETFSINFO
:
5457 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5458 END_PROFILE(SMBtrans2
);
5463 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
5464 DEBUG(0, ("talloc failed\n"));
5465 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5466 END_PROFILE(SMBtrans2
);
5470 state
->cmd
= SMBtrans2
;
5472 state
->mid
= req
->mid
;
5473 state
->vuid
= req
->vuid
;
5474 state
->setup_count
= SVAL(req
->vwv
+13, 0);
5475 state
->setup
= NULL
;
5476 state
->total_param
= SVAL(req
->vwv
+0, 0);
5477 state
->param
= NULL
;
5478 state
->total_data
= SVAL(req
->vwv
+1, 0);
5480 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
5481 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
5482 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
5483 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
5484 state
->one_way
= BITSETW(req
->vwv
+5, 1);
5486 state
->call
= tran_call
;
5488 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5489 is so as a sanity check */
5490 if (state
->setup_count
!= 1) {
5492 * Need to have rc=0 for ioctl to get job id for OS/2.
5493 * Network printing will fail if function is not successful.
5494 * Similar function in reply.c will be used if protocol
5495 * is LANMAN1.0 instead of LM1.2X002.
5496 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5497 * outbuf doesn't have to be set(only job id is used).
5499 if ( (state
->setup_count
== 4)
5500 && (tran_call
== TRANSACT2_IOCTL
)
5501 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
5502 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
5503 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5505 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
5506 DEBUG(2,("Transaction is %d\n",tran_call
));
5508 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5509 END_PROFILE(SMBtrans2
);
5514 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
5517 if (state
->total_data
) {
5519 if (smb_buffer_oob(state
->total_data
, 0, dscnt
)
5520 || smb_buffer_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
5524 /* Can't use talloc here, the core routines do realloc on the
5525 * params and data. */
5526 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
5527 if (state
->data
== NULL
) {
5528 DEBUG(0,("reply_trans2: data malloc fail for %u "
5529 "bytes !\n", (unsigned int)state
->total_data
));
5531 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5532 END_PROFILE(SMBtrans2
);
5536 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
5539 if (state
->total_param
) {
5541 if (smb_buffer_oob(state
->total_param
, 0, pscnt
)
5542 || smb_buffer_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
5546 /* Can't use talloc here, the core routines do realloc on the
5547 * params and data. */
5548 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
5549 if (state
->param
== NULL
) {
5550 DEBUG(0,("reply_trans: param malloc fail for %u "
5551 "bytes !\n", (unsigned int)state
->total_param
));
5552 SAFE_FREE(state
->data
);
5554 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5555 END_PROFILE(SMBtrans2
);
5559 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
5562 state
->received_data
= dscnt
;
5563 state
->received_param
= pscnt
;
5565 if ((state
->received_param
== state
->total_param
) &&
5566 (state
->received_data
== state
->total_data
)) {
5568 handle_trans2(conn
, req
, state
);
5570 SAFE_FREE(state
->data
);
5571 SAFE_FREE(state
->param
);
5573 END_PROFILE(SMBtrans2
);
5577 DLIST_ADD(conn
->pending_trans
, state
);
5579 /* We need to send an interim response then receive the rest
5580 of the parameter/data bytes */
5581 reply_smb1_outbuf(req
, 0, 0);
5582 show_msg((char *)req
->outbuf
);
5583 END_PROFILE(SMBtrans2
);
5588 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5589 SAFE_FREE(state
->data
);
5590 SAFE_FREE(state
->param
);
5592 END_PROFILE(SMBtrans2
);
5593 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5596 /****************************************************************************
5597 Reply to a SMBtranss2
5598 ****************************************************************************/
5600 void reply_transs2(struct smb_request
*req
)
5602 connection_struct
*conn
= req
->conn
;
5603 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
5604 struct trans_state
*state
;
5606 START_PROFILE(SMBtranss2
);
5608 show_msg((const char *)req
->inbuf
);
5610 /* Windows clients expect all replies to
5611 a transact secondary (SMBtranss2 0x33)
5612 to have a command code of transact
5613 (SMBtrans2 0x32). See bug #8989
5614 and also [MS-CIFS] section 2.2.4.47.2
5617 req
->cmd
= SMBtrans2
;
5620 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5621 END_PROFILE(SMBtranss2
);
5625 for (state
= conn
->pending_trans
; state
!= NULL
;
5626 state
= state
->next
) {
5627 if (state
->mid
== req
->mid
) {
5632 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
5633 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5634 END_PROFILE(SMBtranss2
);
5638 /* Revise state->total_param and state->total_data in case they have
5639 changed downwards */
5641 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
5642 state
->total_param
= SVAL(req
->vwv
+0, 0);
5643 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
5644 state
->total_data
= SVAL(req
->vwv
+1, 0);
5646 pcnt
= SVAL(req
->vwv
+2, 0);
5647 poff
= SVAL(req
->vwv
+3, 0);
5648 pdisp
= SVAL(req
->vwv
+4, 0);
5650 dcnt
= SVAL(req
->vwv
+5, 0);
5651 doff
= SVAL(req
->vwv
+6, 0);
5652 ddisp
= SVAL(req
->vwv
+7, 0);
5654 state
->received_param
+= pcnt
;
5655 state
->received_data
+= dcnt
;
5657 if ((state
->received_data
> state
->total_data
) ||
5658 (state
->received_param
> state
->total_param
))
5662 if (smb_buffer_oob(state
->total_param
, pdisp
, pcnt
)
5663 || smb_buffer_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
5666 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
5670 if (smb_buffer_oob(state
->total_data
, ddisp
, dcnt
)
5671 || smb_buffer_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
5674 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
5677 if ((state
->received_param
< state
->total_param
) ||
5678 (state
->received_data
< state
->total_data
)) {
5679 END_PROFILE(SMBtranss2
);
5683 handle_trans2(conn
, req
, state
);
5685 DLIST_REMOVE(conn
->pending_trans
, state
);
5686 SAFE_FREE(state
->data
);
5687 SAFE_FREE(state
->param
);
5690 END_PROFILE(SMBtranss2
);
5695 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5696 DLIST_REMOVE(conn
->pending_trans
, state
);
5697 SAFE_FREE(state
->data
);
5698 SAFE_FREE(state
->param
);
5700 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5701 END_PROFILE(SMBtranss2
);