smbd: Introduce srv_put_dos_date2_ts()
[Samba.git] / source3 / smbd / smb1_trans2.c
blobb068982529e1600a92a90da38e590d4f9de0d9c1
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "ntioctl.h"
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.h"
30 #include "version.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "../libcli/auth/libcli_auth.h"
34 #include "../librpc/gen_ndr/xattr.h"
35 #include "../librpc/gen_ndr/ndr_security.h"
36 #include "libcli/security/security.h"
37 #include "trans2.h"
38 #include "auth.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
41 #include "printing.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
44 #include "messages.h"
45 #include "libcli/smb/smb2_posix.h"
46 #include "lib/util/string_wrappers.h"
47 #include "source3/lib/substitute.h"
48 #include "source3/lib/adouble.h"
50 #define DIR_ENTRY_SAFETY_MARGIN 4096
52 /****************************************************************************
53 Send the required number of replies back.
54 We assume all fields other than the data fields are
55 set correctly for the type of call.
56 HACK ! Always assumes smb_setup field is zero.
57 ****************************************************************************/
59 static void send_trans2_replies(connection_struct *conn,
60 struct smb_request *req,
61 NTSTATUS status,
62 const char *params,
63 int paramsize,
64 const char *pdata,
65 int datasize,
66 int max_data_bytes)
68 /* As we are using a protocol > LANMAN1 then the max_send
69 variable must have been set in the sessetupX call.
70 This takes precedence over the max_xmit field in the
71 global struct. These different max_xmit variables should
72 be merged as this is now too confusing */
74 int data_to_send = datasize;
75 int params_to_send = paramsize;
76 int useable_space;
77 const char *pp = params;
78 const char *pd = pdata;
79 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
80 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
81 int data_alignment_offset = 0;
82 bool overflow = False;
83 struct smbXsrv_connection *xconn = req->xconn;
84 int max_send = xconn->smb1.sessions.max_send;
86 /* Modify the data_to_send and datasize and set the error if
87 we're trying to send more than max_data_bytes. We still send
88 the part of the packet(s) that fit. Strange, but needed
89 for OS/2. */
91 if (max_data_bytes > 0 && datasize > max_data_bytes) {
92 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
93 max_data_bytes, datasize ));
94 datasize = data_to_send = max_data_bytes;
95 overflow = True;
98 /* If there genuinely are no parameters or data to send just send the empty packet */
100 if(params_to_send == 0 && data_to_send == 0) {
101 reply_smb1_outbuf(req, 10, 0);
102 if (NT_STATUS_V(status)) {
103 uint8_t eclass;
104 uint32_t ecode;
105 ntstatus_to_dos(status, &eclass, &ecode);
106 error_packet_set((char *)req->outbuf,
107 eclass, ecode, status,
108 __LINE__,__FILE__);
110 show_msg((char *)req->outbuf);
111 if (!smb1_srv_send(xconn,
112 (char *)req->outbuf,
113 true,
114 req->seqnum + 1,
115 IS_CONN_ENCRYPTED(conn))) {
116 exit_server_cleanly("send_trans2_replies: smb1_srv_send failed.");
118 TALLOC_FREE(req->outbuf);
119 return;
122 /* When sending params and data ensure that both are nicely aligned */
123 /* Only do this alignment when there is also data to send - else
124 can cause NT redirector problems. */
126 if (((params_to_send % 4) != 0) && (data_to_send != 0))
127 data_alignment_offset = 4 - (params_to_send % 4);
129 /* Space is bufsize minus Netbios over TCP header minus SMB header */
130 /* The alignment_offset is to align the param bytes on an even byte
131 boundary. NT 4.0 Beta needs this to work correctly. */
133 useable_space = max_send - (smb_size
134 + 2 * 10 /* wct */
135 + alignment_offset
136 + data_alignment_offset);
138 if (useable_space < 0) {
139 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
140 "= %d!!!\n", useable_space));
141 exit_server_cleanly("send_trans2_replies: Not enough space");
144 while (params_to_send || data_to_send) {
145 /* Calculate whether we will totally or partially fill this packet */
147 total_sent_thistime = params_to_send + data_to_send;
149 /* We can never send more than useable_space */
151 * Note that 'useable_space' does not include the alignment offsets,
152 * but we must include the alignment offsets in the calculation of
153 * the length of the data we send over the wire, as the alignment offsets
154 * are sent here. Fix from Marc_Jacobsen@hp.com.
157 total_sent_thistime = MIN(total_sent_thistime, useable_space);
159 reply_smb1_outbuf(req, 10, total_sent_thistime + alignment_offset
160 + data_alignment_offset);
162 /* Set total params and data to be sent */
163 SSVAL(req->outbuf,smb_tprcnt,paramsize);
164 SSVAL(req->outbuf,smb_tdrcnt,datasize);
166 /* Calculate how many parameters and data we can fit into
167 * this packet. Parameters get precedence
170 params_sent_thistime = MIN(params_to_send,useable_space);
171 data_sent_thistime = useable_space - params_sent_thistime;
172 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
174 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
176 /* smb_proff is the offset from the start of the SMB header to the
177 parameter bytes, however the first 4 bytes of outbuf are
178 the Netbios over TCP header. Thus use smb_base() to subtract
179 them from the calculation */
181 SSVAL(req->outbuf,smb_proff,
182 ((smb_buf(req->outbuf)+alignment_offset)
183 - smb_base(req->outbuf)));
185 if(params_sent_thistime == 0)
186 SSVAL(req->outbuf,smb_prdisp,0);
187 else
188 /* Absolute displacement of param bytes sent in this packet */
189 SSVAL(req->outbuf,smb_prdisp,pp - params);
191 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
192 if(data_sent_thistime == 0) {
193 SSVAL(req->outbuf,smb_droff,0);
194 SSVAL(req->outbuf,smb_drdisp, 0);
195 } else {
196 /* The offset of the data bytes is the offset of the
197 parameter bytes plus the number of parameters being sent this time */
198 SSVAL(req->outbuf, smb_droff,
199 ((smb_buf(req->outbuf)+alignment_offset)
200 - smb_base(req->outbuf))
201 + params_sent_thistime + data_alignment_offset);
202 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
205 /* Initialize the padding for alignment */
207 if (alignment_offset != 0) {
208 memset(smb_buf(req->outbuf), 0, alignment_offset);
211 /* Copy the param bytes into the packet */
213 if(params_sent_thistime) {
214 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
215 params_sent_thistime);
218 /* Copy in the data bytes */
219 if(data_sent_thistime) {
220 if (data_alignment_offset != 0) {
221 memset((smb_buf(req->outbuf)+alignment_offset+
222 params_sent_thistime), 0,
223 data_alignment_offset);
225 memcpy(smb_buf(req->outbuf)+alignment_offset
226 +params_sent_thistime+data_alignment_offset,
227 pd,data_sent_thistime);
230 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
231 params_sent_thistime, data_sent_thistime, useable_space));
232 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
233 params_to_send, data_to_send, paramsize, datasize));
235 if (overflow) {
236 error_packet_set((char *)req->outbuf,
237 ERRDOS,ERRbufferoverflow,
238 STATUS_BUFFER_OVERFLOW,
239 __LINE__,__FILE__);
240 } else if (NT_STATUS_V(status)) {
241 uint8_t eclass;
242 uint32_t ecode;
243 ntstatus_to_dos(status, &eclass, &ecode);
244 error_packet_set((char *)req->outbuf,
245 eclass, ecode, status,
246 __LINE__,__FILE__);
249 /* Send the packet */
250 show_msg((char *)req->outbuf);
251 if (!smb1_srv_send(xconn,
252 (char *)req->outbuf,
253 true,
254 req->seqnum + 1,
255 IS_CONN_ENCRYPTED(conn))) {
256 exit_server_cleanly("send_trans2_replies: smb1_srv_send failed.");
259 TALLOC_FREE(req->outbuf);
261 pp += params_sent_thistime;
262 pd += data_sent_thistime;
264 params_to_send -= params_sent_thistime;
265 data_to_send -= data_sent_thistime;
267 /* Sanity check */
268 if(params_to_send < 0 || data_to_send < 0) {
269 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
270 params_to_send, data_to_send));
271 return;
275 return;
278 /****************************************************************************
279 Deal with SMB_SET_POSIX_LOCK.
280 ****************************************************************************/
282 static void smb_set_posix_lock_done(struct tevent_req *subreq);
284 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
285 struct smb_request *req,
286 const char *pdata,
287 int total_data,
288 files_struct *fsp)
290 struct tevent_req *subreq = NULL;
291 struct smbd_lock_element *lck = NULL;
292 uint64_t count;
293 uint64_t offset;
294 uint64_t smblctx;
295 bool blocking_lock = False;
296 enum brl_type lock_type;
298 NTSTATUS status = NT_STATUS_OK;
300 if (!CAN_WRITE(conn)) {
301 return NT_STATUS_DOS(ERRSRV, ERRaccess);
304 if (fsp == NULL ||
305 fsp->fsp_flags.is_pathref ||
306 fsp_get_io_fd(fsp) == -1)
308 return NT_STATUS_INVALID_HANDLE;
311 if (total_data != POSIX_LOCK_DATA_SIZE) {
312 return NT_STATUS_INVALID_PARAMETER;
315 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
316 case POSIX_LOCK_TYPE_READ:
317 lock_type = READ_LOCK;
318 break;
319 case POSIX_LOCK_TYPE_WRITE:
320 /* Return the right POSIX-mappable error code for files opened read-only. */
321 if (!fsp->fsp_flags.can_write) {
322 return NT_STATUS_INVALID_HANDLE;
324 lock_type = WRITE_LOCK;
325 break;
326 case POSIX_LOCK_TYPE_UNLOCK:
327 lock_type = UNLOCK_LOCK;
328 break;
329 default:
330 return NT_STATUS_INVALID_PARAMETER;
333 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
334 case POSIX_LOCK_FLAG_NOWAIT:
335 blocking_lock = false;
336 break;
337 case POSIX_LOCK_FLAG_WAIT:
338 blocking_lock = true;
339 break;
340 default:
341 return NT_STATUS_INVALID_PARAMETER;
344 if (!lp_blocking_locks(SNUM(conn))) {
345 blocking_lock = False;
348 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
349 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
350 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
351 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
352 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
354 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
355 "count = %"PRIu64", offset = %"PRIu64"\n",
356 fsp_str_dbg(fsp),
357 (unsigned int)lock_type,
358 smblctx,
359 count,
360 offset);
362 if (lock_type == UNLOCK_LOCK) {
363 struct smbd_lock_element l = {
364 .req_guid = smbd_request_guid(req, 0),
365 .smblctx = smblctx,
366 .brltype = UNLOCK_LOCK,
367 .lock_flav = POSIX_LOCK,
368 .offset = offset,
369 .count = count,
371 status = smbd_do_unlocking(req, fsp, 1, &l);
372 return status;
375 lck = talloc(req, struct smbd_lock_element);
376 if (lck == NULL) {
377 return NT_STATUS_NO_MEMORY;
380 *lck = (struct smbd_lock_element) {
381 .req_guid = smbd_request_guid(req, 0),
382 .smblctx = smblctx,
383 .brltype = lock_type,
384 .lock_flav = POSIX_LOCK,
385 .count = count,
386 .offset = offset,
389 subreq = smbd_smb1_do_locks_send(
390 fsp,
391 req->sconn->ev_ctx,
392 &req,
393 fsp,
394 blocking_lock ? UINT32_MAX : 0,
395 true, /* large_offset */
397 lck);
398 if (subreq == NULL) {
399 TALLOC_FREE(lck);
400 return NT_STATUS_NO_MEMORY;
402 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
403 return NT_STATUS_EVENT_PENDING;
406 static void smb_set_posix_lock_done(struct tevent_req *subreq)
408 struct smb_request *req = NULL;
409 NTSTATUS status;
410 bool ok;
412 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
413 SMB_ASSERT(ok);
415 status = smbd_smb1_do_locks_recv(subreq);
416 TALLOC_FREE(subreq);
418 if (NT_STATUS_IS_OK(status)) {
419 char params[2] = {0};
420 /* Fake up max_data_bytes here - we know it fits. */
421 send_trans2_replies(
422 req->conn,
423 req,
424 NT_STATUS_OK,
425 params,
427 NULL,
429 0xffff);
430 } else {
431 reply_nterror(req, status);
432 ok = smb1_srv_send(req->xconn,
433 (char *)req->outbuf,
434 true,
435 req->seqnum + 1,
436 IS_CONN_ENCRYPTED(req->conn));
437 if (!ok) {
438 exit_server_cleanly("smb_set_posix_lock_done: "
439 "smb1_srv_send failed.");
443 TALLOC_FREE(req);
444 return;
447 /****************************************************************************
448 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
449 ****************************************************************************/
451 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
453 struct ea_list *ea_list_head = NULL;
454 size_t converted_size, offset = 0;
456 while (offset + 2 < data_size) {
457 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
458 unsigned int namelen = CVAL(pdata,offset);
460 offset++; /* Go past the namelen byte. */
462 /* integer wrap paranioa. */
463 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
464 (offset > data_size) || (namelen > data_size) ||
465 (offset + namelen >= data_size)) {
466 break;
468 /* Ensure the name is null terminated. */
469 if (pdata[offset + namelen] != '\0') {
470 return NULL;
472 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
473 &converted_size)) {
474 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
475 "failed: %s\n", strerror(errno)));
477 if (!eal->ea.name) {
478 return NULL;
481 offset += (namelen + 1); /* Go past the name + terminating zero. */
482 DLIST_ADD_END(ea_list_head, eal);
483 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
486 return ea_list_head;
489 /****************************************************************************
490 Reply to a TRANSACT2_OPEN.
491 ****************************************************************************/
493 static void call_trans2open(connection_struct *conn,
494 struct smb_request *req,
495 char **pparams, int total_params,
496 char **ppdata, int total_data,
497 unsigned int max_data_bytes)
499 struct smb_filename *smb_fname = NULL;
500 char *params = *pparams;
501 char *pdata = *ppdata;
502 int deny_mode;
503 int32_t open_attr;
504 bool oplock_request;
505 #if 0
506 bool return_additional_info;
507 int16 open_sattr;
508 time_t open_time;
509 #endif
510 int open_ofun;
511 uint32_t open_size;
512 char *pname;
513 char *fname = NULL;
514 off_t size=0;
515 int fattr = 0;
516 SMB_INO_T inode = 0;
517 int smb_action = 0;
518 struct files_struct *dirfsp = NULL;
519 files_struct *fsp;
520 struct ea_list *ea_list = NULL;
521 uint16_t flags = 0;
522 NTSTATUS status;
523 uint32_t access_mask;
524 uint32_t share_mode;
525 uint32_t create_disposition;
526 uint32_t create_options = 0;
527 uint32_t private_flags = 0;
528 NTTIME twrp = 0;
529 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
530 TALLOC_CTX *ctx = talloc_tos();
533 * Ensure we have enough parameters to perform the operation.
536 if (total_params < 29) {
537 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
538 goto out;
541 flags = SVAL(params, 0);
542 deny_mode = SVAL(params, 2);
543 open_attr = SVAL(params,6);
544 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
545 if (oplock_request) {
546 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
549 #if 0
550 return_additional_info = BITSETW(params,0);
551 open_sattr = SVAL(params, 4);
552 open_time = make_unix_date3(params+8);
553 #endif
554 open_ofun = SVAL(params,12);
555 open_size = IVAL(params,14);
556 pname = &params[28];
558 if (IS_IPC(conn)) {
559 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
560 goto out;
563 if (req->posix_pathnames) {
564 srvstr_get_path_posix(ctx,
565 params,
566 req->flags2,
567 &fname,
568 pname,
569 total_params - 28,
570 STR_TERMINATE,
571 &status);
572 } else {
573 srvstr_get_path(ctx,
574 params,
575 req->flags2,
576 &fname,
577 pname,
578 total_params - 28,
579 STR_TERMINATE,
580 &status);
582 if (!NT_STATUS_IS_OK(status)) {
583 reply_nterror(req, status);
584 goto out;
587 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
588 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
589 (unsigned int)open_ofun, open_size));
591 if (ucf_flags & UCF_GMT_PATHNAME) {
592 extract_snapshot_token(fname, &twrp);
594 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
595 if (!NT_STATUS_IS_OK(status)) {
596 reply_nterror(req, status);
597 goto out;
599 status = filename_convert_dirfsp(ctx,
600 conn,
601 fname,
602 ucf_flags,
603 twrp,
604 &dirfsp,
605 &smb_fname);
606 if (!NT_STATUS_IS_OK(status)) {
607 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
608 reply_botherror(req,
609 NT_STATUS_PATH_NOT_COVERED,
610 ERRSRV, ERRbadpath);
611 goto out;
613 reply_nterror(req, status);
614 goto out;
617 if (open_ofun == 0) {
618 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
619 goto out;
622 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
623 open_ofun,
624 &access_mask, &share_mode,
625 &create_disposition,
626 &create_options,
627 &private_flags)) {
628 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
629 goto out;
632 /* Any data in this call is an EA list. */
633 if (total_data && (total_data != 4)) {
634 if (total_data < 10) {
635 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
636 goto out;
639 if (IVAL(pdata,0) > total_data) {
640 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
641 IVAL(pdata,0), (unsigned int)total_data));
642 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
643 goto out;
646 ea_list = read_ea_list(talloc_tos(), pdata + 4,
647 total_data - 4);
648 if (!ea_list) {
649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
650 goto out;
653 if (!lp_ea_support(SNUM(conn))) {
654 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
655 goto out;
658 if (!req->posix_pathnames &&
659 ea_list_has_invalid_name(ea_list)) {
660 int param_len = 30;
661 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
662 if(*pparams == NULL ) {
663 reply_nterror(req, NT_STATUS_NO_MEMORY);
664 goto out;
666 params = *pparams;
667 memset(params, '\0', param_len);
668 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
669 params, param_len, NULL, 0, max_data_bytes);
670 goto out;
674 status = SMB_VFS_CREATE_FILE(
675 conn, /* conn */
676 req, /* req */
677 dirfsp, /* dirfsp */
678 smb_fname, /* fname */
679 access_mask, /* access_mask */
680 share_mode, /* share_access */
681 create_disposition, /* create_disposition*/
682 create_options, /* create_options */
683 open_attr, /* file_attributes */
684 oplock_request, /* oplock_request */
685 NULL, /* lease */
686 open_size, /* allocation_size */
687 private_flags,
688 NULL, /* sd */
689 ea_list, /* ea_list */
690 &fsp, /* result */
691 &smb_action, /* psbuf */
692 NULL, NULL); /* create context */
694 if (!NT_STATUS_IS_OK(status)) {
695 if (open_was_deferred(req->xconn, req->mid)) {
696 /* We have re-scheduled this call. */
697 goto out;
700 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
701 reply_openerror(req, status);
702 goto out;
705 fsp = fcb_or_dos_open(
706 req,
707 smb_fname,
708 access_mask,
709 create_options,
710 private_flags);
711 if (fsp == NULL) {
712 bool ok = defer_smb1_sharing_violation(req);
713 if (ok) {
714 goto out;
716 reply_openerror(req, status);
717 goto out;
720 smb_action = FILE_WAS_OPENED;
723 size = get_file_size_stat(&smb_fname->st);
724 fattr = fdos_mode(fsp);
725 inode = smb_fname->st.st_ex_ino;
726 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
727 close_file_free(req, &fsp, ERROR_CLOSE);
728 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
729 goto out;
732 /* Realloc the size of parameters and data we will return */
733 *pparams = (char *)SMB_REALLOC(*pparams, 30);
734 if(*pparams == NULL ) {
735 reply_nterror(req, NT_STATUS_NO_MEMORY);
736 goto out;
738 params = *pparams;
740 SSVAL(params,0,fsp->fnum);
741 SSVAL(params,2,fattr);
742 srv_put_dos_date2_ts(params, 4, smb_fname->st.st_ex_mtime);
743 SIVAL(params,8, (uint32_t)size);
744 SSVAL(params,12,deny_mode);
745 SSVAL(params,14,0); /* open_type - file or directory. */
746 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
748 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
749 smb_action |= EXTENDED_OPLOCK_GRANTED;
752 SSVAL(params,18,smb_action);
755 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
757 SIVAL(params,20,inode);
758 SSVAL(params,24,0); /* Padding. */
759 if (flags & 8) {
760 uint32_t ea_size = estimate_ea_size(smb_fname->fsp);
761 SIVAL(params, 26, ea_size);
762 } else {
763 SIVAL(params, 26, 0);
766 /* Send the required number of replies */
767 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
768 out:
769 TALLOC_FREE(smb_fname);
772 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
773 connection_struct *conn,
774 struct dptr_struct *dirptr,
775 uint16_t flags2,
776 const char *path_mask,
777 uint32_t dirtype,
778 int info_level,
779 bool requires_resume_key,
780 bool dont_descend,
781 bool ask_sharemode,
782 char **ppdata,
783 char *base_data,
784 char *end_data,
785 int space_remaining,
786 int *last_entry_off,
787 struct ea_list *name_list)
789 uint8_t align = 4;
790 const bool do_pad = true;
792 if (info_level >= 1 && info_level <= 3) {
793 /* No alignment on earlier info levels. */
794 align = 1;
797 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
798 path_mask, dirtype, info_level,
799 requires_resume_key, dont_descend, ask_sharemode,
800 true, align, do_pad,
801 ppdata, base_data, end_data,
802 space_remaining,
803 NULL,
804 last_entry_off, name_list, NULL);
807 /****************************************************************************
808 Reply to a TRANS2_FINDFIRST.
809 ****************************************************************************/
811 static void call_trans2findfirst(connection_struct *conn,
812 struct smb_request *req,
813 char **pparams, int total_params,
814 char **ppdata, int total_data,
815 unsigned int max_data_bytes)
817 /* We must be careful here that we don't return more than the
818 allowed number of data bytes. If this means returning fewer than
819 maxentries then so be it. We assume that the redirector has
820 enough room for the fixed number of parameter bytes it has
821 requested. */
822 struct smb_filename *smb_dname = NULL;
823 char *params = *pparams;
824 char *pdata = *ppdata;
825 char *data_end;
826 uint32_t dirtype;
827 int maxentries;
828 uint16_t findfirst_flags;
829 bool close_after_first;
830 bool close_if_end;
831 bool requires_resume_key;
832 int info_level;
833 char *directory = NULL;
834 char *mask = NULL;
835 char *p;
836 int last_entry_off=0;
837 int dptr_num = -1;
838 int numentries = 0;
839 int i;
840 bool finished = False;
841 bool dont_descend = False;
842 bool out_of_space = False;
843 int space_remaining;
844 struct ea_list *ea_list = NULL;
845 NTSTATUS ntstatus = NT_STATUS_OK;
846 bool ask_sharemode;
847 struct smbXsrv_connection *xconn = req->xconn;
848 struct smbd_server_connection *sconn = req->sconn;
849 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
850 bool backup_priv = false;
851 bool as_root = false;
852 files_struct *fsp = NULL;
853 struct files_struct *dirfsp = NULL;
854 const struct loadparm_substitution *lp_sub =
855 loadparm_s3_global_substitution();
857 if (total_params < 13) {
858 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
859 goto out;
862 dirtype = SVAL(params,0);
863 maxentries = SVAL(params,2);
864 findfirst_flags = SVAL(params,4);
865 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
866 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
867 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
868 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
869 security_token_has_privilege(get_current_nttok(conn),
870 SEC_PRIV_BACKUP));
872 info_level = SVAL(params,6);
874 DBG_NOTICE("dirtype = %"PRIx32", maxentries = %d, "
875 "close_after_first=%d, close_if_end = %d "
876 "requires_resume_key = %d backup_priv = %d level = 0x%x, "
877 "max_data_bytes = %d\n",
878 dirtype,
879 maxentries,
880 close_after_first,
881 close_if_end,
882 requires_resume_key,
883 backup_priv,
884 info_level,
885 max_data_bytes);
887 if (!maxentries) {
888 /* W2K3 seems to treat zero as 1. */
889 maxentries = 1;
892 switch (info_level) {
893 case SMB_FIND_INFO_STANDARD:
894 case SMB_FIND_EA_SIZE:
895 case SMB_FIND_EA_LIST:
896 case SMB_FIND_FILE_DIRECTORY_INFO:
897 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
898 case SMB_FIND_FILE_NAMES_INFO:
899 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
900 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
901 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
902 break;
903 case SMB_FIND_FILE_UNIX:
904 case SMB_FIND_FILE_UNIX_INFO2:
905 if (!lp_smb1_unix_extensions()) {
906 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
907 goto out;
909 if (!req->posix_pathnames) {
910 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
911 goto out;
913 break;
914 default:
915 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
916 goto out;
919 if (req->posix_pathnames) {
920 srvstr_get_path_posix(talloc_tos(),
921 params,
922 req->flags2,
923 &directory,
924 params+12,
925 total_params - 12,
926 STR_TERMINATE,
927 &ntstatus);
928 } else {
929 srvstr_get_path(talloc_tos(),
930 params,
931 req->flags2,
932 &directory,
933 params+12,
934 total_params - 12,
935 STR_TERMINATE,
936 &ntstatus);
938 if (!NT_STATUS_IS_OK(ntstatus)) {
939 reply_nterror(req, ntstatus);
940 goto out;
943 if (backup_priv) {
944 become_root();
945 as_root = true;
947 ntstatus = smb1_strip_dfs_path(talloc_tos(), &ucf_flags, &directory);
948 if (!NT_STATUS_IS_OK(ntstatus)) {
949 reply_nterror(req, ntstatus);
950 goto out;
953 ntstatus = filename_convert_smb1_search_path(talloc_tos(),
954 conn,
955 directory,
956 ucf_flags,
957 &dirfsp,
958 &smb_dname,
959 &mask);
961 if (!NT_STATUS_IS_OK(ntstatus)) {
962 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
963 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
964 ERRSRV, ERRbadpath);
965 goto out;
967 reply_nterror(req, ntstatus);
968 goto out;
971 TALLOC_FREE(directory);
972 directory = smb_dname->base_name;
974 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
976 if (info_level == SMB_FIND_EA_LIST) {
977 uint32_t ea_size;
979 if (total_data < 4) {
980 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
981 goto out;
984 ea_size = IVAL(pdata,0);
985 if (ea_size != total_data) {
986 DBG_NOTICE("Rejecting EA request with incorrect "
987 "total_data=%d (should be %" PRIu32 ")\n",
988 total_data,
989 ea_size);
990 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
991 goto out;
994 if (!lp_ea_support(SNUM(conn))) {
995 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
996 goto out;
999 /* Pull out the list of names. */
1000 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
1001 if (!ea_list) {
1002 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1003 goto out;
1007 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1008 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1009 goto out;
1012 *ppdata = (char *)SMB_REALLOC(
1013 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1014 if(*ppdata == NULL ) {
1015 reply_nterror(req, NT_STATUS_NO_MEMORY);
1016 goto out;
1018 pdata = *ppdata;
1019 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1021 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
1022 * error.
1024 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
1025 /* Realloc the params space */
1026 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1027 if (*pparams == NULL) {
1028 reply_nterror(req, NT_STATUS_NO_MEMORY);
1029 goto out;
1031 params = *pparams;
1034 * Open an fsp on this directory for the dptr.
1036 ntstatus = SMB_VFS_CREATE_FILE(
1037 conn, /* conn */
1038 req, /* req */
1039 dirfsp, /* dirfsp */
1040 smb_dname, /* dname */
1041 FILE_LIST_DIRECTORY, /* access_mask */
1042 FILE_SHARE_READ|
1043 FILE_SHARE_WRITE, /* share_access */
1044 FILE_OPEN, /* create_disposition*/
1045 FILE_DIRECTORY_FILE, /* create_options */
1046 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1047 NO_OPLOCK, /* oplock_request */
1048 NULL, /* lease */
1049 0, /* allocation_size */
1050 0, /* private_flags */
1051 NULL, /* sd */
1052 NULL, /* ea_list */
1053 &fsp, /* result */
1054 NULL, /* pinfo */
1055 NULL, /* in_context */
1056 NULL);/* out_context */
1058 if (!NT_STATUS_IS_OK(ntstatus)) {
1059 DBG_ERR("failed to open directory %s\n",
1060 smb_fname_str_dbg(smb_dname));
1061 reply_nterror(req, ntstatus);
1062 goto out;
1065 /* Save the wildcard match and attribs we are using on this directory -
1066 needed as lanman2 assumes these are being saved between calls */
1068 ntstatus = dptr_create(conn,
1069 req,
1070 fsp, /* fsp */
1071 False,
1072 mask,
1073 dirtype,
1074 &fsp->dptr);
1076 if (!NT_STATUS_IS_OK(ntstatus)) {
1078 * Use NULL here for the first parameter (req)
1079 * as this is not a client visible handle so
1080 * can't be part of an SMB1 chain.
1082 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1083 reply_nterror(req, ntstatus);
1084 goto out;
1087 if (backup_priv) {
1088 /* Remember this in case we have
1089 to do a findnext. */
1090 dptr_set_priv(fsp->dptr);
1093 dptr_num = dptr_dnum(fsp->dptr);
1094 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1096 /* We don't need to check for VOL here as this is returned by
1097 a different TRANS2 call. */
1099 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1100 directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
1101 if (in_list(directory,
1102 lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
1103 dptr_case_sensitive(fsp->dptr))) {
1104 dont_descend = True;
1107 p = pdata;
1108 space_remaining = max_data_bytes;
1109 out_of_space = False;
1111 ask_sharemode = fsp_search_ask_sharemode(fsp);
1113 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1115 ntstatus = get_lanman2_dir_entry(talloc_tos(),
1116 conn,
1117 fsp->dptr,
1118 req->flags2,
1119 mask,
1120 dirtype,
1121 info_level,
1122 requires_resume_key,
1123 dont_descend,
1124 ask_sharemode,
1126 pdata,
1127 data_end,
1128 space_remaining,
1129 &last_entry_off,
1130 ea_list);
1131 if (NT_STATUS_EQUAL(ntstatus, NT_STATUS_ILLEGAL_CHARACTER)) {
1133 * Bad character conversion on name. Ignore
1134 * this entry.
1136 continue;
1138 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
1139 out_of_space = true;
1140 } else {
1141 finished = !NT_STATUS_IS_OK(ntstatus);
1144 if (!finished && !out_of_space) {
1145 numentries++;
1148 /* Ensure space_remaining never goes -ve. */
1149 if (PTR_DIFF(p,pdata) > max_data_bytes) {
1150 space_remaining = 0;
1151 out_of_space = true;
1152 } else {
1153 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1157 /* Check if we can close the dirptr */
1158 if(close_after_first || (finished && close_if_end)) {
1159 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1160 dptr_num = -1;
1161 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1165 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1166 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1167 * the protocol level is less than NT1. Tested with smbclient. JRA.
1168 * This should fix the OS/2 client bug #2335.
1171 if(numentries == 0) {
1172 dptr_num = -1;
1174 * We may have already closed the file in the
1175 * close_after_first or finished case above.
1177 if (fsp != NULL) {
1178 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1180 if (xconn->protocol < PROTOCOL_NT1) {
1181 reply_force_doserror(req, ERRDOS, ERRnofiles);
1182 goto out;
1183 } else {
1184 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
1185 ERRDOS, ERRbadfile);
1186 goto out;
1190 /* At this point pdata points to numentries directory entries. */
1192 /* Set up the return parameter block */
1193 SSVAL(params,0,dptr_num);
1194 SSVAL(params,2,numentries);
1195 SSVAL(params,4,finished);
1196 SSVAL(params,6,0); /* Never an EA error */
1197 SSVAL(params,8,last_entry_off);
1199 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
1200 max_data_bytes);
1202 if ((! *directory) && dptr_path(sconn, dptr_num)) {
1203 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
1204 if (!directory) {
1205 reply_nterror(req, NT_STATUS_NO_MEMORY);
1209 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1210 smb_fn_name(req->cmd),
1211 mask, directory, dirtype, numentries ) );
1214 * Force a name mangle here to ensure that the
1215 * mask as an 8.3 name is top of the mangled cache.
1216 * The reasons for this are subtle. Don't remove
1217 * this code unless you know what you are doing
1218 * (see PR#13758). JRA.
1221 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
1222 char mangled_name[13];
1223 name_to_8_3(mask, mangled_name, True, conn->params);
1225 out:
1227 if (as_root) {
1228 unbecome_root();
1231 TALLOC_FREE(smb_dname);
1232 return;
1235 static bool smbd_dptr_name_equal(struct dptr_struct *dptr,
1236 const char *name1,
1237 const char *name2)
1239 bool equal;
1241 if (dptr_case_sensitive(dptr)) {
1242 equal = (strcmp(name1, name2) == 0);
1243 } else {
1244 equal = strequal(name1, name2);
1247 return equal;
1250 /****************************************************************************
1251 Reply to a TRANS2_FINDNEXT.
1252 ****************************************************************************/
1254 static void call_trans2findnext(connection_struct *conn,
1255 struct smb_request *req,
1256 char **pparams, int total_params,
1257 char **ppdata, int total_data,
1258 unsigned int max_data_bytes)
1260 /* We must be careful here that we don't return more than the
1261 allowed number of data bytes. If this means returning fewer than
1262 maxentries then so be it. We assume that the redirector has
1263 enough room for the fixed number of parameter bytes it has
1264 requested. */
1265 char *params = *pparams;
1266 char *pdata = *ppdata;
1267 char *data_end;
1268 int dptr_num;
1269 int maxentries;
1270 uint16_t info_level;
1271 uint32_t resume_key;
1272 uint16_t findnext_flags;
1273 bool close_after_request;
1274 bool close_if_end;
1275 bool requires_resume_key;
1276 bool continue_bit;
1277 char *resume_name = NULL;
1278 const char *mask = NULL;
1279 const char *directory = NULL;
1280 char *p = NULL;
1281 uint16_t dirtype;
1282 int numentries = 0;
1283 int i, last_entry_off=0;
1284 bool finished = False;
1285 bool dont_descend = False;
1286 bool out_of_space = False;
1287 int space_remaining;
1288 struct ea_list *ea_list = NULL;
1289 NTSTATUS ntstatus = NT_STATUS_OK;
1290 bool ask_sharemode;
1291 TALLOC_CTX *ctx = talloc_tos();
1292 struct smbd_server_connection *sconn = req->sconn;
1293 bool backup_priv = false;
1294 bool as_root = false;
1295 files_struct *fsp = NULL;
1296 const struct loadparm_substitution *lp_sub =
1297 loadparm_s3_global_substitution();
1299 if (total_params < 13) {
1300 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1301 return;
1304 dptr_num = SVAL(params,0);
1305 maxentries = SVAL(params,2);
1306 info_level = SVAL(params,4);
1307 resume_key = IVAL(params,6);
1308 findnext_flags = SVAL(params,10);
1309 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1310 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1311 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1312 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1314 if (!continue_bit) {
1315 /* We only need resume_name if continue_bit is zero. */
1316 if (req->posix_pathnames) {
1317 srvstr_get_path_posix(ctx,
1318 params,
1319 req->flags2,
1320 &resume_name,
1321 params+12,
1322 total_params - 12,
1323 STR_TERMINATE,
1324 &ntstatus);
1325 } else {
1326 srvstr_get_path(ctx,
1327 params,
1328 req->flags2,
1329 &resume_name,
1330 params+12,
1331 total_params - 12,
1332 STR_TERMINATE,
1333 &ntstatus);
1335 if (!NT_STATUS_IS_OK(ntstatus)) {
1336 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1337 complain (it thinks we're asking for the directory above the shared
1338 path or an invalid name). Catch this as the resume name is only compared, never used in
1339 a file access. JRA. */
1340 srvstr_pull_talloc(ctx, params, req->flags2,
1341 &resume_name, params+12,
1342 total_params - 12,
1343 STR_TERMINATE);
1345 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
1346 reply_nterror(req, ntstatus);
1347 return;
1352 DBG_NOTICE("dirhandle = %d, max_data_bytes = %u, maxentries = %d, "
1353 "close_after_request=%d, close_if_end = %d "
1354 "requires_resume_key = %d resume_key = %d "
1355 "resume name = %s continue=%d level = %d\n",
1356 dptr_num,
1357 max_data_bytes,
1358 maxentries,
1359 close_after_request,
1360 close_if_end,
1361 requires_resume_key,
1362 resume_key,
1363 resume_name ? resume_name : "(NULL)",
1364 continue_bit,
1365 info_level);
1367 if (!maxentries) {
1368 /* W2K3 seems to treat zero as 1. */
1369 maxentries = 1;
1372 switch (info_level) {
1373 case SMB_FIND_INFO_STANDARD:
1374 case SMB_FIND_EA_SIZE:
1375 case SMB_FIND_EA_LIST:
1376 case SMB_FIND_FILE_DIRECTORY_INFO:
1377 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1378 case SMB_FIND_FILE_NAMES_INFO:
1379 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1380 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1381 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1382 break;
1383 case SMB_FIND_FILE_UNIX:
1384 case SMB_FIND_FILE_UNIX_INFO2:
1385 if (!lp_smb1_unix_extensions()) {
1386 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1387 return;
1389 if (!req->posix_pathnames) {
1390 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1391 return;
1393 break;
1394 default:
1395 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1396 return;
1399 if (info_level == SMB_FIND_EA_LIST) {
1400 uint32_t ea_size;
1402 if (total_data < 4) {
1403 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1404 return;
1407 ea_size = IVAL(pdata,0);
1408 if (ea_size != total_data) {
1409 DBG_NOTICE("Rejecting EA request with incorrect "
1410 "total_data=%d (should be %" PRIu32 ")\n",
1411 total_data,
1412 ea_size);
1413 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1414 return;
1417 if (!lp_ea_support(SNUM(conn))) {
1418 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1419 return;
1422 /* Pull out the list of names. */
1423 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1424 if (!ea_list) {
1425 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1426 return;
1430 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1432 return;
1435 *ppdata = (char *)SMB_REALLOC(
1436 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1437 if(*ppdata == NULL) {
1438 reply_nterror(req, NT_STATUS_NO_MEMORY);
1439 return;
1442 pdata = *ppdata;
1443 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1446 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
1447 * error.
1449 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
1450 /* Realloc the params space */
1451 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1452 if(*pparams == NULL ) {
1453 reply_nterror(req, NT_STATUS_NO_MEMORY);
1454 return;
1457 params = *pparams;
1459 /* Check that the dptr is valid */
1460 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
1461 if (fsp == NULL) {
1462 reply_nterror(req, STATUS_NO_MORE_FILES);
1463 return;
1466 directory = dptr_path(sconn, dptr_num);
1468 /* Get the wildcard mask from the dptr */
1469 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
1470 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1471 reply_nterror(req, STATUS_NO_MORE_FILES);
1472 return;
1475 /* Get the attr mask from the dptr */
1476 dirtype = dptr_attr(sconn, dptr_num);
1478 backup_priv = dptr_get_priv(fsp->dptr);
1480 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX) "
1481 "backup_priv = %d\n",
1482 dptr_num, mask, dirtype,
1483 (long)fsp->dptr,
1484 (int)backup_priv));
1486 /* We don't need to check for VOL here as this is returned by
1487 a different TRANS2 call. */
1489 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1490 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1491 if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),
1492 dptr_case_sensitive(fsp->dptr)))
1493 dont_descend = True;
1495 p = pdata;
1496 space_remaining = max_data_bytes;
1497 out_of_space = False;
1499 if (backup_priv) {
1500 become_root();
1501 as_root = true;
1505 * Seek to the correct position. We no longer use the resume key but
1506 * depend on the last file name instead.
1509 if(!continue_bit && resume_name && *resume_name) {
1510 bool posix_open = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN);
1511 char *last_name_sent = NULL;
1512 bool sequential;
1515 * Remember, name_to_8_3 is called by
1516 * get_lanman2_dir_entry(), so the resume name
1517 * could be mangled. Ensure we check the unmangled name.
1520 if (!posix_open &&
1521 mangle_is_mangled(resume_name, conn->params)) {
1522 char *new_resume_name = NULL;
1523 mangle_lookup_name_from_8_3(ctx,
1524 resume_name,
1525 &new_resume_name,
1526 conn->params);
1527 if (new_resume_name) {
1528 resume_name = new_resume_name;
1533 * Fix for NT redirector problem triggered by resume key indexes
1534 * changing between directory scans. We now return a resume key of 0
1535 * and instead look for the filename to continue from (also given
1536 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1537 * findfirst/findnext (as is usual) then the directory pointer
1538 * should already be at the correct place.
1541 last_name_sent = smbd_dirptr_get_last_name_sent(fsp->dptr);
1542 sequential = smbd_dptr_name_equal(fsp->dptr,
1543 resume_name,
1544 last_name_sent);
1545 if (!sequential) {
1546 char *name = NULL;
1547 bool found = false;
1549 dptr_RewindDir(fsp->dptr);
1551 while ((name = dptr_ReadDirName(talloc_tos(),
1552 fsp->dptr)) != NULL) {
1553 found = smbd_dptr_name_equal(fsp->dptr,
1554 resume_name,
1555 name);
1556 TALLOC_FREE(name);
1557 if (found) {
1558 break;
1562 if (!found) {
1564 * We got a name that used to exist
1565 * but does not anymore. Just start
1566 * from the beginning. Shown by the
1567 * "raw.search.os2 delete" smbtorture
1568 * test.
1570 dptr_RewindDir(fsp->dptr);
1573 } /* end if resume_name && !continue_bit */
1575 ask_sharemode = fsp_search_ask_sharemode(fsp);
1577 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1579 ntstatus = get_lanman2_dir_entry(ctx,
1580 conn,
1581 fsp->dptr,
1582 req->flags2,
1583 mask,
1584 dirtype,
1585 info_level,
1586 requires_resume_key,
1587 dont_descend,
1588 ask_sharemode,
1590 pdata,
1591 data_end,
1592 space_remaining,
1593 &last_entry_off,
1594 ea_list);
1595 if (NT_STATUS_EQUAL(ntstatus, NT_STATUS_ILLEGAL_CHARACTER)) {
1597 * Bad character conversion on name. Ignore
1598 * this entry.
1600 continue;
1602 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
1603 out_of_space = true;
1604 } else {
1605 finished = !NT_STATUS_IS_OK(ntstatus);
1608 if (!finished && !out_of_space) {
1609 numentries++;
1612 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1615 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1616 smb_fn_name(req->cmd),
1617 mask, directory, dirtype, numentries ) );
1619 /* Check if we can close the fsp->dptr */
1620 if(close_after_request || (finished && close_if_end)) {
1621 DBG_INFO("closing dptr_num = %d\n", dptr_num);
1622 dptr_num = -1;
1623 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1626 if (as_root) {
1627 unbecome_root();
1630 /* Set up the return parameter block */
1631 SSVAL(params,0,numentries);
1632 SSVAL(params,2,finished);
1633 SSVAL(params,4,0); /* Never an EA error */
1634 SSVAL(params,6,last_entry_off);
1636 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
1637 max_data_bytes);
1639 return;
1642 /****************************************************************************
1643 Reply to a TRANS2_QFSINFO (query filesystem info).
1644 ****************************************************************************/
1646 static void call_trans2qfsinfo(connection_struct *conn,
1647 struct smb_request *req,
1648 char **pparams, int total_params,
1649 char **ppdata, int total_data,
1650 unsigned int max_data_bytes)
1652 char *params = *pparams;
1653 uint16_t info_level;
1654 int data_len = 0;
1655 size_t fixed_portion;
1656 NTSTATUS status;
1658 if (total_params < 2) {
1659 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1660 return;
1663 info_level = SVAL(params,0);
1665 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
1666 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
1667 DEBUG(0,("call_trans2qfsinfo: encryption required "
1668 "and info level 0x%x sent.\n",
1669 (unsigned int)info_level));
1670 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1671 return;
1675 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1677 status = smbd_do_qfsinfo(req->xconn, conn, req,
1678 info_level,
1679 req->flags2,
1680 max_data_bytes,
1681 &fixed_portion,
1682 NULL,
1683 NULL,
1684 ppdata, &data_len);
1685 if (!NT_STATUS_IS_OK(status)) {
1686 reply_nterror(req, status);
1687 return;
1690 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
1691 max_data_bytes);
1693 DEBUG( 4, ( "%s info_level = %d\n",
1694 smb_fn_name(req->cmd), info_level) );
1696 return;
1699 /****************************************************************************
1700 Reply to a TRANS2_SETFSINFO (set filesystem info).
1701 ****************************************************************************/
1703 static void call_trans2setfsinfo(connection_struct *conn,
1704 struct smb_request *req,
1705 char **pparams, int total_params,
1706 char **ppdata, int total_data,
1707 unsigned int max_data_bytes)
1709 const struct loadparm_substitution *lp_sub =
1710 loadparm_s3_global_substitution();
1711 struct smbXsrv_connection *xconn = req->xconn;
1712 char *pdata = *ppdata;
1713 char *params = *pparams;
1714 uint16_t info_level;
1716 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
1717 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
1719 /* */
1720 if (total_params < 4) {
1721 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1722 total_params));
1723 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1724 return;
1727 info_level = SVAL(params,2);
1729 if (IS_IPC(conn)) {
1730 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
1731 info_level != SMB_SET_CIFS_UNIX_INFO) {
1732 DEBUG(0,("call_trans2setfsinfo: not an allowed "
1733 "info level (0x%x) on IPC$.\n",
1734 (unsigned int)info_level));
1735 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1736 return;
1740 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
1741 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
1742 DEBUG(0,("call_trans2setfsinfo: encryption required "
1743 "and info level 0x%x sent.\n",
1744 (unsigned int)info_level));
1745 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1746 return;
1750 switch(info_level) {
1751 case SMB_SET_CIFS_UNIX_INFO:
1752 if (!lp_smb1_unix_extensions()) {
1753 DEBUG(2,("call_trans2setfsinfo: "
1754 "SMB_SET_CIFS_UNIX_INFO is invalid with "
1755 "unix extensions off\n"));
1756 reply_nterror(req,
1757 NT_STATUS_INVALID_LEVEL);
1758 return;
1761 /* There should be 12 bytes of capabilities set. */
1762 if (total_data < 12) {
1763 reply_nterror(
1764 req,
1765 NT_STATUS_INVALID_PARAMETER);
1766 return;
1768 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
1769 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
1770 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
1771 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
1773 /* Just print these values for now. */
1774 DBG_DEBUG("set unix_info info. "
1775 "major = %"PRIu16", minor = %"PRIu16
1776 "cap_low = 0x%"PRIx32", "
1777 "cap_high = 0x%"PRIx32"\n",
1778 xconn->smb1.unix_info.client_major,
1779 xconn->smb1.unix_info.client_minor,
1780 xconn->smb1.unix_info.client_cap_low,
1781 xconn->smb1.unix_info.client_cap_high);
1784 * Here is where we must switch to posix
1785 * pathname processing...
1787 if (xconn->smb1.unix_info.client_cap_low &
1788 CIFS_UNIX_POSIX_PATHNAMES_CAP)
1790 lp_set_posix_pathnames();
1791 mangle_change_to_posix();
1794 if ((xconn->smb1.unix_info.client_cap_low &
1795 CIFS_UNIX_FCNTL_LOCKS_CAP) &&
1796 !(xconn->smb1.unix_info.client_cap_low &
1797 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP))
1799 /* Client that knows how to do posix locks,
1800 * but not posix open/mkdir operations. Set a
1801 * default type for read/write checks. */
1803 lp_set_posix_default_cifsx_readwrite_locktype(
1804 POSIX_LOCK);
1807 break;
1809 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
1811 NTSTATUS status;
1812 size_t param_len = 0;
1813 size_t data_len = total_data;
1815 if (!lp_smb1_unix_extensions()) {
1816 reply_nterror(
1817 req,
1818 NT_STATUS_INVALID_LEVEL);
1819 return;
1822 if (lp_server_smb_encrypt(SNUM(conn)) ==
1823 SMB_ENCRYPTION_OFF) {
1824 reply_nterror(
1825 req,
1826 NT_STATUS_NOT_SUPPORTED);
1827 return;
1830 if (xconn->smb1.echo_handler.trusted_fde) {
1831 DEBUG( 2,("call_trans2setfsinfo: "
1832 "request transport encryption disabled"
1833 "with 'fork echo handler = yes'\n"));
1834 reply_nterror(
1835 req,
1836 NT_STATUS_NOT_SUPPORTED);
1837 return;
1840 DEBUG( 4,("call_trans2setfsinfo: "
1841 "request transport encryption.\n"));
1843 status = srv_request_encryption_setup(conn,
1844 (unsigned char **)ppdata,
1845 &data_len,
1846 (unsigned char **)pparams,
1847 &param_len);
1849 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
1850 !NT_STATUS_IS_OK(status)) {
1851 reply_nterror(req, status);
1852 return;
1855 send_trans2_replies(conn, req,
1856 NT_STATUS_OK,
1857 *pparams,
1858 param_len,
1859 *ppdata,
1860 data_len,
1861 max_data_bytes);
1863 if (NT_STATUS_IS_OK(status)) {
1864 /* Server-side transport
1865 * encryption is now *on*. */
1866 status = srv_encryption_start(conn);
1867 if (!NT_STATUS_IS_OK(status)) {
1868 char *reason = talloc_asprintf(talloc_tos(),
1869 "Failure in setting "
1870 "up encrypted transport: %s",
1871 nt_errstr(status));
1872 exit_server_cleanly(reason);
1875 return;
1878 case SMB_FS_QUOTA_INFORMATION:
1880 NTSTATUS status;
1881 DATA_BLOB qdata = {
1882 .data = (uint8_t *)pdata,
1883 .length = total_data
1885 files_struct *fsp = NULL;
1886 fsp = file_fsp(req, SVAL(params,0));
1888 status = smb_set_fsquota(conn,
1889 req,
1890 fsp,
1891 &qdata);
1892 if (!NT_STATUS_IS_OK(status)) {
1893 reply_nterror(req, status);
1894 return;
1896 break;
1898 default:
1899 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1900 info_level));
1901 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1902 return;
1903 break;
1907 * sending this reply works fine,
1908 * but I'm not sure it's the same
1909 * like windows do...
1910 * --metze
1912 reply_smb1_outbuf(req, 10, 0);
1915 /****************************************************************************
1916 Reply to a TRANSACT2_QFILEINFO on a PIPE !
1917 ****************************************************************************/
1919 static void call_trans2qpipeinfo(connection_struct *conn,
1920 struct smb_request *req,
1921 files_struct *fsp,
1922 uint16_t info_level,
1923 unsigned int tran_call,
1924 char **pparams, int total_params,
1925 char **ppdata, int total_data,
1926 unsigned int max_data_bytes)
1928 char *params = *pparams;
1929 char *pdata = *ppdata;
1930 unsigned int data_size = 0;
1931 unsigned int param_size = 2;
1933 if (!fsp_is_np(fsp)) {
1934 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1935 return;
1938 *pparams = (char *)SMB_REALLOC(*pparams,2);
1939 if (*pparams == NULL) {
1940 reply_nterror(req, NT_STATUS_NO_MEMORY);
1941 return;
1943 params = *pparams;
1944 SSVAL(params,0,0);
1945 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1946 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1947 return;
1949 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
1950 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
1951 if (*ppdata == NULL ) {
1952 reply_nterror(req, NT_STATUS_NO_MEMORY);
1953 return;
1955 pdata = *ppdata;
1957 switch (info_level) {
1958 case SMB_FILE_STANDARD_INFORMATION:
1959 memset(pdata,0,24);
1960 SOFF_T(pdata,0,4096LL);
1961 SIVAL(pdata,16,1);
1962 SIVAL(pdata,20,1);
1963 data_size = 24;
1964 break;
1966 default:
1967 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1968 return;
1971 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
1972 max_data_bytes);
1975 static void handle_trans2qfilepathinfo_result(
1976 connection_struct *conn,
1977 struct smb_request *req,
1978 uint16_t info_level,
1979 NTSTATUS status,
1980 char *pdata,
1981 int data_return_size,
1982 size_t fixed_portion,
1983 unsigned int max_data_bytes)
1985 char params[2] = { 0, 0, };
1986 int param_size = 2;
1989 * draft-leach-cifs-v1-spec-02.txt
1990 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
1991 * says:
1993 * The requested information is placed in the Data portion of the
1994 * transaction response. For the information levels greater than 0x100,
1995 * the transaction response has 1 parameter word which should be
1996 * ignored by the client.
1998 * However Windows only follows this rule for the IS_NAME_VALID call.
2000 switch (info_level) {
2001 case SMB_INFO_IS_NAME_VALID:
2002 param_size = 0;
2003 break;
2006 if (!NT_STATUS_IS_OK(status)) {
2007 if (open_was_deferred(req->xconn, req->mid)) {
2008 /* We have re-scheduled this call. */
2009 return;
2011 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2012 bool ok = defer_smb1_sharing_violation(req);
2013 if (ok) {
2014 return;
2017 reply_nterror(req, status);
2018 return;
2021 if (fixed_portion > max_data_bytes) {
2022 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
2023 return;
2026 send_trans2_replies(
2027 conn,
2028 req,
2029 NT_STATUS_OK,
2030 params,
2031 param_size,
2032 pdata,
2033 data_return_size,
2034 max_data_bytes);
2037 /****************************************************************************
2038 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2039 file name or file id).
2040 ****************************************************************************/
2042 static void call_trans2qfilepathinfo(connection_struct *conn,
2043 struct smb_request *req,
2044 unsigned int tran_call,
2045 uint16_t info_level,
2046 struct smb_filename *smb_fname,
2047 struct files_struct *fsp,
2048 bool delete_pending,
2049 struct timespec write_time_ts,
2050 char **pparams, int total_params,
2051 char **ppdata, int total_data,
2052 unsigned int max_data_bytes)
2054 char *params = *pparams;
2055 char *pdata = *ppdata;
2056 unsigned int data_size = 0;
2057 struct ea_list *ea_list = NULL;
2058 size_t fixed_portion;
2059 NTSTATUS status = NT_STATUS_OK;
2061 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
2062 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
2063 fsp_fnum_dbg(fsp),
2064 info_level,tran_call,total_data));
2066 /* Pull out any data sent here before we realloc. */
2067 switch (info_level) {
2068 case SMB_INFO_QUERY_EAS_FROM_LIST:
2070 /* Pull any EA list from the data portion. */
2071 uint32_t ea_size;
2073 if (total_data < 4) {
2074 reply_nterror(
2075 req, NT_STATUS_INVALID_PARAMETER);
2076 return;
2078 ea_size = IVAL(pdata,0);
2080 if (total_data > 0 && ea_size != total_data) {
2081 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2082 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2083 reply_nterror(
2084 req, NT_STATUS_INVALID_PARAMETER);
2085 return;
2088 if (!lp_ea_support(SNUM(conn))) {
2089 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2090 return;
2093 /* Pull out the list of names. */
2094 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
2095 if (!ea_list) {
2096 reply_nterror(
2097 req, NT_STATUS_INVALID_PARAMETER);
2098 return;
2100 break;
2103 default:
2104 break;
2107 *pparams = (char *)SMB_REALLOC(*pparams,2);
2108 if (*pparams == NULL) {
2109 reply_nterror(req, NT_STATUS_NO_MEMORY);
2110 return;
2112 params = *pparams;
2113 SSVAL(params,0,0);
2115 if ((info_level & SMB2_INFO_SPECIAL) == SMB2_INFO_SPECIAL) {
2117 * We use levels that start with 0xFF00
2118 * internally to represent SMB2 specific levels
2120 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2121 return;
2124 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
2125 fsp, smb_fname,
2126 delete_pending, write_time_ts,
2127 ea_list,
2128 req->flags2, max_data_bytes,
2129 &fixed_portion,
2130 ppdata, &data_size);
2132 handle_trans2qfilepathinfo_result(
2133 conn,
2134 req,
2135 info_level,
2136 status,
2137 *ppdata,
2138 data_size,
2139 fixed_portion,
2140 max_data_bytes);
2143 static NTSTATUS smb_q_unix_basic(
2144 struct connection_struct *conn,
2145 struct smb_request *req,
2146 struct smb_filename *smb_fname,
2147 struct files_struct *fsp,
2148 char **ppdata,
2149 int *ptotal_data)
2151 const int total_data = 100;
2153 *ppdata = SMB_REALLOC(*ppdata, total_data);
2154 if (*ppdata == NULL) {
2155 return NT_STATUS_NO_MEMORY;
2157 store_file_unix_basic(conn, *ppdata, fsp, &smb_fname->st);
2159 *ptotal_data = total_data;
2161 return NT_STATUS_OK;
2164 static NTSTATUS smb_q_unix_info2(
2165 struct connection_struct *conn,
2166 struct smb_request *req,
2167 struct smb_filename *smb_fname,
2168 struct files_struct *fsp,
2169 char **ppdata,
2170 int *ptotal_data)
2172 const int total_data = 116;
2174 *ppdata = SMB_REALLOC(*ppdata, total_data);
2175 if (*ppdata == NULL) {
2176 return NT_STATUS_NO_MEMORY;
2178 store_file_unix_basic_info2(conn, *ppdata, fsp, &smb_fname->st);
2180 *ptotal_data = total_data;
2182 return NT_STATUS_OK;
2185 #if defined(HAVE_POSIX_ACLS)
2186 /****************************************************************************
2187 Utility function to open a fsp for a POSIX handle operation.
2188 ****************************************************************************/
2190 static NTSTATUS get_posix_fsp(connection_struct *conn,
2191 struct smb_request *req,
2192 struct smb_filename *smb_fname,
2193 uint32_t access_mask,
2194 files_struct **ret_fsp)
2196 NTSTATUS status;
2197 uint32_t create_disposition = FILE_OPEN;
2198 uint32_t share_access = FILE_SHARE_READ|
2199 FILE_SHARE_WRITE|
2200 FILE_SHARE_DELETE;
2201 struct smb2_create_blobs *posx = NULL;
2204 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
2205 * but set reasonable defaults.
2207 uint32_t file_attributes = 0664;
2208 uint32_t oplock = NO_OPLOCK;
2209 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
2211 /* File or directory must exist. */
2212 if (!VALID_STAT(smb_fname->st)) {
2213 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2215 /* Cannot be a symlink. */
2216 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
2217 return NT_STATUS_ACCESS_DENIED;
2219 /* Set options correctly for directory open. */
2220 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
2222 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
2223 * directories, but set reasonable defaults.
2225 file_attributes = 0775;
2226 create_options = FILE_DIRECTORY_FILE;
2229 status = make_smb2_posix_create_ctx(
2230 talloc_tos(), &posx, file_attributes);
2231 if (!NT_STATUS_IS_OK(status)) {
2232 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
2233 nt_errstr(status));
2234 goto done;
2237 status = SMB_VFS_CREATE_FILE(
2238 conn, /* conn */
2239 req, /* req */
2240 NULL, /* dirfsp */
2241 smb_fname, /* fname */
2242 access_mask, /* access_mask */
2243 share_access, /* share_access */
2244 create_disposition,/* create_disposition*/
2245 create_options, /* create_options */
2246 file_attributes,/* file_attributes */
2247 oplock, /* oplock_request */
2248 NULL, /* lease */
2249 0, /* allocation_size */
2250 0, /* private_flags */
2251 NULL, /* sd */
2252 NULL, /* ea_list */
2253 ret_fsp, /* result */
2254 NULL, /* pinfo */
2255 posx, /* in_context */
2256 NULL); /* out_context */
2258 done:
2259 TALLOC_FREE(posx);
2260 return status;
2263 /****************************************************************************
2264 Utility function to count the number of entries in a POSIX acl.
2265 ****************************************************************************/
2267 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2269 unsigned int ace_count = 0;
2270 int entry_id = SMB_ACL_FIRST_ENTRY;
2271 SMB_ACL_ENTRY_T entry;
2273 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2274 entry_id = SMB_ACL_NEXT_ENTRY;
2275 ace_count++;
2277 return ace_count;
2280 /****************************************************************************
2281 Utility function to marshall a POSIX acl into wire format.
2282 ****************************************************************************/
2284 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2286 int entry_id = SMB_ACL_FIRST_ENTRY;
2287 SMB_ACL_ENTRY_T entry;
2289 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2290 SMB_ACL_TAG_T tagtype;
2291 SMB_ACL_PERMSET_T permset;
2292 unsigned char perms = 0;
2293 unsigned int own_grp;
2295 entry_id = SMB_ACL_NEXT_ENTRY;
2297 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
2298 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2299 return False;
2302 if (sys_acl_get_permset(entry, &permset) == -1) {
2303 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2304 return False;
2307 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2308 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2309 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2311 SCVAL(pdata,1,perms);
2313 switch (tagtype) {
2314 case SMB_ACL_USER_OBJ:
2315 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2316 own_grp = (unsigned int)pst->st_ex_uid;
2317 SIVAL(pdata,2,own_grp);
2318 SIVAL(pdata,6,0);
2319 break;
2320 case SMB_ACL_USER:
2322 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
2323 if (!puid) {
2324 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2325 return False;
2327 own_grp = (unsigned int)*puid;
2328 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2329 SIVAL(pdata,2,own_grp);
2330 SIVAL(pdata,6,0);
2331 break;
2333 case SMB_ACL_GROUP_OBJ:
2334 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2335 own_grp = (unsigned int)pst->st_ex_gid;
2336 SIVAL(pdata,2,own_grp);
2337 SIVAL(pdata,6,0);
2338 break;
2339 case SMB_ACL_GROUP:
2341 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
2342 if (!pgid) {
2343 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2344 return False;
2346 own_grp = (unsigned int)*pgid;
2347 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2348 SIVAL(pdata,2,own_grp);
2349 SIVAL(pdata,6,0);
2350 break;
2352 case SMB_ACL_MASK:
2353 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2354 SIVAL(pdata,2,0xFFFFFFFF);
2355 SIVAL(pdata,6,0xFFFFFFFF);
2356 break;
2357 case SMB_ACL_OTHER:
2358 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2359 SIVAL(pdata,2,0xFFFFFFFF);
2360 SIVAL(pdata,6,0xFFFFFFFF);
2361 break;
2362 default:
2363 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2364 return False;
2366 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2369 return True;
2371 #endif
2373 static NTSTATUS smb_q_posix_acl(
2374 struct connection_struct *conn,
2375 struct smb_request *req,
2376 struct smb_filename *smb_fname,
2377 struct files_struct *fsp,
2378 char **ppdata,
2379 int *ptotal_data)
2381 #if !defined(HAVE_POSIX_ACLS)
2382 return NT_STATUS_INVALID_LEVEL;
2383 #else
2384 char *pdata = NULL;
2385 SMB_ACL_T file_acl = NULL;
2386 SMB_ACL_T def_acl = NULL;
2387 uint16_t num_file_acls = 0;
2388 uint16_t num_def_acls = 0;
2389 unsigned int size_needed = 0;
2390 NTSTATUS status;
2391 bool ok;
2392 bool close_fsp = false;
2395 * Ensure we always operate on a file descriptor, not just
2396 * the filename.
2398 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
2399 uint32_t access_mask = SEC_STD_READ_CONTROL|
2400 FILE_READ_ATTRIBUTES|
2401 FILE_WRITE_ATTRIBUTES;
2403 status = get_posix_fsp(conn,
2404 req,
2405 smb_fname,
2406 access_mask,
2407 &fsp);
2409 if (!NT_STATUS_IS_OK(status)) {
2410 goto out;
2412 close_fsp = true;
2415 SMB_ASSERT(fsp != NULL);
2417 status = refuse_symlink_fsp(fsp);
2418 if (!NT_STATUS_IS_OK(status)) {
2419 goto out;
2422 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, SMB_ACL_TYPE_ACCESS,
2423 talloc_tos());
2425 if (file_acl == NULL && no_acl_syscall_error(errno)) {
2426 DBG_INFO("ACLs not implemented on "
2427 "filesystem containing %s\n",
2428 fsp_str_dbg(fsp));
2429 status = NT_STATUS_NOT_IMPLEMENTED;
2430 goto out;
2433 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2435 * We can only have default POSIX ACLs on
2436 * directories.
2438 if (!fsp->fsp_flags.is_directory) {
2439 DBG_INFO("Non-directory open %s\n",
2440 fsp_str_dbg(fsp));
2441 status = NT_STATUS_INVALID_HANDLE;
2442 goto out;
2444 def_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
2445 SMB_ACL_TYPE_DEFAULT,
2446 talloc_tos());
2447 def_acl = free_empty_sys_acl(conn, def_acl);
2450 num_file_acls = count_acl_entries(conn, file_acl);
2451 num_def_acls = count_acl_entries(conn, def_acl);
2453 /* Wrap checks. */
2454 if (num_file_acls + num_def_acls < num_file_acls) {
2455 status = NT_STATUS_INVALID_PARAMETER;
2456 goto out;
2459 size_needed = num_file_acls + num_def_acls;
2462 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
2463 * than UINT_MAX, so check by division.
2465 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
2466 status = NT_STATUS_INVALID_PARAMETER;
2467 goto out;
2470 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
2471 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
2472 status = NT_STATUS_INVALID_PARAMETER;
2473 goto out;
2475 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
2477 *ppdata = SMB_REALLOC(*ppdata, size_needed);
2478 if (*ppdata == NULL) {
2479 status = NT_STATUS_NO_MEMORY;
2480 goto out;
2482 pdata = *ppdata;
2484 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
2485 SSVAL(pdata,2,num_file_acls);
2486 SSVAL(pdata,4,num_def_acls);
2487 pdata += SMB_POSIX_ACL_HEADER_SIZE;
2489 ok = marshall_posix_acl(conn,
2490 pdata,
2491 &fsp->fsp_name->st,
2492 file_acl);
2493 if (!ok) {
2494 status = NT_STATUS_INTERNAL_ERROR;
2495 goto out;
2497 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
2499 ok = marshall_posix_acl(conn,
2500 pdata,
2501 &fsp->fsp_name->st,
2502 def_acl);
2503 if (!ok) {
2504 status = NT_STATUS_INTERNAL_ERROR;
2505 goto out;
2508 *ptotal_data = size_needed;
2509 status = NT_STATUS_OK;
2511 out:
2513 if (close_fsp) {
2515 * Ensure the stat struct in smb_fname is up to
2516 * date. Structure copy.
2518 smb_fname->st = fsp->fsp_name->st;
2519 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
2522 TALLOC_FREE(file_acl);
2523 TALLOC_FREE(def_acl);
2524 return status;
2525 #endif
2528 static NTSTATUS smb_q_posix_symlink(
2529 struct connection_struct *conn,
2530 struct smb_request *req,
2531 struct smb_filename *smb_fname,
2532 char **ppdata,
2533 int *ptotal_data)
2535 char buffer[PATH_MAX+1];
2536 size_t needed, len;
2537 int link_len;
2538 char *pdata = NULL;
2539 struct smb_filename *parent_fname = NULL;
2540 struct smb_filename *base_name = 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 status = parent_pathref(
2551 talloc_tos(),
2552 conn->cwd_fsp,
2553 smb_fname,
2554 &parent_fname,
2555 &base_name);
2557 if (!NT_STATUS_IS_OK(status)) {
2558 DBG_DEBUG("parent_pathref failed: %s\n", nt_errstr(status));
2559 return status;
2562 link_len = SMB_VFS_READLINKAT(
2563 conn,
2564 parent_fname->fsp,
2565 base_name,
2566 buffer,
2567 sizeof(buffer)-1);
2568 TALLOC_FREE(parent_fname);
2570 if (link_len == -1) {
2571 status = map_nt_error_from_unix(errno);
2572 DBG_DEBUG("READLINKAT failed: %s\n", nt_errstr(status));
2573 return status;
2575 if (link_len >= sizeof(buffer)) {
2576 return NT_STATUS_INTERNAL_ERROR;
2578 buffer[link_len] = 0;
2580 needed = (link_len+1)*2;
2582 *ppdata = SMB_REALLOC(*ppdata, needed);
2583 if (*ppdata == NULL) {
2584 return NT_STATUS_NO_MEMORY;
2586 pdata = *ppdata;
2588 status = srvstr_push(
2589 pdata,
2590 req->flags2,
2591 pdata,
2592 buffer,
2593 needed,
2594 STR_TERMINATE,
2595 &len);
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 struct file_id fileid;
2621 uint32_t name_hash;
2622 char *fname = NULL;
2623 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2624 NTTIME twrp = 0;
2625 bool info_level_handled;
2626 NTSTATUS status = NT_STATUS_OK;
2627 int ret;
2629 if (!params) {
2630 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2631 return;
2635 /* qpathinfo */
2636 if (total_params < 7) {
2637 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2638 return;
2641 info_level = SVAL(params,0);
2643 DBG_NOTICE("TRANSACT2_QPATHINFO: level = %d\n", info_level);
2645 if (INFO_LEVEL_IS_UNIX(info_level)) {
2646 if (!lp_smb1_unix_extensions()) {
2647 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2648 return;
2650 if (!req->posix_pathnames) {
2651 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2652 return;
2656 if (req->posix_pathnames) {
2657 srvstr_get_path_posix(req,
2658 params,
2659 req->flags2,
2660 &fname,
2661 &params[6],
2662 total_params - 6,
2663 STR_TERMINATE,
2664 &status);
2665 } else {
2666 srvstr_get_path(req,
2667 params,
2668 req->flags2,
2669 &fname,
2670 &params[6],
2671 total_params - 6,
2672 STR_TERMINATE,
2673 &status);
2675 if (!NT_STATUS_IS_OK(status)) {
2676 reply_nterror(req, status);
2677 return;
2680 if (ucf_flags & UCF_GMT_PATHNAME) {
2681 extract_snapshot_token(fname, &twrp);
2683 status = smb1_strip_dfs_path(req, &ucf_flags, &fname);
2684 if (!NT_STATUS_IS_OK(status)) {
2685 reply_nterror(req, status);
2686 return;
2688 status = filename_convert_dirfsp(req,
2689 conn,
2690 fname,
2691 ucf_flags,
2692 twrp,
2693 &dirfsp,
2694 &smb_fname);
2695 if (!NT_STATUS_IS_OK(status)) {
2696 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2697 reply_botherror(req,
2698 NT_STATUS_PATH_NOT_COVERED,
2699 ERRSRV, ERRbadpath);
2700 return;
2702 reply_nterror(req, status);
2703 return;
2707 * qpathinfo must operate on an existing file, so we
2708 * can exit early if filename_convert_dirfsp() returned the
2709 * "new file" NT_STATUS_OK, !VALID_STAT case.
2712 if (!VALID_STAT(smb_fname->st)) {
2713 reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2714 return;
2718 * smb_fname->fsp may be NULL if smb_fname points at a symlink
2719 * and we're in POSIX context, so be careful when using fsp
2720 * below, it can still be NULL.
2722 fsp = smb_fname->fsp;
2724 /* If this is a stream, check if there is a delete_pending. */
2725 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
2726 && is_ntfs_stream_smb_fname(smb_fname)) {
2727 struct smb_filename *smb_fname_base;
2729 /* Create an smb_filename with stream_name == NULL. */
2730 smb_fname_base = synthetic_smb_fname(
2731 talloc_tos(),
2732 smb_fname->base_name,
2733 NULL,
2734 NULL,
2735 smb_fname->twrp,
2736 smb_fname->flags);
2737 if (smb_fname_base == NULL) {
2738 reply_nterror(req, NT_STATUS_NO_MEMORY);
2739 return;
2742 ret = vfs_stat(conn, smb_fname_base);
2743 if (ret != 0) {
2744 DBG_NOTICE("vfs_stat of %s failed "
2745 "(%s)\n",
2746 smb_fname_str_dbg(smb_fname_base),
2747 strerror(errno));
2748 TALLOC_FREE(smb_fname_base);
2749 reply_nterror(req,
2750 map_nt_error_from_unix(errno));
2751 return;
2754 status = file_name_hash(conn,
2755 smb_fname_str_dbg(smb_fname_base),
2756 &name_hash);
2757 if (!NT_STATUS_IS_OK(status)) {
2758 TALLOC_FREE(smb_fname_base);
2759 reply_nterror(req, status);
2760 return;
2763 fileid = vfs_file_id_from_sbuf(conn,
2764 &smb_fname_base->st);
2765 TALLOC_FREE(smb_fname_base);
2766 get_file_infos(fileid, name_hash, &delete_pending, NULL);
2767 if (delete_pending) {
2768 reply_nterror(req, NT_STATUS_DELETE_PENDING);
2769 return;
2773 status = file_name_hash(conn,
2774 smb_fname_str_dbg(smb_fname),
2775 &name_hash);
2776 if (!NT_STATUS_IS_OK(status)) {
2777 reply_nterror(req, status);
2778 return;
2781 if (fsp_getinfo_ask_sharemode(fsp)) {
2782 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2783 get_file_infos(fileid, name_hash, &delete_pending,
2784 &write_time_ts);
2787 if (delete_pending) {
2788 reply_nterror(req, NT_STATUS_DELETE_PENDING);
2789 return;
2792 info_level_handled = true; /* Untouched in switch cases below */
2794 switch (info_level) {
2796 default:
2797 info_level_handled = false;
2798 break;
2800 case SMB_QUERY_FILE_UNIX_BASIC:
2801 status = smb_q_unix_basic(
2802 conn,
2803 req,
2804 smb_fname,
2805 smb_fname->fsp,
2806 ppdata,
2807 &total_data);
2808 break;
2810 case SMB_QUERY_FILE_UNIX_INFO2:
2811 status = smb_q_unix_info2(
2812 conn,
2813 req,
2814 smb_fname,
2815 smb_fname->fsp,
2816 ppdata,
2817 &total_data);
2818 break;
2820 case SMB_QUERY_POSIX_ACL:
2821 status = smb_q_posix_acl(
2822 conn,
2823 req,
2824 smb_fname,
2825 smb_fname->fsp,
2826 ppdata,
2827 &total_data);
2828 break;
2830 case SMB_QUERY_FILE_UNIX_LINK:
2831 status = smb_q_posix_symlink(
2832 conn,
2833 req,
2834 smb_fname,
2835 ppdata,
2836 &total_data);
2837 break;
2840 if (info_level_handled) {
2841 handle_trans2qfilepathinfo_result(
2842 conn,
2843 req,
2844 info_level,
2845 status,
2846 *ppdata,
2847 total_data,
2848 total_data,
2849 max_data_bytes);
2850 return;
2853 call_trans2qfilepathinfo(
2854 conn,
2855 req,
2856 TRANSACT2_QPATHINFO,
2857 info_level,
2858 smb_fname,
2859 fsp,
2860 false,
2861 write_time_ts,
2862 pparams,
2863 total_params,
2864 ppdata,
2865 total_data,
2866 max_data_bytes);
2869 static NTSTATUS smb_q_posix_lock(
2870 struct connection_struct *conn,
2871 struct smb_request *req,
2872 struct files_struct *fsp,
2873 char **ppdata,
2874 int *ptotal_data)
2876 char *pdata = *ppdata;
2877 int total_data = *ptotal_data;
2878 uint64_t count;
2879 uint64_t offset;
2880 uint64_t smblctx;
2881 enum brl_type lock_type;
2882 NTSTATUS status;
2884 if (fsp->fsp_flags.is_pathref || (fsp_get_io_fd(fsp) == -1)) {
2885 return NT_STATUS_INVALID_HANDLE;
2888 if (total_data != POSIX_LOCK_DATA_SIZE) {
2889 return NT_STATUS_INVALID_PARAMETER;
2892 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
2893 case POSIX_LOCK_TYPE_READ:
2894 lock_type = READ_LOCK;
2895 break;
2896 case POSIX_LOCK_TYPE_WRITE:
2897 lock_type = WRITE_LOCK;
2898 break;
2899 case POSIX_LOCK_TYPE_UNLOCK:
2900 default:
2901 /* There's no point in asking for an unlock... */
2902 return NT_STATUS_INVALID_PARAMETER;
2905 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
2906 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
2907 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
2909 status = query_lock(
2910 fsp,
2911 &smblctx,
2912 &count,
2913 &offset,
2914 &lock_type,
2915 POSIX_LOCK);
2917 if (NT_STATUS_IS_OK(status)) {
2919 * For success we just return a copy of what we sent
2920 * with the lock type set to POSIX_LOCK_TYPE_UNLOCK.
2922 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
2923 return NT_STATUS_OK;
2926 if (!ERROR_WAS_LOCK_DENIED(status)) {
2927 DBG_DEBUG("query_lock() failed: %s\n", nt_errstr(status));
2928 return status;
2932 * Here we need to report who has it locked.
2935 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
2936 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
2937 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
2938 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
2939 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
2941 return NT_STATUS_OK;
2944 static void call_trans2qfileinfo(
2945 connection_struct *conn,
2946 struct smb_request *req,
2947 char **pparams,
2948 int total_params,
2949 char **ppdata,
2950 int total_data,
2951 unsigned int max_data_bytes)
2953 char *params = *pparams;
2954 uint16_t info_level;
2955 struct smb_filename *smb_fname = NULL;
2956 bool delete_pending = False;
2957 struct timespec write_time_ts = { .tv_sec = 0, };
2958 files_struct *fsp = NULL;
2959 struct file_id fileid;
2960 bool info_level_handled;
2961 NTSTATUS status = NT_STATUS_OK;
2962 int ret;
2964 if (params == NULL) {
2965 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2966 return;
2969 if (total_params < 4) {
2970 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2971 return;
2974 fsp = file_fsp(req, SVAL(params,0));
2975 info_level = SVAL(params,2);
2977 if (IS_IPC(conn)) {
2978 call_trans2qpipeinfo(
2979 conn,
2980 req,
2981 fsp,
2982 info_level,
2983 TRANSACT2_QFILEINFO,
2984 pparams,
2985 total_params,
2986 ppdata,
2987 total_data,
2988 max_data_bytes);
2989 return;
2992 DBG_NOTICE("TRANSACT2_QFILEINFO: level = %d\n", info_level);
2994 if (INFO_LEVEL_IS_UNIX(info_level)) {
2995 if (!lp_smb1_unix_extensions()) {
2996 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2997 return;
2999 if (!req->posix_pathnames) {
3000 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3001 return;
3005 /* Initial check for valid fsp ptr. */
3006 if (!check_fsp_open(conn, req, fsp)) {
3007 return;
3010 smb_fname = fsp->fsp_name;
3012 if(fsp->fake_file_handle) {
3014 * This is actually for the QUOTA_FAKE_FILE --metze
3017 /* We know this name is ok, it's already passed the checks. */
3019 } else if(fsp_get_pathref_fd(fsp) == -1) {
3021 * This is actually a QFILEINFO on a directory
3022 * handle (returned from an NT SMB). NT5.0 seems
3023 * to do this call. JRA.
3025 ret = vfs_stat(conn, smb_fname);
3026 if (ret != 0) {
3027 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
3028 smb_fname_str_dbg(smb_fname),
3029 strerror(errno));
3030 reply_nterror(req,
3031 map_nt_error_from_unix(errno));
3032 return;
3035 if (fsp_getinfo_ask_sharemode(fsp)) {
3036 fileid = vfs_file_id_from_sbuf(
3037 conn, &smb_fname->st);
3038 get_file_infos(fileid, fsp->name_hash,
3039 &delete_pending,
3040 &write_time_ts);
3042 } else {
3044 * Original code - this is an open file.
3046 status = vfs_stat_fsp(fsp);
3047 if (!NT_STATUS_IS_OK(status)) {
3048 DEBUG(3, ("fstat of %s failed (%s)\n",
3049 fsp_fnum_dbg(fsp), nt_errstr(status)));
3050 reply_nterror(req, status);
3051 return;
3053 if (fsp_getinfo_ask_sharemode(fsp)) {
3054 fileid = vfs_file_id_from_sbuf(
3055 conn, &smb_fname->st);
3056 get_file_infos(fileid, fsp->name_hash,
3057 &delete_pending,
3058 &write_time_ts);
3062 info_level_handled = true; /* Untouched in switch cases below */
3064 switch (info_level) {
3066 default:
3067 info_level_handled = false;
3068 break;
3070 case SMB_QUERY_POSIX_LOCK:
3071 status = smb_q_posix_lock(conn, req, fsp, ppdata, &total_data);
3072 break;
3074 case SMB_QUERY_FILE_UNIX_BASIC:
3075 status = smb_q_unix_basic(
3076 conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3077 break;
3079 case SMB_QUERY_FILE_UNIX_INFO2:
3080 status = smb_q_unix_info2(
3081 conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3082 break;
3084 case SMB_QUERY_POSIX_ACL:
3085 status = smb_q_posix_acl(
3086 conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3087 break;
3090 if (info_level_handled) {
3091 handle_trans2qfilepathinfo_result(
3092 conn,
3093 req,
3094 info_level,
3095 status,
3096 *ppdata,
3097 total_data,
3098 total_data,
3099 max_data_bytes);
3100 return;
3103 call_trans2qfilepathinfo(
3104 conn,
3105 req,
3106 TRANSACT2_QFILEINFO,
3107 info_level,
3108 smb_fname,
3109 fsp,
3110 delete_pending,
3111 write_time_ts,
3112 pparams,
3113 total_params,
3114 ppdata,
3115 total_data,
3116 max_data_bytes);
3119 static void handle_trans2setfilepathinfo_result(
3120 connection_struct *conn,
3121 struct smb_request *req,
3122 uint16_t info_level,
3123 NTSTATUS status,
3124 char *pdata,
3125 int data_return_size,
3126 unsigned int max_data_bytes)
3128 char params[2] = { 0, 0, };
3130 if (NT_STATUS_IS_OK(status)) {
3131 send_trans2_replies(
3132 conn,
3133 req,
3134 NT_STATUS_OK,
3135 params,
3137 pdata,
3138 data_return_size,
3139 max_data_bytes);
3140 return;
3143 if (open_was_deferred(req->xconn, req->mid)) {
3144 /* We have re-scheduled this call. */
3145 return;
3148 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3149 bool ok = defer_smb1_sharing_violation(req);
3150 if (ok) {
3151 return;
3155 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
3156 /* We have re-scheduled this call. */
3157 return;
3160 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3161 reply_botherror(
3162 req,
3163 NT_STATUS_PATH_NOT_COVERED,
3164 ERRSRV,
3165 ERRbadpath);
3166 return;
3169 if (info_level == SMB_POSIX_PATH_OPEN) {
3170 reply_openerror(req, status);
3171 return;
3174 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
3176 * Invalid EA name needs to return 2 param bytes,
3177 * not a zero-length error packet.
3180 send_trans2_replies(
3181 conn,
3182 req,
3183 status,
3184 params,
3186 NULL,
3188 max_data_bytes);
3189 return;
3192 reply_nterror(req, status);
3195 /****************************************************************************
3196 Create a directory with POSIX semantics.
3197 ****************************************************************************/
3199 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
3200 struct smb_request *req,
3201 char **ppdata,
3202 int total_data,
3203 struct smb_filename *smb_fname,
3204 int *pdata_return_size)
3206 NTSTATUS status = NT_STATUS_OK;
3207 uint32_t raw_unixmode = 0;
3208 mode_t unixmode = (mode_t)0;
3209 files_struct *fsp = NULL;
3210 uint16_t info_level_return = 0;
3211 int info;
3212 char *pdata = *ppdata;
3213 struct smb2_create_blobs *posx = NULL;
3215 if (total_data < 18) {
3216 return NT_STATUS_INVALID_PARAMETER;
3219 raw_unixmode = IVAL(pdata,8);
3220 /* Next 4 bytes are not yet defined. */
3222 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
3223 PERM_NEW_DIR, &unixmode);
3224 if (!NT_STATUS_IS_OK(status)) {
3225 return status;
3228 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
3229 if (!NT_STATUS_IS_OK(status)) {
3230 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3231 nt_errstr(status));
3232 return status;
3235 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
3236 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
3238 status = SMB_VFS_CREATE_FILE(
3239 conn, /* conn */
3240 req, /* req */
3241 NULL, /* dirfsp */
3242 smb_fname, /* fname */
3243 FILE_READ_ATTRIBUTES, /* access_mask */
3244 FILE_SHARE_NONE, /* share_access */
3245 FILE_CREATE, /* create_disposition*/
3246 FILE_DIRECTORY_FILE, /* create_options */
3247 0, /* file_attributes */
3248 0, /* oplock_request */
3249 NULL, /* lease */
3250 0, /* allocation_size */
3251 0, /* private_flags */
3252 NULL, /* sd */
3253 NULL, /* ea_list */
3254 &fsp, /* result */
3255 &info, /* pinfo */
3256 posx, /* in_context_blobs */
3257 NULL); /* out_context_blobs */
3259 TALLOC_FREE(posx);
3261 if (NT_STATUS_IS_OK(status)) {
3262 close_file_free(req, &fsp, NORMAL_CLOSE);
3265 info_level_return = SVAL(pdata,16);
3267 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
3268 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
3269 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
3270 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
3271 } else {
3272 *pdata_return_size = 12;
3275 /* Realloc the data size */
3276 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
3277 if (*ppdata == NULL) {
3278 *pdata_return_size = 0;
3279 return NT_STATUS_NO_MEMORY;
3281 pdata = *ppdata;
3283 SSVAL(pdata,0,NO_OPLOCK_RETURN);
3284 SSVAL(pdata,2,0); /* No fnum. */
3285 SIVAL(pdata,4,info); /* Was directory created. */
3287 switch (info_level_return) {
3288 case SMB_QUERY_FILE_UNIX_BASIC:
3289 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
3290 SSVAL(pdata,10,0); /* Padding. */
3291 store_file_unix_basic(conn, pdata + 12, fsp,
3292 &smb_fname->st);
3293 break;
3294 case SMB_QUERY_FILE_UNIX_INFO2:
3295 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
3296 SSVAL(pdata,10,0); /* Padding. */
3297 store_file_unix_basic_info2(conn, pdata + 12, fsp,
3298 &smb_fname->st);
3299 break;
3300 default:
3301 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
3302 SSVAL(pdata,10,0); /* Padding. */
3303 break;
3306 return status;
3309 /****************************************************************************
3310 Open/Create a file with POSIX semantics.
3311 ****************************************************************************/
3313 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
3314 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
3316 static NTSTATUS smb_posix_open(connection_struct *conn,
3317 struct smb_request *req,
3318 char **ppdata,
3319 int total_data,
3320 struct files_struct *dirfsp,
3321 struct smb_filename *smb_fname,
3322 int *pdata_return_size)
3324 bool extended_oplock_granted = False;
3325 char *pdata = *ppdata;
3326 uint32_t flags = 0;
3327 uint32_t wire_open_mode = 0;
3328 uint32_t raw_unixmode = 0;
3329 uint32_t attributes = 0;
3330 uint32_t create_disp = 0;
3331 uint32_t access_mask = 0;
3332 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
3333 NTSTATUS status = NT_STATUS_OK;
3334 mode_t unixmode = (mode_t)0;
3335 files_struct *fsp = NULL;
3336 int oplock_request = 0;
3337 int info = 0;
3338 uint16_t info_level_return = 0;
3339 struct smb2_create_blobs *posx = NULL;
3341 if (total_data < 18) {
3342 return NT_STATUS_INVALID_PARAMETER;
3345 flags = IVAL(pdata,0);
3346 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
3347 if (oplock_request) {
3348 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
3351 wire_open_mode = IVAL(pdata,4);
3353 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
3354 return smb_posix_mkdir(conn, req,
3355 ppdata,
3356 total_data,
3357 smb_fname,
3358 pdata_return_size);
3361 switch (wire_open_mode & SMB_ACCMODE) {
3362 case SMB_O_RDONLY:
3363 access_mask = SMB_O_RDONLY_MAPPING;
3364 break;
3365 case SMB_O_WRONLY:
3366 access_mask = SMB_O_WRONLY_MAPPING;
3367 break;
3368 case SMB_O_RDWR:
3369 access_mask = (SMB_O_RDONLY_MAPPING|
3370 SMB_O_WRONLY_MAPPING);
3371 break;
3372 default:
3373 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
3374 (unsigned int)wire_open_mode ));
3375 return NT_STATUS_INVALID_PARAMETER;
3378 wire_open_mode &= ~SMB_ACCMODE;
3380 /* First take care of O_CREAT|O_EXCL interactions. */
3381 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
3382 case (SMB_O_CREAT | SMB_O_EXCL):
3383 /* File exists fail. File not exist create. */
3384 create_disp = FILE_CREATE;
3385 break;
3386 case SMB_O_CREAT:
3387 /* File exists open. File not exist create. */
3388 create_disp = FILE_OPEN_IF;
3389 break;
3390 case SMB_O_EXCL:
3391 /* O_EXCL on its own without O_CREAT is undefined.
3392 We deliberately ignore it as some versions of
3393 Linux CIFSFS can send a bare O_EXCL on the
3394 wire which other filesystems in the kernel
3395 ignore. See bug 9519 for details. */
3397 /* Fallthrough. */
3399 case 0:
3400 /* File exists open. File not exist fail. */
3401 create_disp = FILE_OPEN;
3402 break;
3403 default:
3404 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
3405 (unsigned int)wire_open_mode ));
3406 return NT_STATUS_INVALID_PARAMETER;
3409 /* Next factor in the effects of O_TRUNC. */
3410 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
3412 if (wire_open_mode & SMB_O_TRUNC) {
3413 switch (create_disp) {
3414 case FILE_CREATE:
3415 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
3416 /* Leave create_disp alone as
3417 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
3419 /* File exists fail. File not exist create. */
3420 break;
3421 case FILE_OPEN_IF:
3422 /* SMB_O_CREAT | SMB_O_TRUNC */
3423 /* File exists overwrite. File not exist create. */
3424 create_disp = FILE_OVERWRITE_IF;
3425 break;
3426 case FILE_OPEN:
3427 /* SMB_O_TRUNC */
3428 /* File exists overwrite. File not exist fail. */
3429 create_disp = FILE_OVERWRITE;
3430 break;
3431 default:
3432 /* Cannot get here. */
3433 smb_panic("smb_posix_open: logic error");
3434 return NT_STATUS_INVALID_PARAMETER;
3438 raw_unixmode = IVAL(pdata,8);
3439 /* Next 4 bytes are not yet defined. */
3441 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
3442 (VALID_STAT(smb_fname->st) ?
3443 PERM_EXISTING_FILE : PERM_NEW_FILE),
3444 &unixmode);
3446 if (!NT_STATUS_IS_OK(status)) {
3447 return status;
3450 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
3451 if (!NT_STATUS_IS_OK(status)) {
3452 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3453 nt_errstr(status));
3454 return status;
3457 if (wire_open_mode & SMB_O_SYNC) {
3458 create_options |= FILE_WRITE_THROUGH;
3460 if (wire_open_mode & SMB_O_APPEND) {
3461 access_mask |= FILE_APPEND_DATA;
3463 if (wire_open_mode & SMB_O_DIRECT) {
3465 * BUG: this doesn't work anymore since
3466 * e0814dc5082dd4ecca8a155e0ce24b073158fd92. But since
3467 * FILE_FLAG_NO_BUFFERING isn't used at all in the IO codepath,
3468 * it doesn't really matter.
3470 attributes |= FILE_FLAG_NO_BUFFERING;
3473 if ((wire_open_mode & SMB_O_DIRECTORY) ||
3474 VALID_STAT_OF_DIR(smb_fname->st)) {
3475 if (access_mask != SMB_O_RDONLY_MAPPING) {
3476 return NT_STATUS_FILE_IS_A_DIRECTORY;
3478 create_options &= ~FILE_NON_DIRECTORY_FILE;
3479 create_options |= FILE_DIRECTORY_FILE;
3482 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
3483 smb_fname_str_dbg(smb_fname),
3484 (unsigned int)wire_open_mode,
3485 (unsigned int)unixmode ));
3487 status = SMB_VFS_CREATE_FILE(
3488 conn, /* conn */
3489 req, /* req */
3490 dirfsp, /* dirfsp */
3491 smb_fname, /* fname */
3492 access_mask, /* access_mask */
3493 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
3494 FILE_SHARE_DELETE),
3495 create_disp, /* create_disposition*/
3496 create_options, /* create_options */
3497 attributes, /* file_attributes */
3498 oplock_request, /* oplock_request */
3499 NULL, /* lease */
3500 0, /* allocation_size */
3501 0, /* private_flags */
3502 NULL, /* sd */
3503 NULL, /* ea_list */
3504 &fsp, /* result */
3505 &info, /* pinfo */
3506 posx, /* in_context_blobs */
3507 NULL); /* out_context_blobs */
3509 TALLOC_FREE(posx);
3511 if (!NT_STATUS_IS_OK(status)) {
3512 return status;
3515 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3516 extended_oplock_granted = True;
3519 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3520 extended_oplock_granted = True;
3523 info_level_return = SVAL(pdata,16);
3525 /* Allocate the correct return size. */
3527 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
3528 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
3529 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
3530 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
3531 } else {
3532 *pdata_return_size = 12;
3535 /* Realloc the data size */
3536 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
3537 if (*ppdata == NULL) {
3538 close_file_free(req, &fsp, ERROR_CLOSE);
3539 *pdata_return_size = 0;
3540 return NT_STATUS_NO_MEMORY;
3542 pdata = *ppdata;
3544 if (extended_oplock_granted) {
3545 if (flags & REQUEST_BATCH_OPLOCK) {
3546 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
3547 } else {
3548 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
3550 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
3551 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
3552 } else {
3553 SSVAL(pdata,0,NO_OPLOCK_RETURN);
3556 SSVAL(pdata,2,fsp->fnum);
3557 SIVAL(pdata,4,info); /* Was file created etc. */
3559 switch (info_level_return) {
3560 case SMB_QUERY_FILE_UNIX_BASIC:
3561 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
3562 SSVAL(pdata,10,0); /* padding. */
3563 store_file_unix_basic(conn, pdata + 12, fsp,
3564 &smb_fname->st);
3565 break;
3566 case SMB_QUERY_FILE_UNIX_INFO2:
3567 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
3568 SSVAL(pdata,10,0); /* padding. */
3569 store_file_unix_basic_info2(conn, pdata + 12, fsp,
3570 &smb_fname->st);
3571 break;
3572 default:
3573 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
3574 SSVAL(pdata,10,0); /* padding. */
3575 break;
3577 return NT_STATUS_OK;
3580 /****************************************************************************
3581 Delete a file with POSIX semantics.
3582 ****************************************************************************/
3584 struct smb_posix_unlink_state {
3585 struct smb_filename *smb_fname;
3586 struct files_struct *fsp;
3587 NTSTATUS status;
3590 static void smb_posix_unlink_locked(struct share_mode_lock *lck,
3591 void *private_data)
3593 struct smb_posix_unlink_state *state = private_data;
3594 char del = 1;
3595 bool other_nonposix_opens;
3597 other_nonposix_opens = has_other_nonposix_opens(lck, state->fsp);
3598 if (other_nonposix_opens) {
3599 /* Fail with sharing violation. */
3600 state->status = NT_STATUS_SHARING_VIOLATION;
3601 return;
3605 * Set the delete on close.
3607 state->status = smb_set_file_disposition_info(state->fsp->conn,
3608 &del,
3610 state->fsp,
3611 state->smb_fname);
3614 static NTSTATUS smb_posix_unlink(connection_struct *conn,
3615 struct smb_request *req,
3616 const char *pdata,
3617 int total_data,
3618 struct files_struct *dirfsp,
3619 struct smb_filename *smb_fname)
3621 struct smb_posix_unlink_state state = {};
3622 NTSTATUS status = NT_STATUS_OK;
3623 files_struct *fsp = NULL;
3624 uint16_t flags = 0;
3625 int info = 0;
3626 int create_options = FILE_OPEN_REPARSE_POINT;
3627 struct smb2_create_blobs *posx = NULL;
3629 if (!CAN_WRITE(conn)) {
3630 return NT_STATUS_DOS(ERRSRV, ERRaccess);
3633 if (total_data < 2) {
3634 return NT_STATUS_INVALID_PARAMETER;
3637 flags = SVAL(pdata,0);
3639 if (!VALID_STAT(smb_fname->st)) {
3640 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3643 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
3644 !VALID_STAT_OF_DIR(smb_fname->st)) {
3645 return NT_STATUS_NOT_A_DIRECTORY;
3648 DEBUG(10,("smb_posix_unlink: %s %s\n",
3649 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
3650 smb_fname_str_dbg(smb_fname)));
3652 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
3653 create_options |= FILE_DIRECTORY_FILE;
3656 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
3657 if (!NT_STATUS_IS_OK(status)) {
3658 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3659 nt_errstr(status));
3660 return status;
3663 status = SMB_VFS_CREATE_FILE(
3664 conn, /* conn */
3665 req, /* req */
3666 dirfsp, /* dirfsp */
3667 smb_fname, /* fname */
3668 DELETE_ACCESS, /* access_mask */
3669 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
3670 FILE_SHARE_DELETE),
3671 FILE_OPEN, /* create_disposition*/
3672 create_options, /* create_options */
3673 0, /* file_attributes */
3674 0, /* oplock_request */
3675 NULL, /* lease */
3676 0, /* allocation_size */
3677 0, /* private_flags */
3678 NULL, /* sd */
3679 NULL, /* ea_list */
3680 &fsp, /* result */
3681 &info, /* pinfo */
3682 posx, /* in_context_blobs */
3683 NULL); /* out_context_blobs */
3685 TALLOC_FREE(posx);
3687 if (!NT_STATUS_IS_OK(status)) {
3688 return status;
3692 * Don't lie to client. If we can't really delete due to
3693 * non-POSIX opens return SHARING_VIOLATION.
3696 state = (struct smb_posix_unlink_state) {
3697 .smb_fname = smb_fname,
3698 .fsp = fsp,
3701 status = share_mode_do_locked_vfs_allowed(fsp->file_id,
3702 smb_posix_unlink_locked,
3703 &state);
3704 if (!NT_STATUS_IS_OK(status)) {
3705 DBG_ERR("share_mode_do_locked_vfs_allowed(%s) failed - %s\n",
3706 fsp_str_dbg(fsp), nt_errstr(status));
3707 close_file_free(req, &fsp, NORMAL_CLOSE);
3708 return NT_STATUS_INVALID_PARAMETER;
3711 status = state.status;
3712 if (!NT_STATUS_IS_OK(status)) {
3713 close_file_free(req, &fsp, NORMAL_CLOSE);
3714 return status;
3716 return close_file_free(req, &fsp, NORMAL_CLOSE);
3719 /****************************************************************************
3720 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
3721 ****************************************************************************/
3723 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
3724 struct smb_request *req,
3725 const char *pdata,
3726 int total_data,
3727 struct smb_filename *new_smb_fname)
3729 char *link_target = NULL;
3730 struct smb_filename target_fname;
3731 TALLOC_CTX *ctx = talloc_tos();
3732 NTSTATUS status;
3733 int ret;
3734 struct smb_filename *parent_fname = NULL;
3735 struct smb_filename *base_name = NULL;
3737 if (!CAN_WRITE(conn)) {
3738 return NT_STATUS_DOS(ERRSRV, ERRaccess);
3741 /* Set a symbolic link. */
3742 /* Don't allow this if follow links is false. */
3744 if (total_data == 0) {
3745 return NT_STATUS_INVALID_PARAMETER;
3748 if (!lp_follow_symlinks(SNUM(conn))) {
3749 return NT_STATUS_ACCESS_DENIED;
3752 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
3753 total_data, STR_TERMINATE);
3755 if (!link_target) {
3756 return NT_STATUS_INVALID_PARAMETER;
3759 target_fname = (struct smb_filename) {
3760 .base_name = link_target,
3763 /* Removes @GMT tokens if any */
3764 status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
3765 if (!NT_STATUS_IS_OK(status)) {
3766 return status;
3769 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3770 new_smb_fname->base_name, link_target ));
3772 status = parent_pathref(talloc_tos(),
3773 conn->cwd_fsp,
3774 new_smb_fname,
3775 &parent_fname,
3776 &base_name);
3777 if (!NT_STATUS_IS_OK(status)) {
3778 return status;
3781 ret = SMB_VFS_SYMLINKAT(conn,
3782 &target_fname,
3783 parent_fname->fsp,
3784 base_name);
3785 if (ret != 0) {
3786 TALLOC_FREE(parent_fname);
3787 return map_nt_error_from_unix(errno);
3790 TALLOC_FREE(parent_fname);
3791 return NT_STATUS_OK;
3794 /****************************************************************************
3795 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
3796 ****************************************************************************/
3798 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
3799 struct smb_request *req,
3800 const char *pdata, int total_data,
3801 struct smb_filename *smb_fname_new)
3803 char *oldname = NULL;
3804 struct files_struct *src_dirfsp = NULL;
3805 struct smb_filename *smb_fname_old = NULL;
3806 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
3807 NTTIME old_twrp = 0;
3808 TALLOC_CTX *ctx = talloc_tos();
3809 NTSTATUS status = NT_STATUS_OK;
3811 if (!CAN_WRITE(conn)) {
3812 return NT_STATUS_DOS(ERRSRV, ERRaccess);
3815 /* Set a hard link. */
3816 if (total_data == 0) {
3817 return NT_STATUS_INVALID_PARAMETER;
3820 if (req->posix_pathnames) {
3821 srvstr_get_path_posix(ctx,
3822 pdata,
3823 req->flags2,
3824 &oldname,
3825 pdata,
3826 total_data,
3827 STR_TERMINATE,
3828 &status);
3829 } else {
3830 srvstr_get_path(ctx,
3831 pdata,
3832 req->flags2,
3833 &oldname,
3834 pdata,
3835 total_data,
3836 STR_TERMINATE,
3837 &status);
3839 if (!NT_STATUS_IS_OK(status)) {
3840 return status;
3843 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3844 smb_fname_str_dbg(smb_fname_new), oldname));
3846 if (ucf_flags & UCF_GMT_PATHNAME) {
3847 extract_snapshot_token(oldname, &old_twrp);
3849 status = smb1_strip_dfs_path(ctx, &ucf_flags, &oldname);
3850 if (!NT_STATUS_IS_OK(status)) {
3851 return status;
3853 status = filename_convert_dirfsp(ctx,
3854 conn,
3855 oldname,
3856 ucf_flags,
3857 old_twrp,
3858 &src_dirfsp,
3859 &smb_fname_old);
3860 if (!NT_STATUS_IS_OK(status)) {
3861 return status;
3864 return hardlink_internals(ctx,
3865 conn,
3866 req,
3867 false,
3868 smb_fname_old,
3869 smb_fname_new);
3872 /****************************************************************************
3873 Allow a UNIX info mknod.
3874 ****************************************************************************/
3876 static NTSTATUS smb_unix_mknod(connection_struct *conn,
3877 const char *pdata,
3878 int total_data,
3879 struct files_struct *dirfsp,
3880 const struct smb_filename *smb_fname)
3882 uint32_t file_type = IVAL(pdata,56);
3883 #if defined(HAVE_MAKEDEV)
3884 uint32_t dev_major = IVAL(pdata,60);
3885 uint32_t dev_minor = IVAL(pdata,68);
3886 #endif
3887 SMB_DEV_T dev = (SMB_DEV_T)0;
3888 uint32_t raw_unixmode = IVAL(pdata,84);
3889 NTSTATUS status;
3890 mode_t unixmode;
3891 int ret;
3892 struct smb_filename *parent_fname = NULL;
3893 struct smb_filename *atname = NULL;
3895 if (total_data < 100) {
3896 return NT_STATUS_INVALID_PARAMETER;
3899 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
3900 PERM_NEW_FILE, &unixmode);
3901 if (!NT_STATUS_IS_OK(status)) {
3902 return status;
3905 #if defined(HAVE_MAKEDEV)
3906 dev = makedev(dev_major, dev_minor);
3907 #endif
3909 switch (file_type) {
3910 /* We can't create other objects here. */
3911 case UNIX_TYPE_FILE:
3912 case UNIX_TYPE_DIR:
3913 case UNIX_TYPE_SYMLINK:
3914 return NT_STATUS_ACCESS_DENIED;
3915 #if defined(S_IFIFO)
3916 case UNIX_TYPE_FIFO:
3917 unixmode |= S_IFIFO;
3918 break;
3919 #endif
3920 #if defined(S_IFSOCK)
3921 case UNIX_TYPE_SOCKET:
3922 unixmode |= S_IFSOCK;
3923 break;
3924 #endif
3925 #if defined(S_IFCHR)
3926 case UNIX_TYPE_CHARDEV:
3927 /* This is only allowed for root. */
3928 if (get_current_uid(conn) != sec_initial_uid()) {
3929 return NT_STATUS_ACCESS_DENIED;
3931 unixmode |= S_IFCHR;
3932 break;
3933 #endif
3934 #if defined(S_IFBLK)
3935 case UNIX_TYPE_BLKDEV:
3936 if (get_current_uid(conn) != sec_initial_uid()) {
3937 return NT_STATUS_ACCESS_DENIED;
3939 unixmode |= S_IFBLK;
3940 break;
3941 #endif
3942 default:
3943 return NT_STATUS_INVALID_PARAMETER;
3946 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
3947 "%.0f mode 0%o for file %s\n", (double)dev,
3948 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
3950 status = SMB_VFS_PARENT_PATHNAME(dirfsp->conn,
3951 talloc_tos(),
3952 smb_fname,
3953 &parent_fname,
3954 &atname);
3955 if (!NT_STATUS_IS_OK(status)) {
3956 return status;
3959 /* Ok - do the mknod. */
3960 ret = SMB_VFS_MKNODAT(conn,
3961 dirfsp,
3962 atname,
3963 unixmode,
3964 dev);
3966 if (ret != 0) {
3967 TALLOC_FREE(parent_fname);
3968 return map_nt_error_from_unix(errno);
3971 /* If any of the other "set" calls fail we
3972 * don't want to end up with a half-constructed mknod.
3975 if (lp_inherit_permissions(SNUM(conn))) {
3976 inherit_access_posix_acl(conn,
3977 dirfsp,
3978 smb_fname,
3979 unixmode);
3981 TALLOC_FREE(parent_fname);
3983 return NT_STATUS_OK;
3986 /****************************************************************************
3987 Deal with SMB_SET_FILE_UNIX_BASIC.
3988 ****************************************************************************/
3990 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
3991 struct smb_request *req,
3992 const char *pdata,
3993 int total_data,
3994 struct files_struct *dirfsp,
3995 files_struct *fsp,
3996 struct smb_filename *smb_fname)
3998 struct smb_file_time ft;
3999 uint32_t raw_unixmode;
4000 mode_t unixmode;
4001 off_t size = 0;
4002 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
4003 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
4004 NTSTATUS status = NT_STATUS_OK;
4005 enum perm_type ptype;
4006 files_struct *all_fsps = NULL;
4007 bool modify_mtime = true;
4008 struct file_id id;
4009 SMB_STRUCT_STAT sbuf;
4011 if (!CAN_WRITE(conn)) {
4012 return NT_STATUS_DOS(ERRSRV, ERRaccess);
4015 init_smb_file_time(&ft);
4017 if (total_data < 100) {
4018 return NT_STATUS_INVALID_PARAMETER;
4021 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4022 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4023 size=IVAL(pdata,0); /* first 8 Bytes are size */
4024 size |= (((off_t)IVAL(pdata,4)) << 32);
4027 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
4028 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
4029 set_owner = (uid_t)IVAL(pdata,40);
4030 set_grp = (gid_t)IVAL(pdata,48);
4031 raw_unixmode = IVAL(pdata,84);
4033 if (VALID_STAT(smb_fname->st)) {
4034 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
4035 ptype = PERM_EXISTING_DIR;
4036 } else {
4037 ptype = PERM_EXISTING_FILE;
4039 } else {
4040 ptype = PERM_NEW_FILE;
4043 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
4044 ptype, &unixmode);
4045 if (!NT_STATUS_IS_OK(status)) {
4046 return status;
4049 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
4050 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4051 smb_fname_str_dbg(smb_fname), (double)size,
4052 (unsigned int)set_owner, (unsigned int)set_grp,
4053 (int)raw_unixmode));
4055 sbuf = smb_fname->st;
4057 if (!VALID_STAT(sbuf)) {
4059 * The only valid use of this is to create character and block
4060 * devices, and named pipes. This is deprecated (IMHO) and
4061 * a new info level should be used for mknod. JRA.
4064 if (dirfsp == NULL) {
4065 return NT_STATUS_INVALID_PARAMETER;
4068 return smb_unix_mknod(conn,
4069 pdata,
4070 total_data,
4071 dirfsp,
4072 smb_fname);
4075 #if 1
4076 /* Horrible backwards compatibility hack as an old server bug
4077 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
4078 * */
4080 if (!size) {
4081 size = get_file_size_stat(&sbuf);
4083 #endif
4086 * Deal with the UNIX specific mode set.
4089 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4090 int ret;
4092 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
4093 DBG_WARNING("Can't set mode on symlink %s\n",
4094 smb_fname_str_dbg(smb_fname));
4095 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4098 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4099 "setting mode 0%o for file %s\n",
4100 (unsigned int)unixmode,
4101 smb_fname_str_dbg(smb_fname)));
4102 ret = SMB_VFS_FCHMOD(fsp, unixmode);
4103 if (ret != 0) {
4104 return map_nt_error_from_unix(errno);
4109 * Deal with the UNIX specific uid set.
4112 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
4113 (sbuf.st_ex_uid != set_owner)) {
4114 int ret;
4116 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4117 "changing owner %u for path %s\n",
4118 (unsigned int)set_owner,
4119 smb_fname_str_dbg(smb_fname)));
4121 if (fsp &&
4122 !fsp->fsp_flags.is_pathref &&
4123 fsp_get_io_fd(fsp) != -1)
4125 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
4126 } else {
4128 * UNIX extensions calls must always operate
4129 * on symlinks.
4131 ret = SMB_VFS_LCHOWN(conn, smb_fname,
4132 set_owner, (gid_t)-1);
4135 if (ret != 0) {
4136 status = map_nt_error_from_unix(errno);
4137 return status;
4142 * Deal with the UNIX specific gid set.
4145 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
4146 (sbuf.st_ex_gid != set_grp)) {
4147 int ret;
4149 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4150 "changing group %u for file %s\n",
4151 (unsigned int)set_grp,
4152 smb_fname_str_dbg(smb_fname)));
4153 if (fsp &&
4154 !fsp->fsp_flags.is_pathref &&
4155 fsp_get_io_fd(fsp) != -1)
4157 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
4158 } else {
4160 * UNIX extensions calls must always operate
4161 * on symlinks.
4163 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
4164 set_grp);
4166 if (ret != 0) {
4167 status = map_nt_error_from_unix(errno);
4168 return status;
4172 /* Deal with any size changes. */
4174 if (S_ISREG(sbuf.st_ex_mode)) {
4175 status = smb_set_file_size(conn, req,
4176 fsp,
4177 smb_fname,
4178 &sbuf,
4179 size,
4180 false);
4181 if (!NT_STATUS_IS_OK(status)) {
4182 return status;
4186 /* Deal with any time changes. */
4187 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
4188 /* No change, don't cancel anything. */
4189 return status;
4192 id = vfs_file_id_from_sbuf(conn, &sbuf);
4193 for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
4194 all_fsps = file_find_di_next(all_fsps, true)) {
4196 * We're setting the time explicitly for UNIX.
4197 * Cancel any pending changes over all handles.
4199 all_fsps->fsp_flags.update_write_time_on_close = false;
4200 TALLOC_FREE(all_fsps->update_write_time_event);
4204 * Override the "setting_write_time"
4205 * parameter here as it almost does what
4206 * we need. Just remember if we modified
4207 * mtime and send the notify ourselves.
4209 if (is_omit_timespec(&ft.mtime)) {
4210 modify_mtime = false;
4213 status = smb_set_file_time(conn,
4214 fsp,
4215 smb_fname,
4216 &ft,
4217 false);
4218 if (modify_mtime) {
4219 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4220 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
4222 return status;
4225 /****************************************************************************
4226 Deal with SMB_SET_FILE_UNIX_INFO2.
4227 ****************************************************************************/
4229 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
4230 struct smb_request *req,
4231 const char *pdata,
4232 int total_data,
4233 struct files_struct *dirfsp,
4234 files_struct *fsp,
4235 struct smb_filename *smb_fname)
4237 NTSTATUS status;
4238 uint32_t smb_fflags;
4239 uint32_t smb_fmask;
4241 if (!CAN_WRITE(conn)) {
4242 return NT_STATUS_DOS(ERRSRV, ERRaccess);
4245 if (total_data < 116) {
4246 return NT_STATUS_INVALID_PARAMETER;
4249 /* Start by setting all the fields that are common between UNIX_BASIC
4250 * and UNIX_INFO2.
4252 status = smb_set_file_unix_basic(conn,
4253 req,
4254 pdata,
4255 total_data,
4256 dirfsp,
4257 fsp,
4258 smb_fname);
4259 if (!NT_STATUS_IS_OK(status)) {
4260 return status;
4263 smb_fflags = IVAL(pdata, 108);
4264 smb_fmask = IVAL(pdata, 112);
4266 /* NB: We should only attempt to alter the file flags if the client
4267 * sends a non-zero mask.
4269 if (smb_fmask != 0) {
4270 int stat_fflags = 0;
4272 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
4273 smb_fmask, &stat_fflags)) {
4274 /* Client asked to alter a flag we don't understand. */
4275 return NT_STATUS_INVALID_PARAMETER;
4278 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
4279 DBG_WARNING("Can't change flags on symlink %s\n",
4280 smb_fname_str_dbg(smb_fname));
4281 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4283 if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) {
4284 return map_nt_error_from_unix(errno);
4288 /* XXX: need to add support for changing the create_time here. You
4289 * can do this for paths on Darwin with setattrlist(2). The right way
4290 * to hook this up is probably by extending the VFS utimes interface.
4293 return NT_STATUS_OK;
4296 /****************************************************************************
4297 Deal with SMB_SET_POSIX_ACL.
4298 ****************************************************************************/
4300 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4301 struct smb_request *req,
4302 const char *pdata,
4303 int total_data_in,
4304 files_struct *fsp,
4305 struct smb_filename *smb_fname)
4307 #if !defined(HAVE_POSIX_ACLS)
4308 return NT_STATUS_INVALID_LEVEL;
4309 #else
4310 uint16_t posix_acl_version;
4311 uint16_t num_file_acls;
4312 uint16_t num_def_acls;
4313 bool valid_file_acls = true;
4314 bool valid_def_acls = true;
4315 NTSTATUS status;
4316 unsigned int size_needed;
4317 unsigned int total_data;
4318 bool close_fsp = false;
4320 if (total_data_in < 0) {
4321 status = NT_STATUS_INVALID_PARAMETER;
4322 goto out;
4325 total_data = total_data_in;
4327 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4328 status = NT_STATUS_INVALID_PARAMETER;
4329 goto out;
4331 posix_acl_version = SVAL(pdata,0);
4332 num_file_acls = SVAL(pdata,2);
4333 num_def_acls = SVAL(pdata,4);
4335 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4336 valid_file_acls = false;
4337 num_file_acls = 0;
4340 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4341 valid_def_acls = false;
4342 num_def_acls = 0;
4345 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4346 status = NT_STATUS_INVALID_PARAMETER;
4347 goto out;
4350 /* Wrap checks. */
4351 if (num_file_acls + num_def_acls < num_file_acls) {
4352 status = NT_STATUS_INVALID_PARAMETER;
4353 goto out;
4356 size_needed = num_file_acls + num_def_acls;
4359 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4360 * than UINT_MAX, so check by division.
4362 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
4363 status = NT_STATUS_INVALID_PARAMETER;
4364 goto out;
4367 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
4368 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
4369 status = NT_STATUS_INVALID_PARAMETER;
4370 goto out;
4372 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
4374 if (total_data < size_needed) {
4375 status = NT_STATUS_INVALID_PARAMETER;
4376 goto out;
4380 * Ensure we always operate on a file descriptor, not just
4381 * the filename.
4383 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
4384 uint32_t access_mask = SEC_STD_WRITE_OWNER|
4385 SEC_STD_WRITE_DAC|
4386 SEC_STD_READ_CONTROL|
4387 FILE_READ_ATTRIBUTES|
4388 FILE_WRITE_ATTRIBUTES;
4390 status = get_posix_fsp(conn,
4391 req,
4392 smb_fname,
4393 access_mask,
4394 &fsp);
4396 if (!NT_STATUS_IS_OK(status)) {
4397 goto out;
4399 close_fsp = true;
4402 /* Here we know fsp != NULL */
4403 SMB_ASSERT(fsp != NULL);
4405 status = refuse_symlink_fsp(fsp);
4406 if (!NT_STATUS_IS_OK(status)) {
4407 goto out;
4410 /* If we have a default acl, this *must* be a directory. */
4411 if (valid_def_acls && !fsp->fsp_flags.is_directory) {
4412 DBG_INFO("Can't set default acls on "
4413 "non-directory %s\n",
4414 fsp_str_dbg(fsp));
4415 return NT_STATUS_INVALID_HANDLE;
4418 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
4419 "num_def_acls = %"PRIu16"\n",
4420 fsp_str_dbg(fsp),
4421 num_file_acls,
4422 num_def_acls);
4424 /* Move pdata to the start of the file ACL entries. */
4425 pdata += SMB_POSIX_ACL_HEADER_SIZE;
4427 if (valid_file_acls) {
4428 status = set_unix_posix_acl(conn,
4429 fsp,
4430 num_file_acls,
4431 pdata);
4432 if (!NT_STATUS_IS_OK(status)) {
4433 goto out;
4437 /* Move pdata to the start of the default ACL entries. */
4438 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
4440 if (valid_def_acls) {
4441 status = set_unix_posix_default_acl(conn,
4442 fsp,
4443 num_def_acls,
4444 pdata);
4445 if (!NT_STATUS_IS_OK(status)) {
4446 goto out;
4450 status = NT_STATUS_OK;
4452 out:
4454 if (close_fsp) {
4455 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
4457 return status;
4458 #endif
4461 static void call_trans2setpathinfo(
4462 connection_struct *conn,
4463 struct smb_request *req,
4464 char **pparams,
4465 int total_params,
4466 char **ppdata,
4467 int total_data,
4468 unsigned int max_data_bytes)
4470 uint16_t info_level;
4471 struct smb_filename *smb_fname = NULL;
4472 struct files_struct *dirfsp = NULL;
4473 struct files_struct *fsp = NULL;
4474 char *params = *pparams;
4475 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4476 NTTIME twrp = 0;
4477 char *fname = NULL;
4478 bool info_level_handled;
4479 int data_return_size = 0;
4480 NTSTATUS status;
4482 if (params == NULL) {
4483 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4484 return;
4487 /* set path info */
4488 if (total_params < 7) {
4489 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4490 return;
4493 info_level = SVAL(params,0);
4495 if (INFO_LEVEL_IS_UNIX(info_level)) {
4496 if (!lp_smb1_unix_extensions()) {
4497 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4498 return;
4500 if (!req->posix_pathnames) {
4501 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4502 return;
4506 if (req->posix_pathnames) {
4507 srvstr_get_path_posix(req,
4508 params,
4509 req->flags2,
4510 &fname,
4511 &params[6],
4512 total_params - 6,
4513 STR_TERMINATE,
4514 &status);
4515 } else {
4516 srvstr_get_path(req,
4517 params,
4518 req->flags2,
4519 &fname,
4520 &params[6],
4521 total_params - 6,
4522 STR_TERMINATE,
4523 &status);
4525 if (!NT_STATUS_IS_OK(status)) {
4526 reply_nterror(req, status);
4527 return;
4530 DBG_NOTICE("fname=%s info_level=%d totdata=%d\n",
4531 fname,
4532 info_level,
4533 total_data);
4535 if (ucf_flags & UCF_GMT_PATHNAME) {
4536 extract_snapshot_token(fname, &twrp);
4538 status = smb1_strip_dfs_path(req, &ucf_flags, &fname);
4539 if (!NT_STATUS_IS_OK(status)) {
4540 reply_nterror(req, status);
4541 return;
4543 status = filename_convert_dirfsp(req,
4544 conn,
4545 fname,
4546 ucf_flags,
4547 twrp,
4548 &dirfsp,
4549 &smb_fname);
4550 if (!NT_STATUS_IS_OK(status)) {
4551 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4552 reply_botherror(req,
4553 NT_STATUS_PATH_NOT_COVERED,
4554 ERRSRV, ERRbadpath);
4555 return;
4557 reply_nterror(req, status);
4558 return;
4561 info_level_handled = true; /* Untouched in switch cases below */
4563 switch (info_level) {
4565 default:
4566 info_level_handled = false;
4567 break;
4569 case SMB_POSIX_PATH_OPEN:
4570 status = smb_posix_open(conn,
4571 req,
4572 ppdata,
4573 total_data,
4574 dirfsp,
4575 smb_fname,
4576 &data_return_size);
4577 break;
4579 case SMB_POSIX_PATH_UNLINK:
4580 status = smb_posix_unlink(conn,
4581 req,
4582 *ppdata,
4583 total_data,
4584 dirfsp,
4585 smb_fname);
4586 break;
4588 case SMB_SET_FILE_UNIX_LINK:
4589 status = smb_set_file_unix_link(
4590 conn, req, *ppdata, total_data, smb_fname);
4591 break;
4593 case SMB_SET_FILE_UNIX_HLINK:
4594 status = smb_set_file_unix_hlink(
4595 conn, req, *ppdata, total_data, smb_fname);
4596 break;
4598 case SMB_SET_FILE_UNIX_BASIC:
4599 status = smb_set_file_unix_basic(conn,
4600 req,
4601 *ppdata,
4602 total_data,
4603 dirfsp,
4604 smb_fname->fsp,
4605 smb_fname);
4606 break;
4608 case SMB_SET_FILE_UNIX_INFO2:
4609 status = smb_set_file_unix_info2(conn,
4610 req,
4611 *ppdata,
4612 total_data,
4613 dirfsp,
4614 smb_fname->fsp,
4615 smb_fname);
4616 break;
4617 case SMB_SET_POSIX_ACL:
4618 status = smb_set_posix_acl(
4619 conn, req, *ppdata, total_data, NULL, smb_fname);
4620 break;
4623 if (info_level_handled) {
4624 handle_trans2setfilepathinfo_result(
4625 conn,
4626 req,
4627 info_level,
4628 status,
4629 *ppdata,
4630 data_return_size,
4631 max_data_bytes);
4632 return;
4636 * smb_fname->fsp may be NULL if smb_fname points at a symlink
4637 * and we're in POSIX context, so be careful when using fsp
4638 * below, it can still be NULL.
4640 fsp = smb_fname->fsp;
4642 status = smbd_do_setfilepathinfo(
4643 conn,
4644 req,
4645 req,
4646 info_level,
4647 fsp,
4648 smb_fname,
4649 ppdata,
4650 total_data,
4651 &data_return_size);
4653 handle_trans2setfilepathinfo_result(
4654 conn,
4655 req,
4656 info_level,
4657 status,
4658 *ppdata,
4659 data_return_size,
4660 max_data_bytes);
4663 static void call_trans2setfileinfo(
4664 connection_struct *conn,
4665 struct smb_request *req,
4666 char **pparams,
4667 int total_params,
4668 char **ppdata,
4669 int total_data,
4670 unsigned int max_data_bytes)
4672 char *pdata = *ppdata;
4673 uint16_t info_level;
4674 struct smb_filename *smb_fname = NULL;
4675 struct files_struct *fsp = NULL;
4676 char *params = *pparams;
4677 int data_return_size = 0;
4678 bool info_level_handled;
4679 NTSTATUS status;
4680 int ret;
4682 if (params == NULL) {
4683 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4684 return;
4686 if (total_params < 4) {
4687 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4688 return;
4691 fsp = file_fsp(req, SVAL(params,0));
4692 /* Basic check for non-null fsp. */
4693 if (!check_fsp_open(conn, req, fsp)) {
4694 return;
4696 info_level = SVAL(params,2);
4698 if (INFO_LEVEL_IS_UNIX(info_level)) {
4699 if (!lp_smb1_unix_extensions()) {
4700 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4701 return;
4703 if (!req->posix_pathnames) {
4704 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4705 return;
4709 smb_fname = fsp->fsp_name;
4711 DBG_NOTICE("fnum=%s fname=%s info_level=%d totdata=%d\n",
4712 fsp_fnum_dbg(fsp),
4713 fsp_str_dbg(fsp),
4714 info_level,
4715 total_data);
4717 if (fsp_get_pathref_fd(fsp) == -1) {
4719 * This is actually a SETFILEINFO on a directory
4720 * handle (returned from an NT SMB). NT5.0 seems
4721 * to do this call. JRA.
4723 ret = vfs_stat(conn, smb_fname);
4724 if (ret != 0) {
4725 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
4726 smb_fname_str_dbg(smb_fname),
4727 strerror(errno));
4728 reply_nterror(req, map_nt_error_from_unix(errno));
4729 return;
4731 } else if (fsp->print_file) {
4733 * Doing a DELETE_ON_CLOSE should cancel a print job.
4735 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) &&
4736 CVAL(pdata,0)) {
4738 fsp->fsp_flags.delete_on_close = true;
4740 DBG_NOTICE("Cancelling print job (%s)\n",
4741 fsp_str_dbg(fsp));
4743 SSVAL(params,0,0);
4744 send_trans2_replies(
4745 conn,
4746 req,
4747 NT_STATUS_OK,
4748 params,
4750 *ppdata, 0,
4751 max_data_bytes);
4752 return;
4753 } else {
4754 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
4755 return;
4757 } else {
4759 * Original code - this is an open file.
4761 status = vfs_stat_fsp(fsp);
4762 if (!NT_STATUS_IS_OK(status)) {
4763 DBG_NOTICE("fstat of %s failed (%s)\n",
4764 fsp_fnum_dbg(fsp),
4765 nt_errstr(status));
4766 reply_nterror(req, status);
4767 return;
4771 info_level_handled = true; /* Untouched in switch cases below */
4773 switch (info_level) {
4775 default:
4776 info_level_handled = false;
4777 break;
4779 case SMB_SET_FILE_UNIX_BASIC:
4780 status = smb_set_file_unix_basic(conn,
4781 req,
4782 pdata,
4783 total_data,
4784 NULL,
4785 fsp,
4786 smb_fname);
4787 break;
4789 case SMB_SET_FILE_UNIX_INFO2:
4790 status = smb_set_file_unix_info2(conn,
4791 req,
4792 pdata,
4793 total_data,
4794 NULL,
4795 fsp,
4796 smb_fname);
4797 break;
4799 case SMB_SET_POSIX_LOCK:
4800 status = smb_set_posix_lock(
4801 conn, req, *ppdata, total_data, fsp);
4802 break;
4805 if (info_level_handled) {
4806 handle_trans2setfilepathinfo_result(
4807 conn,
4808 req,
4809 info_level,
4810 status,
4811 *ppdata,
4812 data_return_size,
4813 max_data_bytes);
4814 return;
4817 status = smbd_do_setfilepathinfo(
4818 conn,
4819 req,
4820 req,
4821 info_level,
4822 fsp,
4823 smb_fname,
4824 ppdata,
4825 total_data,
4826 &data_return_size);
4828 handle_trans2setfilepathinfo_result(
4829 conn,
4830 req,
4831 info_level,
4832 status,
4833 *ppdata,
4834 data_return_size,
4835 max_data_bytes);
4838 /****************************************************************************
4839 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4840 ****************************************************************************/
4842 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
4843 char **pparams, int total_params,
4844 char **ppdata, int total_data,
4845 unsigned int max_data_bytes)
4847 struct files_struct *dirfsp = NULL;
4848 struct files_struct *fsp = NULL;
4849 struct smb_filename *smb_dname = NULL;
4850 char *params = *pparams;
4851 char *pdata = *ppdata;
4852 char *directory = NULL;
4853 NTSTATUS status = NT_STATUS_OK;
4854 struct ea_list *ea_list = NULL;
4855 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4856 NTTIME twrp = 0;
4857 TALLOC_CTX *ctx = talloc_tos();
4859 if (!CAN_WRITE(conn)) {
4860 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4861 return;
4864 if (total_params < 5) {
4865 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4866 return;
4869 if (req->posix_pathnames) {
4870 srvstr_get_path_posix(ctx,
4871 params,
4872 req->flags2,
4873 &directory,
4874 &params[4],
4875 total_params - 4,
4876 STR_TERMINATE,
4877 &status);
4878 } else {
4879 srvstr_get_path(ctx,
4880 params,
4881 req->flags2,
4882 &directory,
4883 &params[4],
4884 total_params - 4,
4885 STR_TERMINATE,
4886 &status);
4888 if (!NT_STATUS_IS_OK(status)) {
4889 reply_nterror(req, status);
4890 return;
4893 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4895 if (ucf_flags & UCF_GMT_PATHNAME) {
4896 extract_snapshot_token(directory, &twrp);
4898 status = smb1_strip_dfs_path(ctx, &ucf_flags, &directory);
4899 if (!NT_STATUS_IS_OK(status)) {
4900 reply_nterror(req, status);
4901 goto out;
4903 status = filename_convert_dirfsp(ctx,
4904 conn,
4905 directory,
4906 ucf_flags,
4907 twrp,
4908 &dirfsp,
4909 &smb_dname);
4910 if (!NT_STATUS_IS_OK(status)) {
4911 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4912 reply_botherror(req,
4913 NT_STATUS_PATH_NOT_COVERED,
4914 ERRSRV, ERRbadpath);
4915 return;
4917 reply_nterror(req, status);
4918 return;
4922 * OS/2 workplace shell seems to send SET_EA requests of "null"
4923 * length (4 bytes containing IVAL 4).
4924 * They seem to have no effect. Bug #3212. JRA.
4927 if (total_data && (total_data != 4)) {
4928 /* Any data in this call is an EA list. */
4929 if (total_data < 10) {
4930 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4931 goto out;
4934 if (IVAL(pdata,0) > total_data) {
4935 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4936 IVAL(pdata,0), (unsigned int)total_data));
4937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4938 goto out;
4941 ea_list = read_ea_list(talloc_tos(), pdata + 4,
4942 total_data - 4);
4943 if (!ea_list) {
4944 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4945 goto out;
4948 if (!lp_ea_support(SNUM(conn))) {
4949 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
4950 goto out;
4953 /* If total_data == 4 Windows doesn't care what values
4954 * are placed in that field, it just ignores them.
4955 * The System i QNTC IBM SMB client puts bad values here,
4956 * so ignore them. */
4958 status = SMB_VFS_CREATE_FILE(
4959 conn, /* conn */
4960 req, /* req */
4961 dirfsp, /* dirfsp */
4962 smb_dname, /* fname */
4963 MAXIMUM_ALLOWED_ACCESS, /* access_mask */
4964 FILE_SHARE_NONE, /* share_access */
4965 FILE_CREATE, /* create_disposition*/
4966 FILE_DIRECTORY_FILE, /* create_options */
4967 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
4968 0, /* oplock_request */
4969 NULL, /* lease */
4970 0, /* allocation_size */
4971 0, /* private_flags */
4972 NULL, /* sd */
4973 NULL, /* ea_list */
4974 &fsp, /* result */
4975 NULL, /* pinfo */
4976 NULL, NULL); /* create context */
4977 if (!NT_STATUS_IS_OK(status)) {
4978 reply_nterror(req, status);
4979 goto out;
4982 /* Try and set any given EA. */
4983 if (ea_list) {
4984 status = set_ea(conn, fsp, ea_list);
4985 if (!NT_STATUS_IS_OK(status)) {
4986 reply_nterror(req, status);
4987 goto out;
4991 /* Realloc the parameter and data sizes */
4992 *pparams = (char *)SMB_REALLOC(*pparams,2);
4993 if(*pparams == NULL) {
4994 reply_nterror(req, NT_STATUS_NO_MEMORY);
4995 goto out;
4997 params = *pparams;
4999 SSVAL(params,0,0);
5001 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
5003 out:
5004 if (fsp != NULL) {
5005 close_file_free(NULL, &fsp, NORMAL_CLOSE);
5007 TALLOC_FREE(smb_dname);
5010 /****************************************************************************
5011 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
5012 We don't actually do this - we just send a null response.
5013 ****************************************************************************/
5015 static void call_trans2findnotifyfirst(connection_struct *conn,
5016 struct smb_request *req,
5017 char **pparams, int total_params,
5018 char **ppdata, int total_data,
5019 unsigned int max_data_bytes)
5021 char *params = *pparams;
5022 uint16_t info_level;
5024 if (total_params < 6) {
5025 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5026 return;
5029 info_level = SVAL(params,4);
5030 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
5032 switch (info_level) {
5033 case 1:
5034 case 2:
5035 break;
5036 default:
5037 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5038 return;
5041 /* Realloc the parameter and data sizes */
5042 *pparams = (char *)SMB_REALLOC(*pparams,6);
5043 if (*pparams == NULL) {
5044 reply_nterror(req, NT_STATUS_NO_MEMORY);
5045 return;
5047 params = *pparams;
5049 SSVAL(params,0,fnf_handle);
5050 SSVAL(params,2,0); /* No changes */
5051 SSVAL(params,4,0); /* No EA errors */
5053 fnf_handle++;
5055 if(fnf_handle == 0)
5056 fnf_handle = 257;
5058 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
5061 /****************************************************************************
5062 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
5063 changes). Currently this does nothing.
5064 ****************************************************************************/
5066 static void call_trans2findnotifynext(connection_struct *conn,
5067 struct smb_request *req,
5068 char **pparams, int total_params,
5069 char **ppdata, int total_data,
5070 unsigned int max_data_bytes)
5072 char *params = *pparams;
5074 DEBUG(3,("call_trans2findnotifynext\n"));
5076 /* Realloc the parameter and data sizes */
5077 *pparams = (char *)SMB_REALLOC(*pparams,4);
5078 if (*pparams == NULL) {
5079 reply_nterror(req, NT_STATUS_NO_MEMORY);
5080 return;
5082 params = *pparams;
5084 SSVAL(params,0,0); /* No changes */
5085 SSVAL(params,2,0); /* No EA errors */
5087 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
5090 /****************************************************************************
5091 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5092 ****************************************************************************/
5094 static void call_trans2getdfsreferral(connection_struct *conn,
5095 struct smb_request *req,
5096 char **pparams, int total_params,
5097 char **ppdata, int total_data,
5098 unsigned int max_data_bytes)
5100 char *params = *pparams;
5101 char *pathname = NULL;
5102 int reply_size = 0;
5103 int max_referral_level;
5104 NTSTATUS status = NT_STATUS_OK;
5105 TALLOC_CTX *ctx = talloc_tos();
5107 DEBUG(10,("call_trans2getdfsreferral\n"));
5109 if (!IS_IPC(conn)) {
5110 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5111 return;
5114 if (total_params < 3) {
5115 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5116 return;
5119 max_referral_level = SVAL(params,0);
5121 if(!lp_host_msdfs()) {
5122 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5123 return;
5126 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
5127 total_params - 2, STR_TERMINATE);
5128 if (!pathname) {
5129 reply_nterror(req, NT_STATUS_NOT_FOUND);
5130 return;
5132 reply_size = setup_dfs_referral(
5133 conn, pathname, max_referral_level, ppdata, &status);
5134 if (reply_size < 0) {
5135 reply_nterror(req, status);
5136 return;
5139 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
5140 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
5141 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
5144 #define LMCAT_SPL 0x53
5145 #define LMFUNC_GETJOBID 0x60
5147 /****************************************************************************
5148 Reply to a TRANS2_IOCTL - used for OS/2 printing.
5149 ****************************************************************************/
5151 static void call_trans2ioctl(connection_struct *conn,
5152 struct smb_request *req,
5153 char **pparams, int total_params,
5154 char **ppdata, int total_data,
5155 unsigned int max_data_bytes)
5157 const struct loadparm_substitution *lp_sub =
5158 loadparm_s3_global_substitution();
5159 char *pdata = *ppdata;
5160 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
5161 NTSTATUS status;
5162 size_t len = 0;
5164 /* check for an invalid fid before proceeding */
5166 if (!fsp) {
5167 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5168 return;
5171 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
5172 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
5173 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
5174 if (*ppdata == NULL) {
5175 reply_nterror(req, NT_STATUS_NO_MEMORY);
5176 return;
5178 pdata = *ppdata;
5180 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5181 CAN ACCEPT THIS IN UNICODE. JRA. */
5183 /* Job number */
5184 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
5186 status = srvstr_push(pdata, req->flags2, pdata + 2,
5187 lp_netbios_name(), 15,
5188 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
5189 if (!NT_STATUS_IS_OK(status)) {
5190 reply_nterror(req, status);
5191 return;
5193 status = srvstr_push(pdata, req->flags2, pdata+18,
5194 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
5195 STR_ASCII|STR_TERMINATE, &len); /* Service name */
5196 if (!NT_STATUS_IS_OK(status)) {
5197 reply_nterror(req, status);
5198 return;
5200 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
5201 max_data_bytes);
5202 return;
5205 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5206 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5209 static void handle_trans2(connection_struct *conn, struct smb_request *req,
5210 struct trans_state *state)
5212 struct smbXsrv_connection *xconn = req->xconn;
5214 if (xconn->protocol >= PROTOCOL_NT1) {
5215 req->flags2 |= 0x40; /* IS_LONG_NAME */
5216 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
5219 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
5220 if (state->call != TRANSACT2_QFSINFO &&
5221 state->call != TRANSACT2_SETFSINFO) {
5222 DEBUG(0,("handle_trans2: encryption required "
5223 "with call 0x%x\n",
5224 (unsigned int)state->call));
5225 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5226 return;
5230 /* Now we must call the relevant TRANS2 function */
5231 switch(state->call) {
5232 case TRANSACT2_OPEN:
5234 START_PROFILE(Trans2_open);
5235 call_trans2open(conn, req,
5236 &state->param, state->total_param,
5237 &state->data, state->total_data,
5238 state->max_data_return);
5239 END_PROFILE(Trans2_open);
5240 break;
5243 case TRANSACT2_FINDFIRST:
5245 START_PROFILE(Trans2_findfirst);
5246 call_trans2findfirst(conn, req,
5247 &state->param, state->total_param,
5248 &state->data, state->total_data,
5249 state->max_data_return);
5250 END_PROFILE(Trans2_findfirst);
5251 break;
5254 case TRANSACT2_FINDNEXT:
5256 START_PROFILE(Trans2_findnext);
5257 call_trans2findnext(conn, req,
5258 &state->param, state->total_param,
5259 &state->data, state->total_data,
5260 state->max_data_return);
5261 END_PROFILE(Trans2_findnext);
5262 break;
5265 case TRANSACT2_QFSINFO:
5267 START_PROFILE(Trans2_qfsinfo);
5268 call_trans2qfsinfo(conn, req,
5269 &state->param, state->total_param,
5270 &state->data, state->total_data,
5271 state->max_data_return);
5272 END_PROFILE(Trans2_qfsinfo);
5273 break;
5276 case TRANSACT2_SETFSINFO:
5278 START_PROFILE(Trans2_setfsinfo);
5279 call_trans2setfsinfo(conn, req,
5280 &state->param, state->total_param,
5281 &state->data, state->total_data,
5282 state->max_data_return);
5283 END_PROFILE(Trans2_setfsinfo);
5284 break;
5287 case TRANSACT2_QPATHINFO:
5289 START_PROFILE(Trans2_qpathinfo);
5290 call_trans2qpathinfo(
5291 conn,
5292 req,
5293 &state->param,
5294 state->total_param,
5295 &state->data,
5296 state->total_data,
5297 state->max_data_return);
5298 END_PROFILE(Trans2_qpathinfo);
5299 break;
5302 case TRANSACT2_QFILEINFO:
5304 START_PROFILE(Trans2_qfileinfo);
5305 call_trans2qfileinfo(
5306 conn,
5307 req,
5308 &state->param,
5309 state->total_param,
5310 &state->data,
5311 state->total_data,
5312 state->max_data_return);
5313 END_PROFILE(Trans2_qfileinfo);
5314 break;
5317 case TRANSACT2_SETPATHINFO:
5319 START_PROFILE(Trans2_setpathinfo);
5320 call_trans2setpathinfo(
5321 conn,
5322 req,
5323 &state->param,
5324 state->total_param,
5325 &state->data,
5326 state->total_data,
5327 state->max_data_return);
5328 END_PROFILE(Trans2_setpathinfo);
5329 break;
5332 case TRANSACT2_SETFILEINFO:
5334 START_PROFILE(Trans2_setfileinfo);
5335 call_trans2setfileinfo(
5336 conn,
5337 req,
5338 &state->param,
5339 state->total_param,
5340 &state->data,
5341 state->total_data,
5342 state->max_data_return);
5343 END_PROFILE(Trans2_setfileinfo);
5344 break;
5347 case TRANSACT2_FINDNOTIFYFIRST:
5349 START_PROFILE(Trans2_findnotifyfirst);
5350 call_trans2findnotifyfirst(conn, req,
5351 &state->param, state->total_param,
5352 &state->data, state->total_data,
5353 state->max_data_return);
5354 END_PROFILE(Trans2_findnotifyfirst);
5355 break;
5358 case TRANSACT2_FINDNOTIFYNEXT:
5360 START_PROFILE(Trans2_findnotifynext);
5361 call_trans2findnotifynext(conn, req,
5362 &state->param, state->total_param,
5363 &state->data, state->total_data,
5364 state->max_data_return);
5365 END_PROFILE(Trans2_findnotifynext);
5366 break;
5369 case TRANSACT2_MKDIR:
5371 START_PROFILE(Trans2_mkdir);
5372 call_trans2mkdir(conn, req,
5373 &state->param, state->total_param,
5374 &state->data, state->total_data,
5375 state->max_data_return);
5376 END_PROFILE(Trans2_mkdir);
5377 break;
5380 case TRANSACT2_GET_DFS_REFERRAL:
5382 START_PROFILE(Trans2_get_dfs_referral);
5383 call_trans2getdfsreferral(conn, req,
5384 &state->param, state->total_param,
5385 &state->data, state->total_data,
5386 state->max_data_return);
5387 END_PROFILE(Trans2_get_dfs_referral);
5388 break;
5391 case TRANSACT2_IOCTL:
5393 START_PROFILE(Trans2_ioctl);
5394 call_trans2ioctl(conn, req,
5395 &state->param, state->total_param,
5396 &state->data, state->total_data,
5397 state->max_data_return);
5398 END_PROFILE(Trans2_ioctl);
5399 break;
5402 default:
5403 /* Error in request */
5404 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5405 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5409 /****************************************************************************
5410 Reply to a SMBtrans2.
5411 ****************************************************************************/
5413 void reply_trans2(struct smb_request *req)
5415 connection_struct *conn = req->conn;
5416 unsigned int dsoff;
5417 unsigned int dscnt;
5418 unsigned int psoff;
5419 unsigned int pscnt;
5420 unsigned int tran_call;
5421 struct trans_state *state;
5422 NTSTATUS result;
5424 START_PROFILE(SMBtrans2);
5426 if (req->wct < 14) {
5427 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5428 END_PROFILE(SMBtrans2);
5429 return;
5432 dsoff = SVAL(req->vwv+12, 0);
5433 dscnt = SVAL(req->vwv+11, 0);
5434 psoff = SVAL(req->vwv+10, 0);
5435 pscnt = SVAL(req->vwv+9, 0);
5436 tran_call = SVAL(req->vwv+14, 0);
5438 result = allow_new_trans(conn->pending_trans, req->mid);
5439 if (!NT_STATUS_IS_OK(result)) {
5440 DEBUG(2, ("Got invalid trans2 request: %s\n",
5441 nt_errstr(result)));
5442 reply_nterror(req, result);
5443 END_PROFILE(SMBtrans2);
5444 return;
5447 if (IS_IPC(conn)) {
5448 switch (tran_call) {
5449 /* List the allowed trans2 calls on IPC$ */
5450 case TRANSACT2_OPEN:
5451 case TRANSACT2_GET_DFS_REFERRAL:
5452 case TRANSACT2_QFILEINFO:
5453 case TRANSACT2_QFSINFO:
5454 case TRANSACT2_SETFSINFO:
5455 break;
5456 default:
5457 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5458 END_PROFILE(SMBtrans2);
5459 return;
5463 if ((state = talloc(conn, struct trans_state)) == NULL) {
5464 DEBUG(0, ("talloc failed\n"));
5465 reply_nterror(req, NT_STATUS_NO_MEMORY);
5466 END_PROFILE(SMBtrans2);
5467 return;
5470 state->cmd = SMBtrans2;
5472 state->mid = req->mid;
5473 state->vuid = req->vuid;
5474 state->setup_count = SVAL(req->vwv+13, 0);
5475 state->setup = NULL;
5476 state->total_param = SVAL(req->vwv+0, 0);
5477 state->param = NULL;
5478 state->total_data = SVAL(req->vwv+1, 0);
5479 state->data = NULL;
5480 state->max_param_return = SVAL(req->vwv+2, 0);
5481 state->max_data_return = SVAL(req->vwv+3, 0);
5482 state->max_setup_return = SVAL(req->vwv+4, 0);
5483 state->close_on_completion = BITSETW(req->vwv+5, 0);
5484 state->one_way = BITSETW(req->vwv+5, 1);
5486 state->call = tran_call;
5488 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5489 is so as a sanity check */
5490 if (state->setup_count != 1) {
5492 * Need to have rc=0 for ioctl to get job id for OS/2.
5493 * Network printing will fail if function is not successful.
5494 * Similar function in reply.c will be used if protocol
5495 * is LANMAN1.0 instead of LM1.2X002.
5496 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5497 * outbuf doesn't have to be set(only job id is used).
5499 if ( (state->setup_count == 4)
5500 && (tran_call == TRANSACT2_IOCTL)
5501 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
5502 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
5503 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5504 } else {
5505 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5506 DEBUG(2,("Transaction is %d\n",tran_call));
5507 TALLOC_FREE(state);
5508 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5509 END_PROFILE(SMBtrans2);
5510 return;
5514 if ((dscnt > state->total_data) || (pscnt > state->total_param))
5515 goto bad_param;
5517 if (state->total_data) {
5519 if (smb_buffer_oob(state->total_data, 0, dscnt)
5520 || smb_buffer_oob(smb_len(req->inbuf), dsoff, dscnt)) {
5521 goto bad_param;
5524 /* Can't use talloc here, the core routines do realloc on the
5525 * params and data. */
5526 state->data = (char *)SMB_MALLOC(state->total_data);
5527 if (state->data == NULL) {
5528 DEBUG(0,("reply_trans2: data malloc fail for %u "
5529 "bytes !\n", (unsigned int)state->total_data));
5530 TALLOC_FREE(state);
5531 reply_nterror(req, NT_STATUS_NO_MEMORY);
5532 END_PROFILE(SMBtrans2);
5533 return;
5536 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
5539 if (state->total_param) {
5541 if (smb_buffer_oob(state->total_param, 0, pscnt)
5542 || smb_buffer_oob(smb_len(req->inbuf), psoff, pscnt)) {
5543 goto bad_param;
5546 /* Can't use talloc here, the core routines do realloc on the
5547 * params and data. */
5548 state->param = (char *)SMB_MALLOC(state->total_param);
5549 if (state->param == NULL) {
5550 DEBUG(0,("reply_trans: param malloc fail for %u "
5551 "bytes !\n", (unsigned int)state->total_param));
5552 SAFE_FREE(state->data);
5553 TALLOC_FREE(state);
5554 reply_nterror(req, NT_STATUS_NO_MEMORY);
5555 END_PROFILE(SMBtrans2);
5556 return;
5559 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
5562 state->received_data = dscnt;
5563 state->received_param = pscnt;
5565 if ((state->received_param == state->total_param) &&
5566 (state->received_data == state->total_data)) {
5568 handle_trans2(conn, req, state);
5570 SAFE_FREE(state->data);
5571 SAFE_FREE(state->param);
5572 TALLOC_FREE(state);
5573 END_PROFILE(SMBtrans2);
5574 return;
5577 DLIST_ADD(conn->pending_trans, state);
5579 /* We need to send an interim response then receive the rest
5580 of the parameter/data bytes */
5581 reply_smb1_outbuf(req, 0, 0);
5582 show_msg((char *)req->outbuf);
5583 END_PROFILE(SMBtrans2);
5584 return;
5586 bad_param:
5588 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5589 SAFE_FREE(state->data);
5590 SAFE_FREE(state->param);
5591 TALLOC_FREE(state);
5592 END_PROFILE(SMBtrans2);
5593 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5596 /****************************************************************************
5597 Reply to a SMBtranss2
5598 ****************************************************************************/
5600 void reply_transs2(struct smb_request *req)
5602 connection_struct *conn = req->conn;
5603 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5604 struct trans_state *state;
5606 START_PROFILE(SMBtranss2);
5608 show_msg((const char *)req->inbuf);
5610 /* Windows clients expect all replies to
5611 a transact secondary (SMBtranss2 0x33)
5612 to have a command code of transact
5613 (SMBtrans2 0x32). See bug #8989
5614 and also [MS-CIFS] section 2.2.4.47.2
5615 for details.
5617 req->cmd = SMBtrans2;
5619 if (req->wct < 8) {
5620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5621 END_PROFILE(SMBtranss2);
5622 return;
5625 for (state = conn->pending_trans; state != NULL;
5626 state = state->next) {
5627 if (state->mid == req->mid) {
5628 break;
5632 if ((state == NULL) || (state->cmd != SMBtrans2)) {
5633 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5634 END_PROFILE(SMBtranss2);
5635 return;
5638 /* Revise state->total_param and state->total_data in case they have
5639 changed downwards */
5641 if (SVAL(req->vwv+0, 0) < state->total_param)
5642 state->total_param = SVAL(req->vwv+0, 0);
5643 if (SVAL(req->vwv+1, 0) < state->total_data)
5644 state->total_data = SVAL(req->vwv+1, 0);
5646 pcnt = SVAL(req->vwv+2, 0);
5647 poff = SVAL(req->vwv+3, 0);
5648 pdisp = SVAL(req->vwv+4, 0);
5650 dcnt = SVAL(req->vwv+5, 0);
5651 doff = SVAL(req->vwv+6, 0);
5652 ddisp = SVAL(req->vwv+7, 0);
5654 state->received_param += pcnt;
5655 state->received_data += dcnt;
5657 if ((state->received_data > state->total_data) ||
5658 (state->received_param > state->total_param))
5659 goto bad_param;
5661 if (pcnt) {
5662 if (smb_buffer_oob(state->total_param, pdisp, pcnt)
5663 || smb_buffer_oob(smb_len(req->inbuf), poff, pcnt)) {
5664 goto bad_param;
5666 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
5669 if (dcnt) {
5670 if (smb_buffer_oob(state->total_data, ddisp, dcnt)
5671 || smb_buffer_oob(smb_len(req->inbuf), doff, dcnt)) {
5672 goto bad_param;
5674 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
5677 if ((state->received_param < state->total_param) ||
5678 (state->received_data < state->total_data)) {
5679 END_PROFILE(SMBtranss2);
5680 return;
5683 handle_trans2(conn, req, state);
5685 DLIST_REMOVE(conn->pending_trans, state);
5686 SAFE_FREE(state->data);
5687 SAFE_FREE(state->param);
5688 TALLOC_FREE(state);
5690 END_PROFILE(SMBtranss2);
5691 return;
5693 bad_param:
5695 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5696 DLIST_REMOVE(conn->pending_trans, state);
5697 SAFE_FREE(state->data);
5698 SAFE_FREE(state->param);
5699 TALLOC_FREE(state);
5700 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5701 END_PROFILE(SMBtranss2);