s3: smbd: hardlink_internals() never looks at src_dirfsp or dst_dirfsp.
[Samba.git] / source3 / smbd / smb1_trans2.c
blob47493d57904ef746a15b66e7e56a1ecf59593cc3
1 /*
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/>.
26 #include "includes.h"
27 #include "ntioctl.h"
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.h"
30 #include "version.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"
37 #include "trans2.h"
38 #include "auth.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
41 #include "printing.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
44 #include "messages.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,
61 NTSTATUS status,
62 const char *params,
63 int paramsize,
64 const char *pdata,
65 int datasize,
66 int max_data_bytes)
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;
76 int useable_space;
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
89 for OS/2. */
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;
95 overflow = True;
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)) {
103 uint8_t eclass;
104 uint32_t ecode;
105 ntstatus_to_dos(status, &eclass, &ecode);
106 error_packet_set((char *)req->outbuf,
107 eclass, ecode, status,
108 __LINE__,__FILE__);
110 show_msg((char *)req->outbuf);
111 if (!smb1_srv_send(xconn,
112 (char *)req->outbuf,
113 true,
114 req->seqnum + 1,
115 IS_CONN_ENCRYPTED(conn))) {
116 exit_server_cleanly("send_trans2_replies: smb1_srv_send failed.");
118 TALLOC_FREE(req->outbuf);
119 return;
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
134 + 2 * 10 /* wct */
135 + alignment_offset
136 + data_alignment_offset);
138 if (useable_space < 0) {
139 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
140 "= %d!!!\n", useable_space));
141 exit_server_cleanly("send_trans2_replies: Not enough space");
144 while (params_to_send || data_to_send) {
145 /* Calculate whether we will totally or partially fill this packet */
147 total_sent_thistime = params_to_send + data_to_send;
149 /* We can never send more than useable_space */
151 * Note that 'useable_space' does not include the alignment offsets,
152 * but we must include the alignment offsets in the calculation of
153 * the length of the data we send over the wire, as the alignment offsets
154 * are sent here. Fix from Marc_Jacobsen@hp.com.
157 total_sent_thistime = MIN(total_sent_thistime, useable_space);
159 reply_smb1_outbuf(req, 10, total_sent_thistime + alignment_offset
160 + data_alignment_offset);
162 /* Set total params and data to be sent */
163 SSVAL(req->outbuf,smb_tprcnt,paramsize);
164 SSVAL(req->outbuf,smb_tdrcnt,datasize);
166 /* Calculate how many parameters and data we can fit into
167 * this packet. Parameters get precedence
170 params_sent_thistime = MIN(params_to_send,useable_space);
171 data_sent_thistime = useable_space - params_sent_thistime;
172 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
174 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
176 /* smb_proff is the offset from the start of the SMB header to the
177 parameter bytes, however the first 4 bytes of outbuf are
178 the Netbios over TCP header. Thus use smb_base() to subtract
179 them from the calculation */
181 SSVAL(req->outbuf,smb_proff,
182 ((smb_buf(req->outbuf)+alignment_offset)
183 - smb_base(req->outbuf)));
185 if(params_sent_thistime == 0)
186 SSVAL(req->outbuf,smb_prdisp,0);
187 else
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);
195 } else {
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));
235 if (overflow) {
236 error_packet_set((char *)req->outbuf,
237 ERRDOS,ERRbufferoverflow,
238 STATUS_BUFFER_OVERFLOW,
239 __LINE__,__FILE__);
240 } else if (NT_STATUS_V(status)) {
241 uint8_t eclass;
242 uint32_t ecode;
243 ntstatus_to_dos(status, &eclass, &ecode);
244 error_packet_set((char *)req->outbuf,
245 eclass, ecode, status,
246 __LINE__,__FILE__);
249 /* Send the packet */
250 show_msg((char *)req->outbuf);
251 if (!smb1_srv_send(xconn,
252 (char *)req->outbuf,
253 true,
254 req->seqnum + 1,
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;
267 /* Sanity check */
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));
271 return;
275 return;
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,
286 const char *pdata,
287 int total_data,
288 files_struct *fsp)
290 struct tevent_req *subreq = NULL;
291 struct smbd_lock_element *lck = NULL;
292 uint64_t count;
293 uint64_t offset;
294 uint64_t smblctx;
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);
304 if (fsp == NULL ||
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;
318 break;
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;
325 break;
326 case POSIX_LOCK_TYPE_UNLOCK:
327 lock_type = UNLOCK_LOCK;
328 break;
329 default:
330 return NT_STATUS_INVALID_PARAMETER;
333 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
334 case POSIX_LOCK_FLAG_NOWAIT:
335 blocking_lock = false;
336 break;
337 case POSIX_LOCK_FLAG_WAIT:
338 blocking_lock = true;
339 break;
340 default:
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",
356 fsp_str_dbg(fsp),
357 (unsigned int)lock_type,
358 smblctx,
359 count,
360 offset);
362 if (lock_type == UNLOCK_LOCK) {
363 struct smbd_lock_element l = {
364 .req_guid = smbd_request_guid(req, 0),
365 .smblctx = smblctx,
366 .brltype = UNLOCK_LOCK,
367 .lock_flav = POSIX_LOCK,
368 .offset = offset,
369 .count = count,
371 status = smbd_do_unlocking(req, fsp, 1, &l);
372 return status;
375 lck = talloc(req, struct smbd_lock_element);
376 if (lck == NULL) {
377 return NT_STATUS_NO_MEMORY;
380 *lck = (struct smbd_lock_element) {
381 .req_guid = smbd_request_guid(req, 0),
382 .smblctx = smblctx,
383 .brltype = lock_type,
384 .lock_flav = POSIX_LOCK,
385 .count = count,
386 .offset = offset,
389 subreq = smbd_smb1_do_locks_send(
390 fsp,
391 req->sconn->ev_ctx,
392 &req,
393 fsp,
394 blocking_lock ? UINT32_MAX : 0,
395 true, /* large_offset */
397 lck);
398 if (subreq == NULL) {
399 TALLOC_FREE(lck);
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;
409 NTSTATUS status;
410 bool ok;
412 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
413 SMB_ASSERT(ok);
415 status = smbd_smb1_do_locks_recv(subreq);
416 TALLOC_FREE(subreq);
418 if (NT_STATUS_IS_OK(status)) {
419 char params[2] = {0};
420 /* Fake up max_data_bytes here - we know it fits. */
421 send_trans2_replies(
422 req->conn,
423 req,
424 NT_STATUS_OK,
425 params,
427 NULL,
429 0xffff);
430 } else {
431 reply_nterror(req, status);
432 ok = smb1_srv_send(req->xconn,
433 (char *)req->outbuf,
434 true,
435 req->seqnum + 1,
436 IS_CONN_ENCRYPTED(req->conn));
437 if (!ok) {
438 exit_server_cleanly("smb_set_posix_lock_done: "
439 "smb1_srv_send failed.");
443 TALLOC_FREE(req);
444 return;
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)) {
466 break;
468 /* Ensure the name is null terminated. */
469 if (pdata[offset + namelen] != '\0') {
470 return NULL;
472 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
473 &converted_size)) {
474 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
475 "failed: %s\n", strerror(errno)));
477 if (!eal->ea.name) {
478 return NULL;
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));
486 return ea_list_head;
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;
502 int deny_mode;
503 int32_t open_attr;
504 bool oplock_request;
505 #if 0
506 bool return_additional_info;
507 int16 open_sattr;
508 time_t open_time;
509 #endif
510 int open_ofun;
511 uint32_t open_size;
512 char *pname;
513 char *fname = NULL;
514 off_t size=0;
515 int fattr=0,mtime=0;
516 SMB_INO_T inode = 0;
517 int smb_action = 0;
518 struct files_struct *dirfsp = NULL;
519 files_struct *fsp;
520 struct ea_list *ea_list = NULL;
521 uint16_t flags = 0;
522 NTSTATUS status;
523 uint32_t access_mask;
524 uint32_t share_mode;
525 uint32_t create_disposition;
526 uint32_t create_options = 0;
527 uint32_t private_flags = 0;
528 NTTIME twrp = 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);
538 goto out;
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;
549 #if 0
550 return_additional_info = BITSETW(params,0);
551 open_sattr = SVAL(params, 4);
552 open_time = make_unix_date3(params+8);
553 #endif
554 open_ofun = SVAL(params,12);
555 open_size = IVAL(params,14);
556 pname = &params[28];
558 if (IS_IPC(conn)) {
559 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
560 goto out;
563 if (req->posix_pathnames) {
564 srvstr_get_path_posix(ctx,
565 params,
566 req->flags2,
567 &fname,
568 pname,
569 total_params - 28,
570 STR_TERMINATE,
571 &status);
572 } else {
573 srvstr_get_path(ctx,
574 params,
575 req->flags2,
576 &fname,
577 pname,
578 total_params - 28,
579 STR_TERMINATE,
580 &status);
582 if (!NT_STATUS_IS_OK(status)) {
583 reply_nterror(req, status);
584 goto out;
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);
597 goto out;
599 status = filename_convert_dirfsp(ctx,
600 conn,
601 fname,
602 ucf_flags,
603 twrp,
604 &dirfsp,
605 &smb_fname);
606 if (!NT_STATUS_IS_OK(status)) {
607 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
608 reply_botherror(req,
609 NT_STATUS_PATH_NOT_COVERED,
610 ERRSRV, ERRbadpath);
611 goto out;
613 reply_nterror(req, status);
614 goto out;
617 if (open_ofun == 0) {
618 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
619 goto out;
622 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
623 open_ofun,
624 &access_mask, &share_mode,
625 &create_disposition,
626 &create_options,
627 &private_flags)) {
628 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
629 goto out;
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);
636 goto out;
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);
643 goto out;
646 ea_list = read_ea_list(talloc_tos(), pdata + 4,
647 total_data - 4);
648 if (!ea_list) {
649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
650 goto out;
653 if (!lp_ea_support(SNUM(conn))) {
654 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
655 goto out;
658 if (!req->posix_pathnames &&
659 ea_list_has_invalid_name(ea_list)) {
660 int param_len = 30;
661 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
662 if(*pparams == NULL ) {
663 reply_nterror(req, NT_STATUS_NO_MEMORY);
664 goto out;
666 params = *pparams;
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);
670 goto out;
674 status = SMB_VFS_CREATE_FILE(
675 conn, /* conn */
676 req, /* req */
677 dirfsp, /* dirfsp */
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 */
685 NULL, /* lease */
686 open_size, /* allocation_size */
687 private_flags,
688 NULL, /* sd */
689 ea_list, /* ea_list */
690 &fsp, /* result */
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. */
697 goto out;
700 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
701 reply_openerror(req, status);
702 goto out;
705 fsp = fcb_or_dos_open(
706 req,
707 smb_fname,
708 access_mask,
709 create_options,
710 private_flags);
711 if (fsp == NULL) {
712 bool ok = defer_smb1_sharing_violation(req);
713 if (ok) {
714 goto out;
716 reply_openerror(req, status);
717 goto out;
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);
730 goto out;
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);
737 goto out;
739 params = *pparams;
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. */
760 if (flags & 8) {
761 uint32_t ea_size = estimate_ea_size(smb_fname->fsp);
762 SIVAL(params, 26, ea_size);
763 } else {
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);
769 out:
770 TALLOC_FREE(smb_fname);
773 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
774 connection_struct *conn,
775 struct dptr_struct *dirptr,
776 uint16_t flags2,
777 const char *path_mask,
778 uint32_t dirtype,
779 int info_level,
780 bool requires_resume_key,
781 bool dont_descend,
782 bool ask_sharemode,
783 char **ppdata,
784 char *base_data,
785 char *end_data,
786 int space_remaining,
787 int *last_entry_off,
788 struct ea_list *name_list)
790 uint8_t align = 4;
791 const bool do_pad = true;
793 if (info_level >= 1 && info_level <= 3) {
794 /* No alignment on earlier info levels. */
795 align = 1;
798 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
799 path_mask, dirtype, info_level,
800 requires_resume_key, dont_descend, ask_sharemode,
801 true, align, do_pad,
802 ppdata, base_data, end_data,
803 space_remaining,
804 NULL,
805 last_entry_off, name_list, NULL);
808 /****************************************************************************
809 Reply to a TRANS2_FINDFIRST.
810 ****************************************************************************/
812 static void call_trans2findfirst(connection_struct *conn,
813 struct smb_request *req,
814 char **pparams, int total_params,
815 char **ppdata, int total_data,
816 unsigned int max_data_bytes)
818 /* We must be careful here that we don't return more than the
819 allowed number of data bytes. If this means returning fewer than
820 maxentries then so be it. We assume that the redirector has
821 enough room for the fixed number of parameter bytes it has
822 requested. */
823 struct smb_filename *smb_dname = NULL;
824 char *params = *pparams;
825 char *pdata = *ppdata;
826 char *data_end;
827 uint32_t dirtype;
828 int maxentries;
829 uint16_t findfirst_flags;
830 bool close_after_first;
831 bool close_if_end;
832 bool requires_resume_key;
833 int info_level;
834 char *directory = NULL;
835 char *mask = NULL;
836 char *p;
837 int last_entry_off=0;
838 int dptr_num = -1;
839 int numentries = 0;
840 int i;
841 bool finished = False;
842 bool dont_descend = False;
843 bool out_of_space = False;
844 int space_remaining;
845 struct ea_list *ea_list = NULL;
846 NTSTATUS ntstatus = NT_STATUS_OK;
847 bool ask_sharemode;
848 struct smbXsrv_connection *xconn = req->xconn;
849 struct smbd_server_connection *sconn = req->sconn;
850 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
851 bool backup_priv = false;
852 bool as_root = false;
853 files_struct *fsp = NULL;
854 struct files_struct *dirfsp = NULL;
855 const struct loadparm_substitution *lp_sub =
856 loadparm_s3_global_substitution();
858 if (total_params < 13) {
859 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
860 goto out;
863 dirtype = SVAL(params,0);
864 maxentries = SVAL(params,2);
865 findfirst_flags = SVAL(params,4);
866 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
867 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
868 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
869 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
870 security_token_has_privilege(get_current_nttok(conn),
871 SEC_PRIV_BACKUP));
873 info_level = SVAL(params,6);
875 DBG_NOTICE("dirtype = %"PRIx32", maxentries = %d, "
876 "close_after_first=%d, close_if_end = %d "
877 "requires_resume_key = %d backup_priv = %d level = 0x%x, "
878 "max_data_bytes = %d\n",
879 dirtype,
880 maxentries,
881 close_after_first,
882 close_if_end,
883 requires_resume_key,
884 backup_priv,
885 info_level,
886 max_data_bytes);
888 if (!maxentries) {
889 /* W2K3 seems to treat zero as 1. */
890 maxentries = 1;
893 switch (info_level) {
894 case SMB_FIND_INFO_STANDARD:
895 case SMB_FIND_EA_SIZE:
896 case SMB_FIND_EA_LIST:
897 case SMB_FIND_FILE_DIRECTORY_INFO:
898 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
899 case SMB_FIND_FILE_NAMES_INFO:
900 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
901 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
902 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
903 break;
904 case SMB_FIND_FILE_UNIX:
905 case SMB_FIND_FILE_UNIX_INFO2:
906 if (!lp_smb1_unix_extensions()) {
907 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
908 goto out;
910 if (!req->posix_pathnames) {
911 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
912 goto out;
914 break;
915 default:
916 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
917 goto out;
920 if (req->posix_pathnames) {
921 srvstr_get_path_posix(talloc_tos(),
922 params,
923 req->flags2,
924 &directory,
925 params+12,
926 total_params - 12,
927 STR_TERMINATE,
928 &ntstatus);
929 } else {
930 srvstr_get_path(talloc_tos(),
931 params,
932 req->flags2,
933 &directory,
934 params+12,
935 total_params - 12,
936 STR_TERMINATE,
937 &ntstatus);
939 if (!NT_STATUS_IS_OK(ntstatus)) {
940 reply_nterror(req, ntstatus);
941 goto out;
944 if (backup_priv) {
945 become_root();
946 as_root = true;
948 ntstatus = smb1_strip_dfs_path(talloc_tos(), &ucf_flags, &directory);
949 if (!NT_STATUS_IS_OK(ntstatus)) {
950 reply_nterror(req, ntstatus);
951 goto out;
954 ntstatus = filename_convert_smb1_search_path(talloc_tos(),
955 conn,
956 directory,
957 ucf_flags,
958 &dirfsp,
959 &smb_dname,
960 &mask);
962 if (!NT_STATUS_IS_OK(ntstatus)) {
963 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
964 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
965 ERRSRV, ERRbadpath);
966 goto out;
968 reply_nterror(req, ntstatus);
969 goto out;
972 TALLOC_FREE(directory);
973 directory = smb_dname->base_name;
975 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
977 if (info_level == SMB_FIND_EA_LIST) {
978 uint32_t ea_size;
980 if (total_data < 4) {
981 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
982 goto out;
985 ea_size = IVAL(pdata,0);
986 if (ea_size != total_data) {
987 DBG_NOTICE("Rejecting EA request with incorrect "
988 "total_data=%d (should be %" PRIu32 ")\n",
989 total_data,
990 ea_size);
991 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
992 goto out;
995 if (!lp_ea_support(SNUM(conn))) {
996 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
997 goto out;
1000 /* Pull out the list of names. */
1001 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
1002 if (!ea_list) {
1003 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1004 goto out;
1008 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1009 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1010 goto out;
1013 *ppdata = (char *)SMB_REALLOC(
1014 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1015 if(*ppdata == NULL ) {
1016 reply_nterror(req, NT_STATUS_NO_MEMORY);
1017 goto out;
1019 pdata = *ppdata;
1020 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1022 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
1023 * error.
1025 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
1026 /* Realloc the params space */
1027 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1028 if (*pparams == NULL) {
1029 reply_nterror(req, NT_STATUS_NO_MEMORY);
1030 goto out;
1032 params = *pparams;
1035 * Open an fsp on this directory for the dptr.
1037 ntstatus = SMB_VFS_CREATE_FILE(
1038 conn, /* conn */
1039 req, /* req */
1040 dirfsp, /* dirfsp */
1041 smb_dname, /* dname */
1042 FILE_LIST_DIRECTORY, /* access_mask */
1043 FILE_SHARE_READ|
1044 FILE_SHARE_WRITE, /* share_access */
1045 FILE_OPEN, /* create_disposition*/
1046 FILE_DIRECTORY_FILE, /* create_options */
1047 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1048 NO_OPLOCK, /* oplock_request */
1049 NULL, /* lease */
1050 0, /* allocation_size */
1051 0, /* private_flags */
1052 NULL, /* sd */
1053 NULL, /* ea_list */
1054 &fsp, /* result */
1055 NULL, /* pinfo */
1056 NULL, /* in_context */
1057 NULL);/* out_context */
1059 if (!NT_STATUS_IS_OK(ntstatus)) {
1060 DBG_ERR("failed to open directory %s\n",
1061 smb_fname_str_dbg(smb_dname));
1062 reply_nterror(req, ntstatus);
1063 goto out;
1066 /* Save the wildcard match and attribs we are using on this directory -
1067 needed as lanman2 assumes these are being saved between calls */
1069 ntstatus = dptr_create(conn,
1070 req,
1071 fsp, /* fsp */
1072 False,
1073 mask,
1074 dirtype,
1075 &fsp->dptr);
1077 if (!NT_STATUS_IS_OK(ntstatus)) {
1079 * Use NULL here for the first parameter (req)
1080 * as this is not a client visible handle so
1081 * can't be part of an SMB1 chain.
1083 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1084 reply_nterror(req, ntstatus);
1085 goto out;
1088 if (backup_priv) {
1089 /* Remember this in case we have
1090 to do a findnext. */
1091 dptr_set_priv(fsp->dptr);
1094 dptr_num = dptr_dnum(fsp->dptr);
1095 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1097 /* We don't need to check for VOL here as this is returned by
1098 a different TRANS2 call. */
1100 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1101 directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
1102 if (in_list(directory,
1103 lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
1104 dptr_case_sensitive(fsp->dptr))) {
1105 dont_descend = True;
1108 p = pdata;
1109 space_remaining = max_data_bytes;
1110 out_of_space = False;
1112 ask_sharemode = fsp_search_ask_sharemode(fsp);
1114 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1116 ntstatus = get_lanman2_dir_entry(talloc_tos(),
1117 conn,
1118 fsp->dptr,
1119 req->flags2,
1120 mask,
1121 dirtype,
1122 info_level,
1123 requires_resume_key,
1124 dont_descend,
1125 ask_sharemode,
1127 pdata,
1128 data_end,
1129 space_remaining,
1130 &last_entry_off,
1131 ea_list);
1132 if (NT_STATUS_EQUAL(ntstatus, NT_STATUS_ILLEGAL_CHARACTER)) {
1134 * Bad character conversion on name. Ignore
1135 * this entry.
1137 continue;
1139 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
1140 out_of_space = true;
1141 } else {
1142 finished = !NT_STATUS_IS_OK(ntstatus);
1145 if (!finished && !out_of_space) {
1146 numentries++;
1149 /* Ensure space_remaining never goes -ve. */
1150 if (PTR_DIFF(p,pdata) > max_data_bytes) {
1151 space_remaining = 0;
1152 out_of_space = true;
1153 } else {
1154 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1158 /* Check if we can close the dirptr */
1159 if(close_after_first || (finished && close_if_end)) {
1160 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1161 dptr_num = -1;
1162 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1166 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1167 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1168 * the protocol level is less than NT1. Tested with smbclient. JRA.
1169 * This should fix the OS/2 client bug #2335.
1172 if(numentries == 0) {
1173 dptr_num = -1;
1175 * We may have already closed the file in the
1176 * close_after_first or finished case above.
1178 if (fsp != NULL) {
1179 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1181 if (xconn->protocol < PROTOCOL_NT1) {
1182 reply_force_doserror(req, ERRDOS, ERRnofiles);
1183 goto out;
1184 } else {
1185 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
1186 ERRDOS, ERRbadfile);
1187 goto out;
1191 /* At this point pdata points to numentries directory entries. */
1193 /* Set up the return parameter block */
1194 SSVAL(params,0,dptr_num);
1195 SSVAL(params,2,numentries);
1196 SSVAL(params,4,finished);
1197 SSVAL(params,6,0); /* Never an EA error */
1198 SSVAL(params,8,last_entry_off);
1200 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
1201 max_data_bytes);
1203 if ((! *directory) && dptr_path(sconn, dptr_num)) {
1204 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
1205 if (!directory) {
1206 reply_nterror(req, NT_STATUS_NO_MEMORY);
1210 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1211 smb_fn_name(req->cmd),
1212 mask, directory, dirtype, numentries ) );
1215 * Force a name mangle here to ensure that the
1216 * mask as an 8.3 name is top of the mangled cache.
1217 * The reasons for this are subtle. Don't remove
1218 * this code unless you know what you are doing
1219 * (see PR#13758). JRA.
1222 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
1223 char mangled_name[13];
1224 name_to_8_3(mask, mangled_name, True, conn->params);
1226 out:
1228 if (as_root) {
1229 unbecome_root();
1232 TALLOC_FREE(smb_dname);
1233 return;
1236 static bool smbd_dptr_name_equal(struct dptr_struct *dptr,
1237 const char *name1,
1238 const char *name2)
1240 bool equal;
1242 if (dptr_case_sensitive(dptr)) {
1243 equal = (strcmp(name1, name2) == 0);
1244 } else {
1245 equal = strequal(name1, name2);
1248 return equal;
1251 /****************************************************************************
1252 Reply to a TRANS2_FINDNEXT.
1253 ****************************************************************************/
1255 static void call_trans2findnext(connection_struct *conn,
1256 struct smb_request *req,
1257 char **pparams, int total_params,
1258 char **ppdata, int total_data,
1259 unsigned int max_data_bytes)
1261 /* We must be careful here that we don't return more than the
1262 allowed number of data bytes. If this means returning fewer than
1263 maxentries then so be it. We assume that the redirector has
1264 enough room for the fixed number of parameter bytes it has
1265 requested. */
1266 char *params = *pparams;
1267 char *pdata = *ppdata;
1268 char *data_end;
1269 int dptr_num;
1270 int maxentries;
1271 uint16_t info_level;
1272 uint32_t resume_key;
1273 uint16_t findnext_flags;
1274 bool close_after_request;
1275 bool close_if_end;
1276 bool requires_resume_key;
1277 bool continue_bit;
1278 char *resume_name = NULL;
1279 const char *mask = NULL;
1280 const char *directory = NULL;
1281 char *p = NULL;
1282 uint16_t dirtype;
1283 int numentries = 0;
1284 int i, last_entry_off=0;
1285 bool finished = False;
1286 bool dont_descend = False;
1287 bool out_of_space = False;
1288 int space_remaining;
1289 struct ea_list *ea_list = NULL;
1290 NTSTATUS ntstatus = NT_STATUS_OK;
1291 bool ask_sharemode;
1292 TALLOC_CTX *ctx = talloc_tos();
1293 struct smbd_server_connection *sconn = req->sconn;
1294 bool backup_priv = false;
1295 bool as_root = false;
1296 files_struct *fsp = NULL;
1297 const struct loadparm_substitution *lp_sub =
1298 loadparm_s3_global_substitution();
1300 if (total_params < 13) {
1301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1302 return;
1305 dptr_num = SVAL(params,0);
1306 maxentries = SVAL(params,2);
1307 info_level = SVAL(params,4);
1308 resume_key = IVAL(params,6);
1309 findnext_flags = SVAL(params,10);
1310 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1311 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1312 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1313 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1315 if (!continue_bit) {
1316 /* We only need resume_name if continue_bit is zero. */
1317 if (req->posix_pathnames) {
1318 srvstr_get_path_posix(ctx,
1319 params,
1320 req->flags2,
1321 &resume_name,
1322 params+12,
1323 total_params - 12,
1324 STR_TERMINATE,
1325 &ntstatus);
1326 } else {
1327 srvstr_get_path(ctx,
1328 params,
1329 req->flags2,
1330 &resume_name,
1331 params+12,
1332 total_params - 12,
1333 STR_TERMINATE,
1334 &ntstatus);
1336 if (!NT_STATUS_IS_OK(ntstatus)) {
1337 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1338 complain (it thinks we're asking for the directory above the shared
1339 path or an invalid name). Catch this as the resume name is only compared, never used in
1340 a file access. JRA. */
1341 srvstr_pull_talloc(ctx, params, req->flags2,
1342 &resume_name, params+12,
1343 total_params - 12,
1344 STR_TERMINATE);
1346 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
1347 reply_nterror(req, ntstatus);
1348 return;
1353 DBG_NOTICE("dirhandle = %d, max_data_bytes = %u, maxentries = %d, "
1354 "close_after_request=%d, close_if_end = %d "
1355 "requires_resume_key = %d resume_key = %d "
1356 "resume name = %s continue=%d level = %d\n",
1357 dptr_num,
1358 max_data_bytes,
1359 maxentries,
1360 close_after_request,
1361 close_if_end,
1362 requires_resume_key,
1363 resume_key,
1364 resume_name ? resume_name : "(NULL)",
1365 continue_bit,
1366 info_level);
1368 if (!maxentries) {
1369 /* W2K3 seems to treat zero as 1. */
1370 maxentries = 1;
1373 switch (info_level) {
1374 case SMB_FIND_INFO_STANDARD:
1375 case SMB_FIND_EA_SIZE:
1376 case SMB_FIND_EA_LIST:
1377 case SMB_FIND_FILE_DIRECTORY_INFO:
1378 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1379 case SMB_FIND_FILE_NAMES_INFO:
1380 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1381 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1382 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1383 break;
1384 case SMB_FIND_FILE_UNIX:
1385 case SMB_FIND_FILE_UNIX_INFO2:
1386 if (!lp_smb1_unix_extensions()) {
1387 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1388 return;
1390 if (!req->posix_pathnames) {
1391 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1392 return;
1394 break;
1395 default:
1396 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1397 return;
1400 if (info_level == SMB_FIND_EA_LIST) {
1401 uint32_t ea_size;
1403 if (total_data < 4) {
1404 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1405 return;
1408 ea_size = IVAL(pdata,0);
1409 if (ea_size != total_data) {
1410 DBG_NOTICE("Rejecting EA request with incorrect "
1411 "total_data=%d (should be %" PRIu32 ")\n",
1412 total_data,
1413 ea_size);
1414 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1415 return;
1418 if (!lp_ea_support(SNUM(conn))) {
1419 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1420 return;
1423 /* Pull out the list of names. */
1424 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1425 if (!ea_list) {
1426 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1427 return;
1431 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1432 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1433 return;
1436 *ppdata = (char *)SMB_REALLOC(
1437 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1438 if(*ppdata == NULL) {
1439 reply_nterror(req, NT_STATUS_NO_MEMORY);
1440 return;
1443 pdata = *ppdata;
1444 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1447 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
1448 * error.
1450 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
1451 /* Realloc the params space */
1452 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1453 if(*pparams == NULL ) {
1454 reply_nterror(req, NT_STATUS_NO_MEMORY);
1455 return;
1458 params = *pparams;
1460 /* Check that the dptr is valid */
1461 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
1462 if (fsp == NULL) {
1463 reply_nterror(req, STATUS_NO_MORE_FILES);
1464 return;
1467 directory = dptr_path(sconn, dptr_num);
1469 /* Get the wildcard mask from the dptr */
1470 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
1471 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1472 reply_nterror(req, STATUS_NO_MORE_FILES);
1473 return;
1476 /* Get the attr mask from the dptr */
1477 dirtype = dptr_attr(sconn, dptr_num);
1479 backup_priv = dptr_get_priv(fsp->dptr);
1481 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX) "
1482 "backup_priv = %d\n",
1483 dptr_num, mask, dirtype,
1484 (long)fsp->dptr,
1485 (int)backup_priv));
1487 /* We don't need to check for VOL here as this is returned by
1488 a different TRANS2 call. */
1490 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1491 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1492 if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),
1493 dptr_case_sensitive(fsp->dptr)))
1494 dont_descend = True;
1496 p = pdata;
1497 space_remaining = max_data_bytes;
1498 out_of_space = False;
1500 if (backup_priv) {
1501 become_root();
1502 as_root = true;
1506 * Seek to the correct position. We no longer use the resume key but
1507 * depend on the last file name instead.
1510 if(!continue_bit && resume_name && *resume_name) {
1511 bool posix_open = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN);
1512 char *last_name_sent = NULL;
1513 bool sequential;
1516 * Remember, name_to_8_3 is called by
1517 * get_lanman2_dir_entry(), so the resume name
1518 * could be mangled. Ensure we check the unmangled name.
1521 if (!posix_open &&
1522 mangle_is_mangled(resume_name, conn->params)) {
1523 char *new_resume_name = NULL;
1524 mangle_lookup_name_from_8_3(ctx,
1525 resume_name,
1526 &new_resume_name,
1527 conn->params);
1528 if (new_resume_name) {
1529 resume_name = new_resume_name;
1534 * Fix for NT redirector problem triggered by resume key indexes
1535 * changing between directory scans. We now return a resume key of 0
1536 * and instead look for the filename to continue from (also given
1537 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1538 * findfirst/findnext (as is usual) then the directory pointer
1539 * should already be at the correct place.
1542 last_name_sent = smbd_dirptr_get_last_name_sent(fsp->dptr);
1543 sequential = smbd_dptr_name_equal(fsp->dptr,
1544 resume_name,
1545 last_name_sent);
1546 if (!sequential) {
1547 char *name = NULL;
1548 bool found = false;
1550 dptr_RewindDir(fsp->dptr);
1552 while ((name = dptr_ReadDirName(talloc_tos(),
1553 fsp->dptr)) != NULL) {
1554 found = smbd_dptr_name_equal(fsp->dptr,
1555 resume_name,
1556 name);
1557 TALLOC_FREE(name);
1558 if (found) {
1559 break;
1563 if (!found) {
1565 * We got a name that used to exist
1566 * but does not anymore. Just start
1567 * from the beginning. Shown by the
1568 * "raw.search.os2 delete" smbtorture
1569 * test.
1571 dptr_RewindDir(fsp->dptr);
1574 } /* end if resume_name && !continue_bit */
1576 ask_sharemode = fsp_search_ask_sharemode(fsp);
1578 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1580 ntstatus = get_lanman2_dir_entry(ctx,
1581 conn,
1582 fsp->dptr,
1583 req->flags2,
1584 mask,
1585 dirtype,
1586 info_level,
1587 requires_resume_key,
1588 dont_descend,
1589 ask_sharemode,
1591 pdata,
1592 data_end,
1593 space_remaining,
1594 &last_entry_off,
1595 ea_list);
1596 if (NT_STATUS_EQUAL(ntstatus, NT_STATUS_ILLEGAL_CHARACTER)) {
1598 * Bad character conversion on name. Ignore
1599 * this entry.
1601 continue;
1603 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
1604 out_of_space = true;
1605 } else {
1606 finished = !NT_STATUS_IS_OK(ntstatus);
1609 if (!finished && !out_of_space) {
1610 numentries++;
1613 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1616 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1617 smb_fn_name(req->cmd),
1618 mask, directory, dirtype, numentries ) );
1620 /* Check if we can close the fsp->dptr */
1621 if(close_after_request || (finished && close_if_end)) {
1622 DBG_INFO("closing dptr_num = %d\n", dptr_num);
1623 dptr_num = -1;
1624 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1627 if (as_root) {
1628 unbecome_root();
1631 /* Set up the return parameter block */
1632 SSVAL(params,0,numentries);
1633 SSVAL(params,2,finished);
1634 SSVAL(params,4,0); /* Never an EA error */
1635 SSVAL(params,6,last_entry_off);
1637 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
1638 max_data_bytes);
1640 return;
1643 /****************************************************************************
1644 Reply to a TRANS2_QFSINFO (query filesystem info).
1645 ****************************************************************************/
1647 static void call_trans2qfsinfo(connection_struct *conn,
1648 struct smb_request *req,
1649 char **pparams, int total_params,
1650 char **ppdata, int total_data,
1651 unsigned int max_data_bytes)
1653 char *params = *pparams;
1654 uint16_t info_level;
1655 int data_len = 0;
1656 size_t fixed_portion;
1657 NTSTATUS status;
1659 if (total_params < 2) {
1660 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1661 return;
1664 info_level = SVAL(params,0);
1666 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
1667 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
1668 DEBUG(0,("call_trans2qfsinfo: encryption required "
1669 "and info level 0x%x sent.\n",
1670 (unsigned int)info_level));
1671 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1672 return;
1676 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1678 status = smbd_do_qfsinfo(req->xconn, conn, req,
1679 info_level,
1680 req->flags2,
1681 max_data_bytes,
1682 &fixed_portion,
1683 NULL,
1684 ppdata, &data_len);
1685 if (!NT_STATUS_IS_OK(status)) {
1686 reply_nterror(req, status);
1687 return;
1690 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
1691 max_data_bytes);
1693 DEBUG( 4, ( "%s info_level = %d\n",
1694 smb_fn_name(req->cmd), info_level) );
1696 return;
1699 /****************************************************************************
1700 Reply to a TRANS2_SETFSINFO (set filesystem info).
1701 ****************************************************************************/
1703 static void call_trans2setfsinfo(connection_struct *conn,
1704 struct smb_request *req,
1705 char **pparams, int total_params,
1706 char **ppdata, int total_data,
1707 unsigned int max_data_bytes)
1709 const struct loadparm_substitution *lp_sub =
1710 loadparm_s3_global_substitution();
1711 struct smbXsrv_connection *xconn = req->xconn;
1712 char *pdata = *ppdata;
1713 char *params = *pparams;
1714 uint16_t info_level;
1716 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
1717 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
1719 /* */
1720 if (total_params < 4) {
1721 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1722 total_params));
1723 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1724 return;
1727 info_level = SVAL(params,2);
1729 if (IS_IPC(conn)) {
1730 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
1731 info_level != SMB_SET_CIFS_UNIX_INFO) {
1732 DEBUG(0,("call_trans2setfsinfo: not an allowed "
1733 "info level (0x%x) on IPC$.\n",
1734 (unsigned int)info_level));
1735 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1736 return;
1740 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
1741 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
1742 DEBUG(0,("call_trans2setfsinfo: encryption required "
1743 "and info level 0x%x sent.\n",
1744 (unsigned int)info_level));
1745 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1746 return;
1750 switch(info_level) {
1751 case SMB_SET_CIFS_UNIX_INFO:
1752 if (!lp_smb1_unix_extensions()) {
1753 DEBUG(2,("call_trans2setfsinfo: "
1754 "SMB_SET_CIFS_UNIX_INFO is invalid with "
1755 "unix extensions off\n"));
1756 reply_nterror(req,
1757 NT_STATUS_INVALID_LEVEL);
1758 return;
1761 /* There should be 12 bytes of capabilities set. */
1762 if (total_data < 12) {
1763 reply_nterror(
1764 req,
1765 NT_STATUS_INVALID_PARAMETER);
1766 return;
1768 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
1769 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
1770 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
1771 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
1773 /* Just print these values for now. */
1774 DBG_DEBUG("set unix_info info. "
1775 "major = %"PRIu16", minor = %"PRIu16
1776 "cap_low = 0x%"PRIx32", "
1777 "cap_high = 0x%"PRIx32"\n",
1778 xconn->smb1.unix_info.client_major,
1779 xconn->smb1.unix_info.client_minor,
1780 xconn->smb1.unix_info.client_cap_low,
1781 xconn->smb1.unix_info.client_cap_high);
1784 * Here is where we must switch to posix
1785 * pathname processing...
1787 if (xconn->smb1.unix_info.client_cap_low &
1788 CIFS_UNIX_POSIX_PATHNAMES_CAP)
1790 lp_set_posix_pathnames();
1791 mangle_change_to_posix();
1794 if ((xconn->smb1.unix_info.client_cap_low &
1795 CIFS_UNIX_FCNTL_LOCKS_CAP) &&
1796 !(xconn->smb1.unix_info.client_cap_low &
1797 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP))
1799 /* Client that knows how to do posix locks,
1800 * but not posix open/mkdir operations. Set a
1801 * default type for read/write checks. */
1803 lp_set_posix_default_cifsx_readwrite_locktype(
1804 POSIX_LOCK);
1807 break;
1809 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
1811 NTSTATUS status;
1812 size_t param_len = 0;
1813 size_t data_len = total_data;
1815 if (!lp_smb1_unix_extensions()) {
1816 reply_nterror(
1817 req,
1818 NT_STATUS_INVALID_LEVEL);
1819 return;
1822 if (lp_server_smb_encrypt(SNUM(conn)) ==
1823 SMB_ENCRYPTION_OFF) {
1824 reply_nterror(
1825 req,
1826 NT_STATUS_NOT_SUPPORTED);
1827 return;
1830 if (xconn->smb1.echo_handler.trusted_fde) {
1831 DEBUG( 2,("call_trans2setfsinfo: "
1832 "request transport encryption disabled"
1833 "with 'fork echo handler = yes'\n"));
1834 reply_nterror(
1835 req,
1836 NT_STATUS_NOT_SUPPORTED);
1837 return;
1840 DEBUG( 4,("call_trans2setfsinfo: "
1841 "request transport encryption.\n"));
1843 status = srv_request_encryption_setup(conn,
1844 (unsigned char **)ppdata,
1845 &data_len,
1846 (unsigned char **)pparams,
1847 &param_len);
1849 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
1850 !NT_STATUS_IS_OK(status)) {
1851 reply_nterror(req, status);
1852 return;
1855 send_trans2_replies(conn, req,
1856 NT_STATUS_OK,
1857 *pparams,
1858 param_len,
1859 *ppdata,
1860 data_len,
1861 max_data_bytes);
1863 if (NT_STATUS_IS_OK(status)) {
1864 /* Server-side transport
1865 * encryption is now *on*. */
1866 status = srv_encryption_start(conn);
1867 if (!NT_STATUS_IS_OK(status)) {
1868 char *reason = talloc_asprintf(talloc_tos(),
1869 "Failure in setting "
1870 "up encrypted transport: %s",
1871 nt_errstr(status));
1872 exit_server_cleanly(reason);
1875 return;
1878 case SMB_FS_QUOTA_INFORMATION:
1880 NTSTATUS status;
1881 DATA_BLOB qdata = {
1882 .data = (uint8_t *)pdata,
1883 .length = total_data
1885 files_struct *fsp = NULL;
1886 fsp = file_fsp(req, SVAL(params,0));
1888 status = smb_set_fsquota(conn,
1889 req,
1890 fsp,
1891 &qdata);
1892 if (!NT_STATUS_IS_OK(status)) {
1893 reply_nterror(req, status);
1894 return;
1896 break;
1898 default:
1899 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1900 info_level));
1901 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1902 return;
1903 break;
1907 * sending this reply works fine,
1908 * but I'm not sure it's the same
1909 * like windows do...
1910 * --metze
1912 reply_smb1_outbuf(req, 10, 0);
1915 /****************************************************************************
1916 Reply to a TRANSACT2_QFILEINFO on a PIPE !
1917 ****************************************************************************/
1919 static void call_trans2qpipeinfo(connection_struct *conn,
1920 struct smb_request *req,
1921 files_struct *fsp,
1922 uint16_t info_level,
1923 unsigned int tran_call,
1924 char **pparams, int total_params,
1925 char **ppdata, int total_data,
1926 unsigned int max_data_bytes)
1928 char *params = *pparams;
1929 char *pdata = *ppdata;
1930 unsigned int data_size = 0;
1931 unsigned int param_size = 2;
1933 if (!fsp_is_np(fsp)) {
1934 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1935 return;
1938 *pparams = (char *)SMB_REALLOC(*pparams,2);
1939 if (*pparams == NULL) {
1940 reply_nterror(req, NT_STATUS_NO_MEMORY);
1941 return;
1943 params = *pparams;
1944 SSVAL(params,0,0);
1945 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1946 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1947 return;
1949 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
1950 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
1951 if (*ppdata == NULL ) {
1952 reply_nterror(req, NT_STATUS_NO_MEMORY);
1953 return;
1955 pdata = *ppdata;
1957 switch (info_level) {
1958 case SMB_FILE_STANDARD_INFORMATION:
1959 memset(pdata,0,24);
1960 SOFF_T(pdata,0,4096LL);
1961 SIVAL(pdata,16,1);
1962 SIVAL(pdata,20,1);
1963 data_size = 24;
1964 break;
1966 default:
1967 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1968 return;
1971 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
1972 max_data_bytes);
1974 return;
1977 static void handle_trans2qfilepathinfo_result(
1978 connection_struct *conn,
1979 struct smb_request *req,
1980 uint16_t info_level,
1981 NTSTATUS status,
1982 char *pdata,
1983 int data_return_size,
1984 size_t fixed_portion,
1985 unsigned int max_data_bytes)
1987 char params[2] = { 0, 0, };
1988 int param_size = 2;
1991 * draft-leach-cifs-v1-spec-02.txt
1992 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
1993 * says:
1995 * The requested information is placed in the Data portion of the
1996 * transaction response. For the information levels greater than 0x100,
1997 * the transaction response has 1 parameter word which should be
1998 * ignored by the client.
2000 * However Windows only follows this rule for the IS_NAME_VALID call.
2002 switch (info_level) {
2003 case SMB_INFO_IS_NAME_VALID:
2004 param_size = 0;
2005 break;
2008 if (!NT_STATUS_IS_OK(status)) {
2009 if (open_was_deferred(req->xconn, req->mid)) {
2010 /* We have re-scheduled this call. */
2011 return;
2013 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2014 bool ok = defer_smb1_sharing_violation(req);
2015 if (ok) {
2016 return;
2019 reply_nterror(req, status);
2020 return;
2023 if (fixed_portion > max_data_bytes) {
2024 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
2025 return;
2028 send_trans2_replies(
2029 conn,
2030 req,
2031 NT_STATUS_OK,
2032 params,
2033 param_size,
2034 pdata,
2035 data_return_size,
2036 max_data_bytes);
2039 /****************************************************************************
2040 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2041 file name or file id).
2042 ****************************************************************************/
2044 static void call_trans2qfilepathinfo(connection_struct *conn,
2045 struct smb_request *req,
2046 unsigned int tran_call,
2047 uint16_t info_level,
2048 struct smb_filename *smb_fname,
2049 struct files_struct *fsp,
2050 bool delete_pending,
2051 struct timespec write_time_ts,
2052 char **pparams, int total_params,
2053 char **ppdata, int total_data,
2054 unsigned int max_data_bytes)
2056 char *params = *pparams;
2057 char *pdata = *ppdata;
2058 unsigned int data_size = 0;
2059 struct ea_list *ea_list = NULL;
2060 size_t fixed_portion;
2061 NTSTATUS status = NT_STATUS_OK;
2063 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
2064 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
2065 fsp_fnum_dbg(fsp),
2066 info_level,tran_call,total_data));
2068 /* Pull out any data sent here before we realloc. */
2069 switch (info_level) {
2070 case SMB_INFO_QUERY_EAS_FROM_LIST:
2072 /* Pull any EA list from the data portion. */
2073 uint32_t ea_size;
2075 if (total_data < 4) {
2076 reply_nterror(
2077 req, NT_STATUS_INVALID_PARAMETER);
2078 return;
2080 ea_size = IVAL(pdata,0);
2082 if (total_data > 0 && ea_size != total_data) {
2083 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2084 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2085 reply_nterror(
2086 req, NT_STATUS_INVALID_PARAMETER);
2087 return;
2090 if (!lp_ea_support(SNUM(conn))) {
2091 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2092 return;
2095 /* Pull out the list of names. */
2096 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
2097 if (!ea_list) {
2098 reply_nterror(
2099 req, NT_STATUS_INVALID_PARAMETER);
2100 return;
2102 break;
2105 default:
2106 break;
2109 *pparams = (char *)SMB_REALLOC(*pparams,2);
2110 if (*pparams == NULL) {
2111 reply_nterror(req, NT_STATUS_NO_MEMORY);
2112 return;
2114 params = *pparams;
2115 SSVAL(params,0,0);
2117 if ((info_level & SMB2_INFO_SPECIAL) == SMB2_INFO_SPECIAL) {
2119 * We use levels that start with 0xFF00
2120 * internally to represent SMB2 specific levels
2122 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2123 return;
2126 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
2127 fsp, smb_fname,
2128 delete_pending, write_time_ts,
2129 ea_list,
2130 req->flags2, max_data_bytes,
2131 &fixed_portion,
2132 ppdata, &data_size);
2134 handle_trans2qfilepathinfo_result(
2135 conn,
2136 req,
2137 info_level,
2138 status,
2139 *ppdata,
2140 data_size,
2141 fixed_portion,
2142 max_data_bytes);
2145 static NTSTATUS smb_q_unix_basic(
2146 struct connection_struct *conn,
2147 struct smb_request *req,
2148 struct smb_filename *smb_fname,
2149 struct files_struct *fsp,
2150 char **ppdata,
2151 int *ptotal_data)
2153 const int total_data = 100;
2155 *ppdata = SMB_REALLOC(*ppdata, total_data);
2156 if (*ppdata == NULL) {
2157 return NT_STATUS_NO_MEMORY;
2159 store_file_unix_basic(conn, *ppdata, fsp, &smb_fname->st);
2161 *ptotal_data = total_data;
2163 return NT_STATUS_OK;
2166 static NTSTATUS smb_q_unix_info2(
2167 struct connection_struct *conn,
2168 struct smb_request *req,
2169 struct smb_filename *smb_fname,
2170 struct files_struct *fsp,
2171 char **ppdata,
2172 int *ptotal_data)
2174 const int total_data = 116;
2176 *ppdata = SMB_REALLOC(*ppdata, total_data);
2177 if (*ppdata == NULL) {
2178 return NT_STATUS_NO_MEMORY;
2180 store_file_unix_basic_info2(conn, *ppdata, fsp, &smb_fname->st);
2182 *ptotal_data = total_data;
2184 return NT_STATUS_OK;
2187 #if defined(HAVE_POSIX_ACLS)
2188 /****************************************************************************
2189 Utility function to open a fsp for a POSIX handle operation.
2190 ****************************************************************************/
2192 static NTSTATUS get_posix_fsp(connection_struct *conn,
2193 struct smb_request *req,
2194 struct smb_filename *smb_fname,
2195 uint32_t access_mask,
2196 files_struct **ret_fsp)
2198 NTSTATUS status;
2199 uint32_t create_disposition = FILE_OPEN;
2200 uint32_t share_access = FILE_SHARE_READ|
2201 FILE_SHARE_WRITE|
2202 FILE_SHARE_DELETE;
2203 struct smb2_create_blobs *posx = NULL;
2206 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
2207 * but set reasonable defaults.
2209 uint32_t file_attributes = 0664;
2210 uint32_t oplock = NO_OPLOCK;
2211 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
2213 /* File or directory must exist. */
2214 if (!VALID_STAT(smb_fname->st)) {
2215 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2217 /* Cannot be a symlink. */
2218 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
2219 return NT_STATUS_ACCESS_DENIED;
2221 /* Set options correctly for directory open. */
2222 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
2224 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
2225 * directories, but set reasonable defaults.
2227 file_attributes = 0775;
2228 create_options = FILE_DIRECTORY_FILE;
2231 status = make_smb2_posix_create_ctx(
2232 talloc_tos(), &posx, file_attributes);
2233 if (!NT_STATUS_IS_OK(status)) {
2234 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
2235 nt_errstr(status));
2236 goto done;
2239 status = SMB_VFS_CREATE_FILE(
2240 conn, /* conn */
2241 req, /* req */
2242 NULL, /* dirfsp */
2243 smb_fname, /* fname */
2244 access_mask, /* access_mask */
2245 share_access, /* share_access */
2246 create_disposition,/* create_disposition*/
2247 create_options, /* create_options */
2248 file_attributes,/* file_attributes */
2249 oplock, /* oplock_request */
2250 NULL, /* lease */
2251 0, /* allocation_size */
2252 0, /* private_flags */
2253 NULL, /* sd */
2254 NULL, /* ea_list */
2255 ret_fsp, /* result */
2256 NULL, /* pinfo */
2257 posx, /* in_context */
2258 NULL); /* out_context */
2260 done:
2261 TALLOC_FREE(posx);
2262 return status;
2265 /****************************************************************************
2266 Utility function to count the number of entries in a POSIX acl.
2267 ****************************************************************************/
2269 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2271 unsigned int ace_count = 0;
2272 int entry_id = SMB_ACL_FIRST_ENTRY;
2273 SMB_ACL_ENTRY_T entry;
2275 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2276 entry_id = SMB_ACL_NEXT_ENTRY;
2277 ace_count++;
2279 return ace_count;
2282 /****************************************************************************
2283 Utility function to marshall a POSIX acl into wire format.
2284 ****************************************************************************/
2286 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2288 int entry_id = SMB_ACL_FIRST_ENTRY;
2289 SMB_ACL_ENTRY_T entry;
2291 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2292 SMB_ACL_TAG_T tagtype;
2293 SMB_ACL_PERMSET_T permset;
2294 unsigned char perms = 0;
2295 unsigned int own_grp;
2297 entry_id = SMB_ACL_NEXT_ENTRY;
2299 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
2300 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2301 return False;
2304 if (sys_acl_get_permset(entry, &permset) == -1) {
2305 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2306 return False;
2309 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2310 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2311 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2313 SCVAL(pdata,1,perms);
2315 switch (tagtype) {
2316 case SMB_ACL_USER_OBJ:
2317 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2318 own_grp = (unsigned int)pst->st_ex_uid;
2319 SIVAL(pdata,2,own_grp);
2320 SIVAL(pdata,6,0);
2321 break;
2322 case SMB_ACL_USER:
2324 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
2325 if (!puid) {
2326 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2327 return False;
2329 own_grp = (unsigned int)*puid;
2330 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2331 SIVAL(pdata,2,own_grp);
2332 SIVAL(pdata,6,0);
2333 break;
2335 case SMB_ACL_GROUP_OBJ:
2336 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2337 own_grp = (unsigned int)pst->st_ex_gid;
2338 SIVAL(pdata,2,own_grp);
2339 SIVAL(pdata,6,0);
2340 break;
2341 case SMB_ACL_GROUP:
2343 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
2344 if (!pgid) {
2345 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2346 return False;
2348 own_grp = (unsigned int)*pgid;
2349 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2350 SIVAL(pdata,2,own_grp);
2351 SIVAL(pdata,6,0);
2352 break;
2354 case SMB_ACL_MASK:
2355 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2356 SIVAL(pdata,2,0xFFFFFFFF);
2357 SIVAL(pdata,6,0xFFFFFFFF);
2358 break;
2359 case SMB_ACL_OTHER:
2360 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2361 SIVAL(pdata,2,0xFFFFFFFF);
2362 SIVAL(pdata,6,0xFFFFFFFF);
2363 break;
2364 default:
2365 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2366 return False;
2368 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2371 return True;
2373 #endif
2375 static NTSTATUS smb_q_posix_acl(
2376 struct connection_struct *conn,
2377 struct smb_request *req,
2378 struct smb_filename *smb_fname,
2379 struct files_struct *fsp,
2380 char **ppdata,
2381 int *ptotal_data)
2383 #if !defined(HAVE_POSIX_ACLS)
2384 return NT_STATUS_INVALID_LEVEL;
2385 #else
2386 char *pdata = NULL;
2387 SMB_ACL_T file_acl = NULL;
2388 SMB_ACL_T def_acl = NULL;
2389 uint16_t num_file_acls = 0;
2390 uint16_t num_def_acls = 0;
2391 unsigned int size_needed = 0;
2392 NTSTATUS status;
2393 bool ok;
2394 bool close_fsp = false;
2397 * Ensure we always operate on a file descriptor, not just
2398 * the filename.
2400 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
2401 uint32_t access_mask = SEC_STD_READ_CONTROL|
2402 FILE_READ_ATTRIBUTES|
2403 FILE_WRITE_ATTRIBUTES;
2405 status = get_posix_fsp(conn,
2406 req,
2407 smb_fname,
2408 access_mask,
2409 &fsp);
2411 if (!NT_STATUS_IS_OK(status)) {
2412 goto out;
2414 close_fsp = true;
2417 SMB_ASSERT(fsp != NULL);
2419 status = refuse_symlink_fsp(fsp);
2420 if (!NT_STATUS_IS_OK(status)) {
2421 goto out;
2424 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, SMB_ACL_TYPE_ACCESS,
2425 talloc_tos());
2427 if (file_acl == NULL && no_acl_syscall_error(errno)) {
2428 DBG_INFO("ACLs not implemented on "
2429 "filesystem containing %s\n",
2430 fsp_str_dbg(fsp));
2431 status = NT_STATUS_NOT_IMPLEMENTED;
2432 goto out;
2435 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2437 * We can only have default POSIX ACLs on
2438 * directories.
2440 if (!fsp->fsp_flags.is_directory) {
2441 DBG_INFO("Non-directory open %s\n",
2442 fsp_str_dbg(fsp));
2443 status = NT_STATUS_INVALID_HANDLE;
2444 goto out;
2446 def_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
2447 SMB_ACL_TYPE_DEFAULT,
2448 talloc_tos());
2449 def_acl = free_empty_sys_acl(conn, def_acl);
2452 num_file_acls = count_acl_entries(conn, file_acl);
2453 num_def_acls = count_acl_entries(conn, def_acl);
2455 /* Wrap checks. */
2456 if (num_file_acls + num_def_acls < num_file_acls) {
2457 status = NT_STATUS_INVALID_PARAMETER;
2458 goto out;
2461 size_needed = num_file_acls + num_def_acls;
2464 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
2465 * than UINT_MAX, so check by division.
2467 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
2468 status = NT_STATUS_INVALID_PARAMETER;
2469 goto out;
2472 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
2473 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
2474 status = NT_STATUS_INVALID_PARAMETER;
2475 goto out;
2477 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
2479 *ppdata = SMB_REALLOC(*ppdata, size_needed);
2480 if (*ppdata == NULL) {
2481 status = NT_STATUS_NO_MEMORY;
2482 goto out;
2484 pdata = *ppdata;
2486 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
2487 SSVAL(pdata,2,num_file_acls);
2488 SSVAL(pdata,4,num_def_acls);
2489 pdata += SMB_POSIX_ACL_HEADER_SIZE;
2491 ok = marshall_posix_acl(conn,
2492 pdata,
2493 &fsp->fsp_name->st,
2494 file_acl);
2495 if (!ok) {
2496 status = NT_STATUS_INTERNAL_ERROR;
2497 goto out;
2499 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
2501 ok = marshall_posix_acl(conn,
2502 pdata,
2503 &fsp->fsp_name->st,
2504 def_acl);
2505 if (!ok) {
2506 status = NT_STATUS_INTERNAL_ERROR;
2507 goto out;
2510 *ptotal_data = size_needed;
2511 status = NT_STATUS_OK;
2513 out:
2515 if (close_fsp) {
2517 * Ensure the stat struct in smb_fname is up to
2518 * date. Structure copy.
2520 smb_fname->st = fsp->fsp_name->st;
2521 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
2524 TALLOC_FREE(file_acl);
2525 TALLOC_FREE(def_acl);
2526 return status;
2527 #endif
2530 static NTSTATUS smb_q_posix_symlink(
2531 struct connection_struct *conn,
2532 struct smb_request *req,
2533 struct smb_filename *smb_fname,
2534 char **ppdata,
2535 int *ptotal_data)
2537 char buffer[PATH_MAX+1];
2538 size_t needed, len;
2539 int link_len;
2540 char *pdata = NULL;
2541 struct smb_filename *parent_fname = NULL;
2542 struct smb_filename *base_name = NULL;
2543 NTSTATUS status;
2545 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
2546 smb_fname_str_dbg(smb_fname));
2548 if (!S_ISLNK(smb_fname->st.st_ex_mode)) {
2549 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
2552 status = parent_pathref(
2553 talloc_tos(),
2554 conn->cwd_fsp,
2555 smb_fname,
2556 &parent_fname,
2557 &base_name);
2559 if (!NT_STATUS_IS_OK(status)) {
2560 DBG_DEBUG("parent_pathref failed: %s\n", nt_errstr(status));
2561 return status;
2564 link_len = SMB_VFS_READLINKAT(
2565 conn,
2566 parent_fname->fsp,
2567 base_name,
2568 buffer,
2569 sizeof(buffer)-1);
2570 TALLOC_FREE(parent_fname);
2572 if (link_len == -1) {
2573 status = map_nt_error_from_unix(errno);
2574 DBG_DEBUG("READLINKAT failed: %s\n", nt_errstr(status));
2575 return status;
2577 if (link_len >= sizeof(buffer)) {
2578 return NT_STATUS_INTERNAL_ERROR;
2580 buffer[link_len] = 0;
2582 needed = (link_len+1)*2;
2584 *ppdata = SMB_REALLOC(*ppdata, needed);
2585 if (*ppdata == NULL) {
2586 return NT_STATUS_NO_MEMORY;
2588 pdata = *ppdata;
2590 status = srvstr_push(
2591 pdata,
2592 req->flags2,
2593 pdata,
2594 buffer,
2595 needed,
2596 STR_TERMINATE,
2597 &len);
2598 if (!NT_STATUS_IS_OK(status)) {
2599 return status;
2601 *ptotal_data = len;
2603 return NT_STATUS_OK;
2606 static void call_trans2qpathinfo(
2607 connection_struct *conn,
2608 struct smb_request *req,
2609 char **pparams,
2610 int total_params,
2611 char **ppdata,
2612 int total_data,
2613 unsigned int max_data_bytes)
2615 char *params = *pparams;
2616 uint16_t info_level;
2617 struct smb_filename *smb_fname = NULL;
2618 bool delete_pending = False;
2619 struct timespec write_time_ts = { .tv_sec = 0, };
2620 struct files_struct *dirfsp = NULL;
2621 files_struct *fsp = NULL;
2622 struct file_id fileid;
2623 uint32_t name_hash;
2624 char *fname = NULL;
2625 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2626 NTTIME twrp = 0;
2627 bool info_level_handled;
2628 NTSTATUS status = NT_STATUS_OK;
2629 int ret;
2631 if (!params) {
2632 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2633 return;
2637 /* qpathinfo */
2638 if (total_params < 7) {
2639 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2640 return;
2643 info_level = SVAL(params,0);
2645 DBG_NOTICE("TRANSACT2_QPATHINFO: level = %d\n", info_level);
2647 if (INFO_LEVEL_IS_UNIX(info_level)) {
2648 if (!lp_smb1_unix_extensions()) {
2649 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2650 return;
2652 if (!req->posix_pathnames) {
2653 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2654 return;
2658 if (req->posix_pathnames) {
2659 srvstr_get_path_posix(req,
2660 params,
2661 req->flags2,
2662 &fname,
2663 &params[6],
2664 total_params - 6,
2665 STR_TERMINATE,
2666 &status);
2667 } else {
2668 srvstr_get_path(req,
2669 params,
2670 req->flags2,
2671 &fname,
2672 &params[6],
2673 total_params - 6,
2674 STR_TERMINATE,
2675 &status);
2677 if (!NT_STATUS_IS_OK(status)) {
2678 reply_nterror(req, status);
2679 return;
2682 if (ucf_flags & UCF_GMT_PATHNAME) {
2683 extract_snapshot_token(fname, &twrp);
2685 status = smb1_strip_dfs_path(req, &ucf_flags, &fname);
2686 if (!NT_STATUS_IS_OK(status)) {
2687 reply_nterror(req, status);
2688 return;
2690 status = filename_convert_dirfsp(req,
2691 conn,
2692 fname,
2693 ucf_flags,
2694 twrp,
2695 &dirfsp,
2696 &smb_fname);
2697 if (!NT_STATUS_IS_OK(status)) {
2698 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2699 reply_botherror(req,
2700 NT_STATUS_PATH_NOT_COVERED,
2701 ERRSRV, ERRbadpath);
2702 return;
2704 reply_nterror(req, status);
2705 return;
2709 * qpathinfo must operate on an existing file, so we
2710 * can exit early if filename_convert_dirfsp() returned the
2711 * "new file" NT_STATUS_OK, !VALID_STAT case.
2714 if (!VALID_STAT(smb_fname->st)) {
2715 reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2716 return;
2720 * smb_fname->fsp may be NULL if smb_fname points at a symlink
2721 * and we're in POSIX context, so be careful when using fsp
2722 * below, it can still be NULL.
2724 fsp = smb_fname->fsp;
2726 /* If this is a stream, check if there is a delete_pending. */
2727 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
2728 && is_ntfs_stream_smb_fname(smb_fname)) {
2729 struct smb_filename *smb_fname_base;
2731 /* Create an smb_filename with stream_name == NULL. */
2732 smb_fname_base = synthetic_smb_fname(
2733 talloc_tos(),
2734 smb_fname->base_name,
2735 NULL,
2736 NULL,
2737 smb_fname->twrp,
2738 smb_fname->flags);
2739 if (smb_fname_base == NULL) {
2740 reply_nterror(req, NT_STATUS_NO_MEMORY);
2741 return;
2744 ret = vfs_stat(conn, smb_fname_base);
2745 if (ret != 0) {
2746 DBG_NOTICE("vfs_stat of %s failed "
2747 "(%s)\n",
2748 smb_fname_str_dbg(smb_fname_base),
2749 strerror(errno));
2750 TALLOC_FREE(smb_fname_base);
2751 reply_nterror(req,
2752 map_nt_error_from_unix(errno));
2753 return;
2756 status = file_name_hash(conn,
2757 smb_fname_str_dbg(smb_fname_base),
2758 &name_hash);
2759 if (!NT_STATUS_IS_OK(status)) {
2760 TALLOC_FREE(smb_fname_base);
2761 reply_nterror(req, status);
2762 return;
2765 fileid = vfs_file_id_from_sbuf(conn,
2766 &smb_fname_base->st);
2767 TALLOC_FREE(smb_fname_base);
2768 get_file_infos(fileid, name_hash, &delete_pending, NULL);
2769 if (delete_pending) {
2770 reply_nterror(req, NT_STATUS_DELETE_PENDING);
2771 return;
2775 status = file_name_hash(conn,
2776 smb_fname_str_dbg(smb_fname),
2777 &name_hash);
2778 if (!NT_STATUS_IS_OK(status)) {
2779 reply_nterror(req, status);
2780 return;
2783 if (fsp_getinfo_ask_sharemode(fsp)) {
2784 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2785 get_file_infos(fileid, name_hash, &delete_pending,
2786 &write_time_ts);
2789 if (delete_pending) {
2790 reply_nterror(req, NT_STATUS_DELETE_PENDING);
2791 return;
2794 info_level_handled = true; /* Untouched in switch cases below */
2796 switch (info_level) {
2798 default:
2799 info_level_handled = false;
2800 break;
2802 case SMB_QUERY_FILE_UNIX_BASIC:
2803 status = smb_q_unix_basic(
2804 conn,
2805 req,
2806 smb_fname,
2807 smb_fname->fsp,
2808 ppdata,
2809 &total_data);
2810 break;
2812 case SMB_QUERY_FILE_UNIX_INFO2:
2813 status = smb_q_unix_info2(
2814 conn,
2815 req,
2816 smb_fname,
2817 smb_fname->fsp,
2818 ppdata,
2819 &total_data);
2820 break;
2822 case SMB_QUERY_POSIX_ACL:
2823 status = smb_q_posix_acl(
2824 conn,
2825 req,
2826 smb_fname,
2827 smb_fname->fsp,
2828 ppdata,
2829 &total_data);
2830 break;
2832 case SMB_QUERY_FILE_UNIX_LINK:
2833 status = smb_q_posix_symlink(
2834 conn,
2835 req,
2836 smb_fname,
2837 ppdata,
2838 &total_data);
2839 break;
2842 if (info_level_handled) {
2843 handle_trans2qfilepathinfo_result(
2844 conn,
2845 req,
2846 info_level,
2847 status,
2848 *ppdata,
2849 total_data,
2850 total_data,
2851 max_data_bytes);
2852 return;
2855 call_trans2qfilepathinfo(
2856 conn,
2857 req,
2858 TRANSACT2_QPATHINFO,
2859 info_level,
2860 smb_fname,
2861 fsp,
2862 false,
2863 write_time_ts,
2864 pparams,
2865 total_params,
2866 ppdata,
2867 total_data,
2868 max_data_bytes);
2871 static NTSTATUS smb_q_posix_lock(
2872 struct connection_struct *conn,
2873 struct smb_request *req,
2874 struct files_struct *fsp,
2875 char **ppdata,
2876 int *ptotal_data)
2878 char *pdata = *ppdata;
2879 int total_data = *ptotal_data;
2880 uint64_t count;
2881 uint64_t offset;
2882 uint64_t smblctx;
2883 enum brl_type lock_type;
2884 NTSTATUS status;
2886 if (fsp->fsp_flags.is_pathref || (fsp_get_io_fd(fsp) == -1)) {
2887 return NT_STATUS_INVALID_HANDLE;
2890 if (total_data != POSIX_LOCK_DATA_SIZE) {
2891 return NT_STATUS_INVALID_PARAMETER;
2894 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
2895 case POSIX_LOCK_TYPE_READ:
2896 lock_type = READ_LOCK;
2897 break;
2898 case POSIX_LOCK_TYPE_WRITE:
2899 lock_type = WRITE_LOCK;
2900 break;
2901 case POSIX_LOCK_TYPE_UNLOCK:
2902 default:
2903 /* There's no point in asking for an unlock... */
2904 return NT_STATUS_INVALID_PARAMETER;
2907 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
2908 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
2909 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
2911 status = query_lock(
2912 fsp,
2913 &smblctx,
2914 &count,
2915 &offset,
2916 &lock_type,
2917 POSIX_LOCK);
2919 if (NT_STATUS_IS_OK(status)) {
2921 * For success we just return a copy of what we sent
2922 * with the lock type set to POSIX_LOCK_TYPE_UNLOCK.
2924 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
2925 return NT_STATUS_OK;
2928 if (!ERROR_WAS_LOCK_DENIED(status)) {
2929 DBG_DEBUG("query_lock() failed: %s\n", nt_errstr(status));
2930 return status;
2934 * Here we need to report who has it locked.
2937 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
2938 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
2939 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
2940 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
2941 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
2943 return NT_STATUS_OK;
2946 static void call_trans2qfileinfo(
2947 connection_struct *conn,
2948 struct smb_request *req,
2949 char **pparams,
2950 int total_params,
2951 char **ppdata,
2952 int total_data,
2953 unsigned int max_data_bytes)
2955 char *params = *pparams;
2956 uint16_t info_level;
2957 struct smb_filename *smb_fname = NULL;
2958 bool delete_pending = False;
2959 struct timespec write_time_ts = { .tv_sec = 0, };
2960 files_struct *fsp = NULL;
2961 struct file_id fileid;
2962 bool info_level_handled;
2963 NTSTATUS status = NT_STATUS_OK;
2964 int ret;
2966 if (params == NULL) {
2967 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2968 return;
2971 if (total_params < 4) {
2972 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2973 return;
2976 fsp = file_fsp(req, SVAL(params,0));
2977 info_level = SVAL(params,2);
2979 if (IS_IPC(conn)) {
2980 call_trans2qpipeinfo(
2981 conn,
2982 req,
2983 fsp,
2984 info_level,
2985 TRANSACT2_QFILEINFO,
2986 pparams,
2987 total_params,
2988 ppdata,
2989 total_data,
2990 max_data_bytes);
2991 return;
2994 DBG_NOTICE("TRANSACT2_QFILEINFO: level = %d\n", info_level);
2996 if (INFO_LEVEL_IS_UNIX(info_level)) {
2997 if (!lp_smb1_unix_extensions()) {
2998 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2999 return;
3001 if (!req->posix_pathnames) {
3002 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3003 return;
3007 /* Initial check for valid fsp ptr. */
3008 if (!check_fsp_open(conn, req, fsp)) {
3009 return;
3012 smb_fname = fsp->fsp_name;
3014 if(fsp->fake_file_handle) {
3016 * This is actually for the QUOTA_FAKE_FILE --metze
3019 /* We know this name is ok, it's already passed the checks. */
3021 } else if(fsp_get_pathref_fd(fsp) == -1) {
3023 * This is actually a QFILEINFO on a directory
3024 * handle (returned from an NT SMB). NT5.0 seems
3025 * to do this call. JRA.
3027 ret = vfs_stat(conn, smb_fname);
3028 if (ret != 0) {
3029 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
3030 smb_fname_str_dbg(smb_fname),
3031 strerror(errno));
3032 reply_nterror(req,
3033 map_nt_error_from_unix(errno));
3034 return;
3037 if (fsp_getinfo_ask_sharemode(fsp)) {
3038 fileid = vfs_file_id_from_sbuf(
3039 conn, &smb_fname->st);
3040 get_file_infos(fileid, fsp->name_hash,
3041 &delete_pending,
3042 &write_time_ts);
3044 } else {
3046 * Original code - this is an open file.
3048 status = vfs_stat_fsp(fsp);
3049 if (!NT_STATUS_IS_OK(status)) {
3050 DEBUG(3, ("fstat of %s failed (%s)\n",
3051 fsp_fnum_dbg(fsp), nt_errstr(status)));
3052 reply_nterror(req, status);
3053 return;
3055 if (fsp_getinfo_ask_sharemode(fsp)) {
3056 fileid = vfs_file_id_from_sbuf(
3057 conn, &smb_fname->st);
3058 get_file_infos(fileid, fsp->name_hash,
3059 &delete_pending,
3060 &write_time_ts);
3064 info_level_handled = true; /* Untouched in switch cases below */
3066 switch (info_level) {
3068 default:
3069 info_level_handled = false;
3070 break;
3072 case SMB_QUERY_POSIX_LOCK:
3073 status = smb_q_posix_lock(conn, req, fsp, ppdata, &total_data);
3074 break;
3076 case SMB_QUERY_FILE_UNIX_BASIC:
3077 status = smb_q_unix_basic(
3078 conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3079 break;
3081 case SMB_QUERY_FILE_UNIX_INFO2:
3082 status = smb_q_unix_info2(
3083 conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3084 break;
3086 case SMB_QUERY_POSIX_ACL:
3087 status = smb_q_posix_acl(
3088 conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3089 break;
3092 if (info_level_handled) {
3093 handle_trans2qfilepathinfo_result(
3094 conn,
3095 req,
3096 info_level,
3097 status,
3098 *ppdata,
3099 total_data,
3100 total_data,
3101 max_data_bytes);
3102 return;
3105 call_trans2qfilepathinfo(
3106 conn,
3107 req,
3108 TRANSACT2_QFILEINFO,
3109 info_level,
3110 smb_fname,
3111 fsp,
3112 delete_pending,
3113 write_time_ts,
3114 pparams,
3115 total_params,
3116 ppdata,
3117 total_data,
3118 max_data_bytes);
3121 static void handle_trans2setfilepathinfo_result(
3122 connection_struct *conn,
3123 struct smb_request *req,
3124 uint16_t info_level,
3125 NTSTATUS status,
3126 char *pdata,
3127 int data_return_size,
3128 unsigned int max_data_bytes)
3130 char params[2] = { 0, 0, };
3132 if (NT_STATUS_IS_OK(status)) {
3133 send_trans2_replies(
3134 conn,
3135 req,
3136 NT_STATUS_OK,
3137 params,
3139 pdata,
3140 data_return_size,
3141 max_data_bytes);
3142 return;
3145 if (open_was_deferred(req->xconn, req->mid)) {
3146 /* We have re-scheduled this call. */
3147 return;
3150 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3151 bool ok = defer_smb1_sharing_violation(req);
3152 if (ok) {
3153 return;
3157 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
3158 /* We have re-scheduled this call. */
3159 return;
3162 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3163 reply_botherror(
3164 req,
3165 NT_STATUS_PATH_NOT_COVERED,
3166 ERRSRV,
3167 ERRbadpath);
3168 return;
3171 if (info_level == SMB_POSIX_PATH_OPEN) {
3172 reply_openerror(req, status);
3173 return;
3176 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
3178 * Invalid EA name needs to return 2 param bytes,
3179 * not a zero-length error packet.
3182 send_trans2_replies(
3183 conn,
3184 req,
3185 status,
3186 params,
3188 NULL,
3190 max_data_bytes);
3191 return;
3194 reply_nterror(req, status);
3197 /****************************************************************************
3198 Create a directory with POSIX semantics.
3199 ****************************************************************************/
3201 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
3202 struct smb_request *req,
3203 char **ppdata,
3204 int total_data,
3205 struct smb_filename *smb_fname,
3206 int *pdata_return_size)
3208 NTSTATUS status = NT_STATUS_OK;
3209 uint32_t raw_unixmode = 0;
3210 mode_t unixmode = (mode_t)0;
3211 files_struct *fsp = NULL;
3212 uint16_t info_level_return = 0;
3213 int info;
3214 char *pdata = *ppdata;
3215 struct smb2_create_blobs *posx = NULL;
3217 if (total_data < 18) {
3218 return NT_STATUS_INVALID_PARAMETER;
3221 raw_unixmode = IVAL(pdata,8);
3222 /* Next 4 bytes are not yet defined. */
3224 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
3225 PERM_NEW_DIR, &unixmode);
3226 if (!NT_STATUS_IS_OK(status)) {
3227 return status;
3230 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
3231 if (!NT_STATUS_IS_OK(status)) {
3232 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3233 nt_errstr(status));
3234 return status;
3237 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
3238 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
3240 status = SMB_VFS_CREATE_FILE(
3241 conn, /* conn */
3242 req, /* req */
3243 NULL, /* dirfsp */
3244 smb_fname, /* fname */
3245 FILE_READ_ATTRIBUTES, /* access_mask */
3246 FILE_SHARE_NONE, /* share_access */
3247 FILE_CREATE, /* create_disposition*/
3248 FILE_DIRECTORY_FILE, /* create_options */
3249 0, /* file_attributes */
3250 0, /* oplock_request */
3251 NULL, /* lease */
3252 0, /* allocation_size */
3253 0, /* private_flags */
3254 NULL, /* sd */
3255 NULL, /* ea_list */
3256 &fsp, /* result */
3257 &info, /* pinfo */
3258 posx, /* in_context_blobs */
3259 NULL); /* out_context_blobs */
3261 TALLOC_FREE(posx);
3263 if (NT_STATUS_IS_OK(status)) {
3264 close_file_free(req, &fsp, NORMAL_CLOSE);
3267 info_level_return = SVAL(pdata,16);
3269 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
3270 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
3271 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
3272 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
3273 } else {
3274 *pdata_return_size = 12;
3277 /* Realloc the data size */
3278 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
3279 if (*ppdata == NULL) {
3280 *pdata_return_size = 0;
3281 return NT_STATUS_NO_MEMORY;
3283 pdata = *ppdata;
3285 SSVAL(pdata,0,NO_OPLOCK_RETURN);
3286 SSVAL(pdata,2,0); /* No fnum. */
3287 SIVAL(pdata,4,info); /* Was directory created. */
3289 switch (info_level_return) {
3290 case SMB_QUERY_FILE_UNIX_BASIC:
3291 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
3292 SSVAL(pdata,10,0); /* Padding. */
3293 store_file_unix_basic(conn, pdata + 12, fsp,
3294 &smb_fname->st);
3295 break;
3296 case SMB_QUERY_FILE_UNIX_INFO2:
3297 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
3298 SSVAL(pdata,10,0); /* Padding. */
3299 store_file_unix_basic_info2(conn, pdata + 12, fsp,
3300 &smb_fname->st);
3301 break;
3302 default:
3303 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
3304 SSVAL(pdata,10,0); /* Padding. */
3305 break;
3308 return status;
3311 /****************************************************************************
3312 Open/Create a file with POSIX semantics.
3313 ****************************************************************************/
3315 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
3316 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
3318 static NTSTATUS smb_posix_open(connection_struct *conn,
3319 struct smb_request *req,
3320 char **ppdata,
3321 int total_data,
3322 struct files_struct *dirfsp,
3323 struct smb_filename *smb_fname,
3324 int *pdata_return_size)
3326 bool extended_oplock_granted = False;
3327 char *pdata = *ppdata;
3328 uint32_t flags = 0;
3329 uint32_t wire_open_mode = 0;
3330 uint32_t raw_unixmode = 0;
3331 uint32_t attributes = 0;
3332 uint32_t create_disp = 0;
3333 uint32_t access_mask = 0;
3334 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
3335 NTSTATUS status = NT_STATUS_OK;
3336 mode_t unixmode = (mode_t)0;
3337 files_struct *fsp = NULL;
3338 int oplock_request = 0;
3339 int info = 0;
3340 uint16_t info_level_return = 0;
3341 struct smb2_create_blobs *posx = NULL;
3343 if (total_data < 18) {
3344 return NT_STATUS_INVALID_PARAMETER;
3347 flags = IVAL(pdata,0);
3348 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
3349 if (oplock_request) {
3350 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
3353 wire_open_mode = IVAL(pdata,4);
3355 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
3356 return smb_posix_mkdir(conn, req,
3357 ppdata,
3358 total_data,
3359 smb_fname,
3360 pdata_return_size);
3363 switch (wire_open_mode & SMB_ACCMODE) {
3364 case SMB_O_RDONLY:
3365 access_mask = SMB_O_RDONLY_MAPPING;
3366 break;
3367 case SMB_O_WRONLY:
3368 access_mask = SMB_O_WRONLY_MAPPING;
3369 break;
3370 case SMB_O_RDWR:
3371 access_mask = (SMB_O_RDONLY_MAPPING|
3372 SMB_O_WRONLY_MAPPING);
3373 break;
3374 default:
3375 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
3376 (unsigned int)wire_open_mode ));
3377 return NT_STATUS_INVALID_PARAMETER;
3380 wire_open_mode &= ~SMB_ACCMODE;
3382 /* First take care of O_CREAT|O_EXCL interactions. */
3383 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
3384 case (SMB_O_CREAT | SMB_O_EXCL):
3385 /* File exists fail. File not exist create. */
3386 create_disp = FILE_CREATE;
3387 break;
3388 case SMB_O_CREAT:
3389 /* File exists open. File not exist create. */
3390 create_disp = FILE_OPEN_IF;
3391 break;
3392 case SMB_O_EXCL:
3393 /* O_EXCL on its own without O_CREAT is undefined.
3394 We deliberately ignore it as some versions of
3395 Linux CIFSFS can send a bare O_EXCL on the
3396 wire which other filesystems in the kernel
3397 ignore. See bug 9519 for details. */
3399 /* Fallthrough. */
3401 case 0:
3402 /* File exists open. File not exist fail. */
3403 create_disp = FILE_OPEN;
3404 break;
3405 default:
3406 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
3407 (unsigned int)wire_open_mode ));
3408 return NT_STATUS_INVALID_PARAMETER;
3411 /* Next factor in the effects of O_TRUNC. */
3412 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
3414 if (wire_open_mode & SMB_O_TRUNC) {
3415 switch (create_disp) {
3416 case FILE_CREATE:
3417 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
3418 /* Leave create_disp alone as
3419 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
3421 /* File exists fail. File not exist create. */
3422 break;
3423 case FILE_OPEN_IF:
3424 /* SMB_O_CREAT | SMB_O_TRUNC */
3425 /* File exists overwrite. File not exist create. */
3426 create_disp = FILE_OVERWRITE_IF;
3427 break;
3428 case FILE_OPEN:
3429 /* SMB_O_TRUNC */
3430 /* File exists overwrite. File not exist fail. */
3431 create_disp = FILE_OVERWRITE;
3432 break;
3433 default:
3434 /* Cannot get here. */
3435 smb_panic("smb_posix_open: logic error");
3436 return NT_STATUS_INVALID_PARAMETER;
3440 raw_unixmode = IVAL(pdata,8);
3441 /* Next 4 bytes are not yet defined. */
3443 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
3444 (VALID_STAT(smb_fname->st) ?
3445 PERM_EXISTING_FILE : PERM_NEW_FILE),
3446 &unixmode);
3448 if (!NT_STATUS_IS_OK(status)) {
3449 return status;
3452 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
3453 if (!NT_STATUS_IS_OK(status)) {
3454 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3455 nt_errstr(status));
3456 return status;
3459 if (wire_open_mode & SMB_O_SYNC) {
3460 create_options |= FILE_WRITE_THROUGH;
3462 if (wire_open_mode & SMB_O_APPEND) {
3463 access_mask |= FILE_APPEND_DATA;
3465 if (wire_open_mode & SMB_O_DIRECT) {
3466 attributes |= FILE_FLAG_NO_BUFFERING;
3469 if ((wire_open_mode & SMB_O_DIRECTORY) ||
3470 VALID_STAT_OF_DIR(smb_fname->st)) {
3471 if (access_mask != SMB_O_RDONLY_MAPPING) {
3472 return NT_STATUS_FILE_IS_A_DIRECTORY;
3474 create_options &= ~FILE_NON_DIRECTORY_FILE;
3475 create_options |= FILE_DIRECTORY_FILE;
3478 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
3479 smb_fname_str_dbg(smb_fname),
3480 (unsigned int)wire_open_mode,
3481 (unsigned int)unixmode ));
3483 status = SMB_VFS_CREATE_FILE(
3484 conn, /* conn */
3485 req, /* req */
3486 dirfsp, /* dirfsp */
3487 smb_fname, /* fname */
3488 access_mask, /* access_mask */
3489 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
3490 FILE_SHARE_DELETE),
3491 create_disp, /* create_disposition*/
3492 create_options, /* create_options */
3493 attributes, /* file_attributes */
3494 oplock_request, /* oplock_request */
3495 NULL, /* lease */
3496 0, /* allocation_size */
3497 0, /* private_flags */
3498 NULL, /* sd */
3499 NULL, /* ea_list */
3500 &fsp, /* result */
3501 &info, /* pinfo */
3502 posx, /* in_context_blobs */
3503 NULL); /* out_context_blobs */
3505 TALLOC_FREE(posx);
3507 if (!NT_STATUS_IS_OK(status)) {
3508 return status;
3511 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3512 extended_oplock_granted = True;
3515 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3516 extended_oplock_granted = True;
3519 info_level_return = SVAL(pdata,16);
3521 /* Allocate the correct return size. */
3523 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
3524 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
3525 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
3526 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
3527 } else {
3528 *pdata_return_size = 12;
3531 /* Realloc the data size */
3532 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
3533 if (*ppdata == NULL) {
3534 close_file_free(req, &fsp, ERROR_CLOSE);
3535 *pdata_return_size = 0;
3536 return NT_STATUS_NO_MEMORY;
3538 pdata = *ppdata;
3540 if (extended_oplock_granted) {
3541 if (flags & REQUEST_BATCH_OPLOCK) {
3542 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
3543 } else {
3544 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
3546 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
3547 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
3548 } else {
3549 SSVAL(pdata,0,NO_OPLOCK_RETURN);
3552 SSVAL(pdata,2,fsp->fnum);
3553 SIVAL(pdata,4,info); /* Was file created etc. */
3555 switch (info_level_return) {
3556 case SMB_QUERY_FILE_UNIX_BASIC:
3557 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
3558 SSVAL(pdata,10,0); /* padding. */
3559 store_file_unix_basic(conn, pdata + 12, fsp,
3560 &smb_fname->st);
3561 break;
3562 case SMB_QUERY_FILE_UNIX_INFO2:
3563 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
3564 SSVAL(pdata,10,0); /* padding. */
3565 store_file_unix_basic_info2(conn, pdata + 12, fsp,
3566 &smb_fname->st);
3567 break;
3568 default:
3569 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
3570 SSVAL(pdata,10,0); /* padding. */
3571 break;
3573 return NT_STATUS_OK;
3576 /****************************************************************************
3577 Delete a file with POSIX semantics.
3578 ****************************************************************************/
3580 struct smb_posix_unlink_state {
3581 struct smb_filename *smb_fname;
3582 struct files_struct *fsp;
3583 NTSTATUS status;
3586 static void smb_posix_unlink_locked(struct share_mode_lock *lck,
3587 void *private_data)
3589 struct smb_posix_unlink_state *state = private_data;
3590 char del = 1;
3591 bool other_nonposix_opens;
3593 other_nonposix_opens = has_other_nonposix_opens(lck, state->fsp);
3594 if (other_nonposix_opens) {
3595 /* Fail with sharing violation. */
3596 state->status = NT_STATUS_SHARING_VIOLATION;
3597 return;
3601 * Set the delete on close.
3603 state->status = smb_set_file_disposition_info(state->fsp->conn,
3604 &del,
3606 state->fsp,
3607 state->smb_fname);
3610 static NTSTATUS smb_posix_unlink(connection_struct *conn,
3611 struct smb_request *req,
3612 const char *pdata,
3613 int total_data,
3614 struct files_struct *dirfsp,
3615 struct smb_filename *smb_fname)
3617 struct smb_posix_unlink_state state = {};
3618 NTSTATUS status = NT_STATUS_OK;
3619 files_struct *fsp = NULL;
3620 uint16_t flags = 0;
3621 int info = 0;
3622 int create_options = 0;
3623 struct smb2_create_blobs *posx = NULL;
3625 if (!CAN_WRITE(conn)) {
3626 return NT_STATUS_DOS(ERRSRV, ERRaccess);
3629 if (total_data < 2) {
3630 return NT_STATUS_INVALID_PARAMETER;
3633 flags = SVAL(pdata,0);
3635 if (!VALID_STAT(smb_fname->st)) {
3636 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3639 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
3640 !VALID_STAT_OF_DIR(smb_fname->st)) {
3641 return NT_STATUS_NOT_A_DIRECTORY;
3644 DEBUG(10,("smb_posix_unlink: %s %s\n",
3645 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
3646 smb_fname_str_dbg(smb_fname)));
3648 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
3649 create_options |= FILE_DIRECTORY_FILE;
3652 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
3653 if (!NT_STATUS_IS_OK(status)) {
3654 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3655 nt_errstr(status));
3656 return status;
3659 status = SMB_VFS_CREATE_FILE(
3660 conn, /* conn */
3661 req, /* req */
3662 dirfsp, /* dirfsp */
3663 smb_fname, /* fname */
3664 DELETE_ACCESS, /* access_mask */
3665 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
3666 FILE_SHARE_DELETE),
3667 FILE_OPEN, /* create_disposition*/
3668 create_options, /* create_options */
3669 0, /* file_attributes */
3670 0, /* oplock_request */
3671 NULL, /* lease */
3672 0, /* allocation_size */
3673 0, /* private_flags */
3674 NULL, /* sd */
3675 NULL, /* ea_list */
3676 &fsp, /* result */
3677 &info, /* pinfo */
3678 posx, /* in_context_blobs */
3679 NULL); /* out_context_blobs */
3681 TALLOC_FREE(posx);
3683 if (!NT_STATUS_IS_OK(status)) {
3684 return status;
3688 * Don't lie to client. If we can't really delete due to
3689 * non-POSIX opens return SHARING_VIOLATION.
3692 state = (struct smb_posix_unlink_state) {
3693 .smb_fname = smb_fname,
3694 .fsp = fsp,
3697 status = share_mode_do_locked_vfs_allowed(fsp->file_id,
3698 smb_posix_unlink_locked,
3699 &state);
3700 if (!NT_STATUS_IS_OK(status)) {
3701 DBG_ERR("share_mode_do_locked_vfs_allowed(%s) failed - %s\n",
3702 fsp_str_dbg(fsp), nt_errstr(status));
3703 close_file_free(req, &fsp, NORMAL_CLOSE);
3704 return NT_STATUS_INVALID_PARAMETER;
3707 status = state.status;
3708 if (!NT_STATUS_IS_OK(status)) {
3709 close_file_free(req, &fsp, NORMAL_CLOSE);
3710 return status;
3712 return close_file_free(req, &fsp, NORMAL_CLOSE);
3715 /****************************************************************************
3716 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
3717 ****************************************************************************/
3719 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
3720 struct smb_request *req,
3721 const char *pdata,
3722 int total_data,
3723 struct smb_filename *new_smb_fname)
3725 char *link_target = NULL;
3726 struct smb_filename target_fname;
3727 TALLOC_CTX *ctx = talloc_tos();
3728 NTSTATUS status;
3729 int ret;
3730 struct smb_filename *parent_fname = NULL;
3731 struct smb_filename *base_name = NULL;
3733 if (!CAN_WRITE(conn)) {
3734 return NT_STATUS_DOS(ERRSRV, ERRaccess);
3737 /* Set a symbolic link. */
3738 /* Don't allow this if follow links is false. */
3740 if (total_data == 0) {
3741 return NT_STATUS_INVALID_PARAMETER;
3744 if (!lp_follow_symlinks(SNUM(conn))) {
3745 return NT_STATUS_ACCESS_DENIED;
3748 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
3749 total_data, STR_TERMINATE);
3751 if (!link_target) {
3752 return NT_STATUS_INVALID_PARAMETER;
3755 target_fname = (struct smb_filename) {
3756 .base_name = link_target,
3759 /* Removes @GMT tokens if any */
3760 status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
3761 if (!NT_STATUS_IS_OK(status)) {
3762 return status;
3765 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3766 new_smb_fname->base_name, link_target ));
3768 status = parent_pathref(talloc_tos(),
3769 conn->cwd_fsp,
3770 new_smb_fname,
3771 &parent_fname,
3772 &base_name);
3773 if (!NT_STATUS_IS_OK(status)) {
3774 return status;
3777 ret = SMB_VFS_SYMLINKAT(conn,
3778 &target_fname,
3779 parent_fname->fsp,
3780 base_name);
3781 if (ret != 0) {
3782 TALLOC_FREE(parent_fname);
3783 return map_nt_error_from_unix(errno);
3786 TALLOC_FREE(parent_fname);
3787 return NT_STATUS_OK;
3790 /****************************************************************************
3791 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
3792 ****************************************************************************/
3794 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
3795 struct smb_request *req,
3796 const char *pdata, int total_data,
3797 struct smb_filename *smb_fname_new)
3799 char *oldname = NULL;
3800 struct files_struct *src_dirfsp = NULL;
3801 struct smb_filename *smb_fname_old = NULL;
3802 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
3803 NTTIME old_twrp = 0;
3804 TALLOC_CTX *ctx = talloc_tos();
3805 NTSTATUS status = NT_STATUS_OK;
3807 if (!CAN_WRITE(conn)) {
3808 return NT_STATUS_DOS(ERRSRV, ERRaccess);
3811 /* Set a hard link. */
3812 if (total_data == 0) {
3813 return NT_STATUS_INVALID_PARAMETER;
3816 if (req->posix_pathnames) {
3817 srvstr_get_path_posix(ctx,
3818 pdata,
3819 req->flags2,
3820 &oldname,
3821 pdata,
3822 total_data,
3823 STR_TERMINATE,
3824 &status);
3825 } else {
3826 srvstr_get_path(ctx,
3827 pdata,
3828 req->flags2,
3829 &oldname,
3830 pdata,
3831 total_data,
3832 STR_TERMINATE,
3833 &status);
3835 if (!NT_STATUS_IS_OK(status)) {
3836 return status;
3839 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3840 smb_fname_str_dbg(smb_fname_new), oldname));
3842 if (ucf_flags & UCF_GMT_PATHNAME) {
3843 extract_snapshot_token(oldname, &old_twrp);
3845 status = smb1_strip_dfs_path(ctx, &ucf_flags, &oldname);
3846 if (!NT_STATUS_IS_OK(status)) {
3847 return status;
3849 status = filename_convert_dirfsp(ctx,
3850 conn,
3851 oldname,
3852 ucf_flags,
3853 old_twrp,
3854 &src_dirfsp,
3855 &smb_fname_old);
3856 if (!NT_STATUS_IS_OK(status)) {
3857 return status;
3860 return hardlink_internals(ctx,
3861 conn,
3862 req,
3863 false,
3864 NULL,
3865 smb_fname_old,
3866 NULL, /* new_dirfsp */
3867 smb_fname_new);
3870 /****************************************************************************
3871 Allow a UNIX info mknod.
3872 ****************************************************************************/
3874 static NTSTATUS smb_unix_mknod(connection_struct *conn,
3875 const char *pdata,
3876 int total_data,
3877 struct files_struct *dirfsp,
3878 const struct smb_filename *smb_fname)
3880 uint32_t file_type = IVAL(pdata,56);
3881 #if defined(HAVE_MAKEDEV)
3882 uint32_t dev_major = IVAL(pdata,60);
3883 uint32_t dev_minor = IVAL(pdata,68);
3884 #endif
3885 SMB_DEV_T dev = (SMB_DEV_T)0;
3886 uint32_t raw_unixmode = IVAL(pdata,84);
3887 NTSTATUS status;
3888 mode_t unixmode;
3889 int ret;
3890 struct smb_filename *parent_fname = NULL;
3891 struct smb_filename *atname = NULL;
3893 if (total_data < 100) {
3894 return NT_STATUS_INVALID_PARAMETER;
3897 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
3898 PERM_NEW_FILE, &unixmode);
3899 if (!NT_STATUS_IS_OK(status)) {
3900 return status;
3903 #if defined(HAVE_MAKEDEV)
3904 dev = makedev(dev_major, dev_minor);
3905 #endif
3907 switch (file_type) {
3908 /* We can't create other objects here. */
3909 case UNIX_TYPE_FILE:
3910 case UNIX_TYPE_DIR:
3911 case UNIX_TYPE_SYMLINK:
3912 return NT_STATUS_ACCESS_DENIED;
3913 #if defined(S_IFIFO)
3914 case UNIX_TYPE_FIFO:
3915 unixmode |= S_IFIFO;
3916 break;
3917 #endif
3918 #if defined(S_IFSOCK)
3919 case UNIX_TYPE_SOCKET:
3920 unixmode |= S_IFSOCK;
3921 break;
3922 #endif
3923 #if defined(S_IFCHR)
3924 case UNIX_TYPE_CHARDEV:
3925 /* This is only allowed for root. */
3926 if (get_current_uid(conn) != sec_initial_uid()) {
3927 return NT_STATUS_ACCESS_DENIED;
3929 unixmode |= S_IFCHR;
3930 break;
3931 #endif
3932 #if defined(S_IFBLK)
3933 case UNIX_TYPE_BLKDEV:
3934 if (get_current_uid(conn) != sec_initial_uid()) {
3935 return NT_STATUS_ACCESS_DENIED;
3937 unixmode |= S_IFBLK;
3938 break;
3939 #endif
3940 default:
3941 return NT_STATUS_INVALID_PARAMETER;
3944 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
3945 "%.0f mode 0%o for file %s\n", (double)dev,
3946 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
3948 status = SMB_VFS_PARENT_PATHNAME(dirfsp->conn,
3949 talloc_tos(),
3950 smb_fname,
3951 &parent_fname,
3952 &atname);
3953 if (!NT_STATUS_IS_OK(status)) {
3954 return status;
3957 /* Ok - do the mknod. */
3958 ret = SMB_VFS_MKNODAT(conn,
3959 dirfsp,
3960 atname,
3961 unixmode,
3962 dev);
3964 if (ret != 0) {
3965 TALLOC_FREE(parent_fname);
3966 return map_nt_error_from_unix(errno);
3969 /* If any of the other "set" calls fail we
3970 * don't want to end up with a half-constructed mknod.
3973 if (lp_inherit_permissions(SNUM(conn))) {
3974 inherit_access_posix_acl(conn,
3975 dirfsp,
3976 smb_fname,
3977 unixmode);
3979 TALLOC_FREE(parent_fname);
3981 return NT_STATUS_OK;
3984 /****************************************************************************
3985 Deal with SMB_SET_FILE_UNIX_BASIC.
3986 ****************************************************************************/
3988 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
3989 struct smb_request *req,
3990 const char *pdata,
3991 int total_data,
3992 struct files_struct *dirfsp,
3993 files_struct *fsp,
3994 struct smb_filename *smb_fname)
3996 struct smb_file_time ft;
3997 uint32_t raw_unixmode;
3998 mode_t unixmode;
3999 off_t size = 0;
4000 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
4001 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
4002 NTSTATUS status = NT_STATUS_OK;
4003 enum perm_type ptype;
4004 files_struct *all_fsps = NULL;
4005 bool modify_mtime = true;
4006 struct file_id id;
4007 SMB_STRUCT_STAT sbuf;
4009 if (!CAN_WRITE(conn)) {
4010 return NT_STATUS_DOS(ERRSRV, ERRaccess);
4013 init_smb_file_time(&ft);
4015 if (total_data < 100) {
4016 return NT_STATUS_INVALID_PARAMETER;
4019 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4020 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4021 size=IVAL(pdata,0); /* first 8 Bytes are size */
4022 size |= (((off_t)IVAL(pdata,4)) << 32);
4025 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
4026 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
4027 set_owner = (uid_t)IVAL(pdata,40);
4028 set_grp = (gid_t)IVAL(pdata,48);
4029 raw_unixmode = IVAL(pdata,84);
4031 if (VALID_STAT(smb_fname->st)) {
4032 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
4033 ptype = PERM_EXISTING_DIR;
4034 } else {
4035 ptype = PERM_EXISTING_FILE;
4037 } else {
4038 ptype = PERM_NEW_FILE;
4041 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
4042 ptype, &unixmode);
4043 if (!NT_STATUS_IS_OK(status)) {
4044 return status;
4047 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
4048 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4049 smb_fname_str_dbg(smb_fname), (double)size,
4050 (unsigned int)set_owner, (unsigned int)set_grp,
4051 (int)raw_unixmode));
4053 sbuf = smb_fname->st;
4055 if (!VALID_STAT(sbuf)) {
4057 * The only valid use of this is to create character and block
4058 * devices, and named pipes. This is deprecated (IMHO) and
4059 * a new info level should be used for mknod. JRA.
4062 if (dirfsp == NULL) {
4063 return NT_STATUS_INVALID_PARAMETER;
4066 return smb_unix_mknod(conn,
4067 pdata,
4068 total_data,
4069 dirfsp,
4070 smb_fname);
4073 #if 1
4074 /* Horrible backwards compatibility hack as an old server bug
4075 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
4076 * */
4078 if (!size) {
4079 size = get_file_size_stat(&sbuf);
4081 #endif
4084 * Deal with the UNIX specific mode set.
4087 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4088 int ret;
4090 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
4091 DBG_WARNING("Can't set mode on symlink %s\n",
4092 smb_fname_str_dbg(smb_fname));
4093 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4096 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4097 "setting mode 0%o for file %s\n",
4098 (unsigned int)unixmode,
4099 smb_fname_str_dbg(smb_fname)));
4100 ret = SMB_VFS_FCHMOD(fsp, unixmode);
4101 if (ret != 0) {
4102 return map_nt_error_from_unix(errno);
4107 * Deal with the UNIX specific uid set.
4110 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
4111 (sbuf.st_ex_uid != set_owner)) {
4112 int ret;
4114 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4115 "changing owner %u for path %s\n",
4116 (unsigned int)set_owner,
4117 smb_fname_str_dbg(smb_fname)));
4119 if (fsp &&
4120 !fsp->fsp_flags.is_pathref &&
4121 fsp_get_io_fd(fsp) != -1)
4123 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
4124 } else {
4126 * UNIX extensions calls must always operate
4127 * on symlinks.
4129 ret = SMB_VFS_LCHOWN(conn, smb_fname,
4130 set_owner, (gid_t)-1);
4133 if (ret != 0) {
4134 status = map_nt_error_from_unix(errno);
4135 return status;
4140 * Deal with the UNIX specific gid set.
4143 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
4144 (sbuf.st_ex_gid != set_grp)) {
4145 int ret;
4147 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4148 "changing group %u for file %s\n",
4149 (unsigned int)set_grp,
4150 smb_fname_str_dbg(smb_fname)));
4151 if (fsp &&
4152 !fsp->fsp_flags.is_pathref &&
4153 fsp_get_io_fd(fsp) != -1)
4155 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
4156 } else {
4158 * UNIX extensions calls must always operate
4159 * on symlinks.
4161 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
4162 set_grp);
4164 if (ret != 0) {
4165 status = map_nt_error_from_unix(errno);
4166 return status;
4170 /* Deal with any size changes. */
4172 if (S_ISREG(sbuf.st_ex_mode)) {
4173 status = smb_set_file_size(conn, req,
4174 fsp,
4175 smb_fname,
4176 &sbuf,
4177 size,
4178 false);
4179 if (!NT_STATUS_IS_OK(status)) {
4180 return status;
4184 /* Deal with any time changes. */
4185 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
4186 /* No change, don't cancel anything. */
4187 return status;
4190 id = vfs_file_id_from_sbuf(conn, &sbuf);
4191 for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
4192 all_fsps = file_find_di_next(all_fsps, true)) {
4194 * We're setting the time explicitly for UNIX.
4195 * Cancel any pending changes over all handles.
4197 all_fsps->fsp_flags.update_write_time_on_close = false;
4198 TALLOC_FREE(all_fsps->update_write_time_event);
4202 * Override the "setting_write_time"
4203 * parameter here as it almost does what
4204 * we need. Just remember if we modified
4205 * mtime and send the notify ourselves.
4207 if (is_omit_timespec(&ft.mtime)) {
4208 modify_mtime = false;
4211 status = smb_set_file_time(conn,
4212 fsp,
4213 smb_fname,
4214 &ft,
4215 false);
4216 if (modify_mtime) {
4217 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4218 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
4220 return status;
4223 /****************************************************************************
4224 Deal with SMB_SET_FILE_UNIX_INFO2.
4225 ****************************************************************************/
4227 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
4228 struct smb_request *req,
4229 const char *pdata,
4230 int total_data,
4231 struct files_struct *dirfsp,
4232 files_struct *fsp,
4233 struct smb_filename *smb_fname)
4235 NTSTATUS status;
4236 uint32_t smb_fflags;
4237 uint32_t smb_fmask;
4239 if (!CAN_WRITE(conn)) {
4240 return NT_STATUS_DOS(ERRSRV, ERRaccess);
4243 if (total_data < 116) {
4244 return NT_STATUS_INVALID_PARAMETER;
4247 /* Start by setting all the fields that are common between UNIX_BASIC
4248 * and UNIX_INFO2.
4250 status = smb_set_file_unix_basic(conn,
4251 req,
4252 pdata,
4253 total_data,
4254 dirfsp,
4255 fsp,
4256 smb_fname);
4257 if (!NT_STATUS_IS_OK(status)) {
4258 return status;
4261 smb_fflags = IVAL(pdata, 108);
4262 smb_fmask = IVAL(pdata, 112);
4264 /* NB: We should only attempt to alter the file flags if the client
4265 * sends a non-zero mask.
4267 if (smb_fmask != 0) {
4268 int stat_fflags = 0;
4270 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
4271 smb_fmask, &stat_fflags)) {
4272 /* Client asked to alter a flag we don't understand. */
4273 return NT_STATUS_INVALID_PARAMETER;
4276 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
4277 DBG_WARNING("Can't change flags on symlink %s\n",
4278 smb_fname_str_dbg(smb_fname));
4279 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4281 if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) {
4282 return map_nt_error_from_unix(errno);
4286 /* XXX: need to add support for changing the create_time here. You
4287 * can do this for paths on Darwin with setattrlist(2). The right way
4288 * to hook this up is probably by extending the VFS utimes interface.
4291 return NT_STATUS_OK;
4294 /****************************************************************************
4295 Deal with SMB_SET_POSIX_ACL.
4296 ****************************************************************************/
4298 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4299 struct smb_request *req,
4300 const char *pdata,
4301 int total_data_in,
4302 files_struct *fsp,
4303 struct smb_filename *smb_fname)
4305 #if !defined(HAVE_POSIX_ACLS)
4306 return NT_STATUS_INVALID_LEVEL;
4307 #else
4308 uint16_t posix_acl_version;
4309 uint16_t num_file_acls;
4310 uint16_t num_def_acls;
4311 bool valid_file_acls = true;
4312 bool valid_def_acls = true;
4313 NTSTATUS status;
4314 unsigned int size_needed;
4315 unsigned int total_data;
4316 bool close_fsp = false;
4318 if (total_data_in < 0) {
4319 status = NT_STATUS_INVALID_PARAMETER;
4320 goto out;
4323 total_data = total_data_in;
4325 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4326 status = NT_STATUS_INVALID_PARAMETER;
4327 goto out;
4329 posix_acl_version = SVAL(pdata,0);
4330 num_file_acls = SVAL(pdata,2);
4331 num_def_acls = SVAL(pdata,4);
4333 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4334 valid_file_acls = false;
4335 num_file_acls = 0;
4338 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4339 valid_def_acls = false;
4340 num_def_acls = 0;
4343 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4344 status = NT_STATUS_INVALID_PARAMETER;
4345 goto out;
4348 /* Wrap checks. */
4349 if (num_file_acls + num_def_acls < num_file_acls) {
4350 status = NT_STATUS_INVALID_PARAMETER;
4351 goto out;
4354 size_needed = num_file_acls + num_def_acls;
4357 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4358 * than UINT_MAX, so check by division.
4360 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
4361 status = NT_STATUS_INVALID_PARAMETER;
4362 goto out;
4365 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
4366 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
4367 status = NT_STATUS_INVALID_PARAMETER;
4368 goto out;
4370 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
4372 if (total_data < size_needed) {
4373 status = NT_STATUS_INVALID_PARAMETER;
4374 goto out;
4378 * Ensure we always operate on a file descriptor, not just
4379 * the filename.
4381 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
4382 uint32_t access_mask = SEC_STD_WRITE_OWNER|
4383 SEC_STD_WRITE_DAC|
4384 SEC_STD_READ_CONTROL|
4385 FILE_READ_ATTRIBUTES|
4386 FILE_WRITE_ATTRIBUTES;
4388 status = get_posix_fsp(conn,
4389 req,
4390 smb_fname,
4391 access_mask,
4392 &fsp);
4394 if (!NT_STATUS_IS_OK(status)) {
4395 goto out;
4397 close_fsp = true;
4400 /* Here we know fsp != NULL */
4401 SMB_ASSERT(fsp != NULL);
4403 status = refuse_symlink_fsp(fsp);
4404 if (!NT_STATUS_IS_OK(status)) {
4405 goto out;
4408 /* If we have a default acl, this *must* be a directory. */
4409 if (valid_def_acls && !fsp->fsp_flags.is_directory) {
4410 DBG_INFO("Can't set default acls on "
4411 "non-directory %s\n",
4412 fsp_str_dbg(fsp));
4413 return NT_STATUS_INVALID_HANDLE;
4416 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
4417 "num_def_acls = %"PRIu16"\n",
4418 fsp_str_dbg(fsp),
4419 num_file_acls,
4420 num_def_acls);
4422 /* Move pdata to the start of the file ACL entries. */
4423 pdata += SMB_POSIX_ACL_HEADER_SIZE;
4425 if (valid_file_acls) {
4426 status = set_unix_posix_acl(conn,
4427 fsp,
4428 num_file_acls,
4429 pdata);
4430 if (!NT_STATUS_IS_OK(status)) {
4431 goto out;
4435 /* Move pdata to the start of the default ACL entries. */
4436 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
4438 if (valid_def_acls) {
4439 status = set_unix_posix_default_acl(conn,
4440 fsp,
4441 num_def_acls,
4442 pdata);
4443 if (!NT_STATUS_IS_OK(status)) {
4444 goto out;
4448 status = NT_STATUS_OK;
4450 out:
4452 if (close_fsp) {
4453 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
4455 return status;
4456 #endif
4459 static void call_trans2setpathinfo(
4460 connection_struct *conn,
4461 struct smb_request *req,
4462 char **pparams,
4463 int total_params,
4464 char **ppdata,
4465 int total_data,
4466 unsigned int max_data_bytes)
4468 uint16_t info_level;
4469 struct smb_filename *smb_fname = NULL;
4470 struct files_struct *dirfsp = NULL;
4471 struct files_struct *fsp = NULL;
4472 char *params = *pparams;
4473 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4474 NTTIME twrp = 0;
4475 char *fname = NULL;
4476 bool info_level_handled;
4477 int data_return_size = 0;
4478 NTSTATUS status;
4480 if (params == NULL) {
4481 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4482 return;
4485 /* set path info */
4486 if (total_params < 7) {
4487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4488 return;
4491 info_level = SVAL(params,0);
4493 if (INFO_LEVEL_IS_UNIX(info_level)) {
4494 if (!lp_smb1_unix_extensions()) {
4495 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4496 return;
4498 if (!req->posix_pathnames) {
4499 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4500 return;
4504 if (req->posix_pathnames) {
4505 srvstr_get_path_posix(req,
4506 params,
4507 req->flags2,
4508 &fname,
4509 &params[6],
4510 total_params - 6,
4511 STR_TERMINATE,
4512 &status);
4513 } else {
4514 srvstr_get_path(req,
4515 params,
4516 req->flags2,
4517 &fname,
4518 &params[6],
4519 total_params - 6,
4520 STR_TERMINATE,
4521 &status);
4523 if (!NT_STATUS_IS_OK(status)) {
4524 reply_nterror(req, status);
4525 return;
4528 DBG_NOTICE("fname=%s info_level=%d totdata=%d\n",
4529 fname,
4530 info_level,
4531 total_data);
4533 if (ucf_flags & UCF_GMT_PATHNAME) {
4534 extract_snapshot_token(fname, &twrp);
4536 status = smb1_strip_dfs_path(req, &ucf_flags, &fname);
4537 if (!NT_STATUS_IS_OK(status)) {
4538 reply_nterror(req, status);
4539 return;
4541 status = filename_convert_dirfsp(req,
4542 conn,
4543 fname,
4544 ucf_flags,
4545 twrp,
4546 &dirfsp,
4547 &smb_fname);
4548 if (!NT_STATUS_IS_OK(status)) {
4549 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4550 reply_botherror(req,
4551 NT_STATUS_PATH_NOT_COVERED,
4552 ERRSRV, ERRbadpath);
4553 return;
4555 reply_nterror(req, status);
4556 return;
4559 info_level_handled = true; /* Untouched in switch cases below */
4561 switch (info_level) {
4563 default:
4564 info_level_handled = false;
4565 break;
4567 case SMB_POSIX_PATH_OPEN:
4568 status = smb_posix_open(conn,
4569 req,
4570 ppdata,
4571 total_data,
4572 dirfsp,
4573 smb_fname,
4574 &data_return_size);
4575 break;
4577 case SMB_POSIX_PATH_UNLINK:
4578 status = smb_posix_unlink(conn,
4579 req,
4580 *ppdata,
4581 total_data,
4582 dirfsp,
4583 smb_fname);
4584 break;
4586 case SMB_SET_FILE_UNIX_LINK:
4587 status = smb_set_file_unix_link(
4588 conn, req, *ppdata, total_data, smb_fname);
4589 break;
4591 case SMB_SET_FILE_UNIX_HLINK:
4592 status = smb_set_file_unix_hlink(
4593 conn, req, *ppdata, total_data, smb_fname);
4594 break;
4596 case SMB_SET_FILE_UNIX_BASIC:
4597 status = smb_set_file_unix_basic(conn,
4598 req,
4599 *ppdata,
4600 total_data,
4601 dirfsp,
4602 smb_fname->fsp,
4603 smb_fname);
4604 break;
4606 case SMB_SET_FILE_UNIX_INFO2:
4607 status = smb_set_file_unix_info2(conn,
4608 req,
4609 *ppdata,
4610 total_data,
4611 dirfsp,
4612 smb_fname->fsp,
4613 smb_fname);
4614 break;
4615 case SMB_SET_POSIX_ACL:
4616 status = smb_set_posix_acl(
4617 conn, req, *ppdata, total_data, NULL, smb_fname);
4618 break;
4621 if (info_level_handled) {
4622 handle_trans2setfilepathinfo_result(
4623 conn,
4624 req,
4625 info_level,
4626 status,
4627 *ppdata,
4628 data_return_size,
4629 max_data_bytes);
4630 return;
4634 * smb_fname->fsp may be NULL if smb_fname points at a symlink
4635 * and we're in POSIX context, so be careful when using fsp
4636 * below, it can still be NULL.
4638 fsp = smb_fname->fsp;
4640 status = smbd_do_setfilepathinfo(
4641 conn,
4642 req,
4643 req,
4644 info_level,
4645 fsp,
4646 smb_fname,
4647 ppdata,
4648 total_data,
4649 &data_return_size);
4651 handle_trans2setfilepathinfo_result(
4652 conn,
4653 req,
4654 info_level,
4655 status,
4656 *ppdata,
4657 data_return_size,
4658 max_data_bytes);
4661 static void call_trans2setfileinfo(
4662 connection_struct *conn,
4663 struct smb_request *req,
4664 char **pparams,
4665 int total_params,
4666 char **ppdata,
4667 int total_data,
4668 unsigned int max_data_bytes)
4670 char *pdata = *ppdata;
4671 uint16_t info_level;
4672 struct smb_filename *smb_fname = NULL;
4673 struct files_struct *fsp = NULL;
4674 char *params = *pparams;
4675 int data_return_size = 0;
4676 bool info_level_handled;
4677 NTSTATUS status;
4678 int ret;
4680 if (params == NULL) {
4681 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4682 return;
4684 if (total_params < 4) {
4685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4686 return;
4689 fsp = file_fsp(req, SVAL(params,0));
4690 /* Basic check for non-null fsp. */
4691 if (!check_fsp_open(conn, req, fsp)) {
4692 return;
4694 info_level = SVAL(params,2);
4696 if (INFO_LEVEL_IS_UNIX(info_level)) {
4697 if (!lp_smb1_unix_extensions()) {
4698 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4699 return;
4701 if (!req->posix_pathnames) {
4702 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4703 return;
4707 smb_fname = fsp->fsp_name;
4709 DBG_NOTICE("fnum=%s fname=%s info_level=%d totdata=%d\n",
4710 fsp_fnum_dbg(fsp),
4711 fsp_str_dbg(fsp),
4712 info_level,
4713 total_data);
4715 if (fsp_get_pathref_fd(fsp) == -1) {
4717 * This is actually a SETFILEINFO on a directory
4718 * handle (returned from an NT SMB). NT5.0 seems
4719 * to do this call. JRA.
4721 ret = vfs_stat(conn, smb_fname);
4722 if (ret != 0) {
4723 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
4724 smb_fname_str_dbg(smb_fname),
4725 strerror(errno));
4726 reply_nterror(req, map_nt_error_from_unix(errno));
4727 return;
4729 } else if (fsp->print_file) {
4731 * Doing a DELETE_ON_CLOSE should cancel a print job.
4733 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) &&
4734 CVAL(pdata,0)) {
4736 fsp->fsp_flags.delete_on_close = true;
4738 DBG_NOTICE("Cancelling print job (%s)\n",
4739 fsp_str_dbg(fsp));
4741 SSVAL(params,0,0);
4742 send_trans2_replies(
4743 conn,
4744 req,
4745 NT_STATUS_OK,
4746 params,
4748 *ppdata, 0,
4749 max_data_bytes);
4750 return;
4751 } else {
4752 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
4753 return;
4755 } else {
4757 * Original code - this is an open file.
4759 status = vfs_stat_fsp(fsp);
4760 if (!NT_STATUS_IS_OK(status)) {
4761 DBG_NOTICE("fstat of %s failed (%s)\n",
4762 fsp_fnum_dbg(fsp),
4763 nt_errstr(status));
4764 reply_nterror(req, status);
4765 return;
4769 info_level_handled = true; /* Untouched in switch cases below */
4771 switch (info_level) {
4773 default:
4774 info_level_handled = false;
4775 break;
4777 case SMB_SET_FILE_UNIX_BASIC:
4778 status = smb_set_file_unix_basic(conn,
4779 req,
4780 pdata,
4781 total_data,
4782 NULL,
4783 fsp,
4784 smb_fname);
4785 break;
4787 case SMB_SET_FILE_UNIX_INFO2:
4788 status = smb_set_file_unix_info2(conn,
4789 req,
4790 pdata,
4791 total_data,
4792 NULL,
4793 fsp,
4794 smb_fname);
4795 break;
4797 case SMB_SET_POSIX_LOCK:
4798 status = smb_set_posix_lock(
4799 conn, req, *ppdata, total_data, fsp);
4800 break;
4803 if (info_level_handled) {
4804 handle_trans2setfilepathinfo_result(
4805 conn,
4806 req,
4807 info_level,
4808 status,
4809 *ppdata,
4810 data_return_size,
4811 max_data_bytes);
4812 return;
4815 status = smbd_do_setfilepathinfo(
4816 conn,
4817 req,
4818 req,
4819 info_level,
4820 fsp,
4821 smb_fname,
4822 ppdata,
4823 total_data,
4824 &data_return_size);
4826 handle_trans2setfilepathinfo_result(
4827 conn,
4828 req,
4829 info_level,
4830 status,
4831 *ppdata,
4832 data_return_size,
4833 max_data_bytes);
4836 /****************************************************************************
4837 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4838 ****************************************************************************/
4840 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
4841 char **pparams, int total_params,
4842 char **ppdata, int total_data,
4843 unsigned int max_data_bytes)
4845 struct files_struct *dirfsp = NULL;
4846 struct files_struct *fsp = NULL;
4847 struct smb_filename *smb_dname = NULL;
4848 char *params = *pparams;
4849 char *pdata = *ppdata;
4850 char *directory = NULL;
4851 NTSTATUS status = NT_STATUS_OK;
4852 struct ea_list *ea_list = NULL;
4853 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4854 NTTIME twrp = 0;
4855 TALLOC_CTX *ctx = talloc_tos();
4857 if (!CAN_WRITE(conn)) {
4858 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4859 return;
4862 if (total_params < 5) {
4863 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4864 return;
4867 if (req->posix_pathnames) {
4868 srvstr_get_path_posix(ctx,
4869 params,
4870 req->flags2,
4871 &directory,
4872 &params[4],
4873 total_params - 4,
4874 STR_TERMINATE,
4875 &status);
4876 } else {
4877 srvstr_get_path(ctx,
4878 params,
4879 req->flags2,
4880 &directory,
4881 &params[4],
4882 total_params - 4,
4883 STR_TERMINATE,
4884 &status);
4886 if (!NT_STATUS_IS_OK(status)) {
4887 reply_nterror(req, status);
4888 return;
4891 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4893 if (ucf_flags & UCF_GMT_PATHNAME) {
4894 extract_snapshot_token(directory, &twrp);
4896 status = smb1_strip_dfs_path(ctx, &ucf_flags, &directory);
4897 if (!NT_STATUS_IS_OK(status)) {
4898 reply_nterror(req, status);
4899 goto out;
4901 status = filename_convert_dirfsp(ctx,
4902 conn,
4903 directory,
4904 ucf_flags,
4905 twrp,
4906 &dirfsp,
4907 &smb_dname);
4908 if (!NT_STATUS_IS_OK(status)) {
4909 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4910 reply_botherror(req,
4911 NT_STATUS_PATH_NOT_COVERED,
4912 ERRSRV, ERRbadpath);
4913 return;
4915 reply_nterror(req, status);
4916 return;
4920 * OS/2 workplace shell seems to send SET_EA requests of "null"
4921 * length (4 bytes containing IVAL 4).
4922 * They seem to have no effect. Bug #3212. JRA.
4925 if (total_data && (total_data != 4)) {
4926 /* Any data in this call is an EA list. */
4927 if (total_data < 10) {
4928 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4929 goto out;
4932 if (IVAL(pdata,0) > total_data) {
4933 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4934 IVAL(pdata,0), (unsigned int)total_data));
4935 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4936 goto out;
4939 ea_list = read_ea_list(talloc_tos(), pdata + 4,
4940 total_data - 4);
4941 if (!ea_list) {
4942 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4943 goto out;
4946 if (!lp_ea_support(SNUM(conn))) {
4947 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
4948 goto out;
4951 /* If total_data == 4 Windows doesn't care what values
4952 * are placed in that field, it just ignores them.
4953 * The System i QNTC IBM SMB client puts bad values here,
4954 * so ignore them. */
4956 status = SMB_VFS_CREATE_FILE(
4957 conn, /* conn */
4958 req, /* req */
4959 dirfsp, /* dirfsp */
4960 smb_dname, /* fname */
4961 MAXIMUM_ALLOWED_ACCESS, /* access_mask */
4962 FILE_SHARE_NONE, /* share_access */
4963 FILE_CREATE, /* create_disposition*/
4964 FILE_DIRECTORY_FILE, /* create_options */
4965 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
4966 0, /* oplock_request */
4967 NULL, /* lease */
4968 0, /* allocation_size */
4969 0, /* private_flags */
4970 NULL, /* sd */
4971 NULL, /* ea_list */
4972 &fsp, /* result */
4973 NULL, /* pinfo */
4974 NULL, NULL); /* create context */
4975 if (!NT_STATUS_IS_OK(status)) {
4976 reply_nterror(req, status);
4977 goto out;
4980 /* Try and set any given EA. */
4981 if (ea_list) {
4982 status = set_ea(conn, fsp, ea_list);
4983 if (!NT_STATUS_IS_OK(status)) {
4984 reply_nterror(req, status);
4985 goto out;
4989 /* Realloc the parameter and data sizes */
4990 *pparams = (char *)SMB_REALLOC(*pparams,2);
4991 if(*pparams == NULL) {
4992 reply_nterror(req, NT_STATUS_NO_MEMORY);
4993 goto out;
4995 params = *pparams;
4997 SSVAL(params,0,0);
4999 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
5001 out:
5002 if (fsp != NULL) {
5003 close_file_free(NULL, &fsp, NORMAL_CLOSE);
5005 TALLOC_FREE(smb_dname);
5006 return;
5009 /****************************************************************************
5010 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
5011 We don't actually do this - we just send a null response.
5012 ****************************************************************************/
5014 static void call_trans2findnotifyfirst(connection_struct *conn,
5015 struct smb_request *req,
5016 char **pparams, int total_params,
5017 char **ppdata, int total_data,
5018 unsigned int max_data_bytes)
5020 char *params = *pparams;
5021 uint16_t info_level;
5023 if (total_params < 6) {
5024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5025 return;
5028 info_level = SVAL(params,4);
5029 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
5031 switch (info_level) {
5032 case 1:
5033 case 2:
5034 break;
5035 default:
5036 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5037 return;
5040 /* Realloc the parameter and data sizes */
5041 *pparams = (char *)SMB_REALLOC(*pparams,6);
5042 if (*pparams == NULL) {
5043 reply_nterror(req, NT_STATUS_NO_MEMORY);
5044 return;
5046 params = *pparams;
5048 SSVAL(params,0,fnf_handle);
5049 SSVAL(params,2,0); /* No changes */
5050 SSVAL(params,4,0); /* No EA errors */
5052 fnf_handle++;
5054 if(fnf_handle == 0)
5055 fnf_handle = 257;
5057 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
5059 return;
5062 /****************************************************************************
5063 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
5064 changes). Currently this does nothing.
5065 ****************************************************************************/
5067 static void call_trans2findnotifynext(connection_struct *conn,
5068 struct smb_request *req,
5069 char **pparams, int total_params,
5070 char **ppdata, int total_data,
5071 unsigned int max_data_bytes)
5073 char *params = *pparams;
5075 DEBUG(3,("call_trans2findnotifynext\n"));
5077 /* Realloc the parameter and data sizes */
5078 *pparams = (char *)SMB_REALLOC(*pparams,4);
5079 if (*pparams == NULL) {
5080 reply_nterror(req, NT_STATUS_NO_MEMORY);
5081 return;
5083 params = *pparams;
5085 SSVAL(params,0,0); /* No changes */
5086 SSVAL(params,2,0); /* No EA errors */
5088 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
5090 return;
5093 /****************************************************************************
5094 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5095 ****************************************************************************/
5097 static void call_trans2getdfsreferral(connection_struct *conn,
5098 struct smb_request *req,
5099 char **pparams, int total_params,
5100 char **ppdata, int total_data,
5101 unsigned int max_data_bytes)
5103 char *params = *pparams;
5104 char *pathname = NULL;
5105 int reply_size = 0;
5106 int max_referral_level;
5107 NTSTATUS status = NT_STATUS_OK;
5108 TALLOC_CTX *ctx = talloc_tos();
5110 DEBUG(10,("call_trans2getdfsreferral\n"));
5112 if (!IS_IPC(conn)) {
5113 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5114 return;
5117 if (total_params < 3) {
5118 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5119 return;
5122 max_referral_level = SVAL(params,0);
5124 if(!lp_host_msdfs()) {
5125 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5126 return;
5129 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
5130 total_params - 2, STR_TERMINATE);
5131 if (!pathname) {
5132 reply_nterror(req, NT_STATUS_NOT_FOUND);
5133 return;
5135 reply_size = setup_dfs_referral(
5136 conn, pathname, max_referral_level, ppdata, &status);
5137 if (reply_size < 0) {
5138 reply_nterror(req, status);
5139 return;
5142 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
5143 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
5144 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
5146 return;
5149 #define LMCAT_SPL 0x53
5150 #define LMFUNC_GETJOBID 0x60
5152 /****************************************************************************
5153 Reply to a TRANS2_IOCTL - used for OS/2 printing.
5154 ****************************************************************************/
5156 static void call_trans2ioctl(connection_struct *conn,
5157 struct smb_request *req,
5158 char **pparams, int total_params,
5159 char **ppdata, int total_data,
5160 unsigned int max_data_bytes)
5162 const struct loadparm_substitution *lp_sub =
5163 loadparm_s3_global_substitution();
5164 char *pdata = *ppdata;
5165 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
5166 NTSTATUS status;
5167 size_t len = 0;
5169 /* check for an invalid fid before proceeding */
5171 if (!fsp) {
5172 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5173 return;
5176 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
5177 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
5178 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
5179 if (*ppdata == NULL) {
5180 reply_nterror(req, NT_STATUS_NO_MEMORY);
5181 return;
5183 pdata = *ppdata;
5185 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5186 CAN ACCEPT THIS IN UNICODE. JRA. */
5188 /* Job number */
5189 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
5191 status = srvstr_push(pdata, req->flags2, pdata + 2,
5192 lp_netbios_name(), 15,
5193 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
5194 if (!NT_STATUS_IS_OK(status)) {
5195 reply_nterror(req, status);
5196 return;
5198 status = srvstr_push(pdata, req->flags2, pdata+18,
5199 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
5200 STR_ASCII|STR_TERMINATE, &len); /* Service name */
5201 if (!NT_STATUS_IS_OK(status)) {
5202 reply_nterror(req, status);
5203 return;
5205 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
5206 max_data_bytes);
5207 return;
5210 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5211 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5214 static void handle_trans2(connection_struct *conn, struct smb_request *req,
5215 struct trans_state *state)
5217 struct smbXsrv_connection *xconn = req->xconn;
5219 if (xconn->protocol >= PROTOCOL_NT1) {
5220 req->flags2 |= 0x40; /* IS_LONG_NAME */
5221 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
5224 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
5225 if (state->call != TRANSACT2_QFSINFO &&
5226 state->call != TRANSACT2_SETFSINFO) {
5227 DEBUG(0,("handle_trans2: encryption required "
5228 "with call 0x%x\n",
5229 (unsigned int)state->call));
5230 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5231 return;
5235 /* Now we must call the relevant TRANS2 function */
5236 switch(state->call) {
5237 case TRANSACT2_OPEN:
5239 START_PROFILE(Trans2_open);
5240 call_trans2open(conn, req,
5241 &state->param, state->total_param,
5242 &state->data, state->total_data,
5243 state->max_data_return);
5244 END_PROFILE(Trans2_open);
5245 break;
5248 case TRANSACT2_FINDFIRST:
5250 START_PROFILE(Trans2_findfirst);
5251 call_trans2findfirst(conn, req,
5252 &state->param, state->total_param,
5253 &state->data, state->total_data,
5254 state->max_data_return);
5255 END_PROFILE(Trans2_findfirst);
5256 break;
5259 case TRANSACT2_FINDNEXT:
5261 START_PROFILE(Trans2_findnext);
5262 call_trans2findnext(conn, req,
5263 &state->param, state->total_param,
5264 &state->data, state->total_data,
5265 state->max_data_return);
5266 END_PROFILE(Trans2_findnext);
5267 break;
5270 case TRANSACT2_QFSINFO:
5272 START_PROFILE(Trans2_qfsinfo);
5273 call_trans2qfsinfo(conn, req,
5274 &state->param, state->total_param,
5275 &state->data, state->total_data,
5276 state->max_data_return);
5277 END_PROFILE(Trans2_qfsinfo);
5278 break;
5281 case TRANSACT2_SETFSINFO:
5283 START_PROFILE(Trans2_setfsinfo);
5284 call_trans2setfsinfo(conn, req,
5285 &state->param, state->total_param,
5286 &state->data, state->total_data,
5287 state->max_data_return);
5288 END_PROFILE(Trans2_setfsinfo);
5289 break;
5292 case TRANSACT2_QPATHINFO:
5294 START_PROFILE(Trans2_qpathinfo);
5295 call_trans2qpathinfo(
5296 conn,
5297 req,
5298 &state->param,
5299 state->total_param,
5300 &state->data,
5301 state->total_data,
5302 state->max_data_return);
5303 END_PROFILE(Trans2_qpathinfo);
5304 break;
5307 case TRANSACT2_QFILEINFO:
5309 START_PROFILE(Trans2_qfileinfo);
5310 call_trans2qfileinfo(
5311 conn,
5312 req,
5313 &state->param,
5314 state->total_param,
5315 &state->data,
5316 state->total_data,
5317 state->max_data_return);
5318 END_PROFILE(Trans2_qfileinfo);
5319 break;
5322 case TRANSACT2_SETPATHINFO:
5324 START_PROFILE(Trans2_setpathinfo);
5325 call_trans2setpathinfo(
5326 conn,
5327 req,
5328 &state->param,
5329 state->total_param,
5330 &state->data,
5331 state->total_data,
5332 state->max_data_return);
5333 END_PROFILE(Trans2_setpathinfo);
5334 break;
5337 case TRANSACT2_SETFILEINFO:
5339 START_PROFILE(Trans2_setfileinfo);
5340 call_trans2setfileinfo(
5341 conn,
5342 req,
5343 &state->param,
5344 state->total_param,
5345 &state->data,
5346 state->total_data,
5347 state->max_data_return);
5348 END_PROFILE(Trans2_setfileinfo);
5349 break;
5352 case TRANSACT2_FINDNOTIFYFIRST:
5354 START_PROFILE(Trans2_findnotifyfirst);
5355 call_trans2findnotifyfirst(conn, req,
5356 &state->param, state->total_param,
5357 &state->data, state->total_data,
5358 state->max_data_return);
5359 END_PROFILE(Trans2_findnotifyfirst);
5360 break;
5363 case TRANSACT2_FINDNOTIFYNEXT:
5365 START_PROFILE(Trans2_findnotifynext);
5366 call_trans2findnotifynext(conn, req,
5367 &state->param, state->total_param,
5368 &state->data, state->total_data,
5369 state->max_data_return);
5370 END_PROFILE(Trans2_findnotifynext);
5371 break;
5374 case TRANSACT2_MKDIR:
5376 START_PROFILE(Trans2_mkdir);
5377 call_trans2mkdir(conn, req,
5378 &state->param, state->total_param,
5379 &state->data, state->total_data,
5380 state->max_data_return);
5381 END_PROFILE(Trans2_mkdir);
5382 break;
5385 case TRANSACT2_GET_DFS_REFERRAL:
5387 START_PROFILE(Trans2_get_dfs_referral);
5388 call_trans2getdfsreferral(conn, req,
5389 &state->param, state->total_param,
5390 &state->data, state->total_data,
5391 state->max_data_return);
5392 END_PROFILE(Trans2_get_dfs_referral);
5393 break;
5396 case TRANSACT2_IOCTL:
5398 START_PROFILE(Trans2_ioctl);
5399 call_trans2ioctl(conn, req,
5400 &state->param, state->total_param,
5401 &state->data, state->total_data,
5402 state->max_data_return);
5403 END_PROFILE(Trans2_ioctl);
5404 break;
5407 default:
5408 /* Error in request */
5409 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5410 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5414 /****************************************************************************
5415 Reply to a SMBtrans2.
5416 ****************************************************************************/
5418 void reply_trans2(struct smb_request *req)
5420 connection_struct *conn = req->conn;
5421 unsigned int dsoff;
5422 unsigned int dscnt;
5423 unsigned int psoff;
5424 unsigned int pscnt;
5425 unsigned int tran_call;
5426 struct trans_state *state;
5427 NTSTATUS result;
5429 START_PROFILE(SMBtrans2);
5431 if (req->wct < 14) {
5432 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5433 END_PROFILE(SMBtrans2);
5434 return;
5437 dsoff = SVAL(req->vwv+12, 0);
5438 dscnt = SVAL(req->vwv+11, 0);
5439 psoff = SVAL(req->vwv+10, 0);
5440 pscnt = SVAL(req->vwv+9, 0);
5441 tran_call = SVAL(req->vwv+14, 0);
5443 result = allow_new_trans(conn->pending_trans, req->mid);
5444 if (!NT_STATUS_IS_OK(result)) {
5445 DEBUG(2, ("Got invalid trans2 request: %s\n",
5446 nt_errstr(result)));
5447 reply_nterror(req, result);
5448 END_PROFILE(SMBtrans2);
5449 return;
5452 if (IS_IPC(conn)) {
5453 switch (tran_call) {
5454 /* List the allowed trans2 calls on IPC$ */
5455 case TRANSACT2_OPEN:
5456 case TRANSACT2_GET_DFS_REFERRAL:
5457 case TRANSACT2_QFILEINFO:
5458 case TRANSACT2_QFSINFO:
5459 case TRANSACT2_SETFSINFO:
5460 break;
5461 default:
5462 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5463 END_PROFILE(SMBtrans2);
5464 return;
5468 if ((state = talloc(conn, struct trans_state)) == NULL) {
5469 DEBUG(0, ("talloc failed\n"));
5470 reply_nterror(req, NT_STATUS_NO_MEMORY);
5471 END_PROFILE(SMBtrans2);
5472 return;
5475 state->cmd = SMBtrans2;
5477 state->mid = req->mid;
5478 state->vuid = req->vuid;
5479 state->setup_count = SVAL(req->vwv+13, 0);
5480 state->setup = NULL;
5481 state->total_param = SVAL(req->vwv+0, 0);
5482 state->param = NULL;
5483 state->total_data = SVAL(req->vwv+1, 0);
5484 state->data = NULL;
5485 state->max_param_return = SVAL(req->vwv+2, 0);
5486 state->max_data_return = SVAL(req->vwv+3, 0);
5487 state->max_setup_return = SVAL(req->vwv+4, 0);
5488 state->close_on_completion = BITSETW(req->vwv+5, 0);
5489 state->one_way = BITSETW(req->vwv+5, 1);
5491 state->call = tran_call;
5493 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5494 is so as a sanity check */
5495 if (state->setup_count != 1) {
5497 * Need to have rc=0 for ioctl to get job id for OS/2.
5498 * Network printing will fail if function is not successful.
5499 * Similar function in reply.c will be used if protocol
5500 * is LANMAN1.0 instead of LM1.2X002.
5501 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5502 * outbuf doesn't have to be set(only job id is used).
5504 if ( (state->setup_count == 4)
5505 && (tran_call == TRANSACT2_IOCTL)
5506 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
5507 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
5508 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5509 } else {
5510 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5511 DEBUG(2,("Transaction is %d\n",tran_call));
5512 TALLOC_FREE(state);
5513 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5514 END_PROFILE(SMBtrans2);
5515 return;
5519 if ((dscnt > state->total_data) || (pscnt > state->total_param))
5520 goto bad_param;
5522 if (state->total_data) {
5524 if (smb_buffer_oob(state->total_data, 0, dscnt)
5525 || smb_buffer_oob(smb_len(req->inbuf), dsoff, dscnt)) {
5526 goto bad_param;
5529 /* Can't use talloc here, the core routines do realloc on the
5530 * params and data. */
5531 state->data = (char *)SMB_MALLOC(state->total_data);
5532 if (state->data == NULL) {
5533 DEBUG(0,("reply_trans2: data malloc fail for %u "
5534 "bytes !\n", (unsigned int)state->total_data));
5535 TALLOC_FREE(state);
5536 reply_nterror(req, NT_STATUS_NO_MEMORY);
5537 END_PROFILE(SMBtrans2);
5538 return;
5541 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
5544 if (state->total_param) {
5546 if (smb_buffer_oob(state->total_param, 0, pscnt)
5547 || smb_buffer_oob(smb_len(req->inbuf), psoff, pscnt)) {
5548 goto bad_param;
5551 /* Can't use talloc here, the core routines do realloc on the
5552 * params and data. */
5553 state->param = (char *)SMB_MALLOC(state->total_param);
5554 if (state->param == NULL) {
5555 DEBUG(0,("reply_trans: param malloc fail for %u "
5556 "bytes !\n", (unsigned int)state->total_param));
5557 SAFE_FREE(state->data);
5558 TALLOC_FREE(state);
5559 reply_nterror(req, NT_STATUS_NO_MEMORY);
5560 END_PROFILE(SMBtrans2);
5561 return;
5564 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
5567 state->received_data = dscnt;
5568 state->received_param = pscnt;
5570 if ((state->received_param == state->total_param) &&
5571 (state->received_data == state->total_data)) {
5573 handle_trans2(conn, req, state);
5575 SAFE_FREE(state->data);
5576 SAFE_FREE(state->param);
5577 TALLOC_FREE(state);
5578 END_PROFILE(SMBtrans2);
5579 return;
5582 DLIST_ADD(conn->pending_trans, state);
5584 /* We need to send an interim response then receive the rest
5585 of the parameter/data bytes */
5586 reply_smb1_outbuf(req, 0, 0);
5587 show_msg((char *)req->outbuf);
5588 END_PROFILE(SMBtrans2);
5589 return;
5591 bad_param:
5593 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5594 SAFE_FREE(state->data);
5595 SAFE_FREE(state->param);
5596 TALLOC_FREE(state);
5597 END_PROFILE(SMBtrans2);
5598 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5601 /****************************************************************************
5602 Reply to a SMBtranss2
5603 ****************************************************************************/
5605 void reply_transs2(struct smb_request *req)
5607 connection_struct *conn = req->conn;
5608 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5609 struct trans_state *state;
5611 START_PROFILE(SMBtranss2);
5613 show_msg((const char *)req->inbuf);
5615 /* Windows clients expect all replies to
5616 a transact secondary (SMBtranss2 0x33)
5617 to have a command code of transact
5618 (SMBtrans2 0x32). See bug #8989
5619 and also [MS-CIFS] section 2.2.4.47.2
5620 for details.
5622 req->cmd = SMBtrans2;
5624 if (req->wct < 8) {
5625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5626 END_PROFILE(SMBtranss2);
5627 return;
5630 for (state = conn->pending_trans; state != NULL;
5631 state = state->next) {
5632 if (state->mid == req->mid) {
5633 break;
5637 if ((state == NULL) || (state->cmd != SMBtrans2)) {
5638 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5639 END_PROFILE(SMBtranss2);
5640 return;
5643 /* Revise state->total_param and state->total_data in case they have
5644 changed downwards */
5646 if (SVAL(req->vwv+0, 0) < state->total_param)
5647 state->total_param = SVAL(req->vwv+0, 0);
5648 if (SVAL(req->vwv+1, 0) < state->total_data)
5649 state->total_data = SVAL(req->vwv+1, 0);
5651 pcnt = SVAL(req->vwv+2, 0);
5652 poff = SVAL(req->vwv+3, 0);
5653 pdisp = SVAL(req->vwv+4, 0);
5655 dcnt = SVAL(req->vwv+5, 0);
5656 doff = SVAL(req->vwv+6, 0);
5657 ddisp = SVAL(req->vwv+7, 0);
5659 state->received_param += pcnt;
5660 state->received_data += dcnt;
5662 if ((state->received_data > state->total_data) ||
5663 (state->received_param > state->total_param))
5664 goto bad_param;
5666 if (pcnt) {
5667 if (smb_buffer_oob(state->total_param, pdisp, pcnt)
5668 || smb_buffer_oob(smb_len(req->inbuf), poff, pcnt)) {
5669 goto bad_param;
5671 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
5674 if (dcnt) {
5675 if (smb_buffer_oob(state->total_data, ddisp, dcnt)
5676 || smb_buffer_oob(smb_len(req->inbuf), doff, dcnt)) {
5677 goto bad_param;
5679 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
5682 if ((state->received_param < state->total_param) ||
5683 (state->received_data < state->total_data)) {
5684 END_PROFILE(SMBtranss2);
5685 return;
5688 handle_trans2(conn, req, state);
5690 DLIST_REMOVE(conn->pending_trans, state);
5691 SAFE_FREE(state->data);
5692 SAFE_FREE(state->param);
5693 TALLOC_FREE(state);
5695 END_PROFILE(SMBtranss2);
5696 return;
5698 bad_param:
5700 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5701 DLIST_REMOVE(conn->pending_trans, state);
5702 SAFE_FREE(state->data);
5703 SAFE_FREE(state->param);
5704 TALLOC_FREE(state);
5705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5706 END_PROFILE(SMBtranss2);
5707 return;