smbd: Make reopen_from_fsp() public
[samba4-gss.git] / source3 / smbd / smb1_trans2.c
blob244a8740b0fe7947580a9329a0536a7b1195c0b0
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"
49 #include "source3/smbd/dir.h"
51 #define DIR_ENTRY_SAFETY_MARGIN 4096
53 /****************************************************************************
54 Send the required number of replies back.
55 We assume all fields other than the data fields are
56 set correctly for the type of call.
57 HACK ! Always assumes smb_setup field is zero.
58 ****************************************************************************/
60 static void send_trans2_replies(connection_struct *conn,
61 struct smb_request *req,
62 NTSTATUS status,
63 const char *params,
64 int paramsize,
65 const char *pdata,
66 int datasize,
67 int max_data_bytes)
69 /* As we are using a protocol > LANMAN1 then the max_send
70 variable must have been set in the sessetupX call.
71 This takes precedence over the max_xmit field in the
72 global struct. These different max_xmit variables should
73 be merged as this is now too confusing */
75 int data_to_send = datasize;
76 int params_to_send = paramsize;
77 int useable_space;
78 const char *pp = params;
79 const char *pd = pdata;
80 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
81 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
82 int data_alignment_offset = 0;
83 bool overflow = False;
84 struct smbXsrv_connection *xconn = req->xconn;
85 int max_send = xconn->smb1.sessions.max_send;
87 /* Modify the data_to_send and datasize and set the error if
88 we're trying to send more than max_data_bytes. We still send
89 the part of the packet(s) that fit. Strange, but needed
90 for OS/2. */
92 if (max_data_bytes > 0 && datasize > max_data_bytes) {
93 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
94 max_data_bytes, datasize ));
95 datasize = data_to_send = max_data_bytes;
96 overflow = True;
99 /* If there genuinely are no parameters or data to send just send the empty packet */
101 if(params_to_send == 0 && data_to_send == 0) {
102 reply_smb1_outbuf(req, 10, 0);
103 if (NT_STATUS_V(status)) {
104 uint8_t eclass;
105 uint32_t ecode;
106 ntstatus_to_dos(status, &eclass, &ecode);
107 error_packet_set((char *)req->outbuf,
108 eclass, ecode, status,
109 __LINE__,__FILE__);
111 show_msg((char *)req->outbuf);
112 if (!smb1_srv_send(xconn,
113 (char *)req->outbuf,
114 true,
115 req->seqnum + 1,
116 IS_CONN_ENCRYPTED(conn))) {
117 exit_server_cleanly("send_trans2_replies: smb1_srv_send failed.");
119 TALLOC_FREE(req->outbuf);
120 return;
123 /* When sending params and data ensure that both are nicely aligned */
124 /* Only do this alignment when there is also data to send - else
125 can cause NT redirector problems. */
127 if (((params_to_send % 4) != 0) && (data_to_send != 0))
128 data_alignment_offset = 4 - (params_to_send % 4);
130 /* Space is bufsize minus Netbios over TCP header minus SMB header */
131 /* The alignment_offset is to align the param bytes on an even byte
132 boundary. NT 4.0 Beta needs this to work correctly. */
134 useable_space = max_send - (smb_size
135 + 2 * 10 /* wct */
136 + alignment_offset
137 + data_alignment_offset);
139 if (useable_space < 0) {
140 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
141 "= %d!!!\n", useable_space));
142 exit_server_cleanly("send_trans2_replies: Not enough space");
145 while (params_to_send || data_to_send) {
146 /* Calculate whether we will totally or partially fill this packet */
148 total_sent_thistime = params_to_send + data_to_send;
150 /* We can never send more than useable_space */
152 * Note that 'useable_space' does not include the alignment offsets,
153 * but we must include the alignment offsets in the calculation of
154 * the length of the data we send over the wire, as the alignment offsets
155 * are sent here. Fix from Marc_Jacobsen@hp.com.
158 total_sent_thistime = MIN(total_sent_thistime, useable_space);
160 reply_smb1_outbuf(req, 10, total_sent_thistime + alignment_offset
161 + data_alignment_offset);
163 /* Set total params and data to be sent */
164 SSVAL(req->outbuf,smb_tprcnt,paramsize);
165 SSVAL(req->outbuf,smb_tdrcnt,datasize);
167 /* Calculate how many parameters and data we can fit into
168 * this packet. Parameters get precedence
171 params_sent_thistime = MIN(params_to_send,useable_space);
172 data_sent_thistime = useable_space - params_sent_thistime;
173 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
175 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
177 /* smb_proff is the offset from the start of the SMB header to the
178 parameter bytes, however the first 4 bytes of outbuf are
179 the Netbios over TCP header. Thus use smb_base() to subtract
180 them from the calculation */
182 SSVAL(req->outbuf,smb_proff,
183 ((smb_buf(req->outbuf)+alignment_offset)
184 - smb_base(req->outbuf)));
186 if(params_sent_thistime == 0)
187 SSVAL(req->outbuf,smb_prdisp,0);
188 else
189 /* Absolute displacement of param bytes sent in this packet */
190 SSVAL(req->outbuf,smb_prdisp,pp - params);
192 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
193 if(data_sent_thistime == 0) {
194 SSVAL(req->outbuf,smb_droff,0);
195 SSVAL(req->outbuf,smb_drdisp, 0);
196 } else {
197 /* The offset of the data bytes is the offset of the
198 parameter bytes plus the number of parameters being sent this time */
199 SSVAL(req->outbuf, smb_droff,
200 ((smb_buf(req->outbuf)+alignment_offset)
201 - smb_base(req->outbuf))
202 + params_sent_thistime + data_alignment_offset);
203 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
206 /* Initialize the padding for alignment */
208 if (alignment_offset != 0) {
209 memset(smb_buf(req->outbuf), 0, alignment_offset);
212 /* Copy the param bytes into the packet */
214 if(params_sent_thistime) {
215 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
216 params_sent_thistime);
219 /* Copy in the data bytes */
220 if(data_sent_thistime) {
221 if (data_alignment_offset != 0) {
222 memset((smb_buf(req->outbuf)+alignment_offset+
223 params_sent_thistime), 0,
224 data_alignment_offset);
226 memcpy(smb_buf(req->outbuf)+alignment_offset
227 +params_sent_thistime+data_alignment_offset,
228 pd,data_sent_thistime);
231 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
232 params_sent_thistime, data_sent_thistime, useable_space));
233 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
234 params_to_send, data_to_send, paramsize, datasize));
236 if (overflow) {
237 error_packet_set((char *)req->outbuf,
238 ERRDOS,ERRbufferoverflow,
239 STATUS_BUFFER_OVERFLOW,
240 __LINE__,__FILE__);
241 } else if (NT_STATUS_V(status)) {
242 uint8_t eclass;
243 uint32_t ecode;
244 ntstatus_to_dos(status, &eclass, &ecode);
245 error_packet_set((char *)req->outbuf,
246 eclass, ecode, status,
247 __LINE__,__FILE__);
250 /* Send the packet */
251 show_msg((char *)req->outbuf);
252 if (!smb1_srv_send(xconn,
253 (char *)req->outbuf,
254 true,
255 req->seqnum + 1,
256 IS_CONN_ENCRYPTED(conn))) {
257 exit_server_cleanly("send_trans2_replies: smb1_srv_send failed.");
260 TALLOC_FREE(req->outbuf);
262 pp += params_sent_thistime;
263 pd += data_sent_thistime;
265 params_to_send -= params_sent_thistime;
266 data_to_send -= data_sent_thistime;
268 /* Sanity check */
269 if(params_to_send < 0 || data_to_send < 0) {
270 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
271 params_to_send, data_to_send));
272 return;
276 return;
279 /****************************************************************************
280 Deal with SMB_SET_POSIX_LOCK.
281 ****************************************************************************/
283 static void smb_set_posix_lock_done(struct tevent_req *subreq);
285 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
286 struct smb_request *req,
287 const char *pdata,
288 int total_data,
289 files_struct *fsp)
291 struct tevent_req *subreq = NULL;
292 struct smbd_lock_element *lck = NULL;
293 uint64_t count;
294 uint64_t offset;
295 uint64_t smblctx;
296 bool blocking_lock = False;
297 enum brl_type lock_type;
299 NTSTATUS status = NT_STATUS_OK;
301 if (!CAN_WRITE(conn)) {
302 return NT_STATUS_DOS(ERRSRV, ERRaccess);
305 if (fsp == NULL ||
306 fsp->fsp_flags.is_pathref ||
307 fsp_get_io_fd(fsp) == -1)
309 return NT_STATUS_INVALID_HANDLE;
312 if (total_data != POSIX_LOCK_DATA_SIZE) {
313 return NT_STATUS_INVALID_PARAMETER;
316 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
317 case POSIX_LOCK_TYPE_READ:
318 lock_type = READ_LOCK;
319 break;
320 case POSIX_LOCK_TYPE_WRITE:
321 /* Return the right POSIX-mappable error code for files opened read-only. */
322 if (!fsp->fsp_flags.can_write) {
323 return NT_STATUS_INVALID_HANDLE;
325 lock_type = WRITE_LOCK;
326 break;
327 case POSIX_LOCK_TYPE_UNLOCK:
328 lock_type = UNLOCK_LOCK;
329 break;
330 default:
331 return NT_STATUS_INVALID_PARAMETER;
334 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
335 case POSIX_LOCK_FLAG_NOWAIT:
336 blocking_lock = false;
337 break;
338 case POSIX_LOCK_FLAG_WAIT:
339 blocking_lock = true;
340 break;
341 default:
342 return NT_STATUS_INVALID_PARAMETER;
345 if (!lp_blocking_locks(SNUM(conn))) {
346 blocking_lock = False;
349 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
350 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
351 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
352 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
353 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
355 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
356 "count = %"PRIu64", offset = %"PRIu64"\n",
357 fsp_str_dbg(fsp),
358 (unsigned int)lock_type,
359 smblctx,
360 count,
361 offset);
363 if (lock_type == UNLOCK_LOCK) {
364 struct smbd_lock_element l = {
365 .req_guid = smbd_request_guid(req, 0),
366 .smblctx = smblctx,
367 .brltype = UNLOCK_LOCK,
368 .lock_flav = POSIX_LOCK,
369 .offset = offset,
370 .count = count,
372 status = smbd_do_unlocking(req, fsp, 1, &l);
373 return status;
376 lck = talloc(req, struct smbd_lock_element);
377 if (lck == NULL) {
378 return NT_STATUS_NO_MEMORY;
381 *lck = (struct smbd_lock_element) {
382 .req_guid = smbd_request_guid(req, 0),
383 .smblctx = smblctx,
384 .brltype = lock_type,
385 .lock_flav = POSIX_LOCK,
386 .count = count,
387 .offset = offset,
390 subreq = smbd_smb1_do_locks_send(
391 fsp,
392 req->sconn->ev_ctx,
393 &req,
394 fsp,
395 blocking_lock ? UINT32_MAX : 0,
396 true, /* large_offset */
398 lck);
399 if (subreq == NULL) {
400 TALLOC_FREE(lck);
401 return NT_STATUS_NO_MEMORY;
403 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
404 return NT_STATUS_EVENT_PENDING;
407 static void smb_set_posix_lock_done(struct tevent_req *subreq)
409 struct smb_request *req = NULL;
410 NTSTATUS status;
411 bool ok;
413 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
414 SMB_ASSERT(ok);
416 status = smbd_smb1_do_locks_recv(subreq);
417 TALLOC_FREE(subreq);
419 if (NT_STATUS_IS_OK(status)) {
420 char params[2] = {0};
421 /* Fake up max_data_bytes here - we know it fits. */
422 send_trans2_replies(
423 req->conn,
424 req,
425 NT_STATUS_OK,
426 params,
428 NULL,
430 0xffff);
431 } else {
432 reply_nterror(req, status);
433 ok = smb1_srv_send(req->xconn,
434 (char *)req->outbuf,
435 true,
436 req->seqnum + 1,
437 IS_CONN_ENCRYPTED(req->conn));
438 if (!ok) {
439 exit_server_cleanly("smb_set_posix_lock_done: "
440 "smb1_srv_send failed.");
444 TALLOC_FREE(req);
445 return;
448 /****************************************************************************
449 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
450 ****************************************************************************/
452 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
454 struct ea_list *ea_list_head = NULL;
455 size_t converted_size, offset = 0;
457 while (offset + 2 < data_size) {
458 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
459 unsigned int namelen = CVAL(pdata,offset);
461 offset++; /* Go past the namelen byte. */
463 /* integer wrap paranioa. */
464 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
465 (offset > data_size) || (namelen > data_size) ||
466 (offset + namelen >= data_size)) {
467 break;
469 /* Ensure the name is null terminated. */
470 if (pdata[offset + namelen] != '\0') {
471 return NULL;
473 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
474 &converted_size)) {
475 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
476 "failed: %s\n", strerror(errno)));
478 if (!eal->ea.name) {
479 return NULL;
482 offset += (namelen + 1); /* Go past the name + terminating zero. */
483 DLIST_ADD_END(ea_list_head, eal);
484 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
487 return ea_list_head;
490 /****************************************************************************
491 Reply to a TRANSACT2_OPEN.
492 ****************************************************************************/
494 static void call_trans2open(connection_struct *conn,
495 struct smb_request *req,
496 char **pparams, int total_params,
497 char **ppdata, int total_data,
498 unsigned int max_data_bytes)
500 struct smb_filename *smb_fname = NULL;
501 char *params = *pparams;
502 char *pdata = *ppdata;
503 int deny_mode;
504 int32_t open_attr;
505 bool oplock_request;
506 #if 0
507 bool return_additional_info;
508 int16 open_sattr;
509 time_t open_time;
510 #endif
511 int open_ofun;
512 uint32_t open_size;
513 char *pname;
514 char *fname = NULL;
515 off_t size=0;
516 int fattr = 0;
517 SMB_INO_T inode = 0;
518 int smb_action = 0;
519 struct files_struct *dirfsp = NULL;
520 files_struct *fsp;
521 struct ea_list *ea_list = NULL;
522 uint16_t flags = 0;
523 NTSTATUS status;
524 uint32_t access_mask;
525 uint32_t share_mode;
526 uint32_t create_disposition;
527 uint32_t create_options = 0;
528 uint32_t private_flags = 0;
529 NTTIME twrp = 0;
530 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
531 TALLOC_CTX *ctx = talloc_tos();
534 * Ensure we have enough parameters to perform the operation.
537 if (total_params < 29) {
538 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
539 goto out;
542 flags = SVAL(params, 0);
543 deny_mode = SVAL(params, 2);
544 open_attr = SVAL(params,6);
545 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
546 if (oplock_request) {
547 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
550 #if 0
551 return_additional_info = BITSETW(params,0);
552 open_sattr = SVAL(params, 4);
553 open_time = make_unix_date3(params+8);
554 #endif
555 open_ofun = SVAL(params,12);
556 open_size = IVAL(params,14);
557 pname = &params[28];
559 if (IS_IPC(conn)) {
560 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
561 goto out;
564 if (req->posix_pathnames) {
565 srvstr_get_path_posix(ctx,
566 params,
567 req->flags2,
568 &fname,
569 pname,
570 total_params - 28,
571 STR_TERMINATE,
572 &status);
573 } else {
574 srvstr_get_path(ctx,
575 params,
576 req->flags2,
577 &fname,
578 pname,
579 total_params - 28,
580 STR_TERMINATE,
581 &status);
583 if (!NT_STATUS_IS_OK(status)) {
584 reply_nterror(req, status);
585 goto out;
588 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
589 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
590 (unsigned int)open_ofun, open_size));
592 if (ucf_flags & UCF_GMT_PATHNAME) {
593 extract_snapshot_token(fname, &twrp);
595 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
596 if (!NT_STATUS_IS_OK(status)) {
597 reply_nterror(req, status);
598 goto out;
600 status = filename_convert_dirfsp(ctx,
601 conn,
602 fname,
603 ucf_flags,
604 twrp,
605 &dirfsp,
606 &smb_fname);
607 if (!NT_STATUS_IS_OK(status)) {
608 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
609 reply_botherror(req,
610 NT_STATUS_PATH_NOT_COVERED,
611 ERRSRV, ERRbadpath);
612 goto out;
614 reply_nterror(req, status);
615 goto out;
618 if (open_ofun == 0) {
619 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
620 goto out;
623 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
624 open_ofun,
625 &access_mask, &share_mode,
626 &create_disposition,
627 &create_options,
628 &private_flags)) {
629 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
630 goto out;
633 /* Any data in this call is an EA list. */
634 if (total_data && (total_data != 4)) {
635 if (total_data < 10) {
636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
637 goto out;
640 if (IVAL(pdata,0) > total_data) {
641 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
642 IVAL(pdata,0), (unsigned int)total_data));
643 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
644 goto out;
647 ea_list = read_ea_list(talloc_tos(), pdata + 4,
648 total_data - 4);
649 if (!ea_list) {
650 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
651 goto out;
654 if (!lp_ea_support(SNUM(conn))) {
655 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
656 goto out;
659 if (!req->posix_pathnames &&
660 ea_list_has_invalid_name(ea_list)) {
661 int param_len = 30;
662 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
663 if(*pparams == NULL ) {
664 reply_nterror(req, NT_STATUS_NO_MEMORY);
665 goto out;
667 params = *pparams;
668 memset(params, '\0', param_len);
669 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
670 params, param_len, NULL, 0, max_data_bytes);
671 goto out;
675 status = SMB_VFS_CREATE_FILE(
676 conn, /* conn */
677 req, /* req */
678 dirfsp, /* dirfsp */
679 smb_fname, /* fname */
680 access_mask, /* access_mask */
681 share_mode, /* share_access */
682 create_disposition, /* create_disposition*/
683 create_options, /* create_options */
684 open_attr, /* file_attributes */
685 oplock_request, /* oplock_request */
686 NULL, /* lease */
687 open_size, /* allocation_size */
688 private_flags,
689 NULL, /* sd */
690 ea_list, /* ea_list */
691 &fsp, /* result */
692 &smb_action, /* psbuf */
693 NULL, NULL); /* create context */
695 if (!NT_STATUS_IS_OK(status)) {
696 if (open_was_deferred(req->xconn, req->mid)) {
697 /* We have re-scheduled this call. */
698 goto out;
701 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
702 reply_openerror(req, status);
703 goto out;
706 fsp = fcb_or_dos_open(
707 req,
708 smb_fname,
709 access_mask,
710 create_options,
711 private_flags);
712 if (fsp == NULL) {
713 bool ok = defer_smb1_sharing_violation(req);
714 if (ok) {
715 goto out;
717 reply_openerror(req, status);
718 goto out;
721 smb_action = FILE_WAS_OPENED;
724 size = get_file_size_stat(&smb_fname->st);
725 fattr = fdos_mode(fsp);
726 inode = smb_fname->st.st_ex_ino;
727 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
728 close_file_free(req, &fsp, ERROR_CLOSE);
729 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
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_ts(params, 4, smb_fname->st.st_ex_mtime);
744 SIVAL(params,8, (uint32_t)size);
745 SSVAL(params,12,deny_mode);
746 SSVAL(params,14,0); /* open_type - file or directory. */
747 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
749 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
750 smb_action |= EXTENDED_OPLOCK_GRANTED;
753 SSVAL(params,18,smb_action);
756 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
758 SIVAL(params,20,inode);
759 SSVAL(params,24,0); /* Padding. */
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->fsp_flags.posix_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 NULL,
1685 ppdata, &data_len);
1686 if (!NT_STATUS_IS_OK(status)) {
1687 reply_nterror(req, status);
1688 return;
1691 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
1692 max_data_bytes);
1694 DEBUG( 4, ( "%s info_level = %d\n",
1695 smb_fn_name(req->cmd), info_level) );
1697 return;
1700 /****************************************************************************
1701 Reply to a TRANS2_SETFSINFO (set filesystem info).
1702 ****************************************************************************/
1704 static void call_trans2setfsinfo(connection_struct *conn,
1705 struct smb_request *req,
1706 char **pparams, int total_params,
1707 char **ppdata, int total_data,
1708 unsigned int max_data_bytes)
1710 const struct loadparm_substitution *lp_sub =
1711 loadparm_s3_global_substitution();
1712 struct smbXsrv_connection *xconn = req->xconn;
1713 char *pdata = *ppdata;
1714 char *params = *pparams;
1715 uint16_t info_level;
1717 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
1718 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
1720 /* */
1721 if (total_params < 4) {
1722 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1723 total_params));
1724 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1725 return;
1728 info_level = SVAL(params,2);
1730 if (IS_IPC(conn)) {
1731 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
1732 info_level != SMB_SET_CIFS_UNIX_INFO) {
1733 DEBUG(0,("call_trans2setfsinfo: not an allowed "
1734 "info level (0x%x) on IPC$.\n",
1735 (unsigned int)info_level));
1736 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1737 return;
1741 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
1742 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
1743 DEBUG(0,("call_trans2setfsinfo: encryption required "
1744 "and info level 0x%x sent.\n",
1745 (unsigned int)info_level));
1746 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1747 return;
1751 switch(info_level) {
1752 case SMB_SET_CIFS_UNIX_INFO:
1753 if (!lp_smb1_unix_extensions()) {
1754 DEBUG(2,("call_trans2setfsinfo: "
1755 "SMB_SET_CIFS_UNIX_INFO is invalid with "
1756 "unix extensions off\n"));
1757 reply_nterror(req,
1758 NT_STATUS_INVALID_LEVEL);
1759 return;
1762 /* There should be 12 bytes of capabilities set. */
1763 if (total_data < 12) {
1764 reply_nterror(
1765 req,
1766 NT_STATUS_INVALID_PARAMETER);
1767 return;
1769 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
1770 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
1771 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
1772 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
1774 /* Just print these values for now. */
1775 DBG_DEBUG("set unix_info info. "
1776 "major = %"PRIu16", minor = %"PRIu16
1777 "cap_low = 0x%"PRIx32", "
1778 "cap_high = 0x%"PRIx32"\n",
1779 xconn->smb1.unix_info.client_major,
1780 xconn->smb1.unix_info.client_minor,
1781 xconn->smb1.unix_info.client_cap_low,
1782 xconn->smb1.unix_info.client_cap_high);
1785 * Here is where we must switch to posix
1786 * pathname processing...
1788 if (xconn->smb1.unix_info.client_cap_low &
1789 CIFS_UNIX_POSIX_PATHNAMES_CAP)
1791 lp_set_posix_pathnames();
1792 mangle_change_to_posix();
1795 if ((xconn->smb1.unix_info.client_cap_low &
1796 CIFS_UNIX_FCNTL_LOCKS_CAP) &&
1797 !(xconn->smb1.unix_info.client_cap_low &
1798 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP))
1800 /* Client that knows how to do posix locks,
1801 * but not posix open/mkdir operations. Set a
1802 * default type for read/write checks. */
1804 lp_set_posix_default_cifsx_readwrite_locktype(
1805 POSIX_LOCK);
1808 break;
1810 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
1812 NTSTATUS status;
1813 size_t param_len = 0;
1814 size_t data_len = total_data;
1816 if (!lp_smb1_unix_extensions()) {
1817 reply_nterror(
1818 req,
1819 NT_STATUS_INVALID_LEVEL);
1820 return;
1823 if (lp_server_smb_encrypt(SNUM(conn)) ==
1824 SMB_ENCRYPTION_OFF) {
1825 reply_nterror(
1826 req,
1827 NT_STATUS_NOT_SUPPORTED);
1828 return;
1831 if (xconn->smb1.echo_handler.trusted_fde) {
1832 DEBUG( 2,("call_trans2setfsinfo: "
1833 "request transport encryption disabled"
1834 "with 'fork echo handler = yes'\n"));
1835 reply_nterror(
1836 req,
1837 NT_STATUS_NOT_SUPPORTED);
1838 return;
1841 DEBUG( 4,("call_trans2setfsinfo: "
1842 "request transport encryption.\n"));
1844 status = srv_request_encryption_setup(conn,
1845 (unsigned char **)ppdata,
1846 &data_len,
1847 (unsigned char **)pparams,
1848 &param_len);
1850 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
1851 !NT_STATUS_IS_OK(status)) {
1852 reply_nterror(req, status);
1853 return;
1856 send_trans2_replies(conn, req,
1857 NT_STATUS_OK,
1858 *pparams,
1859 param_len,
1860 *ppdata,
1861 data_len,
1862 max_data_bytes);
1864 if (NT_STATUS_IS_OK(status)) {
1865 /* Server-side transport
1866 * encryption is now *on*. */
1867 status = srv_encryption_start(conn);
1868 if (!NT_STATUS_IS_OK(status)) {
1869 char *reason = talloc_asprintf(talloc_tos(),
1870 "Failure in setting "
1871 "up encrypted transport: %s",
1872 nt_errstr(status));
1873 exit_server_cleanly(reason);
1876 return;
1879 case SMB_FS_QUOTA_INFORMATION:
1881 NTSTATUS status;
1882 DATA_BLOB qdata = {
1883 .data = (uint8_t *)pdata,
1884 .length = total_data
1886 files_struct *fsp = NULL;
1887 fsp = file_fsp(req, SVAL(params,0));
1889 status = smb_set_fsquota(conn,
1890 req,
1891 fsp,
1892 &qdata);
1893 if (!NT_STATUS_IS_OK(status)) {
1894 reply_nterror(req, status);
1895 return;
1897 break;
1899 default:
1900 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1901 info_level));
1902 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1903 return;
1904 break;
1908 * sending this reply works fine,
1909 * but I'm not sure it's the same
1910 * like windows do...
1911 * --metze
1913 reply_smb1_outbuf(req, 10, 0);
1916 /****************************************************************************
1917 Reply to a TRANSACT2_QFILEINFO on a PIPE !
1918 ****************************************************************************/
1920 static void call_trans2qpipeinfo(connection_struct *conn,
1921 struct smb_request *req,
1922 files_struct *fsp,
1923 uint16_t info_level,
1924 unsigned int tran_call,
1925 char **pparams, int total_params,
1926 char **ppdata, int total_data,
1927 unsigned int max_data_bytes)
1929 char *params = *pparams;
1930 char *pdata = *ppdata;
1931 unsigned int data_size = 0;
1932 unsigned int param_size = 2;
1934 if (!fsp_is_np(fsp)) {
1935 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1936 return;
1939 *pparams = (char *)SMB_REALLOC(*pparams,2);
1940 if (*pparams == NULL) {
1941 reply_nterror(req, NT_STATUS_NO_MEMORY);
1942 return;
1944 params = *pparams;
1945 SSVAL(params,0,0);
1946 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1948 return;
1950 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
1951 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
1952 if (*ppdata == NULL ) {
1953 reply_nterror(req, NT_STATUS_NO_MEMORY);
1954 return;
1956 pdata = *ppdata;
1958 switch (info_level) {
1959 case SMB_FILE_STANDARD_INFORMATION:
1960 memset(pdata,0,24);
1961 SOFF_T(pdata,0,4096LL);
1962 SIVAL(pdata,16,1);
1963 SIVAL(pdata,20,1);
1964 data_size = 24;
1965 break;
1967 default:
1968 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1969 return;
1972 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
1973 max_data_bytes);
1976 static void handle_trans2qfilepathinfo_result(
1977 connection_struct *conn,
1978 struct smb_request *req,
1979 uint16_t info_level,
1980 NTSTATUS status,
1981 char *pdata,
1982 int data_return_size,
1983 size_t fixed_portion,
1984 unsigned int max_data_bytes)
1986 char params[2] = { 0, 0, };
1987 int param_size = 2;
1990 * draft-leach-cifs-v1-spec-02.txt
1991 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
1992 * says:
1994 * The requested information is placed in the Data portion of the
1995 * transaction response. For the information levels greater than 0x100,
1996 * the transaction response has 1 parameter word which should be
1997 * ignored by the client.
1999 * However Windows only follows this rule for the IS_NAME_VALID call.
2001 switch (info_level) {
2002 case SMB_INFO_IS_NAME_VALID:
2003 param_size = 0;
2004 break;
2007 if (!NT_STATUS_IS_OK(status)) {
2008 if (open_was_deferred(req->xconn, req->mid)) {
2009 /* We have re-scheduled this call. */
2010 return;
2012 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2013 bool ok = defer_smb1_sharing_violation(req);
2014 if (ok) {
2015 return;
2018 reply_nterror(req, status);
2019 return;
2022 if (fixed_portion > max_data_bytes) {
2023 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
2024 return;
2027 send_trans2_replies(
2028 conn,
2029 req,
2030 NT_STATUS_OK,
2031 params,
2032 param_size,
2033 pdata,
2034 data_return_size,
2035 max_data_bytes);
2038 /****************************************************************************
2039 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2040 file name or file id).
2041 ****************************************************************************/
2043 static void call_trans2qfilepathinfo(connection_struct *conn,
2044 struct smb_request *req,
2045 unsigned int tran_call,
2046 uint16_t info_level,
2047 struct smb_filename *smb_fname,
2048 struct files_struct *fsp,
2049 bool delete_pending,
2050 struct timespec write_time_ts,
2051 char **pparams, int total_params,
2052 char **ppdata, int total_data,
2053 unsigned int max_data_bytes)
2055 char *params = *pparams;
2056 char *pdata = *ppdata;
2057 unsigned int data_size = 0;
2058 struct ea_list *ea_list = NULL;
2059 size_t fixed_portion;
2060 NTSTATUS status = NT_STATUS_OK;
2062 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
2063 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
2064 fsp_fnum_dbg(fsp),
2065 info_level,tran_call,total_data));
2067 /* Pull out any data sent here before we realloc. */
2068 switch (info_level) {
2069 case SMB_INFO_QUERY_EAS_FROM_LIST:
2071 /* Pull any EA list from the data portion. */
2072 uint32_t ea_size;
2074 if (total_data < 4) {
2075 reply_nterror(
2076 req, NT_STATUS_INVALID_PARAMETER);
2077 return;
2079 ea_size = IVAL(pdata,0);
2081 if (total_data > 0 && ea_size != total_data) {
2082 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2083 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2084 reply_nterror(
2085 req, NT_STATUS_INVALID_PARAMETER);
2086 return;
2089 if (!lp_ea_support(SNUM(conn))) {
2090 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2091 return;
2094 /* Pull out the list of names. */
2095 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
2096 if (!ea_list) {
2097 reply_nterror(
2098 req, NT_STATUS_INVALID_PARAMETER);
2099 return;
2101 break;
2104 default:
2105 break;
2108 *pparams = (char *)SMB_REALLOC(*pparams,2);
2109 if (*pparams == NULL) {
2110 reply_nterror(req, NT_STATUS_NO_MEMORY);
2111 return;
2113 params = *pparams;
2114 SSVAL(params,0,0);
2116 if ((info_level & SMB2_INFO_SPECIAL) == SMB2_INFO_SPECIAL) {
2118 * We use levels that start with 0xFF00
2119 * internally to represent SMB2 specific levels
2121 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2122 return;
2125 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
2126 fsp, smb_fname,
2127 delete_pending, write_time_ts,
2128 ea_list,
2129 req->flags2, max_data_bytes,
2130 &fixed_portion,
2131 ppdata, &data_size);
2133 handle_trans2qfilepathinfo_result(
2134 conn,
2135 req,
2136 info_level,
2137 status,
2138 *ppdata,
2139 data_size,
2140 fixed_portion,
2141 max_data_bytes);
2144 static NTSTATUS smb_q_unix_basic(
2145 struct connection_struct *conn,
2146 struct smb_request *req,
2147 struct smb_filename *smb_fname,
2148 struct files_struct *fsp,
2149 char **ppdata,
2150 int *ptotal_data)
2152 const int total_data = 100;
2154 *ppdata = SMB_REALLOC(*ppdata, total_data);
2155 if (*ppdata == NULL) {
2156 return NT_STATUS_NO_MEMORY;
2158 store_file_unix_basic(conn, *ppdata, fsp, &smb_fname->st);
2160 *ptotal_data = total_data;
2162 return NT_STATUS_OK;
2165 static NTSTATUS smb_q_unix_info2(
2166 struct connection_struct *conn,
2167 struct smb_request *req,
2168 struct smb_filename *smb_fname,
2169 struct files_struct *fsp,
2170 char **ppdata,
2171 int *ptotal_data)
2173 const int total_data = 116;
2175 *ppdata = SMB_REALLOC(*ppdata, total_data);
2176 if (*ppdata == NULL) {
2177 return NT_STATUS_NO_MEMORY;
2179 store_file_unix_basic_info2(conn, *ppdata, fsp, &smb_fname->st);
2181 *ptotal_data = total_data;
2183 return NT_STATUS_OK;
2186 #if defined(HAVE_POSIX_ACLS)
2187 /****************************************************************************
2188 Utility function to open a fsp for a POSIX handle operation.
2189 ****************************************************************************/
2191 static NTSTATUS get_posix_fsp(connection_struct *conn,
2192 struct smb_request *req,
2193 struct smb_filename *smb_fname,
2194 uint32_t access_mask,
2195 files_struct **ret_fsp)
2197 NTSTATUS status;
2198 uint32_t create_disposition = FILE_OPEN;
2199 uint32_t share_access = FILE_SHARE_READ|
2200 FILE_SHARE_WRITE|
2201 FILE_SHARE_DELETE;
2202 struct smb2_create_blobs *posx = NULL;
2205 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
2206 * but set reasonable defaults.
2208 uint32_t file_attributes = 0664;
2209 uint32_t oplock = NO_OPLOCK;
2210 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
2212 /* File or directory must exist. */
2213 if (!VALID_STAT(smb_fname->st)) {
2214 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2216 /* Cannot be a symlink. */
2217 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
2218 return NT_STATUS_ACCESS_DENIED;
2220 /* Set options correctly for directory open. */
2221 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
2223 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
2224 * directories, but set reasonable defaults.
2226 file_attributes = 0775;
2227 create_options = FILE_DIRECTORY_FILE;
2230 status = make_smb2_posix_create_ctx(
2231 talloc_tos(), &posx, file_attributes);
2232 if (!NT_STATUS_IS_OK(status)) {
2233 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
2234 nt_errstr(status));
2235 goto done;
2238 status = SMB_VFS_CREATE_FILE(
2239 conn, /* conn */
2240 req, /* req */
2241 NULL, /* dirfsp */
2242 smb_fname, /* fname */
2243 access_mask, /* access_mask */
2244 share_access, /* share_access */
2245 create_disposition,/* create_disposition*/
2246 create_options, /* create_options */
2247 file_attributes,/* file_attributes */
2248 oplock, /* oplock_request */
2249 NULL, /* lease */
2250 0, /* allocation_size */
2251 0, /* private_flags */
2252 NULL, /* sd */
2253 NULL, /* ea_list */
2254 ret_fsp, /* result */
2255 NULL, /* pinfo */
2256 posx, /* in_context */
2257 NULL); /* out_context */
2259 done:
2260 TALLOC_FREE(posx);
2261 return status;
2264 /****************************************************************************
2265 Utility function to count the number of entries in a POSIX acl.
2266 ****************************************************************************/
2268 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2270 unsigned int ace_count = 0;
2271 int entry_id = SMB_ACL_FIRST_ENTRY;
2272 SMB_ACL_ENTRY_T entry;
2274 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2275 entry_id = SMB_ACL_NEXT_ENTRY;
2276 ace_count++;
2278 return ace_count;
2281 /****************************************************************************
2282 Utility function to marshall a POSIX acl into wire format.
2283 ****************************************************************************/
2285 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2287 int entry_id = SMB_ACL_FIRST_ENTRY;
2288 SMB_ACL_ENTRY_T entry;
2290 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2291 SMB_ACL_TAG_T tagtype;
2292 SMB_ACL_PERMSET_T permset;
2293 unsigned char perms = 0;
2294 unsigned int own_grp;
2296 entry_id = SMB_ACL_NEXT_ENTRY;
2298 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
2299 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2300 return False;
2303 if (sys_acl_get_permset(entry, &permset) == -1) {
2304 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2305 return False;
2308 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2309 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2310 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2312 SCVAL(pdata,1,perms);
2314 switch (tagtype) {
2315 case SMB_ACL_USER_OBJ:
2316 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2317 own_grp = (unsigned int)pst->st_ex_uid;
2318 SIVAL(pdata,2,own_grp);
2319 SIVAL(pdata,6,0);
2320 break;
2321 case SMB_ACL_USER:
2323 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
2324 if (!puid) {
2325 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2326 return False;
2328 own_grp = (unsigned int)*puid;
2329 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2330 SIVAL(pdata,2,own_grp);
2331 SIVAL(pdata,6,0);
2332 break;
2334 case SMB_ACL_GROUP_OBJ:
2335 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2336 own_grp = (unsigned int)pst->st_ex_gid;
2337 SIVAL(pdata,2,own_grp);
2338 SIVAL(pdata,6,0);
2339 break;
2340 case SMB_ACL_GROUP:
2342 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
2343 if (!pgid) {
2344 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2345 return False;
2347 own_grp = (unsigned int)*pgid;
2348 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2349 SIVAL(pdata,2,own_grp);
2350 SIVAL(pdata,6,0);
2351 break;
2353 case SMB_ACL_MASK:
2354 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2355 SIVAL(pdata,2,0xFFFFFFFF);
2356 SIVAL(pdata,6,0xFFFFFFFF);
2357 break;
2358 case SMB_ACL_OTHER:
2359 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2360 SIVAL(pdata,2,0xFFFFFFFF);
2361 SIVAL(pdata,6,0xFFFFFFFF);
2362 break;
2363 default:
2364 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2365 return False;
2367 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2370 return True;
2372 #endif
2374 static NTSTATUS smb_q_posix_acl(
2375 struct connection_struct *conn,
2376 struct smb_request *req,
2377 struct smb_filename *smb_fname,
2378 struct files_struct *fsp,
2379 char **ppdata,
2380 int *ptotal_data)
2382 #if !defined(HAVE_POSIX_ACLS)
2383 return NT_STATUS_INVALID_LEVEL;
2384 #else
2385 char *pdata = NULL;
2386 SMB_ACL_T file_acl = NULL;
2387 SMB_ACL_T def_acl = NULL;
2388 uint16_t num_file_acls = 0;
2389 uint16_t num_def_acls = 0;
2390 unsigned int size_needed = 0;
2391 NTSTATUS status;
2392 bool ok, refuse;
2393 bool close_fsp = false;
2396 * Ensure we always operate on a file descriptor, not just
2397 * the filename.
2399 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
2400 uint32_t access_mask = SEC_STD_READ_CONTROL|
2401 FILE_READ_ATTRIBUTES|
2402 FILE_WRITE_ATTRIBUTES;
2404 status = get_posix_fsp(conn,
2405 req,
2406 smb_fname,
2407 access_mask,
2408 &fsp);
2410 if (!NT_STATUS_IS_OK(status)) {
2411 goto out;
2413 close_fsp = true;
2416 SMB_ASSERT(fsp != NULL);
2418 refuse = refuse_symlink_fsp(fsp);
2419 if (refuse) {
2420 status = NT_STATUS_ACCESS_DENIED;
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 files_struct *dirfsp,
2534 struct smb_filename *smb_fname,
2535 char **ppdata,
2536 int *ptotal_data)
2538 char *target = NULL;
2539 size_t needed, len;
2540 char *pdata = NULL;
2541 NTSTATUS status;
2543 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
2544 smb_fname_str_dbg(smb_fname));
2546 if (!S_ISLNK(smb_fname->st.st_ex_mode)) {
2547 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
2550 if (fsp_get_pathref_fd(smb_fname->fsp) != -1) {
2552 * fsp is an O_PATH open, Linux does a "freadlink"
2553 * with an empty name argument to readlinkat
2555 status = readlink_talloc(talloc_tos(),
2556 smb_fname->fsp,
2557 NULL,
2558 &target);
2559 } else {
2560 struct smb_filename smb_fname_rel = *smb_fname;
2561 char *slash = NULL;
2563 slash = strrchr_m(smb_fname->base_name, '/');
2564 if (slash != NULL) {
2565 smb_fname_rel.base_name = slash + 1;
2567 status = readlink_talloc(talloc_tos(),
2568 dirfsp,
2569 &smb_fname_rel,
2570 &target);
2573 if (!NT_STATUS_IS_OK(status)) {
2574 DBG_DEBUG("readlink_talloc() failed: %s\n", nt_errstr(status));
2575 return status;
2578 needed = talloc_get_size(target) * 2;
2580 *ppdata = SMB_REALLOC(*ppdata, needed);
2581 if (*ppdata == NULL) {
2582 TALLOC_FREE(target);
2583 return NT_STATUS_NO_MEMORY;
2585 pdata = *ppdata;
2587 status = srvstr_push(
2588 pdata,
2589 req->flags2,
2590 pdata,
2591 target,
2592 needed,
2593 STR_TERMINATE,
2594 &len);
2595 TALLOC_FREE(target);
2596 if (!NT_STATUS_IS_OK(status)) {
2597 return status;
2599 *ptotal_data = len;
2601 return NT_STATUS_OK;
2604 static void call_trans2qpathinfo(
2605 connection_struct *conn,
2606 struct smb_request *req,
2607 char **pparams,
2608 int total_params,
2609 char **ppdata,
2610 int total_data,
2611 unsigned int max_data_bytes)
2613 char *params = *pparams;
2614 uint16_t info_level;
2615 struct smb_filename *smb_fname = NULL;
2616 bool delete_pending = False;
2617 struct timespec write_time_ts = { .tv_sec = 0, };
2618 struct files_struct *dirfsp = NULL;
2619 files_struct *fsp = NULL;
2620 char *fname = NULL;
2621 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2622 NTTIME twrp = 0;
2623 bool info_level_handled;
2624 NTSTATUS status = NT_STATUS_OK;
2626 if (!params) {
2627 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2628 return;
2632 /* qpathinfo */
2633 if (total_params < 7) {
2634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2635 return;
2638 info_level = SVAL(params,0);
2640 DBG_NOTICE("TRANSACT2_QPATHINFO: level = %d\n", info_level);
2642 if (INFO_LEVEL_IS_UNIX(info_level)) {
2643 if (!lp_smb1_unix_extensions()) {
2644 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2645 return;
2647 if (!req->posix_pathnames) {
2648 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2649 return;
2653 if (req->posix_pathnames) {
2654 srvstr_get_path_posix(req,
2655 params,
2656 req->flags2,
2657 &fname,
2658 &params[6],
2659 total_params - 6,
2660 STR_TERMINATE,
2661 &status);
2662 } else {
2663 srvstr_get_path(req,
2664 params,
2665 req->flags2,
2666 &fname,
2667 &params[6],
2668 total_params - 6,
2669 STR_TERMINATE,
2670 &status);
2672 if (!NT_STATUS_IS_OK(status)) {
2673 reply_nterror(req, status);
2674 return;
2677 if (ucf_flags & UCF_GMT_PATHNAME) {
2678 extract_snapshot_token(fname, &twrp);
2680 status = smb1_strip_dfs_path(req, &ucf_flags, &fname);
2681 if (!NT_STATUS_IS_OK(status)) {
2682 reply_nterror(req, status);
2683 return;
2685 status = filename_convert_dirfsp(req,
2686 conn,
2687 fname,
2688 ucf_flags,
2689 twrp,
2690 &dirfsp,
2691 &smb_fname);
2692 if (!NT_STATUS_IS_OK(status)) {
2693 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2694 reply_botherror(req,
2695 NT_STATUS_PATH_NOT_COVERED,
2696 ERRSRV, ERRbadpath);
2697 return;
2699 reply_nterror(req, status);
2700 return;
2704 * qpathinfo must operate on an existing file, so we
2705 * can exit early if filename_convert_dirfsp() returned the
2706 * "new file" NT_STATUS_OK, !VALID_STAT case.
2709 if (!VALID_STAT(smb_fname->st)) {
2710 reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2711 return;
2714 fsp = smb_fname->fsp;
2716 /* If this is a stream, check if there is a delete_pending. */
2717 if (fsp_is_alternate_stream(fsp)) {
2719 struct files_struct *base_fsp = fsp->base_fsp;
2721 get_file_infos(base_fsp->file_id,
2722 base_fsp->name_hash,
2723 &delete_pending,
2724 NULL);
2725 if (delete_pending) {
2726 reply_nterror(req, NT_STATUS_DELETE_PENDING);
2727 return;
2731 if (fsp_getinfo_ask_sharemode(fsp)) {
2732 get_file_infos(fsp->file_id,
2733 fsp->name_hash,
2734 &delete_pending,
2735 &write_time_ts);
2738 if (delete_pending) {
2739 reply_nterror(req, NT_STATUS_DELETE_PENDING);
2740 return;
2743 info_level_handled = true; /* Untouched in switch cases below */
2745 switch (info_level) {
2747 default:
2748 info_level_handled = false;
2749 break;
2751 case SMB_QUERY_FILE_UNIX_BASIC:
2752 status = smb_q_unix_basic(
2753 conn,
2754 req,
2755 smb_fname,
2756 smb_fname->fsp,
2757 ppdata,
2758 &total_data);
2759 break;
2761 case SMB_QUERY_FILE_UNIX_INFO2:
2762 status = smb_q_unix_info2(
2763 conn,
2764 req,
2765 smb_fname,
2766 smb_fname->fsp,
2767 ppdata,
2768 &total_data);
2769 break;
2771 case SMB_QUERY_POSIX_ACL:
2772 status = smb_q_posix_acl(
2773 conn,
2774 req,
2775 smb_fname,
2776 smb_fname->fsp,
2777 ppdata,
2778 &total_data);
2779 break;
2781 case SMB_QUERY_FILE_UNIX_LINK:
2782 status = smb_q_posix_symlink(
2783 conn,
2784 req,
2785 dirfsp,
2786 smb_fname,
2787 ppdata,
2788 &total_data);
2789 break;
2792 if (info_level_handled) {
2793 handle_trans2qfilepathinfo_result(
2794 conn,
2795 req,
2796 info_level,
2797 status,
2798 *ppdata,
2799 total_data,
2800 total_data,
2801 max_data_bytes);
2802 return;
2805 call_trans2qfilepathinfo(
2806 conn,
2807 req,
2808 TRANSACT2_QPATHINFO,
2809 info_level,
2810 smb_fname,
2811 fsp,
2812 false,
2813 write_time_ts,
2814 pparams,
2815 total_params,
2816 ppdata,
2817 total_data,
2818 max_data_bytes);
2821 static NTSTATUS smb_q_posix_lock(
2822 struct connection_struct *conn,
2823 struct smb_request *req,
2824 struct files_struct *fsp,
2825 char **ppdata,
2826 int *ptotal_data)
2828 char *pdata = *ppdata;
2829 int total_data = *ptotal_data;
2830 uint64_t count;
2831 uint64_t offset;
2832 uint64_t smblctx;
2833 enum brl_type lock_type;
2834 NTSTATUS status;
2836 if (fsp->fsp_flags.is_pathref || (fsp_get_io_fd(fsp) == -1)) {
2837 return NT_STATUS_INVALID_HANDLE;
2840 if (total_data != POSIX_LOCK_DATA_SIZE) {
2841 return NT_STATUS_INVALID_PARAMETER;
2844 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
2845 case POSIX_LOCK_TYPE_READ:
2846 lock_type = READ_LOCK;
2847 break;
2848 case POSIX_LOCK_TYPE_WRITE:
2849 lock_type = WRITE_LOCK;
2850 break;
2851 case POSIX_LOCK_TYPE_UNLOCK:
2852 default:
2853 /* There's no point in asking for an unlock... */
2854 return NT_STATUS_INVALID_PARAMETER;
2857 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
2858 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
2859 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
2861 status = query_lock(
2862 fsp,
2863 &smblctx,
2864 &count,
2865 &offset,
2866 &lock_type,
2867 POSIX_LOCK);
2869 if (NT_STATUS_IS_OK(status)) {
2871 * For success we just return a copy of what we sent
2872 * with the lock type set to POSIX_LOCK_TYPE_UNLOCK.
2874 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
2875 return NT_STATUS_OK;
2878 if (!ERROR_WAS_LOCK_DENIED(status)) {
2879 DBG_DEBUG("query_lock() failed: %s\n", nt_errstr(status));
2880 return status;
2884 * Here we need to report who has it locked.
2887 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
2888 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
2889 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
2890 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
2891 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
2893 return NT_STATUS_OK;
2896 static void call_trans2qfileinfo(
2897 connection_struct *conn,
2898 struct smb_request *req,
2899 char **pparams,
2900 int total_params,
2901 char **ppdata,
2902 int total_data,
2903 unsigned int max_data_bytes)
2905 char *params = *pparams;
2906 uint16_t info_level;
2907 struct smb_filename *smb_fname = NULL;
2908 bool delete_pending = False;
2909 struct timespec write_time_ts = { .tv_sec = 0, };
2910 files_struct *fsp = NULL;
2911 struct file_id fileid;
2912 bool info_level_handled;
2913 NTSTATUS status = NT_STATUS_OK;
2914 int ret;
2916 if (params == NULL) {
2917 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2918 return;
2921 if (total_params < 4) {
2922 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2923 return;
2926 fsp = file_fsp(req, SVAL(params,0));
2927 info_level = SVAL(params,2);
2929 if (IS_IPC(conn)) {
2930 call_trans2qpipeinfo(
2931 conn,
2932 req,
2933 fsp,
2934 info_level,
2935 TRANSACT2_QFILEINFO,
2936 pparams,
2937 total_params,
2938 ppdata,
2939 total_data,
2940 max_data_bytes);
2941 return;
2944 DBG_NOTICE("TRANSACT2_QFILEINFO: level = %d\n", info_level);
2946 if (INFO_LEVEL_IS_UNIX(info_level)) {
2947 if (!lp_smb1_unix_extensions()) {
2948 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2949 return;
2951 if (!req->posix_pathnames) {
2952 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2953 return;
2957 /* Initial check for valid fsp ptr. */
2958 if (!check_fsp_open(conn, req, fsp)) {
2959 return;
2962 smb_fname = fsp->fsp_name;
2964 if(fsp->fake_file_handle) {
2966 * This is actually for the QUOTA_FAKE_FILE --metze
2969 /* We know this name is ok, it's already passed the checks. */
2971 } else if(fsp_get_pathref_fd(fsp) == -1) {
2973 * This is actually a QFILEINFO on a directory
2974 * handle (returned from an NT SMB). NT5.0 seems
2975 * to do this call. JRA.
2977 ret = vfs_stat(conn, smb_fname);
2978 if (ret != 0) {
2979 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
2980 smb_fname_str_dbg(smb_fname),
2981 strerror(errno));
2982 reply_nterror(req,
2983 map_nt_error_from_unix(errno));
2984 return;
2987 if (fsp_getinfo_ask_sharemode(fsp)) {
2988 fileid = vfs_file_id_from_sbuf(
2989 conn, &smb_fname->st);
2990 get_file_infos(fileid, fsp->name_hash,
2991 &delete_pending,
2992 &write_time_ts);
2994 } else {
2996 * Original code - this is an open file.
2998 status = vfs_stat_fsp(fsp);
2999 if (!NT_STATUS_IS_OK(status)) {
3000 DEBUG(3, ("fstat of %s failed (%s)\n",
3001 fsp_fnum_dbg(fsp), nt_errstr(status)));
3002 reply_nterror(req, status);
3003 return;
3005 if (fsp_getinfo_ask_sharemode(fsp)) {
3006 fileid = vfs_file_id_from_sbuf(
3007 conn, &smb_fname->st);
3008 get_file_infos(fileid, fsp->name_hash,
3009 &delete_pending,
3010 &write_time_ts);
3014 info_level_handled = true; /* Untouched in switch cases below */
3016 switch (info_level) {
3018 default:
3019 info_level_handled = false;
3020 break;
3022 case SMB_QUERY_POSIX_LOCK:
3023 status = smb_q_posix_lock(conn, req, fsp, ppdata, &total_data);
3024 break;
3026 case SMB_QUERY_FILE_UNIX_BASIC:
3027 status = smb_q_unix_basic(
3028 conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3029 break;
3031 case SMB_QUERY_FILE_UNIX_INFO2:
3032 status = smb_q_unix_info2(
3033 conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3034 break;
3036 case SMB_QUERY_POSIX_ACL:
3037 status = smb_q_posix_acl(
3038 conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3039 break;
3042 if (info_level_handled) {
3043 handle_trans2qfilepathinfo_result(
3044 conn,
3045 req,
3046 info_level,
3047 status,
3048 *ppdata,
3049 total_data,
3050 total_data,
3051 max_data_bytes);
3052 return;
3055 call_trans2qfilepathinfo(
3056 conn,
3057 req,
3058 TRANSACT2_QFILEINFO,
3059 info_level,
3060 smb_fname,
3061 fsp,
3062 delete_pending,
3063 write_time_ts,
3064 pparams,
3065 total_params,
3066 ppdata,
3067 total_data,
3068 max_data_bytes);
3071 static void handle_trans2setfilepathinfo_result(
3072 connection_struct *conn,
3073 struct smb_request *req,
3074 uint16_t info_level,
3075 NTSTATUS status,
3076 char *pdata,
3077 int data_return_size,
3078 unsigned int max_data_bytes)
3080 char params[2] = { 0, 0, };
3082 if (NT_STATUS_IS_OK(status)) {
3083 send_trans2_replies(
3084 conn,
3085 req,
3086 NT_STATUS_OK,
3087 params,
3089 pdata,
3090 data_return_size,
3091 max_data_bytes);
3092 return;
3095 if (open_was_deferred(req->xconn, req->mid)) {
3096 /* We have re-scheduled this call. */
3097 return;
3100 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3101 bool ok = defer_smb1_sharing_violation(req);
3102 if (ok) {
3103 return;
3107 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
3108 /* We have re-scheduled this call. */
3109 return;
3112 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3113 reply_botherror(
3114 req,
3115 NT_STATUS_PATH_NOT_COVERED,
3116 ERRSRV,
3117 ERRbadpath);
3118 return;
3121 if (info_level == SMB_POSIX_PATH_OPEN) {
3122 reply_openerror(req, status);
3123 return;
3126 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
3128 * Invalid EA name needs to return 2 param bytes,
3129 * not a zero-length error packet.
3132 send_trans2_replies(
3133 conn,
3134 req,
3135 status,
3136 params,
3138 NULL,
3140 max_data_bytes);
3141 return;
3144 reply_nterror(req, status);
3147 /****************************************************************************
3148 Create a directory with POSIX semantics.
3149 ****************************************************************************/
3151 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
3152 struct smb_request *req,
3153 char **ppdata,
3154 int total_data,
3155 struct smb_filename *smb_fname,
3156 int *pdata_return_size)
3158 NTSTATUS status = NT_STATUS_OK;
3159 uint32_t raw_unixmode = 0;
3160 mode_t unixmode = (mode_t)0;
3161 files_struct *fsp = NULL;
3162 uint16_t info_level_return = 0;
3163 int info;
3164 char *pdata = *ppdata;
3165 struct smb2_create_blobs *posx = NULL;
3167 if (total_data < 18) {
3168 return NT_STATUS_INVALID_PARAMETER;
3171 raw_unixmode = IVAL(pdata,8);
3172 /* Next 4 bytes are not yet defined. */
3174 status = unix_perms_from_wire(conn,
3175 &smb_fname->st,
3176 raw_unixmode,
3177 &unixmode);
3178 if (!NT_STATUS_IS_OK(status)) {
3179 return status;
3181 unixmode = apply_conf_dir_mask(conn, unixmode);
3183 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
3184 if (!NT_STATUS_IS_OK(status)) {
3185 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3186 nt_errstr(status));
3187 return status;
3190 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
3191 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
3193 status = SMB_VFS_CREATE_FILE(
3194 conn, /* conn */
3195 req, /* req */
3196 NULL, /* dirfsp */
3197 smb_fname, /* fname */
3198 FILE_READ_ATTRIBUTES, /* access_mask */
3199 FILE_SHARE_NONE, /* share_access */
3200 FILE_CREATE, /* create_disposition*/
3201 FILE_DIRECTORY_FILE, /* create_options */
3202 0, /* file_attributes */
3203 0, /* oplock_request */
3204 NULL, /* lease */
3205 0, /* allocation_size */
3206 0, /* private_flags */
3207 NULL, /* sd */
3208 NULL, /* ea_list */
3209 &fsp, /* result */
3210 &info, /* pinfo */
3211 posx, /* in_context_blobs */
3212 NULL); /* out_context_blobs */
3214 TALLOC_FREE(posx);
3216 if (NT_STATUS_IS_OK(status)) {
3217 close_file_free(req, &fsp, NORMAL_CLOSE);
3220 info_level_return = SVAL(pdata,16);
3222 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
3223 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
3224 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
3225 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
3226 } else {
3227 *pdata_return_size = 12;
3230 /* Realloc the data size */
3231 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
3232 if (*ppdata == NULL) {
3233 *pdata_return_size = 0;
3234 return NT_STATUS_NO_MEMORY;
3236 pdata = *ppdata;
3238 SSVAL(pdata,0,NO_OPLOCK_RETURN);
3239 SSVAL(pdata,2,0); /* No fnum. */
3240 SIVAL(pdata,4,info); /* Was directory created. */
3242 switch (info_level_return) {
3243 case SMB_QUERY_FILE_UNIX_BASIC:
3244 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
3245 SSVAL(pdata,10,0); /* Padding. */
3246 store_file_unix_basic(conn, pdata + 12, fsp,
3247 &smb_fname->st);
3248 break;
3249 case SMB_QUERY_FILE_UNIX_INFO2:
3250 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
3251 SSVAL(pdata,10,0); /* Padding. */
3252 store_file_unix_basic_info2(conn, pdata + 12, fsp,
3253 &smb_fname->st);
3254 break;
3255 default:
3256 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
3257 SSVAL(pdata,10,0); /* Padding. */
3258 break;
3261 return status;
3264 /****************************************************************************
3265 Open/Create a file with POSIX semantics.
3266 ****************************************************************************/
3268 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
3269 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
3271 static NTSTATUS smb_posix_open(connection_struct *conn,
3272 struct smb_request *req,
3273 char **ppdata,
3274 int total_data,
3275 struct files_struct *dirfsp,
3276 struct smb_filename *smb_fname,
3277 int *pdata_return_size)
3279 bool extended_oplock_granted = False;
3280 char *pdata = *ppdata;
3281 uint32_t flags = 0;
3282 uint32_t wire_open_mode = 0;
3283 uint32_t raw_unixmode = 0;
3284 uint32_t attributes = 0;
3285 uint32_t create_disp = 0;
3286 uint32_t access_mask = 0;
3287 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
3288 NTSTATUS status = NT_STATUS_OK;
3289 mode_t unixmode = (mode_t)0;
3290 files_struct *fsp = NULL;
3291 int oplock_request = 0;
3292 int info = 0;
3293 uint16_t info_level_return = 0;
3294 struct smb2_create_blobs *posx = NULL;
3296 if (total_data < 18) {
3297 return NT_STATUS_INVALID_PARAMETER;
3300 flags = IVAL(pdata,0);
3301 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
3302 if (oplock_request) {
3303 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
3306 wire_open_mode = IVAL(pdata,4);
3308 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
3309 return smb_posix_mkdir(conn, req,
3310 ppdata,
3311 total_data,
3312 smb_fname,
3313 pdata_return_size);
3316 switch (wire_open_mode & SMB_ACCMODE) {
3317 case SMB_O_RDONLY:
3318 access_mask = SMB_O_RDONLY_MAPPING;
3319 break;
3320 case SMB_O_WRONLY:
3321 access_mask = SMB_O_WRONLY_MAPPING;
3322 break;
3323 case SMB_O_RDWR:
3324 access_mask = (SMB_O_RDONLY_MAPPING|
3325 SMB_O_WRONLY_MAPPING);
3326 break;
3327 default:
3328 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
3329 (unsigned int)wire_open_mode ));
3330 return NT_STATUS_INVALID_PARAMETER;
3333 wire_open_mode &= ~SMB_ACCMODE;
3335 /* First take care of O_CREAT|O_EXCL interactions. */
3336 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
3337 case (SMB_O_CREAT | SMB_O_EXCL):
3338 /* File exists fail. File not exist create. */
3339 create_disp = FILE_CREATE;
3340 break;
3341 case SMB_O_CREAT:
3342 /* File exists open. File not exist create. */
3343 create_disp = FILE_OPEN_IF;
3344 break;
3345 case SMB_O_EXCL:
3346 /* O_EXCL on its own without O_CREAT is undefined.
3347 We deliberately ignore it as some versions of
3348 Linux CIFSFS can send a bare O_EXCL on the
3349 wire which other filesystems in the kernel
3350 ignore. See bug 9519 for details. */
3352 /* Fallthrough. */
3354 case 0:
3355 /* File exists open. File not exist fail. */
3356 create_disp = FILE_OPEN;
3357 break;
3358 default:
3359 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
3360 (unsigned int)wire_open_mode ));
3361 return NT_STATUS_INVALID_PARAMETER;
3364 /* Next factor in the effects of O_TRUNC. */
3365 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
3367 if (wire_open_mode & SMB_O_TRUNC) {
3368 switch (create_disp) {
3369 case FILE_CREATE:
3370 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
3371 /* Leave create_disp alone as
3372 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
3374 /* File exists fail. File not exist create. */
3375 break;
3376 case FILE_OPEN_IF:
3377 /* SMB_O_CREAT | SMB_O_TRUNC */
3378 /* File exists overwrite. File not exist create. */
3379 create_disp = FILE_OVERWRITE_IF;
3380 break;
3381 case FILE_OPEN:
3382 /* SMB_O_TRUNC */
3383 /* File exists overwrite. File not exist fail. */
3384 create_disp = FILE_OVERWRITE;
3385 break;
3386 default:
3387 /* Cannot get here. */
3388 smb_panic("smb_posix_open: logic error");
3389 return NT_STATUS_INVALID_PARAMETER;
3393 raw_unixmode = IVAL(pdata,8);
3394 /* Next 4 bytes are not yet defined. */
3396 status = unix_perms_from_wire(conn,
3397 &smb_fname->st,
3398 raw_unixmode,
3399 &unixmode);
3401 if (!NT_STATUS_IS_OK(status)) {
3402 return status;
3404 if (!VALID_STAT(smb_fname->st)) {
3405 unixmode = apply_conf_dir_mask(conn, unixmode);
3408 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
3409 if (!NT_STATUS_IS_OK(status)) {
3410 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3411 nt_errstr(status));
3412 return status;
3415 if (wire_open_mode & SMB_O_SYNC) {
3416 create_options |= FILE_WRITE_THROUGH;
3418 if (wire_open_mode & SMB_O_APPEND) {
3419 access_mask |= FILE_APPEND_DATA;
3421 if (wire_open_mode & SMB_O_DIRECT) {
3423 * BUG: this doesn't work anymore since
3424 * e0814dc5082dd4ecca8a155e0ce24b073158fd92. But since
3425 * FILE_FLAG_NO_BUFFERING isn't used at all in the IO codepath,
3426 * it doesn't really matter.
3428 attributes |= FILE_FLAG_NO_BUFFERING;
3431 if ((wire_open_mode & SMB_O_DIRECTORY) ||
3432 VALID_STAT_OF_DIR(smb_fname->st)) {
3433 if (access_mask != SMB_O_RDONLY_MAPPING) {
3434 return NT_STATUS_FILE_IS_A_DIRECTORY;
3436 create_options &= ~FILE_NON_DIRECTORY_FILE;
3437 create_options |= FILE_DIRECTORY_FILE;
3440 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
3441 smb_fname_str_dbg(smb_fname),
3442 (unsigned int)wire_open_mode,
3443 (unsigned int)unixmode ));
3445 status = SMB_VFS_CREATE_FILE(
3446 conn, /* conn */
3447 req, /* req */
3448 dirfsp, /* dirfsp */
3449 smb_fname, /* fname */
3450 access_mask, /* access_mask */
3451 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
3452 FILE_SHARE_DELETE),
3453 create_disp, /* create_disposition*/
3454 create_options, /* create_options */
3455 attributes, /* file_attributes */
3456 oplock_request, /* oplock_request */
3457 NULL, /* lease */
3458 0, /* allocation_size */
3459 0, /* private_flags */
3460 NULL, /* sd */
3461 NULL, /* ea_list */
3462 &fsp, /* result */
3463 &info, /* pinfo */
3464 posx, /* in_context_blobs */
3465 NULL); /* out_context_blobs */
3467 TALLOC_FREE(posx);
3469 if (!NT_STATUS_IS_OK(status)) {
3470 return status;
3473 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3474 extended_oplock_granted = True;
3477 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3478 extended_oplock_granted = True;
3481 info_level_return = SVAL(pdata,16);
3483 /* Allocate the correct return size. */
3485 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
3486 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
3487 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
3488 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
3489 } else {
3490 *pdata_return_size = 12;
3493 /* Realloc the data size */
3494 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
3495 if (*ppdata == NULL) {
3496 close_file_free(req, &fsp, ERROR_CLOSE);
3497 *pdata_return_size = 0;
3498 return NT_STATUS_NO_MEMORY;
3500 pdata = *ppdata;
3502 if (extended_oplock_granted) {
3503 if (flags & REQUEST_BATCH_OPLOCK) {
3504 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
3505 } else {
3506 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
3508 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
3509 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
3510 } else {
3511 SSVAL(pdata,0,NO_OPLOCK_RETURN);
3514 SSVAL(pdata,2,fsp->fnum);
3515 SIVAL(pdata,4,info); /* Was file created etc. */
3517 switch (info_level_return) {
3518 case SMB_QUERY_FILE_UNIX_BASIC:
3519 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
3520 SSVAL(pdata,10,0); /* padding. */
3521 store_file_unix_basic(conn, pdata + 12, fsp,
3522 &smb_fname->st);
3523 break;
3524 case SMB_QUERY_FILE_UNIX_INFO2:
3525 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
3526 SSVAL(pdata,10,0); /* padding. */
3527 store_file_unix_basic_info2(conn, pdata + 12, fsp,
3528 &smb_fname->st);
3529 break;
3530 default:
3531 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
3532 SSVAL(pdata,10,0); /* padding. */
3533 break;
3535 return NT_STATUS_OK;
3538 /****************************************************************************
3539 Delete a file with POSIX semantics.
3540 ****************************************************************************/
3542 struct smb_posix_unlink_state {
3543 struct smb_filename *smb_fname;
3544 struct files_struct *fsp;
3545 NTSTATUS status;
3548 static void smb_posix_unlink_locked(struct share_mode_lock *lck,
3549 void *private_data)
3551 struct smb_posix_unlink_state *state = private_data;
3552 char del = 1;
3553 bool other_nonposix_opens;
3555 other_nonposix_opens = has_other_nonposix_opens(lck, state->fsp);
3556 if (other_nonposix_opens) {
3557 /* Fail with sharing violation. */
3558 state->status = NT_STATUS_SHARING_VIOLATION;
3559 return;
3563 * Set the delete on close.
3565 state->status = smb_set_file_disposition_info(state->fsp->conn,
3566 &del,
3568 state->fsp,
3569 state->smb_fname);
3572 static NTSTATUS smb_posix_unlink(connection_struct *conn,
3573 struct smb_request *req,
3574 const char *pdata,
3575 int total_data,
3576 struct files_struct *dirfsp,
3577 struct smb_filename *smb_fname)
3579 struct smb_posix_unlink_state state = {};
3580 NTSTATUS status = NT_STATUS_OK;
3581 files_struct *fsp = NULL;
3582 uint16_t flags = 0;
3583 int info = 0;
3584 int create_options = FILE_OPEN_REPARSE_POINT;
3585 struct smb2_create_blobs *posx = NULL;
3587 if (!CAN_WRITE(conn)) {
3588 return NT_STATUS_DOS(ERRSRV, ERRaccess);
3591 if (total_data < 2) {
3592 return NT_STATUS_INVALID_PARAMETER;
3595 flags = SVAL(pdata,0);
3597 if (!VALID_STAT(smb_fname->st)) {
3598 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3601 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
3602 !VALID_STAT_OF_DIR(smb_fname->st)) {
3603 return NT_STATUS_NOT_A_DIRECTORY;
3606 DEBUG(10,("smb_posix_unlink: %s %s\n",
3607 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
3608 smb_fname_str_dbg(smb_fname)));
3610 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
3611 create_options |= FILE_DIRECTORY_FILE;
3614 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
3615 if (!NT_STATUS_IS_OK(status)) {
3616 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3617 nt_errstr(status));
3618 return status;
3621 status = SMB_VFS_CREATE_FILE(
3622 conn, /* conn */
3623 req, /* req */
3624 dirfsp, /* dirfsp */
3625 smb_fname, /* fname */
3626 DELETE_ACCESS, /* access_mask */
3627 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
3628 FILE_SHARE_DELETE),
3629 FILE_OPEN, /* create_disposition*/
3630 create_options, /* create_options */
3631 0, /* file_attributes */
3632 0, /* oplock_request */
3633 NULL, /* lease */
3634 0, /* allocation_size */
3635 0, /* private_flags */
3636 NULL, /* sd */
3637 NULL, /* ea_list */
3638 &fsp, /* result */
3639 &info, /* pinfo */
3640 posx, /* in_context_blobs */
3641 NULL); /* out_context_blobs */
3643 TALLOC_FREE(posx);
3645 if (!NT_STATUS_IS_OK(status)) {
3646 return status;
3650 * Don't lie to client. If we can't really delete due to
3651 * non-POSIX opens return SHARING_VIOLATION.
3654 state = (struct smb_posix_unlink_state) {
3655 .smb_fname = smb_fname,
3656 .fsp = fsp,
3659 status = share_mode_do_locked_vfs_allowed(fsp->file_id,
3660 smb_posix_unlink_locked,
3661 &state);
3662 if (!NT_STATUS_IS_OK(status)) {
3663 DBG_ERR("share_mode_do_locked_vfs_allowed(%s) failed - %s\n",
3664 fsp_str_dbg(fsp), nt_errstr(status));
3665 close_file_free(req, &fsp, NORMAL_CLOSE);
3666 return NT_STATUS_INVALID_PARAMETER;
3669 status = state.status;
3670 if (!NT_STATUS_IS_OK(status)) {
3671 close_file_free(req, &fsp, NORMAL_CLOSE);
3672 return status;
3674 return close_file_free(req, &fsp, NORMAL_CLOSE);
3677 /****************************************************************************
3678 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
3679 ****************************************************************************/
3681 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
3682 struct smb_request *req,
3683 const char *pdata,
3684 int total_data,
3685 struct files_struct *dirfsp,
3686 struct smb_filename *new_smb_fname)
3688 char *link_target = NULL;
3689 struct smb_filename target_fname;
3690 TALLOC_CTX *ctx = talloc_tos();
3691 struct smb_filename new_smb_fname_rel = {};
3692 char *slash = NULL;
3693 NTSTATUS status;
3694 int ret;
3696 if (!CAN_WRITE(conn)) {
3697 return NT_STATUS_DOS(ERRSRV, ERRaccess);
3700 /* Set a symbolic link. */
3701 /* Don't allow this if follow links is false. */
3703 if (total_data == 0) {
3704 return NT_STATUS_INVALID_PARAMETER;
3707 if (!lp_follow_symlinks(SNUM(conn))) {
3708 return NT_STATUS_ACCESS_DENIED;
3711 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
3712 total_data, STR_TERMINATE);
3714 if (!link_target) {
3715 return NT_STATUS_INVALID_PARAMETER;
3718 target_fname = (struct smb_filename) {
3719 .base_name = link_target,
3722 /* Removes @GMT tokens if any */
3723 status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
3724 if (!NT_STATUS_IS_OK(status)) {
3725 return status;
3728 DBG_DEBUG("SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3729 new_smb_fname->base_name, link_target);
3731 new_smb_fname_rel = *new_smb_fname;
3732 slash = strrchr_m(new_smb_fname_rel.base_name, '/');
3733 if (slash != NULL) {
3734 new_smb_fname_rel.base_name = slash + 1;
3737 ret = SMB_VFS_SYMLINKAT(conn,
3738 &target_fname,
3739 dirfsp,
3740 &new_smb_fname_rel);
3741 if (ret != 0) {
3742 return map_nt_error_from_unix(errno);
3745 return NT_STATUS_OK;
3748 /****************************************************************************
3749 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
3750 ****************************************************************************/
3752 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
3753 struct smb_request *req,
3754 const char *pdata, int total_data,
3755 struct smb_filename *smb_fname_new)
3757 char *oldname = NULL;
3758 struct files_struct *src_dirfsp = NULL;
3759 struct smb_filename *smb_fname_old = NULL;
3760 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
3761 NTTIME old_twrp = 0;
3762 TALLOC_CTX *ctx = talloc_tos();
3763 NTSTATUS status = NT_STATUS_OK;
3765 if (!CAN_WRITE(conn)) {
3766 return NT_STATUS_DOS(ERRSRV, ERRaccess);
3769 /* Set a hard link. */
3770 if (total_data == 0) {
3771 return NT_STATUS_INVALID_PARAMETER;
3774 if (req->posix_pathnames) {
3775 srvstr_get_path_posix(ctx,
3776 pdata,
3777 req->flags2,
3778 &oldname,
3779 pdata,
3780 total_data,
3781 STR_TERMINATE,
3782 &status);
3783 } else {
3784 srvstr_get_path(ctx,
3785 pdata,
3786 req->flags2,
3787 &oldname,
3788 pdata,
3789 total_data,
3790 STR_TERMINATE,
3791 &status);
3793 if (!NT_STATUS_IS_OK(status)) {
3794 return status;
3797 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3798 smb_fname_str_dbg(smb_fname_new), oldname));
3800 if (ucf_flags & UCF_GMT_PATHNAME) {
3801 extract_snapshot_token(oldname, &old_twrp);
3803 status = smb1_strip_dfs_path(ctx, &ucf_flags, &oldname);
3804 if (!NT_STATUS_IS_OK(status)) {
3805 return status;
3807 status = filename_convert_dirfsp(ctx,
3808 conn,
3809 oldname,
3810 ucf_flags,
3811 old_twrp,
3812 &src_dirfsp,
3813 &smb_fname_old);
3814 if (!NT_STATUS_IS_OK(status)) {
3815 return status;
3818 return hardlink_internals(ctx,
3819 conn,
3820 req,
3821 false,
3822 smb_fname_old,
3823 smb_fname_new);
3826 /****************************************************************************
3827 Allow a UNIX info mknod.
3828 ****************************************************************************/
3830 static NTSTATUS smb_unix_mknod(connection_struct *conn,
3831 const char *pdata,
3832 int total_data,
3833 struct files_struct *dirfsp,
3834 const struct smb_filename *smb_fname)
3836 uint32_t file_type = IVAL(pdata,56);
3837 #if defined(HAVE_MAKEDEV)
3838 uint32_t dev_major = IVAL(pdata,60);
3839 uint32_t dev_minor = IVAL(pdata,68);
3840 #endif
3841 SMB_DEV_T dev = (SMB_DEV_T)0;
3842 uint32_t raw_unixmode = IVAL(pdata,84);
3843 NTSTATUS status;
3844 mode_t unixmode;
3845 int ret;
3846 struct smb_filename *parent_fname = NULL;
3847 struct smb_filename *atname = NULL;
3849 if (total_data < 100) {
3850 return NT_STATUS_INVALID_PARAMETER;
3853 status = unix_perms_from_wire(conn,
3854 &smb_fname->st,
3855 raw_unixmode,
3856 &unixmode);
3857 if (!NT_STATUS_IS_OK(status)) {
3858 return status;
3860 unixmode = apply_conf_file_mask(conn, unixmode);
3862 #if defined(HAVE_MAKEDEV)
3863 dev = makedev(dev_major, dev_minor);
3864 #endif
3866 switch (file_type) {
3867 /* We can't create other objects here. */
3868 case UNIX_TYPE_FILE:
3869 case UNIX_TYPE_DIR:
3870 case UNIX_TYPE_SYMLINK:
3871 return NT_STATUS_ACCESS_DENIED;
3872 #if defined(S_IFIFO)
3873 case UNIX_TYPE_FIFO:
3874 unixmode |= S_IFIFO;
3875 break;
3876 #endif
3877 #if defined(S_IFSOCK)
3878 case UNIX_TYPE_SOCKET:
3879 unixmode |= S_IFSOCK;
3880 break;
3881 #endif
3882 #if defined(S_IFCHR)
3883 case UNIX_TYPE_CHARDEV:
3884 /* This is only allowed for root. */
3885 if (get_current_uid(conn) != sec_initial_uid()) {
3886 return NT_STATUS_ACCESS_DENIED;
3888 unixmode |= S_IFCHR;
3889 break;
3890 #endif
3891 #if defined(S_IFBLK)
3892 case UNIX_TYPE_BLKDEV:
3893 if (get_current_uid(conn) != sec_initial_uid()) {
3894 return NT_STATUS_ACCESS_DENIED;
3896 unixmode |= S_IFBLK;
3897 break;
3898 #endif
3899 default:
3900 return NT_STATUS_INVALID_PARAMETER;
3903 DBG_DEBUG("SMB_SET_FILE_UNIX_BASIC doing mknod dev "
3904 "%ju mode 0%o for file %s\n",
3905 (uintmax_t)dev,
3906 (unsigned int)unixmode,
3907 smb_fname_str_dbg(smb_fname));
3909 status = SMB_VFS_PARENT_PATHNAME(dirfsp->conn,
3910 talloc_tos(),
3911 smb_fname,
3912 &parent_fname,
3913 &atname);
3914 if (!NT_STATUS_IS_OK(status)) {
3915 return status;
3918 /* Ok - do the mknod. */
3919 ret = SMB_VFS_MKNODAT(conn,
3920 dirfsp,
3921 atname,
3922 unixmode,
3923 dev);
3925 if (ret != 0) {
3926 TALLOC_FREE(parent_fname);
3927 return map_nt_error_from_unix(errno);
3930 /* If any of the other "set" calls fail we
3931 * don't want to end up with a half-constructed mknod.
3934 if (lp_inherit_permissions(SNUM(conn))) {
3935 inherit_access_posix_acl(conn,
3936 dirfsp,
3937 smb_fname,
3938 unixmode);
3940 TALLOC_FREE(parent_fname);
3942 return NT_STATUS_OK;
3945 /****************************************************************************
3946 Deal with SMB_SET_FILE_UNIX_BASIC.
3947 ****************************************************************************/
3949 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
3950 struct smb_request *req,
3951 const char *pdata,
3952 int total_data,
3953 struct files_struct *dirfsp,
3954 files_struct *fsp,
3955 struct smb_filename *smb_fname)
3957 struct smb_file_time ft;
3958 uint32_t raw_unixmode;
3959 mode_t unixmode;
3960 off_t size = 0;
3961 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3962 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3963 NTSTATUS status = NT_STATUS_OK;
3964 files_struct *all_fsps = NULL;
3965 bool modify_mtime = true;
3966 struct file_id id;
3967 SMB_STRUCT_STAT sbuf;
3969 if (!CAN_WRITE(conn)) {
3970 return NT_STATUS_DOS(ERRSRV, ERRaccess);
3973 init_smb_file_time(&ft);
3975 if (total_data < 100) {
3976 return NT_STATUS_INVALID_PARAMETER;
3979 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3980 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3981 size=IVAL(pdata,0); /* first 8 Bytes are size */
3982 size |= (((off_t)IVAL(pdata,4)) << 32);
3985 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
3986 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
3987 set_owner = (uid_t)IVAL(pdata,40);
3988 set_grp = (gid_t)IVAL(pdata,48);
3989 raw_unixmode = IVAL(pdata,84);
3991 status = unix_perms_from_wire(conn,
3992 &smb_fname->st,
3993 raw_unixmode,
3994 &unixmode);
3995 if (!NT_STATUS_IS_OK(status)) {
3996 return status;
3998 if (!VALID_STAT(smb_fname->st)) {
3999 unixmode = apply_conf_file_mask(conn, unixmode);
4002 DBG_DEBUG("SMB_SET_FILE_UNIX_BASIC: name = "
4003 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4004 smb_fname_str_dbg(smb_fname),
4005 (double)size,
4006 (unsigned int)set_owner,
4007 (unsigned int)set_grp,
4008 (int)raw_unixmode);
4010 sbuf = smb_fname->st;
4012 if (!VALID_STAT(sbuf)) {
4014 * The only valid use of this is to create character and block
4015 * devices, and named pipes. This is deprecated (IMHO) and
4016 * a new info level should be used for mknod. JRA.
4019 if (dirfsp == NULL) {
4020 return NT_STATUS_INVALID_PARAMETER;
4023 return smb_unix_mknod(conn,
4024 pdata,
4025 total_data,
4026 dirfsp,
4027 smb_fname);
4030 #if 1
4031 /* Horrible backwards compatibility hack as an old server bug
4032 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
4033 * */
4035 if (!size) {
4036 size = get_file_size_stat(&sbuf);
4038 #endif
4041 * Deal with the UNIX specific mode set.
4044 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4045 int ret;
4047 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
4048 DBG_WARNING("Can't set mode on symlink %s\n",
4049 smb_fname_str_dbg(smb_fname));
4050 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4053 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4054 "setting mode 0%o for file %s\n",
4055 (unsigned int)unixmode,
4056 smb_fname_str_dbg(smb_fname)));
4057 ret = SMB_VFS_FCHMOD(fsp, unixmode);
4058 if (ret != 0) {
4059 return map_nt_error_from_unix(errno);
4064 * Deal with the UNIX specific uid set.
4067 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
4068 (sbuf.st_ex_uid != set_owner)) {
4069 int ret;
4071 DBG_DEBUG("SMB_SET_FILE_UNIX_BASIC "
4072 "changing owner %u for path %s\n",
4073 (unsigned int)set_owner,
4074 smb_fname_str_dbg(smb_fname));
4076 if (fsp &&
4077 !fsp->fsp_flags.is_pathref &&
4078 fsp_get_io_fd(fsp) != -1)
4080 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
4081 } else {
4083 * UNIX extensions calls must always operate
4084 * on symlinks.
4086 ret = SMB_VFS_LCHOWN(conn, smb_fname,
4087 set_owner, (gid_t)-1);
4090 if (ret != 0) {
4091 status = map_nt_error_from_unix(errno);
4092 return status;
4097 * Deal with the UNIX specific gid set.
4100 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
4101 (sbuf.st_ex_gid != set_grp)) {
4102 int ret;
4104 DBG_DEBUG("SMB_SET_FILE_UNIX_BASIC "
4105 "changing group %u for file %s\n",
4106 (unsigned int)set_grp,
4107 smb_fname_str_dbg(smb_fname));
4108 if (fsp &&
4109 !fsp->fsp_flags.is_pathref &&
4110 fsp_get_io_fd(fsp) != -1)
4112 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
4113 } else {
4115 * UNIX extensions calls must always operate
4116 * on symlinks.
4118 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
4119 set_grp);
4121 if (ret != 0) {
4122 status = map_nt_error_from_unix(errno);
4123 return status;
4127 /* Deal with any size changes. */
4129 if (S_ISREG(sbuf.st_ex_mode)) {
4130 status = smb_set_file_size(conn, req,
4131 fsp,
4132 smb_fname,
4133 &sbuf,
4134 size,
4135 false);
4136 if (!NT_STATUS_IS_OK(status)) {
4137 return status;
4141 /* Deal with any time changes. */
4142 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
4143 /* No change, don't cancel anything. */
4144 return status;
4147 id = vfs_file_id_from_sbuf(conn, &sbuf);
4148 for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
4149 all_fsps = file_find_di_next(all_fsps, true)) {
4151 * We're setting the time explicitly for UNIX.
4152 * Cancel any pending changes over all handles.
4154 all_fsps->fsp_flags.update_write_time_on_close = false;
4155 TALLOC_FREE(all_fsps->update_write_time_event);
4159 * Override the "setting_write_time"
4160 * parameter here as it almost does what
4161 * we need. Just remember if we modified
4162 * mtime and send the notify ourselves.
4164 if (is_omit_timespec(&ft.mtime)) {
4165 modify_mtime = false;
4168 status = smb_set_file_time(conn,
4169 fsp,
4170 smb_fname,
4171 &ft,
4172 false);
4173 if (modify_mtime) {
4174 notify_fname(conn,
4175 NOTIFY_ACTION_MODIFIED,
4176 FILE_NOTIFY_CHANGE_LAST_WRITE,
4177 smb_fname,
4178 NULL);
4180 return status;
4183 /****************************************************************************
4184 Deal with SMB_SET_FILE_UNIX_INFO2.
4185 ****************************************************************************/
4187 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
4188 struct smb_request *req,
4189 const char *pdata,
4190 int total_data,
4191 struct files_struct *dirfsp,
4192 files_struct *fsp,
4193 struct smb_filename *smb_fname)
4195 NTSTATUS status;
4196 uint32_t smb_fflags;
4197 uint32_t smb_fmask;
4199 if (!CAN_WRITE(conn)) {
4200 return NT_STATUS_DOS(ERRSRV, ERRaccess);
4203 if (total_data < 116) {
4204 return NT_STATUS_INVALID_PARAMETER;
4207 /* Start by setting all the fields that are common between UNIX_BASIC
4208 * and UNIX_INFO2.
4210 status = smb_set_file_unix_basic(conn,
4211 req,
4212 pdata,
4213 total_data,
4214 dirfsp,
4215 fsp,
4216 smb_fname);
4217 if (!NT_STATUS_IS_OK(status)) {
4218 return status;
4221 smb_fflags = IVAL(pdata, 108);
4222 smb_fmask = IVAL(pdata, 112);
4224 /* NB: We should only attempt to alter the file flags if the client
4225 * sends a non-zero mask.
4227 if (smb_fmask != 0) {
4228 int stat_fflags = 0;
4230 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
4231 smb_fmask, &stat_fflags)) {
4232 /* Client asked to alter a flag we don't understand. */
4233 return NT_STATUS_INVALID_PARAMETER;
4236 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
4237 DBG_WARNING("Can't change flags on symlink %s\n",
4238 smb_fname_str_dbg(smb_fname));
4239 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4241 if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) {
4242 return map_nt_error_from_unix(errno);
4246 /* XXX: need to add support for changing the create_time here. You
4247 * can do this for paths on Darwin with setattrlist(2). The right way
4248 * to hook this up is probably by extending the VFS utimes interface.
4251 return NT_STATUS_OK;
4254 /****************************************************************************
4255 Deal with SMB_SET_POSIX_ACL.
4256 ****************************************************************************/
4258 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4259 struct smb_request *req,
4260 const char *pdata,
4261 int total_data_in,
4262 files_struct *fsp,
4263 struct smb_filename *smb_fname)
4265 #if !defined(HAVE_POSIX_ACLS)
4266 return NT_STATUS_INVALID_LEVEL;
4267 #else
4268 uint16_t posix_acl_version;
4269 uint16_t num_file_acls;
4270 uint16_t num_def_acls;
4271 bool valid_file_acls = true;
4272 bool valid_def_acls = true;
4273 NTSTATUS status;
4274 unsigned int size_needed;
4275 unsigned int total_data;
4276 bool close_fsp = false;
4277 bool refuse;
4279 if (total_data_in < 0) {
4280 status = NT_STATUS_INVALID_PARAMETER;
4281 goto out;
4284 total_data = total_data_in;
4286 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4287 status = NT_STATUS_INVALID_PARAMETER;
4288 goto out;
4290 posix_acl_version = SVAL(pdata,0);
4291 num_file_acls = SVAL(pdata,2);
4292 num_def_acls = SVAL(pdata,4);
4294 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4295 valid_file_acls = false;
4296 num_file_acls = 0;
4299 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4300 valid_def_acls = false;
4301 num_def_acls = 0;
4304 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4305 status = NT_STATUS_INVALID_PARAMETER;
4306 goto out;
4309 /* Wrap checks. */
4310 if (num_file_acls + num_def_acls < num_file_acls) {
4311 status = NT_STATUS_INVALID_PARAMETER;
4312 goto out;
4315 size_needed = num_file_acls + num_def_acls;
4318 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4319 * than UINT_MAX, so check by division.
4321 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
4322 status = NT_STATUS_INVALID_PARAMETER;
4323 goto out;
4326 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
4327 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
4328 status = NT_STATUS_INVALID_PARAMETER;
4329 goto out;
4331 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
4333 if (total_data < size_needed) {
4334 status = NT_STATUS_INVALID_PARAMETER;
4335 goto out;
4339 * Ensure we always operate on a file descriptor, not just
4340 * the filename.
4342 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
4343 uint32_t access_mask = SEC_STD_WRITE_OWNER|
4344 SEC_STD_WRITE_DAC|
4345 SEC_STD_READ_CONTROL|
4346 FILE_READ_ATTRIBUTES|
4347 FILE_WRITE_ATTRIBUTES;
4349 status = get_posix_fsp(conn,
4350 req,
4351 smb_fname,
4352 access_mask,
4353 &fsp);
4355 if (!NT_STATUS_IS_OK(status)) {
4356 goto out;
4358 close_fsp = true;
4361 /* Here we know fsp != NULL */
4362 SMB_ASSERT(fsp != NULL);
4364 refuse = refuse_symlink_fsp(fsp);
4365 if (refuse) {
4366 status = NT_STATUS_ACCESS_DENIED;
4367 goto out;
4370 /* If we have a default acl, this *must* be a directory. */
4371 if (valid_def_acls && !fsp->fsp_flags.is_directory) {
4372 DBG_INFO("Can't set default acls on "
4373 "non-directory %s\n",
4374 fsp_str_dbg(fsp));
4375 return NT_STATUS_INVALID_HANDLE;
4378 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
4379 "num_def_acls = %"PRIu16"\n",
4380 fsp_str_dbg(fsp),
4381 num_file_acls,
4382 num_def_acls);
4384 /* Move pdata to the start of the file ACL entries. */
4385 pdata += SMB_POSIX_ACL_HEADER_SIZE;
4387 if (valid_file_acls) {
4388 status = set_unix_posix_acl(conn,
4389 fsp,
4390 num_file_acls,
4391 pdata);
4392 if (!NT_STATUS_IS_OK(status)) {
4393 goto out;
4397 /* Move pdata to the start of the default ACL entries. */
4398 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
4400 if (valid_def_acls) {
4401 status = set_unix_posix_default_acl(conn,
4402 fsp,
4403 num_def_acls,
4404 pdata);
4405 if (!NT_STATUS_IS_OK(status)) {
4406 goto out;
4410 status = NT_STATUS_OK;
4412 out:
4414 if (close_fsp) {
4415 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
4417 return status;
4418 #endif
4421 static void call_trans2setpathinfo(
4422 connection_struct *conn,
4423 struct smb_request *req,
4424 char **pparams,
4425 int total_params,
4426 char **ppdata,
4427 int total_data,
4428 unsigned int max_data_bytes)
4430 uint16_t info_level;
4431 struct smb_filename *smb_fname = NULL;
4432 struct files_struct *dirfsp = NULL;
4433 struct files_struct *fsp = NULL;
4434 char *params = *pparams;
4435 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4436 NTTIME twrp = 0;
4437 char *fname = NULL;
4438 bool info_level_handled;
4439 int data_return_size = 0;
4440 NTSTATUS status;
4442 if (params == NULL) {
4443 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4444 return;
4447 /* set path info */
4448 if (total_params < 7) {
4449 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4450 return;
4453 info_level = SVAL(params,0);
4455 if (INFO_LEVEL_IS_UNIX(info_level)) {
4456 if (!lp_smb1_unix_extensions()) {
4457 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4458 return;
4460 if (!req->posix_pathnames) {
4461 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4462 return;
4466 if (req->posix_pathnames) {
4467 srvstr_get_path_posix(req,
4468 params,
4469 req->flags2,
4470 &fname,
4471 &params[6],
4472 total_params - 6,
4473 STR_TERMINATE,
4474 &status);
4475 } else {
4476 srvstr_get_path(req,
4477 params,
4478 req->flags2,
4479 &fname,
4480 &params[6],
4481 total_params - 6,
4482 STR_TERMINATE,
4483 &status);
4485 if (!NT_STATUS_IS_OK(status)) {
4486 reply_nterror(req, status);
4487 return;
4490 DBG_NOTICE("fname=%s info_level=%d totdata=%d\n",
4491 fname,
4492 info_level,
4493 total_data);
4495 if (ucf_flags & UCF_GMT_PATHNAME) {
4496 extract_snapshot_token(fname, &twrp);
4498 status = smb1_strip_dfs_path(req, &ucf_flags, &fname);
4499 if (!NT_STATUS_IS_OK(status)) {
4500 reply_nterror(req, status);
4501 return;
4503 status = filename_convert_dirfsp(req,
4504 conn,
4505 fname,
4506 ucf_flags,
4507 twrp,
4508 &dirfsp,
4509 &smb_fname);
4510 if (!NT_STATUS_IS_OK(status)) {
4511 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4512 reply_botherror(req,
4513 NT_STATUS_PATH_NOT_COVERED,
4514 ERRSRV, ERRbadpath);
4515 return;
4517 reply_nterror(req, status);
4518 return;
4521 info_level_handled = true; /* Untouched in switch cases below */
4523 switch (info_level) {
4525 default:
4526 info_level_handled = false;
4527 break;
4529 case SMB_POSIX_PATH_OPEN:
4530 status = smb_posix_open(conn,
4531 req,
4532 ppdata,
4533 total_data,
4534 dirfsp,
4535 smb_fname,
4536 &data_return_size);
4537 break;
4539 case SMB_POSIX_PATH_UNLINK:
4540 status = smb_posix_unlink(conn,
4541 req,
4542 *ppdata,
4543 total_data,
4544 dirfsp,
4545 smb_fname);
4546 break;
4548 case SMB_SET_FILE_UNIX_LINK:
4549 status = smb_set_file_unix_link(
4550 conn, req, *ppdata, total_data, dirfsp, smb_fname);
4551 break;
4553 case SMB_SET_FILE_UNIX_HLINK:
4554 status = smb_set_file_unix_hlink(
4555 conn, req, *ppdata, total_data, smb_fname);
4556 break;
4558 case SMB_SET_FILE_UNIX_BASIC:
4559 status = smb_set_file_unix_basic(conn,
4560 req,
4561 *ppdata,
4562 total_data,
4563 dirfsp,
4564 smb_fname->fsp,
4565 smb_fname);
4566 break;
4568 case SMB_SET_FILE_UNIX_INFO2:
4569 status = smb_set_file_unix_info2(conn,
4570 req,
4571 *ppdata,
4572 total_data,
4573 dirfsp,
4574 smb_fname->fsp,
4575 smb_fname);
4576 break;
4577 case SMB_SET_POSIX_ACL:
4578 status = smb_set_posix_acl(
4579 conn, req, *ppdata, total_data, NULL, smb_fname);
4580 break;
4583 if (info_level_handled) {
4584 goto done;
4588 * smb_fname->fsp may be NULL if smb_fname points at a symlink
4589 * and we're in POSIX context, so be careful when using fsp
4590 * below, it can still be NULL.
4592 fsp = smb_fname->fsp;
4593 if (fsp == NULL) {
4594 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4595 goto done;
4598 status = smbd_do_setfilepathinfo(
4599 conn,
4600 req,
4601 req,
4602 info_level,
4603 fsp,
4604 NULL,
4605 smb_fname,
4606 *ppdata,
4607 total_data,
4608 &data_return_size);
4610 done:
4611 handle_trans2setfilepathinfo_result(
4612 conn,
4613 req,
4614 info_level,
4615 status,
4616 *ppdata,
4617 data_return_size,
4618 max_data_bytes);
4621 static void call_trans2setfileinfo(
4622 connection_struct *conn,
4623 struct smb_request *req,
4624 char **pparams,
4625 int total_params,
4626 char **ppdata,
4627 int total_data,
4628 unsigned int max_data_bytes)
4630 char *pdata = *ppdata;
4631 uint16_t info_level;
4632 struct smb_filename *smb_fname = NULL;
4633 struct files_struct *fsp = NULL;
4634 char *params = *pparams;
4635 int data_return_size = 0;
4636 bool info_level_handled;
4637 NTSTATUS status;
4638 int ret;
4640 if (params == NULL) {
4641 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4642 return;
4644 if (total_params < 4) {
4645 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4646 return;
4649 fsp = file_fsp(req, SVAL(params,0));
4650 /* Basic check for non-null fsp. */
4651 if (!check_fsp_open(conn, req, fsp)) {
4652 return;
4654 info_level = SVAL(params,2);
4656 if (INFO_LEVEL_IS_UNIX(info_level)) {
4657 if (!lp_smb1_unix_extensions()) {
4658 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4659 return;
4661 if (!req->posix_pathnames) {
4662 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4663 return;
4667 smb_fname = fsp->fsp_name;
4669 DBG_NOTICE("fnum=%s fname=%s info_level=%d totdata=%d\n",
4670 fsp_fnum_dbg(fsp),
4671 fsp_str_dbg(fsp),
4672 info_level,
4673 total_data);
4675 if (fsp_get_pathref_fd(fsp) == -1) {
4677 * This is actually a SETFILEINFO on a directory
4678 * handle (returned from an NT SMB). NT5.0 seems
4679 * to do this call. JRA.
4681 ret = vfs_stat(conn, smb_fname);
4682 if (ret != 0) {
4683 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
4684 smb_fname_str_dbg(smb_fname),
4685 strerror(errno));
4686 reply_nterror(req, map_nt_error_from_unix(errno));
4687 return;
4689 } else if (fsp->print_file) {
4691 * Doing a DELETE_ON_CLOSE should cancel a print job.
4693 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) &&
4694 CVAL(pdata,0)) {
4696 fsp->fsp_flags.delete_on_close = true;
4698 DBG_NOTICE("Cancelling print job (%s)\n",
4699 fsp_str_dbg(fsp));
4701 SSVAL(params,0,0);
4702 send_trans2_replies(
4703 conn,
4704 req,
4705 NT_STATUS_OK,
4706 params,
4708 *ppdata, 0,
4709 max_data_bytes);
4710 return;
4711 } else {
4712 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
4713 return;
4715 } else {
4717 * Original code - this is an open file.
4719 status = vfs_stat_fsp(fsp);
4720 if (!NT_STATUS_IS_OK(status)) {
4721 DBG_NOTICE("fstat of %s failed (%s)\n",
4722 fsp_fnum_dbg(fsp),
4723 nt_errstr(status));
4724 reply_nterror(req, status);
4725 return;
4729 info_level_handled = true; /* Untouched in switch cases below */
4731 switch (info_level) {
4733 default:
4734 info_level_handled = false;
4735 break;
4737 case SMB_SET_FILE_UNIX_BASIC:
4738 status = smb_set_file_unix_basic(conn,
4739 req,
4740 pdata,
4741 total_data,
4742 NULL,
4743 fsp,
4744 smb_fname);
4745 break;
4747 case SMB_SET_FILE_UNIX_INFO2:
4748 status = smb_set_file_unix_info2(conn,
4749 req,
4750 pdata,
4751 total_data,
4752 NULL,
4753 fsp,
4754 smb_fname);
4755 break;
4757 case SMB_SET_POSIX_LOCK:
4758 status = smb_set_posix_lock(
4759 conn, req, *ppdata, total_data, fsp);
4760 break;
4763 if (info_level_handled) {
4764 handle_trans2setfilepathinfo_result(
4765 conn,
4766 req,
4767 info_level,
4768 status,
4769 *ppdata,
4770 data_return_size,
4771 max_data_bytes);
4772 return;
4775 status = smbd_do_setfilepathinfo(
4776 conn,
4777 req,
4778 req,
4779 info_level,
4780 fsp,
4781 NULL,
4782 smb_fname,
4783 *ppdata,
4784 total_data,
4785 &data_return_size);
4787 handle_trans2setfilepathinfo_result(
4788 conn,
4789 req,
4790 info_level,
4791 status,
4792 *ppdata,
4793 data_return_size,
4794 max_data_bytes);
4797 /****************************************************************************
4798 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4799 ****************************************************************************/
4801 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
4802 char **pparams, int total_params,
4803 char **ppdata, int total_data,
4804 unsigned int max_data_bytes)
4806 struct files_struct *dirfsp = NULL;
4807 struct files_struct *fsp = NULL;
4808 struct smb_filename *smb_dname = NULL;
4809 char *params = *pparams;
4810 char *pdata = *ppdata;
4811 char *directory = NULL;
4812 NTSTATUS status = NT_STATUS_OK;
4813 struct ea_list *ea_list = NULL;
4814 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4815 NTTIME twrp = 0;
4816 TALLOC_CTX *ctx = talloc_tos();
4818 if (!CAN_WRITE(conn)) {
4819 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4820 return;
4823 if (total_params < 5) {
4824 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4825 return;
4828 if (req->posix_pathnames) {
4829 srvstr_get_path_posix(ctx,
4830 params,
4831 req->flags2,
4832 &directory,
4833 &params[4],
4834 total_params - 4,
4835 STR_TERMINATE,
4836 &status);
4837 } else {
4838 srvstr_get_path(ctx,
4839 params,
4840 req->flags2,
4841 &directory,
4842 &params[4],
4843 total_params - 4,
4844 STR_TERMINATE,
4845 &status);
4847 if (!NT_STATUS_IS_OK(status)) {
4848 reply_nterror(req, status);
4849 return;
4852 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4854 if (ucf_flags & UCF_GMT_PATHNAME) {
4855 extract_snapshot_token(directory, &twrp);
4857 status = smb1_strip_dfs_path(ctx, &ucf_flags, &directory);
4858 if (!NT_STATUS_IS_OK(status)) {
4859 reply_nterror(req, status);
4860 goto out;
4862 status = filename_convert_dirfsp(ctx,
4863 conn,
4864 directory,
4865 ucf_flags,
4866 twrp,
4867 &dirfsp,
4868 &smb_dname);
4869 if (!NT_STATUS_IS_OK(status)) {
4870 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4871 reply_botherror(req,
4872 NT_STATUS_PATH_NOT_COVERED,
4873 ERRSRV, ERRbadpath);
4874 return;
4876 reply_nterror(req, status);
4877 return;
4881 * OS/2 workplace shell seems to send SET_EA requests of "null"
4882 * length (4 bytes containing IVAL 4).
4883 * They seem to have no effect. Bug #3212. JRA.
4886 if (total_data && (total_data != 4)) {
4887 /* Any data in this call is an EA list. */
4888 if (total_data < 10) {
4889 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4890 goto out;
4893 if (IVAL(pdata,0) > total_data) {
4894 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4895 IVAL(pdata,0), (unsigned int)total_data));
4896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4897 goto out;
4900 ea_list = read_ea_list(talloc_tos(), pdata + 4,
4901 total_data - 4);
4902 if (!ea_list) {
4903 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4904 goto out;
4907 if (!lp_ea_support(SNUM(conn))) {
4908 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
4909 goto out;
4912 /* If total_data == 4 Windows doesn't care what values
4913 * are placed in that field, it just ignores them.
4914 * The System i QNTC IBM SMB client puts bad values here,
4915 * so ignore them. */
4917 status = SMB_VFS_CREATE_FILE(
4918 conn, /* conn */
4919 req, /* req */
4920 dirfsp, /* dirfsp */
4921 smb_dname, /* fname */
4922 MAXIMUM_ALLOWED_ACCESS, /* access_mask */
4923 FILE_SHARE_NONE, /* share_access */
4924 FILE_CREATE, /* create_disposition*/
4925 FILE_DIRECTORY_FILE, /* create_options */
4926 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
4927 0, /* oplock_request */
4928 NULL, /* lease */
4929 0, /* allocation_size */
4930 0, /* private_flags */
4931 NULL, /* sd */
4932 NULL, /* ea_list */
4933 &fsp, /* result */
4934 NULL, /* pinfo */
4935 NULL, NULL); /* create context */
4936 if (!NT_STATUS_IS_OK(status)) {
4937 reply_nterror(req, status);
4938 goto out;
4941 /* Try and set any given EA. */
4942 if (ea_list) {
4943 status = set_ea(conn, fsp, ea_list);
4944 if (!NT_STATUS_IS_OK(status)) {
4945 reply_nterror(req, status);
4946 goto out;
4950 /* Realloc the parameter and data sizes */
4951 *pparams = (char *)SMB_REALLOC(*pparams,2);
4952 if(*pparams == NULL) {
4953 reply_nterror(req, NT_STATUS_NO_MEMORY);
4954 goto out;
4956 params = *pparams;
4958 SSVAL(params,0,0);
4960 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
4962 out:
4963 if (fsp != NULL) {
4964 close_file_free(NULL, &fsp, NORMAL_CLOSE);
4966 TALLOC_FREE(smb_dname);
4969 /****************************************************************************
4970 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4971 We don't actually do this - we just send a null response.
4972 ****************************************************************************/
4974 static void call_trans2findnotifyfirst(connection_struct *conn,
4975 struct smb_request *req,
4976 char **pparams, int total_params,
4977 char **ppdata, int total_data,
4978 unsigned int max_data_bytes)
4980 char *params = *pparams;
4981 uint16_t info_level;
4983 if (total_params < 6) {
4984 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4985 return;
4988 info_level = SVAL(params,4);
4989 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4991 switch (info_level) {
4992 case 1:
4993 case 2:
4994 break;
4995 default:
4996 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4997 return;
5000 /* Realloc the parameter and data sizes */
5001 *pparams = (char *)SMB_REALLOC(*pparams,6);
5002 if (*pparams == NULL) {
5003 reply_nterror(req, NT_STATUS_NO_MEMORY);
5004 return;
5006 params = *pparams;
5008 SSVAL(params,0,fnf_handle);
5009 SSVAL(params,2,0); /* No changes */
5010 SSVAL(params,4,0); /* No EA errors */
5012 fnf_handle++;
5014 if(fnf_handle == 0)
5015 fnf_handle = 257;
5017 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
5020 /****************************************************************************
5021 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
5022 changes). Currently this does nothing.
5023 ****************************************************************************/
5025 static void call_trans2findnotifynext(connection_struct *conn,
5026 struct smb_request *req,
5027 char **pparams, int total_params,
5028 char **ppdata, int total_data,
5029 unsigned int max_data_bytes)
5031 char *params = *pparams;
5033 DEBUG(3,("call_trans2findnotifynext\n"));
5035 /* Realloc the parameter and data sizes */
5036 *pparams = (char *)SMB_REALLOC(*pparams,4);
5037 if (*pparams == NULL) {
5038 reply_nterror(req, NT_STATUS_NO_MEMORY);
5039 return;
5041 params = *pparams;
5043 SSVAL(params,0,0); /* No changes */
5044 SSVAL(params,2,0); /* No EA errors */
5046 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
5049 /****************************************************************************
5050 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5051 ****************************************************************************/
5053 static void call_trans2getdfsreferral(connection_struct *conn,
5054 struct smb_request *req,
5055 char **pparams, int total_params,
5056 char **ppdata, int total_data,
5057 unsigned int max_data_bytes)
5059 char *params = *pparams;
5060 char *pathname = NULL;
5061 int reply_size = 0;
5062 int max_referral_level;
5063 NTSTATUS status = NT_STATUS_OK;
5064 TALLOC_CTX *ctx = talloc_tos();
5066 DEBUG(10,("call_trans2getdfsreferral\n"));
5068 if (!IS_IPC(conn)) {
5069 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5070 return;
5073 if (total_params < 3) {
5074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5075 return;
5078 max_referral_level = SVAL(params,0);
5080 if(!lp_host_msdfs()) {
5081 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5082 return;
5085 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
5086 total_params - 2, STR_TERMINATE);
5087 if (!pathname) {
5088 reply_nterror(req, NT_STATUS_NOT_FOUND);
5089 return;
5091 reply_size = setup_dfs_referral(
5092 conn, pathname, max_referral_level, ppdata, &status);
5093 if (reply_size < 0) {
5094 reply_nterror(req, status);
5095 return;
5098 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
5099 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
5100 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
5103 #define LMCAT_SPL 0x53
5104 #define LMFUNC_GETJOBID 0x60
5106 /****************************************************************************
5107 Reply to a TRANS2_IOCTL - used for OS/2 printing.
5108 ****************************************************************************/
5110 static void call_trans2ioctl(connection_struct *conn,
5111 struct smb_request *req,
5112 char **pparams, int total_params,
5113 char **ppdata, int total_data,
5114 unsigned int max_data_bytes)
5116 const struct loadparm_substitution *lp_sub =
5117 loadparm_s3_global_substitution();
5118 char *pdata = *ppdata;
5119 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
5120 NTSTATUS status;
5121 size_t len = 0;
5123 /* check for an invalid fid before proceeding */
5125 if (!fsp) {
5126 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5127 return;
5130 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
5131 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
5132 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
5133 if (*ppdata == NULL) {
5134 reply_nterror(req, NT_STATUS_NO_MEMORY);
5135 return;
5137 pdata = *ppdata;
5139 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5140 CAN ACCEPT THIS IN UNICODE. JRA. */
5142 /* Job number */
5143 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
5145 status = srvstr_push(pdata, req->flags2, pdata + 2,
5146 lp_netbios_name(), 15,
5147 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
5148 if (!NT_STATUS_IS_OK(status)) {
5149 reply_nterror(req, status);
5150 return;
5152 status = srvstr_push(pdata, req->flags2, pdata+18,
5153 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
5154 STR_ASCII|STR_TERMINATE, &len); /* Service name */
5155 if (!NT_STATUS_IS_OK(status)) {
5156 reply_nterror(req, status);
5157 return;
5159 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
5160 max_data_bytes);
5161 return;
5164 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5165 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5168 static void handle_trans2(connection_struct *conn, struct smb_request *req,
5169 struct trans_state *state)
5171 struct smbXsrv_connection *xconn = req->xconn;
5173 if (xconn->protocol >= PROTOCOL_NT1) {
5174 req->flags2 |= 0x40; /* IS_LONG_NAME */
5175 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
5178 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
5179 if (state->call != TRANSACT2_QFSINFO &&
5180 state->call != TRANSACT2_SETFSINFO) {
5181 DEBUG(0,("handle_trans2: encryption required "
5182 "with call 0x%x\n",
5183 (unsigned int)state->call));
5184 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5185 return;
5189 /* Now we must call the relevant TRANS2 function */
5190 switch(state->call) {
5191 case TRANSACT2_OPEN:
5193 START_PROFILE(Trans2_open);
5194 call_trans2open(conn, req,
5195 &state->param, state->total_param,
5196 &state->data, state->total_data,
5197 state->max_data_return);
5198 END_PROFILE(Trans2_open);
5199 break;
5202 case TRANSACT2_FINDFIRST:
5204 START_PROFILE(Trans2_findfirst);
5205 call_trans2findfirst(conn, req,
5206 &state->param, state->total_param,
5207 &state->data, state->total_data,
5208 state->max_data_return);
5209 END_PROFILE(Trans2_findfirst);
5210 break;
5213 case TRANSACT2_FINDNEXT:
5215 START_PROFILE(Trans2_findnext);
5216 call_trans2findnext(conn, req,
5217 &state->param, state->total_param,
5218 &state->data, state->total_data,
5219 state->max_data_return);
5220 END_PROFILE(Trans2_findnext);
5221 break;
5224 case TRANSACT2_QFSINFO:
5226 START_PROFILE(Trans2_qfsinfo);
5227 call_trans2qfsinfo(conn, req,
5228 &state->param, state->total_param,
5229 &state->data, state->total_data,
5230 state->max_data_return);
5231 END_PROFILE(Trans2_qfsinfo);
5232 break;
5235 case TRANSACT2_SETFSINFO:
5237 START_PROFILE(Trans2_setfsinfo);
5238 call_trans2setfsinfo(conn, req,
5239 &state->param, state->total_param,
5240 &state->data, state->total_data,
5241 state->max_data_return);
5242 END_PROFILE(Trans2_setfsinfo);
5243 break;
5246 case TRANSACT2_QPATHINFO:
5248 START_PROFILE(Trans2_qpathinfo);
5249 call_trans2qpathinfo(
5250 conn,
5251 req,
5252 &state->param,
5253 state->total_param,
5254 &state->data,
5255 state->total_data,
5256 state->max_data_return);
5257 END_PROFILE(Trans2_qpathinfo);
5258 break;
5261 case TRANSACT2_QFILEINFO:
5263 START_PROFILE(Trans2_qfileinfo);
5264 call_trans2qfileinfo(
5265 conn,
5266 req,
5267 &state->param,
5268 state->total_param,
5269 &state->data,
5270 state->total_data,
5271 state->max_data_return);
5272 END_PROFILE(Trans2_qfileinfo);
5273 break;
5276 case TRANSACT2_SETPATHINFO:
5278 START_PROFILE(Trans2_setpathinfo);
5279 call_trans2setpathinfo(
5280 conn,
5281 req,
5282 &state->param,
5283 state->total_param,
5284 &state->data,
5285 state->total_data,
5286 state->max_data_return);
5287 END_PROFILE(Trans2_setpathinfo);
5288 break;
5291 case TRANSACT2_SETFILEINFO:
5293 START_PROFILE(Trans2_setfileinfo);
5294 call_trans2setfileinfo(
5295 conn,
5296 req,
5297 &state->param,
5298 state->total_param,
5299 &state->data,
5300 state->total_data,
5301 state->max_data_return);
5302 END_PROFILE(Trans2_setfileinfo);
5303 break;
5306 case TRANSACT2_FINDNOTIFYFIRST:
5308 START_PROFILE(Trans2_findnotifyfirst);
5309 call_trans2findnotifyfirst(conn, req,
5310 &state->param, state->total_param,
5311 &state->data, state->total_data,
5312 state->max_data_return);
5313 END_PROFILE(Trans2_findnotifyfirst);
5314 break;
5317 case TRANSACT2_FINDNOTIFYNEXT:
5319 START_PROFILE(Trans2_findnotifynext);
5320 call_trans2findnotifynext(conn, req,
5321 &state->param, state->total_param,
5322 &state->data, state->total_data,
5323 state->max_data_return);
5324 END_PROFILE(Trans2_findnotifynext);
5325 break;
5328 case TRANSACT2_MKDIR:
5330 START_PROFILE(Trans2_mkdir);
5331 call_trans2mkdir(conn, req,
5332 &state->param, state->total_param,
5333 &state->data, state->total_data,
5334 state->max_data_return);
5335 END_PROFILE(Trans2_mkdir);
5336 break;
5339 case TRANSACT2_GET_DFS_REFERRAL:
5341 START_PROFILE(Trans2_get_dfs_referral);
5342 call_trans2getdfsreferral(conn, req,
5343 &state->param, state->total_param,
5344 &state->data, state->total_data,
5345 state->max_data_return);
5346 END_PROFILE(Trans2_get_dfs_referral);
5347 break;
5350 case TRANSACT2_IOCTL:
5352 START_PROFILE(Trans2_ioctl);
5353 call_trans2ioctl(conn, req,
5354 &state->param, state->total_param,
5355 &state->data, state->total_data,
5356 state->max_data_return);
5357 END_PROFILE(Trans2_ioctl);
5358 break;
5361 default:
5362 /* Error in request */
5363 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5364 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5368 /****************************************************************************
5369 Reply to a SMBtrans2.
5370 ****************************************************************************/
5372 void reply_trans2(struct smb_request *req)
5374 connection_struct *conn = req->conn;
5375 unsigned int dsoff;
5376 unsigned int dscnt;
5377 unsigned int psoff;
5378 unsigned int pscnt;
5379 unsigned int tran_call;
5380 struct trans_state *state;
5381 NTSTATUS result;
5383 START_PROFILE(SMBtrans2);
5385 if (req->wct < 14) {
5386 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5387 END_PROFILE(SMBtrans2);
5388 return;
5391 dsoff = SVAL(req->vwv+12, 0);
5392 dscnt = SVAL(req->vwv+11, 0);
5393 psoff = SVAL(req->vwv+10, 0);
5394 pscnt = SVAL(req->vwv+9, 0);
5395 tran_call = SVAL(req->vwv+14, 0);
5397 result = allow_new_trans(conn->pending_trans, req->mid);
5398 if (!NT_STATUS_IS_OK(result)) {
5399 DEBUG(2, ("Got invalid trans2 request: %s\n",
5400 nt_errstr(result)));
5401 reply_nterror(req, result);
5402 END_PROFILE(SMBtrans2);
5403 return;
5406 if (IS_IPC(conn)) {
5407 switch (tran_call) {
5408 /* List the allowed trans2 calls on IPC$ */
5409 case TRANSACT2_OPEN:
5410 case TRANSACT2_GET_DFS_REFERRAL:
5411 case TRANSACT2_QFILEINFO:
5412 case TRANSACT2_QFSINFO:
5413 case TRANSACT2_SETFSINFO:
5414 break;
5415 default:
5416 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5417 END_PROFILE(SMBtrans2);
5418 return;
5422 if ((state = talloc(conn, struct trans_state)) == NULL) {
5423 DEBUG(0, ("talloc failed\n"));
5424 reply_nterror(req, NT_STATUS_NO_MEMORY);
5425 END_PROFILE(SMBtrans2);
5426 return;
5429 state->cmd = SMBtrans2;
5431 state->mid = req->mid;
5432 state->vuid = req->vuid;
5433 state->setup_count = SVAL(req->vwv+13, 0);
5434 state->setup = NULL;
5435 state->total_param = SVAL(req->vwv+0, 0);
5436 state->param = NULL;
5437 state->total_data = SVAL(req->vwv+1, 0);
5438 state->data = NULL;
5439 state->max_param_return = SVAL(req->vwv+2, 0);
5440 state->max_data_return = SVAL(req->vwv+3, 0);
5441 state->max_setup_return = SVAL(req->vwv+4, 0);
5442 state->close_on_completion = BITSETW(req->vwv+5, 0);
5443 state->one_way = BITSETW(req->vwv+5, 1);
5445 state->call = tran_call;
5447 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5448 is so as a sanity check */
5449 if (state->setup_count != 1) {
5451 * Need to have rc=0 for ioctl to get job id for OS/2.
5452 * Network printing will fail if function is not successful.
5453 * Similar function in reply.c will be used if protocol
5454 * is LANMAN1.0 instead of LM1.2X002.
5455 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5456 * outbuf doesn't have to be set(only job id is used).
5458 if ( (state->setup_count == 4)
5459 && (tran_call == TRANSACT2_IOCTL)
5460 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
5461 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
5462 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5463 } else {
5464 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5465 DEBUG(2,("Transaction is %d\n",tran_call));
5466 TALLOC_FREE(state);
5467 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5468 END_PROFILE(SMBtrans2);
5469 return;
5473 if ((dscnt > state->total_data) || (pscnt > state->total_param))
5474 goto bad_param;
5476 if (state->total_data) {
5478 if (smb_buffer_oob(state->total_data, 0, dscnt)
5479 || smb_buffer_oob(smb_len(req->inbuf), dsoff, dscnt)) {
5480 goto bad_param;
5483 /* Can't use talloc here, the core routines do realloc on the
5484 * params and data. */
5485 state->data = (char *)SMB_MALLOC(state->total_data);
5486 if (state->data == NULL) {
5487 DEBUG(0,("reply_trans2: data malloc fail for %u "
5488 "bytes !\n", (unsigned int)state->total_data));
5489 TALLOC_FREE(state);
5490 reply_nterror(req, NT_STATUS_NO_MEMORY);
5491 END_PROFILE(SMBtrans2);
5492 return;
5495 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
5498 if (state->total_param) {
5500 if (smb_buffer_oob(state->total_param, 0, pscnt)
5501 || smb_buffer_oob(smb_len(req->inbuf), psoff, pscnt)) {
5502 goto bad_param;
5505 /* Can't use talloc here, the core routines do realloc on the
5506 * params and data. */
5507 state->param = (char *)SMB_MALLOC(state->total_param);
5508 if (state->param == NULL) {
5509 DEBUG(0,("reply_trans: param malloc fail for %u "
5510 "bytes !\n", (unsigned int)state->total_param));
5511 SAFE_FREE(state->data);
5512 TALLOC_FREE(state);
5513 reply_nterror(req, NT_STATUS_NO_MEMORY);
5514 END_PROFILE(SMBtrans2);
5515 return;
5518 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
5521 state->received_data = dscnt;
5522 state->received_param = pscnt;
5524 if ((state->received_param == state->total_param) &&
5525 (state->received_data == state->total_data)) {
5527 handle_trans2(conn, req, state);
5529 SAFE_FREE(state->data);
5530 SAFE_FREE(state->param);
5531 TALLOC_FREE(state);
5532 END_PROFILE(SMBtrans2);
5533 return;
5536 DLIST_ADD(conn->pending_trans, state);
5538 /* We need to send an interim response then receive the rest
5539 of the parameter/data bytes */
5540 reply_smb1_outbuf(req, 0, 0);
5541 show_msg((char *)req->outbuf);
5542 END_PROFILE(SMBtrans2);
5543 return;
5545 bad_param:
5547 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5548 SAFE_FREE(state->data);
5549 SAFE_FREE(state->param);
5550 TALLOC_FREE(state);
5551 END_PROFILE(SMBtrans2);
5552 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5555 /****************************************************************************
5556 Reply to a SMBtranss2
5557 ****************************************************************************/
5559 void reply_transs2(struct smb_request *req)
5561 connection_struct *conn = req->conn;
5562 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5563 struct trans_state *state;
5565 START_PROFILE(SMBtranss2);
5567 show_msg((const char *)req->inbuf);
5569 /* Windows clients expect all replies to
5570 a transact secondary (SMBtranss2 0x33)
5571 to have a command code of transact
5572 (SMBtrans2 0x32). See bug #8989
5573 and also [MS-CIFS] section 2.2.4.47.2
5574 for details.
5576 req->cmd = SMBtrans2;
5578 if (req->wct < 8) {
5579 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5580 END_PROFILE(SMBtranss2);
5581 return;
5584 for (state = conn->pending_trans; state != NULL;
5585 state = state->next) {
5586 if (state->mid == req->mid) {
5587 break;
5591 if ((state == NULL) || (state->cmd != SMBtrans2)) {
5592 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5593 END_PROFILE(SMBtranss2);
5594 return;
5597 /* Revise state->total_param and state->total_data in case they have
5598 changed downwards */
5600 if (SVAL(req->vwv+0, 0) < state->total_param)
5601 state->total_param = SVAL(req->vwv+0, 0);
5602 if (SVAL(req->vwv+1, 0) < state->total_data)
5603 state->total_data = SVAL(req->vwv+1, 0);
5605 pcnt = SVAL(req->vwv+2, 0);
5606 poff = SVAL(req->vwv+3, 0);
5607 pdisp = SVAL(req->vwv+4, 0);
5609 dcnt = SVAL(req->vwv+5, 0);
5610 doff = SVAL(req->vwv+6, 0);
5611 ddisp = SVAL(req->vwv+7, 0);
5613 state->received_param += pcnt;
5614 state->received_data += dcnt;
5616 if ((state->received_data > state->total_data) ||
5617 (state->received_param > state->total_param))
5618 goto bad_param;
5620 if (pcnt) {
5621 if (smb_buffer_oob(state->total_param, pdisp, pcnt)
5622 || smb_buffer_oob(smb_len(req->inbuf), poff, pcnt)) {
5623 goto bad_param;
5625 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
5628 if (dcnt) {
5629 if (smb_buffer_oob(state->total_data, ddisp, dcnt)
5630 || smb_buffer_oob(smb_len(req->inbuf), doff, dcnt)) {
5631 goto bad_param;
5633 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
5636 if ((state->received_param < state->total_param) ||
5637 (state->received_data < state->total_data)) {
5638 END_PROFILE(SMBtranss2);
5639 return;
5642 handle_trans2(conn, req, state);
5644 DLIST_REMOVE(conn->pending_trans, state);
5645 SAFE_FREE(state->data);
5646 SAFE_FREE(state->param);
5647 TALLOC_FREE(state);
5649 END_PROFILE(SMBtranss2);
5650 return;
5652 bad_param:
5654 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5655 DLIST_REMOVE(conn->pending_trans, state);
5656 SAFE_FREE(state->data);
5657 SAFE_FREE(state->param);
5658 TALLOC_FREE(state);
5659 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5660 END_PROFILE(SMBtranss2);