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 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
726 inode
= smb_fname
->st
.st_ex_ino
;
727 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
728 close_file_free(req
, &fsp
, ERROR_CLOSE
);
729 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
733 /* Realloc the size of parameters and data we will return */
734 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
735 if(*pparams
== NULL
) {
736 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
741 SSVAL(params
,0,fsp
->fnum
);
742 SSVAL(params
,2,fattr
);
743 srv_put_dos_date2(params
,4, mtime
);
744 SIVAL(params
,8, (uint32_t)size
);
745 SSVAL(params
,12,deny_mode
);
746 SSVAL(params
,14,0); /* open_type - file or directory. */
747 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
749 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
750 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
753 SSVAL(params
,18,smb_action
);
756 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
758 SIVAL(params
,20,inode
);
759 SSVAL(params
,24,0); /* Padding. */
761 uint32_t ea_size
= estimate_ea_size(smb_fname
->fsp
);
762 SIVAL(params
, 26, ea_size
);
764 SIVAL(params
, 26, 0);
767 /* Send the required number of replies */
768 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 30, *ppdata
, 0, max_data_bytes
);
770 TALLOC_FREE(smb_fname
);
773 static NTSTATUS
get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
774 connection_struct
*conn
,
775 struct dptr_struct
*dirptr
,
777 const char *path_mask
,
780 bool requires_resume_key
,
788 struct ea_list
*name_list
)
791 const bool do_pad
= true;
793 if (info_level
>= 1 && info_level
<= 3) {
794 /* No alignment on earlier info levels. */
798 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
799 path_mask
, dirtype
, info_level
,
800 requires_resume_key
, dont_descend
, ask_sharemode
,
802 ppdata
, base_data
, end_data
,
805 last_entry_off
, name_list
, NULL
);
808 /****************************************************************************
809 Reply to a TRANS2_FINDFIRST.
810 ****************************************************************************/
812 static void call_trans2findfirst(connection_struct
*conn
,
813 struct smb_request
*req
,
814 char **pparams
, int total_params
,
815 char **ppdata
, int total_data
,
816 unsigned int max_data_bytes
)
818 /* We must be careful here that we don't return more than the
819 allowed number of data bytes. If this means returning fewer than
820 maxentries then so be it. We assume that the redirector has
821 enough room for the fixed number of parameter bytes it has
823 struct smb_filename
*smb_dname
= NULL
;
824 char *params
= *pparams
;
825 char *pdata
= *ppdata
;
829 uint16_t findfirst_flags
;
830 bool close_after_first
;
832 bool requires_resume_key
;
834 char *directory
= NULL
;
837 int last_entry_off
=0;
841 bool finished
= False
;
842 bool dont_descend
= False
;
843 bool out_of_space
= False
;
845 struct ea_list
*ea_list
= NULL
;
846 NTSTATUS ntstatus
= NT_STATUS_OK
;
848 struct smbXsrv_connection
*xconn
= req
->xconn
;
849 struct smbd_server_connection
*sconn
= req
->sconn
;
850 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
851 bool backup_priv
= false;
852 bool as_root
= false;
853 files_struct
*fsp
= NULL
;
854 struct files_struct
*dirfsp
= NULL
;
855 const struct loadparm_substitution
*lp_sub
=
856 loadparm_s3_global_substitution();
858 if (total_params
< 13) {
859 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
863 dirtype
= SVAL(params
,0);
864 maxentries
= SVAL(params
,2);
865 findfirst_flags
= SVAL(params
,4);
866 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
867 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
868 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
869 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
870 security_token_has_privilege(get_current_nttok(conn
),
873 info_level
= SVAL(params
,6);
875 DBG_NOTICE("dirtype = %"PRIx32
", maxentries = %d, "
876 "close_after_first=%d, close_if_end = %d "
877 "requires_resume_key = %d backup_priv = %d level = 0x%x, "
878 "max_data_bytes = %d\n",
889 /* W2K3 seems to treat zero as 1. */
893 switch (info_level
) {
894 case SMB_FIND_INFO_STANDARD
:
895 case SMB_FIND_EA_SIZE
:
896 case SMB_FIND_EA_LIST
:
897 case SMB_FIND_FILE_DIRECTORY_INFO
:
898 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
899 case SMB_FIND_FILE_NAMES_INFO
:
900 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
901 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
902 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
904 case SMB_FIND_FILE_UNIX
:
905 case SMB_FIND_FILE_UNIX_INFO2
:
906 if (!lp_smb1_unix_extensions()) {
907 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
910 if (!req
->posix_pathnames
) {
911 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
916 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
920 if (req
->posix_pathnames
) {
921 srvstr_get_path_posix(talloc_tos(),
930 srvstr_get_path(talloc_tos(),
939 if (!NT_STATUS_IS_OK(ntstatus
)) {
940 reply_nterror(req
, ntstatus
);
948 ntstatus
= smb1_strip_dfs_path(talloc_tos(), &ucf_flags
, &directory
);
949 if (!NT_STATUS_IS_OK(ntstatus
)) {
950 reply_nterror(req
, ntstatus
);
954 ntstatus
= filename_convert_smb1_search_path(talloc_tos(),
962 if (!NT_STATUS_IS_OK(ntstatus
)) {
963 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
964 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
968 reply_nterror(req
, ntstatus
);
972 TALLOC_FREE(directory
);
973 directory
= smb_dname
->base_name
;
975 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
977 if (info_level
== SMB_FIND_EA_LIST
) {
980 if (total_data
< 4) {
981 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
985 ea_size
= IVAL(pdata
,0);
986 if (ea_size
!= total_data
) {
987 DBG_NOTICE("Rejecting EA request with incorrect "
988 "total_data=%d (should be %" PRIu32
")\n",
991 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
995 if (!lp_ea_support(SNUM(conn
))) {
996 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1000 /* Pull out the list of names. */
1001 ea_list
= read_ea_name_list(talloc_tos(), pdata
+ 4, ea_size
- 4);
1003 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1008 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
1009 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1013 *ppdata
= (char *)SMB_REALLOC(
1014 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
1015 if(*ppdata
== NULL
) {
1016 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1020 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
1022 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
1025 memset(pdata
+ total_data
, 0, ((max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
) - total_data
));
1026 /* Realloc the params space */
1027 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
1028 if (*pparams
== NULL
) {
1029 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1035 * Open an fsp on this directory for the dptr.
1037 ntstatus
= SMB_VFS_CREATE_FILE(
1040 dirfsp
, /* dirfsp */
1041 smb_dname
, /* dname */
1042 FILE_LIST_DIRECTORY
, /* access_mask */
1044 FILE_SHARE_WRITE
, /* share_access */
1045 FILE_OPEN
, /* create_disposition*/
1046 FILE_DIRECTORY_FILE
, /* create_options */
1047 FILE_ATTRIBUTE_DIRECTORY
,/* file_attributes */
1048 NO_OPLOCK
, /* oplock_request */
1050 0, /* allocation_size */
1051 0, /* private_flags */
1056 NULL
, /* in_context */
1057 NULL
);/* out_context */
1059 if (!NT_STATUS_IS_OK(ntstatus
)) {
1060 DBG_ERR("failed to open directory %s\n",
1061 smb_fname_str_dbg(smb_dname
));
1062 reply_nterror(req
, ntstatus
);
1066 /* Save the wildcard match and attribs we are using on this directory -
1067 needed as lanman2 assumes these are being saved between calls */
1069 ntstatus
= dptr_create(conn
,
1077 if (!NT_STATUS_IS_OK(ntstatus
)) {
1079 * Use NULL here for the first parameter (req)
1080 * as this is not a client visible handle so
1081 * can't be part of an SMB1 chain.
1083 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1084 reply_nterror(req
, ntstatus
);
1089 /* Remember this in case we have
1090 to do a findnext. */
1091 dptr_set_priv(fsp
->dptr
);
1094 dptr_num
= dptr_dnum(fsp
->dptr
);
1095 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
1097 /* We don't need to check for VOL here as this is returned by
1098 a different TRANS2 call. */
1100 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1101 directory
,lp_dont_descend(talloc_tos(), lp_sub
, SNUM(conn
))));
1102 if (in_list(directory
,
1103 lp_dont_descend(talloc_tos(), lp_sub
, SNUM(conn
)),
1104 dptr_case_sensitive(fsp
->dptr
))) {
1105 dont_descend
= True
;
1109 space_remaining
= max_data_bytes
;
1110 out_of_space
= False
;
1112 ask_sharemode
= fsp_search_ask_sharemode(fsp
);
1114 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
1116 ntstatus
= get_lanman2_dir_entry(talloc_tos(),
1123 requires_resume_key
,
1132 if (NT_STATUS_EQUAL(ntstatus
, NT_STATUS_ILLEGAL_CHARACTER
)) {
1134 * Bad character conversion on name. Ignore
1139 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
1140 out_of_space
= true;
1142 finished
= !NT_STATUS_IS_OK(ntstatus
);
1145 if (!finished
&& !out_of_space
) {
1149 /* Ensure space_remaining never goes -ve. */
1150 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
1151 space_remaining
= 0;
1152 out_of_space
= true;
1154 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
1158 /* Check if we can close the dirptr */
1159 if(close_after_first
|| (finished
&& close_if_end
)) {
1160 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
1162 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1166 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1167 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1168 * the protocol level is less than NT1. Tested with smbclient. JRA.
1169 * This should fix the OS/2 client bug #2335.
1172 if(numentries
== 0) {
1175 * We may have already closed the file in the
1176 * close_after_first or finished case above.
1179 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1181 if (xconn
->protocol
< PROTOCOL_NT1
) {
1182 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
1185 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
1186 ERRDOS
, ERRbadfile
);
1191 /* At this point pdata points to numentries directory entries. */
1193 /* Set up the return parameter block */
1194 SSVAL(params
,0,dptr_num
);
1195 SSVAL(params
,2,numentries
);
1196 SSVAL(params
,4,finished
);
1197 SSVAL(params
,6,0); /* Never an EA error */
1198 SSVAL(params
,8,last_entry_off
);
1200 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
1203 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
1204 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
1206 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1210 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1211 smb_fn_name(req
->cmd
),
1212 mask
, directory
, dirtype
, numentries
) );
1215 * Force a name mangle here to ensure that the
1216 * mask as an 8.3 name is top of the mangled cache.
1217 * The reasons for this are subtle. Don't remove
1218 * this code unless you know what you are doing
1219 * (see PR#13758). JRA.
1222 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
1223 char mangled_name
[13];
1224 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
1232 TALLOC_FREE(smb_dname
);
1236 static bool smbd_dptr_name_equal(struct dptr_struct
*dptr
,
1242 if (dptr_case_sensitive(dptr
)) {
1243 equal
= (strcmp(name1
, name2
) == 0);
1245 equal
= strequal(name1
, name2
);
1251 /****************************************************************************
1252 Reply to a TRANS2_FINDNEXT.
1253 ****************************************************************************/
1255 static void call_trans2findnext(connection_struct
*conn
,
1256 struct smb_request
*req
,
1257 char **pparams
, int total_params
,
1258 char **ppdata
, int total_data
,
1259 unsigned int max_data_bytes
)
1261 /* We must be careful here that we don't return more than the
1262 allowed number of data bytes. If this means returning fewer than
1263 maxentries then so be it. We assume that the redirector has
1264 enough room for the fixed number of parameter bytes it has
1266 char *params
= *pparams
;
1267 char *pdata
= *ppdata
;
1271 uint16_t info_level
;
1272 uint32_t resume_key
;
1273 uint16_t findnext_flags
;
1274 bool close_after_request
;
1276 bool requires_resume_key
;
1278 char *resume_name
= NULL
;
1279 const char *mask
= NULL
;
1280 const char *directory
= NULL
;
1284 int i
, last_entry_off
=0;
1285 bool finished
= False
;
1286 bool dont_descend
= False
;
1287 bool out_of_space
= False
;
1288 int space_remaining
;
1289 struct ea_list
*ea_list
= NULL
;
1290 NTSTATUS ntstatus
= NT_STATUS_OK
;
1292 TALLOC_CTX
*ctx
= talloc_tos();
1293 struct smbd_server_connection
*sconn
= req
->sconn
;
1294 bool backup_priv
= false;
1295 bool as_root
= false;
1296 files_struct
*fsp
= NULL
;
1297 const struct loadparm_substitution
*lp_sub
=
1298 loadparm_s3_global_substitution();
1300 if (total_params
< 13) {
1301 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1305 dptr_num
= SVAL(params
,0);
1306 maxentries
= SVAL(params
,2);
1307 info_level
= SVAL(params
,4);
1308 resume_key
= IVAL(params
,6);
1309 findnext_flags
= SVAL(params
,10);
1310 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
1311 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
1312 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
1313 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
1315 if (!continue_bit
) {
1316 /* We only need resume_name if continue_bit is zero. */
1317 if (req
->posix_pathnames
) {
1318 srvstr_get_path_posix(ctx
,
1327 srvstr_get_path(ctx
,
1336 if (!NT_STATUS_IS_OK(ntstatus
)) {
1337 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1338 complain (it thinks we're asking for the directory above the shared
1339 path or an invalid name). Catch this as the resume name is only compared, never used in
1340 a file access. JRA. */
1341 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
1342 &resume_name
, params
+12,
1346 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
1347 reply_nterror(req
, ntstatus
);
1353 DBG_NOTICE("dirhandle = %d, max_data_bytes = %u, maxentries = %d, "
1354 "close_after_request=%d, close_if_end = %d "
1355 "requires_resume_key = %d resume_key = %d "
1356 "resume name = %s continue=%d level = %d\n",
1360 close_after_request
,
1362 requires_resume_key
,
1364 resume_name
? resume_name
: "(NULL)",
1369 /* W2K3 seems to treat zero as 1. */
1373 switch (info_level
) {
1374 case SMB_FIND_INFO_STANDARD
:
1375 case SMB_FIND_EA_SIZE
:
1376 case SMB_FIND_EA_LIST
:
1377 case SMB_FIND_FILE_DIRECTORY_INFO
:
1378 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1379 case SMB_FIND_FILE_NAMES_INFO
:
1380 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1381 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1382 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1384 case SMB_FIND_FILE_UNIX
:
1385 case SMB_FIND_FILE_UNIX_INFO2
:
1386 if (!lp_smb1_unix_extensions()) {
1387 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1390 if (!req
->posix_pathnames
) {
1391 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1396 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1400 if (info_level
== SMB_FIND_EA_LIST
) {
1403 if (total_data
< 4) {
1404 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1408 ea_size
= IVAL(pdata
,0);
1409 if (ea_size
!= total_data
) {
1410 DBG_NOTICE("Rejecting EA request with incorrect "
1411 "total_data=%d (should be %" PRIu32
")\n",
1414 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1418 if (!lp_ea_support(SNUM(conn
))) {
1419 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1423 /* Pull out the list of names. */
1424 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
1426 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1431 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
1432 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1436 *ppdata
= (char *)SMB_REALLOC(
1437 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
1438 if(*ppdata
== NULL
) {
1439 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1444 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
1447 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
1450 memset(pdata
+ total_data
, 0, (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
) - total_data
);
1451 /* Realloc the params space */
1452 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
1453 if(*pparams
== NULL
) {
1454 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1460 /* Check that the dptr is valid */
1461 fsp
= dptr_fetch_lanman2_fsp(sconn
, dptr_num
);
1463 reply_nterror(req
, STATUS_NO_MORE_FILES
);
1467 directory
= dptr_path(sconn
, dptr_num
);
1469 /* Get the wildcard mask from the dptr */
1470 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
1471 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
1472 reply_nterror(req
, STATUS_NO_MORE_FILES
);
1476 /* Get the attr mask from the dptr */
1477 dirtype
= dptr_attr(sconn
, dptr_num
);
1479 backup_priv
= dptr_get_priv(fsp
->dptr
);
1481 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX) "
1482 "backup_priv = %d\n",
1483 dptr_num
, mask
, dirtype
,
1487 /* We don't need to check for VOL here as this is returned by
1488 a different TRANS2 call. */
1490 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1491 directory
,lp_dont_descend(ctx
, lp_sub
, SNUM(conn
))));
1492 if (in_list(directory
,lp_dont_descend(ctx
, lp_sub
, SNUM(conn
)),
1493 dptr_case_sensitive(fsp
->dptr
)))
1494 dont_descend
= True
;
1497 space_remaining
= max_data_bytes
;
1498 out_of_space
= False
;
1506 * Seek to the correct position. We no longer use the resume key but
1507 * depend on the last file name instead.
1510 if(!continue_bit
&& resume_name
&& *resume_name
) {
1511 bool posix_open
= (fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
);
1512 char *last_name_sent
= NULL
;
1516 * Remember, name_to_8_3 is called by
1517 * get_lanman2_dir_entry(), so the resume name
1518 * could be mangled. Ensure we check the unmangled name.
1522 mangle_is_mangled(resume_name
, conn
->params
)) {
1523 char *new_resume_name
= NULL
;
1524 mangle_lookup_name_from_8_3(ctx
,
1528 if (new_resume_name
) {
1529 resume_name
= new_resume_name
;
1534 * Fix for NT redirector problem triggered by resume key indexes
1535 * changing between directory scans. We now return a resume key of 0
1536 * and instead look for the filename to continue from (also given
1537 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1538 * findfirst/findnext (as is usual) then the directory pointer
1539 * should already be at the correct place.
1542 last_name_sent
= smbd_dirptr_get_last_name_sent(fsp
->dptr
);
1543 sequential
= smbd_dptr_name_equal(fsp
->dptr
,
1550 dptr_RewindDir(fsp
->dptr
);
1552 while ((name
= dptr_ReadDirName(talloc_tos(),
1553 fsp
->dptr
)) != NULL
) {
1554 found
= smbd_dptr_name_equal(fsp
->dptr
,
1565 * We got a name that used to exist
1566 * but does not anymore. Just start
1567 * from the beginning. Shown by the
1568 * "raw.search.os2 delete" smbtorture
1571 dptr_RewindDir(fsp
->dptr
);
1574 } /* end if resume_name && !continue_bit */
1576 ask_sharemode
= fsp_search_ask_sharemode(fsp
);
1578 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
1580 ntstatus
= get_lanman2_dir_entry(ctx
,
1587 requires_resume_key
,
1596 if (NT_STATUS_EQUAL(ntstatus
, NT_STATUS_ILLEGAL_CHARACTER
)) {
1598 * Bad character conversion on name. Ignore
1603 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
1604 out_of_space
= true;
1606 finished
= !NT_STATUS_IS_OK(ntstatus
);
1609 if (!finished
&& !out_of_space
) {
1613 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
1616 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1617 smb_fn_name(req
->cmd
),
1618 mask
, directory
, dirtype
, numentries
) );
1620 /* Check if we can close the fsp->dptr */
1621 if(close_after_request
|| (finished
&& close_if_end
)) {
1622 DBG_INFO("closing dptr_num = %d\n", dptr_num
);
1624 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1631 /* Set up the return parameter block */
1632 SSVAL(params
,0,numentries
);
1633 SSVAL(params
,2,finished
);
1634 SSVAL(params
,4,0); /* Never an EA error */
1635 SSVAL(params
,6,last_entry_off
);
1637 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
1643 /****************************************************************************
1644 Reply to a TRANS2_QFSINFO (query filesystem info).
1645 ****************************************************************************/
1647 static void call_trans2qfsinfo(connection_struct
*conn
,
1648 struct smb_request
*req
,
1649 char **pparams
, int total_params
,
1650 char **ppdata
, int total_data
,
1651 unsigned int max_data_bytes
)
1653 char *params
= *pparams
;
1654 uint16_t info_level
;
1656 size_t fixed_portion
;
1659 if (total_params
< 2) {
1660 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1664 info_level
= SVAL(params
,0);
1666 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
1667 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
1668 DEBUG(0,("call_trans2qfsinfo: encryption required "
1669 "and info level 0x%x sent.\n",
1670 (unsigned int)info_level
));
1671 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1676 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
1678 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
,
1977 static void handle_trans2qfilepathinfo_result(
1978 connection_struct
*conn
,
1979 struct smb_request
*req
,
1980 uint16_t info_level
,
1983 int data_return_size
,
1984 size_t fixed_portion
,
1985 unsigned int max_data_bytes
)
1987 char params
[2] = { 0, 0, };
1991 * draft-leach-cifs-v1-spec-02.txt
1992 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
1995 * The requested information is placed in the Data portion of the
1996 * transaction response. For the information levels greater than 0x100,
1997 * the transaction response has 1 parameter word which should be
1998 * ignored by the client.
2000 * However Windows only follows this rule for the IS_NAME_VALID call.
2002 switch (info_level
) {
2003 case SMB_INFO_IS_NAME_VALID
:
2008 if (!NT_STATUS_IS_OK(status
)) {
2009 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2010 /* We have re-scheduled this call. */
2013 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2014 bool ok
= defer_smb1_sharing_violation(req
);
2019 reply_nterror(req
, status
);
2023 if (fixed_portion
> max_data_bytes
) {
2024 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
2028 send_trans2_replies(
2039 /****************************************************************************
2040 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2041 file name or file id).
2042 ****************************************************************************/
2044 static void call_trans2qfilepathinfo(connection_struct
*conn
,
2045 struct smb_request
*req
,
2046 unsigned int tran_call
,
2047 uint16_t info_level
,
2048 struct smb_filename
*smb_fname
,
2049 struct files_struct
*fsp
,
2050 bool delete_pending
,
2051 struct timespec write_time_ts
,
2052 char **pparams
, int total_params
,
2053 char **ppdata
, int total_data
,
2054 unsigned int max_data_bytes
)
2056 char *params
= *pparams
;
2057 char *pdata
= *ppdata
;
2058 unsigned int data_size
= 0;
2059 struct ea_list
*ea_list
= NULL
;
2060 size_t fixed_portion
;
2061 NTSTATUS status
= NT_STATUS_OK
;
2063 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
2064 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
2066 info_level
,tran_call
,total_data
));
2068 /* Pull out any data sent here before we realloc. */
2069 switch (info_level
) {
2070 case SMB_INFO_QUERY_EAS_FROM_LIST
:
2072 /* Pull any EA list from the data portion. */
2075 if (total_data
< 4) {
2077 req
, NT_STATUS_INVALID_PARAMETER
);
2080 ea_size
= IVAL(pdata
,0);
2082 if (total_data
> 0 && ea_size
!= total_data
) {
2083 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2084 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2086 req
, NT_STATUS_INVALID_PARAMETER
);
2090 if (!lp_ea_support(SNUM(conn
))) {
2091 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2095 /* Pull out the list of names. */
2096 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
2099 req
, NT_STATUS_INVALID_PARAMETER
);
2109 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
2110 if (*pparams
== NULL
) {
2111 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2117 if ((info_level
& SMB2_INFO_SPECIAL
) == SMB2_INFO_SPECIAL
) {
2119 * We use levels that start with 0xFF00
2120 * internally to represent SMB2 specific levels
2122 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2126 status
= smbd_do_qfilepathinfo(conn
, req
, req
, info_level
,
2128 delete_pending
, write_time_ts
,
2130 req
->flags2
, max_data_bytes
,
2132 ppdata
, &data_size
);
2134 handle_trans2qfilepathinfo_result(
2145 static NTSTATUS
smb_q_unix_basic(
2146 struct connection_struct
*conn
,
2147 struct smb_request
*req
,
2148 struct smb_filename
*smb_fname
,
2149 struct files_struct
*fsp
,
2153 const int total_data
= 100;
2155 *ppdata
= SMB_REALLOC(*ppdata
, total_data
);
2156 if (*ppdata
== NULL
) {
2157 return NT_STATUS_NO_MEMORY
;
2159 store_file_unix_basic(conn
, *ppdata
, fsp
, &smb_fname
->st
);
2161 *ptotal_data
= total_data
;
2163 return NT_STATUS_OK
;
2166 static NTSTATUS
smb_q_unix_info2(
2167 struct connection_struct
*conn
,
2168 struct smb_request
*req
,
2169 struct smb_filename
*smb_fname
,
2170 struct files_struct
*fsp
,
2174 const int total_data
= 116;
2176 *ppdata
= SMB_REALLOC(*ppdata
, total_data
);
2177 if (*ppdata
== NULL
) {
2178 return NT_STATUS_NO_MEMORY
;
2180 store_file_unix_basic_info2(conn
, *ppdata
, fsp
, &smb_fname
->st
);
2182 *ptotal_data
= total_data
;
2184 return NT_STATUS_OK
;
2187 #if defined(HAVE_POSIX_ACLS)
2188 /****************************************************************************
2189 Utility function to open a fsp for a POSIX handle operation.
2190 ****************************************************************************/
2192 static NTSTATUS
get_posix_fsp(connection_struct
*conn
,
2193 struct smb_request
*req
,
2194 struct smb_filename
*smb_fname
,
2195 uint32_t access_mask
,
2196 files_struct
**ret_fsp
)
2199 uint32_t create_disposition
= FILE_OPEN
;
2200 uint32_t share_access
= FILE_SHARE_READ
|
2203 struct smb2_create_blobs
*posx
= NULL
;
2206 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
2207 * but set reasonable defaults.
2209 uint32_t file_attributes
= 0664;
2210 uint32_t oplock
= NO_OPLOCK
;
2211 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
2213 /* File or directory must exist. */
2214 if (!VALID_STAT(smb_fname
->st
)) {
2215 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
2217 /* Cannot be a symlink. */
2218 if (S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
2219 return NT_STATUS_ACCESS_DENIED
;
2221 /* Set options correctly for directory open. */
2222 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
2224 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
2225 * directories, but set reasonable defaults.
2227 file_attributes
= 0775;
2228 create_options
= FILE_DIRECTORY_FILE
;
2231 status
= make_smb2_posix_create_ctx(
2232 talloc_tos(), &posx
, file_attributes
);
2233 if (!NT_STATUS_IS_OK(status
)) {
2234 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
2239 status
= SMB_VFS_CREATE_FILE(
2243 smb_fname
, /* fname */
2244 access_mask
, /* access_mask */
2245 share_access
, /* share_access */
2246 create_disposition
,/* create_disposition*/
2247 create_options
, /* create_options */
2248 file_attributes
,/* file_attributes */
2249 oplock
, /* oplock_request */
2251 0, /* allocation_size */
2252 0, /* private_flags */
2255 ret_fsp
, /* result */
2257 posx
, /* in_context */
2258 NULL
); /* out_context */
2265 /****************************************************************************
2266 Utility function to count the number of entries in a POSIX acl.
2267 ****************************************************************************/
2269 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
2271 unsigned int ace_count
= 0;
2272 int entry_id
= SMB_ACL_FIRST_ENTRY
;
2273 SMB_ACL_ENTRY_T entry
;
2275 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
2276 entry_id
= SMB_ACL_NEXT_ENTRY
;
2282 /****************************************************************************
2283 Utility function to marshall a POSIX acl into wire format.
2284 ****************************************************************************/
2286 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
2288 int entry_id
= SMB_ACL_FIRST_ENTRY
;
2289 SMB_ACL_ENTRY_T entry
;
2291 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
2292 SMB_ACL_TAG_T tagtype
;
2293 SMB_ACL_PERMSET_T permset
;
2294 unsigned char perms
= 0;
2295 unsigned int own_grp
;
2297 entry_id
= SMB_ACL_NEXT_ENTRY
;
2299 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
2300 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2304 if (sys_acl_get_permset(entry
, &permset
) == -1) {
2305 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2309 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
2310 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
2311 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
2313 SCVAL(pdata
,1,perms
);
2316 case SMB_ACL_USER_OBJ
:
2317 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
2318 own_grp
= (unsigned int)pst
->st_ex_uid
;
2319 SIVAL(pdata
,2,own_grp
);
2324 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
2326 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2329 own_grp
= (unsigned int)*puid
;
2330 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
2331 SIVAL(pdata
,2,own_grp
);
2335 case SMB_ACL_GROUP_OBJ
:
2336 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
2337 own_grp
= (unsigned int)pst
->st_ex_gid
;
2338 SIVAL(pdata
,2,own_grp
);
2343 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
2345 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2348 own_grp
= (unsigned int)*pgid
;
2349 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
2350 SIVAL(pdata
,2,own_grp
);
2355 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
2356 SIVAL(pdata
,2,0xFFFFFFFF);
2357 SIVAL(pdata
,6,0xFFFFFFFF);
2360 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
2361 SIVAL(pdata
,2,0xFFFFFFFF);
2362 SIVAL(pdata
,6,0xFFFFFFFF);
2365 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2368 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
2375 static NTSTATUS
smb_q_posix_acl(
2376 struct connection_struct
*conn
,
2377 struct smb_request
*req
,
2378 struct smb_filename
*smb_fname
,
2379 struct files_struct
*fsp
,
2383 #if !defined(HAVE_POSIX_ACLS)
2384 return NT_STATUS_INVALID_LEVEL
;
2387 SMB_ACL_T file_acl
= NULL
;
2388 SMB_ACL_T def_acl
= NULL
;
2389 uint16_t num_file_acls
= 0;
2390 uint16_t num_def_acls
= 0;
2391 unsigned int size_needed
= 0;
2394 bool close_fsp
= false;
2397 * Ensure we always operate on a file descriptor, not just
2400 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
2401 uint32_t access_mask
= SEC_STD_READ_CONTROL
|
2402 FILE_READ_ATTRIBUTES
|
2403 FILE_WRITE_ATTRIBUTES
;
2405 status
= get_posix_fsp(conn
,
2411 if (!NT_STATUS_IS_OK(status
)) {
2417 SMB_ASSERT(fsp
!= NULL
);
2419 status
= refuse_symlink_fsp(fsp
);
2420 if (!NT_STATUS_IS_OK(status
)) {
2424 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
, SMB_ACL_TYPE_ACCESS
,
2427 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
2428 DBG_INFO("ACLs not implemented on "
2429 "filesystem containing %s\n",
2431 status
= NT_STATUS_NOT_IMPLEMENTED
;
2435 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2437 * We can only have default POSIX ACLs on
2440 if (!fsp
->fsp_flags
.is_directory
) {
2441 DBG_INFO("Non-directory open %s\n",
2443 status
= NT_STATUS_INVALID_HANDLE
;
2446 def_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
2447 SMB_ACL_TYPE_DEFAULT
,
2449 def_acl
= free_empty_sys_acl(conn
, def_acl
);
2452 num_file_acls
= count_acl_entries(conn
, file_acl
);
2453 num_def_acls
= count_acl_entries(conn
, def_acl
);
2456 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
2457 status
= NT_STATUS_INVALID_PARAMETER
;
2461 size_needed
= num_file_acls
+ num_def_acls
;
2464 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
2465 * than UINT_MAX, so check by division.
2467 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
2468 status
= NT_STATUS_INVALID_PARAMETER
;
2472 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
2473 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
2474 status
= NT_STATUS_INVALID_PARAMETER
;
2477 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
2479 *ppdata
= SMB_REALLOC(*ppdata
, size_needed
);
2480 if (*ppdata
== NULL
) {
2481 status
= NT_STATUS_NO_MEMORY
;
2486 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
2487 SSVAL(pdata
,2,num_file_acls
);
2488 SSVAL(pdata
,4,num_def_acls
);
2489 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
2491 ok
= marshall_posix_acl(conn
,
2496 status
= NT_STATUS_INTERNAL_ERROR
;
2499 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
2501 ok
= marshall_posix_acl(conn
,
2506 status
= NT_STATUS_INTERNAL_ERROR
;
2510 *ptotal_data
= size_needed
;
2511 status
= NT_STATUS_OK
;
2517 * Ensure the stat struct in smb_fname is up to
2518 * date. Structure copy.
2520 smb_fname
->st
= fsp
->fsp_name
->st
;
2521 (void)close_file_free(req
, &fsp
, NORMAL_CLOSE
);
2524 TALLOC_FREE(file_acl
);
2525 TALLOC_FREE(def_acl
);
2530 static NTSTATUS
smb_q_posix_symlink(
2531 struct connection_struct
*conn
,
2532 struct smb_request
*req
,
2533 struct smb_filename
*smb_fname
,
2537 char buffer
[PATH_MAX
+1];
2541 struct smb_filename
*parent_fname
= NULL
;
2542 struct smb_filename
*base_name
= NULL
;
2545 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
2546 smb_fname_str_dbg(smb_fname
));
2548 if (!S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
2549 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
2552 status
= parent_pathref(
2559 if (!NT_STATUS_IS_OK(status
)) {
2560 DBG_DEBUG("parent_pathref failed: %s\n", nt_errstr(status
));
2564 link_len
= SMB_VFS_READLINKAT(
2570 TALLOC_FREE(parent_fname
);
2572 if (link_len
== -1) {
2573 status
= map_nt_error_from_unix(errno
);
2574 DBG_DEBUG("READLINKAT failed: %s\n", nt_errstr(status
));
2577 if (link_len
>= sizeof(buffer
)) {
2578 return NT_STATUS_INTERNAL_ERROR
;
2580 buffer
[link_len
] = 0;
2582 needed
= (link_len
+1)*2;
2584 *ppdata
= SMB_REALLOC(*ppdata
, needed
);
2585 if (*ppdata
== NULL
) {
2586 return NT_STATUS_NO_MEMORY
;
2590 status
= srvstr_push(
2598 if (!NT_STATUS_IS_OK(status
)) {
2603 return NT_STATUS_OK
;
2606 static void call_trans2qpathinfo(
2607 connection_struct
*conn
,
2608 struct smb_request
*req
,
2613 unsigned int max_data_bytes
)
2615 char *params
= *pparams
;
2616 uint16_t info_level
;
2617 struct smb_filename
*smb_fname
= NULL
;
2618 bool delete_pending
= False
;
2619 struct timespec write_time_ts
= { .tv_sec
= 0, };
2620 struct files_struct
*dirfsp
= NULL
;
2621 files_struct
*fsp
= NULL
;
2622 struct file_id fileid
;
2625 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
2627 bool info_level_handled
;
2628 NTSTATUS status
= NT_STATUS_OK
;
2632 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2638 if (total_params
< 7) {
2639 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2643 info_level
= SVAL(params
,0);
2645 DBG_NOTICE("TRANSACT2_QPATHINFO: level = %d\n", info_level
);
2647 if (INFO_LEVEL_IS_UNIX(info_level
)) {
2648 if (!lp_smb1_unix_extensions()) {
2649 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2652 if (!req
->posix_pathnames
) {
2653 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2658 if (req
->posix_pathnames
) {
2659 srvstr_get_path_posix(req
,
2668 srvstr_get_path(req
,
2677 if (!NT_STATUS_IS_OK(status
)) {
2678 reply_nterror(req
, status
);
2682 if (ucf_flags
& UCF_GMT_PATHNAME
) {
2683 extract_snapshot_token(fname
, &twrp
);
2685 status
= smb1_strip_dfs_path(req
, &ucf_flags
, &fname
);
2686 if (!NT_STATUS_IS_OK(status
)) {
2687 reply_nterror(req
, status
);
2690 status
= filename_convert_dirfsp(req
,
2697 if (!NT_STATUS_IS_OK(status
)) {
2698 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2699 reply_botherror(req
,
2700 NT_STATUS_PATH_NOT_COVERED
,
2701 ERRSRV
, ERRbadpath
);
2704 reply_nterror(req
, status
);
2709 * qpathinfo must operate on an existing file, so we
2710 * can exit early if filename_convert_dirfsp() returned the
2711 * "new file" NT_STATUS_OK, !VALID_STAT case.
2714 if (!VALID_STAT(smb_fname
->st
)) {
2715 reply_nterror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2720 * smb_fname->fsp may be NULL if smb_fname points at a symlink
2721 * and we're in POSIX context, so be careful when using fsp
2722 * below, it can still be NULL.
2724 fsp
= smb_fname
->fsp
;
2726 /* If this is a stream, check if there is a delete_pending. */
2727 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
2728 && is_ntfs_stream_smb_fname(smb_fname
)) {
2729 struct smb_filename
*smb_fname_base
;
2731 /* Create an smb_filename with stream_name == NULL. */
2732 smb_fname_base
= synthetic_smb_fname(
2734 smb_fname
->base_name
,
2739 if (smb_fname_base
== NULL
) {
2740 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2744 ret
= vfs_stat(conn
, smb_fname_base
);
2746 DBG_NOTICE("vfs_stat of %s failed "
2748 smb_fname_str_dbg(smb_fname_base
),
2750 TALLOC_FREE(smb_fname_base
);
2752 map_nt_error_from_unix(errno
));
2756 status
= file_name_hash(conn
,
2757 smb_fname_str_dbg(smb_fname_base
),
2759 if (!NT_STATUS_IS_OK(status
)) {
2760 TALLOC_FREE(smb_fname_base
);
2761 reply_nterror(req
, status
);
2765 fileid
= vfs_file_id_from_sbuf(conn
,
2766 &smb_fname_base
->st
);
2767 TALLOC_FREE(smb_fname_base
);
2768 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
2769 if (delete_pending
) {
2770 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
2775 status
= file_name_hash(conn
,
2776 smb_fname_str_dbg(smb_fname
),
2778 if (!NT_STATUS_IS_OK(status
)) {
2779 reply_nterror(req
, status
);
2783 if (fsp_getinfo_ask_sharemode(fsp
)) {
2784 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
2785 get_file_infos(fileid
, name_hash
, &delete_pending
,
2789 if (delete_pending
) {
2790 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
2794 info_level_handled
= true; /* Untouched in switch cases below */
2796 switch (info_level
) {
2799 info_level_handled
= false;
2802 case SMB_QUERY_FILE_UNIX_BASIC
:
2803 status
= smb_q_unix_basic(
2812 case SMB_QUERY_FILE_UNIX_INFO2
:
2813 status
= smb_q_unix_info2(
2822 case SMB_QUERY_POSIX_ACL
:
2823 status
= smb_q_posix_acl(
2832 case SMB_QUERY_FILE_UNIX_LINK
:
2833 status
= smb_q_posix_symlink(
2842 if (info_level_handled
) {
2843 handle_trans2qfilepathinfo_result(
2855 call_trans2qfilepathinfo(
2858 TRANSACT2_QPATHINFO
,
2871 static NTSTATUS
smb_q_posix_lock(
2872 struct connection_struct
*conn
,
2873 struct smb_request
*req
,
2874 struct files_struct
*fsp
,
2878 char *pdata
= *ppdata
;
2879 int total_data
= *ptotal_data
;
2883 enum brl_type lock_type
;
2886 if (fsp
->fsp_flags
.is_pathref
|| (fsp_get_io_fd(fsp
) == -1)) {
2887 return NT_STATUS_INVALID_HANDLE
;
2890 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
2891 return NT_STATUS_INVALID_PARAMETER
;
2894 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
2895 case POSIX_LOCK_TYPE_READ
:
2896 lock_type
= READ_LOCK
;
2898 case POSIX_LOCK_TYPE_WRITE
:
2899 lock_type
= WRITE_LOCK
;
2901 case POSIX_LOCK_TYPE_UNLOCK
:
2903 /* There's no point in asking for an unlock... */
2904 return NT_STATUS_INVALID_PARAMETER
;
2907 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
2908 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
2909 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
2911 status
= query_lock(
2919 if (NT_STATUS_IS_OK(status
)) {
2921 * For success we just return a copy of what we sent
2922 * with the lock type set to POSIX_LOCK_TYPE_UNLOCK.
2924 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
2925 return NT_STATUS_OK
;
2928 if (!ERROR_WAS_LOCK_DENIED(status
)) {
2929 DBG_DEBUG("query_lock() failed: %s\n", nt_errstr(status
));
2934 * Here we need to report who has it locked.
2937 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
2938 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
2939 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
2940 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
2941 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
2943 return NT_STATUS_OK
;
2946 static void call_trans2qfileinfo(
2947 connection_struct
*conn
,
2948 struct smb_request
*req
,
2953 unsigned int max_data_bytes
)
2955 char *params
= *pparams
;
2956 uint16_t info_level
;
2957 struct smb_filename
*smb_fname
= NULL
;
2958 bool delete_pending
= False
;
2959 struct timespec write_time_ts
= { .tv_sec
= 0, };
2960 files_struct
*fsp
= NULL
;
2961 struct file_id fileid
;
2962 bool info_level_handled
;
2963 NTSTATUS status
= NT_STATUS_OK
;
2966 if (params
== NULL
) {
2967 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2971 if (total_params
< 4) {
2972 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2976 fsp
= file_fsp(req
, SVAL(params
,0));
2977 info_level
= SVAL(params
,2);
2980 call_trans2qpipeinfo(
2985 TRANSACT2_QFILEINFO
,
2994 DBG_NOTICE("TRANSACT2_QFILEINFO: level = %d\n", info_level
);
2996 if (INFO_LEVEL_IS_UNIX(info_level
)) {
2997 if (!lp_smb1_unix_extensions()) {
2998 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3001 if (!req
->posix_pathnames
) {
3002 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3007 /* Initial check for valid fsp ptr. */
3008 if (!check_fsp_open(conn
, req
, fsp
)) {
3012 smb_fname
= fsp
->fsp_name
;
3014 if(fsp
->fake_file_handle
) {
3016 * This is actually for the QUOTA_FAKE_FILE --metze
3019 /* We know this name is ok, it's already passed the checks. */
3021 } else if(fsp_get_pathref_fd(fsp
) == -1) {
3023 * This is actually a QFILEINFO on a directory
3024 * handle (returned from an NT SMB). NT5.0 seems
3025 * to do this call. JRA.
3027 ret
= vfs_stat(conn
, smb_fname
);
3029 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
3030 smb_fname_str_dbg(smb_fname
),
3033 map_nt_error_from_unix(errno
));
3037 if (fsp_getinfo_ask_sharemode(fsp
)) {
3038 fileid
= vfs_file_id_from_sbuf(
3039 conn
, &smb_fname
->st
);
3040 get_file_infos(fileid
, fsp
->name_hash
,
3046 * Original code - this is an open file.
3048 status
= vfs_stat_fsp(fsp
);
3049 if (!NT_STATUS_IS_OK(status
)) {
3050 DEBUG(3, ("fstat of %s failed (%s)\n",
3051 fsp_fnum_dbg(fsp
), nt_errstr(status
)));
3052 reply_nterror(req
, status
);
3055 if (fsp_getinfo_ask_sharemode(fsp
)) {
3056 fileid
= vfs_file_id_from_sbuf(
3057 conn
, &smb_fname
->st
);
3058 get_file_infos(fileid
, fsp
->name_hash
,
3064 info_level_handled
= true; /* Untouched in switch cases below */
3066 switch (info_level
) {
3069 info_level_handled
= false;
3072 case SMB_QUERY_POSIX_LOCK
:
3073 status
= smb_q_posix_lock(conn
, req
, fsp
, ppdata
, &total_data
);
3076 case SMB_QUERY_FILE_UNIX_BASIC
:
3077 status
= smb_q_unix_basic(
3078 conn
, req
, fsp
->fsp_name
, fsp
, ppdata
, &total_data
);
3081 case SMB_QUERY_FILE_UNIX_INFO2
:
3082 status
= smb_q_unix_info2(
3083 conn
, req
, fsp
->fsp_name
, fsp
, ppdata
, &total_data
);
3086 case SMB_QUERY_POSIX_ACL
:
3087 status
= smb_q_posix_acl(
3088 conn
, req
, fsp
->fsp_name
, fsp
, ppdata
, &total_data
);
3092 if (info_level_handled
) {
3093 handle_trans2qfilepathinfo_result(
3105 call_trans2qfilepathinfo(
3108 TRANSACT2_QFILEINFO
,
3121 static void handle_trans2setfilepathinfo_result(
3122 connection_struct
*conn
,
3123 struct smb_request
*req
,
3124 uint16_t info_level
,
3127 int data_return_size
,
3128 unsigned int max_data_bytes
)
3130 char params
[2] = { 0, 0, };
3132 if (NT_STATUS_IS_OK(status
)) {
3133 send_trans2_replies(
3145 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3146 /* We have re-scheduled this call. */
3150 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
3151 bool ok
= defer_smb1_sharing_violation(req
);
3157 if (NT_STATUS_EQUAL(status
, NT_STATUS_EVENT_PENDING
)) {
3158 /* We have re-scheduled this call. */
3162 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3165 NT_STATUS_PATH_NOT_COVERED
,
3171 if (info_level
== SMB_POSIX_PATH_OPEN
) {
3172 reply_openerror(req
, status
);
3176 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
3178 * Invalid EA name needs to return 2 param bytes,
3179 * not a zero-length error packet.
3182 send_trans2_replies(
3194 reply_nterror(req
, status
);
3197 /****************************************************************************
3198 Create a directory with POSIX semantics.
3199 ****************************************************************************/
3201 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
3202 struct smb_request
*req
,
3205 struct smb_filename
*smb_fname
,
3206 int *pdata_return_size
)
3208 NTSTATUS status
= NT_STATUS_OK
;
3209 uint32_t raw_unixmode
= 0;
3210 mode_t unixmode
= (mode_t
)0;
3211 files_struct
*fsp
= NULL
;
3212 uint16_t info_level_return
= 0;
3214 char *pdata
= *ppdata
;
3215 struct smb2_create_blobs
*posx
= NULL
;
3217 if (total_data
< 18) {
3218 return NT_STATUS_INVALID_PARAMETER
;
3221 raw_unixmode
= IVAL(pdata
,8);
3222 /* Next 4 bytes are not yet defined. */
3224 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
3225 PERM_NEW_DIR
, &unixmode
);
3226 if (!NT_STATUS_IS_OK(status
)) {
3230 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, unixmode
);
3231 if (!NT_STATUS_IS_OK(status
)) {
3232 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3237 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
3238 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
3240 status
= SMB_VFS_CREATE_FILE(
3244 smb_fname
, /* fname */
3245 FILE_READ_ATTRIBUTES
, /* access_mask */
3246 FILE_SHARE_NONE
, /* share_access */
3247 FILE_CREATE
, /* create_disposition*/
3248 FILE_DIRECTORY_FILE
, /* create_options */
3249 0, /* file_attributes */
3250 0, /* oplock_request */
3252 0, /* allocation_size */
3253 0, /* private_flags */
3258 posx
, /* in_context_blobs */
3259 NULL
); /* out_context_blobs */
3263 if (NT_STATUS_IS_OK(status
)) {
3264 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3267 info_level_return
= SVAL(pdata
,16);
3269 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
3270 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
3271 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
3272 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
3274 *pdata_return_size
= 12;
3277 /* Realloc the data size */
3278 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
3279 if (*ppdata
== NULL
) {
3280 *pdata_return_size
= 0;
3281 return NT_STATUS_NO_MEMORY
;
3285 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
3286 SSVAL(pdata
,2,0); /* No fnum. */
3287 SIVAL(pdata
,4,info
); /* Was directory created. */
3289 switch (info_level_return
) {
3290 case SMB_QUERY_FILE_UNIX_BASIC
:
3291 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
3292 SSVAL(pdata
,10,0); /* Padding. */
3293 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
3296 case SMB_QUERY_FILE_UNIX_INFO2
:
3297 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
3298 SSVAL(pdata
,10,0); /* Padding. */
3299 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
3303 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
3304 SSVAL(pdata
,10,0); /* Padding. */
3311 /****************************************************************************
3312 Open/Create a file with POSIX semantics.
3313 ****************************************************************************/
3315 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
3316 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
3318 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
3319 struct smb_request
*req
,
3322 struct files_struct
*dirfsp
,
3323 struct smb_filename
*smb_fname
,
3324 int *pdata_return_size
)
3326 bool extended_oplock_granted
= False
;
3327 char *pdata
= *ppdata
;
3329 uint32_t wire_open_mode
= 0;
3330 uint32_t raw_unixmode
= 0;
3331 uint32_t attributes
= 0;
3332 uint32_t create_disp
= 0;
3333 uint32_t access_mask
= 0;
3334 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
3335 NTSTATUS status
= NT_STATUS_OK
;
3336 mode_t unixmode
= (mode_t
)0;
3337 files_struct
*fsp
= NULL
;
3338 int oplock_request
= 0;
3340 uint16_t info_level_return
= 0;
3341 struct smb2_create_blobs
*posx
= NULL
;
3343 if (total_data
< 18) {
3344 return NT_STATUS_INVALID_PARAMETER
;
3347 flags
= IVAL(pdata
,0);
3348 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
3349 if (oplock_request
) {
3350 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
3353 wire_open_mode
= IVAL(pdata
,4);
3355 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
3356 return smb_posix_mkdir(conn
, req
,
3363 switch (wire_open_mode
& SMB_ACCMODE
) {
3365 access_mask
= SMB_O_RDONLY_MAPPING
;
3368 access_mask
= SMB_O_WRONLY_MAPPING
;
3371 access_mask
= (SMB_O_RDONLY_MAPPING
|
3372 SMB_O_WRONLY_MAPPING
);
3375 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
3376 (unsigned int)wire_open_mode
));
3377 return NT_STATUS_INVALID_PARAMETER
;
3380 wire_open_mode
&= ~SMB_ACCMODE
;
3382 /* First take care of O_CREAT|O_EXCL interactions. */
3383 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
3384 case (SMB_O_CREAT
| SMB_O_EXCL
):
3385 /* File exists fail. File not exist create. */
3386 create_disp
= FILE_CREATE
;
3389 /* File exists open. File not exist create. */
3390 create_disp
= FILE_OPEN_IF
;
3393 /* O_EXCL on its own without O_CREAT is undefined.
3394 We deliberately ignore it as some versions of
3395 Linux CIFSFS can send a bare O_EXCL on the
3396 wire which other filesystems in the kernel
3397 ignore. See bug 9519 for details. */
3402 /* File exists open. File not exist fail. */
3403 create_disp
= FILE_OPEN
;
3406 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
3407 (unsigned int)wire_open_mode
));
3408 return NT_STATUS_INVALID_PARAMETER
;
3411 /* Next factor in the effects of O_TRUNC. */
3412 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
3414 if (wire_open_mode
& SMB_O_TRUNC
) {
3415 switch (create_disp
) {
3417 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
3418 /* Leave create_disp alone as
3419 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
3421 /* File exists fail. File not exist create. */
3424 /* SMB_O_CREAT | SMB_O_TRUNC */
3425 /* File exists overwrite. File not exist create. */
3426 create_disp
= FILE_OVERWRITE_IF
;
3430 /* File exists overwrite. File not exist fail. */
3431 create_disp
= FILE_OVERWRITE
;
3434 /* Cannot get here. */
3435 smb_panic("smb_posix_open: logic error");
3436 return NT_STATUS_INVALID_PARAMETER
;
3440 raw_unixmode
= IVAL(pdata
,8);
3441 /* Next 4 bytes are not yet defined. */
3443 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
3444 (VALID_STAT(smb_fname
->st
) ?
3445 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
3448 if (!NT_STATUS_IS_OK(status
)) {
3452 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, unixmode
);
3453 if (!NT_STATUS_IS_OK(status
)) {
3454 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3459 if (wire_open_mode
& SMB_O_SYNC
) {
3460 create_options
|= FILE_WRITE_THROUGH
;
3462 if (wire_open_mode
& SMB_O_APPEND
) {
3463 access_mask
|= FILE_APPEND_DATA
;
3465 if (wire_open_mode
& SMB_O_DIRECT
) {
3466 attributes
|= FILE_FLAG_NO_BUFFERING
;
3469 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
3470 VALID_STAT_OF_DIR(smb_fname
->st
)) {
3471 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
3472 return NT_STATUS_FILE_IS_A_DIRECTORY
;
3474 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
3475 create_options
|= FILE_DIRECTORY_FILE
;
3478 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
3479 smb_fname_str_dbg(smb_fname
),
3480 (unsigned int)wire_open_mode
,
3481 (unsigned int)unixmode
));
3483 status
= SMB_VFS_CREATE_FILE(
3486 dirfsp
, /* dirfsp */
3487 smb_fname
, /* fname */
3488 access_mask
, /* access_mask */
3489 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
3491 create_disp
, /* create_disposition*/
3492 create_options
, /* create_options */
3493 attributes
, /* file_attributes */
3494 oplock_request
, /* oplock_request */
3496 0, /* allocation_size */
3497 0, /* private_flags */
3502 posx
, /* in_context_blobs */
3503 NULL
); /* out_context_blobs */
3507 if (!NT_STATUS_IS_OK(status
)) {
3511 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
3512 extended_oplock_granted
= True
;
3515 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
3516 extended_oplock_granted
= True
;
3519 info_level_return
= SVAL(pdata
,16);
3521 /* Allocate the correct return size. */
3523 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
3524 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
3525 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
3526 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
3528 *pdata_return_size
= 12;
3531 /* Realloc the data size */
3532 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
3533 if (*ppdata
== NULL
) {
3534 close_file_free(req
, &fsp
, ERROR_CLOSE
);
3535 *pdata_return_size
= 0;
3536 return NT_STATUS_NO_MEMORY
;
3540 if (extended_oplock_granted
) {
3541 if (flags
& REQUEST_BATCH_OPLOCK
) {
3542 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
3544 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
3546 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
3547 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
3549 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
3552 SSVAL(pdata
,2,fsp
->fnum
);
3553 SIVAL(pdata
,4,info
); /* Was file created etc. */
3555 switch (info_level_return
) {
3556 case SMB_QUERY_FILE_UNIX_BASIC
:
3557 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
3558 SSVAL(pdata
,10,0); /* padding. */
3559 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
3562 case SMB_QUERY_FILE_UNIX_INFO2
:
3563 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
3564 SSVAL(pdata
,10,0); /* padding. */
3565 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
3569 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
3570 SSVAL(pdata
,10,0); /* padding. */
3573 return NT_STATUS_OK
;
3576 /****************************************************************************
3577 Delete a file with POSIX semantics.
3578 ****************************************************************************/
3580 struct smb_posix_unlink_state
{
3581 struct smb_filename
*smb_fname
;
3582 struct files_struct
*fsp
;
3586 static void smb_posix_unlink_locked(struct share_mode_lock
*lck
,
3589 struct smb_posix_unlink_state
*state
= private_data
;
3591 bool other_nonposix_opens
;
3593 other_nonposix_opens
= has_other_nonposix_opens(lck
, state
->fsp
);
3594 if (other_nonposix_opens
) {
3595 /* Fail with sharing violation. */
3596 state
->status
= NT_STATUS_SHARING_VIOLATION
;
3601 * Set the delete on close.
3603 state
->status
= smb_set_file_disposition_info(state
->fsp
->conn
,
3610 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
3611 struct smb_request
*req
,
3614 struct files_struct
*dirfsp
,
3615 struct smb_filename
*smb_fname
)
3617 struct smb_posix_unlink_state state
= {};
3618 NTSTATUS status
= NT_STATUS_OK
;
3619 files_struct
*fsp
= NULL
;
3622 int create_options
= 0;
3623 struct smb2_create_blobs
*posx
= NULL
;
3625 if (!CAN_WRITE(conn
)) {
3626 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
3629 if (total_data
< 2) {
3630 return NT_STATUS_INVALID_PARAMETER
;
3633 flags
= SVAL(pdata
,0);
3635 if (!VALID_STAT(smb_fname
->st
)) {
3636 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3639 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
3640 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
3641 return NT_STATUS_NOT_A_DIRECTORY
;
3644 DEBUG(10,("smb_posix_unlink: %s %s\n",
3645 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
3646 smb_fname_str_dbg(smb_fname
)));
3648 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
3649 create_options
|= FILE_DIRECTORY_FILE
;
3652 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, 0777);
3653 if (!NT_STATUS_IS_OK(status
)) {
3654 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3659 status
= SMB_VFS_CREATE_FILE(
3662 dirfsp
, /* dirfsp */
3663 smb_fname
, /* fname */
3664 DELETE_ACCESS
, /* access_mask */
3665 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
3667 FILE_OPEN
, /* create_disposition*/
3668 create_options
, /* create_options */
3669 0, /* file_attributes */
3670 0, /* oplock_request */
3672 0, /* allocation_size */
3673 0, /* private_flags */
3678 posx
, /* in_context_blobs */
3679 NULL
); /* out_context_blobs */
3683 if (!NT_STATUS_IS_OK(status
)) {
3688 * Don't lie to client. If we can't really delete due to
3689 * non-POSIX opens return SHARING_VIOLATION.
3692 state
= (struct smb_posix_unlink_state
) {
3693 .smb_fname
= smb_fname
,
3697 status
= share_mode_do_locked_vfs_allowed(fsp
->file_id
,
3698 smb_posix_unlink_locked
,
3700 if (!NT_STATUS_IS_OK(status
)) {
3701 DBG_ERR("share_mode_do_locked_vfs_allowed(%s) failed - %s\n",
3702 fsp_str_dbg(fsp
), nt_errstr(status
));
3703 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3704 return NT_STATUS_INVALID_PARAMETER
;
3707 status
= state
.status
;
3708 if (!NT_STATUS_IS_OK(status
)) {
3709 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3712 return close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3715 /****************************************************************************
3716 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
3717 ****************************************************************************/
3719 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
3720 struct smb_request
*req
,
3723 struct smb_filename
*new_smb_fname
)
3725 char *link_target
= NULL
;
3726 struct smb_filename target_fname
;
3727 TALLOC_CTX
*ctx
= talloc_tos();
3730 struct smb_filename
*parent_fname
= NULL
;
3731 struct smb_filename
*base_name
= NULL
;
3733 if (!CAN_WRITE(conn
)) {
3734 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
3737 /* Set a symbolic link. */
3738 /* Don't allow this if follow links is false. */
3740 if (total_data
== 0) {
3741 return NT_STATUS_INVALID_PARAMETER
;
3744 if (!lp_follow_symlinks(SNUM(conn
))) {
3745 return NT_STATUS_ACCESS_DENIED
;
3748 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
3749 total_data
, STR_TERMINATE
);
3752 return NT_STATUS_INVALID_PARAMETER
;
3755 target_fname
= (struct smb_filename
) {
3756 .base_name
= link_target
,
3759 /* Removes @GMT tokens if any */
3760 status
= canonicalize_snapshot_path(&target_fname
, UCF_GMT_PATHNAME
, 0);
3761 if (!NT_STATUS_IS_OK(status
)) {
3765 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3766 new_smb_fname
->base_name
, link_target
));
3768 status
= parent_pathref(talloc_tos(),
3773 if (!NT_STATUS_IS_OK(status
)) {
3777 ret
= SMB_VFS_SYMLINKAT(conn
,
3782 TALLOC_FREE(parent_fname
);
3783 return map_nt_error_from_unix(errno
);
3786 TALLOC_FREE(parent_fname
);
3787 return NT_STATUS_OK
;
3790 /****************************************************************************
3791 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
3792 ****************************************************************************/
3794 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
3795 struct smb_request
*req
,
3796 const char *pdata
, int total_data
,
3797 struct smb_filename
*smb_fname_new
)
3799 char *oldname
= NULL
;
3800 struct files_struct
*src_dirfsp
= NULL
;
3801 struct smb_filename
*smb_fname_old
= NULL
;
3802 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
3803 NTTIME old_twrp
= 0;
3804 TALLOC_CTX
*ctx
= talloc_tos();
3805 NTSTATUS status
= NT_STATUS_OK
;
3807 if (!CAN_WRITE(conn
)) {
3808 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
3811 /* Set a hard link. */
3812 if (total_data
== 0) {
3813 return NT_STATUS_INVALID_PARAMETER
;
3816 if (req
->posix_pathnames
) {
3817 srvstr_get_path_posix(ctx
,
3826 srvstr_get_path(ctx
,
3835 if (!NT_STATUS_IS_OK(status
)) {
3839 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3840 smb_fname_str_dbg(smb_fname_new
), oldname
));
3842 if (ucf_flags
& UCF_GMT_PATHNAME
) {
3843 extract_snapshot_token(oldname
, &old_twrp
);
3845 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &oldname
);
3846 if (!NT_STATUS_IS_OK(status
)) {
3849 status
= filename_convert_dirfsp(ctx
,
3856 if (!NT_STATUS_IS_OK(status
)) {
3860 return hardlink_internals(ctx
,
3866 NULL
, /* new_dirfsp */
3870 /****************************************************************************
3871 Allow a UNIX info mknod.
3872 ****************************************************************************/
3874 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
3877 struct files_struct
*dirfsp
,
3878 const struct smb_filename
*smb_fname
)
3880 uint32_t file_type
= IVAL(pdata
,56);
3881 #if defined(HAVE_MAKEDEV)
3882 uint32_t dev_major
= IVAL(pdata
,60);
3883 uint32_t dev_minor
= IVAL(pdata
,68);
3885 SMB_DEV_T dev
= (SMB_DEV_T
)0;
3886 uint32_t raw_unixmode
= IVAL(pdata
,84);
3890 struct smb_filename
*parent_fname
= NULL
;
3891 struct smb_filename
*atname
= NULL
;
3893 if (total_data
< 100) {
3894 return NT_STATUS_INVALID_PARAMETER
;
3897 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
3898 PERM_NEW_FILE
, &unixmode
);
3899 if (!NT_STATUS_IS_OK(status
)) {
3903 #if defined(HAVE_MAKEDEV)
3904 dev
= makedev(dev_major
, dev_minor
);
3907 switch (file_type
) {
3908 /* We can't create other objects here. */
3909 case UNIX_TYPE_FILE
:
3911 case UNIX_TYPE_SYMLINK
:
3912 return NT_STATUS_ACCESS_DENIED
;
3913 #if defined(S_IFIFO)
3914 case UNIX_TYPE_FIFO
:
3915 unixmode
|= S_IFIFO
;
3918 #if defined(S_IFSOCK)
3919 case UNIX_TYPE_SOCKET
:
3920 unixmode
|= S_IFSOCK
;
3923 #if defined(S_IFCHR)
3924 case UNIX_TYPE_CHARDEV
:
3925 /* This is only allowed for root. */
3926 if (get_current_uid(conn
) != sec_initial_uid()) {
3927 return NT_STATUS_ACCESS_DENIED
;
3929 unixmode
|= S_IFCHR
;
3932 #if defined(S_IFBLK)
3933 case UNIX_TYPE_BLKDEV
:
3934 if (get_current_uid(conn
) != sec_initial_uid()) {
3935 return NT_STATUS_ACCESS_DENIED
;
3937 unixmode
|= S_IFBLK
;
3941 return NT_STATUS_INVALID_PARAMETER
;
3944 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
3945 "%.0f mode 0%o for file %s\n", (double)dev
,
3946 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
3948 status
= SMB_VFS_PARENT_PATHNAME(dirfsp
->conn
,
3953 if (!NT_STATUS_IS_OK(status
)) {
3957 /* Ok - do the mknod. */
3958 ret
= SMB_VFS_MKNODAT(conn
,
3965 TALLOC_FREE(parent_fname
);
3966 return map_nt_error_from_unix(errno
);
3969 /* If any of the other "set" calls fail we
3970 * don't want to end up with a half-constructed mknod.
3973 if (lp_inherit_permissions(SNUM(conn
))) {
3974 inherit_access_posix_acl(conn
,
3979 TALLOC_FREE(parent_fname
);
3981 return NT_STATUS_OK
;
3984 /****************************************************************************
3985 Deal with SMB_SET_FILE_UNIX_BASIC.
3986 ****************************************************************************/
3988 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
3989 struct smb_request
*req
,
3992 struct files_struct
*dirfsp
,
3994 struct smb_filename
*smb_fname
)
3996 struct smb_file_time ft
;
3997 uint32_t raw_unixmode
;
4000 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
4001 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
4002 NTSTATUS status
= NT_STATUS_OK
;
4003 enum perm_type ptype
;
4004 files_struct
*all_fsps
= NULL
;
4005 bool modify_mtime
= true;
4007 SMB_STRUCT_STAT sbuf
;
4009 if (!CAN_WRITE(conn
)) {
4010 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
4013 init_smb_file_time(&ft
);
4015 if (total_data
< 100) {
4016 return NT_STATUS_INVALID_PARAMETER
;
4019 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
4020 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
4021 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
4022 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
4025 ft
.atime
= pull_long_date_full_timespec(pdata
+24); /* access_time */
4026 ft
.mtime
= pull_long_date_full_timespec(pdata
+32); /* modification_time */
4027 set_owner
= (uid_t
)IVAL(pdata
,40);
4028 set_grp
= (gid_t
)IVAL(pdata
,48);
4029 raw_unixmode
= IVAL(pdata
,84);
4031 if (VALID_STAT(smb_fname
->st
)) {
4032 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
4033 ptype
= PERM_EXISTING_DIR
;
4035 ptype
= PERM_EXISTING_FILE
;
4038 ptype
= PERM_NEW_FILE
;
4041 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
4043 if (!NT_STATUS_IS_OK(status
)) {
4047 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
4048 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4049 smb_fname_str_dbg(smb_fname
), (double)size
,
4050 (unsigned int)set_owner
, (unsigned int)set_grp
,
4051 (int)raw_unixmode
));
4053 sbuf
= smb_fname
->st
;
4055 if (!VALID_STAT(sbuf
)) {
4057 * The only valid use of this is to create character and block
4058 * devices, and named pipes. This is deprecated (IMHO) and
4059 * a new info level should be used for mknod. JRA.
4062 if (dirfsp
== NULL
) {
4063 return NT_STATUS_INVALID_PARAMETER
;
4066 return smb_unix_mknod(conn
,
4074 /* Horrible backwards compatibility hack as an old server bug
4075 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
4079 size
= get_file_size_stat(&sbuf
);
4084 * Deal with the UNIX specific mode set.
4087 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
4090 if (fsp
== NULL
|| S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
4091 DBG_WARNING("Can't set mode on symlink %s\n",
4092 smb_fname_str_dbg(smb_fname
));
4093 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4096 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4097 "setting mode 0%o for file %s\n",
4098 (unsigned int)unixmode
,
4099 smb_fname_str_dbg(smb_fname
)));
4100 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
4102 return map_nt_error_from_unix(errno
);
4107 * Deal with the UNIX specific uid set.
4110 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
4111 (sbuf
.st_ex_uid
!= set_owner
)) {
4114 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4115 "changing owner %u for path %s\n",
4116 (unsigned int)set_owner
,
4117 smb_fname_str_dbg(smb_fname
)));
4120 !fsp
->fsp_flags
.is_pathref
&&
4121 fsp_get_io_fd(fsp
) != -1)
4123 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
4126 * UNIX extensions calls must always operate
4129 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
,
4130 set_owner
, (gid_t
)-1);
4134 status
= map_nt_error_from_unix(errno
);
4140 * Deal with the UNIX specific gid set.
4143 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
4144 (sbuf
.st_ex_gid
!= set_grp
)) {
4147 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4148 "changing group %u for file %s\n",
4149 (unsigned int)set_grp
,
4150 smb_fname_str_dbg(smb_fname
)));
4152 !fsp
->fsp_flags
.is_pathref
&&
4153 fsp_get_io_fd(fsp
) != -1)
4155 ret
= SMB_VFS_FCHOWN(fsp
, (uid_t
)-1, set_grp
);
4158 * UNIX extensions calls must always operate
4161 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
, (uid_t
)-1,
4165 status
= map_nt_error_from_unix(errno
);
4170 /* Deal with any size changes. */
4172 if (S_ISREG(sbuf
.st_ex_mode
)) {
4173 status
= smb_set_file_size(conn
, req
,
4179 if (!NT_STATUS_IS_OK(status
)) {
4184 /* Deal with any time changes. */
4185 if (is_omit_timespec(&ft
.mtime
) && is_omit_timespec(&ft
.atime
)) {
4186 /* No change, don't cancel anything. */
4190 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4191 for(all_fsps
= file_find_di_first(conn
->sconn
, id
, true); all_fsps
;
4192 all_fsps
= file_find_di_next(all_fsps
, true)) {
4194 * We're setting the time explicitly for UNIX.
4195 * Cancel any pending changes over all handles.
4197 all_fsps
->fsp_flags
.update_write_time_on_close
= false;
4198 TALLOC_FREE(all_fsps
->update_write_time_event
);
4202 * Override the "setting_write_time"
4203 * parameter here as it almost does what
4204 * we need. Just remember if we modified
4205 * mtime and send the notify ourselves.
4207 if (is_omit_timespec(&ft
.mtime
)) {
4208 modify_mtime
= false;
4211 status
= smb_set_file_time(conn
,
4217 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
4218 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
4223 /****************************************************************************
4224 Deal with SMB_SET_FILE_UNIX_INFO2.
4225 ****************************************************************************/
4227 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
4228 struct smb_request
*req
,
4231 struct files_struct
*dirfsp
,
4233 struct smb_filename
*smb_fname
)
4236 uint32_t smb_fflags
;
4239 if (!CAN_WRITE(conn
)) {
4240 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
4243 if (total_data
< 116) {
4244 return NT_STATUS_INVALID_PARAMETER
;
4247 /* Start by setting all the fields that are common between UNIX_BASIC
4250 status
= smb_set_file_unix_basic(conn
,
4257 if (!NT_STATUS_IS_OK(status
)) {
4261 smb_fflags
= IVAL(pdata
, 108);
4262 smb_fmask
= IVAL(pdata
, 112);
4264 /* NB: We should only attempt to alter the file flags if the client
4265 * sends a non-zero mask.
4267 if (smb_fmask
!= 0) {
4268 int stat_fflags
= 0;
4270 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
4271 smb_fmask
, &stat_fflags
)) {
4272 /* Client asked to alter a flag we don't understand. */
4273 return NT_STATUS_INVALID_PARAMETER
;
4276 if (fsp
== NULL
|| S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
4277 DBG_WARNING("Can't change flags on symlink %s\n",
4278 smb_fname_str_dbg(smb_fname
));
4279 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4281 if (SMB_VFS_FCHFLAGS(fsp
, stat_fflags
) != 0) {
4282 return map_nt_error_from_unix(errno
);
4286 /* XXX: need to add support for changing the create_time here. You
4287 * can do this for paths on Darwin with setattrlist(2). The right way
4288 * to hook this up is probably by extending the VFS utimes interface.
4291 return NT_STATUS_OK
;
4294 /****************************************************************************
4295 Deal with SMB_SET_POSIX_ACL.
4296 ****************************************************************************/
4298 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
4299 struct smb_request
*req
,
4303 struct smb_filename
*smb_fname
)
4305 #if !defined(HAVE_POSIX_ACLS)
4306 return NT_STATUS_INVALID_LEVEL
;
4308 uint16_t posix_acl_version
;
4309 uint16_t num_file_acls
;
4310 uint16_t num_def_acls
;
4311 bool valid_file_acls
= true;
4312 bool valid_def_acls
= true;
4314 unsigned int size_needed
;
4315 unsigned int total_data
;
4316 bool close_fsp
= false;
4318 if (total_data_in
< 0) {
4319 status
= NT_STATUS_INVALID_PARAMETER
;
4323 total_data
= total_data_in
;
4325 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
4326 status
= NT_STATUS_INVALID_PARAMETER
;
4329 posix_acl_version
= SVAL(pdata
,0);
4330 num_file_acls
= SVAL(pdata
,2);
4331 num_def_acls
= SVAL(pdata
,4);
4333 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
4334 valid_file_acls
= false;
4338 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
4339 valid_def_acls
= false;
4343 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
4344 status
= NT_STATUS_INVALID_PARAMETER
;
4349 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
4350 status
= NT_STATUS_INVALID_PARAMETER
;
4354 size_needed
= num_file_acls
+ num_def_acls
;
4357 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4358 * than UINT_MAX, so check by division.
4360 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
4361 status
= NT_STATUS_INVALID_PARAMETER
;
4365 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
4366 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
4367 status
= NT_STATUS_INVALID_PARAMETER
;
4370 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
4372 if (total_data
< size_needed
) {
4373 status
= NT_STATUS_INVALID_PARAMETER
;
4378 * Ensure we always operate on a file descriptor, not just
4381 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
4382 uint32_t access_mask
= SEC_STD_WRITE_OWNER
|
4384 SEC_STD_READ_CONTROL
|
4385 FILE_READ_ATTRIBUTES
|
4386 FILE_WRITE_ATTRIBUTES
;
4388 status
= get_posix_fsp(conn
,
4394 if (!NT_STATUS_IS_OK(status
)) {
4400 /* Here we know fsp != NULL */
4401 SMB_ASSERT(fsp
!= NULL
);
4403 status
= refuse_symlink_fsp(fsp
);
4404 if (!NT_STATUS_IS_OK(status
)) {
4408 /* If we have a default acl, this *must* be a directory. */
4409 if (valid_def_acls
&& !fsp
->fsp_flags
.is_directory
) {
4410 DBG_INFO("Can't set default acls on "
4411 "non-directory %s\n",
4413 return NT_STATUS_INVALID_HANDLE
;
4416 DBG_DEBUG("file %s num_file_acls = %"PRIu16
", "
4417 "num_def_acls = %"PRIu16
"\n",
4422 /* Move pdata to the start of the file ACL entries. */
4423 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
4425 if (valid_file_acls
) {
4426 status
= set_unix_posix_acl(conn
,
4430 if (!NT_STATUS_IS_OK(status
)) {
4435 /* Move pdata to the start of the default ACL entries. */
4436 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
4438 if (valid_def_acls
) {
4439 status
= set_unix_posix_default_acl(conn
,
4443 if (!NT_STATUS_IS_OK(status
)) {
4448 status
= NT_STATUS_OK
;
4453 (void)close_file_free(req
, &fsp
, NORMAL_CLOSE
);
4459 static void call_trans2setpathinfo(
4460 connection_struct
*conn
,
4461 struct smb_request
*req
,
4466 unsigned int max_data_bytes
)
4468 uint16_t info_level
;
4469 struct smb_filename
*smb_fname
= NULL
;
4470 struct files_struct
*dirfsp
= NULL
;
4471 struct files_struct
*fsp
= NULL
;
4472 char *params
= *pparams
;
4473 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4476 bool info_level_handled
;
4477 int data_return_size
= 0;
4480 if (params
== NULL
) {
4481 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4486 if (total_params
< 7) {
4487 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4491 info_level
= SVAL(params
,0);
4493 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4494 if (!lp_smb1_unix_extensions()) {
4495 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4498 if (!req
->posix_pathnames
) {
4499 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4504 if (req
->posix_pathnames
) {
4505 srvstr_get_path_posix(req
,
4514 srvstr_get_path(req
,
4523 if (!NT_STATUS_IS_OK(status
)) {
4524 reply_nterror(req
, status
);
4528 DBG_NOTICE("fname=%s info_level=%d totdata=%d\n",
4533 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4534 extract_snapshot_token(fname
, &twrp
);
4536 status
= smb1_strip_dfs_path(req
, &ucf_flags
, &fname
);
4537 if (!NT_STATUS_IS_OK(status
)) {
4538 reply_nterror(req
, status
);
4541 status
= filename_convert_dirfsp(req
,
4548 if (!NT_STATUS_IS_OK(status
)) {
4549 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
4550 reply_botherror(req
,
4551 NT_STATUS_PATH_NOT_COVERED
,
4552 ERRSRV
, ERRbadpath
);
4555 reply_nterror(req
, status
);
4559 info_level_handled
= true; /* Untouched in switch cases below */
4561 switch (info_level
) {
4564 info_level_handled
= false;
4567 case SMB_POSIX_PATH_OPEN
:
4568 status
= smb_posix_open(conn
,
4577 case SMB_POSIX_PATH_UNLINK
:
4578 status
= smb_posix_unlink(conn
,
4586 case SMB_SET_FILE_UNIX_LINK
:
4587 status
= smb_set_file_unix_link(
4588 conn
, req
, *ppdata
, total_data
, smb_fname
);
4591 case SMB_SET_FILE_UNIX_HLINK
:
4592 status
= smb_set_file_unix_hlink(
4593 conn
, req
, *ppdata
, total_data
, smb_fname
);
4596 case SMB_SET_FILE_UNIX_BASIC
:
4597 status
= smb_set_file_unix_basic(conn
,
4606 case SMB_SET_FILE_UNIX_INFO2
:
4607 status
= smb_set_file_unix_info2(conn
,
4615 case SMB_SET_POSIX_ACL
:
4616 status
= smb_set_posix_acl(
4617 conn
, req
, *ppdata
, total_data
, NULL
, smb_fname
);
4621 if (info_level_handled
) {
4622 handle_trans2setfilepathinfo_result(
4634 * smb_fname->fsp may be NULL if smb_fname points at a symlink
4635 * and we're in POSIX context, so be careful when using fsp
4636 * below, it can still be NULL.
4638 fsp
= smb_fname
->fsp
;
4640 status
= smbd_do_setfilepathinfo(
4651 handle_trans2setfilepathinfo_result(
4661 static void call_trans2setfileinfo(
4662 connection_struct
*conn
,
4663 struct smb_request
*req
,
4668 unsigned int max_data_bytes
)
4670 char *pdata
= *ppdata
;
4671 uint16_t info_level
;
4672 struct smb_filename
*smb_fname
= NULL
;
4673 struct files_struct
*fsp
= NULL
;
4674 char *params
= *pparams
;
4675 int data_return_size
= 0;
4676 bool info_level_handled
;
4680 if (params
== NULL
) {
4681 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4684 if (total_params
< 4) {
4685 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4689 fsp
= file_fsp(req
, SVAL(params
,0));
4690 /* Basic check for non-null fsp. */
4691 if (!check_fsp_open(conn
, req
, fsp
)) {
4694 info_level
= SVAL(params
,2);
4696 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4697 if (!lp_smb1_unix_extensions()) {
4698 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4701 if (!req
->posix_pathnames
) {
4702 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4707 smb_fname
= fsp
->fsp_name
;
4709 DBG_NOTICE("fnum=%s fname=%s info_level=%d totdata=%d\n",
4715 if (fsp_get_pathref_fd(fsp
) == -1) {
4717 * This is actually a SETFILEINFO on a directory
4718 * handle (returned from an NT SMB). NT5.0 seems
4719 * to do this call. JRA.
4721 ret
= vfs_stat(conn
, smb_fname
);
4723 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
4724 smb_fname_str_dbg(smb_fname
),
4726 reply_nterror(req
, map_nt_error_from_unix(errno
));
4729 } else if (fsp
->print_file
) {
4731 * Doing a DELETE_ON_CLOSE should cancel a print job.
4733 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) &&
4736 fsp
->fsp_flags
.delete_on_close
= true;
4738 DBG_NOTICE("Cancelling print job (%s)\n",
4742 send_trans2_replies(
4752 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
4757 * Original code - this is an open file.
4759 status
= vfs_stat_fsp(fsp
);
4760 if (!NT_STATUS_IS_OK(status
)) {
4761 DBG_NOTICE("fstat of %s failed (%s)\n",
4764 reply_nterror(req
, status
);
4769 info_level_handled
= true; /* Untouched in switch cases below */
4771 switch (info_level
) {
4774 info_level_handled
= false;
4777 case SMB_SET_FILE_UNIX_BASIC
:
4778 status
= smb_set_file_unix_basic(conn
,
4787 case SMB_SET_FILE_UNIX_INFO2
:
4788 status
= smb_set_file_unix_info2(conn
,
4797 case SMB_SET_POSIX_LOCK
:
4798 status
= smb_set_posix_lock(
4799 conn
, req
, *ppdata
, total_data
, fsp
);
4803 if (info_level_handled
) {
4804 handle_trans2setfilepathinfo_result(
4815 status
= smbd_do_setfilepathinfo(
4826 handle_trans2setfilepathinfo_result(
4836 /****************************************************************************
4837 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4838 ****************************************************************************/
4840 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
4841 char **pparams
, int total_params
,
4842 char **ppdata
, int total_data
,
4843 unsigned int max_data_bytes
)
4845 struct files_struct
*dirfsp
= NULL
;
4846 struct files_struct
*fsp
= NULL
;
4847 struct smb_filename
*smb_dname
= NULL
;
4848 char *params
= *pparams
;
4849 char *pdata
= *ppdata
;
4850 char *directory
= NULL
;
4851 NTSTATUS status
= NT_STATUS_OK
;
4852 struct ea_list
*ea_list
= NULL
;
4853 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4855 TALLOC_CTX
*ctx
= talloc_tos();
4857 if (!CAN_WRITE(conn
)) {
4858 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4862 if (total_params
< 5) {
4863 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4867 if (req
->posix_pathnames
) {
4868 srvstr_get_path_posix(ctx
,
4877 srvstr_get_path(ctx
,
4886 if (!NT_STATUS_IS_OK(status
)) {
4887 reply_nterror(req
, status
);
4891 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
4893 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4894 extract_snapshot_token(directory
, &twrp
);
4896 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &directory
);
4897 if (!NT_STATUS_IS_OK(status
)) {
4898 reply_nterror(req
, status
);
4901 status
= filename_convert_dirfsp(ctx
,
4908 if (!NT_STATUS_IS_OK(status
)) {
4909 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
4910 reply_botherror(req
,
4911 NT_STATUS_PATH_NOT_COVERED
,
4912 ERRSRV
, ERRbadpath
);
4915 reply_nterror(req
, status
);
4920 * OS/2 workplace shell seems to send SET_EA requests of "null"
4921 * length (4 bytes containing IVAL 4).
4922 * They seem to have no effect. Bug #3212. JRA.
4925 if (total_data
&& (total_data
!= 4)) {
4926 /* Any data in this call is an EA list. */
4927 if (total_data
< 10) {
4928 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4932 if (IVAL(pdata
,0) > total_data
) {
4933 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4934 IVAL(pdata
,0), (unsigned int)total_data
));
4935 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4939 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
4942 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4946 if (!lp_ea_support(SNUM(conn
))) {
4947 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
4951 /* If total_data == 4 Windows doesn't care what values
4952 * are placed in that field, it just ignores them.
4953 * The System i QNTC IBM SMB client puts bad values here,
4954 * so ignore them. */
4956 status
= SMB_VFS_CREATE_FILE(
4959 dirfsp
, /* dirfsp */
4960 smb_dname
, /* fname */
4961 MAXIMUM_ALLOWED_ACCESS
, /* access_mask */
4962 FILE_SHARE_NONE
, /* share_access */
4963 FILE_CREATE
, /* create_disposition*/
4964 FILE_DIRECTORY_FILE
, /* create_options */
4965 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
4966 0, /* oplock_request */
4968 0, /* allocation_size */
4969 0, /* private_flags */
4974 NULL
, NULL
); /* create context */
4975 if (!NT_STATUS_IS_OK(status
)) {
4976 reply_nterror(req
, status
);
4980 /* Try and set any given EA. */
4982 status
= set_ea(conn
, fsp
, ea_list
);
4983 if (!NT_STATUS_IS_OK(status
)) {
4984 reply_nterror(req
, status
);
4989 /* Realloc the parameter and data sizes */
4990 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4991 if(*pparams
== NULL
) {
4992 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4999 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
5003 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
5005 TALLOC_FREE(smb_dname
);
5009 /****************************************************************************
5010 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
5011 We don't actually do this - we just send a null response.
5012 ****************************************************************************/
5014 static void call_trans2findnotifyfirst(connection_struct
*conn
,
5015 struct smb_request
*req
,
5016 char **pparams
, int total_params
,
5017 char **ppdata
, int total_data
,
5018 unsigned int max_data_bytes
)
5020 char *params
= *pparams
;
5021 uint16_t info_level
;
5023 if (total_params
< 6) {
5024 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5028 info_level
= SVAL(params
,4);
5029 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
5031 switch (info_level
) {
5036 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5040 /* Realloc the parameter and data sizes */
5041 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
5042 if (*pparams
== NULL
) {
5043 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5048 SSVAL(params
,0,fnf_handle
);
5049 SSVAL(params
,2,0); /* No changes */
5050 SSVAL(params
,4,0); /* No EA errors */
5057 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
5062 /****************************************************************************
5063 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
5064 changes). Currently this does nothing.
5065 ****************************************************************************/
5067 static void call_trans2findnotifynext(connection_struct
*conn
,
5068 struct smb_request
*req
,
5069 char **pparams
, int total_params
,
5070 char **ppdata
, int total_data
,
5071 unsigned int max_data_bytes
)
5073 char *params
= *pparams
;
5075 DEBUG(3,("call_trans2findnotifynext\n"));
5077 /* Realloc the parameter and data sizes */
5078 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
5079 if (*pparams
== NULL
) {
5080 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5085 SSVAL(params
,0,0); /* No changes */
5086 SSVAL(params
,2,0); /* No EA errors */
5088 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
5093 /****************************************************************************
5094 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5095 ****************************************************************************/
5097 static void call_trans2getdfsreferral(connection_struct
*conn
,
5098 struct smb_request
*req
,
5099 char **pparams
, int total_params
,
5100 char **ppdata
, int total_data
,
5101 unsigned int max_data_bytes
)
5103 char *params
= *pparams
;
5104 char *pathname
= NULL
;
5106 int max_referral_level
;
5107 NTSTATUS status
= NT_STATUS_OK
;
5108 TALLOC_CTX
*ctx
= talloc_tos();
5110 DEBUG(10,("call_trans2getdfsreferral\n"));
5112 if (!IS_IPC(conn
)) {
5113 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5117 if (total_params
< 3) {
5118 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5122 max_referral_level
= SVAL(params
,0);
5124 if(!lp_host_msdfs()) {
5125 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
5129 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
5130 total_params
- 2, STR_TERMINATE
);
5132 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
5135 reply_size
= setup_dfs_referral(
5136 conn
, pathname
, max_referral_level
, ppdata
, &status
);
5137 if (reply_size
< 0) {
5138 reply_nterror(req
, status
);
5142 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
5143 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
5144 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
5149 #define LMCAT_SPL 0x53
5150 #define LMFUNC_GETJOBID 0x60
5152 /****************************************************************************
5153 Reply to a TRANS2_IOCTL - used for OS/2 printing.
5154 ****************************************************************************/
5156 static void call_trans2ioctl(connection_struct
*conn
,
5157 struct smb_request
*req
,
5158 char **pparams
, int total_params
,
5159 char **ppdata
, int total_data
,
5160 unsigned int max_data_bytes
)
5162 const struct loadparm_substitution
*lp_sub
=
5163 loadparm_s3_global_substitution();
5164 char *pdata
= *ppdata
;
5165 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
5169 /* check for an invalid fid before proceeding */
5172 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5176 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
5177 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
5178 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
5179 if (*ppdata
== NULL
) {
5180 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5185 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5186 CAN ACCEPT THIS IN UNICODE. JRA. */
5189 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
5191 status
= srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
5192 lp_netbios_name(), 15,
5193 STR_ASCII
|STR_TERMINATE
, &len
); /* Our NetBIOS name */
5194 if (!NT_STATUS_IS_OK(status
)) {
5195 reply_nterror(req
, status
);
5198 status
= srvstr_push(pdata
, req
->flags2
, pdata
+18,
5199 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)), 13,
5200 STR_ASCII
|STR_TERMINATE
, &len
); /* Service name */
5201 if (!NT_STATUS_IS_OK(status
)) {
5202 reply_nterror(req
, status
);
5205 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
5210 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5211 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
5214 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
5215 struct trans_state
*state
)
5217 struct smbXsrv_connection
*xconn
= req
->xconn
;
5219 if (xconn
->protocol
>= PROTOCOL_NT1
) {
5220 req
->flags2
|= 0x40; /* IS_LONG_NAME */
5221 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
5224 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
5225 if (state
->call
!= TRANSACT2_QFSINFO
&&
5226 state
->call
!= TRANSACT2_SETFSINFO
) {
5227 DEBUG(0,("handle_trans2: encryption required "
5229 (unsigned int)state
->call
));
5230 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5235 /* Now we must call the relevant TRANS2 function */
5236 switch(state
->call
) {
5237 case TRANSACT2_OPEN
:
5239 START_PROFILE(Trans2_open
);
5240 call_trans2open(conn
, req
,
5241 &state
->param
, state
->total_param
,
5242 &state
->data
, state
->total_data
,
5243 state
->max_data_return
);
5244 END_PROFILE(Trans2_open
);
5248 case TRANSACT2_FINDFIRST
:
5250 START_PROFILE(Trans2_findfirst
);
5251 call_trans2findfirst(conn
, req
,
5252 &state
->param
, state
->total_param
,
5253 &state
->data
, state
->total_data
,
5254 state
->max_data_return
);
5255 END_PROFILE(Trans2_findfirst
);
5259 case TRANSACT2_FINDNEXT
:
5261 START_PROFILE(Trans2_findnext
);
5262 call_trans2findnext(conn
, req
,
5263 &state
->param
, state
->total_param
,
5264 &state
->data
, state
->total_data
,
5265 state
->max_data_return
);
5266 END_PROFILE(Trans2_findnext
);
5270 case TRANSACT2_QFSINFO
:
5272 START_PROFILE(Trans2_qfsinfo
);
5273 call_trans2qfsinfo(conn
, req
,
5274 &state
->param
, state
->total_param
,
5275 &state
->data
, state
->total_data
,
5276 state
->max_data_return
);
5277 END_PROFILE(Trans2_qfsinfo
);
5281 case TRANSACT2_SETFSINFO
:
5283 START_PROFILE(Trans2_setfsinfo
);
5284 call_trans2setfsinfo(conn
, req
,
5285 &state
->param
, state
->total_param
,
5286 &state
->data
, state
->total_data
,
5287 state
->max_data_return
);
5288 END_PROFILE(Trans2_setfsinfo
);
5292 case TRANSACT2_QPATHINFO
:
5294 START_PROFILE(Trans2_qpathinfo
);
5295 call_trans2qpathinfo(
5302 state
->max_data_return
);
5303 END_PROFILE(Trans2_qpathinfo
);
5307 case TRANSACT2_QFILEINFO
:
5309 START_PROFILE(Trans2_qfileinfo
);
5310 call_trans2qfileinfo(
5317 state
->max_data_return
);
5318 END_PROFILE(Trans2_qfileinfo
);
5322 case TRANSACT2_SETPATHINFO
:
5324 START_PROFILE(Trans2_setpathinfo
);
5325 call_trans2setpathinfo(
5332 state
->max_data_return
);
5333 END_PROFILE(Trans2_setpathinfo
);
5337 case TRANSACT2_SETFILEINFO
:
5339 START_PROFILE(Trans2_setfileinfo
);
5340 call_trans2setfileinfo(
5347 state
->max_data_return
);
5348 END_PROFILE(Trans2_setfileinfo
);
5352 case TRANSACT2_FINDNOTIFYFIRST
:
5354 START_PROFILE(Trans2_findnotifyfirst
);
5355 call_trans2findnotifyfirst(conn
, req
,
5356 &state
->param
, state
->total_param
,
5357 &state
->data
, state
->total_data
,
5358 state
->max_data_return
);
5359 END_PROFILE(Trans2_findnotifyfirst
);
5363 case TRANSACT2_FINDNOTIFYNEXT
:
5365 START_PROFILE(Trans2_findnotifynext
);
5366 call_trans2findnotifynext(conn
, req
,
5367 &state
->param
, state
->total_param
,
5368 &state
->data
, state
->total_data
,
5369 state
->max_data_return
);
5370 END_PROFILE(Trans2_findnotifynext
);
5374 case TRANSACT2_MKDIR
:
5376 START_PROFILE(Trans2_mkdir
);
5377 call_trans2mkdir(conn
, req
,
5378 &state
->param
, state
->total_param
,
5379 &state
->data
, state
->total_data
,
5380 state
->max_data_return
);
5381 END_PROFILE(Trans2_mkdir
);
5385 case TRANSACT2_GET_DFS_REFERRAL
:
5387 START_PROFILE(Trans2_get_dfs_referral
);
5388 call_trans2getdfsreferral(conn
, req
,
5389 &state
->param
, state
->total_param
,
5390 &state
->data
, state
->total_data
,
5391 state
->max_data_return
);
5392 END_PROFILE(Trans2_get_dfs_referral
);
5396 case TRANSACT2_IOCTL
:
5398 START_PROFILE(Trans2_ioctl
);
5399 call_trans2ioctl(conn
, req
,
5400 &state
->param
, state
->total_param
,
5401 &state
->data
, state
->total_data
,
5402 state
->max_data_return
);
5403 END_PROFILE(Trans2_ioctl
);
5408 /* Error in request */
5409 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
5410 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
5414 /****************************************************************************
5415 Reply to a SMBtrans2.
5416 ****************************************************************************/
5418 void reply_trans2(struct smb_request
*req
)
5420 connection_struct
*conn
= req
->conn
;
5425 unsigned int tran_call
;
5426 struct trans_state
*state
;
5429 START_PROFILE(SMBtrans2
);
5431 if (req
->wct
< 14) {
5432 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5433 END_PROFILE(SMBtrans2
);
5437 dsoff
= SVAL(req
->vwv
+12, 0);
5438 dscnt
= SVAL(req
->vwv
+11, 0);
5439 psoff
= SVAL(req
->vwv
+10, 0);
5440 pscnt
= SVAL(req
->vwv
+9, 0);
5441 tran_call
= SVAL(req
->vwv
+14, 0);
5443 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
5444 if (!NT_STATUS_IS_OK(result
)) {
5445 DEBUG(2, ("Got invalid trans2 request: %s\n",
5446 nt_errstr(result
)));
5447 reply_nterror(req
, result
);
5448 END_PROFILE(SMBtrans2
);
5453 switch (tran_call
) {
5454 /* List the allowed trans2 calls on IPC$ */
5455 case TRANSACT2_OPEN
:
5456 case TRANSACT2_GET_DFS_REFERRAL
:
5457 case TRANSACT2_QFILEINFO
:
5458 case TRANSACT2_QFSINFO
:
5459 case TRANSACT2_SETFSINFO
:
5462 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5463 END_PROFILE(SMBtrans2
);
5468 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
5469 DEBUG(0, ("talloc failed\n"));
5470 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5471 END_PROFILE(SMBtrans2
);
5475 state
->cmd
= SMBtrans2
;
5477 state
->mid
= req
->mid
;
5478 state
->vuid
= req
->vuid
;
5479 state
->setup_count
= SVAL(req
->vwv
+13, 0);
5480 state
->setup
= NULL
;
5481 state
->total_param
= SVAL(req
->vwv
+0, 0);
5482 state
->param
= NULL
;
5483 state
->total_data
= SVAL(req
->vwv
+1, 0);
5485 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
5486 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
5487 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
5488 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
5489 state
->one_way
= BITSETW(req
->vwv
+5, 1);
5491 state
->call
= tran_call
;
5493 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5494 is so as a sanity check */
5495 if (state
->setup_count
!= 1) {
5497 * Need to have rc=0 for ioctl to get job id for OS/2.
5498 * Network printing will fail if function is not successful.
5499 * Similar function in reply.c will be used if protocol
5500 * is LANMAN1.0 instead of LM1.2X002.
5501 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5502 * outbuf doesn't have to be set(only job id is used).
5504 if ( (state
->setup_count
== 4)
5505 && (tran_call
== TRANSACT2_IOCTL
)
5506 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
5507 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
5508 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5510 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
5511 DEBUG(2,("Transaction is %d\n",tran_call
));
5513 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5514 END_PROFILE(SMBtrans2
);
5519 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
5522 if (state
->total_data
) {
5524 if (smb_buffer_oob(state
->total_data
, 0, dscnt
)
5525 || smb_buffer_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
5529 /* Can't use talloc here, the core routines do realloc on the
5530 * params and data. */
5531 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
5532 if (state
->data
== NULL
) {
5533 DEBUG(0,("reply_trans2: data malloc fail for %u "
5534 "bytes !\n", (unsigned int)state
->total_data
));
5536 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5537 END_PROFILE(SMBtrans2
);
5541 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
5544 if (state
->total_param
) {
5546 if (smb_buffer_oob(state
->total_param
, 0, pscnt
)
5547 || smb_buffer_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
5551 /* Can't use talloc here, the core routines do realloc on the
5552 * params and data. */
5553 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
5554 if (state
->param
== NULL
) {
5555 DEBUG(0,("reply_trans: param malloc fail for %u "
5556 "bytes !\n", (unsigned int)state
->total_param
));
5557 SAFE_FREE(state
->data
);
5559 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5560 END_PROFILE(SMBtrans2
);
5564 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
5567 state
->received_data
= dscnt
;
5568 state
->received_param
= pscnt
;
5570 if ((state
->received_param
== state
->total_param
) &&
5571 (state
->received_data
== state
->total_data
)) {
5573 handle_trans2(conn
, req
, state
);
5575 SAFE_FREE(state
->data
);
5576 SAFE_FREE(state
->param
);
5578 END_PROFILE(SMBtrans2
);
5582 DLIST_ADD(conn
->pending_trans
, state
);
5584 /* We need to send an interim response then receive the rest
5585 of the parameter/data bytes */
5586 reply_smb1_outbuf(req
, 0, 0);
5587 show_msg((char *)req
->outbuf
);
5588 END_PROFILE(SMBtrans2
);
5593 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5594 SAFE_FREE(state
->data
);
5595 SAFE_FREE(state
->param
);
5597 END_PROFILE(SMBtrans2
);
5598 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5601 /****************************************************************************
5602 Reply to a SMBtranss2
5603 ****************************************************************************/
5605 void reply_transs2(struct smb_request
*req
)
5607 connection_struct
*conn
= req
->conn
;
5608 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
5609 struct trans_state
*state
;
5611 START_PROFILE(SMBtranss2
);
5613 show_msg((const char *)req
->inbuf
);
5615 /* Windows clients expect all replies to
5616 a transact secondary (SMBtranss2 0x33)
5617 to have a command code of transact
5618 (SMBtrans2 0x32). See bug #8989
5619 and also [MS-CIFS] section 2.2.4.47.2
5622 req
->cmd
= SMBtrans2
;
5625 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5626 END_PROFILE(SMBtranss2
);
5630 for (state
= conn
->pending_trans
; state
!= NULL
;
5631 state
= state
->next
) {
5632 if (state
->mid
== req
->mid
) {
5637 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
5638 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5639 END_PROFILE(SMBtranss2
);
5643 /* Revise state->total_param and state->total_data in case they have
5644 changed downwards */
5646 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
5647 state
->total_param
= SVAL(req
->vwv
+0, 0);
5648 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
5649 state
->total_data
= SVAL(req
->vwv
+1, 0);
5651 pcnt
= SVAL(req
->vwv
+2, 0);
5652 poff
= SVAL(req
->vwv
+3, 0);
5653 pdisp
= SVAL(req
->vwv
+4, 0);
5655 dcnt
= SVAL(req
->vwv
+5, 0);
5656 doff
= SVAL(req
->vwv
+6, 0);
5657 ddisp
= SVAL(req
->vwv
+7, 0);
5659 state
->received_param
+= pcnt
;
5660 state
->received_data
+= dcnt
;
5662 if ((state
->received_data
> state
->total_data
) ||
5663 (state
->received_param
> state
->total_param
))
5667 if (smb_buffer_oob(state
->total_param
, pdisp
, pcnt
)
5668 || smb_buffer_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
5671 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
5675 if (smb_buffer_oob(state
->total_data
, ddisp
, dcnt
)
5676 || smb_buffer_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
5679 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
5682 if ((state
->received_param
< state
->total_param
) ||
5683 (state
->received_data
< state
->total_data
)) {
5684 END_PROFILE(SMBtranss2
);
5688 handle_trans2(conn
, req
, state
);
5690 DLIST_REMOVE(conn
->pending_trans
, state
);
5691 SAFE_FREE(state
->data
);
5692 SAFE_FREE(state
->param
);
5695 END_PROFILE(SMBtranss2
);
5700 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5701 DLIST_REMOVE(conn
->pending_trans
, state
);
5702 SAFE_FREE(state
->data
);
5703 SAFE_FREE(state
->param
);
5705 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5706 END_PROFILE(SMBtranss2
);