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"
49 #include "source3/smbd/dir.h"
51 #define DIR_ENTRY_SAFETY_MARGIN 4096
53 /****************************************************************************
54 Send the required number of replies back.
55 We assume all fields other than the data fields are
56 set correctly for the type of call.
57 HACK ! Always assumes smb_setup field is zero.
58 ****************************************************************************/
60 static void send_trans2_replies(connection_struct
*conn
,
61 struct smb_request
*req
,
69 /* As we are using a protocol > LANMAN1 then the max_send
70 variable must have been set in the sessetupX call.
71 This takes precedence over the max_xmit field in the
72 global struct. These different max_xmit variables should
73 be merged as this is now too confusing */
75 int data_to_send
= datasize
;
76 int params_to_send
= paramsize
;
78 const char *pp
= params
;
79 const char *pd
= pdata
;
80 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
81 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
82 int data_alignment_offset
= 0;
83 bool overflow
= False
;
84 struct smbXsrv_connection
*xconn
= req
->xconn
;
85 int max_send
= xconn
->smb1
.sessions
.max_send
;
87 /* Modify the data_to_send and datasize and set the error if
88 we're trying to send more than max_data_bytes. We still send
89 the part of the packet(s) that fit. Strange, but needed
92 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
93 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
94 max_data_bytes
, datasize
));
95 datasize
= data_to_send
= max_data_bytes
;
99 /* If there genuinely are no parameters or data to send just send the empty packet */
101 if(params_to_send
== 0 && data_to_send
== 0) {
102 reply_smb1_outbuf(req
, 10, 0);
103 if (NT_STATUS_V(status
)) {
106 ntstatus_to_dos(status
, &eclass
, &ecode
);
107 error_packet_set((char *)req
->outbuf
,
108 eclass
, ecode
, status
,
111 show_msg((char *)req
->outbuf
);
112 if (!smb1_srv_send(xconn
,
116 IS_CONN_ENCRYPTED(conn
))) {
117 exit_server_cleanly("send_trans2_replies: smb1_srv_send failed.");
119 TALLOC_FREE(req
->outbuf
);
123 /* When sending params and data ensure that both are nicely aligned */
124 /* Only do this alignment when there is also data to send - else
125 can cause NT redirector problems. */
127 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
128 data_alignment_offset
= 4 - (params_to_send
% 4);
130 /* Space is bufsize minus Netbios over TCP header minus SMB header */
131 /* The alignment_offset is to align the param bytes on an even byte
132 boundary. NT 4.0 Beta needs this to work correctly. */
134 useable_space
= max_send
- (smb_size
137 + data_alignment_offset
);
139 if (useable_space
< 0) {
140 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
141 "= %d!!!\n", useable_space
));
142 exit_server_cleanly("send_trans2_replies: Not enough space");
145 while (params_to_send
|| data_to_send
) {
146 /* Calculate whether we will totally or partially fill this packet */
148 total_sent_thistime
= params_to_send
+ data_to_send
;
150 /* We can never send more than useable_space */
152 * Note that 'useable_space' does not include the alignment offsets,
153 * but we must include the alignment offsets in the calculation of
154 * the length of the data we send over the wire, as the alignment offsets
155 * are sent here. Fix from Marc_Jacobsen@hp.com.
158 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
160 reply_smb1_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
161 + data_alignment_offset
);
163 /* Set total params and data to be sent */
164 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
165 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
167 /* Calculate how many parameters and data we can fit into
168 * this packet. Parameters get precedence
171 params_sent_thistime
= MIN(params_to_send
,useable_space
);
172 data_sent_thistime
= useable_space
- params_sent_thistime
;
173 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
175 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
177 /* smb_proff is the offset from the start of the SMB header to the
178 parameter bytes, however the first 4 bytes of outbuf are
179 the Netbios over TCP header. Thus use smb_base() to subtract
180 them from the calculation */
182 SSVAL(req
->outbuf
,smb_proff
,
183 ((smb_buf(req
->outbuf
)+alignment_offset
)
184 - smb_base(req
->outbuf
)));
186 if(params_sent_thistime
== 0)
187 SSVAL(req
->outbuf
,smb_prdisp
,0);
189 /* Absolute displacement of param bytes sent in this packet */
190 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
192 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
193 if(data_sent_thistime
== 0) {
194 SSVAL(req
->outbuf
,smb_droff
,0);
195 SSVAL(req
->outbuf
,smb_drdisp
, 0);
197 /* The offset of the data bytes is the offset of the
198 parameter bytes plus the number of parameters being sent this time */
199 SSVAL(req
->outbuf
, smb_droff
,
200 ((smb_buf(req
->outbuf
)+alignment_offset
)
201 - smb_base(req
->outbuf
))
202 + params_sent_thistime
+ data_alignment_offset
);
203 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
206 /* Initialize the padding for alignment */
208 if (alignment_offset
!= 0) {
209 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
212 /* Copy the param bytes into the packet */
214 if(params_sent_thistime
) {
215 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
216 params_sent_thistime
);
219 /* Copy in the data bytes */
220 if(data_sent_thistime
) {
221 if (data_alignment_offset
!= 0) {
222 memset((smb_buf(req
->outbuf
)+alignment_offset
+
223 params_sent_thistime
), 0,
224 data_alignment_offset
);
226 memcpy(smb_buf(req
->outbuf
)+alignment_offset
227 +params_sent_thistime
+data_alignment_offset
,
228 pd
,data_sent_thistime
);
231 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
232 params_sent_thistime
, data_sent_thistime
, useable_space
));
233 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
234 params_to_send
, data_to_send
, paramsize
, datasize
));
237 error_packet_set((char *)req
->outbuf
,
238 ERRDOS
,ERRbufferoverflow
,
239 STATUS_BUFFER_OVERFLOW
,
241 } else if (NT_STATUS_V(status
)) {
244 ntstatus_to_dos(status
, &eclass
, &ecode
);
245 error_packet_set((char *)req
->outbuf
,
246 eclass
, ecode
, status
,
250 /* Send the packet */
251 show_msg((char *)req
->outbuf
);
252 if (!smb1_srv_send(xconn
,
256 IS_CONN_ENCRYPTED(conn
))) {
257 exit_server_cleanly("send_trans2_replies: smb1_srv_send failed.");
260 TALLOC_FREE(req
->outbuf
);
262 pp
+= params_sent_thistime
;
263 pd
+= data_sent_thistime
;
265 params_to_send
-= params_sent_thistime
;
266 data_to_send
-= data_sent_thistime
;
269 if(params_to_send
< 0 || data_to_send
< 0) {
270 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
271 params_to_send
, data_to_send
));
279 /****************************************************************************
280 Deal with SMB_SET_POSIX_LOCK.
281 ****************************************************************************/
283 static void smb_set_posix_lock_done(struct tevent_req
*subreq
);
285 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
286 struct smb_request
*req
,
291 struct tevent_req
*subreq
= NULL
;
292 struct smbd_lock_element
*lck
= NULL
;
296 bool blocking_lock
= False
;
297 enum brl_type lock_type
;
299 NTSTATUS status
= NT_STATUS_OK
;
301 if (!CAN_WRITE(conn
)) {
302 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
306 fsp
->fsp_flags
.is_pathref
||
307 fsp_get_io_fd(fsp
) == -1)
309 return NT_STATUS_INVALID_HANDLE
;
312 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
313 return NT_STATUS_INVALID_PARAMETER
;
316 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
317 case POSIX_LOCK_TYPE_READ
:
318 lock_type
= READ_LOCK
;
320 case POSIX_LOCK_TYPE_WRITE
:
321 /* Return the right POSIX-mappable error code for files opened read-only. */
322 if (!fsp
->fsp_flags
.can_write
) {
323 return NT_STATUS_INVALID_HANDLE
;
325 lock_type
= WRITE_LOCK
;
327 case POSIX_LOCK_TYPE_UNLOCK
:
328 lock_type
= UNLOCK_LOCK
;
331 return NT_STATUS_INVALID_PARAMETER
;
334 switch (SVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
)) {
335 case POSIX_LOCK_FLAG_NOWAIT
:
336 blocking_lock
= false;
338 case POSIX_LOCK_FLAG_WAIT
:
339 blocking_lock
= true;
342 return NT_STATUS_INVALID_PARAMETER
;
345 if (!lp_blocking_locks(SNUM(conn
))) {
346 blocking_lock
= False
;
349 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
350 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
351 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
352 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
353 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
355 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64
", "
356 "count = %"PRIu64
", offset = %"PRIu64
"\n",
358 (unsigned int)lock_type
,
363 if (lock_type
== UNLOCK_LOCK
) {
364 struct smbd_lock_element l
= {
365 .req_guid
= smbd_request_guid(req
, 0),
367 .brltype
= UNLOCK_LOCK
,
368 .lock_flav
= POSIX_LOCK
,
372 status
= smbd_do_unlocking(req
, fsp
, 1, &l
);
376 lck
= talloc(req
, struct smbd_lock_element
);
378 return NT_STATUS_NO_MEMORY
;
381 *lck
= (struct smbd_lock_element
) {
382 .req_guid
= smbd_request_guid(req
, 0),
384 .brltype
= lock_type
,
385 .lock_flav
= POSIX_LOCK
,
390 subreq
= smbd_smb1_do_locks_send(
395 blocking_lock
? UINT32_MAX
: 0,
396 true, /* large_offset */
399 if (subreq
== NULL
) {
401 return NT_STATUS_NO_MEMORY
;
403 tevent_req_set_callback(subreq
, smb_set_posix_lock_done
, req
);
404 return NT_STATUS_EVENT_PENDING
;
407 static void smb_set_posix_lock_done(struct tevent_req
*subreq
)
409 struct smb_request
*req
= NULL
;
413 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
416 status
= smbd_smb1_do_locks_recv(subreq
);
419 if (NT_STATUS_IS_OK(status
)) {
420 char params
[2] = {0};
421 /* Fake up max_data_bytes here - we know it fits. */
432 reply_nterror(req
, status
);
433 ok
= smb1_srv_send(req
->xconn
,
437 IS_CONN_ENCRYPTED(req
->conn
));
439 exit_server_cleanly("smb_set_posix_lock_done: "
440 "smb1_srv_send failed.");
448 /****************************************************************************
449 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
450 ****************************************************************************/
452 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
454 struct ea_list
*ea_list_head
= NULL
;
455 size_t converted_size
, offset
= 0;
457 while (offset
+ 2 < data_size
) {
458 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
459 unsigned int namelen
= CVAL(pdata
,offset
);
461 offset
++; /* Go past the namelen byte. */
463 /* integer wrap paranioa. */
464 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
465 (offset
> data_size
) || (namelen
> data_size
) ||
466 (offset
+ namelen
>= data_size
)) {
469 /* Ensure the name is null terminated. */
470 if (pdata
[offset
+ namelen
] != '\0') {
473 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
475 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
476 "failed: %s\n", strerror(errno
)));
482 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
483 DLIST_ADD_END(ea_list_head
, eal
);
484 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
490 /****************************************************************************
491 Reply to a TRANSACT2_OPEN.
492 ****************************************************************************/
494 static void call_trans2open(connection_struct
*conn
,
495 struct smb_request
*req
,
496 char **pparams
, int total_params
,
497 char **ppdata
, int total_data
,
498 unsigned int max_data_bytes
)
500 struct smb_filename
*smb_fname
= NULL
;
501 char *params
= *pparams
;
502 char *pdata
= *ppdata
;
507 bool return_additional_info
;
519 struct files_struct
*dirfsp
= NULL
;
521 struct ea_list
*ea_list
= NULL
;
524 uint32_t access_mask
;
526 uint32_t create_disposition
;
527 uint32_t create_options
= 0;
528 uint32_t private_flags
= 0;
530 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
531 TALLOC_CTX
*ctx
= talloc_tos();
534 * Ensure we have enough parameters to perform the operation.
537 if (total_params
< 29) {
538 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
542 flags
= SVAL(params
, 0);
543 deny_mode
= SVAL(params
, 2);
544 open_attr
= SVAL(params
,6);
545 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
546 if (oplock_request
) {
547 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
551 return_additional_info
= BITSETW(params
,0);
552 open_sattr
= SVAL(params
, 4);
553 open_time
= make_unix_date3(params
+8);
555 open_ofun
= SVAL(params
,12);
556 open_size
= IVAL(params
,14);
560 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
564 if (req
->posix_pathnames
) {
565 srvstr_get_path_posix(ctx
,
583 if (!NT_STATUS_IS_OK(status
)) {
584 reply_nterror(req
, status
);
588 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
589 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
590 (unsigned int)open_ofun
, open_size
));
592 if (ucf_flags
& UCF_GMT_PATHNAME
) {
593 extract_snapshot_token(fname
, &twrp
);
595 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &fname
);
596 if (!NT_STATUS_IS_OK(status
)) {
597 reply_nterror(req
, status
);
600 status
= filename_convert_dirfsp(ctx
,
607 if (!NT_STATUS_IS_OK(status
)) {
608 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
610 NT_STATUS_PATH_NOT_COVERED
,
614 reply_nterror(req
, status
);
618 if (open_ofun
== 0) {
619 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
623 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
625 &access_mask
, &share_mode
,
629 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
633 /* Any data in this call is an EA list. */
634 if (total_data
&& (total_data
!= 4)) {
635 if (total_data
< 10) {
636 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
640 if (IVAL(pdata
,0) > total_data
) {
641 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
642 IVAL(pdata
,0), (unsigned int)total_data
));
643 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
647 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
650 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
654 if (!lp_ea_support(SNUM(conn
))) {
655 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
659 if (!req
->posix_pathnames
&&
660 ea_list_has_invalid_name(ea_list
)) {
662 *pparams
= (char *)SMB_REALLOC(*pparams
, param_len
);
663 if(*pparams
== NULL
) {
664 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
668 memset(params
, '\0', param_len
);
669 send_trans2_replies(conn
, req
, STATUS_INVALID_EA_NAME
,
670 params
, param_len
, NULL
, 0, max_data_bytes
);
675 status
= SMB_VFS_CREATE_FILE(
679 smb_fname
, /* fname */
680 access_mask
, /* access_mask */
681 share_mode
, /* share_access */
682 create_disposition
, /* create_disposition*/
683 create_options
, /* create_options */
684 open_attr
, /* file_attributes */
685 oplock_request
, /* oplock_request */
687 open_size
, /* allocation_size */
690 ea_list
, /* ea_list */
692 &smb_action
, /* psbuf */
693 NULL
, NULL
); /* create context */
695 if (!NT_STATUS_IS_OK(status
)) {
696 if (open_was_deferred(req
->xconn
, req
->mid
)) {
697 /* We have re-scheduled this call. */
701 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
702 reply_openerror(req
, status
);
706 fsp
= fcb_or_dos_open(
713 bool ok
= defer_smb1_sharing_violation(req
);
717 reply_openerror(req
, status
);
721 smb_action
= FILE_WAS_OPENED
;
724 size
= get_file_size_stat(&smb_fname
->st
);
725 fattr
= fdos_mode(fsp
);
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_ts(params
, 4, smb_fname
->st
.st_ex_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
->fsp_flags
.posix_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
,
1686 if (!NT_STATUS_IS_OK(status
)) {
1687 reply_nterror(req
, status
);
1691 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
1694 DEBUG( 4, ( "%s info_level = %d\n",
1695 smb_fn_name(req
->cmd
), info_level
) );
1700 /****************************************************************************
1701 Reply to a TRANS2_SETFSINFO (set filesystem info).
1702 ****************************************************************************/
1704 static void call_trans2setfsinfo(connection_struct
*conn
,
1705 struct smb_request
*req
,
1706 char **pparams
, int total_params
,
1707 char **ppdata
, int total_data
,
1708 unsigned int max_data_bytes
)
1710 const struct loadparm_substitution
*lp_sub
=
1711 loadparm_s3_global_substitution();
1712 struct smbXsrv_connection
*xconn
= req
->xconn
;
1713 char *pdata
= *ppdata
;
1714 char *params
= *pparams
;
1715 uint16_t info_level
;
1717 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
1718 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
1721 if (total_params
< 4) {
1722 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1724 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1728 info_level
= SVAL(params
,2);
1731 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
1732 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
1733 DEBUG(0,("call_trans2setfsinfo: not an allowed "
1734 "info level (0x%x) on IPC$.\n",
1735 (unsigned int)info_level
));
1736 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1741 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
1742 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
1743 DEBUG(0,("call_trans2setfsinfo: encryption required "
1744 "and info level 0x%x sent.\n",
1745 (unsigned int)info_level
));
1746 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1751 switch(info_level
) {
1752 case SMB_SET_CIFS_UNIX_INFO
:
1753 if (!lp_smb1_unix_extensions()) {
1754 DEBUG(2,("call_trans2setfsinfo: "
1755 "SMB_SET_CIFS_UNIX_INFO is invalid with "
1756 "unix extensions off\n"));
1758 NT_STATUS_INVALID_LEVEL
);
1762 /* There should be 12 bytes of capabilities set. */
1763 if (total_data
< 12) {
1766 NT_STATUS_INVALID_PARAMETER
);
1769 xconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
1770 xconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
1771 xconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
1772 xconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
1774 /* Just print these values for now. */
1775 DBG_DEBUG("set unix_info info. "
1776 "major = %"PRIu16
", minor = %"PRIu16
1777 "cap_low = 0x%"PRIx32
", "
1778 "cap_high = 0x%"PRIx32
"\n",
1779 xconn
->smb1
.unix_info
.client_major
,
1780 xconn
->smb1
.unix_info
.client_minor
,
1781 xconn
->smb1
.unix_info
.client_cap_low
,
1782 xconn
->smb1
.unix_info
.client_cap_high
);
1785 * Here is where we must switch to posix
1786 * pathname processing...
1788 if (xconn
->smb1
.unix_info
.client_cap_low
&
1789 CIFS_UNIX_POSIX_PATHNAMES_CAP
)
1791 lp_set_posix_pathnames();
1792 mangle_change_to_posix();
1795 if ((xconn
->smb1
.unix_info
.client_cap_low
&
1796 CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
1797 !(xconn
->smb1
.unix_info
.client_cap_low
&
1798 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
))
1800 /* Client that knows how to do posix locks,
1801 * but not posix open/mkdir operations. Set a
1802 * default type for read/write checks. */
1804 lp_set_posix_default_cifsx_readwrite_locktype(
1810 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
1813 size_t param_len
= 0;
1814 size_t data_len
= total_data
;
1816 if (!lp_smb1_unix_extensions()) {
1819 NT_STATUS_INVALID_LEVEL
);
1823 if (lp_server_smb_encrypt(SNUM(conn
)) ==
1824 SMB_ENCRYPTION_OFF
) {
1827 NT_STATUS_NOT_SUPPORTED
);
1831 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
1832 DEBUG( 2,("call_trans2setfsinfo: "
1833 "request transport encryption disabled"
1834 "with 'fork echo handler = yes'\n"));
1837 NT_STATUS_NOT_SUPPORTED
);
1841 DEBUG( 4,("call_trans2setfsinfo: "
1842 "request transport encryption.\n"));
1844 status
= srv_request_encryption_setup(conn
,
1845 (unsigned char **)ppdata
,
1847 (unsigned char **)pparams
,
1850 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
1851 !NT_STATUS_IS_OK(status
)) {
1852 reply_nterror(req
, status
);
1856 send_trans2_replies(conn
, req
,
1864 if (NT_STATUS_IS_OK(status
)) {
1865 /* Server-side transport
1866 * encryption is now *on*. */
1867 status
= srv_encryption_start(conn
);
1868 if (!NT_STATUS_IS_OK(status
)) {
1869 char *reason
= talloc_asprintf(talloc_tos(),
1870 "Failure in setting "
1871 "up encrypted transport: %s",
1873 exit_server_cleanly(reason
);
1879 case SMB_FS_QUOTA_INFORMATION
:
1883 .data
= (uint8_t *)pdata
,
1884 .length
= total_data
1886 files_struct
*fsp
= NULL
;
1887 fsp
= file_fsp(req
, SVAL(params
,0));
1889 status
= smb_set_fsquota(conn
,
1893 if (!NT_STATUS_IS_OK(status
)) {
1894 reply_nterror(req
, status
);
1900 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1902 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1908 * sending this reply works fine,
1909 * but I'm not sure it's the same
1910 * like windows do...
1913 reply_smb1_outbuf(req
, 10, 0);
1916 /****************************************************************************
1917 Reply to a TRANSACT2_QFILEINFO on a PIPE !
1918 ****************************************************************************/
1920 static void call_trans2qpipeinfo(connection_struct
*conn
,
1921 struct smb_request
*req
,
1923 uint16_t info_level
,
1924 unsigned int tran_call
,
1925 char **pparams
, int total_params
,
1926 char **ppdata
, int total_data
,
1927 unsigned int max_data_bytes
)
1929 char *params
= *pparams
;
1930 char *pdata
= *ppdata
;
1931 unsigned int data_size
= 0;
1932 unsigned int param_size
= 2;
1934 if (!fsp_is_np(fsp
)) {
1935 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1939 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
1940 if (*pparams
== NULL
) {
1941 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1946 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
1947 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1950 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
1951 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
1952 if (*ppdata
== NULL
) {
1953 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1958 switch (info_level
) {
1959 case SMB_FILE_STANDARD_INFORMATION
:
1961 SOFF_T(pdata
,0,4096LL);
1968 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1972 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
1976 static void handle_trans2qfilepathinfo_result(
1977 connection_struct
*conn
,
1978 struct smb_request
*req
,
1979 uint16_t info_level
,
1982 int data_return_size
,
1983 size_t fixed_portion
,
1984 unsigned int max_data_bytes
)
1986 char params
[2] = { 0, 0, };
1990 * draft-leach-cifs-v1-spec-02.txt
1991 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
1994 * The requested information is placed in the Data portion of the
1995 * transaction response. For the information levels greater than 0x100,
1996 * the transaction response has 1 parameter word which should be
1997 * ignored by the client.
1999 * However Windows only follows this rule for the IS_NAME_VALID call.
2001 switch (info_level
) {
2002 case SMB_INFO_IS_NAME_VALID
:
2007 if (!NT_STATUS_IS_OK(status
)) {
2008 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2009 /* We have re-scheduled this call. */
2012 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2013 bool ok
= defer_smb1_sharing_violation(req
);
2018 reply_nterror(req
, status
);
2022 if (fixed_portion
> max_data_bytes
) {
2023 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
2027 send_trans2_replies(
2038 /****************************************************************************
2039 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2040 file name or file id).
2041 ****************************************************************************/
2043 static void call_trans2qfilepathinfo(connection_struct
*conn
,
2044 struct smb_request
*req
,
2045 unsigned int tran_call
,
2046 uint16_t info_level
,
2047 struct smb_filename
*smb_fname
,
2048 struct files_struct
*fsp
,
2049 bool delete_pending
,
2050 struct timespec write_time_ts
,
2051 char **pparams
, int total_params
,
2052 char **ppdata
, int total_data
,
2053 unsigned int max_data_bytes
)
2055 char *params
= *pparams
;
2056 char *pdata
= *ppdata
;
2057 unsigned int data_size
= 0;
2058 struct ea_list
*ea_list
= NULL
;
2059 size_t fixed_portion
;
2060 NTSTATUS status
= NT_STATUS_OK
;
2062 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
2063 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
2065 info_level
,tran_call
,total_data
));
2067 /* Pull out any data sent here before we realloc. */
2068 switch (info_level
) {
2069 case SMB_INFO_QUERY_EAS_FROM_LIST
:
2071 /* Pull any EA list from the data portion. */
2074 if (total_data
< 4) {
2076 req
, NT_STATUS_INVALID_PARAMETER
);
2079 ea_size
= IVAL(pdata
,0);
2081 if (total_data
> 0 && ea_size
!= total_data
) {
2082 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2083 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2085 req
, NT_STATUS_INVALID_PARAMETER
);
2089 if (!lp_ea_support(SNUM(conn
))) {
2090 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2094 /* Pull out the list of names. */
2095 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
2098 req
, NT_STATUS_INVALID_PARAMETER
);
2108 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
2109 if (*pparams
== NULL
) {
2110 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2116 if ((info_level
& SMB2_INFO_SPECIAL
) == SMB2_INFO_SPECIAL
) {
2118 * We use levels that start with 0xFF00
2119 * internally to represent SMB2 specific levels
2121 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2125 status
= smbd_do_qfilepathinfo(conn
, req
, req
, info_level
,
2127 delete_pending
, write_time_ts
,
2129 req
->flags2
, max_data_bytes
,
2131 ppdata
, &data_size
);
2133 handle_trans2qfilepathinfo_result(
2144 static NTSTATUS
smb_q_unix_basic(
2145 struct connection_struct
*conn
,
2146 struct smb_request
*req
,
2147 struct smb_filename
*smb_fname
,
2148 struct files_struct
*fsp
,
2152 const int total_data
= 100;
2154 *ppdata
= SMB_REALLOC(*ppdata
, total_data
);
2155 if (*ppdata
== NULL
) {
2156 return NT_STATUS_NO_MEMORY
;
2158 store_file_unix_basic(conn
, *ppdata
, fsp
, &smb_fname
->st
);
2160 *ptotal_data
= total_data
;
2162 return NT_STATUS_OK
;
2165 static NTSTATUS
smb_q_unix_info2(
2166 struct connection_struct
*conn
,
2167 struct smb_request
*req
,
2168 struct smb_filename
*smb_fname
,
2169 struct files_struct
*fsp
,
2173 const int total_data
= 116;
2175 *ppdata
= SMB_REALLOC(*ppdata
, total_data
);
2176 if (*ppdata
== NULL
) {
2177 return NT_STATUS_NO_MEMORY
;
2179 store_file_unix_basic_info2(conn
, *ppdata
, fsp
, &smb_fname
->st
);
2181 *ptotal_data
= total_data
;
2183 return NT_STATUS_OK
;
2186 #if defined(HAVE_POSIX_ACLS)
2187 /****************************************************************************
2188 Utility function to open a fsp for a POSIX handle operation.
2189 ****************************************************************************/
2191 static NTSTATUS
get_posix_fsp(connection_struct
*conn
,
2192 struct smb_request
*req
,
2193 struct smb_filename
*smb_fname
,
2194 uint32_t access_mask
,
2195 files_struct
**ret_fsp
)
2198 uint32_t create_disposition
= FILE_OPEN
;
2199 uint32_t share_access
= FILE_SHARE_READ
|
2202 struct smb2_create_blobs
*posx
= NULL
;
2205 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
2206 * but set reasonable defaults.
2208 uint32_t file_attributes
= 0664;
2209 uint32_t oplock
= NO_OPLOCK
;
2210 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
2212 /* File or directory must exist. */
2213 if (!VALID_STAT(smb_fname
->st
)) {
2214 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
2216 /* Cannot be a symlink. */
2217 if (S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
2218 return NT_STATUS_ACCESS_DENIED
;
2220 /* Set options correctly for directory open. */
2221 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
2223 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
2224 * directories, but set reasonable defaults.
2226 file_attributes
= 0775;
2227 create_options
= FILE_DIRECTORY_FILE
;
2230 status
= make_smb2_posix_create_ctx(
2231 talloc_tos(), &posx
, file_attributes
);
2232 if (!NT_STATUS_IS_OK(status
)) {
2233 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
2238 status
= SMB_VFS_CREATE_FILE(
2242 smb_fname
, /* fname */
2243 access_mask
, /* access_mask */
2244 share_access
, /* share_access */
2245 create_disposition
,/* create_disposition*/
2246 create_options
, /* create_options */
2247 file_attributes
,/* file_attributes */
2248 oplock
, /* oplock_request */
2250 0, /* allocation_size */
2251 0, /* private_flags */
2254 ret_fsp
, /* result */
2256 posx
, /* in_context */
2257 NULL
); /* out_context */
2264 /****************************************************************************
2265 Utility function to count the number of entries in a POSIX acl.
2266 ****************************************************************************/
2268 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
2270 unsigned int ace_count
= 0;
2271 int entry_id
= SMB_ACL_FIRST_ENTRY
;
2272 SMB_ACL_ENTRY_T entry
;
2274 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
2275 entry_id
= SMB_ACL_NEXT_ENTRY
;
2281 /****************************************************************************
2282 Utility function to marshall a POSIX acl into wire format.
2283 ****************************************************************************/
2285 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
2287 int entry_id
= SMB_ACL_FIRST_ENTRY
;
2288 SMB_ACL_ENTRY_T entry
;
2290 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
2291 SMB_ACL_TAG_T tagtype
;
2292 SMB_ACL_PERMSET_T permset
;
2293 unsigned char perms
= 0;
2294 unsigned int own_grp
;
2296 entry_id
= SMB_ACL_NEXT_ENTRY
;
2298 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
2299 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2303 if (sys_acl_get_permset(entry
, &permset
) == -1) {
2304 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2308 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
2309 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
2310 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
2312 SCVAL(pdata
,1,perms
);
2315 case SMB_ACL_USER_OBJ
:
2316 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
2317 own_grp
= (unsigned int)pst
->st_ex_uid
;
2318 SIVAL(pdata
,2,own_grp
);
2323 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
2325 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2328 own_grp
= (unsigned int)*puid
;
2329 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
2330 SIVAL(pdata
,2,own_grp
);
2334 case SMB_ACL_GROUP_OBJ
:
2335 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
2336 own_grp
= (unsigned int)pst
->st_ex_gid
;
2337 SIVAL(pdata
,2,own_grp
);
2342 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
2344 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2347 own_grp
= (unsigned int)*pgid
;
2348 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
2349 SIVAL(pdata
,2,own_grp
);
2354 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
2355 SIVAL(pdata
,2,0xFFFFFFFF);
2356 SIVAL(pdata
,6,0xFFFFFFFF);
2359 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
2360 SIVAL(pdata
,2,0xFFFFFFFF);
2361 SIVAL(pdata
,6,0xFFFFFFFF);
2364 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2367 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
2374 static NTSTATUS
smb_q_posix_acl(
2375 struct connection_struct
*conn
,
2376 struct smb_request
*req
,
2377 struct smb_filename
*smb_fname
,
2378 struct files_struct
*fsp
,
2382 #if !defined(HAVE_POSIX_ACLS)
2383 return NT_STATUS_INVALID_LEVEL
;
2386 SMB_ACL_T file_acl
= NULL
;
2387 SMB_ACL_T def_acl
= NULL
;
2388 uint16_t num_file_acls
= 0;
2389 uint16_t num_def_acls
= 0;
2390 unsigned int size_needed
= 0;
2393 bool close_fsp
= false;
2396 * Ensure we always operate on a file descriptor, not just
2399 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
2400 uint32_t access_mask
= SEC_STD_READ_CONTROL
|
2401 FILE_READ_ATTRIBUTES
|
2402 FILE_WRITE_ATTRIBUTES
;
2404 status
= get_posix_fsp(conn
,
2410 if (!NT_STATUS_IS_OK(status
)) {
2416 SMB_ASSERT(fsp
!= NULL
);
2418 refuse
= refuse_symlink_fsp(fsp
);
2420 status
= NT_STATUS_ACCESS_DENIED
;
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 files_struct
*dirfsp
,
2534 struct smb_filename
*smb_fname
,
2538 char *target
= NULL
;
2543 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
2544 smb_fname_str_dbg(smb_fname
));
2546 if (!S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
2547 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
2550 if (fsp_get_pathref_fd(smb_fname
->fsp
) != -1) {
2552 * fsp is an O_PATH open, Linux does a "freadlink"
2553 * with an empty name argument to readlinkat
2555 status
= readlink_talloc(talloc_tos(),
2560 struct smb_filename smb_fname_rel
= *smb_fname
;
2563 slash
= strrchr_m(smb_fname
->base_name
, '/');
2564 if (slash
!= NULL
) {
2565 smb_fname_rel
.base_name
= slash
+ 1;
2567 status
= readlink_talloc(talloc_tos(),
2573 if (!NT_STATUS_IS_OK(status
)) {
2574 DBG_DEBUG("readlink_talloc() failed: %s\n", nt_errstr(status
));
2578 needed
= talloc_get_size(target
) * 2;
2580 *ppdata
= SMB_REALLOC(*ppdata
, needed
);
2581 if (*ppdata
== NULL
) {
2582 TALLOC_FREE(target
);
2583 return NT_STATUS_NO_MEMORY
;
2587 status
= srvstr_push(
2595 TALLOC_FREE(target
);
2596 if (!NT_STATUS_IS_OK(status
)) {
2601 return NT_STATUS_OK
;
2604 static void call_trans2qpathinfo(
2605 connection_struct
*conn
,
2606 struct smb_request
*req
,
2611 unsigned int max_data_bytes
)
2613 char *params
= *pparams
;
2614 uint16_t info_level
;
2615 struct smb_filename
*smb_fname
= NULL
;
2616 bool delete_pending
= False
;
2617 struct timespec write_time_ts
= { .tv_sec
= 0, };
2618 struct files_struct
*dirfsp
= NULL
;
2619 files_struct
*fsp
= NULL
;
2621 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
2623 bool info_level_handled
;
2624 NTSTATUS status
= NT_STATUS_OK
;
2627 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2633 if (total_params
< 7) {
2634 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2638 info_level
= SVAL(params
,0);
2640 DBG_NOTICE("TRANSACT2_QPATHINFO: level = %d\n", info_level
);
2642 if (INFO_LEVEL_IS_UNIX(info_level
)) {
2643 if (!lp_smb1_unix_extensions()) {
2644 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2647 if (!req
->posix_pathnames
) {
2648 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2653 if (req
->posix_pathnames
) {
2654 srvstr_get_path_posix(req
,
2663 srvstr_get_path(req
,
2672 if (!NT_STATUS_IS_OK(status
)) {
2673 reply_nterror(req
, status
);
2677 if (ucf_flags
& UCF_GMT_PATHNAME
) {
2678 extract_snapshot_token(fname
, &twrp
);
2680 status
= smb1_strip_dfs_path(req
, &ucf_flags
, &fname
);
2681 if (!NT_STATUS_IS_OK(status
)) {
2682 reply_nterror(req
, status
);
2685 status
= filename_convert_dirfsp(req
,
2692 if (!NT_STATUS_IS_OK(status
)) {
2693 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2694 reply_botherror(req
,
2695 NT_STATUS_PATH_NOT_COVERED
,
2696 ERRSRV
, ERRbadpath
);
2699 reply_nterror(req
, status
);
2704 * qpathinfo must operate on an existing file, so we
2705 * can exit early if filename_convert_dirfsp() returned the
2706 * "new file" NT_STATUS_OK, !VALID_STAT case.
2709 if (!VALID_STAT(smb_fname
->st
)) {
2710 reply_nterror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2714 fsp
= smb_fname
->fsp
;
2716 /* If this is a stream, check if there is a delete_pending. */
2717 if (fsp_is_alternate_stream(fsp
)) {
2719 struct files_struct
*base_fsp
= fsp
->base_fsp
;
2721 get_file_infos(base_fsp
->file_id
,
2722 base_fsp
->name_hash
,
2725 if (delete_pending
) {
2726 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
2731 if (fsp_getinfo_ask_sharemode(fsp
)) {
2732 get_file_infos(fsp
->file_id
,
2738 if (delete_pending
) {
2739 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
2743 info_level_handled
= true; /* Untouched in switch cases below */
2745 switch (info_level
) {
2748 info_level_handled
= false;
2751 case SMB_QUERY_FILE_UNIX_BASIC
:
2752 status
= smb_q_unix_basic(
2761 case SMB_QUERY_FILE_UNIX_INFO2
:
2762 status
= smb_q_unix_info2(
2771 case SMB_QUERY_POSIX_ACL
:
2772 status
= smb_q_posix_acl(
2781 case SMB_QUERY_FILE_UNIX_LINK
:
2782 status
= smb_q_posix_symlink(
2792 if (info_level_handled
) {
2793 handle_trans2qfilepathinfo_result(
2805 call_trans2qfilepathinfo(
2808 TRANSACT2_QPATHINFO
,
2821 static NTSTATUS
smb_q_posix_lock(
2822 struct connection_struct
*conn
,
2823 struct smb_request
*req
,
2824 struct files_struct
*fsp
,
2828 char *pdata
= *ppdata
;
2829 int total_data
= *ptotal_data
;
2833 enum brl_type lock_type
;
2836 if (fsp
->fsp_flags
.is_pathref
|| (fsp_get_io_fd(fsp
) == -1)) {
2837 return NT_STATUS_INVALID_HANDLE
;
2840 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
2841 return NT_STATUS_INVALID_PARAMETER
;
2844 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
2845 case POSIX_LOCK_TYPE_READ
:
2846 lock_type
= READ_LOCK
;
2848 case POSIX_LOCK_TYPE_WRITE
:
2849 lock_type
= WRITE_LOCK
;
2851 case POSIX_LOCK_TYPE_UNLOCK
:
2853 /* There's no point in asking for an unlock... */
2854 return NT_STATUS_INVALID_PARAMETER
;
2857 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
2858 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
2859 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
2861 status
= query_lock(
2869 if (NT_STATUS_IS_OK(status
)) {
2871 * For success we just return a copy of what we sent
2872 * with the lock type set to POSIX_LOCK_TYPE_UNLOCK.
2874 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
2875 return NT_STATUS_OK
;
2878 if (!ERROR_WAS_LOCK_DENIED(status
)) {
2879 DBG_DEBUG("query_lock() failed: %s\n", nt_errstr(status
));
2884 * Here we need to report who has it locked.
2887 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
2888 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
2889 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
2890 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
2891 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
2893 return NT_STATUS_OK
;
2896 static void call_trans2qfileinfo(
2897 connection_struct
*conn
,
2898 struct smb_request
*req
,
2903 unsigned int max_data_bytes
)
2905 char *params
= *pparams
;
2906 uint16_t info_level
;
2907 struct smb_filename
*smb_fname
= NULL
;
2908 bool delete_pending
= False
;
2909 struct timespec write_time_ts
= { .tv_sec
= 0, };
2910 files_struct
*fsp
= NULL
;
2911 struct file_id fileid
;
2912 bool info_level_handled
;
2913 NTSTATUS status
= NT_STATUS_OK
;
2916 if (params
== NULL
) {
2917 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2921 if (total_params
< 4) {
2922 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2926 fsp
= file_fsp(req
, SVAL(params
,0));
2927 info_level
= SVAL(params
,2);
2930 call_trans2qpipeinfo(
2935 TRANSACT2_QFILEINFO
,
2944 DBG_NOTICE("TRANSACT2_QFILEINFO: level = %d\n", info_level
);
2946 if (INFO_LEVEL_IS_UNIX(info_level
)) {
2947 if (!lp_smb1_unix_extensions()) {
2948 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2951 if (!req
->posix_pathnames
) {
2952 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2957 /* Initial check for valid fsp ptr. */
2958 if (!check_fsp_open(conn
, req
, fsp
)) {
2962 smb_fname
= fsp
->fsp_name
;
2964 if(fsp
->fake_file_handle
) {
2966 * This is actually for the QUOTA_FAKE_FILE --metze
2969 /* We know this name is ok, it's already passed the checks. */
2971 } else if(fsp_get_pathref_fd(fsp
) == -1) {
2973 * This is actually a QFILEINFO on a directory
2974 * handle (returned from an NT SMB). NT5.0 seems
2975 * to do this call. JRA.
2977 ret
= vfs_stat(conn
, smb_fname
);
2979 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
2980 smb_fname_str_dbg(smb_fname
),
2983 map_nt_error_from_unix(errno
));
2987 if (fsp_getinfo_ask_sharemode(fsp
)) {
2988 fileid
= vfs_file_id_from_sbuf(
2989 conn
, &smb_fname
->st
);
2990 get_file_infos(fileid
, fsp
->name_hash
,
2996 * Original code - this is an open file.
2998 status
= vfs_stat_fsp(fsp
);
2999 if (!NT_STATUS_IS_OK(status
)) {
3000 DEBUG(3, ("fstat of %s failed (%s)\n",
3001 fsp_fnum_dbg(fsp
), nt_errstr(status
)));
3002 reply_nterror(req
, status
);
3005 if (fsp_getinfo_ask_sharemode(fsp
)) {
3006 fileid
= vfs_file_id_from_sbuf(
3007 conn
, &smb_fname
->st
);
3008 get_file_infos(fileid
, fsp
->name_hash
,
3014 info_level_handled
= true; /* Untouched in switch cases below */
3016 switch (info_level
) {
3019 info_level_handled
= false;
3022 case SMB_QUERY_POSIX_LOCK
:
3023 status
= smb_q_posix_lock(conn
, req
, fsp
, ppdata
, &total_data
);
3026 case SMB_QUERY_FILE_UNIX_BASIC
:
3027 status
= smb_q_unix_basic(
3028 conn
, req
, fsp
->fsp_name
, fsp
, ppdata
, &total_data
);
3031 case SMB_QUERY_FILE_UNIX_INFO2
:
3032 status
= smb_q_unix_info2(
3033 conn
, req
, fsp
->fsp_name
, fsp
, ppdata
, &total_data
);
3036 case SMB_QUERY_POSIX_ACL
:
3037 status
= smb_q_posix_acl(
3038 conn
, req
, fsp
->fsp_name
, fsp
, ppdata
, &total_data
);
3042 if (info_level_handled
) {
3043 handle_trans2qfilepathinfo_result(
3055 call_trans2qfilepathinfo(
3058 TRANSACT2_QFILEINFO
,
3071 static void handle_trans2setfilepathinfo_result(
3072 connection_struct
*conn
,
3073 struct smb_request
*req
,
3074 uint16_t info_level
,
3077 int data_return_size
,
3078 unsigned int max_data_bytes
)
3080 char params
[2] = { 0, 0, };
3082 if (NT_STATUS_IS_OK(status
)) {
3083 send_trans2_replies(
3095 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3096 /* We have re-scheduled this call. */
3100 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
3101 bool ok
= defer_smb1_sharing_violation(req
);
3107 if (NT_STATUS_EQUAL(status
, NT_STATUS_EVENT_PENDING
)) {
3108 /* We have re-scheduled this call. */
3112 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3115 NT_STATUS_PATH_NOT_COVERED
,
3121 if (info_level
== SMB_POSIX_PATH_OPEN
) {
3122 reply_openerror(req
, status
);
3126 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
3128 * Invalid EA name needs to return 2 param bytes,
3129 * not a zero-length error packet.
3132 send_trans2_replies(
3144 reply_nterror(req
, status
);
3147 /****************************************************************************
3148 Create a directory with POSIX semantics.
3149 ****************************************************************************/
3151 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
3152 struct smb_request
*req
,
3155 struct smb_filename
*smb_fname
,
3156 int *pdata_return_size
)
3158 NTSTATUS status
= NT_STATUS_OK
;
3159 uint32_t raw_unixmode
= 0;
3160 mode_t unixmode
= (mode_t
)0;
3161 files_struct
*fsp
= NULL
;
3162 uint16_t info_level_return
= 0;
3164 char *pdata
= *ppdata
;
3165 struct smb2_create_blobs
*posx
= NULL
;
3167 if (total_data
< 18) {
3168 return NT_STATUS_INVALID_PARAMETER
;
3171 raw_unixmode
= IVAL(pdata
,8);
3172 /* Next 4 bytes are not yet defined. */
3174 status
= unix_perms_from_wire(conn
,
3178 if (!NT_STATUS_IS_OK(status
)) {
3181 unixmode
= apply_conf_dir_mask(conn
, unixmode
);
3183 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, unixmode
);
3184 if (!NT_STATUS_IS_OK(status
)) {
3185 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3190 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
3191 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
3193 status
= SMB_VFS_CREATE_FILE(
3197 smb_fname
, /* fname */
3198 FILE_READ_ATTRIBUTES
, /* access_mask */
3199 FILE_SHARE_NONE
, /* share_access */
3200 FILE_CREATE
, /* create_disposition*/
3201 FILE_DIRECTORY_FILE
, /* create_options */
3202 0, /* file_attributes */
3203 0, /* oplock_request */
3205 0, /* allocation_size */
3206 0, /* private_flags */
3211 posx
, /* in_context_blobs */
3212 NULL
); /* out_context_blobs */
3216 if (NT_STATUS_IS_OK(status
)) {
3217 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3220 info_level_return
= SVAL(pdata
,16);
3222 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
3223 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
3224 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
3225 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
3227 *pdata_return_size
= 12;
3230 /* Realloc the data size */
3231 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
3232 if (*ppdata
== NULL
) {
3233 *pdata_return_size
= 0;
3234 return NT_STATUS_NO_MEMORY
;
3238 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
3239 SSVAL(pdata
,2,0); /* No fnum. */
3240 SIVAL(pdata
,4,info
); /* Was directory created. */
3242 switch (info_level_return
) {
3243 case SMB_QUERY_FILE_UNIX_BASIC
:
3244 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
3245 SSVAL(pdata
,10,0); /* Padding. */
3246 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
3249 case SMB_QUERY_FILE_UNIX_INFO2
:
3250 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
3251 SSVAL(pdata
,10,0); /* Padding. */
3252 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
3256 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
3257 SSVAL(pdata
,10,0); /* Padding. */
3264 /****************************************************************************
3265 Open/Create a file with POSIX semantics.
3266 ****************************************************************************/
3268 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
3269 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
3271 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
3272 struct smb_request
*req
,
3275 struct files_struct
*dirfsp
,
3276 struct smb_filename
*smb_fname
,
3277 int *pdata_return_size
)
3279 bool extended_oplock_granted
= False
;
3280 char *pdata
= *ppdata
;
3282 uint32_t wire_open_mode
= 0;
3283 uint32_t raw_unixmode
= 0;
3284 uint32_t attributes
= 0;
3285 uint32_t create_disp
= 0;
3286 uint32_t access_mask
= 0;
3287 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
3288 NTSTATUS status
= NT_STATUS_OK
;
3289 mode_t unixmode
= (mode_t
)0;
3290 files_struct
*fsp
= NULL
;
3291 int oplock_request
= 0;
3293 uint16_t info_level_return
= 0;
3294 struct smb2_create_blobs
*posx
= NULL
;
3296 if (total_data
< 18) {
3297 return NT_STATUS_INVALID_PARAMETER
;
3300 flags
= IVAL(pdata
,0);
3301 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
3302 if (oplock_request
) {
3303 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
3306 wire_open_mode
= IVAL(pdata
,4);
3308 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
3309 return smb_posix_mkdir(conn
, req
,
3316 switch (wire_open_mode
& SMB_ACCMODE
) {
3318 access_mask
= SMB_O_RDONLY_MAPPING
;
3321 access_mask
= SMB_O_WRONLY_MAPPING
;
3324 access_mask
= (SMB_O_RDONLY_MAPPING
|
3325 SMB_O_WRONLY_MAPPING
);
3328 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
3329 (unsigned int)wire_open_mode
));
3330 return NT_STATUS_INVALID_PARAMETER
;
3333 wire_open_mode
&= ~SMB_ACCMODE
;
3335 /* First take care of O_CREAT|O_EXCL interactions. */
3336 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
3337 case (SMB_O_CREAT
| SMB_O_EXCL
):
3338 /* File exists fail. File not exist create. */
3339 create_disp
= FILE_CREATE
;
3342 /* File exists open. File not exist create. */
3343 create_disp
= FILE_OPEN_IF
;
3346 /* O_EXCL on its own without O_CREAT is undefined.
3347 We deliberately ignore it as some versions of
3348 Linux CIFSFS can send a bare O_EXCL on the
3349 wire which other filesystems in the kernel
3350 ignore. See bug 9519 for details. */
3355 /* File exists open. File not exist fail. */
3356 create_disp
= FILE_OPEN
;
3359 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
3360 (unsigned int)wire_open_mode
));
3361 return NT_STATUS_INVALID_PARAMETER
;
3364 /* Next factor in the effects of O_TRUNC. */
3365 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
3367 if (wire_open_mode
& SMB_O_TRUNC
) {
3368 switch (create_disp
) {
3370 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
3371 /* Leave create_disp alone as
3372 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
3374 /* File exists fail. File not exist create. */
3377 /* SMB_O_CREAT | SMB_O_TRUNC */
3378 /* File exists overwrite. File not exist create. */
3379 create_disp
= FILE_OVERWRITE_IF
;
3383 /* File exists overwrite. File not exist fail. */
3384 create_disp
= FILE_OVERWRITE
;
3387 /* Cannot get here. */
3388 smb_panic("smb_posix_open: logic error");
3389 return NT_STATUS_INVALID_PARAMETER
;
3393 raw_unixmode
= IVAL(pdata
,8);
3394 /* Next 4 bytes are not yet defined. */
3396 status
= unix_perms_from_wire(conn
,
3401 if (!NT_STATUS_IS_OK(status
)) {
3404 if (!VALID_STAT(smb_fname
->st
)) {
3405 unixmode
= apply_conf_dir_mask(conn
, unixmode
);
3408 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, unixmode
);
3409 if (!NT_STATUS_IS_OK(status
)) {
3410 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3415 if (wire_open_mode
& SMB_O_SYNC
) {
3416 create_options
|= FILE_WRITE_THROUGH
;
3418 if (wire_open_mode
& SMB_O_APPEND
) {
3419 access_mask
|= FILE_APPEND_DATA
;
3421 if (wire_open_mode
& SMB_O_DIRECT
) {
3423 * BUG: this doesn't work anymore since
3424 * e0814dc5082dd4ecca8a155e0ce24b073158fd92. But since
3425 * FILE_FLAG_NO_BUFFERING isn't used at all in the IO codepath,
3426 * it doesn't really matter.
3428 attributes
|= FILE_FLAG_NO_BUFFERING
;
3431 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
3432 VALID_STAT_OF_DIR(smb_fname
->st
)) {
3433 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
3434 return NT_STATUS_FILE_IS_A_DIRECTORY
;
3436 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
3437 create_options
|= FILE_DIRECTORY_FILE
;
3440 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
3441 smb_fname_str_dbg(smb_fname
),
3442 (unsigned int)wire_open_mode
,
3443 (unsigned int)unixmode
));
3445 status
= SMB_VFS_CREATE_FILE(
3448 dirfsp
, /* dirfsp */
3449 smb_fname
, /* fname */
3450 access_mask
, /* access_mask */
3451 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
3453 create_disp
, /* create_disposition*/
3454 create_options
, /* create_options */
3455 attributes
, /* file_attributes */
3456 oplock_request
, /* oplock_request */
3458 0, /* allocation_size */
3459 0, /* private_flags */
3464 posx
, /* in_context_blobs */
3465 NULL
); /* out_context_blobs */
3469 if (!NT_STATUS_IS_OK(status
)) {
3473 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
3474 extended_oplock_granted
= True
;
3477 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
3478 extended_oplock_granted
= True
;
3481 info_level_return
= SVAL(pdata
,16);
3483 /* Allocate the correct return size. */
3485 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
3486 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
3487 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
3488 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
3490 *pdata_return_size
= 12;
3493 /* Realloc the data size */
3494 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
3495 if (*ppdata
== NULL
) {
3496 close_file_free(req
, &fsp
, ERROR_CLOSE
);
3497 *pdata_return_size
= 0;
3498 return NT_STATUS_NO_MEMORY
;
3502 if (extended_oplock_granted
) {
3503 if (flags
& REQUEST_BATCH_OPLOCK
) {
3504 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
3506 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
3508 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
3509 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
3511 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
3514 SSVAL(pdata
,2,fsp
->fnum
);
3515 SIVAL(pdata
,4,info
); /* Was file created etc. */
3517 switch (info_level_return
) {
3518 case SMB_QUERY_FILE_UNIX_BASIC
:
3519 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
3520 SSVAL(pdata
,10,0); /* padding. */
3521 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
3524 case SMB_QUERY_FILE_UNIX_INFO2
:
3525 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
3526 SSVAL(pdata
,10,0); /* padding. */
3527 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
3531 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
3532 SSVAL(pdata
,10,0); /* padding. */
3535 return NT_STATUS_OK
;
3538 /****************************************************************************
3539 Delete a file with POSIX semantics.
3540 ****************************************************************************/
3542 struct smb_posix_unlink_state
{
3543 struct smb_filename
*smb_fname
;
3544 struct files_struct
*fsp
;
3548 static void smb_posix_unlink_locked(struct share_mode_lock
*lck
,
3551 struct smb_posix_unlink_state
*state
= private_data
;
3553 bool other_nonposix_opens
;
3555 other_nonposix_opens
= has_other_nonposix_opens(lck
, state
->fsp
);
3556 if (other_nonposix_opens
) {
3557 /* Fail with sharing violation. */
3558 state
->status
= NT_STATUS_SHARING_VIOLATION
;
3563 * Set the delete on close.
3565 state
->status
= smb_set_file_disposition_info(state
->fsp
->conn
,
3572 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
3573 struct smb_request
*req
,
3576 struct files_struct
*dirfsp
,
3577 struct smb_filename
*smb_fname
)
3579 struct smb_posix_unlink_state state
= {};
3580 NTSTATUS status
= NT_STATUS_OK
;
3581 files_struct
*fsp
= NULL
;
3584 int create_options
= FILE_OPEN_REPARSE_POINT
;
3585 struct smb2_create_blobs
*posx
= NULL
;
3587 if (!CAN_WRITE(conn
)) {
3588 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
3591 if (total_data
< 2) {
3592 return NT_STATUS_INVALID_PARAMETER
;
3595 flags
= SVAL(pdata
,0);
3597 if (!VALID_STAT(smb_fname
->st
)) {
3598 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3601 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
3602 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
3603 return NT_STATUS_NOT_A_DIRECTORY
;
3606 DEBUG(10,("smb_posix_unlink: %s %s\n",
3607 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
3608 smb_fname_str_dbg(smb_fname
)));
3610 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
3611 create_options
|= FILE_DIRECTORY_FILE
;
3614 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, 0777);
3615 if (!NT_STATUS_IS_OK(status
)) {
3616 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3621 status
= SMB_VFS_CREATE_FILE(
3624 dirfsp
, /* dirfsp */
3625 smb_fname
, /* fname */
3626 DELETE_ACCESS
, /* access_mask */
3627 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
3629 FILE_OPEN
, /* create_disposition*/
3630 create_options
, /* create_options */
3631 0, /* file_attributes */
3632 0, /* oplock_request */
3634 0, /* allocation_size */
3635 0, /* private_flags */
3640 posx
, /* in_context_blobs */
3641 NULL
); /* out_context_blobs */
3645 if (!NT_STATUS_IS_OK(status
)) {
3650 * Don't lie to client. If we can't really delete due to
3651 * non-POSIX opens return SHARING_VIOLATION.
3654 state
= (struct smb_posix_unlink_state
) {
3655 .smb_fname
= smb_fname
,
3659 status
= share_mode_do_locked_vfs_allowed(fsp
->file_id
,
3660 smb_posix_unlink_locked
,
3662 if (!NT_STATUS_IS_OK(status
)) {
3663 DBG_ERR("share_mode_do_locked_vfs_allowed(%s) failed - %s\n",
3664 fsp_str_dbg(fsp
), nt_errstr(status
));
3665 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3666 return NT_STATUS_INVALID_PARAMETER
;
3669 status
= state
.status
;
3670 if (!NT_STATUS_IS_OK(status
)) {
3671 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3674 return close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3677 /****************************************************************************
3678 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
3679 ****************************************************************************/
3681 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
3682 struct smb_request
*req
,
3685 struct files_struct
*dirfsp
,
3686 struct smb_filename
*new_smb_fname
)
3688 char *link_target
= NULL
;
3689 struct smb_filename target_fname
;
3690 TALLOC_CTX
*ctx
= talloc_tos();
3691 struct smb_filename new_smb_fname_rel
= {};
3696 if (!CAN_WRITE(conn
)) {
3697 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
3700 /* Set a symbolic link. */
3701 /* Don't allow this if follow links is false. */
3703 if (total_data
== 0) {
3704 return NT_STATUS_INVALID_PARAMETER
;
3707 if (!lp_follow_symlinks(SNUM(conn
))) {
3708 return NT_STATUS_ACCESS_DENIED
;
3711 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
3712 total_data
, STR_TERMINATE
);
3715 return NT_STATUS_INVALID_PARAMETER
;
3718 target_fname
= (struct smb_filename
) {
3719 .base_name
= link_target
,
3722 /* Removes @GMT tokens if any */
3723 status
= canonicalize_snapshot_path(&target_fname
, UCF_GMT_PATHNAME
, 0);
3724 if (!NT_STATUS_IS_OK(status
)) {
3728 DBG_DEBUG("SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3729 new_smb_fname
->base_name
, link_target
);
3731 new_smb_fname_rel
= *new_smb_fname
;
3732 slash
= strrchr_m(new_smb_fname_rel
.base_name
, '/');
3733 if (slash
!= NULL
) {
3734 new_smb_fname_rel
.base_name
= slash
+ 1;
3737 ret
= SMB_VFS_SYMLINKAT(conn
,
3740 &new_smb_fname_rel
);
3742 return map_nt_error_from_unix(errno
);
3745 return NT_STATUS_OK
;
3748 /****************************************************************************
3749 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
3750 ****************************************************************************/
3752 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
3753 struct smb_request
*req
,
3754 const char *pdata
, int total_data
,
3755 struct smb_filename
*smb_fname_new
)
3757 char *oldname
= NULL
;
3758 struct files_struct
*src_dirfsp
= NULL
;
3759 struct smb_filename
*smb_fname_old
= NULL
;
3760 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
3761 NTTIME old_twrp
= 0;
3762 TALLOC_CTX
*ctx
= talloc_tos();
3763 NTSTATUS status
= NT_STATUS_OK
;
3765 if (!CAN_WRITE(conn
)) {
3766 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
3769 /* Set a hard link. */
3770 if (total_data
== 0) {
3771 return NT_STATUS_INVALID_PARAMETER
;
3774 if (req
->posix_pathnames
) {
3775 srvstr_get_path_posix(ctx
,
3784 srvstr_get_path(ctx
,
3793 if (!NT_STATUS_IS_OK(status
)) {
3797 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3798 smb_fname_str_dbg(smb_fname_new
), oldname
));
3800 if (ucf_flags
& UCF_GMT_PATHNAME
) {
3801 extract_snapshot_token(oldname
, &old_twrp
);
3803 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &oldname
);
3804 if (!NT_STATUS_IS_OK(status
)) {
3807 status
= filename_convert_dirfsp(ctx
,
3814 if (!NT_STATUS_IS_OK(status
)) {
3818 return hardlink_internals(ctx
,
3826 /****************************************************************************
3827 Allow a UNIX info mknod.
3828 ****************************************************************************/
3830 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
3833 struct files_struct
*dirfsp
,
3834 const struct smb_filename
*smb_fname
)
3836 uint32_t file_type
= IVAL(pdata
,56);
3837 #if defined(HAVE_MAKEDEV)
3838 uint32_t dev_major
= IVAL(pdata
,60);
3839 uint32_t dev_minor
= IVAL(pdata
,68);
3841 SMB_DEV_T dev
= (SMB_DEV_T
)0;
3842 uint32_t raw_unixmode
= IVAL(pdata
,84);
3846 struct smb_filename
*parent_fname
= NULL
;
3847 struct smb_filename
*atname
= NULL
;
3849 if (total_data
< 100) {
3850 return NT_STATUS_INVALID_PARAMETER
;
3853 status
= unix_perms_from_wire(conn
,
3857 if (!NT_STATUS_IS_OK(status
)) {
3860 unixmode
= apply_conf_file_mask(conn
, unixmode
);
3862 #if defined(HAVE_MAKEDEV)
3863 dev
= makedev(dev_major
, dev_minor
);
3866 switch (file_type
) {
3867 /* We can't create other objects here. */
3868 case UNIX_TYPE_FILE
:
3870 case UNIX_TYPE_SYMLINK
:
3871 return NT_STATUS_ACCESS_DENIED
;
3872 #if defined(S_IFIFO)
3873 case UNIX_TYPE_FIFO
:
3874 unixmode
|= S_IFIFO
;
3877 #if defined(S_IFSOCK)
3878 case UNIX_TYPE_SOCKET
:
3879 unixmode
|= S_IFSOCK
;
3882 #if defined(S_IFCHR)
3883 case UNIX_TYPE_CHARDEV
:
3884 /* This is only allowed for root. */
3885 if (get_current_uid(conn
) != sec_initial_uid()) {
3886 return NT_STATUS_ACCESS_DENIED
;
3888 unixmode
|= S_IFCHR
;
3891 #if defined(S_IFBLK)
3892 case UNIX_TYPE_BLKDEV
:
3893 if (get_current_uid(conn
) != sec_initial_uid()) {
3894 return NT_STATUS_ACCESS_DENIED
;
3896 unixmode
|= S_IFBLK
;
3900 return NT_STATUS_INVALID_PARAMETER
;
3903 DBG_DEBUG("SMB_SET_FILE_UNIX_BASIC doing mknod dev "
3904 "%ju mode 0%o for file %s\n",
3906 (unsigned int)unixmode
,
3907 smb_fname_str_dbg(smb_fname
));
3909 status
= SMB_VFS_PARENT_PATHNAME(dirfsp
->conn
,
3914 if (!NT_STATUS_IS_OK(status
)) {
3918 /* Ok - do the mknod. */
3919 ret
= SMB_VFS_MKNODAT(conn
,
3926 TALLOC_FREE(parent_fname
);
3927 return map_nt_error_from_unix(errno
);
3930 /* If any of the other "set" calls fail we
3931 * don't want to end up with a half-constructed mknod.
3934 if (lp_inherit_permissions(SNUM(conn
))) {
3935 inherit_access_posix_acl(conn
,
3940 TALLOC_FREE(parent_fname
);
3942 return NT_STATUS_OK
;
3945 /****************************************************************************
3946 Deal with SMB_SET_FILE_UNIX_BASIC.
3947 ****************************************************************************/
3949 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
3950 struct smb_request
*req
,
3953 struct files_struct
*dirfsp
,
3955 struct smb_filename
*smb_fname
)
3957 struct smb_file_time ft
;
3958 uint32_t raw_unixmode
;
3961 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
3962 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
3963 NTSTATUS status
= NT_STATUS_OK
;
3964 files_struct
*all_fsps
= NULL
;
3965 bool modify_mtime
= true;
3967 SMB_STRUCT_STAT sbuf
;
3969 if (!CAN_WRITE(conn
)) {
3970 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
3973 init_smb_file_time(&ft
);
3975 if (total_data
< 100) {
3976 return NT_STATUS_INVALID_PARAMETER
;
3979 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
3980 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
3981 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
3982 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
3985 ft
.atime
= pull_long_date_full_timespec(pdata
+24); /* access_time */
3986 ft
.mtime
= pull_long_date_full_timespec(pdata
+32); /* modification_time */
3987 set_owner
= (uid_t
)IVAL(pdata
,40);
3988 set_grp
= (gid_t
)IVAL(pdata
,48);
3989 raw_unixmode
= IVAL(pdata
,84);
3991 status
= unix_perms_from_wire(conn
,
3995 if (!NT_STATUS_IS_OK(status
)) {
3998 if (!VALID_STAT(smb_fname
->st
)) {
3999 unixmode
= apply_conf_file_mask(conn
, unixmode
);
4002 DBG_DEBUG("SMB_SET_FILE_UNIX_BASIC: name = "
4003 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4004 smb_fname_str_dbg(smb_fname
),
4006 (unsigned int)set_owner
,
4007 (unsigned int)set_grp
,
4010 sbuf
= smb_fname
->st
;
4012 if (!VALID_STAT(sbuf
)) {
4014 * The only valid use of this is to create character and block
4015 * devices, and named pipes. This is deprecated (IMHO) and
4016 * a new info level should be used for mknod. JRA.
4019 if (dirfsp
== NULL
) {
4020 return NT_STATUS_INVALID_PARAMETER
;
4023 return smb_unix_mknod(conn
,
4031 /* Horrible backwards compatibility hack as an old server bug
4032 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
4036 size
= get_file_size_stat(&sbuf
);
4041 * Deal with the UNIX specific mode set.
4044 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
4047 if (fsp
== NULL
|| S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
4048 DBG_WARNING("Can't set mode on symlink %s\n",
4049 smb_fname_str_dbg(smb_fname
));
4050 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4053 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4054 "setting mode 0%o for file %s\n",
4055 (unsigned int)unixmode
,
4056 smb_fname_str_dbg(smb_fname
)));
4057 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
4059 return map_nt_error_from_unix(errno
);
4064 * Deal with the UNIX specific uid set.
4067 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
4068 (sbuf
.st_ex_uid
!= set_owner
)) {
4071 DBG_DEBUG("SMB_SET_FILE_UNIX_BASIC "
4072 "changing owner %u for path %s\n",
4073 (unsigned int)set_owner
,
4074 smb_fname_str_dbg(smb_fname
));
4077 !fsp
->fsp_flags
.is_pathref
&&
4078 fsp_get_io_fd(fsp
) != -1)
4080 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
4083 * UNIX extensions calls must always operate
4086 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
,
4087 set_owner
, (gid_t
)-1);
4091 status
= map_nt_error_from_unix(errno
);
4097 * Deal with the UNIX specific gid set.
4100 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
4101 (sbuf
.st_ex_gid
!= set_grp
)) {
4104 DBG_DEBUG("SMB_SET_FILE_UNIX_BASIC "
4105 "changing group %u for file %s\n",
4106 (unsigned int)set_grp
,
4107 smb_fname_str_dbg(smb_fname
));
4109 !fsp
->fsp_flags
.is_pathref
&&
4110 fsp_get_io_fd(fsp
) != -1)
4112 ret
= SMB_VFS_FCHOWN(fsp
, (uid_t
)-1, set_grp
);
4115 * UNIX extensions calls must always operate
4118 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
, (uid_t
)-1,
4122 status
= map_nt_error_from_unix(errno
);
4127 /* Deal with any size changes. */
4129 if (S_ISREG(sbuf
.st_ex_mode
)) {
4130 status
= smb_set_file_size(conn
, req
,
4136 if (!NT_STATUS_IS_OK(status
)) {
4141 /* Deal with any time changes. */
4142 if (is_omit_timespec(&ft
.mtime
) && is_omit_timespec(&ft
.atime
)) {
4143 /* No change, don't cancel anything. */
4147 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4148 for(all_fsps
= file_find_di_first(conn
->sconn
, id
, true); all_fsps
;
4149 all_fsps
= file_find_di_next(all_fsps
, true)) {
4151 * We're setting the time explicitly for UNIX.
4152 * Cancel any pending changes over all handles.
4154 all_fsps
->fsp_flags
.update_write_time_on_close
= false;
4155 TALLOC_FREE(all_fsps
->update_write_time_event
);
4159 * Override the "setting_write_time"
4160 * parameter here as it almost does what
4161 * we need. Just remember if we modified
4162 * mtime and send the notify ourselves.
4164 if (is_omit_timespec(&ft
.mtime
)) {
4165 modify_mtime
= false;
4168 status
= smb_set_file_time(conn
,
4175 NOTIFY_ACTION_MODIFIED
,
4176 FILE_NOTIFY_CHANGE_LAST_WRITE
,
4183 /****************************************************************************
4184 Deal with SMB_SET_FILE_UNIX_INFO2.
4185 ****************************************************************************/
4187 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
4188 struct smb_request
*req
,
4191 struct files_struct
*dirfsp
,
4193 struct smb_filename
*smb_fname
)
4196 uint32_t smb_fflags
;
4199 if (!CAN_WRITE(conn
)) {
4200 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
4203 if (total_data
< 116) {
4204 return NT_STATUS_INVALID_PARAMETER
;
4207 /* Start by setting all the fields that are common between UNIX_BASIC
4210 status
= smb_set_file_unix_basic(conn
,
4217 if (!NT_STATUS_IS_OK(status
)) {
4221 smb_fflags
= IVAL(pdata
, 108);
4222 smb_fmask
= IVAL(pdata
, 112);
4224 /* NB: We should only attempt to alter the file flags if the client
4225 * sends a non-zero mask.
4227 if (smb_fmask
!= 0) {
4228 int stat_fflags
= 0;
4230 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
4231 smb_fmask
, &stat_fflags
)) {
4232 /* Client asked to alter a flag we don't understand. */
4233 return NT_STATUS_INVALID_PARAMETER
;
4236 if (fsp
== NULL
|| S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
4237 DBG_WARNING("Can't change flags on symlink %s\n",
4238 smb_fname_str_dbg(smb_fname
));
4239 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4241 if (SMB_VFS_FCHFLAGS(fsp
, stat_fflags
) != 0) {
4242 return map_nt_error_from_unix(errno
);
4246 /* XXX: need to add support for changing the create_time here. You
4247 * can do this for paths on Darwin with setattrlist(2). The right way
4248 * to hook this up is probably by extending the VFS utimes interface.
4251 return NT_STATUS_OK
;
4254 /****************************************************************************
4255 Deal with SMB_SET_POSIX_ACL.
4256 ****************************************************************************/
4258 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
4259 struct smb_request
*req
,
4263 struct smb_filename
*smb_fname
)
4265 #if !defined(HAVE_POSIX_ACLS)
4266 return NT_STATUS_INVALID_LEVEL
;
4268 uint16_t posix_acl_version
;
4269 uint16_t num_file_acls
;
4270 uint16_t num_def_acls
;
4271 bool valid_file_acls
= true;
4272 bool valid_def_acls
= true;
4274 unsigned int size_needed
;
4275 unsigned int total_data
;
4276 bool close_fsp
= false;
4279 if (total_data_in
< 0) {
4280 status
= NT_STATUS_INVALID_PARAMETER
;
4284 total_data
= total_data_in
;
4286 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
4287 status
= NT_STATUS_INVALID_PARAMETER
;
4290 posix_acl_version
= SVAL(pdata
,0);
4291 num_file_acls
= SVAL(pdata
,2);
4292 num_def_acls
= SVAL(pdata
,4);
4294 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
4295 valid_file_acls
= false;
4299 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
4300 valid_def_acls
= false;
4304 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
4305 status
= NT_STATUS_INVALID_PARAMETER
;
4310 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
4311 status
= NT_STATUS_INVALID_PARAMETER
;
4315 size_needed
= num_file_acls
+ num_def_acls
;
4318 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4319 * than UINT_MAX, so check by division.
4321 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
4322 status
= NT_STATUS_INVALID_PARAMETER
;
4326 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
4327 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
4328 status
= NT_STATUS_INVALID_PARAMETER
;
4331 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
4333 if (total_data
< size_needed
) {
4334 status
= NT_STATUS_INVALID_PARAMETER
;
4339 * Ensure we always operate on a file descriptor, not just
4342 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
4343 uint32_t access_mask
= SEC_STD_WRITE_OWNER
|
4345 SEC_STD_READ_CONTROL
|
4346 FILE_READ_ATTRIBUTES
|
4347 FILE_WRITE_ATTRIBUTES
;
4349 status
= get_posix_fsp(conn
,
4355 if (!NT_STATUS_IS_OK(status
)) {
4361 /* Here we know fsp != NULL */
4362 SMB_ASSERT(fsp
!= NULL
);
4364 refuse
= refuse_symlink_fsp(fsp
);
4366 status
= NT_STATUS_ACCESS_DENIED
;
4370 /* If we have a default acl, this *must* be a directory. */
4371 if (valid_def_acls
&& !fsp
->fsp_flags
.is_directory
) {
4372 DBG_INFO("Can't set default acls on "
4373 "non-directory %s\n",
4375 return NT_STATUS_INVALID_HANDLE
;
4378 DBG_DEBUG("file %s num_file_acls = %"PRIu16
", "
4379 "num_def_acls = %"PRIu16
"\n",
4384 /* Move pdata to the start of the file ACL entries. */
4385 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
4387 if (valid_file_acls
) {
4388 status
= set_unix_posix_acl(conn
,
4392 if (!NT_STATUS_IS_OK(status
)) {
4397 /* Move pdata to the start of the default ACL entries. */
4398 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
4400 if (valid_def_acls
) {
4401 status
= set_unix_posix_default_acl(conn
,
4405 if (!NT_STATUS_IS_OK(status
)) {
4410 status
= NT_STATUS_OK
;
4415 (void)close_file_free(req
, &fsp
, NORMAL_CLOSE
);
4421 static void call_trans2setpathinfo(
4422 connection_struct
*conn
,
4423 struct smb_request
*req
,
4428 unsigned int max_data_bytes
)
4430 uint16_t info_level
;
4431 struct smb_filename
*smb_fname
= NULL
;
4432 struct files_struct
*dirfsp
= NULL
;
4433 struct files_struct
*fsp
= NULL
;
4434 char *params
= *pparams
;
4435 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4438 bool info_level_handled
;
4439 int data_return_size
= 0;
4442 if (params
== NULL
) {
4443 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4448 if (total_params
< 7) {
4449 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4453 info_level
= SVAL(params
,0);
4455 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4456 if (!lp_smb1_unix_extensions()) {
4457 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4460 if (!req
->posix_pathnames
) {
4461 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4466 if (req
->posix_pathnames
) {
4467 srvstr_get_path_posix(req
,
4476 srvstr_get_path(req
,
4485 if (!NT_STATUS_IS_OK(status
)) {
4486 reply_nterror(req
, status
);
4490 DBG_NOTICE("fname=%s info_level=%d totdata=%d\n",
4495 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4496 extract_snapshot_token(fname
, &twrp
);
4498 status
= smb1_strip_dfs_path(req
, &ucf_flags
, &fname
);
4499 if (!NT_STATUS_IS_OK(status
)) {
4500 reply_nterror(req
, status
);
4503 status
= filename_convert_dirfsp(req
,
4510 if (!NT_STATUS_IS_OK(status
)) {
4511 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
4512 reply_botherror(req
,
4513 NT_STATUS_PATH_NOT_COVERED
,
4514 ERRSRV
, ERRbadpath
);
4517 reply_nterror(req
, status
);
4521 info_level_handled
= true; /* Untouched in switch cases below */
4523 switch (info_level
) {
4526 info_level_handled
= false;
4529 case SMB_POSIX_PATH_OPEN
:
4530 status
= smb_posix_open(conn
,
4539 case SMB_POSIX_PATH_UNLINK
:
4540 status
= smb_posix_unlink(conn
,
4548 case SMB_SET_FILE_UNIX_LINK
:
4549 status
= smb_set_file_unix_link(
4550 conn
, req
, *ppdata
, total_data
, dirfsp
, smb_fname
);
4553 case SMB_SET_FILE_UNIX_HLINK
:
4554 status
= smb_set_file_unix_hlink(
4555 conn
, req
, *ppdata
, total_data
, smb_fname
);
4558 case SMB_SET_FILE_UNIX_BASIC
:
4559 status
= smb_set_file_unix_basic(conn
,
4568 case SMB_SET_FILE_UNIX_INFO2
:
4569 status
= smb_set_file_unix_info2(conn
,
4577 case SMB_SET_POSIX_ACL
:
4578 status
= smb_set_posix_acl(
4579 conn
, req
, *ppdata
, total_data
, NULL
, smb_fname
);
4583 if (info_level_handled
) {
4588 * smb_fname->fsp may be NULL if smb_fname points at a symlink
4589 * and we're in POSIX context, so be careful when using fsp
4590 * below, it can still be NULL.
4592 fsp
= smb_fname
->fsp
;
4594 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4598 status
= smbd_do_setfilepathinfo(
4611 handle_trans2setfilepathinfo_result(
4621 static void call_trans2setfileinfo(
4622 connection_struct
*conn
,
4623 struct smb_request
*req
,
4628 unsigned int max_data_bytes
)
4630 char *pdata
= *ppdata
;
4631 uint16_t info_level
;
4632 struct smb_filename
*smb_fname
= NULL
;
4633 struct files_struct
*fsp
= NULL
;
4634 char *params
= *pparams
;
4635 int data_return_size
= 0;
4636 bool info_level_handled
;
4640 if (params
== NULL
) {
4641 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4644 if (total_params
< 4) {
4645 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4649 fsp
= file_fsp(req
, SVAL(params
,0));
4650 /* Basic check for non-null fsp. */
4651 if (!check_fsp_open(conn
, req
, fsp
)) {
4654 info_level
= SVAL(params
,2);
4656 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4657 if (!lp_smb1_unix_extensions()) {
4658 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4661 if (!req
->posix_pathnames
) {
4662 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4667 smb_fname
= fsp
->fsp_name
;
4669 DBG_NOTICE("fnum=%s fname=%s info_level=%d totdata=%d\n",
4675 if (fsp_get_pathref_fd(fsp
) == -1) {
4677 * This is actually a SETFILEINFO on a directory
4678 * handle (returned from an NT SMB). NT5.0 seems
4679 * to do this call. JRA.
4681 ret
= vfs_stat(conn
, smb_fname
);
4683 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
4684 smb_fname_str_dbg(smb_fname
),
4686 reply_nterror(req
, map_nt_error_from_unix(errno
));
4689 } else if (fsp
->print_file
) {
4691 * Doing a DELETE_ON_CLOSE should cancel a print job.
4693 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) &&
4696 fsp
->fsp_flags
.delete_on_close
= true;
4698 DBG_NOTICE("Cancelling print job (%s)\n",
4702 send_trans2_replies(
4712 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
4717 * Original code - this is an open file.
4719 status
= vfs_stat_fsp(fsp
);
4720 if (!NT_STATUS_IS_OK(status
)) {
4721 DBG_NOTICE("fstat of %s failed (%s)\n",
4724 reply_nterror(req
, status
);
4729 info_level_handled
= true; /* Untouched in switch cases below */
4731 switch (info_level
) {
4734 info_level_handled
= false;
4737 case SMB_SET_FILE_UNIX_BASIC
:
4738 status
= smb_set_file_unix_basic(conn
,
4747 case SMB_SET_FILE_UNIX_INFO2
:
4748 status
= smb_set_file_unix_info2(conn
,
4757 case SMB_SET_POSIX_LOCK
:
4758 status
= smb_set_posix_lock(
4759 conn
, req
, *ppdata
, total_data
, fsp
);
4763 if (info_level_handled
) {
4764 handle_trans2setfilepathinfo_result(
4775 status
= smbd_do_setfilepathinfo(
4787 handle_trans2setfilepathinfo_result(
4797 /****************************************************************************
4798 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4799 ****************************************************************************/
4801 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
4802 char **pparams
, int total_params
,
4803 char **ppdata
, int total_data
,
4804 unsigned int max_data_bytes
)
4806 struct files_struct
*dirfsp
= NULL
;
4807 struct files_struct
*fsp
= NULL
;
4808 struct smb_filename
*smb_dname
= NULL
;
4809 char *params
= *pparams
;
4810 char *pdata
= *ppdata
;
4811 char *directory
= NULL
;
4812 NTSTATUS status
= NT_STATUS_OK
;
4813 struct ea_list
*ea_list
= NULL
;
4814 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4816 TALLOC_CTX
*ctx
= talloc_tos();
4818 if (!CAN_WRITE(conn
)) {
4819 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4823 if (total_params
< 5) {
4824 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4828 if (req
->posix_pathnames
) {
4829 srvstr_get_path_posix(ctx
,
4838 srvstr_get_path(ctx
,
4847 if (!NT_STATUS_IS_OK(status
)) {
4848 reply_nterror(req
, status
);
4852 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
4854 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4855 extract_snapshot_token(directory
, &twrp
);
4857 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &directory
);
4858 if (!NT_STATUS_IS_OK(status
)) {
4859 reply_nterror(req
, status
);
4862 status
= filename_convert_dirfsp(ctx
,
4869 if (!NT_STATUS_IS_OK(status
)) {
4870 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
4871 reply_botherror(req
,
4872 NT_STATUS_PATH_NOT_COVERED
,
4873 ERRSRV
, ERRbadpath
);
4876 reply_nterror(req
, status
);
4881 * OS/2 workplace shell seems to send SET_EA requests of "null"
4882 * length (4 bytes containing IVAL 4).
4883 * They seem to have no effect. Bug #3212. JRA.
4886 if (total_data
&& (total_data
!= 4)) {
4887 /* Any data in this call is an EA list. */
4888 if (total_data
< 10) {
4889 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4893 if (IVAL(pdata
,0) > total_data
) {
4894 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4895 IVAL(pdata
,0), (unsigned int)total_data
));
4896 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4900 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
4903 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4907 if (!lp_ea_support(SNUM(conn
))) {
4908 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
4912 /* If total_data == 4 Windows doesn't care what values
4913 * are placed in that field, it just ignores them.
4914 * The System i QNTC IBM SMB client puts bad values here,
4915 * so ignore them. */
4917 status
= SMB_VFS_CREATE_FILE(
4920 dirfsp
, /* dirfsp */
4921 smb_dname
, /* fname */
4922 MAXIMUM_ALLOWED_ACCESS
, /* access_mask */
4923 FILE_SHARE_NONE
, /* share_access */
4924 FILE_CREATE
, /* create_disposition*/
4925 FILE_DIRECTORY_FILE
, /* create_options */
4926 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
4927 0, /* oplock_request */
4929 0, /* allocation_size */
4930 0, /* private_flags */
4935 NULL
, NULL
); /* create context */
4936 if (!NT_STATUS_IS_OK(status
)) {
4937 reply_nterror(req
, status
);
4941 /* Try and set any given EA. */
4943 status
= set_ea(conn
, fsp
, ea_list
);
4944 if (!NT_STATUS_IS_OK(status
)) {
4945 reply_nterror(req
, status
);
4950 /* Realloc the parameter and data sizes */
4951 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4952 if(*pparams
== NULL
) {
4953 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4960 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
4964 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
4966 TALLOC_FREE(smb_dname
);
4969 /****************************************************************************
4970 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4971 We don't actually do this - we just send a null response.
4972 ****************************************************************************/
4974 static void call_trans2findnotifyfirst(connection_struct
*conn
,
4975 struct smb_request
*req
,
4976 char **pparams
, int total_params
,
4977 char **ppdata
, int total_data
,
4978 unsigned int max_data_bytes
)
4980 char *params
= *pparams
;
4981 uint16_t info_level
;
4983 if (total_params
< 6) {
4984 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4988 info_level
= SVAL(params
,4);
4989 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
4991 switch (info_level
) {
4996 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5000 /* Realloc the parameter and data sizes */
5001 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
5002 if (*pparams
== NULL
) {
5003 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5008 SSVAL(params
,0,fnf_handle
);
5009 SSVAL(params
,2,0); /* No changes */
5010 SSVAL(params
,4,0); /* No EA errors */
5017 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
5020 /****************************************************************************
5021 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
5022 changes). Currently this does nothing.
5023 ****************************************************************************/
5025 static void call_trans2findnotifynext(connection_struct
*conn
,
5026 struct smb_request
*req
,
5027 char **pparams
, int total_params
,
5028 char **ppdata
, int total_data
,
5029 unsigned int max_data_bytes
)
5031 char *params
= *pparams
;
5033 DEBUG(3,("call_trans2findnotifynext\n"));
5035 /* Realloc the parameter and data sizes */
5036 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
5037 if (*pparams
== NULL
) {
5038 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5043 SSVAL(params
,0,0); /* No changes */
5044 SSVAL(params
,2,0); /* No EA errors */
5046 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
5049 /****************************************************************************
5050 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5051 ****************************************************************************/
5053 static void call_trans2getdfsreferral(connection_struct
*conn
,
5054 struct smb_request
*req
,
5055 char **pparams
, int total_params
,
5056 char **ppdata
, int total_data
,
5057 unsigned int max_data_bytes
)
5059 char *params
= *pparams
;
5060 char *pathname
= NULL
;
5062 int max_referral_level
;
5063 NTSTATUS status
= NT_STATUS_OK
;
5064 TALLOC_CTX
*ctx
= talloc_tos();
5066 DEBUG(10,("call_trans2getdfsreferral\n"));
5068 if (!IS_IPC(conn
)) {
5069 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5073 if (total_params
< 3) {
5074 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5078 max_referral_level
= SVAL(params
,0);
5080 if(!lp_host_msdfs()) {
5081 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
5085 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
5086 total_params
- 2, STR_TERMINATE
);
5088 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
5091 reply_size
= setup_dfs_referral(
5092 conn
, pathname
, max_referral_level
, ppdata
, &status
);
5093 if (reply_size
< 0) {
5094 reply_nterror(req
, status
);
5098 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
5099 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
5100 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
5103 #define LMCAT_SPL 0x53
5104 #define LMFUNC_GETJOBID 0x60
5106 /****************************************************************************
5107 Reply to a TRANS2_IOCTL - used for OS/2 printing.
5108 ****************************************************************************/
5110 static void call_trans2ioctl(connection_struct
*conn
,
5111 struct smb_request
*req
,
5112 char **pparams
, int total_params
,
5113 char **ppdata
, int total_data
,
5114 unsigned int max_data_bytes
)
5116 const struct loadparm_substitution
*lp_sub
=
5117 loadparm_s3_global_substitution();
5118 char *pdata
= *ppdata
;
5119 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
5123 /* check for an invalid fid before proceeding */
5126 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5130 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
5131 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
5132 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
5133 if (*ppdata
== NULL
) {
5134 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5139 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5140 CAN ACCEPT THIS IN UNICODE. JRA. */
5143 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
5145 status
= srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
5146 lp_netbios_name(), 15,
5147 STR_ASCII
|STR_TERMINATE
, &len
); /* Our NetBIOS name */
5148 if (!NT_STATUS_IS_OK(status
)) {
5149 reply_nterror(req
, status
);
5152 status
= srvstr_push(pdata
, req
->flags2
, pdata
+18,
5153 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)), 13,
5154 STR_ASCII
|STR_TERMINATE
, &len
); /* Service name */
5155 if (!NT_STATUS_IS_OK(status
)) {
5156 reply_nterror(req
, status
);
5159 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
5164 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5165 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
5168 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
5169 struct trans_state
*state
)
5171 struct smbXsrv_connection
*xconn
= req
->xconn
;
5173 if (xconn
->protocol
>= PROTOCOL_NT1
) {
5174 req
->flags2
|= 0x40; /* IS_LONG_NAME */
5175 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
5178 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
5179 if (state
->call
!= TRANSACT2_QFSINFO
&&
5180 state
->call
!= TRANSACT2_SETFSINFO
) {
5181 DEBUG(0,("handle_trans2: encryption required "
5183 (unsigned int)state
->call
));
5184 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5189 /* Now we must call the relevant TRANS2 function */
5190 switch(state
->call
) {
5191 case TRANSACT2_OPEN
:
5193 START_PROFILE(Trans2_open
);
5194 call_trans2open(conn
, req
,
5195 &state
->param
, state
->total_param
,
5196 &state
->data
, state
->total_data
,
5197 state
->max_data_return
);
5198 END_PROFILE(Trans2_open
);
5202 case TRANSACT2_FINDFIRST
:
5204 START_PROFILE(Trans2_findfirst
);
5205 call_trans2findfirst(conn
, req
,
5206 &state
->param
, state
->total_param
,
5207 &state
->data
, state
->total_data
,
5208 state
->max_data_return
);
5209 END_PROFILE(Trans2_findfirst
);
5213 case TRANSACT2_FINDNEXT
:
5215 START_PROFILE(Trans2_findnext
);
5216 call_trans2findnext(conn
, req
,
5217 &state
->param
, state
->total_param
,
5218 &state
->data
, state
->total_data
,
5219 state
->max_data_return
);
5220 END_PROFILE(Trans2_findnext
);
5224 case TRANSACT2_QFSINFO
:
5226 START_PROFILE(Trans2_qfsinfo
);
5227 call_trans2qfsinfo(conn
, req
,
5228 &state
->param
, state
->total_param
,
5229 &state
->data
, state
->total_data
,
5230 state
->max_data_return
);
5231 END_PROFILE(Trans2_qfsinfo
);
5235 case TRANSACT2_SETFSINFO
:
5237 START_PROFILE(Trans2_setfsinfo
);
5238 call_trans2setfsinfo(conn
, req
,
5239 &state
->param
, state
->total_param
,
5240 &state
->data
, state
->total_data
,
5241 state
->max_data_return
);
5242 END_PROFILE(Trans2_setfsinfo
);
5246 case TRANSACT2_QPATHINFO
:
5248 START_PROFILE(Trans2_qpathinfo
);
5249 call_trans2qpathinfo(
5256 state
->max_data_return
);
5257 END_PROFILE(Trans2_qpathinfo
);
5261 case TRANSACT2_QFILEINFO
:
5263 START_PROFILE(Trans2_qfileinfo
);
5264 call_trans2qfileinfo(
5271 state
->max_data_return
);
5272 END_PROFILE(Trans2_qfileinfo
);
5276 case TRANSACT2_SETPATHINFO
:
5278 START_PROFILE(Trans2_setpathinfo
);
5279 call_trans2setpathinfo(
5286 state
->max_data_return
);
5287 END_PROFILE(Trans2_setpathinfo
);
5291 case TRANSACT2_SETFILEINFO
:
5293 START_PROFILE(Trans2_setfileinfo
);
5294 call_trans2setfileinfo(
5301 state
->max_data_return
);
5302 END_PROFILE(Trans2_setfileinfo
);
5306 case TRANSACT2_FINDNOTIFYFIRST
:
5308 START_PROFILE(Trans2_findnotifyfirst
);
5309 call_trans2findnotifyfirst(conn
, req
,
5310 &state
->param
, state
->total_param
,
5311 &state
->data
, state
->total_data
,
5312 state
->max_data_return
);
5313 END_PROFILE(Trans2_findnotifyfirst
);
5317 case TRANSACT2_FINDNOTIFYNEXT
:
5319 START_PROFILE(Trans2_findnotifynext
);
5320 call_trans2findnotifynext(conn
, req
,
5321 &state
->param
, state
->total_param
,
5322 &state
->data
, state
->total_data
,
5323 state
->max_data_return
);
5324 END_PROFILE(Trans2_findnotifynext
);
5328 case TRANSACT2_MKDIR
:
5330 START_PROFILE(Trans2_mkdir
);
5331 call_trans2mkdir(conn
, req
,
5332 &state
->param
, state
->total_param
,
5333 &state
->data
, state
->total_data
,
5334 state
->max_data_return
);
5335 END_PROFILE(Trans2_mkdir
);
5339 case TRANSACT2_GET_DFS_REFERRAL
:
5341 START_PROFILE(Trans2_get_dfs_referral
);
5342 call_trans2getdfsreferral(conn
, req
,
5343 &state
->param
, state
->total_param
,
5344 &state
->data
, state
->total_data
,
5345 state
->max_data_return
);
5346 END_PROFILE(Trans2_get_dfs_referral
);
5350 case TRANSACT2_IOCTL
:
5352 START_PROFILE(Trans2_ioctl
);
5353 call_trans2ioctl(conn
, req
,
5354 &state
->param
, state
->total_param
,
5355 &state
->data
, state
->total_data
,
5356 state
->max_data_return
);
5357 END_PROFILE(Trans2_ioctl
);
5362 /* Error in request */
5363 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
5364 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
5368 /****************************************************************************
5369 Reply to a SMBtrans2.
5370 ****************************************************************************/
5372 void reply_trans2(struct smb_request
*req
)
5374 connection_struct
*conn
= req
->conn
;
5379 unsigned int tran_call
;
5380 struct trans_state
*state
;
5383 START_PROFILE(SMBtrans2
);
5385 if (req
->wct
< 14) {
5386 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5387 END_PROFILE(SMBtrans2
);
5391 dsoff
= SVAL(req
->vwv
+12, 0);
5392 dscnt
= SVAL(req
->vwv
+11, 0);
5393 psoff
= SVAL(req
->vwv
+10, 0);
5394 pscnt
= SVAL(req
->vwv
+9, 0);
5395 tran_call
= SVAL(req
->vwv
+14, 0);
5397 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
5398 if (!NT_STATUS_IS_OK(result
)) {
5399 DEBUG(2, ("Got invalid trans2 request: %s\n",
5400 nt_errstr(result
)));
5401 reply_nterror(req
, result
);
5402 END_PROFILE(SMBtrans2
);
5407 switch (tran_call
) {
5408 /* List the allowed trans2 calls on IPC$ */
5409 case TRANSACT2_OPEN
:
5410 case TRANSACT2_GET_DFS_REFERRAL
:
5411 case TRANSACT2_QFILEINFO
:
5412 case TRANSACT2_QFSINFO
:
5413 case TRANSACT2_SETFSINFO
:
5416 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5417 END_PROFILE(SMBtrans2
);
5422 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
5423 DEBUG(0, ("talloc failed\n"));
5424 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5425 END_PROFILE(SMBtrans2
);
5429 state
->cmd
= SMBtrans2
;
5431 state
->mid
= req
->mid
;
5432 state
->vuid
= req
->vuid
;
5433 state
->setup_count
= SVAL(req
->vwv
+13, 0);
5434 state
->setup
= NULL
;
5435 state
->total_param
= SVAL(req
->vwv
+0, 0);
5436 state
->param
= NULL
;
5437 state
->total_data
= SVAL(req
->vwv
+1, 0);
5439 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
5440 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
5441 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
5442 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
5443 state
->one_way
= BITSETW(req
->vwv
+5, 1);
5445 state
->call
= tran_call
;
5447 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5448 is so as a sanity check */
5449 if (state
->setup_count
!= 1) {
5451 * Need to have rc=0 for ioctl to get job id for OS/2.
5452 * Network printing will fail if function is not successful.
5453 * Similar function in reply.c will be used if protocol
5454 * is LANMAN1.0 instead of LM1.2X002.
5455 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5456 * outbuf doesn't have to be set(only job id is used).
5458 if ( (state
->setup_count
== 4)
5459 && (tran_call
== TRANSACT2_IOCTL
)
5460 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
5461 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
5462 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5464 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
5465 DEBUG(2,("Transaction is %d\n",tran_call
));
5467 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5468 END_PROFILE(SMBtrans2
);
5473 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
5476 if (state
->total_data
) {
5478 if (smb_buffer_oob(state
->total_data
, 0, dscnt
)
5479 || smb_buffer_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
5483 /* Can't use talloc here, the core routines do realloc on the
5484 * params and data. */
5485 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
5486 if (state
->data
== NULL
) {
5487 DEBUG(0,("reply_trans2: data malloc fail for %u "
5488 "bytes !\n", (unsigned int)state
->total_data
));
5490 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5491 END_PROFILE(SMBtrans2
);
5495 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
5498 if (state
->total_param
) {
5500 if (smb_buffer_oob(state
->total_param
, 0, pscnt
)
5501 || smb_buffer_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
5505 /* Can't use talloc here, the core routines do realloc on the
5506 * params and data. */
5507 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
5508 if (state
->param
== NULL
) {
5509 DEBUG(0,("reply_trans: param malloc fail for %u "
5510 "bytes !\n", (unsigned int)state
->total_param
));
5511 SAFE_FREE(state
->data
);
5513 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5514 END_PROFILE(SMBtrans2
);
5518 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
5521 state
->received_data
= dscnt
;
5522 state
->received_param
= pscnt
;
5524 if ((state
->received_param
== state
->total_param
) &&
5525 (state
->received_data
== state
->total_data
)) {
5527 handle_trans2(conn
, req
, state
);
5529 SAFE_FREE(state
->data
);
5530 SAFE_FREE(state
->param
);
5532 END_PROFILE(SMBtrans2
);
5536 DLIST_ADD(conn
->pending_trans
, state
);
5538 /* We need to send an interim response then receive the rest
5539 of the parameter/data bytes */
5540 reply_smb1_outbuf(req
, 0, 0);
5541 show_msg((char *)req
->outbuf
);
5542 END_PROFILE(SMBtrans2
);
5547 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5548 SAFE_FREE(state
->data
);
5549 SAFE_FREE(state
->param
);
5551 END_PROFILE(SMBtrans2
);
5552 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5555 /****************************************************************************
5556 Reply to a SMBtranss2
5557 ****************************************************************************/
5559 void reply_transs2(struct smb_request
*req
)
5561 connection_struct
*conn
= req
->conn
;
5562 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
5563 struct trans_state
*state
;
5565 START_PROFILE(SMBtranss2
);
5567 show_msg((const char *)req
->inbuf
);
5569 /* Windows clients expect all replies to
5570 a transact secondary (SMBtranss2 0x33)
5571 to have a command code of transact
5572 (SMBtrans2 0x32). See bug #8989
5573 and also [MS-CIFS] section 2.2.4.47.2
5576 req
->cmd
= SMBtrans2
;
5579 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5580 END_PROFILE(SMBtranss2
);
5584 for (state
= conn
->pending_trans
; state
!= NULL
;
5585 state
= state
->next
) {
5586 if (state
->mid
== req
->mid
) {
5591 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
5592 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5593 END_PROFILE(SMBtranss2
);
5597 /* Revise state->total_param and state->total_data in case they have
5598 changed downwards */
5600 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
5601 state
->total_param
= SVAL(req
->vwv
+0, 0);
5602 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
5603 state
->total_data
= SVAL(req
->vwv
+1, 0);
5605 pcnt
= SVAL(req
->vwv
+2, 0);
5606 poff
= SVAL(req
->vwv
+3, 0);
5607 pdisp
= SVAL(req
->vwv
+4, 0);
5609 dcnt
= SVAL(req
->vwv
+5, 0);
5610 doff
= SVAL(req
->vwv
+6, 0);
5611 ddisp
= SVAL(req
->vwv
+7, 0);
5613 state
->received_param
+= pcnt
;
5614 state
->received_data
+= dcnt
;
5616 if ((state
->received_data
> state
->total_data
) ||
5617 (state
->received_param
> state
->total_param
))
5621 if (smb_buffer_oob(state
->total_param
, pdisp
, pcnt
)
5622 || smb_buffer_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
5625 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
5629 if (smb_buffer_oob(state
->total_data
, ddisp
, dcnt
)
5630 || smb_buffer_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
5633 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
5636 if ((state
->received_param
< state
->total_param
) ||
5637 (state
->received_data
< state
->total_data
)) {
5638 END_PROFILE(SMBtranss2
);
5642 handle_trans2(conn
, req
, state
);
5644 DLIST_REMOVE(conn
->pending_trans
, state
);
5645 SAFE_FREE(state
->data
);
5646 SAFE_FREE(state
->param
);
5649 END_PROFILE(SMBtranss2
);
5654 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5655 DLIST_REMOVE(conn
->pending_trans
, state
);
5656 SAFE_FREE(state
->data
);
5657 SAFE_FREE(state
->param
);
5659 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5660 END_PROFILE(SMBtranss2
);