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!!!", 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", 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 smb_filename
*smb_fname
,
3323 int *pdata_return_size
)
3325 bool extended_oplock_granted
= False
;
3326 char *pdata
= *ppdata
;
3328 uint32_t wire_open_mode
= 0;
3329 uint32_t raw_unixmode
= 0;
3330 uint32_t attributes
= 0;
3331 uint32_t create_disp
= 0;
3332 uint32_t access_mask
= 0;
3333 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
3334 NTSTATUS status
= NT_STATUS_OK
;
3335 mode_t unixmode
= (mode_t
)0;
3336 files_struct
*fsp
= NULL
;
3337 int oplock_request
= 0;
3339 uint16_t info_level_return
= 0;
3340 struct smb2_create_blobs
*posx
= NULL
;
3342 if (total_data
< 18) {
3343 return NT_STATUS_INVALID_PARAMETER
;
3346 flags
= IVAL(pdata
,0);
3347 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
3348 if (oplock_request
) {
3349 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
3352 wire_open_mode
= IVAL(pdata
,4);
3354 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
3355 return smb_posix_mkdir(conn
, req
,
3362 switch (wire_open_mode
& SMB_ACCMODE
) {
3364 access_mask
= SMB_O_RDONLY_MAPPING
;
3367 access_mask
= SMB_O_WRONLY_MAPPING
;
3370 access_mask
= (SMB_O_RDONLY_MAPPING
|
3371 SMB_O_WRONLY_MAPPING
);
3374 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
3375 (unsigned int)wire_open_mode
));
3376 return NT_STATUS_INVALID_PARAMETER
;
3379 wire_open_mode
&= ~SMB_ACCMODE
;
3381 /* First take care of O_CREAT|O_EXCL interactions. */
3382 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
3383 case (SMB_O_CREAT
| SMB_O_EXCL
):
3384 /* File exists fail. File not exist create. */
3385 create_disp
= FILE_CREATE
;
3388 /* File exists open. File not exist create. */
3389 create_disp
= FILE_OPEN_IF
;
3392 /* O_EXCL on its own without O_CREAT is undefined.
3393 We deliberately ignore it as some versions of
3394 Linux CIFSFS can send a bare O_EXCL on the
3395 wire which other filesystems in the kernel
3396 ignore. See bug 9519 for details. */
3401 /* File exists open. File not exist fail. */
3402 create_disp
= FILE_OPEN
;
3405 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
3406 (unsigned int)wire_open_mode
));
3407 return NT_STATUS_INVALID_PARAMETER
;
3410 /* Next factor in the effects of O_TRUNC. */
3411 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
3413 if (wire_open_mode
& SMB_O_TRUNC
) {
3414 switch (create_disp
) {
3416 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
3417 /* Leave create_disp alone as
3418 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
3420 /* File exists fail. File not exist create. */
3423 /* SMB_O_CREAT | SMB_O_TRUNC */
3424 /* File exists overwrite. File not exist create. */
3425 create_disp
= FILE_OVERWRITE_IF
;
3429 /* File exists overwrite. File not exist fail. */
3430 create_disp
= FILE_OVERWRITE
;
3433 /* Cannot get here. */
3434 smb_panic("smb_posix_open: logic error");
3435 return NT_STATUS_INVALID_PARAMETER
;
3439 raw_unixmode
= IVAL(pdata
,8);
3440 /* Next 4 bytes are not yet defined. */
3442 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
3443 (VALID_STAT(smb_fname
->st
) ?
3444 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
3447 if (!NT_STATUS_IS_OK(status
)) {
3451 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, unixmode
);
3452 if (!NT_STATUS_IS_OK(status
)) {
3453 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3458 if (wire_open_mode
& SMB_O_SYNC
) {
3459 create_options
|= FILE_WRITE_THROUGH
;
3461 if (wire_open_mode
& SMB_O_APPEND
) {
3462 access_mask
|= FILE_APPEND_DATA
;
3464 if (wire_open_mode
& SMB_O_DIRECT
) {
3465 attributes
|= FILE_FLAG_NO_BUFFERING
;
3468 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
3469 VALID_STAT_OF_DIR(smb_fname
->st
)) {
3470 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
3471 return NT_STATUS_FILE_IS_A_DIRECTORY
;
3473 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
3474 create_options
|= FILE_DIRECTORY_FILE
;
3477 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
3478 smb_fname_str_dbg(smb_fname
),
3479 (unsigned int)wire_open_mode
,
3480 (unsigned int)unixmode
));
3482 status
= SMB_VFS_CREATE_FILE(
3486 smb_fname
, /* fname */
3487 access_mask
, /* access_mask */
3488 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
3490 create_disp
, /* create_disposition*/
3491 create_options
, /* create_options */
3492 attributes
, /* file_attributes */
3493 oplock_request
, /* oplock_request */
3495 0, /* allocation_size */
3496 0, /* private_flags */
3501 posx
, /* in_context_blobs */
3502 NULL
); /* out_context_blobs */
3506 if (!NT_STATUS_IS_OK(status
)) {
3510 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
3511 extended_oplock_granted
= True
;
3514 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
3515 extended_oplock_granted
= True
;
3518 info_level_return
= SVAL(pdata
,16);
3520 /* Allocate the correct return size. */
3522 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
3523 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
3524 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
3525 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
3527 *pdata_return_size
= 12;
3530 /* Realloc the data size */
3531 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
3532 if (*ppdata
== NULL
) {
3533 close_file_free(req
, &fsp
, ERROR_CLOSE
);
3534 *pdata_return_size
= 0;
3535 return NT_STATUS_NO_MEMORY
;
3539 if (extended_oplock_granted
) {
3540 if (flags
& REQUEST_BATCH_OPLOCK
) {
3541 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
3543 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
3545 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
3546 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
3548 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
3551 SSVAL(pdata
,2,fsp
->fnum
);
3552 SIVAL(pdata
,4,info
); /* Was file created etc. */
3554 switch (info_level_return
) {
3555 case SMB_QUERY_FILE_UNIX_BASIC
:
3556 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
3557 SSVAL(pdata
,10,0); /* padding. */
3558 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
3561 case SMB_QUERY_FILE_UNIX_INFO2
:
3562 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
3563 SSVAL(pdata
,10,0); /* padding. */
3564 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
3568 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
3569 SSVAL(pdata
,10,0); /* padding. */
3572 return NT_STATUS_OK
;
3575 /****************************************************************************
3576 Delete a file with POSIX semantics.
3577 ****************************************************************************/
3579 struct smb_posix_unlink_state
{
3580 struct smb_filename
*smb_fname
;
3581 struct files_struct
*fsp
;
3585 static void smb_posix_unlink_locked(struct share_mode_lock
*lck
,
3588 struct smb_posix_unlink_state
*state
= private_data
;
3590 bool other_nonposix_opens
;
3592 other_nonposix_opens
= has_other_nonposix_opens(lck
, state
->fsp
);
3593 if (other_nonposix_opens
) {
3594 /* Fail with sharing violation. */
3595 state
->status
= NT_STATUS_SHARING_VIOLATION
;
3600 * Set the delete on close.
3602 state
->status
= smb_set_file_disposition_info(state
->fsp
->conn
,
3609 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
3610 struct smb_request
*req
,
3613 struct smb_filename
*smb_fname
)
3615 struct smb_posix_unlink_state state
= {};
3616 NTSTATUS status
= NT_STATUS_OK
;
3617 files_struct
*fsp
= NULL
;
3620 int create_options
= 0;
3621 struct smb2_create_blobs
*posx
= NULL
;
3623 if (!CAN_WRITE(conn
)) {
3624 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
3627 if (total_data
< 2) {
3628 return NT_STATUS_INVALID_PARAMETER
;
3631 flags
= SVAL(pdata
,0);
3633 if (!VALID_STAT(smb_fname
->st
)) {
3634 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3637 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
3638 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
3639 return NT_STATUS_NOT_A_DIRECTORY
;
3642 DEBUG(10,("smb_posix_unlink: %s %s\n",
3643 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
3644 smb_fname_str_dbg(smb_fname
)));
3646 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
3647 create_options
|= FILE_DIRECTORY_FILE
;
3650 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, 0777);
3651 if (!NT_STATUS_IS_OK(status
)) {
3652 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3657 status
= SMB_VFS_CREATE_FILE(
3661 smb_fname
, /* fname */
3662 DELETE_ACCESS
, /* access_mask */
3663 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
3665 FILE_OPEN
, /* create_disposition*/
3666 create_options
, /* create_options */
3667 0, /* file_attributes */
3668 0, /* oplock_request */
3670 0, /* allocation_size */
3671 0, /* private_flags */
3676 posx
, /* in_context_blobs */
3677 NULL
); /* out_context_blobs */
3681 if (!NT_STATUS_IS_OK(status
)) {
3686 * Don't lie to client. If we can't really delete due to
3687 * non-POSIX opens return SHARING_VIOLATION.
3690 state
= (struct smb_posix_unlink_state
) {
3691 .smb_fname
= smb_fname
,
3695 status
= share_mode_do_locked_vfs_allowed(fsp
->file_id
,
3696 smb_posix_unlink_locked
,
3698 if (!NT_STATUS_IS_OK(status
)) {
3699 DBG_ERR("share_mode_do_locked_vfs_allowed(%s) failed - %s\n",
3700 fsp_str_dbg(fsp
), nt_errstr(status
));
3701 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3702 return NT_STATUS_INVALID_PARAMETER
;
3705 status
= state
.status
;
3706 if (!NT_STATUS_IS_OK(status
)) {
3707 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3710 return close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3713 /****************************************************************************
3714 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
3715 ****************************************************************************/
3717 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
3718 struct smb_request
*req
,
3721 struct smb_filename
*new_smb_fname
)
3723 char *link_target
= NULL
;
3724 struct smb_filename target_fname
;
3725 TALLOC_CTX
*ctx
= talloc_tos();
3728 struct smb_filename
*parent_fname
= NULL
;
3729 struct smb_filename
*base_name
= NULL
;
3731 if (!CAN_WRITE(conn
)) {
3732 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
3735 /* Set a symbolic link. */
3736 /* Don't allow this if follow links is false. */
3738 if (total_data
== 0) {
3739 return NT_STATUS_INVALID_PARAMETER
;
3742 if (!lp_follow_symlinks(SNUM(conn
))) {
3743 return NT_STATUS_ACCESS_DENIED
;
3746 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
3747 total_data
, STR_TERMINATE
);
3750 return NT_STATUS_INVALID_PARAMETER
;
3753 target_fname
= (struct smb_filename
) {
3754 .base_name
= link_target
,
3757 /* Removes @GMT tokens if any */
3758 status
= canonicalize_snapshot_path(&target_fname
, UCF_GMT_PATHNAME
, 0);
3759 if (!NT_STATUS_IS_OK(status
)) {
3763 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3764 new_smb_fname
->base_name
, link_target
));
3766 status
= parent_pathref(talloc_tos(),
3771 if (!NT_STATUS_IS_OK(status
)) {
3775 ret
= SMB_VFS_SYMLINKAT(conn
,
3780 TALLOC_FREE(parent_fname
);
3781 return map_nt_error_from_unix(errno
);
3784 TALLOC_FREE(parent_fname
);
3785 return NT_STATUS_OK
;
3788 /****************************************************************************
3789 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
3790 ****************************************************************************/
3792 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
3793 struct smb_request
*req
,
3794 const char *pdata
, int total_data
,
3795 struct smb_filename
*smb_fname_new
)
3797 char *oldname
= NULL
;
3798 struct files_struct
*src_dirfsp
= NULL
;
3799 struct smb_filename
*smb_fname_old
= NULL
;
3800 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
3801 NTTIME old_twrp
= 0;
3802 TALLOC_CTX
*ctx
= talloc_tos();
3803 NTSTATUS status
= NT_STATUS_OK
;
3805 if (!CAN_WRITE(conn
)) {
3806 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
3809 /* Set a hard link. */
3810 if (total_data
== 0) {
3811 return NT_STATUS_INVALID_PARAMETER
;
3814 if (req
->posix_pathnames
) {
3815 srvstr_get_path_posix(ctx
,
3824 srvstr_get_path(ctx
,
3833 if (!NT_STATUS_IS_OK(status
)) {
3837 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3838 smb_fname_str_dbg(smb_fname_new
), oldname
));
3840 if (ucf_flags
& UCF_GMT_PATHNAME
) {
3841 extract_snapshot_token(oldname
, &old_twrp
);
3843 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &oldname
);
3844 if (!NT_STATUS_IS_OK(status
)) {
3847 status
= filename_convert_dirfsp(ctx
,
3854 if (!NT_STATUS_IS_OK(status
)) {
3858 return hardlink_internals(ctx
,
3864 NULL
, /* new_dirfsp */
3868 /****************************************************************************
3869 Allow a UNIX info mknod.
3870 ****************************************************************************/
3872 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
3875 const struct smb_filename
*smb_fname
)
3877 uint32_t file_type
= IVAL(pdata
,56);
3878 #if defined(HAVE_MAKEDEV)
3879 uint32_t dev_major
= IVAL(pdata
,60);
3880 uint32_t dev_minor
= IVAL(pdata
,68);
3882 SMB_DEV_T dev
= (SMB_DEV_T
)0;
3883 uint32_t raw_unixmode
= IVAL(pdata
,84);
3887 struct smb_filename
*parent_fname
= NULL
;
3888 struct smb_filename
*base_name
= NULL
;
3890 if (total_data
< 100) {
3891 return NT_STATUS_INVALID_PARAMETER
;
3894 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
3895 PERM_NEW_FILE
, &unixmode
);
3896 if (!NT_STATUS_IS_OK(status
)) {
3900 #if defined(HAVE_MAKEDEV)
3901 dev
= makedev(dev_major
, dev_minor
);
3904 switch (file_type
) {
3905 /* We can't create other objects here. */
3906 case UNIX_TYPE_FILE
:
3908 case UNIX_TYPE_SYMLINK
:
3909 return NT_STATUS_ACCESS_DENIED
;
3910 #if defined(S_IFIFO)
3911 case UNIX_TYPE_FIFO
:
3912 unixmode
|= S_IFIFO
;
3915 #if defined(S_IFSOCK)
3916 case UNIX_TYPE_SOCKET
:
3917 unixmode
|= S_IFSOCK
;
3920 #if defined(S_IFCHR)
3921 case UNIX_TYPE_CHARDEV
:
3922 /* This is only allowed for root. */
3923 if (get_current_uid(conn
) != sec_initial_uid()) {
3924 return NT_STATUS_ACCESS_DENIED
;
3926 unixmode
|= S_IFCHR
;
3929 #if defined(S_IFBLK)
3930 case UNIX_TYPE_BLKDEV
:
3931 if (get_current_uid(conn
) != sec_initial_uid()) {
3932 return NT_STATUS_ACCESS_DENIED
;
3934 unixmode
|= S_IFBLK
;
3938 return NT_STATUS_INVALID_PARAMETER
;
3941 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
3942 "%.0f mode 0%o for file %s\n", (double)dev
,
3943 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
3945 status
= parent_pathref(talloc_tos(),
3950 if (!NT_STATUS_IS_OK(status
)) {
3954 /* Ok - do the mknod. */
3955 ret
= SMB_VFS_MKNODAT(conn
,
3962 TALLOC_FREE(parent_fname
);
3963 return map_nt_error_from_unix(errno
);
3966 /* If any of the other "set" calls fail we
3967 * don't want to end up with a half-constructed mknod.
3970 if (lp_inherit_permissions(SNUM(conn
))) {
3971 inherit_access_posix_acl(conn
,
3976 TALLOC_FREE(parent_fname
);
3978 return NT_STATUS_OK
;
3981 /****************************************************************************
3982 Deal with SMB_SET_FILE_UNIX_BASIC.
3983 ****************************************************************************/
3985 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
3986 struct smb_request
*req
,
3990 struct smb_filename
*smb_fname
)
3992 struct smb_file_time ft
;
3993 uint32_t raw_unixmode
;
3996 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
3997 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
3998 NTSTATUS status
= NT_STATUS_OK
;
3999 enum perm_type ptype
;
4000 files_struct
*all_fsps
= NULL
;
4001 bool modify_mtime
= true;
4003 SMB_STRUCT_STAT sbuf
;
4005 if (!CAN_WRITE(conn
)) {
4006 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
4009 init_smb_file_time(&ft
);
4011 if (total_data
< 100) {
4012 return NT_STATUS_INVALID_PARAMETER
;
4015 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
4016 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
4017 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
4018 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
4021 ft
.atime
= pull_long_date_full_timespec(pdata
+24); /* access_time */
4022 ft
.mtime
= pull_long_date_full_timespec(pdata
+32); /* modification_time */
4023 set_owner
= (uid_t
)IVAL(pdata
,40);
4024 set_grp
= (gid_t
)IVAL(pdata
,48);
4025 raw_unixmode
= IVAL(pdata
,84);
4027 if (VALID_STAT(smb_fname
->st
)) {
4028 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
4029 ptype
= PERM_EXISTING_DIR
;
4031 ptype
= PERM_EXISTING_FILE
;
4034 ptype
= PERM_NEW_FILE
;
4037 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
4039 if (!NT_STATUS_IS_OK(status
)) {
4043 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
4044 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4045 smb_fname_str_dbg(smb_fname
), (double)size
,
4046 (unsigned int)set_owner
, (unsigned int)set_grp
,
4047 (int)raw_unixmode
));
4049 sbuf
= smb_fname
->st
;
4051 if (!VALID_STAT(sbuf
)) {
4053 * The only valid use of this is to create character and block
4054 * devices, and named pipes. This is deprecated (IMHO) and
4055 * a new info level should be used for mknod. JRA.
4058 return smb_unix_mknod(conn
,
4065 /* Horrible backwards compatibility hack as an old server bug
4066 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
4070 size
= get_file_size_stat(&sbuf
);
4075 * Deal with the UNIX specific mode set.
4078 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
4081 if (fsp
== NULL
|| S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
4082 DBG_WARNING("Can't set mode on symlink %s\n",
4083 smb_fname_str_dbg(smb_fname
));
4084 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4087 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4088 "setting mode 0%o for file %s\n",
4089 (unsigned int)unixmode
,
4090 smb_fname_str_dbg(smb_fname
)));
4091 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
4093 return map_nt_error_from_unix(errno
);
4098 * Deal with the UNIX specific uid set.
4101 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
4102 (sbuf
.st_ex_uid
!= set_owner
)) {
4105 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4106 "changing owner %u for path %s\n",
4107 (unsigned int)set_owner
,
4108 smb_fname_str_dbg(smb_fname
)));
4111 !fsp
->fsp_flags
.is_pathref
&&
4112 fsp_get_io_fd(fsp
) != -1)
4114 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
4117 * UNIX extensions calls must always operate
4120 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
,
4121 set_owner
, (gid_t
)-1);
4125 status
= map_nt_error_from_unix(errno
);
4131 * Deal with the UNIX specific gid set.
4134 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
4135 (sbuf
.st_ex_gid
!= set_grp
)) {
4138 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4139 "changing group %u for file %s\n",
4140 (unsigned int)set_grp
,
4141 smb_fname_str_dbg(smb_fname
)));
4143 !fsp
->fsp_flags
.is_pathref
&&
4144 fsp_get_io_fd(fsp
) != -1)
4146 ret
= SMB_VFS_FCHOWN(fsp
, (uid_t
)-1, set_grp
);
4149 * UNIX extensions calls must always operate
4152 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
, (uid_t
)-1,
4156 status
= map_nt_error_from_unix(errno
);
4161 /* Deal with any size changes. */
4163 if (S_ISREG(sbuf
.st_ex_mode
)) {
4164 status
= smb_set_file_size(conn
, req
,
4170 if (!NT_STATUS_IS_OK(status
)) {
4175 /* Deal with any time changes. */
4176 if (is_omit_timespec(&ft
.mtime
) && is_omit_timespec(&ft
.atime
)) {
4177 /* No change, don't cancel anything. */
4181 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4182 for(all_fsps
= file_find_di_first(conn
->sconn
, id
, true); all_fsps
;
4183 all_fsps
= file_find_di_next(all_fsps
, true)) {
4185 * We're setting the time explicitly for UNIX.
4186 * Cancel any pending changes over all handles.
4188 all_fsps
->fsp_flags
.update_write_time_on_close
= false;
4189 TALLOC_FREE(all_fsps
->update_write_time_event
);
4193 * Override the "setting_write_time"
4194 * parameter here as it almost does what
4195 * we need. Just remember if we modified
4196 * mtime and send the notify ourselves.
4198 if (is_omit_timespec(&ft
.mtime
)) {
4199 modify_mtime
= false;
4202 status
= smb_set_file_time(conn
,
4208 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
4209 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
4214 /****************************************************************************
4215 Deal with SMB_SET_FILE_UNIX_INFO2.
4216 ****************************************************************************/
4218 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
4219 struct smb_request
*req
,
4223 struct smb_filename
*smb_fname
)
4226 uint32_t smb_fflags
;
4229 if (!CAN_WRITE(conn
)) {
4230 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
4233 if (total_data
< 116) {
4234 return NT_STATUS_INVALID_PARAMETER
;
4237 /* Start by setting all the fields that are common between UNIX_BASIC
4240 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
4242 if (!NT_STATUS_IS_OK(status
)) {
4246 smb_fflags
= IVAL(pdata
, 108);
4247 smb_fmask
= IVAL(pdata
, 112);
4249 /* NB: We should only attempt to alter the file flags if the client
4250 * sends a non-zero mask.
4252 if (smb_fmask
!= 0) {
4253 int stat_fflags
= 0;
4255 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
4256 smb_fmask
, &stat_fflags
)) {
4257 /* Client asked to alter a flag we don't understand. */
4258 return NT_STATUS_INVALID_PARAMETER
;
4261 if (fsp
== NULL
|| S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
4262 DBG_WARNING("Can't change flags on symlink %s\n",
4263 smb_fname_str_dbg(smb_fname
));
4264 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4266 if (SMB_VFS_FCHFLAGS(fsp
, stat_fflags
) != 0) {
4267 return map_nt_error_from_unix(errno
);
4271 /* XXX: need to add support for changing the create_time here. You
4272 * can do this for paths on Darwin with setattrlist(2). The right way
4273 * to hook this up is probably by extending the VFS utimes interface.
4276 return NT_STATUS_OK
;
4279 /****************************************************************************
4280 Deal with SMB_SET_POSIX_ACL.
4281 ****************************************************************************/
4283 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
4284 struct smb_request
*req
,
4288 struct smb_filename
*smb_fname
)
4290 #if !defined(HAVE_POSIX_ACLS)
4291 return NT_STATUS_INVALID_LEVEL
;
4293 uint16_t posix_acl_version
;
4294 uint16_t num_file_acls
;
4295 uint16_t num_def_acls
;
4296 bool valid_file_acls
= true;
4297 bool valid_def_acls
= true;
4299 unsigned int size_needed
;
4300 unsigned int total_data
;
4301 bool close_fsp
= false;
4303 if (total_data_in
< 0) {
4304 status
= NT_STATUS_INVALID_PARAMETER
;
4308 total_data
= total_data_in
;
4310 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
4311 status
= NT_STATUS_INVALID_PARAMETER
;
4314 posix_acl_version
= SVAL(pdata
,0);
4315 num_file_acls
= SVAL(pdata
,2);
4316 num_def_acls
= SVAL(pdata
,4);
4318 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
4319 valid_file_acls
= false;
4323 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
4324 valid_def_acls
= false;
4328 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
4329 status
= NT_STATUS_INVALID_PARAMETER
;
4334 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
4335 status
= NT_STATUS_INVALID_PARAMETER
;
4339 size_needed
= num_file_acls
+ num_def_acls
;
4342 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4343 * than UINT_MAX, so check by division.
4345 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
4346 status
= NT_STATUS_INVALID_PARAMETER
;
4350 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
4351 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
4352 status
= NT_STATUS_INVALID_PARAMETER
;
4355 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
4357 if (total_data
< size_needed
) {
4358 status
= NT_STATUS_INVALID_PARAMETER
;
4363 * Ensure we always operate on a file descriptor, not just
4366 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
4367 uint32_t access_mask
= SEC_STD_WRITE_OWNER
|
4369 SEC_STD_READ_CONTROL
|
4370 FILE_READ_ATTRIBUTES
|
4371 FILE_WRITE_ATTRIBUTES
;
4373 status
= get_posix_fsp(conn
,
4379 if (!NT_STATUS_IS_OK(status
)) {
4385 /* Here we know fsp != NULL */
4386 SMB_ASSERT(fsp
!= NULL
);
4388 status
= refuse_symlink_fsp(fsp
);
4389 if (!NT_STATUS_IS_OK(status
)) {
4393 /* If we have a default acl, this *must* be a directory. */
4394 if (valid_def_acls
&& !fsp
->fsp_flags
.is_directory
) {
4395 DBG_INFO("Can't set default acls on "
4396 "non-directory %s\n",
4398 return NT_STATUS_INVALID_HANDLE
;
4401 DBG_DEBUG("file %s num_file_acls = %"PRIu16
", "
4402 "num_def_acls = %"PRIu16
"\n",
4407 /* Move pdata to the start of the file ACL entries. */
4408 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
4410 if (valid_file_acls
) {
4411 status
= set_unix_posix_acl(conn
,
4415 if (!NT_STATUS_IS_OK(status
)) {
4420 /* Move pdata to the start of the default ACL entries. */
4421 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
4423 if (valid_def_acls
) {
4424 status
= set_unix_posix_default_acl(conn
,
4428 if (!NT_STATUS_IS_OK(status
)) {
4433 status
= NT_STATUS_OK
;
4438 (void)close_file_free(req
, &fsp
, NORMAL_CLOSE
);
4444 static void call_trans2setpathinfo(
4445 connection_struct
*conn
,
4446 struct smb_request
*req
,
4451 unsigned int max_data_bytes
)
4453 uint16_t info_level
;
4454 struct smb_filename
*smb_fname
= NULL
;
4455 struct files_struct
*dirfsp
= NULL
;
4456 struct files_struct
*fsp
= NULL
;
4457 char *params
= *pparams
;
4458 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4461 bool info_level_handled
;
4462 int data_return_size
= 0;
4465 if (params
== NULL
) {
4466 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4471 if (total_params
< 7) {
4472 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4476 info_level
= SVAL(params
,0);
4478 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4479 if (!lp_smb1_unix_extensions()) {
4480 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4483 if (!req
->posix_pathnames
) {
4484 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4489 if (req
->posix_pathnames
) {
4490 srvstr_get_path_posix(req
,
4499 srvstr_get_path(req
,
4508 if (!NT_STATUS_IS_OK(status
)) {
4509 reply_nterror(req
, status
);
4513 DBG_NOTICE("fname=%s info_level=%d totdata=%d\n",
4518 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4519 extract_snapshot_token(fname
, &twrp
);
4521 status
= smb1_strip_dfs_path(req
, &ucf_flags
, &fname
);
4522 if (!NT_STATUS_IS_OK(status
)) {
4523 reply_nterror(req
, status
);
4526 status
= filename_convert_dirfsp(req
,
4533 if (!NT_STATUS_IS_OK(status
)) {
4534 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
4535 reply_botherror(req
,
4536 NT_STATUS_PATH_NOT_COVERED
,
4537 ERRSRV
, ERRbadpath
);
4540 reply_nterror(req
, status
);
4544 info_level_handled
= true; /* Untouched in switch cases below */
4546 switch (info_level
) {
4549 info_level_handled
= false;
4552 case SMB_POSIX_PATH_OPEN
:
4553 status
= smb_posix_open(
4562 case SMB_POSIX_PATH_UNLINK
:
4563 status
= smb_posix_unlink(
4564 conn
, req
, *ppdata
, total_data
, smb_fname
);
4567 case SMB_SET_FILE_UNIX_LINK
:
4568 status
= smb_set_file_unix_link(
4569 conn
, req
, *ppdata
, total_data
, smb_fname
);
4572 case SMB_SET_FILE_UNIX_HLINK
:
4573 status
= smb_set_file_unix_hlink(
4574 conn
, req
, *ppdata
, total_data
, smb_fname
);
4577 case SMB_SET_FILE_UNIX_BASIC
:
4578 status
= smb_set_file_unix_basic(
4587 case SMB_SET_FILE_UNIX_INFO2
:
4588 status
= smb_set_file_unix_info2(
4596 case SMB_SET_POSIX_ACL
:
4597 status
= smb_set_posix_acl(
4598 conn
, req
, *ppdata
, total_data
, NULL
, smb_fname
);
4602 if (info_level_handled
) {
4603 handle_trans2setfilepathinfo_result(
4615 * smb_fname->fsp may be NULL if smb_fname points at a symlink
4616 * and we're in POSIX context, so be careful when using fsp
4617 * below, it can still be NULL.
4619 fsp
= smb_fname
->fsp
;
4621 status
= smbd_do_setfilepathinfo(
4632 handle_trans2setfilepathinfo_result(
4642 static void call_trans2setfileinfo(
4643 connection_struct
*conn
,
4644 struct smb_request
*req
,
4649 unsigned int max_data_bytes
)
4651 char *pdata
= *ppdata
;
4652 uint16_t info_level
;
4653 struct smb_filename
*smb_fname
= NULL
;
4654 struct files_struct
*fsp
= NULL
;
4655 char *params
= *pparams
;
4656 int data_return_size
= 0;
4657 bool info_level_handled
;
4661 if (params
== NULL
) {
4662 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4665 if (total_params
< 4) {
4666 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4670 fsp
= file_fsp(req
, SVAL(params
,0));
4671 /* Basic check for non-null fsp. */
4672 if (!check_fsp_open(conn
, req
, fsp
)) {
4675 info_level
= SVAL(params
,2);
4677 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4678 if (!lp_smb1_unix_extensions()) {
4679 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4682 if (!req
->posix_pathnames
) {
4683 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4688 smb_fname
= fsp
->fsp_name
;
4690 DBG_NOTICE("fnum=%s fname=%s info_level=%d totdata=%d\n",
4696 if (fsp_get_pathref_fd(fsp
) == -1) {
4698 * This is actually a SETFILEINFO on a directory
4699 * handle (returned from an NT SMB). NT5.0 seems
4700 * to do this call. JRA.
4702 ret
= vfs_stat(conn
, smb_fname
);
4704 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
4705 smb_fname_str_dbg(smb_fname
),
4707 reply_nterror(req
, map_nt_error_from_unix(errno
));
4710 } else if (fsp
->print_file
) {
4712 * Doing a DELETE_ON_CLOSE should cancel a print job.
4714 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) &&
4717 fsp
->fsp_flags
.delete_on_close
= true;
4719 DBG_NOTICE("Cancelling print job (%s)\n",
4723 send_trans2_replies(
4733 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
4738 * Original code - this is an open file.
4740 status
= vfs_stat_fsp(fsp
);
4741 if (!NT_STATUS_IS_OK(status
)) {
4742 DBG_NOTICE("fstat of %s failed (%s)\n",
4745 reply_nterror(req
, status
);
4750 info_level_handled
= true; /* Untouched in switch cases below */
4752 switch (info_level
) {
4755 info_level_handled
= false;
4758 case SMB_SET_FILE_UNIX_BASIC
:
4759 status
= smb_set_file_unix_basic(
4760 conn
, req
, pdata
, total_data
, fsp
, smb_fname
);
4763 case SMB_SET_FILE_UNIX_INFO2
:
4764 status
= smb_set_file_unix_info2(
4765 conn
, req
, pdata
, total_data
, fsp
, smb_fname
);
4768 case SMB_SET_POSIX_LOCK
:
4769 status
= smb_set_posix_lock(
4770 conn
, req
, *ppdata
, total_data
, fsp
);
4774 if (info_level_handled
) {
4775 handle_trans2setfilepathinfo_result(
4786 status
= smbd_do_setfilepathinfo(
4797 handle_trans2setfilepathinfo_result(
4807 /****************************************************************************
4808 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4809 ****************************************************************************/
4811 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
4812 char **pparams
, int total_params
,
4813 char **ppdata
, int total_data
,
4814 unsigned int max_data_bytes
)
4816 struct files_struct
*dirfsp
= NULL
;
4817 struct files_struct
*fsp
= NULL
;
4818 struct smb_filename
*smb_dname
= NULL
;
4819 char *params
= *pparams
;
4820 char *pdata
= *ppdata
;
4821 char *directory
= NULL
;
4822 NTSTATUS status
= NT_STATUS_OK
;
4823 struct ea_list
*ea_list
= NULL
;
4824 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4826 TALLOC_CTX
*ctx
= talloc_tos();
4828 if (!CAN_WRITE(conn
)) {
4829 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4833 if (total_params
< 5) {
4834 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4838 if (req
->posix_pathnames
) {
4839 srvstr_get_path_posix(ctx
,
4848 srvstr_get_path(ctx
,
4857 if (!NT_STATUS_IS_OK(status
)) {
4858 reply_nterror(req
, status
);
4862 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
4864 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4865 extract_snapshot_token(directory
, &twrp
);
4867 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &directory
);
4868 if (!NT_STATUS_IS_OK(status
)) {
4869 reply_nterror(req
, status
);
4872 status
= filename_convert_dirfsp(ctx
,
4879 if (!NT_STATUS_IS_OK(status
)) {
4880 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
4881 reply_botherror(req
,
4882 NT_STATUS_PATH_NOT_COVERED
,
4883 ERRSRV
, ERRbadpath
);
4886 reply_nterror(req
, status
);
4891 * OS/2 workplace shell seems to send SET_EA requests of "null"
4892 * length (4 bytes containing IVAL 4).
4893 * They seem to have no effect. Bug #3212. JRA.
4896 if (total_data
&& (total_data
!= 4)) {
4897 /* Any data in this call is an EA list. */
4898 if (total_data
< 10) {
4899 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4903 if (IVAL(pdata
,0) > total_data
) {
4904 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4905 IVAL(pdata
,0), (unsigned int)total_data
));
4906 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4910 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
4913 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4917 if (!lp_ea_support(SNUM(conn
))) {
4918 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
4922 /* If total_data == 4 Windows doesn't care what values
4923 * are placed in that field, it just ignores them.
4924 * The System i QNTC IBM SMB client puts bad values here,
4925 * so ignore them. */
4927 status
= SMB_VFS_CREATE_FILE(
4930 dirfsp
, /* dirfsp */
4931 smb_dname
, /* fname */
4932 MAXIMUM_ALLOWED_ACCESS
, /* access_mask */
4933 FILE_SHARE_NONE
, /* share_access */
4934 FILE_CREATE
, /* create_disposition*/
4935 FILE_DIRECTORY_FILE
, /* create_options */
4936 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
4937 0, /* oplock_request */
4939 0, /* allocation_size */
4940 0, /* private_flags */
4945 NULL
, NULL
); /* create context */
4946 if (!NT_STATUS_IS_OK(status
)) {
4947 reply_nterror(req
, status
);
4951 /* Try and set any given EA. */
4953 status
= set_ea(conn
, fsp
, ea_list
);
4954 if (!NT_STATUS_IS_OK(status
)) {
4955 reply_nterror(req
, status
);
4960 /* Realloc the parameter and data sizes */
4961 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4962 if(*pparams
== NULL
) {
4963 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4970 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
4974 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
4976 TALLOC_FREE(smb_dname
);
4980 /****************************************************************************
4981 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4982 We don't actually do this - we just send a null response.
4983 ****************************************************************************/
4985 static void call_trans2findnotifyfirst(connection_struct
*conn
,
4986 struct smb_request
*req
,
4987 char **pparams
, int total_params
,
4988 char **ppdata
, int total_data
,
4989 unsigned int max_data_bytes
)
4991 char *params
= *pparams
;
4992 uint16_t info_level
;
4994 if (total_params
< 6) {
4995 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4999 info_level
= SVAL(params
,4);
5000 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
5002 switch (info_level
) {
5007 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5011 /* Realloc the parameter and data sizes */
5012 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
5013 if (*pparams
== NULL
) {
5014 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5019 SSVAL(params
,0,fnf_handle
);
5020 SSVAL(params
,2,0); /* No changes */
5021 SSVAL(params
,4,0); /* No EA errors */
5028 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
5033 /****************************************************************************
5034 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
5035 changes). Currently this does nothing.
5036 ****************************************************************************/
5038 static void call_trans2findnotifynext(connection_struct
*conn
,
5039 struct smb_request
*req
,
5040 char **pparams
, int total_params
,
5041 char **ppdata
, int total_data
,
5042 unsigned int max_data_bytes
)
5044 char *params
= *pparams
;
5046 DEBUG(3,("call_trans2findnotifynext\n"));
5048 /* Realloc the parameter and data sizes */
5049 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
5050 if (*pparams
== NULL
) {
5051 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5056 SSVAL(params
,0,0); /* No changes */
5057 SSVAL(params
,2,0); /* No EA errors */
5059 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
5064 /****************************************************************************
5065 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5066 ****************************************************************************/
5068 static void call_trans2getdfsreferral(connection_struct
*conn
,
5069 struct smb_request
*req
,
5070 char **pparams
, int total_params
,
5071 char **ppdata
, int total_data
,
5072 unsigned int max_data_bytes
)
5074 char *params
= *pparams
;
5075 char *pathname
= NULL
;
5077 int max_referral_level
;
5078 NTSTATUS status
= NT_STATUS_OK
;
5079 TALLOC_CTX
*ctx
= talloc_tos();
5081 DEBUG(10,("call_trans2getdfsreferral\n"));
5083 if (!IS_IPC(conn
)) {
5084 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5088 if (total_params
< 3) {
5089 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5093 max_referral_level
= SVAL(params
,0);
5095 if(!lp_host_msdfs()) {
5096 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
5100 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
5101 total_params
- 2, STR_TERMINATE
);
5103 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
5106 reply_size
= setup_dfs_referral(
5107 conn
, pathname
, max_referral_level
, ppdata
, &status
);
5108 if (reply_size
< 0) {
5109 reply_nterror(req
, status
);
5113 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
5114 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
5115 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
5120 #define LMCAT_SPL 0x53
5121 #define LMFUNC_GETJOBID 0x60
5123 /****************************************************************************
5124 Reply to a TRANS2_IOCTL - used for OS/2 printing.
5125 ****************************************************************************/
5127 static void call_trans2ioctl(connection_struct
*conn
,
5128 struct smb_request
*req
,
5129 char **pparams
, int total_params
,
5130 char **ppdata
, int total_data
,
5131 unsigned int max_data_bytes
)
5133 const struct loadparm_substitution
*lp_sub
=
5134 loadparm_s3_global_substitution();
5135 char *pdata
= *ppdata
;
5136 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
5140 /* check for an invalid fid before proceeding */
5143 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5147 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
5148 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
5149 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
5150 if (*ppdata
== NULL
) {
5151 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5156 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5157 CAN ACCEPT THIS IN UNICODE. JRA. */
5160 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
5162 status
= srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
5163 lp_netbios_name(), 15,
5164 STR_ASCII
|STR_TERMINATE
, &len
); /* Our NetBIOS name */
5165 if (!NT_STATUS_IS_OK(status
)) {
5166 reply_nterror(req
, status
);
5169 status
= srvstr_push(pdata
, req
->flags2
, pdata
+18,
5170 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)), 13,
5171 STR_ASCII
|STR_TERMINATE
, &len
); /* Service name */
5172 if (!NT_STATUS_IS_OK(status
)) {
5173 reply_nterror(req
, status
);
5176 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
5181 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5182 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
5185 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
5186 struct trans_state
*state
)
5188 struct smbXsrv_connection
*xconn
= req
->xconn
;
5190 if (xconn
->protocol
>= PROTOCOL_NT1
) {
5191 req
->flags2
|= 0x40; /* IS_LONG_NAME */
5192 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
5195 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
5196 if (state
->call
!= TRANSACT2_QFSINFO
&&
5197 state
->call
!= TRANSACT2_SETFSINFO
) {
5198 DEBUG(0,("handle_trans2: encryption required "
5200 (unsigned int)state
->call
));
5201 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5206 /* Now we must call the relevant TRANS2 function */
5207 switch(state
->call
) {
5208 case TRANSACT2_OPEN
:
5210 START_PROFILE(Trans2_open
);
5211 call_trans2open(conn
, req
,
5212 &state
->param
, state
->total_param
,
5213 &state
->data
, state
->total_data
,
5214 state
->max_data_return
);
5215 END_PROFILE(Trans2_open
);
5219 case TRANSACT2_FINDFIRST
:
5221 START_PROFILE(Trans2_findfirst
);
5222 call_trans2findfirst(conn
, req
,
5223 &state
->param
, state
->total_param
,
5224 &state
->data
, state
->total_data
,
5225 state
->max_data_return
);
5226 END_PROFILE(Trans2_findfirst
);
5230 case TRANSACT2_FINDNEXT
:
5232 START_PROFILE(Trans2_findnext
);
5233 call_trans2findnext(conn
, req
,
5234 &state
->param
, state
->total_param
,
5235 &state
->data
, state
->total_data
,
5236 state
->max_data_return
);
5237 END_PROFILE(Trans2_findnext
);
5241 case TRANSACT2_QFSINFO
:
5243 START_PROFILE(Trans2_qfsinfo
);
5244 call_trans2qfsinfo(conn
, req
,
5245 &state
->param
, state
->total_param
,
5246 &state
->data
, state
->total_data
,
5247 state
->max_data_return
);
5248 END_PROFILE(Trans2_qfsinfo
);
5252 case TRANSACT2_SETFSINFO
:
5254 START_PROFILE(Trans2_setfsinfo
);
5255 call_trans2setfsinfo(conn
, req
,
5256 &state
->param
, state
->total_param
,
5257 &state
->data
, state
->total_data
,
5258 state
->max_data_return
);
5259 END_PROFILE(Trans2_setfsinfo
);
5263 case TRANSACT2_QPATHINFO
:
5265 START_PROFILE(Trans2_qpathinfo
);
5266 call_trans2qpathinfo(
5273 state
->max_data_return
);
5274 END_PROFILE(Trans2_qpathinfo
);
5278 case TRANSACT2_QFILEINFO
:
5280 START_PROFILE(Trans2_qfileinfo
);
5281 call_trans2qfileinfo(
5288 state
->max_data_return
);
5289 END_PROFILE(Trans2_qfileinfo
);
5293 case TRANSACT2_SETPATHINFO
:
5295 START_PROFILE(Trans2_setpathinfo
);
5296 call_trans2setpathinfo(
5303 state
->max_data_return
);
5304 END_PROFILE(Trans2_setpathinfo
);
5308 case TRANSACT2_SETFILEINFO
:
5310 START_PROFILE(Trans2_setfileinfo
);
5311 call_trans2setfileinfo(
5318 state
->max_data_return
);
5319 END_PROFILE(Trans2_setfileinfo
);
5323 case TRANSACT2_FINDNOTIFYFIRST
:
5325 START_PROFILE(Trans2_findnotifyfirst
);
5326 call_trans2findnotifyfirst(conn
, req
,
5327 &state
->param
, state
->total_param
,
5328 &state
->data
, state
->total_data
,
5329 state
->max_data_return
);
5330 END_PROFILE(Trans2_findnotifyfirst
);
5334 case TRANSACT2_FINDNOTIFYNEXT
:
5336 START_PROFILE(Trans2_findnotifynext
);
5337 call_trans2findnotifynext(conn
, req
,
5338 &state
->param
, state
->total_param
,
5339 &state
->data
, state
->total_data
,
5340 state
->max_data_return
);
5341 END_PROFILE(Trans2_findnotifynext
);
5345 case TRANSACT2_MKDIR
:
5347 START_PROFILE(Trans2_mkdir
);
5348 call_trans2mkdir(conn
, req
,
5349 &state
->param
, state
->total_param
,
5350 &state
->data
, state
->total_data
,
5351 state
->max_data_return
);
5352 END_PROFILE(Trans2_mkdir
);
5356 case TRANSACT2_GET_DFS_REFERRAL
:
5358 START_PROFILE(Trans2_get_dfs_referral
);
5359 call_trans2getdfsreferral(conn
, req
,
5360 &state
->param
, state
->total_param
,
5361 &state
->data
, state
->total_data
,
5362 state
->max_data_return
);
5363 END_PROFILE(Trans2_get_dfs_referral
);
5367 case TRANSACT2_IOCTL
:
5369 START_PROFILE(Trans2_ioctl
);
5370 call_trans2ioctl(conn
, req
,
5371 &state
->param
, state
->total_param
,
5372 &state
->data
, state
->total_data
,
5373 state
->max_data_return
);
5374 END_PROFILE(Trans2_ioctl
);
5379 /* Error in request */
5380 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
5381 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
5385 /****************************************************************************
5386 Reply to a SMBtrans2.
5387 ****************************************************************************/
5389 void reply_trans2(struct smb_request
*req
)
5391 connection_struct
*conn
= req
->conn
;
5396 unsigned int tran_call
;
5397 struct trans_state
*state
;
5400 START_PROFILE(SMBtrans2
);
5402 if (req
->wct
< 14) {
5403 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5404 END_PROFILE(SMBtrans2
);
5408 dsoff
= SVAL(req
->vwv
+12, 0);
5409 dscnt
= SVAL(req
->vwv
+11, 0);
5410 psoff
= SVAL(req
->vwv
+10, 0);
5411 pscnt
= SVAL(req
->vwv
+9, 0);
5412 tran_call
= SVAL(req
->vwv
+14, 0);
5414 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
5415 if (!NT_STATUS_IS_OK(result
)) {
5416 DEBUG(2, ("Got invalid trans2 request: %s\n",
5417 nt_errstr(result
)));
5418 reply_nterror(req
, result
);
5419 END_PROFILE(SMBtrans2
);
5424 switch (tran_call
) {
5425 /* List the allowed trans2 calls on IPC$ */
5426 case TRANSACT2_OPEN
:
5427 case TRANSACT2_GET_DFS_REFERRAL
:
5428 case TRANSACT2_QFILEINFO
:
5429 case TRANSACT2_QFSINFO
:
5430 case TRANSACT2_SETFSINFO
:
5433 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5434 END_PROFILE(SMBtrans2
);
5439 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
5440 DEBUG(0, ("talloc failed\n"));
5441 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5442 END_PROFILE(SMBtrans2
);
5446 state
->cmd
= SMBtrans2
;
5448 state
->mid
= req
->mid
;
5449 state
->vuid
= req
->vuid
;
5450 state
->setup_count
= SVAL(req
->vwv
+13, 0);
5451 state
->setup
= NULL
;
5452 state
->total_param
= SVAL(req
->vwv
+0, 0);
5453 state
->param
= NULL
;
5454 state
->total_data
= SVAL(req
->vwv
+1, 0);
5456 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
5457 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
5458 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
5459 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
5460 state
->one_way
= BITSETW(req
->vwv
+5, 1);
5462 state
->call
= tran_call
;
5464 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5465 is so as a sanity check */
5466 if (state
->setup_count
!= 1) {
5468 * Need to have rc=0 for ioctl to get job id for OS/2.
5469 * Network printing will fail if function is not successful.
5470 * Similar function in reply.c will be used if protocol
5471 * is LANMAN1.0 instead of LM1.2X002.
5472 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5473 * outbuf doesn't have to be set(only job id is used).
5475 if ( (state
->setup_count
== 4)
5476 && (tran_call
== TRANSACT2_IOCTL
)
5477 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
5478 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
5479 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5481 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
5482 DEBUG(2,("Transaction is %d\n",tran_call
));
5484 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5485 END_PROFILE(SMBtrans2
);
5490 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
5493 if (state
->total_data
) {
5495 if (smb_buffer_oob(state
->total_data
, 0, dscnt
)
5496 || smb_buffer_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
5500 /* Can't use talloc here, the core routines do realloc on the
5501 * params and data. */
5502 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
5503 if (state
->data
== NULL
) {
5504 DEBUG(0,("reply_trans2: data malloc fail for %u "
5505 "bytes !\n", (unsigned int)state
->total_data
));
5507 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5508 END_PROFILE(SMBtrans2
);
5512 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
5515 if (state
->total_param
) {
5517 if (smb_buffer_oob(state
->total_param
, 0, pscnt
)
5518 || smb_buffer_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
5522 /* Can't use talloc here, the core routines do realloc on the
5523 * params and data. */
5524 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
5525 if (state
->param
== NULL
) {
5526 DEBUG(0,("reply_trans: param malloc fail for %u "
5527 "bytes !\n", (unsigned int)state
->total_param
));
5528 SAFE_FREE(state
->data
);
5530 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5531 END_PROFILE(SMBtrans2
);
5535 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
5538 state
->received_data
= dscnt
;
5539 state
->received_param
= pscnt
;
5541 if ((state
->received_param
== state
->total_param
) &&
5542 (state
->received_data
== state
->total_data
)) {
5544 handle_trans2(conn
, req
, state
);
5546 SAFE_FREE(state
->data
);
5547 SAFE_FREE(state
->param
);
5549 END_PROFILE(SMBtrans2
);
5553 DLIST_ADD(conn
->pending_trans
, state
);
5555 /* We need to send an interim response then receive the rest
5556 of the parameter/data bytes */
5557 reply_smb1_outbuf(req
, 0, 0);
5558 show_msg((char *)req
->outbuf
);
5559 END_PROFILE(SMBtrans2
);
5564 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5565 SAFE_FREE(state
->data
);
5566 SAFE_FREE(state
->param
);
5568 END_PROFILE(SMBtrans2
);
5569 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5572 /****************************************************************************
5573 Reply to a SMBtranss2
5574 ****************************************************************************/
5576 void reply_transs2(struct smb_request
*req
)
5578 connection_struct
*conn
= req
->conn
;
5579 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
5580 struct trans_state
*state
;
5582 START_PROFILE(SMBtranss2
);
5584 show_msg((const char *)req
->inbuf
);
5586 /* Windows clients expect all replies to
5587 a transact secondary (SMBtranss2 0x33)
5588 to have a command code of transact
5589 (SMBtrans2 0x32). See bug #8989
5590 and also [MS-CIFS] section 2.2.4.47.2
5593 req
->cmd
= SMBtrans2
;
5596 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5597 END_PROFILE(SMBtranss2
);
5601 for (state
= conn
->pending_trans
; state
!= NULL
;
5602 state
= state
->next
) {
5603 if (state
->mid
== req
->mid
) {
5608 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
5609 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5610 END_PROFILE(SMBtranss2
);
5614 /* Revise state->total_param and state->total_data in case they have
5615 changed downwards */
5617 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
5618 state
->total_param
= SVAL(req
->vwv
+0, 0);
5619 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
5620 state
->total_data
= SVAL(req
->vwv
+1, 0);
5622 pcnt
= SVAL(req
->vwv
+2, 0);
5623 poff
= SVAL(req
->vwv
+3, 0);
5624 pdisp
= SVAL(req
->vwv
+4, 0);
5626 dcnt
= SVAL(req
->vwv
+5, 0);
5627 doff
= SVAL(req
->vwv
+6, 0);
5628 ddisp
= SVAL(req
->vwv
+7, 0);
5630 state
->received_param
+= pcnt
;
5631 state
->received_data
+= dcnt
;
5633 if ((state
->received_data
> state
->total_data
) ||
5634 (state
->received_param
> state
->total_param
))
5638 if (smb_buffer_oob(state
->total_param
, pdisp
, pcnt
)
5639 || smb_buffer_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
5642 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
5646 if (smb_buffer_oob(state
->total_data
, ddisp
, dcnt
)
5647 || smb_buffer_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
5650 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
5653 if ((state
->received_param
< state
->total_param
) ||
5654 (state
->received_data
< state
->total_data
)) {
5655 END_PROFILE(SMBtranss2
);
5659 handle_trans2(conn
, req
, state
);
5661 DLIST_REMOVE(conn
->pending_trans
, state
);
5662 SAFE_FREE(state
->data
);
5663 SAFE_FREE(state
->param
);
5666 END_PROFILE(SMBtranss2
);
5671 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5672 DLIST_REMOVE(conn
->pending_trans
, state
);
5673 SAFE_FREE(state
->data
);
5674 SAFE_FREE(state
->param
);
5676 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5677 END_PROFILE(SMBtranss2
);