2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "../libcli/auth/libcli_auth.h"
34 #include "../librpc/gen_ndr/xattr.h"
35 #include "../librpc/gen_ndr/ndr_security.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #include "libcli/smb/smb2_posix.h"
46 #include "lib/util/string_wrappers.h"
47 #include "source3/lib/substitute.h"
48 #include "source3/lib/adouble.h"
50 #define DIR_ENTRY_SAFETY_MARGIN 4096
52 /****************************************************************************
53 Send the required number of replies back.
54 We assume all fields other than the data fields are
55 set correctly for the type of call.
56 HACK ! Always assumes smb_setup field is zero.
57 ****************************************************************************/
59 static void send_trans2_replies(connection_struct *conn,
60 struct smb_request *req,
68 /* As we are using a protocol > LANMAN1 then the max_send
69 variable must have been set in the sessetupX call.
70 This takes precedence over the max_xmit field in the
71 global struct. These different max_xmit variables should
72 be merged as this is now too confusing */
74 int data_to_send = datasize;
75 int params_to_send = paramsize;
77 const char *pp = params;
78 const char *pd = pdata;
79 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
80 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
81 int data_alignment_offset = 0;
82 bool overflow = False;
83 struct smbXsrv_connection *xconn = req->xconn;
84 int max_send = xconn->smb1.sessions.max_send;
86 /* Modify the data_to_send and datasize and set the error if
87 we're trying to send more than max_data_bytes. We still send
88 the part of the packet(s) that fit. Strange, but needed
91 if (max_data_bytes > 0 && datasize > max_data_bytes) {
92 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
93 max_data_bytes, datasize ));
94 datasize = data_to_send = max_data_bytes;
98 /* If there genuinely are no parameters or data to send just send the empty packet */
100 if(params_to_send == 0 && data_to_send == 0) {
101 reply_smb1_outbuf(req, 10, 0);
102 if (NT_STATUS_V(status)) {
105 ntstatus_to_dos(status, &eclass, &ecode);
106 error_packet_set((char *)req->outbuf,
107 eclass, ecode, status,
110 show_msg((char *)req->outbuf);
111 if (!smb1_srv_send(xconn,
115 IS_CONN_ENCRYPTED(conn))) {
116 exit_server_cleanly("send_trans2_replies: smb1_srv_send failed.");
118 TALLOC_FREE(req->outbuf);
122 /* When sending params and data ensure that both are nicely aligned */
123 /* Only do this alignment when there is also data to send - else
124 can cause NT redirector problems. */
126 if (((params_to_send % 4) != 0) && (data_to_send != 0))
127 data_alignment_offset = 4 - (params_to_send % 4);
129 /* Space is bufsize minus Netbios over TCP header minus SMB header */
130 /* The alignment_offset is to align the param bytes on an even byte
131 boundary. NT 4.0 Beta needs this to work correctly. */
133 useable_space = max_send - (smb_size
136 + data_alignment_offset);
138 if (useable_space < 0) {
139 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
140 "= %d!!!", useable_space));
141 exit_server_cleanly("send_trans2_replies: Not enough space");
144 while (params_to_send || data_to_send) {
145 /* Calculate whether we will totally or partially fill this packet */
147 total_sent_thistime = params_to_send + data_to_send;
149 /* We can never send more than useable_space */
151 * Note that 'useable_space' does not include the alignment offsets,
152 * but we must include the alignment offsets in the calculation of
153 * the length of the data we send over the wire, as the alignment offsets
154 * are sent here. Fix from Marc_Jacobsen@hp.com.
157 total_sent_thistime = MIN(total_sent_thistime, useable_space);
159 reply_smb1_outbuf(req, 10, total_sent_thistime + alignment_offset
160 + data_alignment_offset);
162 /* Set total params and data to be sent */
163 SSVAL(req->outbuf,smb_tprcnt,paramsize);
164 SSVAL(req->outbuf,smb_tdrcnt,datasize);
166 /* Calculate how many parameters and data we can fit into
167 * this packet. Parameters get precedence
170 params_sent_thistime = MIN(params_to_send,useable_space);
171 data_sent_thistime = useable_space - params_sent_thistime;
172 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
174 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
176 /* smb_proff is the offset from the start of the SMB header to the
177 parameter bytes, however the first 4 bytes of outbuf are
178 the Netbios over TCP header. Thus use smb_base() to subtract
179 them from the calculation */
181 SSVAL(req->outbuf,smb_proff,
182 ((smb_buf(req->outbuf)+alignment_offset)
183 - smb_base(req->outbuf)));
185 if(params_sent_thistime == 0)
186 SSVAL(req->outbuf,smb_prdisp,0);
188 /* Absolute displacement of param bytes sent in this packet */
189 SSVAL(req->outbuf,smb_prdisp,pp - params);
191 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
192 if(data_sent_thistime == 0) {
193 SSVAL(req->outbuf,smb_droff,0);
194 SSVAL(req->outbuf,smb_drdisp, 0);
196 /* The offset of the data bytes is the offset of the
197 parameter bytes plus the number of parameters being sent this time */
198 SSVAL(req->outbuf, smb_droff,
199 ((smb_buf(req->outbuf)+alignment_offset)
200 - smb_base(req->outbuf))
201 + params_sent_thistime + data_alignment_offset);
202 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
205 /* Initialize the padding for alignment */
207 if (alignment_offset != 0) {
208 memset(smb_buf(req->outbuf), 0, alignment_offset);
211 /* Copy the param bytes into the packet */
213 if(params_sent_thistime) {
214 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
215 params_sent_thistime);
218 /* Copy in the data bytes */
219 if(data_sent_thistime) {
220 if (data_alignment_offset != 0) {
221 memset((smb_buf(req->outbuf)+alignment_offset+
222 params_sent_thistime), 0,
223 data_alignment_offset);
225 memcpy(smb_buf(req->outbuf)+alignment_offset
226 +params_sent_thistime+data_alignment_offset,
227 pd,data_sent_thistime);
230 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
231 params_sent_thistime, data_sent_thistime, useable_space));
232 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
233 params_to_send, data_to_send, paramsize, datasize));
236 error_packet_set((char *)req->outbuf,
237 ERRDOS,ERRbufferoverflow,
238 STATUS_BUFFER_OVERFLOW,
240 } else if (NT_STATUS_V(status)) {
243 ntstatus_to_dos(status, &eclass, &ecode);
244 error_packet_set((char *)req->outbuf,
245 eclass, ecode, status,
249 /* Send the packet */
250 show_msg((char *)req->outbuf);
251 if (!smb1_srv_send(xconn,
255 IS_CONN_ENCRYPTED(conn))) {
256 exit_server_cleanly("send_trans2_replies: smb1_srv_send failed.");
259 TALLOC_FREE(req->outbuf);
261 pp += params_sent_thistime;
262 pd += data_sent_thistime;
264 params_to_send -= params_sent_thistime;
265 data_to_send -= data_sent_thistime;
268 if(params_to_send < 0 || data_to_send < 0) {
269 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
270 params_to_send, data_to_send));
278 /****************************************************************************
279 Deal with SMB_SET_POSIX_LOCK.
280 ****************************************************************************/
282 static void smb_set_posix_lock_done(struct tevent_req *subreq);
284 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
285 struct smb_request *req,
290 struct tevent_req *subreq = NULL;
291 struct smbd_lock_element *lck = NULL;
295 bool blocking_lock = False;
296 enum brl_type lock_type;
298 NTSTATUS status = NT_STATUS_OK;
300 if (!CAN_WRITE(conn)) {
301 return NT_STATUS_DOS(ERRSRV, ERRaccess);
305 fsp->fsp_flags.is_pathref ||
306 fsp_get_io_fd(fsp) == -1)
308 return NT_STATUS_INVALID_HANDLE;
311 if (total_data != POSIX_LOCK_DATA_SIZE) {
312 return NT_STATUS_INVALID_PARAMETER;
315 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
316 case POSIX_LOCK_TYPE_READ:
317 lock_type = READ_LOCK;
319 case POSIX_LOCK_TYPE_WRITE:
320 /* Return the right POSIX-mappable error code for files opened read-only. */
321 if (!fsp->fsp_flags.can_write) {
322 return NT_STATUS_INVALID_HANDLE;
324 lock_type = WRITE_LOCK;
326 case POSIX_LOCK_TYPE_UNLOCK:
327 lock_type = UNLOCK_LOCK;
330 return NT_STATUS_INVALID_PARAMETER;
333 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
334 case POSIX_LOCK_FLAG_NOWAIT:
335 blocking_lock = false;
337 case POSIX_LOCK_FLAG_WAIT:
338 blocking_lock = true;
341 return NT_STATUS_INVALID_PARAMETER;
344 if (!lp_blocking_locks(SNUM(conn))) {
345 blocking_lock = False;
348 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
349 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
350 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
351 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
352 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
354 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
355 "count = %"PRIu64", offset = %"PRIu64"\n",
357 (unsigned int)lock_type,
362 if (lock_type == UNLOCK_LOCK) {
363 struct smbd_lock_element l = {
364 .req_guid = smbd_request_guid(req, 0),
366 .brltype = UNLOCK_LOCK,
367 .lock_flav = POSIX_LOCK,
371 status = smbd_do_unlocking(req, fsp, 1, &l);
375 lck = talloc(req, struct smbd_lock_element);
377 return NT_STATUS_NO_MEMORY;
380 *lck = (struct smbd_lock_element) {
381 .req_guid = smbd_request_guid(req, 0),
383 .brltype = lock_type,
384 .lock_flav = POSIX_LOCK,
389 subreq = smbd_smb1_do_locks_send(
394 blocking_lock ? UINT32_MAX : 0,
395 true, /* large_offset */
398 if (subreq == NULL) {
400 return NT_STATUS_NO_MEMORY;
402 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
403 return NT_STATUS_EVENT_PENDING;
406 static void smb_set_posix_lock_done(struct tevent_req *subreq)
408 struct smb_request *req = NULL;
412 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
415 status = smbd_smb1_do_locks_recv(subreq);
418 if (NT_STATUS_IS_OK(status)) {
419 char params[2] = {0};
420 /* Fake up max_data_bytes here - we know it fits. */
431 reply_nterror(req, status);
432 ok = smb1_srv_send(req->xconn,
436 IS_CONN_ENCRYPTED(req->conn));
438 exit_server_cleanly("smb_set_posix_lock_done: "
439 "smb1_srv_send failed.");
447 /****************************************************************************
448 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
449 ****************************************************************************/
451 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
453 struct ea_list *ea_list_head = NULL;
454 size_t converted_size, offset = 0;
456 while (offset + 2 < data_size) {
457 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
458 unsigned int namelen = CVAL(pdata,offset);
460 offset++; /* Go past the namelen byte. */
462 /* integer wrap paranioa. */
463 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
464 (offset > data_size) || (namelen > data_size) ||
465 (offset + namelen >= data_size)) {
468 /* Ensure the name is null terminated. */
469 if (pdata[offset + namelen] != '\0') {
472 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
474 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
475 "failed: %s", strerror(errno)));
481 offset += (namelen + 1); /* Go past the name + terminating zero. */
482 DLIST_ADD_END(ea_list_head, eal);
483 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
489 /****************************************************************************
490 Reply to a TRANSACT2_OPEN.
491 ****************************************************************************/
493 static void call_trans2open(connection_struct *conn,
494 struct smb_request *req,
495 char **pparams, int total_params,
496 char **ppdata, int total_data,
497 unsigned int max_data_bytes)
499 struct smb_filename *smb_fname = NULL;
500 char *params = *pparams;
501 char *pdata = *ppdata;
506 bool return_additional_info;
518 struct files_struct *dirfsp = NULL;
520 struct ea_list *ea_list = NULL;
523 uint32_t access_mask;
525 uint32_t create_disposition;
526 uint32_t create_options = 0;
527 uint32_t private_flags = 0;
529 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
530 TALLOC_CTX *ctx = talloc_tos();
533 * Ensure we have enough parameters to perform the operation.
536 if (total_params < 29) {
537 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
541 flags = SVAL(params, 0);
542 deny_mode = SVAL(params, 2);
543 open_attr = SVAL(params,6);
544 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
545 if (oplock_request) {
546 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
550 return_additional_info = BITSETW(params,0);
551 open_sattr = SVAL(params, 4);
552 open_time = make_unix_date3(params+8);
554 open_ofun = SVAL(params,12);
555 open_size = IVAL(params,14);
559 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
563 if (req->posix_pathnames) {
564 srvstr_get_path_posix(ctx,
582 if (!NT_STATUS_IS_OK(status)) {
583 reply_nterror(req, status);
587 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
588 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
589 (unsigned int)open_ofun, open_size));
591 if (ucf_flags & UCF_GMT_PATHNAME) {
592 extract_snapshot_token(fname, &twrp);
594 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
595 if (!NT_STATUS_IS_OK(status)) {
596 reply_nterror(req, status);
599 status = filename_convert_dirfsp(ctx,
606 if (!NT_STATUS_IS_OK(status)) {
607 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
609 NT_STATUS_PATH_NOT_COVERED,
613 reply_nterror(req, status);
617 if (open_ofun == 0) {
618 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
622 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
624 &access_mask, &share_mode,
628 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
632 /* Any data in this call is an EA list. */
633 if (total_data && (total_data != 4)) {
634 if (total_data < 10) {
635 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
639 if (IVAL(pdata,0) > total_data) {
640 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
641 IVAL(pdata,0), (unsigned int)total_data));
642 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
646 ea_list = read_ea_list(talloc_tos(), pdata + 4,
649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
653 if (!lp_ea_support(SNUM(conn))) {
654 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
658 if (!req->posix_pathnames &&
659 ea_list_has_invalid_name(ea_list)) {
661 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
662 if(*pparams == NULL ) {
663 reply_nterror(req, NT_STATUS_NO_MEMORY);
667 memset(params, '\0', param_len);
668 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
669 params, param_len, NULL, 0, max_data_bytes);
674 status = SMB_VFS_CREATE_FILE(
678 smb_fname, /* fname */
679 access_mask, /* access_mask */
680 share_mode, /* share_access */
681 create_disposition, /* create_disposition*/
682 create_options, /* create_options */
683 open_attr, /* file_attributes */
684 oplock_request, /* oplock_request */
686 open_size, /* allocation_size */
689 ea_list, /* ea_list */
691 &smb_action, /* psbuf */
692 NULL, NULL); /* create context */
694 if (!NT_STATUS_IS_OK(status)) {
695 if (open_was_deferred(req->xconn, req->mid)) {
696 /* We have re-scheduled this call. */
700 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
701 reply_openerror(req, status);
705 fsp = fcb_or_dos_open(
712 bool ok = defer_smb1_sharing_violation(req);
716 reply_openerror(req, status);
720 smb_action = FILE_WAS_OPENED;
723 size = get_file_size_stat(&smb_fname->st);
724 fattr = fdos_mode(fsp);
725 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
726 inode = smb_fname->st.st_ex_ino;
727 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
728 close_file_free(req, &fsp, ERROR_CLOSE);
729 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
733 /* Realloc the size of parameters and data we will return */
734 *pparams = (char *)SMB_REALLOC(*pparams, 30);
735 if(*pparams == NULL ) {
736 reply_nterror(req, NT_STATUS_NO_MEMORY);
741 SSVAL(params,0,fsp->fnum);
742 SSVAL(params,2,fattr);
743 srv_put_dos_date2(params,4, mtime);
744 SIVAL(params,8, (uint32_t)size);
745 SSVAL(params,12,deny_mode);
746 SSVAL(params,14,0); /* open_type - file or directory. */
747 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
749 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
750 smb_action |= EXTENDED_OPLOCK_GRANTED;
753 SSVAL(params,18,smb_action);
756 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
758 SIVAL(params,20,inode);
759 SSVAL(params,24,0); /* Padding. */
761 uint32_t ea_size = estimate_ea_size(smb_fname->fsp);
762 SIVAL(params, 26, ea_size);
764 SIVAL(params, 26, 0);
767 /* Send the required number of replies */
768 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
770 TALLOC_FREE(smb_fname);
773 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
774 connection_struct *conn,
775 struct dptr_struct *dirptr,
777 const char *path_mask,
780 bool requires_resume_key,
787 bool *got_exact_match,
789 struct ea_list *name_list)
792 const bool do_pad = true;
794 if (info_level >= 1 && info_level <= 3) {
795 /* No alignment on earlier info levels. */
799 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
800 path_mask, dirtype, info_level,
801 requires_resume_key, dont_descend, ask_sharemode,
803 ppdata, base_data, end_data,
807 last_entry_off, name_list, NULL);
810 /****************************************************************************
811 Reply to a TRANS2_FINDFIRST.
812 ****************************************************************************/
814 static void call_trans2findfirst(connection_struct *conn,
815 struct smb_request *req,
816 char **pparams, int total_params,
817 char **ppdata, int total_data,
818 unsigned int max_data_bytes)
820 /* We must be careful here that we don't return more than the
821 allowed number of data bytes. If this means returning fewer than
822 maxentries then so be it. We assume that the redirector has
823 enough room for the fixed number of parameter bytes it has
825 struct smb_filename *smb_dname = NULL;
826 char *params = *pparams;
827 char *pdata = *ppdata;
831 uint16_t findfirst_flags;
832 bool close_after_first;
834 bool requires_resume_key;
836 char *directory = NULL;
839 int last_entry_off=0;
843 bool finished = False;
844 bool dont_descend = False;
845 bool out_of_space = False;
847 struct ea_list *ea_list = NULL;
848 NTSTATUS ntstatus = NT_STATUS_OK;
850 struct smbd_server_connection *sconn = req->sconn;
851 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
852 bool backup_priv = false;
853 bool as_root = false;
854 files_struct *fsp = NULL;
855 struct files_struct *dirfsp = NULL;
856 const struct loadparm_substitution *lp_sub =
857 loadparm_s3_global_substitution();
859 if (total_params < 13) {
860 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
864 dirtype = SVAL(params,0);
865 maxentries = SVAL(params,2);
866 findfirst_flags = SVAL(params,4);
867 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
868 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
869 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
870 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
871 security_token_has_privilege(get_current_nttok(conn),
874 info_level = SVAL(params,6);
876 DBG_NOTICE("dirtype = %"PRIx32", maxentries = %d, "
877 "close_after_first=%d, close_if_end = %d "
878 "requires_resume_key = %d backup_priv = %d level = 0x%x, "
879 "max_data_bytes = %d\n",
890 /* W2K3 seems to treat zero as 1. */
894 switch (info_level) {
895 case SMB_FIND_INFO_STANDARD:
896 case SMB_FIND_EA_SIZE:
897 case SMB_FIND_EA_LIST:
898 case SMB_FIND_FILE_DIRECTORY_INFO:
899 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
900 case SMB_FIND_FILE_NAMES_INFO:
901 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
902 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
903 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
905 case SMB_FIND_FILE_UNIX:
906 case SMB_FIND_FILE_UNIX_INFO2:
907 if (!lp_smb1_unix_extensions()) {
908 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
911 if (!req->posix_pathnames) {
912 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
917 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
921 if (req->posix_pathnames) {
922 srvstr_get_path_posix(talloc_tos(),
931 srvstr_get_path(talloc_tos(),
940 if (!NT_STATUS_IS_OK(ntstatus)) {
941 reply_nterror(req, ntstatus);
949 ntstatus = smb1_strip_dfs_path(talloc_tos(), &ucf_flags, &directory);
950 if (!NT_STATUS_IS_OK(ntstatus)) {
951 reply_nterror(req, ntstatus);
955 ntstatus = filename_convert_smb1_search_path(talloc_tos(),
963 if (!NT_STATUS_IS_OK(ntstatus)) {
964 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
965 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
969 reply_nterror(req, ntstatus);
973 TALLOC_FREE(directory);
974 directory = smb_dname->base_name;
976 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
978 if (info_level == SMB_FIND_EA_LIST) {
981 if (total_data < 4) {
982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
986 ea_size = IVAL(pdata,0);
987 if (ea_size != total_data) {
988 DBG_NOTICE("Rejecting EA request with incorrect "
989 "total_data=%d (should be %" PRIu32 ")\n",
992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
996 if (!lp_ea_support(SNUM(conn))) {
997 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1001 /* Pull out the list of names. */
1002 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
1004 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1009 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1010 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1014 *ppdata = (char *)SMB_REALLOC(
1015 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1016 if(*ppdata == NULL ) {
1017 reply_nterror(req, NT_STATUS_NO_MEMORY);
1021 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1023 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
1026 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
1027 /* Realloc the params space */
1028 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1029 if (*pparams == NULL) {
1030 reply_nterror(req, NT_STATUS_NO_MEMORY);
1036 * Open an fsp on this directory for the dptr.
1038 ntstatus = SMB_VFS_CREATE_FILE(
1041 dirfsp, /* dirfsp */
1042 smb_dname, /* dname */
1043 FILE_LIST_DIRECTORY, /* access_mask */
1045 FILE_SHARE_WRITE, /* share_access */
1046 FILE_OPEN, /* create_disposition*/
1047 FILE_DIRECTORY_FILE, /* create_options */
1048 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1049 NO_OPLOCK, /* oplock_request */
1051 0, /* allocation_size */
1052 0, /* private_flags */
1057 NULL, /* in_context */
1058 NULL);/* out_context */
1060 if (!NT_STATUS_IS_OK(ntstatus)) {
1061 DBG_ERR("failed to open directory %s\n",
1062 smb_fname_str_dbg(smb_dname));
1063 reply_nterror(req, ntstatus);
1067 /* Save the wildcard match and attribs we are using on this directory -
1068 needed as lanman2 assumes these are being saved between calls */
1070 ntstatus = dptr_create(conn,
1078 if (!NT_STATUS_IS_OK(ntstatus)) {
1080 * Use NULL here for the first parameter (req)
1081 * as this is not a client visible handle so
1082 * can'tbe part of an SMB1 chain.
1084 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1085 reply_nterror(req, ntstatus);
1090 /* Remember this in case we have
1091 to do a findnext. */
1092 dptr_set_priv(fsp->dptr);
1095 dptr_num = dptr_dnum(fsp->dptr);
1096 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1098 /* We don't need to check for VOL here as this is returned by
1099 a different TRANS2 call. */
1101 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1102 directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
1103 if (in_list(directory,
1104 lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
1105 dptr_case_sensitive(fsp->dptr))) {
1106 dont_descend = True;
1110 space_remaining = max_data_bytes;
1111 out_of_space = False;
1113 ask_sharemode = fsp_search_ask_sharemode(fsp);
1115 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1116 bool got_exact_match = False;
1118 /* this is a heuristic to avoid seeking the dirptr except when
1119 absolutely necessary. It allows for a filename of about 40 chars */
1120 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1121 out_of_space = True;
1124 ntstatus = get_lanman2_dir_entry(talloc_tos(),
1128 mask,dirtype,info_level,
1129 requires_resume_key,dont_descend,
1134 &last_entry_off, ea_list);
1135 if (NT_STATUS_EQUAL(ntstatus,
1136 NT_STATUS_ILLEGAL_CHARACTER)) {
1138 * Bad character conversion on name. Ignore this
1143 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
1144 out_of_space = true;
1146 finished = !NT_STATUS_IS_OK(ntstatus);
1150 if (!finished && !out_of_space) {
1155 * As an optimisation if we know we aren't looking
1156 * for a wildcard name (ie. the name matches the wildcard exactly)
1157 * then we can finish on any (first) match.
1158 * This speeds up large directory searches. JRA.
1161 if (got_exact_match) {
1165 /* Ensure space_remaining never goes -ve. */
1166 if (PTR_DIFF(p,pdata) > max_data_bytes) {
1167 space_remaining = 0;
1168 out_of_space = true;
1170 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1174 /* Check if we can close the dirptr */
1175 if(close_after_first || (finished && close_if_end)) {
1176 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1178 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1182 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1183 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1184 * the protocol level is less than NT1. Tested with smbclient. JRA.
1185 * This should fix the OS/2 client bug #2335.
1188 if(numentries == 0) {
1191 * We may have already closed the file in the
1192 * close_after_first or finished case above.
1195 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1197 if (get_Protocol() < PROTOCOL_NT1) {
1198 reply_force_doserror(req, ERRDOS, ERRnofiles);
1201 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
1202 ERRDOS, ERRbadfile);
1207 /* At this point pdata points to numentries directory entries. */
1209 /* Set up the return parameter block */
1210 SSVAL(params,0,dptr_num);
1211 SSVAL(params,2,numentries);
1212 SSVAL(params,4,finished);
1213 SSVAL(params,6,0); /* Never an EA error */
1214 SSVAL(params,8,last_entry_off);
1216 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
1219 if ((! *directory) && dptr_path(sconn, dptr_num)) {
1220 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
1222 reply_nterror(req, NT_STATUS_NO_MEMORY);
1226 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1227 smb_fn_name(req->cmd),
1228 mask, directory, dirtype, numentries ) );
1231 * Force a name mangle here to ensure that the
1232 * mask as an 8.3 name is top of the mangled cache.
1233 * The reasons for this are subtle. Don't remove
1234 * this code unless you know what you are doing
1235 * (see PR#13758). JRA.
1238 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
1239 char mangled_name[13];
1240 name_to_8_3(mask, mangled_name, True, conn->params);
1248 TALLOC_FREE(smb_dname);
1252 static bool smbd_dptr_name_equal(struct dptr_struct *dptr,
1258 if (dptr_case_sensitive(dptr)) {
1259 equal = (strcmp(name1, name2) == 0);
1261 equal = strequal(name1, name2);
1267 /****************************************************************************
1268 Reply to a TRANS2_FINDNEXT.
1269 ****************************************************************************/
1271 static void call_trans2findnext(connection_struct *conn,
1272 struct smb_request *req,
1273 char **pparams, int total_params,
1274 char **ppdata, int total_data,
1275 unsigned int max_data_bytes)
1277 /* We must be careful here that we don't return more than the
1278 allowed number of data bytes. If this means returning fewer than
1279 maxentries then so be it. We assume that the redirector has
1280 enough room for the fixed number of parameter bytes it has
1282 char *params = *pparams;
1283 char *pdata = *ppdata;
1287 uint16_t info_level;
1288 uint32_t resume_key;
1289 uint16_t findnext_flags;
1290 bool close_after_request;
1292 bool requires_resume_key;
1294 char *resume_name = NULL;
1295 const char *mask = NULL;
1296 const char *directory = NULL;
1300 int i, last_entry_off=0;
1301 bool finished = False;
1302 bool dont_descend = False;
1303 bool out_of_space = False;
1304 int space_remaining;
1305 struct ea_list *ea_list = NULL;
1306 NTSTATUS ntstatus = NT_STATUS_OK;
1308 TALLOC_CTX *ctx = talloc_tos();
1309 struct smbd_server_connection *sconn = req->sconn;
1310 bool backup_priv = false;
1311 bool as_root = false;
1312 files_struct *fsp = NULL;
1313 const struct loadparm_substitution *lp_sub =
1314 loadparm_s3_global_substitution();
1316 if (total_params < 13) {
1317 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1321 dptr_num = SVAL(params,0);
1322 maxentries = SVAL(params,2);
1323 info_level = SVAL(params,4);
1324 resume_key = IVAL(params,6);
1325 findnext_flags = SVAL(params,10);
1326 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1327 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1328 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1329 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1331 if (!continue_bit) {
1332 /* We only need resume_name if continue_bit is zero. */
1333 if (req->posix_pathnames) {
1334 srvstr_get_path_posix(ctx,
1343 srvstr_get_path(ctx,
1352 if (!NT_STATUS_IS_OK(ntstatus)) {
1353 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1354 complain (it thinks we're asking for the directory above the shared
1355 path or an invalid name). Catch this as the resume name is only compared, never used in
1356 a file access. JRA. */
1357 srvstr_pull_talloc(ctx, params, req->flags2,
1358 &resume_name, params+12,
1362 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
1363 reply_nterror(req, ntstatus);
1369 DBG_NOTICE("dirhandle = %d, max_data_bytes = %u, maxentries = %d, "
1370 "close_after_request=%d, close_if_end = %d "
1371 "requires_resume_key = %d resume_key = %d "
1372 "resume name = %s continue=%d level = %d\n",
1376 close_after_request,
1378 requires_resume_key,
1380 resume_name ? resume_name : "(NULL)",
1385 /* W2K3 seems to treat zero as 1. */
1389 switch (info_level) {
1390 case SMB_FIND_INFO_STANDARD:
1391 case SMB_FIND_EA_SIZE:
1392 case SMB_FIND_EA_LIST:
1393 case SMB_FIND_FILE_DIRECTORY_INFO:
1394 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1395 case SMB_FIND_FILE_NAMES_INFO:
1396 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1397 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1398 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1400 case SMB_FIND_FILE_UNIX:
1401 case SMB_FIND_FILE_UNIX_INFO2:
1402 if (!lp_smb1_unix_extensions()) {
1403 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1406 if (!req->posix_pathnames) {
1407 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1412 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1416 if (info_level == SMB_FIND_EA_LIST) {
1419 if (total_data < 4) {
1420 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1424 ea_size = IVAL(pdata,0);
1425 if (ea_size != total_data) {
1426 DBG_NOTICE("Rejecting EA request with incorrect "
1427 "total_data=%d (should be %" PRIu32 ")\n",
1430 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1434 if (!lp_ea_support(SNUM(conn))) {
1435 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1439 /* Pull out the list of names. */
1440 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1442 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1447 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1448 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1452 *ppdata = (char *)SMB_REALLOC(
1453 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1454 if(*ppdata == NULL) {
1455 reply_nterror(req, NT_STATUS_NO_MEMORY);
1460 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1463 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
1466 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
1467 /* Realloc the params space */
1468 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1469 if(*pparams == NULL ) {
1470 reply_nterror(req, NT_STATUS_NO_MEMORY);
1476 /* Check that the dptr is valid */
1477 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
1479 reply_nterror(req, STATUS_NO_MORE_FILES);
1483 directory = dptr_path(sconn, dptr_num);
1485 /* Get the wildcard mask from the dptr */
1486 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
1487 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1488 reply_nterror(req, STATUS_NO_MORE_FILES);
1492 /* Get the attr mask from the dptr */
1493 dirtype = dptr_attr(sconn, dptr_num);
1495 backup_priv = dptr_get_priv(fsp->dptr);
1497 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX) "
1498 "backup_priv = %d\n",
1499 dptr_num, mask, dirtype,
1503 /* We don't need to check for VOL here as this is returned by
1504 a different TRANS2 call. */
1506 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1507 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1508 if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),
1509 dptr_case_sensitive(fsp->dptr)))
1510 dont_descend = True;
1513 space_remaining = max_data_bytes;
1514 out_of_space = False;
1522 * Seek to the correct position. We no longer use the resume key but
1523 * depend on the last file name instead.
1526 if(!continue_bit && resume_name && *resume_name) {
1527 bool posix_open = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN);
1528 char *last_name_sent = NULL;
1532 * Remember, name_to_8_3 is called by
1533 * get_lanman2_dir_entry(), so the resume name
1534 * could be mangled. Ensure we check the unmangled name.
1538 mangle_is_mangled(resume_name, conn->params)) {
1539 char *new_resume_name = NULL;
1540 mangle_lookup_name_from_8_3(ctx,
1544 if (new_resume_name) {
1545 resume_name = new_resume_name;
1550 * Fix for NT redirector problem triggered by resume key indexes
1551 * changing between directory scans. We now return a resume key of 0
1552 * and instead look for the filename to continue from (also given
1553 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1554 * findfirst/findnext (as is usual) then the directory pointer
1555 * should already be at the correct place.
1558 last_name_sent = smbd_dirptr_get_last_name_sent(fsp->dptr);
1559 sequential = smbd_dptr_name_equal(fsp->dptr,
1567 dptr_RewindDir(fsp->dptr);
1569 while ((name = dptr_ReadDirName(talloc_tos(),
1572 found = smbd_dptr_name_equal(fsp->dptr,
1583 * We got a name that used to exist
1584 * but does not anymore. Just start
1585 * from the beginning. Shown by the
1586 * "raw.search.os2 delete" smbtorture
1589 dptr_RewindDir(fsp->dptr);
1592 } /* end if resume_name && !continue_bit */
1594 ask_sharemode = fsp_search_ask_sharemode(fsp);
1596 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1597 bool got_exact_match = False;
1599 /* this is a heuristic to avoid seeking the fsp->dptr except when
1600 absolutely necessary. It allows for a filename of about 40 chars */
1601 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1602 out_of_space = True;
1605 ntstatus = get_lanman2_dir_entry(ctx,
1609 mask,dirtype,info_level,
1610 requires_resume_key,dont_descend,
1615 &last_entry_off, ea_list);
1616 if (NT_STATUS_EQUAL(ntstatus,
1617 NT_STATUS_ILLEGAL_CHARACTER)) {
1619 * Bad character conversion on name. Ignore this
1624 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
1625 out_of_space = true;
1627 finished = !NT_STATUS_IS_OK(ntstatus);
1631 if (!finished && !out_of_space) {
1636 * As an optimisation if we know we aren't looking
1637 * for a wildcard name (ie. the name matches the wildcard exactly)
1638 * then we can finish on any (first) match.
1639 * This speeds up large directory searches. JRA.
1642 if (got_exact_match) {
1646 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1649 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1650 smb_fn_name(req->cmd),
1651 mask, directory, dirtype, numentries ) );
1653 /* Check if we can close the fsp->dptr */
1654 if(close_after_request || (finished && close_if_end)) {
1655 DBG_INFO("closing dptr_num = %d\n", dptr_num);
1657 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1664 /* Set up the return parameter block */
1665 SSVAL(params,0,numentries);
1666 SSVAL(params,2,finished);
1667 SSVAL(params,4,0); /* Never an EA error */
1668 SSVAL(params,6,last_entry_off);
1670 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
1676 /****************************************************************************
1677 Reply to a TRANS2_QFSINFO (query filesystem info).
1678 ****************************************************************************/
1680 static void call_trans2qfsinfo(connection_struct *conn,
1681 struct smb_request *req,
1682 char **pparams, int total_params,
1683 char **ppdata, int total_data,
1684 unsigned int max_data_bytes)
1686 char *params = *pparams;
1687 uint16_t info_level;
1689 size_t fixed_portion;
1692 if (total_params < 2) {
1693 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1697 info_level = SVAL(params,0);
1699 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
1700 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
1701 DEBUG(0,("call_trans2qfsinfo: encryption required "
1702 "and info level 0x%x sent.\n",
1703 (unsigned int)info_level));
1704 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1709 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1711 status = smbd_do_qfsinfo(req->xconn, conn, req,
1718 if (!NT_STATUS_IS_OK(status)) {
1719 reply_nterror(req, status);
1723 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
1726 DEBUG( 4, ( "%s info_level = %d\n",
1727 smb_fn_name(req->cmd), info_level) );
1732 /****************************************************************************
1733 Reply to a TRANS2_SETFSINFO (set filesystem info).
1734 ****************************************************************************/
1736 static void call_trans2setfsinfo(connection_struct *conn,
1737 struct smb_request *req,
1738 char **pparams, int total_params,
1739 char **ppdata, int total_data,
1740 unsigned int max_data_bytes)
1742 const struct loadparm_substitution *lp_sub =
1743 loadparm_s3_global_substitution();
1744 struct smbXsrv_connection *xconn = req->xconn;
1745 char *pdata = *ppdata;
1746 char *params = *pparams;
1747 uint16_t info_level;
1749 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
1750 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
1753 if (total_params < 4) {
1754 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1756 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1760 info_level = SVAL(params,2);
1763 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
1764 info_level != SMB_SET_CIFS_UNIX_INFO) {
1765 DEBUG(0,("call_trans2setfsinfo: not an allowed "
1766 "info level (0x%x) on IPC$.\n",
1767 (unsigned int)info_level));
1768 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1773 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
1774 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
1775 DEBUG(0,("call_trans2setfsinfo: encryption required "
1776 "and info level 0x%x sent.\n",
1777 (unsigned int)info_level));
1778 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1783 switch(info_level) {
1784 case SMB_SET_CIFS_UNIX_INFO:
1785 if (!lp_smb1_unix_extensions()) {
1786 DEBUG(2,("call_trans2setfsinfo: "
1787 "SMB_SET_CIFS_UNIX_INFO is invalid with "
1788 "unix extensions off\n"));
1790 NT_STATUS_INVALID_LEVEL);
1794 /* There should be 12 bytes of capabilities set. */
1795 if (total_data < 12) {
1798 NT_STATUS_INVALID_PARAMETER);
1801 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
1802 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
1803 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
1804 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
1806 /* Just print these values for now. */
1807 DBG_DEBUG("set unix_info info. "
1808 "major = %"PRIu16", minor = %"PRIu16
1809 "cap_low = 0x%"PRIx32", "
1810 "cap_high = 0x%"PRIx32"\n",
1811 xconn->smb1.unix_info.client_major,
1812 xconn->smb1.unix_info.client_minor,
1813 xconn->smb1.unix_info.client_cap_low,
1814 xconn->smb1.unix_info.client_cap_high);
1817 * Here is where we must switch to posix
1818 * pathname processing...
1820 if (xconn->smb1.unix_info.client_cap_low &
1821 CIFS_UNIX_POSIX_PATHNAMES_CAP)
1823 lp_set_posix_pathnames();
1824 mangle_change_to_posix();
1827 if ((xconn->smb1.unix_info.client_cap_low &
1828 CIFS_UNIX_FCNTL_LOCKS_CAP) &&
1829 !(xconn->smb1.unix_info.client_cap_low &
1830 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP))
1832 /* Client that knows how to do posix locks,
1833 * but not posix open/mkdir operations. Set a
1834 * default type for read/write checks. */
1836 lp_set_posix_default_cifsx_readwrite_locktype(
1842 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
1845 size_t param_len = 0;
1846 size_t data_len = total_data;
1848 if (!lp_smb1_unix_extensions()) {
1851 NT_STATUS_INVALID_LEVEL);
1855 if (lp_server_smb_encrypt(SNUM(conn)) ==
1856 SMB_ENCRYPTION_OFF) {
1859 NT_STATUS_NOT_SUPPORTED);
1863 if (xconn->smb1.echo_handler.trusted_fde) {
1864 DEBUG( 2,("call_trans2setfsinfo: "
1865 "request transport encryption disabled"
1866 "with 'fork echo handler = yes'\n"));
1869 NT_STATUS_NOT_SUPPORTED);
1873 DEBUG( 4,("call_trans2setfsinfo: "
1874 "request transport encryption.\n"));
1876 status = srv_request_encryption_setup(conn,
1877 (unsigned char **)ppdata,
1879 (unsigned char **)pparams,
1882 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
1883 !NT_STATUS_IS_OK(status)) {
1884 reply_nterror(req, status);
1888 send_trans2_replies(conn, req,
1896 if (NT_STATUS_IS_OK(status)) {
1897 /* Server-side transport
1898 * encryption is now *on*. */
1899 status = srv_encryption_start(conn);
1900 if (!NT_STATUS_IS_OK(status)) {
1901 char *reason = talloc_asprintf(talloc_tos(),
1902 "Failure in setting "
1903 "up encrypted transport: %s",
1905 exit_server_cleanly(reason);
1911 case SMB_FS_QUOTA_INFORMATION:
1915 .data = (uint8_t *)pdata,
1916 .length = total_data
1918 files_struct *fsp = NULL;
1919 fsp = file_fsp(req, SVAL(params,0));
1921 status = smb_set_fsquota(conn,
1925 if (!NT_STATUS_IS_OK(status)) {
1926 reply_nterror(req, status);
1932 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1934 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1940 * sending this reply works fine,
1941 * but I'm not sure it's the same
1942 * like windows do...
1945 reply_smb1_outbuf(req, 10, 0);
1948 /****************************************************************************
1949 Reply to a TRANSACT2_QFILEINFO on a PIPE !
1950 ****************************************************************************/
1952 static void call_trans2qpipeinfo(connection_struct *conn,
1953 struct smb_request *req,
1955 uint16_t info_level,
1956 unsigned int tran_call,
1957 char **pparams, int total_params,
1958 char **ppdata, int total_data,
1959 unsigned int max_data_bytes)
1961 char *params = *pparams;
1962 char *pdata = *ppdata;
1963 unsigned int data_size = 0;
1964 unsigned int param_size = 2;
1966 if (!fsp_is_np(fsp)) {
1967 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1971 *pparams = (char *)SMB_REALLOC(*pparams,2);
1972 if (*pparams == NULL) {
1973 reply_nterror(req, NT_STATUS_NO_MEMORY);
1978 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1982 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
1983 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
1984 if (*ppdata == NULL ) {
1985 reply_nterror(req, NT_STATUS_NO_MEMORY);
1990 switch (info_level) {
1991 case SMB_FILE_STANDARD_INFORMATION:
1993 SOFF_T(pdata,0,4096LL);
2000 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2004 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
2010 static void handle_trans2qfilepathinfo_result(
2011 connection_struct *conn,
2012 struct smb_request *req,
2013 uint16_t info_level,
2016 int data_return_size,
2017 size_t fixed_portion,
2018 unsigned int max_data_bytes)
2020 char params[2] = { 0, 0, };
2024 * draft-leach-cifs-v1-spec-02.txt
2025 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
2028 * The requested information is placed in the Data portion of the
2029 * transaction response. For the information levels greater than 0x100,
2030 * the transaction response has 1 parameter word which should be
2031 * ignored by the client.
2033 * However Windows only follows this rule for the IS_NAME_VALID call.
2035 switch (info_level) {
2036 case SMB_INFO_IS_NAME_VALID:
2041 if (!NT_STATUS_IS_OK(status)) {
2042 if (open_was_deferred(req->xconn, req->mid)) {
2043 /* We have re-scheduled this call. */
2046 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2047 bool ok = defer_smb1_sharing_violation(req);
2052 reply_nterror(req, status);
2056 if (fixed_portion > max_data_bytes) {
2057 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
2061 send_trans2_replies(
2072 /****************************************************************************
2073 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2074 file name or file id).
2075 ****************************************************************************/
2077 static void call_trans2qfilepathinfo(connection_struct *conn,
2078 struct smb_request *req,
2079 unsigned int tran_call,
2080 uint16_t info_level,
2081 struct smb_filename *smb_fname,
2082 struct files_struct *fsp,
2083 bool delete_pending,
2084 struct timespec write_time_ts,
2085 char **pparams, int total_params,
2086 char **ppdata, int total_data,
2087 unsigned int max_data_bytes)
2089 char *params = *pparams;
2090 char *pdata = *ppdata;
2091 unsigned int data_size = 0;
2092 struct ea_list *ea_list = NULL;
2093 size_t fixed_portion;
2094 NTSTATUS status = NT_STATUS_OK;
2096 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
2097 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
2099 info_level,tran_call,total_data));
2101 /* Pull out any data sent here before we realloc. */
2102 switch (info_level) {
2103 case SMB_INFO_QUERY_EAS_FROM_LIST:
2105 /* Pull any EA list from the data portion. */
2108 if (total_data < 4) {
2110 req, NT_STATUS_INVALID_PARAMETER);
2113 ea_size = IVAL(pdata,0);
2115 if (total_data > 0 && ea_size != total_data) {
2116 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2117 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2119 req, NT_STATUS_INVALID_PARAMETER);
2123 if (!lp_ea_support(SNUM(conn))) {
2124 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2128 /* Pull out the list of names. */
2129 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
2132 req, NT_STATUS_INVALID_PARAMETER);
2142 *pparams = (char *)SMB_REALLOC(*pparams,2);
2143 if (*pparams == NULL) {
2144 reply_nterror(req, NT_STATUS_NO_MEMORY);
2150 if ((info_level & SMB2_INFO_SPECIAL) == SMB2_INFO_SPECIAL) {
2152 * We use levels that start with 0xFF00
2153 * internally to represent SMB2 specific levels
2155 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2159 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
2161 delete_pending, write_time_ts,
2163 req->flags2, max_data_bytes,
2165 ppdata, &data_size);
2167 handle_trans2qfilepathinfo_result(
2178 static NTSTATUS smb_q_unix_basic(
2179 struct connection_struct *conn,
2180 struct smb_request *req,
2181 struct smb_filename *smb_fname,
2182 struct files_struct *fsp,
2186 const int total_data = 100;
2188 *ppdata = SMB_REALLOC(*ppdata, total_data);
2189 if (*ppdata == NULL) {
2190 return NT_STATUS_NO_MEMORY;
2192 store_file_unix_basic(conn, *ppdata, fsp, &smb_fname->st);
2194 *ptotal_data = total_data;
2196 return NT_STATUS_OK;
2199 static NTSTATUS smb_q_unix_info2(
2200 struct connection_struct *conn,
2201 struct smb_request *req,
2202 struct smb_filename *smb_fname,
2203 struct files_struct *fsp,
2207 const int total_data = 116;
2209 *ppdata = SMB_REALLOC(*ppdata, total_data);
2210 if (*ppdata == NULL) {
2211 return NT_STATUS_NO_MEMORY;
2213 store_file_unix_basic_info2(conn, *ppdata, fsp, &smb_fname->st);
2215 *ptotal_data = total_data;
2217 return NT_STATUS_OK;
2220 #if defined(HAVE_POSIX_ACLS)
2221 /****************************************************************************
2222 Utility function to open a fsp for a POSIX handle operation.
2223 ****************************************************************************/
2225 static NTSTATUS get_posix_fsp(connection_struct *conn,
2226 struct smb_request *req,
2227 struct smb_filename *smb_fname,
2228 uint32_t access_mask,
2229 files_struct **ret_fsp)
2232 uint32_t create_disposition = FILE_OPEN;
2233 uint32_t share_access = FILE_SHARE_READ|
2236 struct smb2_create_blobs *posx = NULL;
2239 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
2240 * but set reasonable defaults.
2242 uint32_t file_attributes = 0664;
2243 uint32_t oplock = NO_OPLOCK;
2244 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
2246 /* File or directory must exist. */
2247 if (!VALID_STAT(smb_fname->st)) {
2248 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2250 /* Cannot be a symlink. */
2251 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
2252 return NT_STATUS_ACCESS_DENIED;
2254 /* Set options correctly for directory open. */
2255 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
2257 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
2258 * directories, but set reasonable defaults.
2260 file_attributes = 0775;
2261 create_options = FILE_DIRECTORY_FILE;
2264 status = make_smb2_posix_create_ctx(
2265 talloc_tos(), &posx, file_attributes);
2266 if (!NT_STATUS_IS_OK(status)) {
2267 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
2272 status = SMB_VFS_CREATE_FILE(
2276 smb_fname, /* fname */
2277 access_mask, /* access_mask */
2278 share_access, /* share_access */
2279 create_disposition,/* create_disposition*/
2280 create_options, /* create_options */
2281 file_attributes,/* file_attributes */
2282 oplock, /* oplock_request */
2284 0, /* allocation_size */
2285 0, /* private_flags */
2288 ret_fsp, /* result */
2290 posx, /* in_context */
2291 NULL); /* out_context */
2298 /****************************************************************************
2299 Utility function to count the number of entries in a POSIX acl.
2300 ****************************************************************************/
2302 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2304 unsigned int ace_count = 0;
2305 int entry_id = SMB_ACL_FIRST_ENTRY;
2306 SMB_ACL_ENTRY_T entry;
2308 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2309 entry_id = SMB_ACL_NEXT_ENTRY;
2315 /****************************************************************************
2316 Utility function to marshall a POSIX acl into wire format.
2317 ****************************************************************************/
2319 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2321 int entry_id = SMB_ACL_FIRST_ENTRY;
2322 SMB_ACL_ENTRY_T entry;
2324 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2325 SMB_ACL_TAG_T tagtype;
2326 SMB_ACL_PERMSET_T permset;
2327 unsigned char perms = 0;
2328 unsigned int own_grp;
2330 entry_id = SMB_ACL_NEXT_ENTRY;
2332 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
2333 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2337 if (sys_acl_get_permset(entry, &permset) == -1) {
2338 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2342 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2343 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2344 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2346 SCVAL(pdata,1,perms);
2349 case SMB_ACL_USER_OBJ:
2350 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2351 own_grp = (unsigned int)pst->st_ex_uid;
2352 SIVAL(pdata,2,own_grp);
2357 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
2359 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2362 own_grp = (unsigned int)*puid;
2363 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2364 SIVAL(pdata,2,own_grp);
2368 case SMB_ACL_GROUP_OBJ:
2369 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2370 own_grp = (unsigned int)pst->st_ex_gid;
2371 SIVAL(pdata,2,own_grp);
2376 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
2378 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2381 own_grp = (unsigned int)*pgid;
2382 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2383 SIVAL(pdata,2,own_grp);
2388 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2389 SIVAL(pdata,2,0xFFFFFFFF);
2390 SIVAL(pdata,6,0xFFFFFFFF);
2393 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2394 SIVAL(pdata,2,0xFFFFFFFF);
2395 SIVAL(pdata,6,0xFFFFFFFF);
2398 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2401 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2408 static NTSTATUS smb_q_posix_acl(
2409 struct connection_struct *conn,
2410 struct smb_request *req,
2411 struct smb_filename *smb_fname,
2412 struct files_struct *fsp,
2416 #if !defined(HAVE_POSIX_ACLS)
2417 return NT_STATUS_INVALID_LEVEL;
2420 SMB_ACL_T file_acl = NULL;
2421 SMB_ACL_T def_acl = NULL;
2422 uint16_t num_file_acls = 0;
2423 uint16_t num_def_acls = 0;
2424 unsigned int size_needed = 0;
2427 bool close_fsp = false;
2430 * Ensure we always operate on a file descriptor, not just
2433 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
2434 uint32_t access_mask = SEC_STD_READ_CONTROL|
2435 FILE_READ_ATTRIBUTES|
2436 FILE_WRITE_ATTRIBUTES;
2438 status = get_posix_fsp(conn,
2444 if (!NT_STATUS_IS_OK(status)) {
2450 SMB_ASSERT(fsp != NULL);
2452 status = refuse_symlink_fsp(fsp);
2453 if (!NT_STATUS_IS_OK(status)) {
2457 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, SMB_ACL_TYPE_ACCESS,
2460 if (file_acl == NULL && no_acl_syscall_error(errno)) {
2461 DBG_INFO("ACLs not implemented on "
2462 "filesystem containing %s\n",
2464 status = NT_STATUS_NOT_IMPLEMENTED;
2468 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2470 * We can only have default POSIX ACLs on
2473 if (!fsp->fsp_flags.is_directory) {
2474 DBG_INFO("Non-directory open %s\n",
2476 status = NT_STATUS_INVALID_HANDLE;
2479 def_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
2480 SMB_ACL_TYPE_DEFAULT,
2482 def_acl = free_empty_sys_acl(conn, def_acl);
2485 num_file_acls = count_acl_entries(conn, file_acl);
2486 num_def_acls = count_acl_entries(conn, def_acl);
2489 if (num_file_acls + num_def_acls < num_file_acls) {
2490 status = NT_STATUS_INVALID_PARAMETER;
2494 size_needed = num_file_acls + num_def_acls;
2497 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
2498 * than UINT_MAX, so check by division.
2500 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
2501 status = NT_STATUS_INVALID_PARAMETER;
2505 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
2506 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
2507 status = NT_STATUS_INVALID_PARAMETER;
2510 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
2512 *ppdata = SMB_REALLOC(*ppdata, size_needed);
2513 if (*ppdata == NULL) {
2514 status = NT_STATUS_NO_MEMORY;
2519 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
2520 SSVAL(pdata,2,num_file_acls);
2521 SSVAL(pdata,4,num_def_acls);
2522 pdata += SMB_POSIX_ACL_HEADER_SIZE;
2524 ok = marshall_posix_acl(conn,
2529 status = NT_STATUS_INTERNAL_ERROR;
2532 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
2534 ok = marshall_posix_acl(conn,
2539 status = NT_STATUS_INTERNAL_ERROR;
2543 *ptotal_data = size_needed;
2544 status = NT_STATUS_OK;
2550 * Ensure the stat struct in smb_fname is up to
2551 * date. Structure copy.
2553 smb_fname->st = fsp->fsp_name->st;
2554 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
2557 TALLOC_FREE(file_acl);
2558 TALLOC_FREE(def_acl);
2563 static NTSTATUS smb_q_posix_symlink(
2564 struct connection_struct *conn,
2565 struct smb_request *req,
2566 struct smb_filename *smb_fname,
2570 char buffer[PATH_MAX+1];
2574 struct smb_filename *parent_fname = NULL;
2575 struct smb_filename *base_name = NULL;
2578 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
2579 smb_fname_str_dbg(smb_fname));
2581 if (!S_ISLNK(smb_fname->st.st_ex_mode)) {
2582 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
2585 status = parent_pathref(
2592 if (!NT_STATUS_IS_OK(status)) {
2593 DBG_DEBUG("parent_pathref failed: %s\n", nt_errstr(status));
2597 link_len = SMB_VFS_READLINKAT(
2603 TALLOC_FREE(parent_fname);
2605 if (link_len == -1) {
2606 status = map_nt_error_from_unix(errno);
2607 DBG_DEBUG("READLINKAT failed: %s\n", nt_errstr(status));
2610 if (link_len >= sizeof(buffer)) {
2611 return NT_STATUS_INTERNAL_ERROR;
2613 buffer[link_len] = 0;
2615 needed = (link_len+1)*2;
2617 *ppdata = SMB_REALLOC(*ppdata, needed);
2618 if (*ppdata == NULL) {
2619 return NT_STATUS_NO_MEMORY;
2623 status = srvstr_push(
2631 if (!NT_STATUS_IS_OK(status)) {
2636 return NT_STATUS_OK;
2639 static void call_trans2qpathinfo(
2640 connection_struct *conn,
2641 struct smb_request *req,
2646 unsigned int max_data_bytes)
2648 char *params = *pparams;
2649 uint16_t info_level;
2650 struct smb_filename *smb_fname = NULL;
2651 bool delete_pending = False;
2652 struct timespec write_time_ts = { .tv_sec = 0, };
2653 struct files_struct *dirfsp = NULL;
2654 files_struct *fsp = NULL;
2655 struct file_id fileid;
2658 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2660 bool info_level_handled;
2661 NTSTATUS status = NT_STATUS_OK;
2665 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2671 if (total_params < 7) {
2672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2676 info_level = SVAL(params,0);
2678 DBG_NOTICE("TRANSACT2_QPATHINFO: level = %d\n", info_level);
2680 if (INFO_LEVEL_IS_UNIX(info_level)) {
2681 if (!lp_smb1_unix_extensions()) {
2682 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2685 if (!req->posix_pathnames) {
2686 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2691 if (req->posix_pathnames) {
2692 srvstr_get_path_posix(req,
2701 srvstr_get_path(req,
2710 if (!NT_STATUS_IS_OK(status)) {
2711 reply_nterror(req, status);
2715 if (ucf_flags & UCF_GMT_PATHNAME) {
2716 extract_snapshot_token(fname, &twrp);
2718 status = smb1_strip_dfs_path(req, &ucf_flags, &fname);
2719 if (!NT_STATUS_IS_OK(status)) {
2720 reply_nterror(req, status);
2723 status = filename_convert_dirfsp(req,
2730 if (!NT_STATUS_IS_OK(status)) {
2731 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2732 reply_botherror(req,
2733 NT_STATUS_PATH_NOT_COVERED,
2734 ERRSRV, ERRbadpath);
2737 reply_nterror(req, status);
2742 * qpathinfo must operate on an existing file, so we
2743 * can exit early if filename_convert_dirfsp() returned the
2744 * "new file" NT_STATUS_OK, !VALID_STAT case.
2747 if (!VALID_STAT(smb_fname->st)) {
2748 reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2753 * smb_fname->fsp may be NULL if smb_fname points at a symlink
2754 * and we're in POSIX context, so be careful when using fsp
2755 * below, it can still be NULL.
2757 fsp = smb_fname->fsp;
2759 /* If this is a stream, check if there is a delete_pending. */
2760 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
2761 && is_ntfs_stream_smb_fname(smb_fname)) {
2762 struct smb_filename *smb_fname_base;
2764 /* Create an smb_filename with stream_name == NULL. */
2765 smb_fname_base = synthetic_smb_fname(
2767 smb_fname->base_name,
2772 if (smb_fname_base == NULL) {
2773 reply_nterror(req, NT_STATUS_NO_MEMORY);
2777 ret = vfs_stat(conn, smb_fname_base);
2779 DBG_NOTICE("vfs_stat of %s failed "
2781 smb_fname_str_dbg(smb_fname_base),
2783 TALLOC_FREE(smb_fname_base);
2785 map_nt_error_from_unix(errno));
2789 status = file_name_hash(conn,
2790 smb_fname_str_dbg(smb_fname_base),
2792 if (!NT_STATUS_IS_OK(status)) {
2793 TALLOC_FREE(smb_fname_base);
2794 reply_nterror(req, status);
2798 fileid = vfs_file_id_from_sbuf(conn,
2799 &smb_fname_base->st);
2800 TALLOC_FREE(smb_fname_base);
2801 get_file_infos(fileid, name_hash, &delete_pending, NULL);
2802 if (delete_pending) {
2803 reply_nterror(req, NT_STATUS_DELETE_PENDING);
2808 status = file_name_hash(conn,
2809 smb_fname_str_dbg(smb_fname),
2811 if (!NT_STATUS_IS_OK(status)) {
2812 reply_nterror(req, status);
2816 if (fsp_getinfo_ask_sharemode(fsp)) {
2817 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2818 get_file_infos(fileid, name_hash, &delete_pending,
2822 if (delete_pending) {
2823 reply_nterror(req, NT_STATUS_DELETE_PENDING);
2827 info_level_handled = true; /* Untouched in switch cases below */
2829 switch (info_level) {
2832 info_level_handled = false;
2835 case SMB_QUERY_FILE_UNIX_BASIC:
2836 status = smb_q_unix_basic(
2845 case SMB_QUERY_FILE_UNIX_INFO2:
2846 status = smb_q_unix_info2(
2855 case SMB_QUERY_POSIX_ACL:
2856 status = smb_q_posix_acl(
2865 case SMB_QUERY_FILE_UNIX_LINK:
2866 status = smb_q_posix_symlink(
2875 if (info_level_handled) {
2876 handle_trans2qfilepathinfo_result(
2888 call_trans2qfilepathinfo(
2891 TRANSACT2_QPATHINFO,
2904 static NTSTATUS smb_q_posix_lock(
2905 struct connection_struct *conn,
2906 struct smb_request *req,
2907 struct files_struct *fsp,
2911 char *pdata = *ppdata;
2912 int total_data = *ptotal_data;
2916 enum brl_type lock_type;
2919 if (fsp->fsp_flags.is_pathref || (fsp_get_io_fd(fsp) == -1)) {
2920 return NT_STATUS_INVALID_HANDLE;
2923 if (total_data != POSIX_LOCK_DATA_SIZE) {
2924 return NT_STATUS_INVALID_PARAMETER;
2927 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
2928 case POSIX_LOCK_TYPE_READ:
2929 lock_type = READ_LOCK;
2931 case POSIX_LOCK_TYPE_WRITE:
2932 lock_type = WRITE_LOCK;
2934 case POSIX_LOCK_TYPE_UNLOCK:
2936 /* There's no point in asking for an unlock... */
2937 return NT_STATUS_INVALID_PARAMETER;
2940 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
2941 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
2942 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
2944 status = query_lock(
2952 if (NT_STATUS_IS_OK(status)) {
2954 * For success we just return a copy of what we sent
2955 * with the lock type set to POSIX_LOCK_TYPE_UNLOCK.
2957 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
2958 return NT_STATUS_OK;
2961 if (!ERROR_WAS_LOCK_DENIED(status)) {
2962 DBG_DEBUG("query_lock() failed: %s\n", nt_errstr(status));
2967 * Here we need to report who has it locked.
2970 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
2971 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
2972 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
2973 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
2974 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
2976 return NT_STATUS_OK;
2979 static void call_trans2qfileinfo(
2980 connection_struct *conn,
2981 struct smb_request *req,
2986 unsigned int max_data_bytes)
2988 char *params = *pparams;
2989 uint16_t info_level;
2990 struct smb_filename *smb_fname = NULL;
2991 bool delete_pending = False;
2992 struct timespec write_time_ts = { .tv_sec = 0, };
2993 files_struct *fsp = NULL;
2994 struct file_id fileid;
2995 bool info_level_handled;
2996 NTSTATUS status = NT_STATUS_OK;
2999 if (params == NULL) {
3000 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3004 if (total_params < 4) {
3005 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3009 fsp = file_fsp(req, SVAL(params,0));
3010 info_level = SVAL(params,2);
3013 call_trans2qpipeinfo(
3018 TRANSACT2_QFILEINFO,
3027 DBG_NOTICE("TRANSACT2_QFILEINFO: level = %d\n", info_level);
3029 if (INFO_LEVEL_IS_UNIX(info_level)) {
3030 if (!lp_smb1_unix_extensions()) {
3031 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3034 if (!req->posix_pathnames) {
3035 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3040 /* Initial check for valid fsp ptr. */
3041 if (!check_fsp_open(conn, req, fsp)) {
3045 smb_fname = fsp->fsp_name;
3047 if(fsp->fake_file_handle) {
3049 * This is actually for the QUOTA_FAKE_FILE --metze
3052 /* We know this name is ok, it's already passed the checks. */
3054 } else if(fsp_get_pathref_fd(fsp) == -1) {
3056 * This is actually a QFILEINFO on a directory
3057 * handle (returned from an NT SMB). NT5.0 seems
3058 * to do this call. JRA.
3060 ret = vfs_stat(conn, smb_fname);
3062 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
3063 smb_fname_str_dbg(smb_fname),
3066 map_nt_error_from_unix(errno));
3070 if (fsp_getinfo_ask_sharemode(fsp)) {
3071 fileid = vfs_file_id_from_sbuf(
3072 conn, &smb_fname->st);
3073 get_file_infos(fileid, fsp->name_hash,
3079 * Original code - this is an open file.
3081 status = vfs_stat_fsp(fsp);
3082 if (!NT_STATUS_IS_OK(status)) {
3083 DEBUG(3, ("fstat of %s failed (%s)\n",
3084 fsp_fnum_dbg(fsp), nt_errstr(status)));
3085 reply_nterror(req, status);
3088 if (fsp_getinfo_ask_sharemode(fsp)) {
3089 fileid = vfs_file_id_from_sbuf(
3090 conn, &smb_fname->st);
3091 get_file_infos(fileid, fsp->name_hash,
3097 info_level_handled = true; /* Untouched in switch cases below */
3099 switch (info_level) {
3102 info_level_handled = false;
3105 case SMB_QUERY_POSIX_LOCK:
3106 status = smb_q_posix_lock(conn, req, fsp, ppdata, &total_data);
3109 case SMB_QUERY_FILE_UNIX_BASIC:
3110 status = smb_q_unix_basic(
3111 conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3114 case SMB_QUERY_FILE_UNIX_INFO2:
3115 status = smb_q_unix_info2(
3116 conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3119 case SMB_QUERY_POSIX_ACL:
3120 status = smb_q_posix_acl(
3121 conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3125 if (info_level_handled) {
3126 handle_trans2qfilepathinfo_result(
3138 call_trans2qfilepathinfo(
3141 TRANSACT2_QFILEINFO,
3154 static void handle_trans2setfilepathinfo_result(
3155 connection_struct *conn,
3156 struct smb_request *req,
3157 uint16_t info_level,
3160 int data_return_size,
3161 unsigned int max_data_bytes)
3163 char params[2] = { 0, 0, };
3165 if (NT_STATUS_IS_OK(status)) {
3166 send_trans2_replies(
3178 if (open_was_deferred(req->xconn, req->mid)) {
3179 /* We have re-scheduled this call. */
3183 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3184 bool ok = defer_smb1_sharing_violation(req);
3190 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
3191 /* We have re-scheduled this call. */
3195 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3198 NT_STATUS_PATH_NOT_COVERED,
3204 if (info_level == SMB_POSIX_PATH_OPEN) {
3205 reply_openerror(req, status);
3209 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
3211 * Invalid EA name needs to return 2 param bytes,
3212 * not a zero-length error packet.
3215 send_trans2_replies(
3227 reply_nterror(req, status);
3230 /****************************************************************************
3231 Create a directory with POSIX semantics.
3232 ****************************************************************************/
3234 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
3235 struct smb_request *req,
3238 struct smb_filename *smb_fname,
3239 int *pdata_return_size)
3241 NTSTATUS status = NT_STATUS_OK;
3242 uint32_t raw_unixmode = 0;
3243 mode_t unixmode = (mode_t)0;
3244 files_struct *fsp = NULL;
3245 uint16_t info_level_return = 0;
3247 char *pdata = *ppdata;
3248 struct smb2_create_blobs *posx = NULL;
3250 if (total_data < 18) {
3251 return NT_STATUS_INVALID_PARAMETER;
3254 raw_unixmode = IVAL(pdata,8);
3255 /* Next 4 bytes are not yet defined. */
3257 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
3258 PERM_NEW_DIR, &unixmode);
3259 if (!NT_STATUS_IS_OK(status)) {
3263 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
3264 if (!NT_STATUS_IS_OK(status)) {
3265 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3270 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
3271 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
3273 status = SMB_VFS_CREATE_FILE(
3277 smb_fname, /* fname */
3278 FILE_READ_ATTRIBUTES, /* access_mask */
3279 FILE_SHARE_NONE, /* share_access */
3280 FILE_CREATE, /* create_disposition*/
3281 FILE_DIRECTORY_FILE, /* create_options */
3282 0, /* file_attributes */
3283 0, /* oplock_request */
3285 0, /* allocation_size */
3286 0, /* private_flags */
3291 posx, /* in_context_blobs */
3292 NULL); /* out_context_blobs */
3296 if (NT_STATUS_IS_OK(status)) {
3297 close_file_free(req, &fsp, NORMAL_CLOSE);
3300 info_level_return = SVAL(pdata,16);
3302 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
3303 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
3304 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
3305 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
3307 *pdata_return_size = 12;
3310 /* Realloc the data size */
3311 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
3312 if (*ppdata == NULL) {
3313 *pdata_return_size = 0;
3314 return NT_STATUS_NO_MEMORY;
3318 SSVAL(pdata,0,NO_OPLOCK_RETURN);
3319 SSVAL(pdata,2,0); /* No fnum. */
3320 SIVAL(pdata,4,info); /* Was directory created. */
3322 switch (info_level_return) {
3323 case SMB_QUERY_FILE_UNIX_BASIC:
3324 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
3325 SSVAL(pdata,10,0); /* Padding. */
3326 store_file_unix_basic(conn, pdata + 12, fsp,
3329 case SMB_QUERY_FILE_UNIX_INFO2:
3330 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
3331 SSVAL(pdata,10,0); /* Padding. */
3332 store_file_unix_basic_info2(conn, pdata + 12, fsp,
3336 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
3337 SSVAL(pdata,10,0); /* Padding. */
3344 /****************************************************************************
3345 Open/Create a file with POSIX semantics.
3346 ****************************************************************************/
3348 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
3349 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
3351 static NTSTATUS smb_posix_open(connection_struct *conn,
3352 struct smb_request *req,
3355 struct smb_filename *smb_fname,
3356 int *pdata_return_size)
3358 bool extended_oplock_granted = False;
3359 char *pdata = *ppdata;
3361 uint32_t wire_open_mode = 0;
3362 uint32_t raw_unixmode = 0;
3363 uint32_t attributes = 0;
3364 uint32_t create_disp = 0;
3365 uint32_t access_mask = 0;
3366 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
3367 NTSTATUS status = NT_STATUS_OK;
3368 mode_t unixmode = (mode_t)0;
3369 files_struct *fsp = NULL;
3370 int oplock_request = 0;
3372 uint16_t info_level_return = 0;
3373 struct smb2_create_blobs *posx = NULL;
3375 if (total_data < 18) {
3376 return NT_STATUS_INVALID_PARAMETER;
3379 flags = IVAL(pdata,0);
3380 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
3381 if (oplock_request) {
3382 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
3385 wire_open_mode = IVAL(pdata,4);
3387 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
3388 return smb_posix_mkdir(conn, req,
3395 switch (wire_open_mode & SMB_ACCMODE) {
3397 access_mask = SMB_O_RDONLY_MAPPING;
3400 access_mask = SMB_O_WRONLY_MAPPING;
3403 access_mask = (SMB_O_RDONLY_MAPPING|
3404 SMB_O_WRONLY_MAPPING);
3407 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
3408 (unsigned int)wire_open_mode ));
3409 return NT_STATUS_INVALID_PARAMETER;
3412 wire_open_mode &= ~SMB_ACCMODE;
3414 /* First take care of O_CREAT|O_EXCL interactions. */
3415 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
3416 case (SMB_O_CREAT | SMB_O_EXCL):
3417 /* File exists fail. File not exist create. */
3418 create_disp = FILE_CREATE;
3421 /* File exists open. File not exist create. */
3422 create_disp = FILE_OPEN_IF;
3425 /* O_EXCL on its own without O_CREAT is undefined.
3426 We deliberately ignore it as some versions of
3427 Linux CIFSFS can send a bare O_EXCL on the
3428 wire which other filesystems in the kernel
3429 ignore. See bug 9519 for details. */
3434 /* File exists open. File not exist fail. */
3435 create_disp = FILE_OPEN;
3438 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
3439 (unsigned int)wire_open_mode ));
3440 return NT_STATUS_INVALID_PARAMETER;
3443 /* Next factor in the effects of O_TRUNC. */
3444 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
3446 if (wire_open_mode & SMB_O_TRUNC) {
3447 switch (create_disp) {
3449 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
3450 /* Leave create_disp alone as
3451 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
3453 /* File exists fail. File not exist create. */
3456 /* SMB_O_CREAT | SMB_O_TRUNC */
3457 /* File exists overwrite. File not exist create. */
3458 create_disp = FILE_OVERWRITE_IF;
3462 /* File exists overwrite. File not exist fail. */
3463 create_disp = FILE_OVERWRITE;
3466 /* Cannot get here. */
3467 smb_panic("smb_posix_open: logic error");
3468 return NT_STATUS_INVALID_PARAMETER;
3472 raw_unixmode = IVAL(pdata,8);
3473 /* Next 4 bytes are not yet defined. */
3475 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
3476 (VALID_STAT(smb_fname->st) ?
3477 PERM_EXISTING_FILE : PERM_NEW_FILE),
3480 if (!NT_STATUS_IS_OK(status)) {
3484 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
3485 if (!NT_STATUS_IS_OK(status)) {
3486 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3491 if (wire_open_mode & SMB_O_SYNC) {
3492 create_options |= FILE_WRITE_THROUGH;
3494 if (wire_open_mode & SMB_O_APPEND) {
3495 access_mask |= FILE_APPEND_DATA;
3497 if (wire_open_mode & SMB_O_DIRECT) {
3498 attributes |= FILE_FLAG_NO_BUFFERING;
3501 if ((wire_open_mode & SMB_O_DIRECTORY) ||
3502 VALID_STAT_OF_DIR(smb_fname->st)) {
3503 if (access_mask != SMB_O_RDONLY_MAPPING) {
3504 return NT_STATUS_FILE_IS_A_DIRECTORY;
3506 create_options &= ~FILE_NON_DIRECTORY_FILE;
3507 create_options |= FILE_DIRECTORY_FILE;
3510 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
3511 smb_fname_str_dbg(smb_fname),
3512 (unsigned int)wire_open_mode,
3513 (unsigned int)unixmode ));
3515 status = SMB_VFS_CREATE_FILE(
3519 smb_fname, /* fname */
3520 access_mask, /* access_mask */
3521 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
3523 create_disp, /* create_disposition*/
3524 create_options, /* create_options */
3525 attributes, /* file_attributes */
3526 oplock_request, /* oplock_request */
3528 0, /* allocation_size */
3529 0, /* private_flags */
3534 posx, /* in_context_blobs */
3535 NULL); /* out_context_blobs */
3539 if (!NT_STATUS_IS_OK(status)) {
3543 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3544 extended_oplock_granted = True;
3547 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3548 extended_oplock_granted = True;
3551 info_level_return = SVAL(pdata,16);
3553 /* Allocate the correct return size. */
3555 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
3556 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
3557 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
3558 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
3560 *pdata_return_size = 12;
3563 /* Realloc the data size */
3564 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
3565 if (*ppdata == NULL) {
3566 close_file_free(req, &fsp, ERROR_CLOSE);
3567 *pdata_return_size = 0;
3568 return NT_STATUS_NO_MEMORY;
3572 if (extended_oplock_granted) {
3573 if (flags & REQUEST_BATCH_OPLOCK) {
3574 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
3576 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
3578 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
3579 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
3581 SSVAL(pdata,0,NO_OPLOCK_RETURN);
3584 SSVAL(pdata,2,fsp->fnum);
3585 SIVAL(pdata,4,info); /* Was file created etc. */
3587 switch (info_level_return) {
3588 case SMB_QUERY_FILE_UNIX_BASIC:
3589 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
3590 SSVAL(pdata,10,0); /* padding. */
3591 store_file_unix_basic(conn, pdata + 12, fsp,
3594 case SMB_QUERY_FILE_UNIX_INFO2:
3595 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
3596 SSVAL(pdata,10,0); /* padding. */
3597 store_file_unix_basic_info2(conn, pdata + 12, fsp,
3601 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
3602 SSVAL(pdata,10,0); /* padding. */
3605 return NT_STATUS_OK;
3608 /****************************************************************************
3609 Delete a file with POSIX semantics.
3610 ****************************************************************************/
3612 struct smb_posix_unlink_state {
3613 struct smb_filename *smb_fname;
3614 struct files_struct *fsp;
3618 static void smb_posix_unlink_locked(struct share_mode_lock *lck,
3621 struct smb_posix_unlink_state *state = private_data;
3623 bool other_nonposix_opens;
3625 other_nonposix_opens = has_other_nonposix_opens(lck, state->fsp);
3626 if (other_nonposix_opens) {
3627 /* Fail with sharing violation. */
3628 state->status = NT_STATUS_SHARING_VIOLATION;
3633 * Set the delete on close.
3635 state->status = smb_set_file_disposition_info(state->fsp->conn,
3642 static NTSTATUS smb_posix_unlink(connection_struct *conn,
3643 struct smb_request *req,
3646 struct smb_filename *smb_fname)
3648 struct smb_posix_unlink_state state = {};
3649 NTSTATUS status = NT_STATUS_OK;
3650 files_struct *fsp = NULL;
3653 int create_options = 0;
3654 struct smb2_create_blobs *posx = NULL;
3656 if (!CAN_WRITE(conn)) {
3657 return NT_STATUS_DOS(ERRSRV, ERRaccess);
3660 if (total_data < 2) {
3661 return NT_STATUS_INVALID_PARAMETER;
3664 flags = SVAL(pdata,0);
3666 if (!VALID_STAT(smb_fname->st)) {
3667 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3670 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
3671 !VALID_STAT_OF_DIR(smb_fname->st)) {
3672 return NT_STATUS_NOT_A_DIRECTORY;
3675 DEBUG(10,("smb_posix_unlink: %s %s\n",
3676 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
3677 smb_fname_str_dbg(smb_fname)));
3679 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
3680 create_options |= FILE_DIRECTORY_FILE;
3683 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
3684 if (!NT_STATUS_IS_OK(status)) {
3685 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3690 status = SMB_VFS_CREATE_FILE(
3694 smb_fname, /* fname */
3695 DELETE_ACCESS, /* access_mask */
3696 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
3698 FILE_OPEN, /* create_disposition*/
3699 create_options, /* create_options */
3700 0, /* file_attributes */
3701 0, /* oplock_request */
3703 0, /* allocation_size */
3704 0, /* private_flags */
3709 posx, /* in_context_blobs */
3710 NULL); /* out_context_blobs */
3714 if (!NT_STATUS_IS_OK(status)) {
3719 * Don't lie to client. If we can't really delete due to
3720 * non-POSIX opens return SHARING_VIOLATION.
3723 state = (struct smb_posix_unlink_state) {
3724 .smb_fname = smb_fname,
3728 status = share_mode_do_locked_vfs_allowed(fsp->file_id,
3729 smb_posix_unlink_locked,
3731 if (!NT_STATUS_IS_OK(status)) {
3732 DBG_ERR("share_mode_do_locked_vfs_allowed(%s) failed - %s\n",
3733 fsp_str_dbg(fsp), nt_errstr(status));
3734 close_file_free(req, &fsp, NORMAL_CLOSE);
3735 return NT_STATUS_INVALID_PARAMETER;
3738 status = state.status;
3739 if (!NT_STATUS_IS_OK(status)) {
3740 close_file_free(req, &fsp, NORMAL_CLOSE);
3743 return close_file_free(req, &fsp, NORMAL_CLOSE);
3746 /****************************************************************************
3747 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
3748 ****************************************************************************/
3750 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
3751 struct smb_request *req,
3754 struct smb_filename *new_smb_fname)
3756 char *link_target = NULL;
3757 struct smb_filename target_fname;
3758 TALLOC_CTX *ctx = talloc_tos();
3761 struct smb_filename *parent_fname = NULL;
3762 struct smb_filename *base_name = NULL;
3764 if (!CAN_WRITE(conn)) {
3765 return NT_STATUS_DOS(ERRSRV, ERRaccess);
3768 /* Set a symbolic link. */
3769 /* Don't allow this if follow links is false. */
3771 if (total_data == 0) {
3772 return NT_STATUS_INVALID_PARAMETER;
3775 if (!lp_follow_symlinks(SNUM(conn))) {
3776 return NT_STATUS_ACCESS_DENIED;
3779 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
3780 total_data, STR_TERMINATE);
3783 return NT_STATUS_INVALID_PARAMETER;
3786 target_fname = (struct smb_filename) {
3787 .base_name = link_target,
3790 /* Removes @GMT tokens if any */
3791 status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
3792 if (!NT_STATUS_IS_OK(status)) {
3796 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3797 new_smb_fname->base_name, link_target ));
3799 status = parent_pathref(talloc_tos(),
3804 if (!NT_STATUS_IS_OK(status)) {
3808 ret = SMB_VFS_SYMLINKAT(conn,
3813 TALLOC_FREE(parent_fname);
3814 return map_nt_error_from_unix(errno);
3817 TALLOC_FREE(parent_fname);
3818 return NT_STATUS_OK;
3821 /****************************************************************************
3822 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
3823 ****************************************************************************/
3825 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
3826 struct smb_request *req,
3827 const char *pdata, int total_data,
3828 struct smb_filename *smb_fname_new)
3830 char *oldname = NULL;
3831 struct files_struct *src_dirfsp = NULL;
3832 struct smb_filename *smb_fname_old = NULL;
3833 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
3834 NTTIME old_twrp = 0;
3835 TALLOC_CTX *ctx = talloc_tos();
3836 NTSTATUS status = NT_STATUS_OK;
3838 if (!CAN_WRITE(conn)) {
3839 return NT_STATUS_DOS(ERRSRV, ERRaccess);
3842 /* Set a hard link. */
3843 if (total_data == 0) {
3844 return NT_STATUS_INVALID_PARAMETER;
3847 if (req->posix_pathnames) {
3848 srvstr_get_path_posix(ctx,
3857 srvstr_get_path(ctx,
3866 if (!NT_STATUS_IS_OK(status)) {
3870 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3871 smb_fname_str_dbg(smb_fname_new), oldname));
3873 if (ucf_flags & UCF_GMT_PATHNAME) {
3874 extract_snapshot_token(oldname, &old_twrp);
3876 status = smb1_strip_dfs_path(ctx, &ucf_flags, &oldname);
3877 if (!NT_STATUS_IS_OK(status)) {
3880 status = filename_convert_dirfsp(ctx,
3887 if (!NT_STATUS_IS_OK(status)) {
3891 return hardlink_internals(ctx,
3897 NULL, /* new_dirfsp */
3901 /****************************************************************************
3902 Allow a UNIX info mknod.
3903 ****************************************************************************/
3905 static NTSTATUS smb_unix_mknod(connection_struct *conn,
3908 const struct smb_filename *smb_fname)
3910 uint32_t file_type = IVAL(pdata,56);
3911 #if defined(HAVE_MAKEDEV)
3912 uint32_t dev_major = IVAL(pdata,60);
3913 uint32_t dev_minor = IVAL(pdata,68);
3915 SMB_DEV_T dev = (SMB_DEV_T)0;
3916 uint32_t raw_unixmode = IVAL(pdata,84);
3920 struct smb_filename *parent_fname = NULL;
3921 struct smb_filename *base_name = NULL;
3923 if (total_data < 100) {
3924 return NT_STATUS_INVALID_PARAMETER;
3927 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
3928 PERM_NEW_FILE, &unixmode);
3929 if (!NT_STATUS_IS_OK(status)) {
3933 #if defined(HAVE_MAKEDEV)
3934 dev = makedev(dev_major, dev_minor);
3937 switch (file_type) {
3938 /* We can't create other objects here. */
3939 case UNIX_TYPE_FILE:
3941 case UNIX_TYPE_SYMLINK:
3942 return NT_STATUS_ACCESS_DENIED;
3943 #if defined(S_IFIFO)
3944 case UNIX_TYPE_FIFO:
3945 unixmode |= S_IFIFO;
3948 #if defined(S_IFSOCK)
3949 case UNIX_TYPE_SOCKET:
3950 unixmode |= S_IFSOCK;
3953 #if defined(S_IFCHR)
3954 case UNIX_TYPE_CHARDEV:
3955 /* This is only allowed for root. */
3956 if (get_current_uid(conn) != sec_initial_uid()) {
3957 return NT_STATUS_ACCESS_DENIED;
3959 unixmode |= S_IFCHR;
3962 #if defined(S_IFBLK)
3963 case UNIX_TYPE_BLKDEV:
3964 if (get_current_uid(conn) != sec_initial_uid()) {
3965 return NT_STATUS_ACCESS_DENIED;
3967 unixmode |= S_IFBLK;
3971 return NT_STATUS_INVALID_PARAMETER;
3974 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
3975 "%.0f mode 0%o for file %s\n", (double)dev,
3976 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
3978 status = parent_pathref(talloc_tos(),
3983 if (!NT_STATUS_IS_OK(status)) {
3987 /* Ok - do the mknod. */
3988 ret = SMB_VFS_MKNODAT(conn,
3995 TALLOC_FREE(parent_fname);
3996 return map_nt_error_from_unix(errno);
3999 /* If any of the other "set" calls fail we
4000 * don't want to end up with a half-constructed mknod.
4003 if (lp_inherit_permissions(SNUM(conn))) {
4004 inherit_access_posix_acl(conn,
4009 TALLOC_FREE(parent_fname);
4011 return NT_STATUS_OK;
4014 /****************************************************************************
4015 Deal with SMB_SET_FILE_UNIX_BASIC.
4016 ****************************************************************************/
4018 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
4019 struct smb_request *req,
4023 struct smb_filename *smb_fname)
4025 struct smb_file_time ft;
4026 uint32_t raw_unixmode;
4029 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
4030 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
4031 NTSTATUS status = NT_STATUS_OK;
4032 enum perm_type ptype;
4033 files_struct *all_fsps = NULL;
4034 bool modify_mtime = true;
4036 SMB_STRUCT_STAT sbuf;
4038 if (!CAN_WRITE(conn)) {
4039 return NT_STATUS_DOS(ERRSRV, ERRaccess);
4042 init_smb_file_time(&ft);
4044 if (total_data < 100) {
4045 return NT_STATUS_INVALID_PARAMETER;
4048 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4049 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4050 size=IVAL(pdata,0); /* first 8 Bytes are size */
4051 size |= (((off_t)IVAL(pdata,4)) << 32);
4054 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
4055 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
4056 set_owner = (uid_t)IVAL(pdata,40);
4057 set_grp = (gid_t)IVAL(pdata,48);
4058 raw_unixmode = IVAL(pdata,84);
4060 if (VALID_STAT(smb_fname->st)) {
4061 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
4062 ptype = PERM_EXISTING_DIR;
4064 ptype = PERM_EXISTING_FILE;
4067 ptype = PERM_NEW_FILE;
4070 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
4072 if (!NT_STATUS_IS_OK(status)) {
4076 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
4077 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4078 smb_fname_str_dbg(smb_fname), (double)size,
4079 (unsigned int)set_owner, (unsigned int)set_grp,
4080 (int)raw_unixmode));
4082 sbuf = smb_fname->st;
4084 if (!VALID_STAT(sbuf)) {
4086 * The only valid use of this is to create character and block
4087 * devices, and named pipes. This is deprecated (IMHO) and
4088 * a new info level should be used for mknod. JRA.
4091 return smb_unix_mknod(conn,
4098 /* Horrible backwards compatibility hack as an old server bug
4099 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
4103 size = get_file_size_stat(&sbuf);
4108 * Deal with the UNIX specific mode set.
4111 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4114 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
4115 DBG_WARNING("Can't set mode on symlink %s\n",
4116 smb_fname_str_dbg(smb_fname));
4117 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4120 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4121 "setting mode 0%o for file %s\n",
4122 (unsigned int)unixmode,
4123 smb_fname_str_dbg(smb_fname)));
4124 ret = SMB_VFS_FCHMOD(fsp, unixmode);
4126 return map_nt_error_from_unix(errno);
4131 * Deal with the UNIX specific uid set.
4134 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
4135 (sbuf.st_ex_uid != set_owner)) {
4138 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4139 "changing owner %u for path %s\n",
4140 (unsigned int)set_owner,
4141 smb_fname_str_dbg(smb_fname)));
4144 !fsp->fsp_flags.is_pathref &&
4145 fsp_get_io_fd(fsp) != -1)
4147 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
4150 * UNIX extensions calls must always operate
4153 ret = SMB_VFS_LCHOWN(conn, smb_fname,
4154 set_owner, (gid_t)-1);
4158 status = map_nt_error_from_unix(errno);
4164 * Deal with the UNIX specific gid set.
4167 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
4168 (sbuf.st_ex_gid != set_grp)) {
4171 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4172 "changing group %u for file %s\n",
4173 (unsigned int)set_grp,
4174 smb_fname_str_dbg(smb_fname)));
4176 !fsp->fsp_flags.is_pathref &&
4177 fsp_get_io_fd(fsp) != -1)
4179 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
4182 * UNIX extensions calls must always operate
4185 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
4189 status = map_nt_error_from_unix(errno);
4194 /* Deal with any size changes. */
4196 if (S_ISREG(sbuf.st_ex_mode)) {
4197 status = smb_set_file_size(conn, req,
4203 if (!NT_STATUS_IS_OK(status)) {
4208 /* Deal with any time changes. */
4209 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
4210 /* No change, don't cancel anything. */
4214 id = vfs_file_id_from_sbuf(conn, &sbuf);
4215 for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
4216 all_fsps = file_find_di_next(all_fsps, true)) {
4218 * We're setting the time explicitly for UNIX.
4219 * Cancel any pending changes over all handles.
4221 all_fsps->fsp_flags.update_write_time_on_close = false;
4222 TALLOC_FREE(all_fsps->update_write_time_event);
4226 * Override the "setting_write_time"
4227 * parameter here as it almost does what
4228 * we need. Just remember if we modified
4229 * mtime and send the notify ourselves.
4231 if (is_omit_timespec(&ft.mtime)) {
4232 modify_mtime = false;
4235 status = smb_set_file_time(conn,
4241 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4242 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
4247 /****************************************************************************
4248 Deal with SMB_SET_FILE_UNIX_INFO2.
4249 ****************************************************************************/
4251 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
4252 struct smb_request *req,
4256 struct smb_filename *smb_fname)
4259 uint32_t smb_fflags;
4262 if (!CAN_WRITE(conn)) {
4263 return NT_STATUS_DOS(ERRSRV, ERRaccess);
4266 if (total_data < 116) {
4267 return NT_STATUS_INVALID_PARAMETER;
4270 /* Start by setting all the fields that are common between UNIX_BASIC
4273 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
4275 if (!NT_STATUS_IS_OK(status)) {
4279 smb_fflags = IVAL(pdata, 108);
4280 smb_fmask = IVAL(pdata, 112);
4282 /* NB: We should only attempt to alter the file flags if the client
4283 * sends a non-zero mask.
4285 if (smb_fmask != 0) {
4286 int stat_fflags = 0;
4288 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
4289 smb_fmask, &stat_fflags)) {
4290 /* Client asked to alter a flag we don't understand. */
4291 return NT_STATUS_INVALID_PARAMETER;
4294 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
4295 DBG_WARNING("Can't change flags on symlink %s\n",
4296 smb_fname_str_dbg(smb_fname));
4297 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4299 if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) {
4300 return map_nt_error_from_unix(errno);
4304 /* XXX: need to add support for changing the create_time here. You
4305 * can do this for paths on Darwin with setattrlist(2). The right way
4306 * to hook this up is probably by extending the VFS utimes interface.
4309 return NT_STATUS_OK;
4312 /****************************************************************************
4313 Deal with SMB_SET_POSIX_ACL.
4314 ****************************************************************************/
4316 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4317 struct smb_request *req,
4321 struct smb_filename *smb_fname)
4323 #if !defined(HAVE_POSIX_ACLS)
4324 return NT_STATUS_INVALID_LEVEL;
4326 uint16_t posix_acl_version;
4327 uint16_t num_file_acls;
4328 uint16_t num_def_acls;
4329 bool valid_file_acls = true;
4330 bool valid_def_acls = true;
4332 unsigned int size_needed;
4333 unsigned int total_data;
4334 bool close_fsp = false;
4336 if (total_data_in < 0) {
4337 status = NT_STATUS_INVALID_PARAMETER;
4341 total_data = total_data_in;
4343 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4344 status = NT_STATUS_INVALID_PARAMETER;
4347 posix_acl_version = SVAL(pdata,0);
4348 num_file_acls = SVAL(pdata,2);
4349 num_def_acls = SVAL(pdata,4);
4351 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4352 valid_file_acls = false;
4356 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4357 valid_def_acls = false;
4361 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4362 status = NT_STATUS_INVALID_PARAMETER;
4367 if (num_file_acls + num_def_acls < num_file_acls) {
4368 status = NT_STATUS_INVALID_PARAMETER;
4372 size_needed = num_file_acls + num_def_acls;
4375 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4376 * than UINT_MAX, so check by division.
4378 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
4379 status = NT_STATUS_INVALID_PARAMETER;
4383 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
4384 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
4385 status = NT_STATUS_INVALID_PARAMETER;
4388 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
4390 if (total_data < size_needed) {
4391 status = NT_STATUS_INVALID_PARAMETER;
4396 * Ensure we always operate on a file descriptor, not just
4399 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
4400 uint32_t access_mask = SEC_STD_WRITE_OWNER|
4402 SEC_STD_READ_CONTROL|
4403 FILE_READ_ATTRIBUTES|
4404 FILE_WRITE_ATTRIBUTES;
4406 status = get_posix_fsp(conn,
4412 if (!NT_STATUS_IS_OK(status)) {
4418 /* Here we know fsp != NULL */
4419 SMB_ASSERT(fsp != NULL);
4421 status = refuse_symlink_fsp(fsp);
4422 if (!NT_STATUS_IS_OK(status)) {
4426 /* If we have a default acl, this *must* be a directory. */
4427 if (valid_def_acls && !fsp->fsp_flags.is_directory) {
4428 DBG_INFO("Can't set default acls on "
4429 "non-directory %s\n",
4431 return NT_STATUS_INVALID_HANDLE;
4434 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
4435 "num_def_acls = %"PRIu16"\n",
4440 /* Move pdata to the start of the file ACL entries. */
4441 pdata += SMB_POSIX_ACL_HEADER_SIZE;
4443 if (valid_file_acls) {
4444 status = set_unix_posix_acl(conn,
4448 if (!NT_STATUS_IS_OK(status)) {
4453 /* Move pdata to the start of the default ACL entries. */
4454 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
4456 if (valid_def_acls) {
4457 status = set_unix_posix_default_acl(conn,
4461 if (!NT_STATUS_IS_OK(status)) {
4466 status = NT_STATUS_OK;
4471 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
4477 static void call_trans2setpathinfo(
4478 connection_struct *conn,
4479 struct smb_request *req,
4484 unsigned int max_data_bytes)
4486 uint16_t info_level;
4487 struct smb_filename *smb_fname = NULL;
4488 struct files_struct *dirfsp = NULL;
4489 struct files_struct *fsp = NULL;
4490 char *params = *pparams;
4491 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4494 bool info_level_handled;
4495 int data_return_size = 0;
4498 if (params == NULL) {
4499 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4504 if (total_params < 7) {
4505 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4509 info_level = SVAL(params,0);
4511 if (INFO_LEVEL_IS_UNIX(info_level)) {
4512 if (!lp_smb1_unix_extensions()) {
4513 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4516 if (!req->posix_pathnames) {
4517 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4522 if (req->posix_pathnames) {
4523 srvstr_get_path_posix(req,
4532 srvstr_get_path(req,
4541 if (!NT_STATUS_IS_OK(status)) {
4542 reply_nterror(req, status);
4546 DBG_NOTICE("fname=%s info_level=%d totdata=%d\n",
4551 if (ucf_flags & UCF_GMT_PATHNAME) {
4552 extract_snapshot_token(fname, &twrp);
4554 status = smb1_strip_dfs_path(req, &ucf_flags, &fname);
4555 if (!NT_STATUS_IS_OK(status)) {
4556 reply_nterror(req, status);
4559 status = filename_convert_dirfsp(req,
4566 if (!NT_STATUS_IS_OK(status)) {
4567 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4568 reply_botherror(req,
4569 NT_STATUS_PATH_NOT_COVERED,
4570 ERRSRV, ERRbadpath);
4573 reply_nterror(req, status);
4577 info_level_handled = true; /* Untouched in switch cases below */
4579 switch (info_level) {
4582 info_level_handled = false;
4585 case SMB_POSIX_PATH_OPEN:
4586 status = smb_posix_open(
4595 case SMB_POSIX_PATH_UNLINK:
4596 status = smb_posix_unlink(
4597 conn, req, *ppdata, total_data, smb_fname);
4600 case SMB_SET_FILE_UNIX_LINK:
4601 status = smb_set_file_unix_link(
4602 conn, req, *ppdata, total_data, smb_fname);
4605 case SMB_SET_FILE_UNIX_HLINK:
4606 status = smb_set_file_unix_hlink(
4607 conn, req, *ppdata, total_data, smb_fname);
4610 case SMB_SET_FILE_UNIX_BASIC:
4611 status = smb_set_file_unix_basic(
4620 case SMB_SET_FILE_UNIX_INFO2:
4621 status = smb_set_file_unix_info2(
4629 case SMB_SET_POSIX_ACL:
4630 status = smb_set_posix_acl(
4631 conn, req, *ppdata, total_data, NULL, smb_fname);
4635 if (info_level_handled) {
4636 handle_trans2setfilepathinfo_result(
4648 * smb_fname->fsp may be NULL if smb_fname points at a symlink
4649 * and we're in POSIX context, so be careful when using fsp
4650 * below, it can still be NULL.
4652 fsp = smb_fname->fsp;
4654 status = smbd_do_setfilepathinfo(
4665 handle_trans2setfilepathinfo_result(
4675 static void call_trans2setfileinfo(
4676 connection_struct *conn,
4677 struct smb_request *req,
4682 unsigned int max_data_bytes)
4684 char *pdata = *ppdata;
4685 uint16_t info_level;
4686 struct smb_filename *smb_fname = NULL;
4687 struct files_struct *fsp = NULL;
4688 char *params = *pparams;
4689 int data_return_size = 0;
4690 bool info_level_handled;
4694 if (params == NULL) {
4695 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4698 if (total_params < 4) {
4699 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4703 fsp = file_fsp(req, SVAL(params,0));
4704 /* Basic check for non-null fsp. */
4705 if (!check_fsp_open(conn, req, fsp)) {
4708 info_level = SVAL(params,2);
4710 if (INFO_LEVEL_IS_UNIX(info_level)) {
4711 if (!lp_smb1_unix_extensions()) {
4712 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4715 if (!req->posix_pathnames) {
4716 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4721 smb_fname = fsp->fsp_name;
4723 DBG_NOTICE("fnum=%s fname=%s info_level=%d totdata=%d\n",
4729 if (fsp_get_pathref_fd(fsp) == -1) {
4731 * This is actually a SETFILEINFO on a directory
4732 * handle (returned from an NT SMB). NT5.0 seems
4733 * to do this call. JRA.
4735 ret = vfs_stat(conn, smb_fname);
4737 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
4738 smb_fname_str_dbg(smb_fname),
4740 reply_nterror(req, map_nt_error_from_unix(errno));
4743 } else if (fsp->print_file) {
4745 * Doing a DELETE_ON_CLOSE should cancel a print job.
4747 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) &&
4750 fsp->fsp_flags.delete_on_close = true;
4752 DBG_NOTICE("Cancelling print job (%s)\n",
4756 send_trans2_replies(
4766 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
4771 * Original code - this is an open file.
4773 status = vfs_stat_fsp(fsp);
4774 if (!NT_STATUS_IS_OK(status)) {
4775 DBG_NOTICE("fstat of %s failed (%s)\n",
4778 reply_nterror(req, status);
4783 info_level_handled = true; /* Untouched in switch cases below */
4785 switch (info_level) {
4788 info_level_handled = false;
4791 case SMB_SET_FILE_UNIX_BASIC:
4792 status = smb_set_file_unix_basic(
4793 conn, req, pdata, total_data, fsp, smb_fname);
4796 case SMB_SET_FILE_UNIX_INFO2:
4797 status = smb_set_file_unix_info2(
4798 conn, req, pdata, total_data, fsp, smb_fname);
4801 case SMB_SET_POSIX_LOCK:
4802 status = smb_set_posix_lock(
4803 conn, req, *ppdata, total_data, fsp);
4807 if (info_level_handled) {
4808 handle_trans2setfilepathinfo_result(
4819 status = smbd_do_setfilepathinfo(
4830 handle_trans2setfilepathinfo_result(
4840 /****************************************************************************
4841 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4842 ****************************************************************************/
4844 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
4845 char **pparams, int total_params,
4846 char **ppdata, int total_data,
4847 unsigned int max_data_bytes)
4849 struct files_struct *dirfsp = NULL;
4850 struct files_struct *fsp = NULL;
4851 struct smb_filename *smb_dname = NULL;
4852 char *params = *pparams;
4853 char *pdata = *ppdata;
4854 char *directory = NULL;
4855 NTSTATUS status = NT_STATUS_OK;
4856 struct ea_list *ea_list = NULL;
4857 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4859 TALLOC_CTX *ctx = talloc_tos();
4861 if (!CAN_WRITE(conn)) {
4862 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4866 if (total_params < 5) {
4867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4871 if (req->posix_pathnames) {
4872 srvstr_get_path_posix(ctx,
4881 srvstr_get_path(ctx,
4890 if (!NT_STATUS_IS_OK(status)) {
4891 reply_nterror(req, status);
4895 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4897 if (ucf_flags & UCF_GMT_PATHNAME) {
4898 extract_snapshot_token(directory, &twrp);
4900 status = smb1_strip_dfs_path(ctx, &ucf_flags, &directory);
4901 if (!NT_STATUS_IS_OK(status)) {
4902 reply_nterror(req, status);
4905 status = filename_convert_dirfsp(ctx,
4912 if (!NT_STATUS_IS_OK(status)) {
4913 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4914 reply_botherror(req,
4915 NT_STATUS_PATH_NOT_COVERED,
4916 ERRSRV, ERRbadpath);
4919 reply_nterror(req, status);
4924 * OS/2 workplace shell seems to send SET_EA requests of "null"
4925 * length (4 bytes containing IVAL 4).
4926 * They seem to have no effect. Bug #3212. JRA.
4929 if (total_data && (total_data != 4)) {
4930 /* Any data in this call is an EA list. */
4931 if (total_data < 10) {
4932 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4936 if (IVAL(pdata,0) > total_data) {
4937 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4938 IVAL(pdata,0), (unsigned int)total_data));
4939 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4943 ea_list = read_ea_list(talloc_tos(), pdata + 4,
4946 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4950 if (!lp_ea_support(SNUM(conn))) {
4951 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
4955 /* If total_data == 4 Windows doesn't care what values
4956 * are placed in that field, it just ignores them.
4957 * The System i QNTC IBM SMB client puts bad values here,
4958 * so ignore them. */
4960 status = SMB_VFS_CREATE_FILE(
4963 dirfsp, /* dirfsp */
4964 smb_dname, /* fname */
4965 MAXIMUM_ALLOWED_ACCESS, /* access_mask */
4966 FILE_SHARE_NONE, /* share_access */
4967 FILE_CREATE, /* create_disposition*/
4968 FILE_DIRECTORY_FILE, /* create_options */
4969 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
4970 0, /* oplock_request */
4972 0, /* allocation_size */
4973 0, /* private_flags */
4978 NULL, NULL); /* create context */
4979 if (!NT_STATUS_IS_OK(status)) {
4980 reply_nterror(req, status);
4984 /* Try and set any given EA. */
4986 status = set_ea(conn, fsp, ea_list);
4987 if (!NT_STATUS_IS_OK(status)) {
4988 reply_nterror(req, status);
4993 /* Realloc the parameter and data sizes */
4994 *pparams = (char *)SMB_REALLOC(*pparams,2);
4995 if(*pparams == NULL) {
4996 reply_nterror(req, NT_STATUS_NO_MEMORY);
5003 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
5007 close_file_free(NULL, &fsp, NORMAL_CLOSE);
5009 TALLOC_FREE(smb_dname);
5013 /****************************************************************************
5014 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
5015 We don't actually do this - we just send a null response.
5016 ****************************************************************************/
5018 static void call_trans2findnotifyfirst(connection_struct *conn,
5019 struct smb_request *req,
5020 char **pparams, int total_params,
5021 char **ppdata, int total_data,
5022 unsigned int max_data_bytes)
5024 char *params = *pparams;
5025 uint16_t info_level;
5027 if (total_params < 6) {
5028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5032 info_level = SVAL(params,4);
5033 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
5035 switch (info_level) {
5040 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5044 /* Realloc the parameter and data sizes */
5045 *pparams = (char *)SMB_REALLOC(*pparams,6);
5046 if (*pparams == NULL) {
5047 reply_nterror(req, NT_STATUS_NO_MEMORY);
5052 SSVAL(params,0,fnf_handle);
5053 SSVAL(params,2,0); /* No changes */
5054 SSVAL(params,4,0); /* No EA errors */
5061 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
5066 /****************************************************************************
5067 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
5068 changes). Currently this does nothing.
5069 ****************************************************************************/
5071 static void call_trans2findnotifynext(connection_struct *conn,
5072 struct smb_request *req,
5073 char **pparams, int total_params,
5074 char **ppdata, int total_data,
5075 unsigned int max_data_bytes)
5077 char *params = *pparams;
5079 DEBUG(3,("call_trans2findnotifynext\n"));
5081 /* Realloc the parameter and data sizes */
5082 *pparams = (char *)SMB_REALLOC(*pparams,4);
5083 if (*pparams == NULL) {
5084 reply_nterror(req, NT_STATUS_NO_MEMORY);
5089 SSVAL(params,0,0); /* No changes */
5090 SSVAL(params,2,0); /* No EA errors */
5092 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
5097 /****************************************************************************
5098 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5099 ****************************************************************************/
5101 static void call_trans2getdfsreferral(connection_struct *conn,
5102 struct smb_request *req,
5103 char **pparams, int total_params,
5104 char **ppdata, int total_data,
5105 unsigned int max_data_bytes)
5107 char *params = *pparams;
5108 char *pathname = NULL;
5110 int max_referral_level;
5111 NTSTATUS status = NT_STATUS_OK;
5112 TALLOC_CTX *ctx = talloc_tos();
5114 DEBUG(10,("call_trans2getdfsreferral\n"));
5116 if (!IS_IPC(conn)) {
5117 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5121 if (total_params < 3) {
5122 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5126 max_referral_level = SVAL(params,0);
5128 if(!lp_host_msdfs()) {
5129 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5133 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
5134 total_params - 2, STR_TERMINATE);
5136 reply_nterror(req, NT_STATUS_NOT_FOUND);
5139 reply_size = setup_dfs_referral(
5140 conn, pathname, max_referral_level, ppdata, &status);
5141 if (reply_size < 0) {
5142 reply_nterror(req, status);
5146 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
5147 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
5148 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
5153 #define LMCAT_SPL 0x53
5154 #define LMFUNC_GETJOBID 0x60
5156 /****************************************************************************
5157 Reply to a TRANS2_IOCTL - used for OS/2 printing.
5158 ****************************************************************************/
5160 static void call_trans2ioctl(connection_struct *conn,
5161 struct smb_request *req,
5162 char **pparams, int total_params,
5163 char **ppdata, int total_data,
5164 unsigned int max_data_bytes)
5166 const struct loadparm_substitution *lp_sub =
5167 loadparm_s3_global_substitution();
5168 char *pdata = *ppdata;
5169 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
5173 /* check for an invalid fid before proceeding */
5176 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5180 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
5181 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
5182 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
5183 if (*ppdata == NULL) {
5184 reply_nterror(req, NT_STATUS_NO_MEMORY);
5189 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5190 CAN ACCEPT THIS IN UNICODE. JRA. */
5193 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
5195 status = srvstr_push(pdata, req->flags2, pdata + 2,
5196 lp_netbios_name(), 15,
5197 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
5198 if (!NT_STATUS_IS_OK(status)) {
5199 reply_nterror(req, status);
5202 status = srvstr_push(pdata, req->flags2, pdata+18,
5203 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
5204 STR_ASCII|STR_TERMINATE, &len); /* Service name */
5205 if (!NT_STATUS_IS_OK(status)) {
5206 reply_nterror(req, status);
5209 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
5214 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5215 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5218 static void handle_trans2(connection_struct *conn, struct smb_request *req,
5219 struct trans_state *state)
5221 if (get_Protocol() >= PROTOCOL_NT1) {
5222 req->flags2 |= 0x40; /* IS_LONG_NAME */
5223 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
5226 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
5227 if (state->call != TRANSACT2_QFSINFO &&
5228 state->call != TRANSACT2_SETFSINFO) {
5229 DEBUG(0,("handle_trans2: encryption required "
5231 (unsigned int)state->call));
5232 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5237 /* Now we must call the relevant TRANS2 function */
5238 switch(state->call) {
5239 case TRANSACT2_OPEN:
5241 START_PROFILE(Trans2_open);
5242 call_trans2open(conn, req,
5243 &state->param, state->total_param,
5244 &state->data, state->total_data,
5245 state->max_data_return);
5246 END_PROFILE(Trans2_open);
5250 case TRANSACT2_FINDFIRST:
5252 START_PROFILE(Trans2_findfirst);
5253 call_trans2findfirst(conn, req,
5254 &state->param, state->total_param,
5255 &state->data, state->total_data,
5256 state->max_data_return);
5257 END_PROFILE(Trans2_findfirst);
5261 case TRANSACT2_FINDNEXT:
5263 START_PROFILE(Trans2_findnext);
5264 call_trans2findnext(conn, req,
5265 &state->param, state->total_param,
5266 &state->data, state->total_data,
5267 state->max_data_return);
5268 END_PROFILE(Trans2_findnext);
5272 case TRANSACT2_QFSINFO:
5274 START_PROFILE(Trans2_qfsinfo);
5275 call_trans2qfsinfo(conn, req,
5276 &state->param, state->total_param,
5277 &state->data, state->total_data,
5278 state->max_data_return);
5279 END_PROFILE(Trans2_qfsinfo);
5283 case TRANSACT2_SETFSINFO:
5285 START_PROFILE(Trans2_setfsinfo);
5286 call_trans2setfsinfo(conn, req,
5287 &state->param, state->total_param,
5288 &state->data, state->total_data,
5289 state->max_data_return);
5290 END_PROFILE(Trans2_setfsinfo);
5294 case TRANSACT2_QPATHINFO:
5296 START_PROFILE(Trans2_qpathinfo);
5297 call_trans2qpathinfo(
5304 state->max_data_return);
5305 END_PROFILE(Trans2_qpathinfo);
5309 case TRANSACT2_QFILEINFO:
5311 START_PROFILE(Trans2_qfileinfo);
5312 call_trans2qfileinfo(
5319 state->max_data_return);
5320 END_PROFILE(Trans2_qfileinfo);
5324 case TRANSACT2_SETPATHINFO:
5326 START_PROFILE(Trans2_setpathinfo);
5327 call_trans2setpathinfo(
5334 state->max_data_return);
5335 END_PROFILE(Trans2_setpathinfo);
5339 case TRANSACT2_SETFILEINFO:
5341 START_PROFILE(Trans2_setfileinfo);
5342 call_trans2setfileinfo(
5349 state->max_data_return);
5350 END_PROFILE(Trans2_setfileinfo);
5354 case TRANSACT2_FINDNOTIFYFIRST:
5356 START_PROFILE(Trans2_findnotifyfirst);
5357 call_trans2findnotifyfirst(conn, req,
5358 &state->param, state->total_param,
5359 &state->data, state->total_data,
5360 state->max_data_return);
5361 END_PROFILE(Trans2_findnotifyfirst);
5365 case TRANSACT2_FINDNOTIFYNEXT:
5367 START_PROFILE(Trans2_findnotifynext);
5368 call_trans2findnotifynext(conn, req,
5369 &state->param, state->total_param,
5370 &state->data, state->total_data,
5371 state->max_data_return);
5372 END_PROFILE(Trans2_findnotifynext);
5376 case TRANSACT2_MKDIR:
5378 START_PROFILE(Trans2_mkdir);
5379 call_trans2mkdir(conn, req,
5380 &state->param, state->total_param,
5381 &state->data, state->total_data,
5382 state->max_data_return);
5383 END_PROFILE(Trans2_mkdir);
5387 case TRANSACT2_GET_DFS_REFERRAL:
5389 START_PROFILE(Trans2_get_dfs_referral);
5390 call_trans2getdfsreferral(conn, req,
5391 &state->param, state->total_param,
5392 &state->data, state->total_data,
5393 state->max_data_return);
5394 END_PROFILE(Trans2_get_dfs_referral);
5398 case TRANSACT2_IOCTL:
5400 START_PROFILE(Trans2_ioctl);
5401 call_trans2ioctl(conn, req,
5402 &state->param, state->total_param,
5403 &state->data, state->total_data,
5404 state->max_data_return);
5405 END_PROFILE(Trans2_ioctl);
5410 /* Error in request */
5411 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5412 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5416 /****************************************************************************
5417 Reply to a SMBtrans2.
5418 ****************************************************************************/
5420 void reply_trans2(struct smb_request *req)
5422 connection_struct *conn = req->conn;
5427 unsigned int tran_call;
5428 struct trans_state *state;
5431 START_PROFILE(SMBtrans2);
5433 if (req->wct < 14) {
5434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5435 END_PROFILE(SMBtrans2);
5439 dsoff = SVAL(req->vwv+12, 0);
5440 dscnt = SVAL(req->vwv+11, 0);
5441 psoff = SVAL(req->vwv+10, 0);
5442 pscnt = SVAL(req->vwv+9, 0);
5443 tran_call = SVAL(req->vwv+14, 0);
5445 result = allow_new_trans(conn->pending_trans, req->mid);
5446 if (!NT_STATUS_IS_OK(result)) {
5447 DEBUG(2, ("Got invalid trans2 request: %s\n",
5448 nt_errstr(result)));
5449 reply_nterror(req, result);
5450 END_PROFILE(SMBtrans2);
5455 switch (tran_call) {
5456 /* List the allowed trans2 calls on IPC$ */
5457 case TRANSACT2_OPEN:
5458 case TRANSACT2_GET_DFS_REFERRAL:
5459 case TRANSACT2_QFILEINFO:
5460 case TRANSACT2_QFSINFO:
5461 case TRANSACT2_SETFSINFO:
5464 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5465 END_PROFILE(SMBtrans2);
5470 if ((state = talloc(conn, struct trans_state)) == NULL) {
5471 DEBUG(0, ("talloc failed\n"));
5472 reply_nterror(req, NT_STATUS_NO_MEMORY);
5473 END_PROFILE(SMBtrans2);
5477 state->cmd = SMBtrans2;
5479 state->mid = req->mid;
5480 state->vuid = req->vuid;
5481 state->setup_count = SVAL(req->vwv+13, 0);
5482 state->setup = NULL;
5483 state->total_param = SVAL(req->vwv+0, 0);
5484 state->param = NULL;
5485 state->total_data = SVAL(req->vwv+1, 0);
5487 state->max_param_return = SVAL(req->vwv+2, 0);
5488 state->max_data_return = SVAL(req->vwv+3, 0);
5489 state->max_setup_return = SVAL(req->vwv+4, 0);
5490 state->close_on_completion = BITSETW(req->vwv+5, 0);
5491 state->one_way = BITSETW(req->vwv+5, 1);
5493 state->call = tran_call;
5495 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5496 is so as a sanity check */
5497 if (state->setup_count != 1) {
5499 * Need to have rc=0 for ioctl to get job id for OS/2.
5500 * Network printing will fail if function is not successful.
5501 * Similar function in reply.c will be used if protocol
5502 * is LANMAN1.0 instead of LM1.2X002.
5503 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5504 * outbuf doesn't have to be set(only job id is used).
5506 if ( (state->setup_count == 4)
5507 && (tran_call == TRANSACT2_IOCTL)
5508 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
5509 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
5510 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5512 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5513 DEBUG(2,("Transaction is %d\n",tran_call));
5515 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5516 END_PROFILE(SMBtrans2);
5521 if ((dscnt > state->total_data) || (pscnt > state->total_param))
5524 if (state->total_data) {
5526 if (smb_buffer_oob(state->total_data, 0, dscnt)
5527 || smb_buffer_oob(smb_len(req->inbuf), dsoff, dscnt)) {
5531 /* Can't use talloc here, the core routines do realloc on the
5532 * params and data. */
5533 state->data = (char *)SMB_MALLOC(state->total_data);
5534 if (state->data == NULL) {
5535 DEBUG(0,("reply_trans2: data malloc fail for %u "
5536 "bytes !\n", (unsigned int)state->total_data));
5538 reply_nterror(req, NT_STATUS_NO_MEMORY);
5539 END_PROFILE(SMBtrans2);
5543 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
5546 if (state->total_param) {
5548 if (smb_buffer_oob(state->total_param, 0, pscnt)
5549 || smb_buffer_oob(smb_len(req->inbuf), psoff, pscnt)) {
5553 /* Can't use talloc here, the core routines do realloc on the
5554 * params and data. */
5555 state->param = (char *)SMB_MALLOC(state->total_param);
5556 if (state->param == NULL) {
5557 DEBUG(0,("reply_trans: param malloc fail for %u "
5558 "bytes !\n", (unsigned int)state->total_param));
5559 SAFE_FREE(state->data);
5561 reply_nterror(req, NT_STATUS_NO_MEMORY);
5562 END_PROFILE(SMBtrans2);
5566 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
5569 state->received_data = dscnt;
5570 state->received_param = pscnt;
5572 if ((state->received_param == state->total_param) &&
5573 (state->received_data == state->total_data)) {
5575 handle_trans2(conn, req, state);
5577 SAFE_FREE(state->data);
5578 SAFE_FREE(state->param);
5580 END_PROFILE(SMBtrans2);
5584 DLIST_ADD(conn->pending_trans, state);
5586 /* We need to send an interim response then receive the rest
5587 of the parameter/data bytes */
5588 reply_smb1_outbuf(req, 0, 0);
5589 show_msg((char *)req->outbuf);
5590 END_PROFILE(SMBtrans2);
5595 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5596 SAFE_FREE(state->data);
5597 SAFE_FREE(state->param);
5599 END_PROFILE(SMBtrans2);
5600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5603 /****************************************************************************
5604 Reply to a SMBtranss2
5605 ****************************************************************************/
5607 void reply_transs2(struct smb_request *req)
5609 connection_struct *conn = req->conn;
5610 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5611 struct trans_state *state;
5613 START_PROFILE(SMBtranss2);
5615 show_msg((const char *)req->inbuf);
5617 /* Windows clients expect all replies to
5618 a transact secondary (SMBtranss2 0x33)
5619 to have a command code of transact
5620 (SMBtrans2 0x32). See bug #8989
5621 and also [MS-CIFS] section 2.2.4.47.2
5624 req->cmd = SMBtrans2;
5627 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5628 END_PROFILE(SMBtranss2);
5632 for (state = conn->pending_trans; state != NULL;
5633 state = state->next) {
5634 if (state->mid == req->mid) {
5639 if ((state == NULL) || (state->cmd != SMBtrans2)) {
5640 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5641 END_PROFILE(SMBtranss2);
5645 /* Revise state->total_param and state->total_data in case they have
5646 changed downwards */
5648 if (SVAL(req->vwv+0, 0) < state->total_param)
5649 state->total_param = SVAL(req->vwv+0, 0);
5650 if (SVAL(req->vwv+1, 0) < state->total_data)
5651 state->total_data = SVAL(req->vwv+1, 0);
5653 pcnt = SVAL(req->vwv+2, 0);
5654 poff = SVAL(req->vwv+3, 0);
5655 pdisp = SVAL(req->vwv+4, 0);
5657 dcnt = SVAL(req->vwv+5, 0);
5658 doff = SVAL(req->vwv+6, 0);
5659 ddisp = SVAL(req->vwv+7, 0);
5661 state->received_param += pcnt;
5662 state->received_data += dcnt;
5664 if ((state->received_data > state->total_data) ||
5665 (state->received_param > state->total_param))
5669 if (smb_buffer_oob(state->total_param, pdisp, pcnt)
5670 || smb_buffer_oob(smb_len(req->inbuf), poff, pcnt)) {
5673 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
5677 if (smb_buffer_oob(state->total_data, ddisp, dcnt)
5678 || smb_buffer_oob(smb_len(req->inbuf), doff, dcnt)) {
5681 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
5684 if ((state->received_param < state->total_param) ||
5685 (state->received_data < state->total_data)) {
5686 END_PROFILE(SMBtranss2);
5690 handle_trans2(conn, req, state);
5692 DLIST_REMOVE(conn->pending_trans, state);
5693 SAFE_FREE(state->data);
5694 SAFE_FREE(state->param);
5697 END_PROFILE(SMBtranss2);
5702 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5703 DLIST_REMOVE(conn->pending_trans, state);
5704 SAFE_FREE(state->data);
5705 SAFE_FREE(state->param);
5707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5708 END_PROFILE(SMBtranss2);