s3/smbd: If we fail to close file_handle ensure we should reset the fd
[Samba.git] / source3 / smbd / smb1_trans2.c
blob6a10437713326abb0eb2355878caeeaf2ac8f4e8
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!!!", 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", strerror(errno)));
477 if (!eal->ea.name) {
478 return NULL;
481 offset += (namelen + 1); /* Go past the name + terminating zero. */
482 DLIST_ADD_END(ea_list_head, eal);
483 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
486 return ea_list_head;
489 /****************************************************************************
490 Reply to a TRANSACT2_OPEN.
491 ****************************************************************************/
493 static void call_trans2open(connection_struct *conn,
494 struct smb_request *req,
495 char **pparams, int total_params,
496 char **ppdata, int total_data,
497 unsigned int max_data_bytes)
499 struct smb_filename *smb_fname = NULL;
500 char *params = *pparams;
501 char *pdata = *ppdata;
502 int deny_mode;
503 int32_t open_attr;
504 bool oplock_request;
505 #if 0
506 bool return_additional_info;
507 int16 open_sattr;
508 time_t open_time;
509 #endif
510 int open_ofun;
511 uint32_t open_size;
512 char *pname;
513 char *fname = NULL;
514 off_t size=0;
515 int fattr=0,mtime=0;
516 SMB_INO_T inode = 0;
517 int smb_action = 0;
518 struct files_struct *dirfsp = NULL;
519 files_struct *fsp;
520 struct ea_list *ea_list = NULL;
521 uint16_t flags = 0;
522 NTSTATUS status;
523 uint32_t access_mask;
524 uint32_t share_mode;
525 uint32_t create_disposition;
526 uint32_t create_options = 0;
527 uint32_t private_flags = 0;
528 NTTIME twrp = 0;
529 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
530 TALLOC_CTX *ctx = talloc_tos();
533 * Ensure we have enough parameters to perform the operation.
536 if (total_params < 29) {
537 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
538 goto out;
541 flags = SVAL(params, 0);
542 deny_mode = SVAL(params, 2);
543 open_attr = SVAL(params,6);
544 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
545 if (oplock_request) {
546 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
549 #if 0
550 return_additional_info = BITSETW(params,0);
551 open_sattr = SVAL(params, 4);
552 open_time = make_unix_date3(params+8);
553 #endif
554 open_ofun = SVAL(params,12);
555 open_size = IVAL(params,14);
556 pname = &params[28];
558 if (IS_IPC(conn)) {
559 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
560 goto out;
563 if (req->posix_pathnames) {
564 srvstr_get_path_posix(ctx,
565 params,
566 req->flags2,
567 &fname,
568 pname,
569 total_params - 28,
570 STR_TERMINATE,
571 &status);
572 } else {
573 srvstr_get_path(ctx,
574 params,
575 req->flags2,
576 &fname,
577 pname,
578 total_params - 28,
579 STR_TERMINATE,
580 &status);
582 if (!NT_STATUS_IS_OK(status)) {
583 reply_nterror(req, status);
584 goto out;
587 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
588 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
589 (unsigned int)open_ofun, open_size));
591 if (ucf_flags & UCF_GMT_PATHNAME) {
592 extract_snapshot_token(fname, &twrp);
594 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
595 if (!NT_STATUS_IS_OK(status)) {
596 reply_nterror(req, status);
597 goto out;
599 status = filename_convert_dirfsp(ctx,
600 conn,
601 fname,
602 ucf_flags,
603 twrp,
604 &dirfsp,
605 &smb_fname);
606 if (!NT_STATUS_IS_OK(status)) {
607 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
608 reply_botherror(req,
609 NT_STATUS_PATH_NOT_COVERED,
610 ERRSRV, ERRbadpath);
611 goto out;
613 reply_nterror(req, status);
614 goto out;
617 if (open_ofun == 0) {
618 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
619 goto out;
622 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
623 open_ofun,
624 &access_mask, &share_mode,
625 &create_disposition,
626 &create_options,
627 &private_flags)) {
628 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
629 goto out;
632 /* Any data in this call is an EA list. */
633 if (total_data && (total_data != 4)) {
634 if (total_data < 10) {
635 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
636 goto out;
639 if (IVAL(pdata,0) > total_data) {
640 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
641 IVAL(pdata,0), (unsigned int)total_data));
642 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
643 goto out;
646 ea_list = read_ea_list(talloc_tos(), pdata + 4,
647 total_data - 4);
648 if (!ea_list) {
649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
650 goto out;
653 if (!lp_ea_support(SNUM(conn))) {
654 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
655 goto out;
658 if (!req->posix_pathnames &&
659 ea_list_has_invalid_name(ea_list)) {
660 int param_len = 30;
661 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
662 if(*pparams == NULL ) {
663 reply_nterror(req, NT_STATUS_NO_MEMORY);
664 goto out;
666 params = *pparams;
667 memset(params, '\0', param_len);
668 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
669 params, param_len, NULL, 0, max_data_bytes);
670 goto out;
674 status = SMB_VFS_CREATE_FILE(
675 conn, /* conn */
676 req, /* req */
677 dirfsp, /* dirfsp */
678 smb_fname, /* fname */
679 access_mask, /* access_mask */
680 share_mode, /* share_access */
681 create_disposition, /* create_disposition*/
682 create_options, /* create_options */
683 open_attr, /* file_attributes */
684 oplock_request, /* oplock_request */
685 NULL, /* lease */
686 open_size, /* allocation_size */
687 private_flags,
688 NULL, /* sd */
689 ea_list, /* ea_list */
690 &fsp, /* result */
691 &smb_action, /* psbuf */
692 NULL, NULL); /* create context */
694 if (!NT_STATUS_IS_OK(status)) {
695 if (open_was_deferred(req->xconn, req->mid)) {
696 /* We have re-scheduled this call. */
697 goto out;
700 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
701 reply_openerror(req, status);
702 goto out;
705 fsp = fcb_or_dos_open(
706 req,
707 smb_fname,
708 access_mask,
709 create_options,
710 private_flags);
711 if (fsp == NULL) {
712 bool ok = defer_smb1_sharing_violation(req);
713 if (ok) {
714 goto out;
716 reply_openerror(req, status);
717 goto out;
720 smb_action = FILE_WAS_OPENED;
723 size = get_file_size_stat(&smb_fname->st);
724 fattr = fdos_mode(fsp);
725 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
726 inode = smb_fname->st.st_ex_ino;
727 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
728 close_file_free(req, &fsp, ERROR_CLOSE);
729 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
730 goto out;
733 /* Realloc the size of parameters and data we will return */
734 *pparams = (char *)SMB_REALLOC(*pparams, 30);
735 if(*pparams == NULL ) {
736 reply_nterror(req, NT_STATUS_NO_MEMORY);
737 goto out;
739 params = *pparams;
741 SSVAL(params,0,fsp->fnum);
742 SSVAL(params,2,fattr);
743 srv_put_dos_date2(params,4, mtime);
744 SIVAL(params,8, (uint32_t)size);
745 SSVAL(params,12,deny_mode);
746 SSVAL(params,14,0); /* open_type - file or directory. */
747 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
749 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
750 smb_action |= EXTENDED_OPLOCK_GRANTED;
753 SSVAL(params,18,smb_action);
756 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
758 SIVAL(params,20,inode);
759 SSVAL(params,24,0); /* Padding. */
760 if (flags & 8) {
761 uint32_t ea_size = estimate_ea_size(smb_fname->fsp);
762 SIVAL(params, 26, ea_size);
763 } else {
764 SIVAL(params, 26, 0);
767 /* Send the required number of replies */
768 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
769 out:
770 TALLOC_FREE(smb_fname);
773 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
774 connection_struct *conn,
775 struct dptr_struct *dirptr,
776 uint16_t flags2,
777 const char *path_mask,
778 uint32_t dirtype,
779 int info_level,
780 bool requires_resume_key,
781 bool dont_descend,
782 bool ask_sharemode,
783 char **ppdata,
784 char *base_data,
785 char *end_data,
786 int space_remaining,
787 int *last_entry_off,
788 struct ea_list *name_list)
790 uint8_t align = 4;
791 const bool do_pad = true;
793 if (info_level >= 1 && info_level <= 3) {
794 /* No alignment on earlier info levels. */
795 align = 1;
798 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
799 path_mask, dirtype, info_level,
800 requires_resume_key, dont_descend, ask_sharemode,
801 true, align, do_pad,
802 ppdata, base_data, end_data,
803 space_remaining,
804 NULL,
805 last_entry_off, name_list, NULL);
808 /****************************************************************************
809 Reply to a TRANS2_FINDFIRST.
810 ****************************************************************************/
812 static void call_trans2findfirst(connection_struct *conn,
813 struct smb_request *req,
814 char **pparams, int total_params,
815 char **ppdata, int total_data,
816 unsigned int max_data_bytes)
818 /* We must be careful here that we don't return more than the
819 allowed number of data bytes. If this means returning fewer than
820 maxentries then so be it. We assume that the redirector has
821 enough room for the fixed number of parameter bytes it has
822 requested. */
823 struct smb_filename *smb_dname = NULL;
824 char *params = *pparams;
825 char *pdata = *ppdata;
826 char *data_end;
827 uint32_t dirtype;
828 int maxentries;
829 uint16_t findfirst_flags;
830 bool close_after_first;
831 bool close_if_end;
832 bool requires_resume_key;
833 int info_level;
834 char *directory = NULL;
835 char *mask = NULL;
836 char *p;
837 int last_entry_off=0;
838 int dptr_num = -1;
839 int numentries = 0;
840 int i;
841 bool finished = False;
842 bool dont_descend = False;
843 bool out_of_space = False;
844 int space_remaining;
845 struct ea_list *ea_list = NULL;
846 NTSTATUS ntstatus = NT_STATUS_OK;
847 bool ask_sharemode;
848 struct smbXsrv_connection *xconn = req->xconn;
849 struct smbd_server_connection *sconn = req->sconn;
850 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
851 bool backup_priv = false;
852 bool as_root = false;
853 files_struct *fsp = NULL;
854 struct files_struct *dirfsp = NULL;
855 const struct loadparm_substitution *lp_sub =
856 loadparm_s3_global_substitution();
858 if (total_params < 13) {
859 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
860 goto out;
863 dirtype = SVAL(params,0);
864 maxentries = SVAL(params,2);
865 findfirst_flags = SVAL(params,4);
866 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
867 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
868 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
869 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
870 security_token_has_privilege(get_current_nttok(conn),
871 SEC_PRIV_BACKUP));
873 info_level = SVAL(params,6);
875 DBG_NOTICE("dirtype = %"PRIx32", maxentries = %d, "
876 "close_after_first=%d, close_if_end = %d "
877 "requires_resume_key = %d backup_priv = %d level = 0x%x, "
878 "max_data_bytes = %d\n",
879 dirtype,
880 maxentries,
881 close_after_first,
882 close_if_end,
883 requires_resume_key,
884 backup_priv,
885 info_level,
886 max_data_bytes);
888 if (!maxentries) {
889 /* W2K3 seems to treat zero as 1. */
890 maxentries = 1;
893 switch (info_level) {
894 case SMB_FIND_INFO_STANDARD:
895 case SMB_FIND_EA_SIZE:
896 case SMB_FIND_EA_LIST:
897 case SMB_FIND_FILE_DIRECTORY_INFO:
898 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
899 case SMB_FIND_FILE_NAMES_INFO:
900 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
901 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
902 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
903 break;
904 case SMB_FIND_FILE_UNIX:
905 case SMB_FIND_FILE_UNIX_INFO2:
906 if (!lp_smb1_unix_extensions()) {
907 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
908 goto out;
910 if (!req->posix_pathnames) {
911 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
912 goto out;
914 break;
915 default:
916 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
917 goto out;
920 if (req->posix_pathnames) {
921 srvstr_get_path_posix(talloc_tos(),
922 params,
923 req->flags2,
924 &directory,
925 params+12,
926 total_params - 12,
927 STR_TERMINATE,
928 &ntstatus);
929 } else {
930 srvstr_get_path(talloc_tos(),
931 params,
932 req->flags2,
933 &directory,
934 params+12,
935 total_params - 12,
936 STR_TERMINATE,
937 &ntstatus);
939 if (!NT_STATUS_IS_OK(ntstatus)) {
940 reply_nterror(req, ntstatus);
941 goto out;
944 if (backup_priv) {
945 become_root();
946 as_root = true;
948 ntstatus = smb1_strip_dfs_path(talloc_tos(), &ucf_flags, &directory);
949 if (!NT_STATUS_IS_OK(ntstatus)) {
950 reply_nterror(req, ntstatus);
951 goto out;
954 ntstatus = filename_convert_smb1_search_path(talloc_tos(),
955 conn,
956 directory,
957 ucf_flags,
958 &dirfsp,
959 &smb_dname,
960 &mask);
962 if (!NT_STATUS_IS_OK(ntstatus)) {
963 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
964 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
965 ERRSRV, ERRbadpath);
966 goto out;
968 reply_nterror(req, ntstatus);
969 goto out;
972 TALLOC_FREE(directory);
973 directory = smb_dname->base_name;
975 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
977 if (info_level == SMB_FIND_EA_LIST) {
978 uint32_t ea_size;
980 if (total_data < 4) {
981 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
982 goto out;
985 ea_size = IVAL(pdata,0);
986 if (ea_size != total_data) {
987 DBG_NOTICE("Rejecting EA request with incorrect "
988 "total_data=%d (should be %" PRIu32 ")\n",
989 total_data,
990 ea_size);
991 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
992 goto out;
995 if (!lp_ea_support(SNUM(conn))) {
996 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
997 goto out;
1000 /* Pull out the list of names. */
1001 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
1002 if (!ea_list) {
1003 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1004 goto out;
1008 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1009 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1010 goto out;
1013 *ppdata = (char *)SMB_REALLOC(
1014 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1015 if(*ppdata == NULL ) {
1016 reply_nterror(req, NT_STATUS_NO_MEMORY);
1017 goto out;
1019 pdata = *ppdata;
1020 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1022 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
1023 * error.
1025 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
1026 /* Realloc the params space */
1027 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1028 if (*pparams == NULL) {
1029 reply_nterror(req, NT_STATUS_NO_MEMORY);
1030 goto out;
1032 params = *pparams;
1035 * Open an fsp on this directory for the dptr.
1037 ntstatus = SMB_VFS_CREATE_FILE(
1038 conn, /* conn */
1039 req, /* req */
1040 dirfsp, /* dirfsp */
1041 smb_dname, /* dname */
1042 FILE_LIST_DIRECTORY, /* access_mask */
1043 FILE_SHARE_READ|
1044 FILE_SHARE_WRITE, /* share_access */
1045 FILE_OPEN, /* create_disposition*/
1046 FILE_DIRECTORY_FILE, /* create_options */
1047 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1048 NO_OPLOCK, /* oplock_request */
1049 NULL, /* lease */
1050 0, /* allocation_size */
1051 0, /* private_flags */
1052 NULL, /* sd */
1053 NULL, /* ea_list */
1054 &fsp, /* result */
1055 NULL, /* pinfo */
1056 NULL, /* in_context */
1057 NULL);/* out_context */
1059 if (!NT_STATUS_IS_OK(ntstatus)) {
1060 DBG_ERR("failed to open directory %s\n",
1061 smb_fname_str_dbg(smb_dname));
1062 reply_nterror(req, ntstatus);
1063 goto out;
1066 /* Save the wildcard match and attribs we are using on this directory -
1067 needed as lanman2 assumes these are being saved between calls */
1069 ntstatus = dptr_create(conn,
1070 req,
1071 fsp, /* fsp */
1072 False,
1073 mask,
1074 dirtype,
1075 &fsp->dptr);
1077 if (!NT_STATUS_IS_OK(ntstatus)) {
1079 * Use NULL here for the first parameter (req)
1080 * as this is not a client visible handle so
1081 * can't be part of an SMB1 chain.
1083 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1084 reply_nterror(req, ntstatus);
1085 goto out;
1088 if (backup_priv) {
1089 /* Remember this in case we have
1090 to do a findnext. */
1091 dptr_set_priv(fsp->dptr);
1094 dptr_num = dptr_dnum(fsp->dptr);
1095 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1097 /* We don't need to check for VOL here as this is returned by
1098 a different TRANS2 call. */
1100 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1101 directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
1102 if (in_list(directory,
1103 lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
1104 dptr_case_sensitive(fsp->dptr))) {
1105 dont_descend = True;
1108 p = pdata;
1109 space_remaining = max_data_bytes;
1110 out_of_space = False;
1112 ask_sharemode = fsp_search_ask_sharemode(fsp);
1114 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1116 ntstatus = get_lanman2_dir_entry(talloc_tos(),
1117 conn,
1118 fsp->dptr,
1119 req->flags2,
1120 mask,
1121 dirtype,
1122 info_level,
1123 requires_resume_key,
1124 dont_descend,
1125 ask_sharemode,
1127 pdata,
1128 data_end,
1129 space_remaining,
1130 &last_entry_off,
1131 ea_list);
1132 if (NT_STATUS_EQUAL(ntstatus, NT_STATUS_ILLEGAL_CHARACTER)) {
1134 * Bad character conversion on name. Ignore
1135 * this entry.
1137 continue;
1139 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
1140 out_of_space = true;
1141 } else {
1142 finished = !NT_STATUS_IS_OK(ntstatus);
1145 if (!finished && !out_of_space) {
1146 numentries++;
1149 /* Ensure space_remaining never goes -ve. */
1150 if (PTR_DIFF(p,pdata) > max_data_bytes) {
1151 space_remaining = 0;
1152 out_of_space = true;
1153 } else {
1154 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1158 /* Check if we can close the dirptr */
1159 if(close_after_first || (finished && close_if_end)) {
1160 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1161 dptr_num = -1;
1162 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1166 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1167 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1168 * the protocol level is less than NT1. Tested with smbclient. JRA.
1169 * This should fix the OS/2 client bug #2335.
1172 if(numentries == 0) {
1173 dptr_num = -1;
1175 * We may have already closed the file in the
1176 * close_after_first or finished case above.
1178 if (fsp != NULL) {
1179 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1181 if (xconn->protocol < PROTOCOL_NT1) {
1182 reply_force_doserror(req, ERRDOS, ERRnofiles);
1183 goto out;
1184 } else {
1185 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
1186 ERRDOS, ERRbadfile);
1187 goto out;
1191 /* At this point pdata points to numentries directory entries. */
1193 /* Set up the return parameter block */
1194 SSVAL(params,0,dptr_num);
1195 SSVAL(params,2,numentries);
1196 SSVAL(params,4,finished);
1197 SSVAL(params,6,0); /* Never an EA error */
1198 SSVAL(params,8,last_entry_off);
1200 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
1201 max_data_bytes);
1203 if ((! *directory) && dptr_path(sconn, dptr_num)) {
1204 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
1205 if (!directory) {
1206 reply_nterror(req, NT_STATUS_NO_MEMORY);
1210 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1211 smb_fn_name(req->cmd),
1212 mask, directory, dirtype, numentries ) );
1215 * Force a name mangle here to ensure that the
1216 * mask as an 8.3 name is top of the mangled cache.
1217 * The reasons for this are subtle. Don't remove
1218 * this code unless you know what you are doing
1219 * (see PR#13758). JRA.
1222 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
1223 char mangled_name[13];
1224 name_to_8_3(mask, mangled_name, True, conn->params);
1226 out:
1228 if (as_root) {
1229 unbecome_root();
1232 TALLOC_FREE(smb_dname);
1233 return;
1236 static bool smbd_dptr_name_equal(struct dptr_struct *dptr,
1237 const char *name1,
1238 const char *name2)
1240 bool equal;
1242 if (dptr_case_sensitive(dptr)) {
1243 equal = (strcmp(name1, name2) == 0);
1244 } else {
1245 equal = strequal(name1, name2);
1248 return equal;
1251 /****************************************************************************
1252 Reply to a TRANS2_FINDNEXT.
1253 ****************************************************************************/
1255 static void call_trans2findnext(connection_struct *conn,
1256 struct smb_request *req,
1257 char **pparams, int total_params,
1258 char **ppdata, int total_data,
1259 unsigned int max_data_bytes)
1261 /* We must be careful here that we don't return more than the
1262 allowed number of data bytes. If this means returning fewer than
1263 maxentries then so be it. We assume that the redirector has
1264 enough room for the fixed number of parameter bytes it has
1265 requested. */
1266 char *params = *pparams;
1267 char *pdata = *ppdata;
1268 char *data_end;
1269 int dptr_num;
1270 int maxentries;
1271 uint16_t info_level;
1272 uint32_t resume_key;
1273 uint16_t findnext_flags;
1274 bool close_after_request;
1275 bool close_if_end;
1276 bool requires_resume_key;
1277 bool continue_bit;
1278 char *resume_name = NULL;
1279 const char *mask = NULL;
1280 const char *directory = NULL;
1281 char *p = NULL;
1282 uint16_t dirtype;
1283 int numentries = 0;
1284 int i, last_entry_off=0;
1285 bool finished = False;
1286 bool dont_descend = False;
1287 bool out_of_space = False;
1288 int space_remaining;
1289 struct ea_list *ea_list = NULL;
1290 NTSTATUS ntstatus = NT_STATUS_OK;
1291 bool ask_sharemode;
1292 TALLOC_CTX *ctx = talloc_tos();
1293 struct smbd_server_connection *sconn = req->sconn;
1294 bool backup_priv = false;
1295 bool as_root = false;
1296 files_struct *fsp = NULL;
1297 const struct loadparm_substitution *lp_sub =
1298 loadparm_s3_global_substitution();
1300 if (total_params < 13) {
1301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1302 return;
1305 dptr_num = SVAL(params,0);
1306 maxentries = SVAL(params,2);
1307 info_level = SVAL(params,4);
1308 resume_key = IVAL(params,6);
1309 findnext_flags = SVAL(params,10);
1310 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1311 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1312 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1313 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1315 if (!continue_bit) {
1316 /* We only need resume_name if continue_bit is zero. */
1317 if (req->posix_pathnames) {
1318 srvstr_get_path_posix(ctx,
1319 params,
1320 req->flags2,
1321 &resume_name,
1322 params+12,
1323 total_params - 12,
1324 STR_TERMINATE,
1325 &ntstatus);
1326 } else {
1327 srvstr_get_path(ctx,
1328 params,
1329 req->flags2,
1330 &resume_name,
1331 params+12,
1332 total_params - 12,
1333 STR_TERMINATE,
1334 &ntstatus);
1336 if (!NT_STATUS_IS_OK(ntstatus)) {
1337 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1338 complain (it thinks we're asking for the directory above the shared
1339 path or an invalid name). Catch this as the resume name is only compared, never used in
1340 a file access. JRA. */
1341 srvstr_pull_talloc(ctx, params, req->flags2,
1342 &resume_name, params+12,
1343 total_params - 12,
1344 STR_TERMINATE);
1346 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
1347 reply_nterror(req, ntstatus);
1348 return;
1353 DBG_NOTICE("dirhandle = %d, max_data_bytes = %u, maxentries = %d, "
1354 "close_after_request=%d, close_if_end = %d "
1355 "requires_resume_key = %d resume_key = %d "
1356 "resume name = %s continue=%d level = %d\n",
1357 dptr_num,
1358 max_data_bytes,
1359 maxentries,
1360 close_after_request,
1361 close_if_end,
1362 requires_resume_key,
1363 resume_key,
1364 resume_name ? resume_name : "(NULL)",
1365 continue_bit,
1366 info_level);
1368 if (!maxentries) {
1369 /* W2K3 seems to treat zero as 1. */
1370 maxentries = 1;
1373 switch (info_level) {
1374 case SMB_FIND_INFO_STANDARD:
1375 case SMB_FIND_EA_SIZE:
1376 case SMB_FIND_EA_LIST:
1377 case SMB_FIND_FILE_DIRECTORY_INFO:
1378 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1379 case SMB_FIND_FILE_NAMES_INFO:
1380 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1381 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1382 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1383 break;
1384 case SMB_FIND_FILE_UNIX:
1385 case SMB_FIND_FILE_UNIX_INFO2:
1386 if (!lp_smb1_unix_extensions()) {
1387 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1388 return;
1390 if (!req->posix_pathnames) {
1391 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1392 return;
1394 break;
1395 default:
1396 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1397 return;
1400 if (info_level == SMB_FIND_EA_LIST) {
1401 uint32_t ea_size;
1403 if (total_data < 4) {
1404 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1405 return;
1408 ea_size = IVAL(pdata,0);
1409 if (ea_size != total_data) {
1410 DBG_NOTICE("Rejecting EA request with incorrect "
1411 "total_data=%d (should be %" PRIu32 ")\n",
1412 total_data,
1413 ea_size);
1414 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1415 return;
1418 if (!lp_ea_support(SNUM(conn))) {
1419 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1420 return;
1423 /* Pull out the list of names. */
1424 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1425 if (!ea_list) {
1426 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1427 return;
1431 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1432 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1433 return;
1436 *ppdata = (char *)SMB_REALLOC(
1437 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1438 if(*ppdata == NULL) {
1439 reply_nterror(req, NT_STATUS_NO_MEMORY);
1440 return;
1443 pdata = *ppdata;
1444 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1447 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
1448 * error.
1450 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
1451 /* Realloc the params space */
1452 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1453 if(*pparams == NULL ) {
1454 reply_nterror(req, NT_STATUS_NO_MEMORY);
1455 return;
1458 params = *pparams;
1460 /* Check that the dptr is valid */
1461 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
1462 if (fsp == NULL) {
1463 reply_nterror(req, STATUS_NO_MORE_FILES);
1464 return;
1467 directory = dptr_path(sconn, dptr_num);
1469 /* Get the wildcard mask from the dptr */
1470 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
1471 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1472 reply_nterror(req, STATUS_NO_MORE_FILES);
1473 return;
1476 /* Get the attr mask from the dptr */
1477 dirtype = dptr_attr(sconn, dptr_num);
1479 backup_priv = dptr_get_priv(fsp->dptr);
1481 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX) "
1482 "backup_priv = %d\n",
1483 dptr_num, mask, dirtype,
1484 (long)fsp->dptr,
1485 (int)backup_priv));
1487 /* We don't need to check for VOL here as this is returned by
1488 a different TRANS2 call. */
1490 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1491 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1492 if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),
1493 dptr_case_sensitive(fsp->dptr)))
1494 dont_descend = True;
1496 p = pdata;
1497 space_remaining = max_data_bytes;
1498 out_of_space = False;
1500 if (backup_priv) {
1501 become_root();
1502 as_root = true;
1506 * Seek to the correct position. We no longer use the resume key but
1507 * depend on the last file name instead.
1510 if(!continue_bit && resume_name && *resume_name) {
1511 bool posix_open = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN);
1512 char *last_name_sent = NULL;
1513 bool sequential;
1516 * Remember, name_to_8_3 is called by
1517 * get_lanman2_dir_entry(), so the resume name
1518 * could be mangled. Ensure we check the unmangled name.
1521 if (!posix_open &&
1522 mangle_is_mangled(resume_name, conn->params)) {
1523 char *new_resume_name = NULL;
1524 mangle_lookup_name_from_8_3(ctx,
1525 resume_name,
1526 &new_resume_name,
1527 conn->params);
1528 if (new_resume_name) {
1529 resume_name = new_resume_name;
1534 * Fix for NT redirector problem triggered by resume key indexes
1535 * changing between directory scans. We now return a resume key of 0
1536 * and instead look for the filename to continue from (also given
1537 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1538 * findfirst/findnext (as is usual) then the directory pointer
1539 * should already be at the correct place.
1542 last_name_sent = smbd_dirptr_get_last_name_sent(fsp->dptr);
1543 sequential = smbd_dptr_name_equal(fsp->dptr,
1544 resume_name,
1545 last_name_sent);
1546 if (!sequential) {
1547 char *name = NULL;
1548 bool found = false;
1550 dptr_RewindDir(fsp->dptr);
1552 while ((name = dptr_ReadDirName(talloc_tos(),
1553 fsp->dptr)) != NULL) {
1554 found = smbd_dptr_name_equal(fsp->dptr,
1555 resume_name,
1556 name);
1557 TALLOC_FREE(name);
1558 if (found) {
1559 break;
1563 if (!found) {
1565 * We got a name that used to exist
1566 * but does not anymore. Just start
1567 * from the beginning. Shown by the
1568 * "raw.search.os2 delete" smbtorture
1569 * test.
1571 dptr_RewindDir(fsp->dptr);
1574 } /* end if resume_name && !continue_bit */
1576 ask_sharemode = fsp_search_ask_sharemode(fsp);
1578 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1580 ntstatus = get_lanman2_dir_entry(ctx,
1581 conn,
1582 fsp->dptr,
1583 req->flags2,
1584 mask,
1585 dirtype,
1586 info_level,
1587 requires_resume_key,
1588 dont_descend,
1589 ask_sharemode,
1591 pdata,
1592 data_end,
1593 space_remaining,
1594 &last_entry_off,
1595 ea_list);
1596 if (NT_STATUS_EQUAL(ntstatus, NT_STATUS_ILLEGAL_CHARACTER)) {
1598 * Bad character conversion on name. Ignore
1599 * this entry.
1601 continue;
1603 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
1604 out_of_space = true;
1605 } else {
1606 finished = !NT_STATUS_IS_OK(ntstatus);
1609 if (!finished && !out_of_space) {
1610 numentries++;
1613 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1616 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1617 smb_fn_name(req->cmd),
1618 mask, directory, dirtype, numentries ) );
1620 /* Check if we can close the fsp->dptr */
1621 if(close_after_request || (finished && close_if_end)) {
1622 DBG_INFO("closing dptr_num = %d\n", dptr_num);
1623 dptr_num = -1;
1624 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1627 if (as_root) {
1628 unbecome_root();
1631 /* Set up the return parameter block */
1632 SSVAL(params,0,numentries);
1633 SSVAL(params,2,finished);
1634 SSVAL(params,4,0); /* Never an EA error */
1635 SSVAL(params,6,last_entry_off);
1637 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
1638 max_data_bytes);
1640 return;
1643 /****************************************************************************
1644 Reply to a TRANS2_QFSINFO (query filesystem info).
1645 ****************************************************************************/
1647 static void call_trans2qfsinfo(connection_struct *conn,
1648 struct smb_request *req,
1649 char **pparams, int total_params,
1650 char **ppdata, int total_data,
1651 unsigned int max_data_bytes)
1653 char *params = *pparams;
1654 uint16_t info_level;
1655 int data_len = 0;
1656 size_t fixed_portion;
1657 NTSTATUS status;
1659 if (total_params < 2) {
1660 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1661 return;
1664 info_level = SVAL(params,0);
1666 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
1667 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
1668 DEBUG(0,("call_trans2qfsinfo: encryption required "
1669 "and info level 0x%x sent.\n",
1670 (unsigned int)info_level));
1671 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1672 return;
1676 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1678 status = smbd_do_qfsinfo(req->xconn, conn, req,
1679 info_level,
1680 req->flags2,
1681 max_data_bytes,
1682 &fixed_portion,
1683 NULL,
1684 ppdata, &data_len);
1685 if (!NT_STATUS_IS_OK(status)) {
1686 reply_nterror(req, status);
1687 return;
1690 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
1691 max_data_bytes);
1693 DEBUG( 4, ( "%s info_level = %d\n",
1694 smb_fn_name(req->cmd), info_level) );
1696 return;
1699 /****************************************************************************
1700 Reply to a TRANS2_SETFSINFO (set filesystem info).
1701 ****************************************************************************/
1703 static void call_trans2setfsinfo(connection_struct *conn,
1704 struct smb_request *req,
1705 char **pparams, int total_params,
1706 char **ppdata, int total_data,
1707 unsigned int max_data_bytes)
1709 const struct loadparm_substitution *lp_sub =
1710 loadparm_s3_global_substitution();
1711 struct smbXsrv_connection *xconn = req->xconn;
1712 char *pdata = *ppdata;
1713 char *params = *pparams;
1714 uint16_t info_level;
1716 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
1717 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
1719 /* */
1720 if (total_params < 4) {
1721 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1722 total_params));
1723 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1724 return;
1727 info_level = SVAL(params,2);
1729 if (IS_IPC(conn)) {
1730 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
1731 info_level != SMB_SET_CIFS_UNIX_INFO) {
1732 DEBUG(0,("call_trans2setfsinfo: not an allowed "
1733 "info level (0x%x) on IPC$.\n",
1734 (unsigned int)info_level));
1735 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1736 return;
1740 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
1741 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
1742 DEBUG(0,("call_trans2setfsinfo: encryption required "
1743 "and info level 0x%x sent.\n",
1744 (unsigned int)info_level));
1745 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1746 return;
1750 switch(info_level) {
1751 case SMB_SET_CIFS_UNIX_INFO:
1752 if (!lp_smb1_unix_extensions()) {
1753 DEBUG(2,("call_trans2setfsinfo: "
1754 "SMB_SET_CIFS_UNIX_INFO is invalid with "
1755 "unix extensions off\n"));
1756 reply_nterror(req,
1757 NT_STATUS_INVALID_LEVEL);
1758 return;
1761 /* There should be 12 bytes of capabilities set. */
1762 if (total_data < 12) {
1763 reply_nterror(
1764 req,
1765 NT_STATUS_INVALID_PARAMETER);
1766 return;
1768 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
1769 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
1770 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
1771 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
1773 /* Just print these values for now. */
1774 DBG_DEBUG("set unix_info info. "
1775 "major = %"PRIu16", minor = %"PRIu16
1776 "cap_low = 0x%"PRIx32", "
1777 "cap_high = 0x%"PRIx32"\n",
1778 xconn->smb1.unix_info.client_major,
1779 xconn->smb1.unix_info.client_minor,
1780 xconn->smb1.unix_info.client_cap_low,
1781 xconn->smb1.unix_info.client_cap_high);
1784 * Here is where we must switch to posix
1785 * pathname processing...
1787 if (xconn->smb1.unix_info.client_cap_low &
1788 CIFS_UNIX_POSIX_PATHNAMES_CAP)
1790 lp_set_posix_pathnames();
1791 mangle_change_to_posix();
1794 if ((xconn->smb1.unix_info.client_cap_low &
1795 CIFS_UNIX_FCNTL_LOCKS_CAP) &&
1796 !(xconn->smb1.unix_info.client_cap_low &
1797 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP))
1799 /* Client that knows how to do posix locks,
1800 * but not posix open/mkdir operations. Set a
1801 * default type for read/write checks. */
1803 lp_set_posix_default_cifsx_readwrite_locktype(
1804 POSIX_LOCK);
1807 break;
1809 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
1811 NTSTATUS status;
1812 size_t param_len = 0;
1813 size_t data_len = total_data;
1815 if (!lp_smb1_unix_extensions()) {
1816 reply_nterror(
1817 req,
1818 NT_STATUS_INVALID_LEVEL);
1819 return;
1822 if (lp_server_smb_encrypt(SNUM(conn)) ==
1823 SMB_ENCRYPTION_OFF) {
1824 reply_nterror(
1825 req,
1826 NT_STATUS_NOT_SUPPORTED);
1827 return;
1830 if (xconn->smb1.echo_handler.trusted_fde) {
1831 DEBUG( 2,("call_trans2setfsinfo: "
1832 "request transport encryption disabled"
1833 "with 'fork echo handler = yes'\n"));
1834 reply_nterror(
1835 req,
1836 NT_STATUS_NOT_SUPPORTED);
1837 return;
1840 DEBUG( 4,("call_trans2setfsinfo: "
1841 "request transport encryption.\n"));
1843 status = srv_request_encryption_setup(conn,
1844 (unsigned char **)ppdata,
1845 &data_len,
1846 (unsigned char **)pparams,
1847 &param_len);
1849 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
1850 !NT_STATUS_IS_OK(status)) {
1851 reply_nterror(req, status);
1852 return;
1855 send_trans2_replies(conn, req,
1856 NT_STATUS_OK,
1857 *pparams,
1858 param_len,
1859 *ppdata,
1860 data_len,
1861 max_data_bytes);
1863 if (NT_STATUS_IS_OK(status)) {
1864 /* Server-side transport
1865 * encryption is now *on*. */
1866 status = srv_encryption_start(conn);
1867 if (!NT_STATUS_IS_OK(status)) {
1868 char *reason = talloc_asprintf(talloc_tos(),
1869 "Failure in setting "
1870 "up encrypted transport: %s",
1871 nt_errstr(status));
1872 exit_server_cleanly(reason);
1875 return;
1878 case SMB_FS_QUOTA_INFORMATION:
1880 NTSTATUS status;
1881 DATA_BLOB qdata = {
1882 .data = (uint8_t *)pdata,
1883 .length = total_data
1885 files_struct *fsp = NULL;
1886 fsp = file_fsp(req, SVAL(params,0));
1888 status = smb_set_fsquota(conn,
1889 req,
1890 fsp,
1891 &qdata);
1892 if (!NT_STATUS_IS_OK(status)) {
1893 reply_nterror(req, status);
1894 return;
1896 break;
1898 default:
1899 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1900 info_level));
1901 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1902 return;
1903 break;
1907 * sending this reply works fine,
1908 * but I'm not sure it's the same
1909 * like windows do...
1910 * --metze
1912 reply_smb1_outbuf(req, 10, 0);
1915 /****************************************************************************
1916 Reply to a TRANSACT2_QFILEINFO on a PIPE !
1917 ****************************************************************************/
1919 static void call_trans2qpipeinfo(connection_struct *conn,
1920 struct smb_request *req,
1921 files_struct *fsp,
1922 uint16_t info_level,
1923 unsigned int tran_call,
1924 char **pparams, int total_params,
1925 char **ppdata, int total_data,
1926 unsigned int max_data_bytes)
1928 char *params = *pparams;
1929 char *pdata = *ppdata;
1930 unsigned int data_size = 0;
1931 unsigned int param_size = 2;
1933 if (!fsp_is_np(fsp)) {
1934 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1935 return;
1938 *pparams = (char *)SMB_REALLOC(*pparams,2);
1939 if (*pparams == NULL) {
1940 reply_nterror(req, NT_STATUS_NO_MEMORY);
1941 return;
1943 params = *pparams;
1944 SSVAL(params,0,0);
1945 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1946 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1947 return;
1949 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
1950 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
1951 if (*ppdata == NULL ) {
1952 reply_nterror(req, NT_STATUS_NO_MEMORY);
1953 return;
1955 pdata = *ppdata;
1957 switch (info_level) {
1958 case SMB_FILE_STANDARD_INFORMATION:
1959 memset(pdata,0,24);
1960 SOFF_T(pdata,0,4096LL);
1961 SIVAL(pdata,16,1);
1962 SIVAL(pdata,20,1);
1963 data_size = 24;
1964 break;
1966 default:
1967 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1968 return;
1971 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
1972 max_data_bytes);
1974 return;
1977 static void handle_trans2qfilepathinfo_result(
1978 connection_struct *conn,
1979 struct smb_request *req,
1980 uint16_t info_level,
1981 NTSTATUS status,
1982 char *pdata,
1983 int data_return_size,
1984 size_t fixed_portion,
1985 unsigned int max_data_bytes)
1987 char params[2] = { 0, 0, };
1988 int param_size = 2;
1991 * draft-leach-cifs-v1-spec-02.txt
1992 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
1993 * says:
1995 * The requested information is placed in the Data portion of the
1996 * transaction response. For the information levels greater than 0x100,
1997 * the transaction response has 1 parameter word which should be
1998 * ignored by the client.
2000 * However Windows only follows this rule for the IS_NAME_VALID call.
2002 switch (info_level) {
2003 case SMB_INFO_IS_NAME_VALID:
2004 param_size = 0;
2005 break;
2008 if (!NT_STATUS_IS_OK(status)) {
2009 if (open_was_deferred(req->xconn, req->mid)) {
2010 /* We have re-scheduled this call. */
2011 return;
2013 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2014 bool ok = defer_smb1_sharing_violation(req);
2015 if (ok) {
2016 return;
2019 reply_nterror(req, status);
2020 return;
2023 if (fixed_portion > max_data_bytes) {
2024 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
2025 return;
2028 send_trans2_replies(
2029 conn,
2030 req,
2031 NT_STATUS_OK,
2032 params,
2033 param_size,
2034 pdata,
2035 data_return_size,
2036 max_data_bytes);
2039 /****************************************************************************
2040 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2041 file name or file id).
2042 ****************************************************************************/
2044 static void call_trans2qfilepathinfo(connection_struct *conn,
2045 struct smb_request *req,
2046 unsigned int tran_call,
2047 uint16_t info_level,
2048 struct smb_filename *smb_fname,
2049 struct files_struct *fsp,
2050 bool delete_pending,
2051 struct timespec write_time_ts,
2052 char **pparams, int total_params,
2053 char **ppdata, int total_data,
2054 unsigned int max_data_bytes)
2056 char *params = *pparams;
2057 char *pdata = *ppdata;
2058 unsigned int data_size = 0;
2059 struct ea_list *ea_list = NULL;
2060 size_t fixed_portion;
2061 NTSTATUS status = NT_STATUS_OK;
2063 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
2064 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
2065 fsp_fnum_dbg(fsp),
2066 info_level,tran_call,total_data));
2068 /* Pull out any data sent here before we realloc. */
2069 switch (info_level) {
2070 case SMB_INFO_QUERY_EAS_FROM_LIST:
2072 /* Pull any EA list from the data portion. */
2073 uint32_t ea_size;
2075 if (total_data < 4) {
2076 reply_nterror(
2077 req, NT_STATUS_INVALID_PARAMETER);
2078 return;
2080 ea_size = IVAL(pdata,0);
2082 if (total_data > 0 && ea_size != total_data) {
2083 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2084 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2085 reply_nterror(
2086 req, NT_STATUS_INVALID_PARAMETER);
2087 return;
2090 if (!lp_ea_support(SNUM(conn))) {
2091 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2092 return;
2095 /* Pull out the list of names. */
2096 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
2097 if (!ea_list) {
2098 reply_nterror(
2099 req, NT_STATUS_INVALID_PARAMETER);
2100 return;
2102 break;
2105 default:
2106 break;
2109 *pparams = (char *)SMB_REALLOC(*pparams,2);
2110 if (*pparams == NULL) {
2111 reply_nterror(req, NT_STATUS_NO_MEMORY);
2112 return;
2114 params = *pparams;
2115 SSVAL(params,0,0);
2117 if ((info_level & SMB2_INFO_SPECIAL) == SMB2_INFO_SPECIAL) {
2119 * We use levels that start with 0xFF00
2120 * internally to represent SMB2 specific levels
2122 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2123 return;
2126 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
2127 fsp, smb_fname,
2128 delete_pending, write_time_ts,
2129 ea_list,
2130 req->flags2, max_data_bytes,
2131 &fixed_portion,
2132 ppdata, &data_size);
2134 handle_trans2qfilepathinfo_result(
2135 conn,
2136 req,
2137 info_level,
2138 status,
2139 *ppdata,
2140 data_size,
2141 fixed_portion,
2142 max_data_bytes);
2145 static NTSTATUS smb_q_unix_basic(
2146 struct connection_struct *conn,
2147 struct smb_request *req,
2148 struct smb_filename *smb_fname,
2149 struct files_struct *fsp,
2150 char **ppdata,
2151 int *ptotal_data)
2153 const int total_data = 100;
2155 *ppdata = SMB_REALLOC(*ppdata, total_data);
2156 if (*ppdata == NULL) {
2157 return NT_STATUS_NO_MEMORY;
2159 store_file_unix_basic(conn, *ppdata, fsp, &smb_fname->st);
2161 *ptotal_data = total_data;
2163 return NT_STATUS_OK;
2166 static NTSTATUS smb_q_unix_info2(
2167 struct connection_struct *conn,
2168 struct smb_request *req,
2169 struct smb_filename *smb_fname,
2170 struct files_struct *fsp,
2171 char **ppdata,
2172 int *ptotal_data)
2174 const int total_data = 116;
2176 *ppdata = SMB_REALLOC(*ppdata, total_data);
2177 if (*ppdata == NULL) {
2178 return NT_STATUS_NO_MEMORY;
2180 store_file_unix_basic_info2(conn, *ppdata, fsp, &smb_fname->st);
2182 *ptotal_data = total_data;
2184 return NT_STATUS_OK;
2187 #if defined(HAVE_POSIX_ACLS)
2188 /****************************************************************************
2189 Utility function to open a fsp for a POSIX handle operation.
2190 ****************************************************************************/
2192 static NTSTATUS get_posix_fsp(connection_struct *conn,
2193 struct smb_request *req,
2194 struct smb_filename *smb_fname,
2195 uint32_t access_mask,
2196 files_struct **ret_fsp)
2198 NTSTATUS status;
2199 uint32_t create_disposition = FILE_OPEN;
2200 uint32_t share_access = FILE_SHARE_READ|
2201 FILE_SHARE_WRITE|
2202 FILE_SHARE_DELETE;
2203 struct smb2_create_blobs *posx = NULL;
2206 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
2207 * but set reasonable defaults.
2209 uint32_t file_attributes = 0664;
2210 uint32_t oplock = NO_OPLOCK;
2211 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
2213 /* File or directory must exist. */
2214 if (!VALID_STAT(smb_fname->st)) {
2215 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2217 /* Cannot be a symlink. */
2218 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
2219 return NT_STATUS_ACCESS_DENIED;
2221 /* Set options correctly for directory open. */
2222 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
2224 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
2225 * directories, but set reasonable defaults.
2227 file_attributes = 0775;
2228 create_options = FILE_DIRECTORY_FILE;
2231 status = make_smb2_posix_create_ctx(
2232 talloc_tos(), &posx, file_attributes);
2233 if (!NT_STATUS_IS_OK(status)) {
2234 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
2235 nt_errstr(status));
2236 goto done;
2239 status = SMB_VFS_CREATE_FILE(
2240 conn, /* conn */
2241 req, /* req */
2242 NULL, /* dirfsp */
2243 smb_fname, /* fname */
2244 access_mask, /* access_mask */
2245 share_access, /* share_access */
2246 create_disposition,/* create_disposition*/
2247 create_options, /* create_options */
2248 file_attributes,/* file_attributes */
2249 oplock, /* oplock_request */
2250 NULL, /* lease */
2251 0, /* allocation_size */
2252 0, /* private_flags */
2253 NULL, /* sd */
2254 NULL, /* ea_list */
2255 ret_fsp, /* result */
2256 NULL, /* pinfo */
2257 posx, /* in_context */
2258 NULL); /* out_context */
2260 done:
2261 TALLOC_FREE(posx);
2262 return status;
2265 /****************************************************************************
2266 Utility function to count the number of entries in a POSIX acl.
2267 ****************************************************************************/
2269 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2271 unsigned int ace_count = 0;
2272 int entry_id = SMB_ACL_FIRST_ENTRY;
2273 SMB_ACL_ENTRY_T entry;
2275 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2276 entry_id = SMB_ACL_NEXT_ENTRY;
2277 ace_count++;
2279 return ace_count;
2282 /****************************************************************************
2283 Utility function to marshall a POSIX acl into wire format.
2284 ****************************************************************************/
2286 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2288 int entry_id = SMB_ACL_FIRST_ENTRY;
2289 SMB_ACL_ENTRY_T entry;
2291 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2292 SMB_ACL_TAG_T tagtype;
2293 SMB_ACL_PERMSET_T permset;
2294 unsigned char perms = 0;
2295 unsigned int own_grp;
2297 entry_id = SMB_ACL_NEXT_ENTRY;
2299 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
2300 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2301 return False;
2304 if (sys_acl_get_permset(entry, &permset) == -1) {
2305 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2306 return False;
2309 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2310 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2311 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2313 SCVAL(pdata,1,perms);
2315 switch (tagtype) {
2316 case SMB_ACL_USER_OBJ:
2317 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2318 own_grp = (unsigned int)pst->st_ex_uid;
2319 SIVAL(pdata,2,own_grp);
2320 SIVAL(pdata,6,0);
2321 break;
2322 case SMB_ACL_USER:
2324 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
2325 if (!puid) {
2326 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2327 return False;
2329 own_grp = (unsigned int)*puid;
2330 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2331 SIVAL(pdata,2,own_grp);
2332 SIVAL(pdata,6,0);
2333 break;
2335 case SMB_ACL_GROUP_OBJ:
2336 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2337 own_grp = (unsigned int)pst->st_ex_gid;
2338 SIVAL(pdata,2,own_grp);
2339 SIVAL(pdata,6,0);
2340 break;
2341 case SMB_ACL_GROUP:
2343 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
2344 if (!pgid) {
2345 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2346 return False;
2348 own_grp = (unsigned int)*pgid;
2349 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2350 SIVAL(pdata,2,own_grp);
2351 SIVAL(pdata,6,0);
2352 break;
2354 case SMB_ACL_MASK:
2355 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2356 SIVAL(pdata,2,0xFFFFFFFF);
2357 SIVAL(pdata,6,0xFFFFFFFF);
2358 break;
2359 case SMB_ACL_OTHER:
2360 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2361 SIVAL(pdata,2,0xFFFFFFFF);
2362 SIVAL(pdata,6,0xFFFFFFFF);
2363 break;
2364 default:
2365 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2366 return False;
2368 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2371 return True;
2373 #endif
2375 static NTSTATUS smb_q_posix_acl(
2376 struct connection_struct *conn,
2377 struct smb_request *req,
2378 struct smb_filename *smb_fname,
2379 struct files_struct *fsp,
2380 char **ppdata,
2381 int *ptotal_data)
2383 #if !defined(HAVE_POSIX_ACLS)
2384 return NT_STATUS_INVALID_LEVEL;
2385 #else
2386 char *pdata = NULL;
2387 SMB_ACL_T file_acl = NULL;
2388 SMB_ACL_T def_acl = NULL;
2389 uint16_t num_file_acls = 0;
2390 uint16_t num_def_acls = 0;
2391 unsigned int size_needed = 0;
2392 NTSTATUS status;
2393 bool ok;
2394 bool close_fsp = false;
2397 * Ensure we always operate on a file descriptor, not just
2398 * the filename.
2400 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
2401 uint32_t access_mask = SEC_STD_READ_CONTROL|
2402 FILE_READ_ATTRIBUTES|
2403 FILE_WRITE_ATTRIBUTES;
2405 status = get_posix_fsp(conn,
2406 req,
2407 smb_fname,
2408 access_mask,
2409 &fsp);
2411 if (!NT_STATUS_IS_OK(status)) {
2412 goto out;
2414 close_fsp = true;
2417 SMB_ASSERT(fsp != NULL);
2419 status = refuse_symlink_fsp(fsp);
2420 if (!NT_STATUS_IS_OK(status)) {
2421 goto out;
2424 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, SMB_ACL_TYPE_ACCESS,
2425 talloc_tos());
2427 if (file_acl == NULL && no_acl_syscall_error(errno)) {
2428 DBG_INFO("ACLs not implemented on "
2429 "filesystem containing %s\n",
2430 fsp_str_dbg(fsp));
2431 status = NT_STATUS_NOT_IMPLEMENTED;
2432 goto out;
2435 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2437 * We can only have default POSIX ACLs on
2438 * directories.
2440 if (!fsp->fsp_flags.is_directory) {
2441 DBG_INFO("Non-directory open %s\n",
2442 fsp_str_dbg(fsp));
2443 status = NT_STATUS_INVALID_HANDLE;
2444 goto out;
2446 def_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
2447 SMB_ACL_TYPE_DEFAULT,
2448 talloc_tos());
2449 def_acl = free_empty_sys_acl(conn, def_acl);
2452 num_file_acls = count_acl_entries(conn, file_acl);
2453 num_def_acls = count_acl_entries(conn, def_acl);
2455 /* Wrap checks. */
2456 if (num_file_acls + num_def_acls < num_file_acls) {
2457 status = NT_STATUS_INVALID_PARAMETER;
2458 goto out;
2461 size_needed = num_file_acls + num_def_acls;
2464 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
2465 * than UINT_MAX, so check by division.
2467 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
2468 status = NT_STATUS_INVALID_PARAMETER;
2469 goto out;
2472 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
2473 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
2474 status = NT_STATUS_INVALID_PARAMETER;
2475 goto out;
2477 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
2479 *ppdata = SMB_REALLOC(*ppdata, size_needed);
2480 if (*ppdata == NULL) {
2481 status = NT_STATUS_NO_MEMORY;
2482 goto out;
2484 pdata = *ppdata;
2486 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
2487 SSVAL(pdata,2,num_file_acls);
2488 SSVAL(pdata,4,num_def_acls);
2489 pdata += SMB_POSIX_ACL_HEADER_SIZE;
2491 ok = marshall_posix_acl(conn,
2492 pdata,
2493 &fsp->fsp_name->st,
2494 file_acl);
2495 if (!ok) {
2496 status = NT_STATUS_INTERNAL_ERROR;
2497 goto out;
2499 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
2501 ok = marshall_posix_acl(conn,
2502 pdata,
2503 &fsp->fsp_name->st,
2504 def_acl);
2505 if (!ok) {
2506 status = NT_STATUS_INTERNAL_ERROR;
2507 goto out;
2510 *ptotal_data = size_needed;
2511 status = NT_STATUS_OK;
2513 out:
2515 if (close_fsp) {
2517 * Ensure the stat struct in smb_fname is up to
2518 * date. Structure copy.
2520 smb_fname->st = fsp->fsp_name->st;
2521 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
2524 TALLOC_FREE(file_acl);
2525 TALLOC_FREE(def_acl);
2526 return status;
2527 #endif
2530 static NTSTATUS smb_q_posix_symlink(
2531 struct connection_struct *conn,
2532 struct smb_request *req,
2533 struct smb_filename *smb_fname,
2534 char **ppdata,
2535 int *ptotal_data)
2537 char buffer[PATH_MAX+1];
2538 size_t needed, len;
2539 int link_len;
2540 char *pdata = NULL;
2541 struct smb_filename *parent_fname = NULL;
2542 struct smb_filename *base_name = NULL;
2543 NTSTATUS status;
2545 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
2546 smb_fname_str_dbg(smb_fname));
2548 if (!S_ISLNK(smb_fname->st.st_ex_mode)) {
2549 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
2552 status = parent_pathref(
2553 talloc_tos(),
2554 conn->cwd_fsp,
2555 smb_fname,
2556 &parent_fname,
2557 &base_name);
2559 if (!NT_STATUS_IS_OK(status)) {
2560 DBG_DEBUG("parent_pathref failed: %s\n", nt_errstr(status));
2561 return status;
2564 link_len = SMB_VFS_READLINKAT(
2565 conn,
2566 parent_fname->fsp,
2567 base_name,
2568 buffer,
2569 sizeof(buffer)-1);
2570 TALLOC_FREE(parent_fname);
2572 if (link_len == -1) {
2573 status = map_nt_error_from_unix(errno);
2574 DBG_DEBUG("READLINKAT failed: %s\n", nt_errstr(status));
2575 return status;
2577 if (link_len >= sizeof(buffer)) {
2578 return NT_STATUS_INTERNAL_ERROR;
2580 buffer[link_len] = 0;
2582 needed = (link_len+1)*2;
2584 *ppdata = SMB_REALLOC(*ppdata, needed);
2585 if (*ppdata == NULL) {
2586 return NT_STATUS_NO_MEMORY;
2588 pdata = *ppdata;
2590 status = srvstr_push(
2591 pdata,
2592 req->flags2,
2593 pdata,
2594 buffer,
2595 needed,
2596 STR_TERMINATE,
2597 &len);
2598 if (!NT_STATUS_IS_OK(status)) {
2599 return status;
2601 *ptotal_data = len;
2603 return NT_STATUS_OK;
2606 static void call_trans2qpathinfo(
2607 connection_struct *conn,
2608 struct smb_request *req,
2609 char **pparams,
2610 int total_params,
2611 char **ppdata,
2612 int total_data,
2613 unsigned int max_data_bytes)
2615 char *params = *pparams;
2616 uint16_t info_level;
2617 struct smb_filename *smb_fname = NULL;
2618 bool delete_pending = False;
2619 struct timespec write_time_ts = { .tv_sec = 0, };
2620 struct files_struct *dirfsp = NULL;
2621 files_struct *fsp = NULL;
2622 struct file_id fileid;
2623 uint32_t name_hash;
2624 char *fname = NULL;
2625 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2626 NTTIME twrp = 0;
2627 bool info_level_handled;
2628 NTSTATUS status = NT_STATUS_OK;
2629 int ret;
2631 if (!params) {
2632 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2633 return;
2637 /* qpathinfo */
2638 if (total_params < 7) {
2639 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2640 return;
2643 info_level = SVAL(params,0);
2645 DBG_NOTICE("TRANSACT2_QPATHINFO: level = %d\n", info_level);
2647 if (INFO_LEVEL_IS_UNIX(info_level)) {
2648 if (!lp_smb1_unix_extensions()) {
2649 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2650 return;
2652 if (!req->posix_pathnames) {
2653 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2654 return;
2658 if (req->posix_pathnames) {
2659 srvstr_get_path_posix(req,
2660 params,
2661 req->flags2,
2662 &fname,
2663 &params[6],
2664 total_params - 6,
2665 STR_TERMINATE,
2666 &status);
2667 } else {
2668 srvstr_get_path(req,
2669 params,
2670 req->flags2,
2671 &fname,
2672 &params[6],
2673 total_params - 6,
2674 STR_TERMINATE,
2675 &status);
2677 if (!NT_STATUS_IS_OK(status)) {
2678 reply_nterror(req, status);
2679 return;
2682 if (ucf_flags & UCF_GMT_PATHNAME) {
2683 extract_snapshot_token(fname, &twrp);
2685 status = smb1_strip_dfs_path(req, &ucf_flags, &fname);
2686 if (!NT_STATUS_IS_OK(status)) {
2687 reply_nterror(req, status);
2688 return;
2690 status = filename_convert_dirfsp(req,
2691 conn,
2692 fname,
2693 ucf_flags,
2694 twrp,
2695 &dirfsp,
2696 &smb_fname);
2697 if (!NT_STATUS_IS_OK(status)) {
2698 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2699 reply_botherror(req,
2700 NT_STATUS_PATH_NOT_COVERED,
2701 ERRSRV, ERRbadpath);
2702 return;
2704 reply_nterror(req, status);
2705 return;
2709 * qpathinfo must operate on an existing file, so we
2710 * can exit early if filename_convert_dirfsp() returned the
2711 * "new file" NT_STATUS_OK, !VALID_STAT case.
2714 if (!VALID_STAT(smb_fname->st)) {
2715 reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2716 return;
2720 * smb_fname->fsp may be NULL if smb_fname points at a symlink
2721 * and we're in POSIX context, so be careful when using fsp
2722 * below, it can still be NULL.
2724 fsp = smb_fname->fsp;
2726 /* If this is a stream, check if there is a delete_pending. */
2727 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
2728 && is_ntfs_stream_smb_fname(smb_fname)) {
2729 struct smb_filename *smb_fname_base;
2731 /* Create an smb_filename with stream_name == NULL. */
2732 smb_fname_base = synthetic_smb_fname(
2733 talloc_tos(),
2734 smb_fname->base_name,
2735 NULL,
2736 NULL,
2737 smb_fname->twrp,
2738 smb_fname->flags);
2739 if (smb_fname_base == NULL) {
2740 reply_nterror(req, NT_STATUS_NO_MEMORY);
2741 return;
2744 ret = vfs_stat(conn, smb_fname_base);
2745 if (ret != 0) {
2746 DBG_NOTICE("vfs_stat of %s failed "
2747 "(%s)\n",
2748 smb_fname_str_dbg(smb_fname_base),
2749 strerror(errno));
2750 TALLOC_FREE(smb_fname_base);
2751 reply_nterror(req,
2752 map_nt_error_from_unix(errno));
2753 return;
2756 status = file_name_hash(conn,
2757 smb_fname_str_dbg(smb_fname_base),
2758 &name_hash);
2759 if (!NT_STATUS_IS_OK(status)) {
2760 TALLOC_FREE(smb_fname_base);
2761 reply_nterror(req, status);
2762 return;
2765 fileid = vfs_file_id_from_sbuf(conn,
2766 &smb_fname_base->st);
2767 TALLOC_FREE(smb_fname_base);
2768 get_file_infos(fileid, name_hash, &delete_pending, NULL);
2769 if (delete_pending) {
2770 reply_nterror(req, NT_STATUS_DELETE_PENDING);
2771 return;
2775 status = file_name_hash(conn,
2776 smb_fname_str_dbg(smb_fname),
2777 &name_hash);
2778 if (!NT_STATUS_IS_OK(status)) {
2779 reply_nterror(req, status);
2780 return;
2783 if (fsp_getinfo_ask_sharemode(fsp)) {
2784 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2785 get_file_infos(fileid, name_hash, &delete_pending,
2786 &write_time_ts);
2789 if (delete_pending) {
2790 reply_nterror(req, NT_STATUS_DELETE_PENDING);
2791 return;
2794 info_level_handled = true; /* Untouched in switch cases below */
2796 switch (info_level) {
2798 default:
2799 info_level_handled = false;
2800 break;
2802 case SMB_QUERY_FILE_UNIX_BASIC:
2803 status = smb_q_unix_basic(
2804 conn,
2805 req,
2806 smb_fname,
2807 smb_fname->fsp,
2808 ppdata,
2809 &total_data);
2810 break;
2812 case SMB_QUERY_FILE_UNIX_INFO2:
2813 status = smb_q_unix_info2(
2814 conn,
2815 req,
2816 smb_fname,
2817 smb_fname->fsp,
2818 ppdata,
2819 &total_data);
2820 break;
2822 case SMB_QUERY_POSIX_ACL:
2823 status = smb_q_posix_acl(
2824 conn,
2825 req,
2826 smb_fname,
2827 smb_fname->fsp,
2828 ppdata,
2829 &total_data);
2830 break;
2832 case SMB_QUERY_FILE_UNIX_LINK:
2833 status = smb_q_posix_symlink(
2834 conn,
2835 req,
2836 smb_fname,
2837 ppdata,
2838 &total_data);
2839 break;
2842 if (info_level_handled) {
2843 handle_trans2qfilepathinfo_result(
2844 conn,
2845 req,
2846 info_level,
2847 status,
2848 *ppdata,
2849 total_data,
2850 total_data,
2851 max_data_bytes);
2852 return;
2855 call_trans2qfilepathinfo(
2856 conn,
2857 req,
2858 TRANSACT2_QPATHINFO,
2859 info_level,
2860 smb_fname,
2861 fsp,
2862 false,
2863 write_time_ts,
2864 pparams,
2865 total_params,
2866 ppdata,
2867 total_data,
2868 max_data_bytes);
2871 static NTSTATUS smb_q_posix_lock(
2872 struct connection_struct *conn,
2873 struct smb_request *req,
2874 struct files_struct *fsp,
2875 char **ppdata,
2876 int *ptotal_data)
2878 char *pdata = *ppdata;
2879 int total_data = *ptotal_data;
2880 uint64_t count;
2881 uint64_t offset;
2882 uint64_t smblctx;
2883 enum brl_type lock_type;
2884 NTSTATUS status;
2886 if (fsp->fsp_flags.is_pathref || (fsp_get_io_fd(fsp) == -1)) {
2887 return NT_STATUS_INVALID_HANDLE;
2890 if (total_data != POSIX_LOCK_DATA_SIZE) {
2891 return NT_STATUS_INVALID_PARAMETER;
2894 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
2895 case POSIX_LOCK_TYPE_READ:
2896 lock_type = READ_LOCK;
2897 break;
2898 case POSIX_LOCK_TYPE_WRITE:
2899 lock_type = WRITE_LOCK;
2900 break;
2901 case POSIX_LOCK_TYPE_UNLOCK:
2902 default:
2903 /* There's no point in asking for an unlock... */
2904 return NT_STATUS_INVALID_PARAMETER;
2907 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
2908 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
2909 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
2911 status = query_lock(
2912 fsp,
2913 &smblctx,
2914 &count,
2915 &offset,
2916 &lock_type,
2917 POSIX_LOCK);
2919 if (NT_STATUS_IS_OK(status)) {
2921 * For success we just return a copy of what we sent
2922 * with the lock type set to POSIX_LOCK_TYPE_UNLOCK.
2924 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
2925 return NT_STATUS_OK;
2928 if (!ERROR_WAS_LOCK_DENIED(status)) {
2929 DBG_DEBUG("query_lock() failed: %s\n", nt_errstr(status));
2930 return status;
2934 * Here we need to report who has it locked.
2937 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
2938 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
2939 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
2940 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
2941 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
2943 return NT_STATUS_OK;
2946 static void call_trans2qfileinfo(
2947 connection_struct *conn,
2948 struct smb_request *req,
2949 char **pparams,
2950 int total_params,
2951 char **ppdata,
2952 int total_data,
2953 unsigned int max_data_bytes)
2955 char *params = *pparams;
2956 uint16_t info_level;
2957 struct smb_filename *smb_fname = NULL;
2958 bool delete_pending = False;
2959 struct timespec write_time_ts = { .tv_sec = 0, };
2960 files_struct *fsp = NULL;
2961 struct file_id fileid;
2962 bool info_level_handled;
2963 NTSTATUS status = NT_STATUS_OK;
2964 int ret;
2966 if (params == NULL) {
2967 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2968 return;
2971 if (total_params < 4) {
2972 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2973 return;
2976 fsp = file_fsp(req, SVAL(params,0));
2977 info_level = SVAL(params,2);
2979 if (IS_IPC(conn)) {
2980 call_trans2qpipeinfo(
2981 conn,
2982 req,
2983 fsp,
2984 info_level,
2985 TRANSACT2_QFILEINFO,
2986 pparams,
2987 total_params,
2988 ppdata,
2989 total_data,
2990 max_data_bytes);
2991 return;
2994 DBG_NOTICE("TRANSACT2_QFILEINFO: level = %d\n", info_level);
2996 if (INFO_LEVEL_IS_UNIX(info_level)) {
2997 if (!lp_smb1_unix_extensions()) {
2998 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2999 return;
3001 if (!req->posix_pathnames) {
3002 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3003 return;
3007 /* Initial check for valid fsp ptr. */
3008 if (!check_fsp_open(conn, req, fsp)) {
3009 return;
3012 smb_fname = fsp->fsp_name;
3014 if(fsp->fake_file_handle) {
3016 * This is actually for the QUOTA_FAKE_FILE --metze
3019 /* We know this name is ok, it's already passed the checks. */
3021 } else if(fsp_get_pathref_fd(fsp) == -1) {
3023 * This is actually a QFILEINFO on a directory
3024 * handle (returned from an NT SMB). NT5.0 seems
3025 * to do this call. JRA.
3027 ret = vfs_stat(conn, smb_fname);
3028 if (ret != 0) {
3029 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
3030 smb_fname_str_dbg(smb_fname),
3031 strerror(errno));
3032 reply_nterror(req,
3033 map_nt_error_from_unix(errno));
3034 return;
3037 if (fsp_getinfo_ask_sharemode(fsp)) {
3038 fileid = vfs_file_id_from_sbuf(
3039 conn, &smb_fname->st);
3040 get_file_infos(fileid, fsp->name_hash,
3041 &delete_pending,
3042 &write_time_ts);
3044 } else {
3046 * Original code - this is an open file.
3048 status = vfs_stat_fsp(fsp);
3049 if (!NT_STATUS_IS_OK(status)) {
3050 DEBUG(3, ("fstat of %s failed (%s)\n",
3051 fsp_fnum_dbg(fsp), nt_errstr(status)));
3052 reply_nterror(req, status);
3053 return;
3055 if (fsp_getinfo_ask_sharemode(fsp)) {
3056 fileid = vfs_file_id_from_sbuf(
3057 conn, &smb_fname->st);
3058 get_file_infos(fileid, fsp->name_hash,
3059 &delete_pending,
3060 &write_time_ts);
3064 info_level_handled = true; /* Untouched in switch cases below */
3066 switch (info_level) {
3068 default:
3069 info_level_handled = false;
3070 break;
3072 case SMB_QUERY_POSIX_LOCK:
3073 status = smb_q_posix_lock(conn, req, fsp, ppdata, &total_data);
3074 break;
3076 case SMB_QUERY_FILE_UNIX_BASIC:
3077 status = smb_q_unix_basic(
3078 conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3079 break;
3081 case SMB_QUERY_FILE_UNIX_INFO2:
3082 status = smb_q_unix_info2(
3083 conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3084 break;
3086 case SMB_QUERY_POSIX_ACL:
3087 status = smb_q_posix_acl(
3088 conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3089 break;
3092 if (info_level_handled) {
3093 handle_trans2qfilepathinfo_result(
3094 conn,
3095 req,
3096 info_level,
3097 status,
3098 *ppdata,
3099 total_data,
3100 total_data,
3101 max_data_bytes);
3102 return;
3105 call_trans2qfilepathinfo(
3106 conn,
3107 req,
3108 TRANSACT2_QFILEINFO,
3109 info_level,
3110 smb_fname,
3111 fsp,
3112 delete_pending,
3113 write_time_ts,
3114 pparams,
3115 total_params,
3116 ppdata,
3117 total_data,
3118 max_data_bytes);
3121 static void handle_trans2setfilepathinfo_result(
3122 connection_struct *conn,
3123 struct smb_request *req,
3124 uint16_t info_level,
3125 NTSTATUS status,
3126 char *pdata,
3127 int data_return_size,
3128 unsigned int max_data_bytes)
3130 char params[2] = { 0, 0, };
3132 if (NT_STATUS_IS_OK(status)) {
3133 send_trans2_replies(
3134 conn,
3135 req,
3136 NT_STATUS_OK,
3137 params,
3139 pdata,
3140 data_return_size,
3141 max_data_bytes);
3142 return;
3145 if (open_was_deferred(req->xconn, req->mid)) {
3146 /* We have re-scheduled this call. */
3147 return;
3150 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3151 bool ok = defer_smb1_sharing_violation(req);
3152 if (ok) {
3153 return;
3157 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
3158 /* We have re-scheduled this call. */
3159 return;
3162 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3163 reply_botherror(
3164 req,
3165 NT_STATUS_PATH_NOT_COVERED,
3166 ERRSRV,
3167 ERRbadpath);
3168 return;
3171 if (info_level == SMB_POSIX_PATH_OPEN) {
3172 reply_openerror(req, status);
3173 return;
3176 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
3178 * Invalid EA name needs to return 2 param bytes,
3179 * not a zero-length error packet.
3182 send_trans2_replies(
3183 conn,
3184 req,
3185 status,
3186 params,
3188 NULL,
3190 max_data_bytes);
3191 return;
3194 reply_nterror(req, status);
3197 /****************************************************************************
3198 Create a directory with POSIX semantics.
3199 ****************************************************************************/
3201 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
3202 struct smb_request *req,
3203 char **ppdata,
3204 int total_data,
3205 struct smb_filename *smb_fname,
3206 int *pdata_return_size)
3208 NTSTATUS status = NT_STATUS_OK;
3209 uint32_t raw_unixmode = 0;
3210 mode_t unixmode = (mode_t)0;
3211 files_struct *fsp = NULL;
3212 uint16_t info_level_return = 0;
3213 int info;
3214 char *pdata = *ppdata;
3215 struct smb2_create_blobs *posx = NULL;
3217 if (total_data < 18) {
3218 return NT_STATUS_INVALID_PARAMETER;
3221 raw_unixmode = IVAL(pdata,8);
3222 /* Next 4 bytes are not yet defined. */
3224 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
3225 PERM_NEW_DIR, &unixmode);
3226 if (!NT_STATUS_IS_OK(status)) {
3227 return status;
3230 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
3231 if (!NT_STATUS_IS_OK(status)) {
3232 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3233 nt_errstr(status));
3234 return status;
3237 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
3238 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
3240 status = SMB_VFS_CREATE_FILE(
3241 conn, /* conn */
3242 req, /* req */
3243 NULL, /* dirfsp */
3244 smb_fname, /* fname */
3245 FILE_READ_ATTRIBUTES, /* access_mask */
3246 FILE_SHARE_NONE, /* share_access */
3247 FILE_CREATE, /* create_disposition*/
3248 FILE_DIRECTORY_FILE, /* create_options */
3249 0, /* file_attributes */
3250 0, /* oplock_request */
3251 NULL, /* lease */
3252 0, /* allocation_size */
3253 0, /* private_flags */
3254 NULL, /* sd */
3255 NULL, /* ea_list */
3256 &fsp, /* result */
3257 &info, /* pinfo */
3258 posx, /* in_context_blobs */
3259 NULL); /* out_context_blobs */
3261 TALLOC_FREE(posx);
3263 if (NT_STATUS_IS_OK(status)) {
3264 close_file_free(req, &fsp, NORMAL_CLOSE);
3267 info_level_return = SVAL(pdata,16);
3269 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
3270 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
3271 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
3272 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
3273 } else {
3274 *pdata_return_size = 12;
3277 /* Realloc the data size */
3278 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
3279 if (*ppdata == NULL) {
3280 *pdata_return_size = 0;
3281 return NT_STATUS_NO_MEMORY;
3283 pdata = *ppdata;
3285 SSVAL(pdata,0,NO_OPLOCK_RETURN);
3286 SSVAL(pdata,2,0); /* No fnum. */
3287 SIVAL(pdata,4,info); /* Was directory created. */
3289 switch (info_level_return) {
3290 case SMB_QUERY_FILE_UNIX_BASIC:
3291 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
3292 SSVAL(pdata,10,0); /* Padding. */
3293 store_file_unix_basic(conn, pdata + 12, fsp,
3294 &smb_fname->st);
3295 break;
3296 case SMB_QUERY_FILE_UNIX_INFO2:
3297 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
3298 SSVAL(pdata,10,0); /* Padding. */
3299 store_file_unix_basic_info2(conn, pdata + 12, fsp,
3300 &smb_fname->st);
3301 break;
3302 default:
3303 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
3304 SSVAL(pdata,10,0); /* Padding. */
3305 break;
3308 return status;
3311 /****************************************************************************
3312 Open/Create a file with POSIX semantics.
3313 ****************************************************************************/
3315 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
3316 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
3318 static NTSTATUS smb_posix_open(connection_struct *conn,
3319 struct smb_request *req,
3320 char **ppdata,
3321 int total_data,
3322 struct smb_filename *smb_fname,
3323 int *pdata_return_size)
3325 bool extended_oplock_granted = False;
3326 char *pdata = *ppdata;
3327 uint32_t flags = 0;
3328 uint32_t wire_open_mode = 0;
3329 uint32_t raw_unixmode = 0;
3330 uint32_t attributes = 0;
3331 uint32_t create_disp = 0;
3332 uint32_t access_mask = 0;
3333 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
3334 NTSTATUS status = NT_STATUS_OK;
3335 mode_t unixmode = (mode_t)0;
3336 files_struct *fsp = NULL;
3337 int oplock_request = 0;
3338 int info = 0;
3339 uint16_t info_level_return = 0;
3340 struct smb2_create_blobs *posx = NULL;
3342 if (total_data < 18) {
3343 return NT_STATUS_INVALID_PARAMETER;
3346 flags = IVAL(pdata,0);
3347 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
3348 if (oplock_request) {
3349 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
3352 wire_open_mode = IVAL(pdata,4);
3354 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
3355 return smb_posix_mkdir(conn, req,
3356 ppdata,
3357 total_data,
3358 smb_fname,
3359 pdata_return_size);
3362 switch (wire_open_mode & SMB_ACCMODE) {
3363 case SMB_O_RDONLY:
3364 access_mask = SMB_O_RDONLY_MAPPING;
3365 break;
3366 case SMB_O_WRONLY:
3367 access_mask = SMB_O_WRONLY_MAPPING;
3368 break;
3369 case SMB_O_RDWR:
3370 access_mask = (SMB_O_RDONLY_MAPPING|
3371 SMB_O_WRONLY_MAPPING);
3372 break;
3373 default:
3374 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
3375 (unsigned int)wire_open_mode ));
3376 return NT_STATUS_INVALID_PARAMETER;
3379 wire_open_mode &= ~SMB_ACCMODE;
3381 /* First take care of O_CREAT|O_EXCL interactions. */
3382 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
3383 case (SMB_O_CREAT | SMB_O_EXCL):
3384 /* File exists fail. File not exist create. */
3385 create_disp = FILE_CREATE;
3386 break;
3387 case SMB_O_CREAT:
3388 /* File exists open. File not exist create. */
3389 create_disp = FILE_OPEN_IF;
3390 break;
3391 case SMB_O_EXCL:
3392 /* O_EXCL on its own without O_CREAT is undefined.
3393 We deliberately ignore it as some versions of
3394 Linux CIFSFS can send a bare O_EXCL on the
3395 wire which other filesystems in the kernel
3396 ignore. See bug 9519 for details. */
3398 /* Fallthrough. */
3400 case 0:
3401 /* File exists open. File not exist fail. */
3402 create_disp = FILE_OPEN;
3403 break;
3404 default:
3405 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
3406 (unsigned int)wire_open_mode ));
3407 return NT_STATUS_INVALID_PARAMETER;
3410 /* Next factor in the effects of O_TRUNC. */
3411 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
3413 if (wire_open_mode & SMB_O_TRUNC) {
3414 switch (create_disp) {
3415 case FILE_CREATE:
3416 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
3417 /* Leave create_disp alone as
3418 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
3420 /* File exists fail. File not exist create. */
3421 break;
3422 case FILE_OPEN_IF:
3423 /* SMB_O_CREAT | SMB_O_TRUNC */
3424 /* File exists overwrite. File not exist create. */
3425 create_disp = FILE_OVERWRITE_IF;
3426 break;
3427 case FILE_OPEN:
3428 /* SMB_O_TRUNC */
3429 /* File exists overwrite. File not exist fail. */
3430 create_disp = FILE_OVERWRITE;
3431 break;
3432 default:
3433 /* Cannot get here. */
3434 smb_panic("smb_posix_open: logic error");
3435 return NT_STATUS_INVALID_PARAMETER;
3439 raw_unixmode = IVAL(pdata,8);
3440 /* Next 4 bytes are not yet defined. */
3442 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
3443 (VALID_STAT(smb_fname->st) ?
3444 PERM_EXISTING_FILE : PERM_NEW_FILE),
3445 &unixmode);
3447 if (!NT_STATUS_IS_OK(status)) {
3448 return status;
3451 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
3452 if (!NT_STATUS_IS_OK(status)) {
3453 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3454 nt_errstr(status));
3455 return status;
3458 if (wire_open_mode & SMB_O_SYNC) {
3459 create_options |= FILE_WRITE_THROUGH;
3461 if (wire_open_mode & SMB_O_APPEND) {
3462 access_mask |= FILE_APPEND_DATA;
3464 if (wire_open_mode & SMB_O_DIRECT) {
3465 attributes |= FILE_FLAG_NO_BUFFERING;
3468 if ((wire_open_mode & SMB_O_DIRECTORY) ||
3469 VALID_STAT_OF_DIR(smb_fname->st)) {
3470 if (access_mask != SMB_O_RDONLY_MAPPING) {
3471 return NT_STATUS_FILE_IS_A_DIRECTORY;
3473 create_options &= ~FILE_NON_DIRECTORY_FILE;
3474 create_options |= FILE_DIRECTORY_FILE;
3477 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
3478 smb_fname_str_dbg(smb_fname),
3479 (unsigned int)wire_open_mode,
3480 (unsigned int)unixmode ));
3482 status = SMB_VFS_CREATE_FILE(
3483 conn, /* conn */
3484 req, /* req */
3485 NULL, /* dirfsp */
3486 smb_fname, /* fname */
3487 access_mask, /* access_mask */
3488 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
3489 FILE_SHARE_DELETE),
3490 create_disp, /* create_disposition*/
3491 create_options, /* create_options */
3492 attributes, /* file_attributes */
3493 oplock_request, /* oplock_request */
3494 NULL, /* lease */
3495 0, /* allocation_size */
3496 0, /* private_flags */
3497 NULL, /* sd */
3498 NULL, /* ea_list */
3499 &fsp, /* result */
3500 &info, /* pinfo */
3501 posx, /* in_context_blobs */
3502 NULL); /* out_context_blobs */
3504 TALLOC_FREE(posx);
3506 if (!NT_STATUS_IS_OK(status)) {
3507 return status;
3510 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3511 extended_oplock_granted = True;
3514 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3515 extended_oplock_granted = True;
3518 info_level_return = SVAL(pdata,16);
3520 /* Allocate the correct return size. */
3522 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
3523 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
3524 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
3525 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
3526 } else {
3527 *pdata_return_size = 12;
3530 /* Realloc the data size */
3531 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
3532 if (*ppdata == NULL) {
3533 close_file_free(req, &fsp, ERROR_CLOSE);
3534 *pdata_return_size = 0;
3535 return NT_STATUS_NO_MEMORY;
3537 pdata = *ppdata;
3539 if (extended_oplock_granted) {
3540 if (flags & REQUEST_BATCH_OPLOCK) {
3541 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
3542 } else {
3543 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
3545 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
3546 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
3547 } else {
3548 SSVAL(pdata,0,NO_OPLOCK_RETURN);
3551 SSVAL(pdata,2,fsp->fnum);
3552 SIVAL(pdata,4,info); /* Was file created etc. */
3554 switch (info_level_return) {
3555 case SMB_QUERY_FILE_UNIX_BASIC:
3556 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
3557 SSVAL(pdata,10,0); /* padding. */
3558 store_file_unix_basic(conn, pdata + 12, fsp,
3559 &smb_fname->st);
3560 break;
3561 case SMB_QUERY_FILE_UNIX_INFO2:
3562 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
3563 SSVAL(pdata,10,0); /* padding. */
3564 store_file_unix_basic_info2(conn, pdata + 12, fsp,
3565 &smb_fname->st);
3566 break;
3567 default:
3568 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
3569 SSVAL(pdata,10,0); /* padding. */
3570 break;
3572 return NT_STATUS_OK;
3575 /****************************************************************************
3576 Delete a file with POSIX semantics.
3577 ****************************************************************************/
3579 struct smb_posix_unlink_state {
3580 struct smb_filename *smb_fname;
3581 struct files_struct *fsp;
3582 NTSTATUS status;
3585 static void smb_posix_unlink_locked(struct share_mode_lock *lck,
3586 void *private_data)
3588 struct smb_posix_unlink_state *state = private_data;
3589 char del = 1;
3590 bool other_nonposix_opens;
3592 other_nonposix_opens = has_other_nonposix_opens(lck, state->fsp);
3593 if (other_nonposix_opens) {
3594 /* Fail with sharing violation. */
3595 state->status = NT_STATUS_SHARING_VIOLATION;
3596 return;
3600 * Set the delete on close.
3602 state->status = smb_set_file_disposition_info(state->fsp->conn,
3603 &del,
3605 state->fsp,
3606 state->smb_fname);
3609 static NTSTATUS smb_posix_unlink(connection_struct *conn,
3610 struct smb_request *req,
3611 const char *pdata,
3612 int total_data,
3613 struct smb_filename *smb_fname)
3615 struct smb_posix_unlink_state state = {};
3616 NTSTATUS status = NT_STATUS_OK;
3617 files_struct *fsp = NULL;
3618 uint16_t flags = 0;
3619 int info = 0;
3620 int create_options = 0;
3621 struct smb2_create_blobs *posx = NULL;
3623 if (!CAN_WRITE(conn)) {
3624 return NT_STATUS_DOS(ERRSRV, ERRaccess);
3627 if (total_data < 2) {
3628 return NT_STATUS_INVALID_PARAMETER;
3631 flags = SVAL(pdata,0);
3633 if (!VALID_STAT(smb_fname->st)) {
3634 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3637 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
3638 !VALID_STAT_OF_DIR(smb_fname->st)) {
3639 return NT_STATUS_NOT_A_DIRECTORY;
3642 DEBUG(10,("smb_posix_unlink: %s %s\n",
3643 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
3644 smb_fname_str_dbg(smb_fname)));
3646 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
3647 create_options |= FILE_DIRECTORY_FILE;
3650 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
3651 if (!NT_STATUS_IS_OK(status)) {
3652 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3653 nt_errstr(status));
3654 return status;
3657 status = SMB_VFS_CREATE_FILE(
3658 conn, /* conn */
3659 req, /* req */
3660 NULL, /* dirfsp */
3661 smb_fname, /* fname */
3662 DELETE_ACCESS, /* access_mask */
3663 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
3664 FILE_SHARE_DELETE),
3665 FILE_OPEN, /* create_disposition*/
3666 create_options, /* create_options */
3667 0, /* file_attributes */
3668 0, /* oplock_request */
3669 NULL, /* lease */
3670 0, /* allocation_size */
3671 0, /* private_flags */
3672 NULL, /* sd */
3673 NULL, /* ea_list */
3674 &fsp, /* result */
3675 &info, /* pinfo */
3676 posx, /* in_context_blobs */
3677 NULL); /* out_context_blobs */
3679 TALLOC_FREE(posx);
3681 if (!NT_STATUS_IS_OK(status)) {
3682 return status;
3686 * Don't lie to client. If we can't really delete due to
3687 * non-POSIX opens return SHARING_VIOLATION.
3690 state = (struct smb_posix_unlink_state) {
3691 .smb_fname = smb_fname,
3692 .fsp = fsp,
3695 status = share_mode_do_locked_vfs_allowed(fsp->file_id,
3696 smb_posix_unlink_locked,
3697 &state);
3698 if (!NT_STATUS_IS_OK(status)) {
3699 DBG_ERR("share_mode_do_locked_vfs_allowed(%s) failed - %s\n",
3700 fsp_str_dbg(fsp), nt_errstr(status));
3701 close_file_free(req, &fsp, NORMAL_CLOSE);
3702 return NT_STATUS_INVALID_PARAMETER;
3705 status = state.status;
3706 if (!NT_STATUS_IS_OK(status)) {
3707 close_file_free(req, &fsp, NORMAL_CLOSE);
3708 return status;
3710 return close_file_free(req, &fsp, NORMAL_CLOSE);
3713 /****************************************************************************
3714 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
3715 ****************************************************************************/
3717 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
3718 struct smb_request *req,
3719 const char *pdata,
3720 int total_data,
3721 struct smb_filename *new_smb_fname)
3723 char *link_target = NULL;
3724 struct smb_filename target_fname;
3725 TALLOC_CTX *ctx = talloc_tos();
3726 NTSTATUS status;
3727 int ret;
3728 struct smb_filename *parent_fname = NULL;
3729 struct smb_filename *base_name = NULL;
3731 if (!CAN_WRITE(conn)) {
3732 return NT_STATUS_DOS(ERRSRV, ERRaccess);
3735 /* Set a symbolic link. */
3736 /* Don't allow this if follow links is false. */
3738 if (total_data == 0) {
3739 return NT_STATUS_INVALID_PARAMETER;
3742 if (!lp_follow_symlinks(SNUM(conn))) {
3743 return NT_STATUS_ACCESS_DENIED;
3746 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
3747 total_data, STR_TERMINATE);
3749 if (!link_target) {
3750 return NT_STATUS_INVALID_PARAMETER;
3753 target_fname = (struct smb_filename) {
3754 .base_name = link_target,
3757 /* Removes @GMT tokens if any */
3758 status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
3759 if (!NT_STATUS_IS_OK(status)) {
3760 return status;
3763 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3764 new_smb_fname->base_name, link_target ));
3766 status = parent_pathref(talloc_tos(),
3767 conn->cwd_fsp,
3768 new_smb_fname,
3769 &parent_fname,
3770 &base_name);
3771 if (!NT_STATUS_IS_OK(status)) {
3772 return status;
3775 ret = SMB_VFS_SYMLINKAT(conn,
3776 &target_fname,
3777 parent_fname->fsp,
3778 base_name);
3779 if (ret != 0) {
3780 TALLOC_FREE(parent_fname);
3781 return map_nt_error_from_unix(errno);
3784 TALLOC_FREE(parent_fname);
3785 return NT_STATUS_OK;
3788 /****************************************************************************
3789 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
3790 ****************************************************************************/
3792 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
3793 struct smb_request *req,
3794 const char *pdata, int total_data,
3795 struct smb_filename *smb_fname_new)
3797 char *oldname = NULL;
3798 struct files_struct *src_dirfsp = NULL;
3799 struct smb_filename *smb_fname_old = NULL;
3800 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
3801 NTTIME old_twrp = 0;
3802 TALLOC_CTX *ctx = talloc_tos();
3803 NTSTATUS status = NT_STATUS_OK;
3805 if (!CAN_WRITE(conn)) {
3806 return NT_STATUS_DOS(ERRSRV, ERRaccess);
3809 /* Set a hard link. */
3810 if (total_data == 0) {
3811 return NT_STATUS_INVALID_PARAMETER;
3814 if (req->posix_pathnames) {
3815 srvstr_get_path_posix(ctx,
3816 pdata,
3817 req->flags2,
3818 &oldname,
3819 pdata,
3820 total_data,
3821 STR_TERMINATE,
3822 &status);
3823 } else {
3824 srvstr_get_path(ctx,
3825 pdata,
3826 req->flags2,
3827 &oldname,
3828 pdata,
3829 total_data,
3830 STR_TERMINATE,
3831 &status);
3833 if (!NT_STATUS_IS_OK(status)) {
3834 return status;
3837 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3838 smb_fname_str_dbg(smb_fname_new), oldname));
3840 if (ucf_flags & UCF_GMT_PATHNAME) {
3841 extract_snapshot_token(oldname, &old_twrp);
3843 status = smb1_strip_dfs_path(ctx, &ucf_flags, &oldname);
3844 if (!NT_STATUS_IS_OK(status)) {
3845 return status;
3847 status = filename_convert_dirfsp(ctx,
3848 conn,
3849 oldname,
3850 ucf_flags,
3851 old_twrp,
3852 &src_dirfsp,
3853 &smb_fname_old);
3854 if (!NT_STATUS_IS_OK(status)) {
3855 return status;
3858 return hardlink_internals(ctx,
3859 conn,
3860 req,
3861 false,
3862 src_dirfsp,
3863 smb_fname_old,
3864 NULL, /* new_dirfsp */
3865 smb_fname_new);
3868 /****************************************************************************
3869 Allow a UNIX info mknod.
3870 ****************************************************************************/
3872 static NTSTATUS smb_unix_mknod(connection_struct *conn,
3873 const char *pdata,
3874 int total_data,
3875 const struct smb_filename *smb_fname)
3877 uint32_t file_type = IVAL(pdata,56);
3878 #if defined(HAVE_MAKEDEV)
3879 uint32_t dev_major = IVAL(pdata,60);
3880 uint32_t dev_minor = IVAL(pdata,68);
3881 #endif
3882 SMB_DEV_T dev = (SMB_DEV_T)0;
3883 uint32_t raw_unixmode = IVAL(pdata,84);
3884 NTSTATUS status;
3885 mode_t unixmode;
3886 int ret;
3887 struct smb_filename *parent_fname = NULL;
3888 struct smb_filename *base_name = NULL;
3890 if (total_data < 100) {
3891 return NT_STATUS_INVALID_PARAMETER;
3894 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
3895 PERM_NEW_FILE, &unixmode);
3896 if (!NT_STATUS_IS_OK(status)) {
3897 return status;
3900 #if defined(HAVE_MAKEDEV)
3901 dev = makedev(dev_major, dev_minor);
3902 #endif
3904 switch (file_type) {
3905 /* We can't create other objects here. */
3906 case UNIX_TYPE_FILE:
3907 case UNIX_TYPE_DIR:
3908 case UNIX_TYPE_SYMLINK:
3909 return NT_STATUS_ACCESS_DENIED;
3910 #if defined(S_IFIFO)
3911 case UNIX_TYPE_FIFO:
3912 unixmode |= S_IFIFO;
3913 break;
3914 #endif
3915 #if defined(S_IFSOCK)
3916 case UNIX_TYPE_SOCKET:
3917 unixmode |= S_IFSOCK;
3918 break;
3919 #endif
3920 #if defined(S_IFCHR)
3921 case UNIX_TYPE_CHARDEV:
3922 /* This is only allowed for root. */
3923 if (get_current_uid(conn) != sec_initial_uid()) {
3924 return NT_STATUS_ACCESS_DENIED;
3926 unixmode |= S_IFCHR;
3927 break;
3928 #endif
3929 #if defined(S_IFBLK)
3930 case UNIX_TYPE_BLKDEV:
3931 if (get_current_uid(conn) != sec_initial_uid()) {
3932 return NT_STATUS_ACCESS_DENIED;
3934 unixmode |= S_IFBLK;
3935 break;
3936 #endif
3937 default:
3938 return NT_STATUS_INVALID_PARAMETER;
3941 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
3942 "%.0f mode 0%o for file %s\n", (double)dev,
3943 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
3945 status = parent_pathref(talloc_tos(),
3946 conn->cwd_fsp,
3947 smb_fname,
3948 &parent_fname,
3949 &base_name);
3950 if (!NT_STATUS_IS_OK(status)) {
3951 return status;
3954 /* Ok - do the mknod. */
3955 ret = SMB_VFS_MKNODAT(conn,
3956 parent_fname->fsp,
3957 base_name,
3958 unixmode,
3959 dev);
3961 if (ret != 0) {
3962 TALLOC_FREE(parent_fname);
3963 return map_nt_error_from_unix(errno);
3966 /* If any of the other "set" calls fail we
3967 * don't want to end up with a half-constructed mknod.
3970 if (lp_inherit_permissions(SNUM(conn))) {
3971 inherit_access_posix_acl(conn,
3972 parent_fname->fsp,
3973 smb_fname,
3974 unixmode);
3976 TALLOC_FREE(parent_fname);
3978 return NT_STATUS_OK;
3981 /****************************************************************************
3982 Deal with SMB_SET_FILE_UNIX_BASIC.
3983 ****************************************************************************/
3985 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
3986 struct smb_request *req,
3987 const char *pdata,
3988 int total_data,
3989 files_struct *fsp,
3990 struct smb_filename *smb_fname)
3992 struct smb_file_time ft;
3993 uint32_t raw_unixmode;
3994 mode_t unixmode;
3995 off_t size = 0;
3996 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3997 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3998 NTSTATUS status = NT_STATUS_OK;
3999 enum perm_type ptype;
4000 files_struct *all_fsps = NULL;
4001 bool modify_mtime = true;
4002 struct file_id id;
4003 SMB_STRUCT_STAT sbuf;
4005 if (!CAN_WRITE(conn)) {
4006 return NT_STATUS_DOS(ERRSRV, ERRaccess);
4009 init_smb_file_time(&ft);
4011 if (total_data < 100) {
4012 return NT_STATUS_INVALID_PARAMETER;
4015 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4016 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4017 size=IVAL(pdata,0); /* first 8 Bytes are size */
4018 size |= (((off_t)IVAL(pdata,4)) << 32);
4021 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
4022 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
4023 set_owner = (uid_t)IVAL(pdata,40);
4024 set_grp = (gid_t)IVAL(pdata,48);
4025 raw_unixmode = IVAL(pdata,84);
4027 if (VALID_STAT(smb_fname->st)) {
4028 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
4029 ptype = PERM_EXISTING_DIR;
4030 } else {
4031 ptype = PERM_EXISTING_FILE;
4033 } else {
4034 ptype = PERM_NEW_FILE;
4037 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
4038 ptype, &unixmode);
4039 if (!NT_STATUS_IS_OK(status)) {
4040 return status;
4043 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
4044 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4045 smb_fname_str_dbg(smb_fname), (double)size,
4046 (unsigned int)set_owner, (unsigned int)set_grp,
4047 (int)raw_unixmode));
4049 sbuf = smb_fname->st;
4051 if (!VALID_STAT(sbuf)) {
4053 * The only valid use of this is to create character and block
4054 * devices, and named pipes. This is deprecated (IMHO) and
4055 * a new info level should be used for mknod. JRA.
4058 return smb_unix_mknod(conn,
4059 pdata,
4060 total_data,
4061 smb_fname);
4064 #if 1
4065 /* Horrible backwards compatibility hack as an old server bug
4066 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
4067 * */
4069 if (!size) {
4070 size = get_file_size_stat(&sbuf);
4072 #endif
4075 * Deal with the UNIX specific mode set.
4078 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4079 int ret;
4081 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
4082 DBG_WARNING("Can't set mode on symlink %s\n",
4083 smb_fname_str_dbg(smb_fname));
4084 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4087 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4088 "setting mode 0%o for file %s\n",
4089 (unsigned int)unixmode,
4090 smb_fname_str_dbg(smb_fname)));
4091 ret = SMB_VFS_FCHMOD(fsp, unixmode);
4092 if (ret != 0) {
4093 return map_nt_error_from_unix(errno);
4098 * Deal with the UNIX specific uid set.
4101 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
4102 (sbuf.st_ex_uid != set_owner)) {
4103 int ret;
4105 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4106 "changing owner %u for path %s\n",
4107 (unsigned int)set_owner,
4108 smb_fname_str_dbg(smb_fname)));
4110 if (fsp &&
4111 !fsp->fsp_flags.is_pathref &&
4112 fsp_get_io_fd(fsp) != -1)
4114 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
4115 } else {
4117 * UNIX extensions calls must always operate
4118 * on symlinks.
4120 ret = SMB_VFS_LCHOWN(conn, smb_fname,
4121 set_owner, (gid_t)-1);
4124 if (ret != 0) {
4125 status = map_nt_error_from_unix(errno);
4126 return status;
4131 * Deal with the UNIX specific gid set.
4134 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
4135 (sbuf.st_ex_gid != set_grp)) {
4136 int ret;
4138 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4139 "changing group %u for file %s\n",
4140 (unsigned int)set_grp,
4141 smb_fname_str_dbg(smb_fname)));
4142 if (fsp &&
4143 !fsp->fsp_flags.is_pathref &&
4144 fsp_get_io_fd(fsp) != -1)
4146 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
4147 } else {
4149 * UNIX extensions calls must always operate
4150 * on symlinks.
4152 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
4153 set_grp);
4155 if (ret != 0) {
4156 status = map_nt_error_from_unix(errno);
4157 return status;
4161 /* Deal with any size changes. */
4163 if (S_ISREG(sbuf.st_ex_mode)) {
4164 status = smb_set_file_size(conn, req,
4165 fsp,
4166 smb_fname,
4167 &sbuf,
4168 size,
4169 false);
4170 if (!NT_STATUS_IS_OK(status)) {
4171 return status;
4175 /* Deal with any time changes. */
4176 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
4177 /* No change, don't cancel anything. */
4178 return status;
4181 id = vfs_file_id_from_sbuf(conn, &sbuf);
4182 for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
4183 all_fsps = file_find_di_next(all_fsps, true)) {
4185 * We're setting the time explicitly for UNIX.
4186 * Cancel any pending changes over all handles.
4188 all_fsps->fsp_flags.update_write_time_on_close = false;
4189 TALLOC_FREE(all_fsps->update_write_time_event);
4193 * Override the "setting_write_time"
4194 * parameter here as it almost does what
4195 * we need. Just remember if we modified
4196 * mtime and send the notify ourselves.
4198 if (is_omit_timespec(&ft.mtime)) {
4199 modify_mtime = false;
4202 status = smb_set_file_time(conn,
4203 fsp,
4204 smb_fname,
4205 &ft,
4206 false);
4207 if (modify_mtime) {
4208 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4209 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
4211 return status;
4214 /****************************************************************************
4215 Deal with SMB_SET_FILE_UNIX_INFO2.
4216 ****************************************************************************/
4218 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
4219 struct smb_request *req,
4220 const char *pdata,
4221 int total_data,
4222 files_struct *fsp,
4223 struct smb_filename *smb_fname)
4225 NTSTATUS status;
4226 uint32_t smb_fflags;
4227 uint32_t smb_fmask;
4229 if (!CAN_WRITE(conn)) {
4230 return NT_STATUS_DOS(ERRSRV, ERRaccess);
4233 if (total_data < 116) {
4234 return NT_STATUS_INVALID_PARAMETER;
4237 /* Start by setting all the fields that are common between UNIX_BASIC
4238 * and UNIX_INFO2.
4240 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
4241 fsp, smb_fname);
4242 if (!NT_STATUS_IS_OK(status)) {
4243 return status;
4246 smb_fflags = IVAL(pdata, 108);
4247 smb_fmask = IVAL(pdata, 112);
4249 /* NB: We should only attempt to alter the file flags if the client
4250 * sends a non-zero mask.
4252 if (smb_fmask != 0) {
4253 int stat_fflags = 0;
4255 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
4256 smb_fmask, &stat_fflags)) {
4257 /* Client asked to alter a flag we don't understand. */
4258 return NT_STATUS_INVALID_PARAMETER;
4261 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
4262 DBG_WARNING("Can't change flags on symlink %s\n",
4263 smb_fname_str_dbg(smb_fname));
4264 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4266 if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) {
4267 return map_nt_error_from_unix(errno);
4271 /* XXX: need to add support for changing the create_time here. You
4272 * can do this for paths on Darwin with setattrlist(2). The right way
4273 * to hook this up is probably by extending the VFS utimes interface.
4276 return NT_STATUS_OK;
4279 /****************************************************************************
4280 Deal with SMB_SET_POSIX_ACL.
4281 ****************************************************************************/
4283 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4284 struct smb_request *req,
4285 const char *pdata,
4286 int total_data_in,
4287 files_struct *fsp,
4288 struct smb_filename *smb_fname)
4290 #if !defined(HAVE_POSIX_ACLS)
4291 return NT_STATUS_INVALID_LEVEL;
4292 #else
4293 uint16_t posix_acl_version;
4294 uint16_t num_file_acls;
4295 uint16_t num_def_acls;
4296 bool valid_file_acls = true;
4297 bool valid_def_acls = true;
4298 NTSTATUS status;
4299 unsigned int size_needed;
4300 unsigned int total_data;
4301 bool close_fsp = false;
4303 if (total_data_in < 0) {
4304 status = NT_STATUS_INVALID_PARAMETER;
4305 goto out;
4308 total_data = total_data_in;
4310 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4311 status = NT_STATUS_INVALID_PARAMETER;
4312 goto out;
4314 posix_acl_version = SVAL(pdata,0);
4315 num_file_acls = SVAL(pdata,2);
4316 num_def_acls = SVAL(pdata,4);
4318 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4319 valid_file_acls = false;
4320 num_file_acls = 0;
4323 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4324 valid_def_acls = false;
4325 num_def_acls = 0;
4328 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4329 status = NT_STATUS_INVALID_PARAMETER;
4330 goto out;
4333 /* Wrap checks. */
4334 if (num_file_acls + num_def_acls < num_file_acls) {
4335 status = NT_STATUS_INVALID_PARAMETER;
4336 goto out;
4339 size_needed = num_file_acls + num_def_acls;
4342 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4343 * than UINT_MAX, so check by division.
4345 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
4346 status = NT_STATUS_INVALID_PARAMETER;
4347 goto out;
4350 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
4351 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
4352 status = NT_STATUS_INVALID_PARAMETER;
4353 goto out;
4355 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
4357 if (total_data < size_needed) {
4358 status = NT_STATUS_INVALID_PARAMETER;
4359 goto out;
4363 * Ensure we always operate on a file descriptor, not just
4364 * the filename.
4366 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
4367 uint32_t access_mask = SEC_STD_WRITE_OWNER|
4368 SEC_STD_WRITE_DAC|
4369 SEC_STD_READ_CONTROL|
4370 FILE_READ_ATTRIBUTES|
4371 FILE_WRITE_ATTRIBUTES;
4373 status = get_posix_fsp(conn,
4374 req,
4375 smb_fname,
4376 access_mask,
4377 &fsp);
4379 if (!NT_STATUS_IS_OK(status)) {
4380 goto out;
4382 close_fsp = true;
4385 /* Here we know fsp != NULL */
4386 SMB_ASSERT(fsp != NULL);
4388 status = refuse_symlink_fsp(fsp);
4389 if (!NT_STATUS_IS_OK(status)) {
4390 goto out;
4393 /* If we have a default acl, this *must* be a directory. */
4394 if (valid_def_acls && !fsp->fsp_flags.is_directory) {
4395 DBG_INFO("Can't set default acls on "
4396 "non-directory %s\n",
4397 fsp_str_dbg(fsp));
4398 return NT_STATUS_INVALID_HANDLE;
4401 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
4402 "num_def_acls = %"PRIu16"\n",
4403 fsp_str_dbg(fsp),
4404 num_file_acls,
4405 num_def_acls);
4407 /* Move pdata to the start of the file ACL entries. */
4408 pdata += SMB_POSIX_ACL_HEADER_SIZE;
4410 if (valid_file_acls) {
4411 status = set_unix_posix_acl(conn,
4412 fsp,
4413 num_file_acls,
4414 pdata);
4415 if (!NT_STATUS_IS_OK(status)) {
4416 goto out;
4420 /* Move pdata to the start of the default ACL entries. */
4421 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
4423 if (valid_def_acls) {
4424 status = set_unix_posix_default_acl(conn,
4425 fsp,
4426 num_def_acls,
4427 pdata);
4428 if (!NT_STATUS_IS_OK(status)) {
4429 goto out;
4433 status = NT_STATUS_OK;
4435 out:
4437 if (close_fsp) {
4438 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
4440 return status;
4441 #endif
4444 static void call_trans2setpathinfo(
4445 connection_struct *conn,
4446 struct smb_request *req,
4447 char **pparams,
4448 int total_params,
4449 char **ppdata,
4450 int total_data,
4451 unsigned int max_data_bytes)
4453 uint16_t info_level;
4454 struct smb_filename *smb_fname = NULL;
4455 struct files_struct *dirfsp = NULL;
4456 struct files_struct *fsp = NULL;
4457 char *params = *pparams;
4458 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4459 NTTIME twrp = 0;
4460 char *fname = NULL;
4461 bool info_level_handled;
4462 int data_return_size = 0;
4463 NTSTATUS status;
4465 if (params == NULL) {
4466 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4467 return;
4470 /* set path info */
4471 if (total_params < 7) {
4472 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4473 return;
4476 info_level = SVAL(params,0);
4478 if (INFO_LEVEL_IS_UNIX(info_level)) {
4479 if (!lp_smb1_unix_extensions()) {
4480 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4481 return;
4483 if (!req->posix_pathnames) {
4484 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4485 return;
4489 if (req->posix_pathnames) {
4490 srvstr_get_path_posix(req,
4491 params,
4492 req->flags2,
4493 &fname,
4494 &params[6],
4495 total_params - 6,
4496 STR_TERMINATE,
4497 &status);
4498 } else {
4499 srvstr_get_path(req,
4500 params,
4501 req->flags2,
4502 &fname,
4503 &params[6],
4504 total_params - 6,
4505 STR_TERMINATE,
4506 &status);
4508 if (!NT_STATUS_IS_OK(status)) {
4509 reply_nterror(req, status);
4510 return;
4513 DBG_NOTICE("fname=%s info_level=%d totdata=%d\n",
4514 fname,
4515 info_level,
4516 total_data);
4518 if (ucf_flags & UCF_GMT_PATHNAME) {
4519 extract_snapshot_token(fname, &twrp);
4521 status = smb1_strip_dfs_path(req, &ucf_flags, &fname);
4522 if (!NT_STATUS_IS_OK(status)) {
4523 reply_nterror(req, status);
4524 return;
4526 status = filename_convert_dirfsp(req,
4527 conn,
4528 fname,
4529 ucf_flags,
4530 twrp,
4531 &dirfsp,
4532 &smb_fname);
4533 if (!NT_STATUS_IS_OK(status)) {
4534 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4535 reply_botherror(req,
4536 NT_STATUS_PATH_NOT_COVERED,
4537 ERRSRV, ERRbadpath);
4538 return;
4540 reply_nterror(req, status);
4541 return;
4544 info_level_handled = true; /* Untouched in switch cases below */
4546 switch (info_level) {
4548 default:
4549 info_level_handled = false;
4550 break;
4552 case SMB_POSIX_PATH_OPEN:
4553 status = smb_posix_open(
4554 conn,
4555 req,
4556 ppdata,
4557 total_data,
4558 smb_fname,
4559 &data_return_size);
4560 break;
4562 case SMB_POSIX_PATH_UNLINK:
4563 status = smb_posix_unlink(
4564 conn, req, *ppdata, total_data, smb_fname);
4565 break;
4567 case SMB_SET_FILE_UNIX_LINK:
4568 status = smb_set_file_unix_link(
4569 conn, req, *ppdata, total_data, smb_fname);
4570 break;
4572 case SMB_SET_FILE_UNIX_HLINK:
4573 status = smb_set_file_unix_hlink(
4574 conn, req, *ppdata, total_data, smb_fname);
4575 break;
4577 case SMB_SET_FILE_UNIX_BASIC:
4578 status = smb_set_file_unix_basic(
4579 conn,
4580 req,
4581 *ppdata,
4582 total_data,
4583 smb_fname->fsp,
4584 smb_fname);
4585 break;
4587 case SMB_SET_FILE_UNIX_INFO2:
4588 status = smb_set_file_unix_info2(
4589 conn,
4590 req,
4591 *ppdata,
4592 total_data,
4593 smb_fname->fsp,
4594 smb_fname);
4595 break;
4596 case SMB_SET_POSIX_ACL:
4597 status = smb_set_posix_acl(
4598 conn, req, *ppdata, total_data, NULL, smb_fname);
4599 break;
4602 if (info_level_handled) {
4603 handle_trans2setfilepathinfo_result(
4604 conn,
4605 req,
4606 info_level,
4607 status,
4608 *ppdata,
4609 data_return_size,
4610 max_data_bytes);
4611 return;
4615 * smb_fname->fsp may be NULL if smb_fname points at a symlink
4616 * and we're in POSIX context, so be careful when using fsp
4617 * below, it can still be NULL.
4619 fsp = smb_fname->fsp;
4621 status = smbd_do_setfilepathinfo(
4622 conn,
4623 req,
4624 req,
4625 info_level,
4626 fsp,
4627 smb_fname,
4628 ppdata,
4629 total_data,
4630 &data_return_size);
4632 handle_trans2setfilepathinfo_result(
4633 conn,
4634 req,
4635 info_level,
4636 status,
4637 *ppdata,
4638 data_return_size,
4639 max_data_bytes);
4642 static void call_trans2setfileinfo(
4643 connection_struct *conn,
4644 struct smb_request *req,
4645 char **pparams,
4646 int total_params,
4647 char **ppdata,
4648 int total_data,
4649 unsigned int max_data_bytes)
4651 char *pdata = *ppdata;
4652 uint16_t info_level;
4653 struct smb_filename *smb_fname = NULL;
4654 struct files_struct *fsp = NULL;
4655 char *params = *pparams;
4656 int data_return_size = 0;
4657 bool info_level_handled;
4658 NTSTATUS status;
4659 int ret;
4661 if (params == NULL) {
4662 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4663 return;
4665 if (total_params < 4) {
4666 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4667 return;
4670 fsp = file_fsp(req, SVAL(params,0));
4671 /* Basic check for non-null fsp. */
4672 if (!check_fsp_open(conn, req, fsp)) {
4673 return;
4675 info_level = SVAL(params,2);
4677 if (INFO_LEVEL_IS_UNIX(info_level)) {
4678 if (!lp_smb1_unix_extensions()) {
4679 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4680 return;
4682 if (!req->posix_pathnames) {
4683 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4684 return;
4688 smb_fname = fsp->fsp_name;
4690 DBG_NOTICE("fnum=%s fname=%s info_level=%d totdata=%d\n",
4691 fsp_fnum_dbg(fsp),
4692 fsp_str_dbg(fsp),
4693 info_level,
4694 total_data);
4696 if (fsp_get_pathref_fd(fsp) == -1) {
4698 * This is actually a SETFILEINFO on a directory
4699 * handle (returned from an NT SMB). NT5.0 seems
4700 * to do this call. JRA.
4702 ret = vfs_stat(conn, smb_fname);
4703 if (ret != 0) {
4704 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
4705 smb_fname_str_dbg(smb_fname),
4706 strerror(errno));
4707 reply_nterror(req, map_nt_error_from_unix(errno));
4708 return;
4710 } else if (fsp->print_file) {
4712 * Doing a DELETE_ON_CLOSE should cancel a print job.
4714 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) &&
4715 CVAL(pdata,0)) {
4717 fsp->fsp_flags.delete_on_close = true;
4719 DBG_NOTICE("Cancelling print job (%s)\n",
4720 fsp_str_dbg(fsp));
4722 SSVAL(params,0,0);
4723 send_trans2_replies(
4724 conn,
4725 req,
4726 NT_STATUS_OK,
4727 params,
4729 *ppdata, 0,
4730 max_data_bytes);
4731 return;
4732 } else {
4733 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
4734 return;
4736 } else {
4738 * Original code - this is an open file.
4740 status = vfs_stat_fsp(fsp);
4741 if (!NT_STATUS_IS_OK(status)) {
4742 DBG_NOTICE("fstat of %s failed (%s)\n",
4743 fsp_fnum_dbg(fsp),
4744 nt_errstr(status));
4745 reply_nterror(req, status);
4746 return;
4750 info_level_handled = true; /* Untouched in switch cases below */
4752 switch (info_level) {
4754 default:
4755 info_level_handled = false;
4756 break;
4758 case SMB_SET_FILE_UNIX_BASIC:
4759 status = smb_set_file_unix_basic(
4760 conn, req, pdata, total_data, fsp, smb_fname);
4761 break;
4763 case SMB_SET_FILE_UNIX_INFO2:
4764 status = smb_set_file_unix_info2(
4765 conn, req, pdata, total_data, fsp, smb_fname);
4766 break;
4768 case SMB_SET_POSIX_LOCK:
4769 status = smb_set_posix_lock(
4770 conn, req, *ppdata, total_data, fsp);
4771 break;
4774 if (info_level_handled) {
4775 handle_trans2setfilepathinfo_result(
4776 conn,
4777 req,
4778 info_level,
4779 status,
4780 *ppdata,
4781 data_return_size,
4782 max_data_bytes);
4783 return;
4786 status = smbd_do_setfilepathinfo(
4787 conn,
4788 req,
4789 req,
4790 info_level,
4791 fsp,
4792 smb_fname,
4793 ppdata,
4794 total_data,
4795 &data_return_size);
4797 handle_trans2setfilepathinfo_result(
4798 conn,
4799 req,
4800 info_level,
4801 status,
4802 *ppdata,
4803 data_return_size,
4804 max_data_bytes);
4807 /****************************************************************************
4808 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4809 ****************************************************************************/
4811 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
4812 char **pparams, int total_params,
4813 char **ppdata, int total_data,
4814 unsigned int max_data_bytes)
4816 struct files_struct *dirfsp = NULL;
4817 struct files_struct *fsp = NULL;
4818 struct smb_filename *smb_dname = NULL;
4819 char *params = *pparams;
4820 char *pdata = *ppdata;
4821 char *directory = NULL;
4822 NTSTATUS status = NT_STATUS_OK;
4823 struct ea_list *ea_list = NULL;
4824 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4825 NTTIME twrp = 0;
4826 TALLOC_CTX *ctx = talloc_tos();
4828 if (!CAN_WRITE(conn)) {
4829 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4830 return;
4833 if (total_params < 5) {
4834 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4835 return;
4838 if (req->posix_pathnames) {
4839 srvstr_get_path_posix(ctx,
4840 params,
4841 req->flags2,
4842 &directory,
4843 &params[4],
4844 total_params - 4,
4845 STR_TERMINATE,
4846 &status);
4847 } else {
4848 srvstr_get_path(ctx,
4849 params,
4850 req->flags2,
4851 &directory,
4852 &params[4],
4853 total_params - 4,
4854 STR_TERMINATE,
4855 &status);
4857 if (!NT_STATUS_IS_OK(status)) {
4858 reply_nterror(req, status);
4859 return;
4862 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4864 if (ucf_flags & UCF_GMT_PATHNAME) {
4865 extract_snapshot_token(directory, &twrp);
4867 status = smb1_strip_dfs_path(ctx, &ucf_flags, &directory);
4868 if (!NT_STATUS_IS_OK(status)) {
4869 reply_nterror(req, status);
4870 goto out;
4872 status = filename_convert_dirfsp(ctx,
4873 conn,
4874 directory,
4875 ucf_flags,
4876 twrp,
4877 &dirfsp,
4878 &smb_dname);
4879 if (!NT_STATUS_IS_OK(status)) {
4880 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4881 reply_botherror(req,
4882 NT_STATUS_PATH_NOT_COVERED,
4883 ERRSRV, ERRbadpath);
4884 return;
4886 reply_nterror(req, status);
4887 return;
4891 * OS/2 workplace shell seems to send SET_EA requests of "null"
4892 * length (4 bytes containing IVAL 4).
4893 * They seem to have no effect. Bug #3212. JRA.
4896 if (total_data && (total_data != 4)) {
4897 /* Any data in this call is an EA list. */
4898 if (total_data < 10) {
4899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4900 goto out;
4903 if (IVAL(pdata,0) > total_data) {
4904 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4905 IVAL(pdata,0), (unsigned int)total_data));
4906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4907 goto out;
4910 ea_list = read_ea_list(talloc_tos(), pdata + 4,
4911 total_data - 4);
4912 if (!ea_list) {
4913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4914 goto out;
4917 if (!lp_ea_support(SNUM(conn))) {
4918 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
4919 goto out;
4922 /* If total_data == 4 Windows doesn't care what values
4923 * are placed in that field, it just ignores them.
4924 * The System i QNTC IBM SMB client puts bad values here,
4925 * so ignore them. */
4927 status = SMB_VFS_CREATE_FILE(
4928 conn, /* conn */
4929 req, /* req */
4930 dirfsp, /* dirfsp */
4931 smb_dname, /* fname */
4932 MAXIMUM_ALLOWED_ACCESS, /* access_mask */
4933 FILE_SHARE_NONE, /* share_access */
4934 FILE_CREATE, /* create_disposition*/
4935 FILE_DIRECTORY_FILE, /* create_options */
4936 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
4937 0, /* oplock_request */
4938 NULL, /* lease */
4939 0, /* allocation_size */
4940 0, /* private_flags */
4941 NULL, /* sd */
4942 NULL, /* ea_list */
4943 &fsp, /* result */
4944 NULL, /* pinfo */
4945 NULL, NULL); /* create context */
4946 if (!NT_STATUS_IS_OK(status)) {
4947 reply_nterror(req, status);
4948 goto out;
4951 /* Try and set any given EA. */
4952 if (ea_list) {
4953 status = set_ea(conn, fsp, ea_list);
4954 if (!NT_STATUS_IS_OK(status)) {
4955 reply_nterror(req, status);
4956 goto out;
4960 /* Realloc the parameter and data sizes */
4961 *pparams = (char *)SMB_REALLOC(*pparams,2);
4962 if(*pparams == NULL) {
4963 reply_nterror(req, NT_STATUS_NO_MEMORY);
4964 goto out;
4966 params = *pparams;
4968 SSVAL(params,0,0);
4970 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
4972 out:
4973 if (fsp != NULL) {
4974 close_file_free(NULL, &fsp, NORMAL_CLOSE);
4976 TALLOC_FREE(smb_dname);
4977 return;
4980 /****************************************************************************
4981 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4982 We don't actually do this - we just send a null response.
4983 ****************************************************************************/
4985 static void call_trans2findnotifyfirst(connection_struct *conn,
4986 struct smb_request *req,
4987 char **pparams, int total_params,
4988 char **ppdata, int total_data,
4989 unsigned int max_data_bytes)
4991 char *params = *pparams;
4992 uint16_t info_level;
4994 if (total_params < 6) {
4995 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4996 return;
4999 info_level = SVAL(params,4);
5000 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
5002 switch (info_level) {
5003 case 1:
5004 case 2:
5005 break;
5006 default:
5007 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5008 return;
5011 /* Realloc the parameter and data sizes */
5012 *pparams = (char *)SMB_REALLOC(*pparams,6);
5013 if (*pparams == NULL) {
5014 reply_nterror(req, NT_STATUS_NO_MEMORY);
5015 return;
5017 params = *pparams;
5019 SSVAL(params,0,fnf_handle);
5020 SSVAL(params,2,0); /* No changes */
5021 SSVAL(params,4,0); /* No EA errors */
5023 fnf_handle++;
5025 if(fnf_handle == 0)
5026 fnf_handle = 257;
5028 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
5030 return;
5033 /****************************************************************************
5034 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
5035 changes). Currently this does nothing.
5036 ****************************************************************************/
5038 static void call_trans2findnotifynext(connection_struct *conn,
5039 struct smb_request *req,
5040 char **pparams, int total_params,
5041 char **ppdata, int total_data,
5042 unsigned int max_data_bytes)
5044 char *params = *pparams;
5046 DEBUG(3,("call_trans2findnotifynext\n"));
5048 /* Realloc the parameter and data sizes */
5049 *pparams = (char *)SMB_REALLOC(*pparams,4);
5050 if (*pparams == NULL) {
5051 reply_nterror(req, NT_STATUS_NO_MEMORY);
5052 return;
5054 params = *pparams;
5056 SSVAL(params,0,0); /* No changes */
5057 SSVAL(params,2,0); /* No EA errors */
5059 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
5061 return;
5064 /****************************************************************************
5065 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5066 ****************************************************************************/
5068 static void call_trans2getdfsreferral(connection_struct *conn,
5069 struct smb_request *req,
5070 char **pparams, int total_params,
5071 char **ppdata, int total_data,
5072 unsigned int max_data_bytes)
5074 char *params = *pparams;
5075 char *pathname = NULL;
5076 int reply_size = 0;
5077 int max_referral_level;
5078 NTSTATUS status = NT_STATUS_OK;
5079 TALLOC_CTX *ctx = talloc_tos();
5081 DEBUG(10,("call_trans2getdfsreferral\n"));
5083 if (!IS_IPC(conn)) {
5084 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5085 return;
5088 if (total_params < 3) {
5089 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5090 return;
5093 max_referral_level = SVAL(params,0);
5095 if(!lp_host_msdfs()) {
5096 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5097 return;
5100 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
5101 total_params - 2, STR_TERMINATE);
5102 if (!pathname) {
5103 reply_nterror(req, NT_STATUS_NOT_FOUND);
5104 return;
5106 reply_size = setup_dfs_referral(
5107 conn, pathname, max_referral_level, ppdata, &status);
5108 if (reply_size < 0) {
5109 reply_nterror(req, status);
5110 return;
5113 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
5114 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
5115 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
5117 return;
5120 #define LMCAT_SPL 0x53
5121 #define LMFUNC_GETJOBID 0x60
5123 /****************************************************************************
5124 Reply to a TRANS2_IOCTL - used for OS/2 printing.
5125 ****************************************************************************/
5127 static void call_trans2ioctl(connection_struct *conn,
5128 struct smb_request *req,
5129 char **pparams, int total_params,
5130 char **ppdata, int total_data,
5131 unsigned int max_data_bytes)
5133 const struct loadparm_substitution *lp_sub =
5134 loadparm_s3_global_substitution();
5135 char *pdata = *ppdata;
5136 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
5137 NTSTATUS status;
5138 size_t len = 0;
5140 /* check for an invalid fid before proceeding */
5142 if (!fsp) {
5143 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5144 return;
5147 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
5148 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
5149 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
5150 if (*ppdata == NULL) {
5151 reply_nterror(req, NT_STATUS_NO_MEMORY);
5152 return;
5154 pdata = *ppdata;
5156 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5157 CAN ACCEPT THIS IN UNICODE. JRA. */
5159 /* Job number */
5160 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
5162 status = srvstr_push(pdata, req->flags2, pdata + 2,
5163 lp_netbios_name(), 15,
5164 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
5165 if (!NT_STATUS_IS_OK(status)) {
5166 reply_nterror(req, status);
5167 return;
5169 status = srvstr_push(pdata, req->flags2, pdata+18,
5170 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
5171 STR_ASCII|STR_TERMINATE, &len); /* Service name */
5172 if (!NT_STATUS_IS_OK(status)) {
5173 reply_nterror(req, status);
5174 return;
5176 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
5177 max_data_bytes);
5178 return;
5181 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5182 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5185 static void handle_trans2(connection_struct *conn, struct smb_request *req,
5186 struct trans_state *state)
5188 struct smbXsrv_connection *xconn = req->xconn;
5190 if (xconn->protocol >= PROTOCOL_NT1) {
5191 req->flags2 |= 0x40; /* IS_LONG_NAME */
5192 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
5195 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
5196 if (state->call != TRANSACT2_QFSINFO &&
5197 state->call != TRANSACT2_SETFSINFO) {
5198 DEBUG(0,("handle_trans2: encryption required "
5199 "with call 0x%x\n",
5200 (unsigned int)state->call));
5201 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5202 return;
5206 /* Now we must call the relevant TRANS2 function */
5207 switch(state->call) {
5208 case TRANSACT2_OPEN:
5210 START_PROFILE(Trans2_open);
5211 call_trans2open(conn, req,
5212 &state->param, state->total_param,
5213 &state->data, state->total_data,
5214 state->max_data_return);
5215 END_PROFILE(Trans2_open);
5216 break;
5219 case TRANSACT2_FINDFIRST:
5221 START_PROFILE(Trans2_findfirst);
5222 call_trans2findfirst(conn, req,
5223 &state->param, state->total_param,
5224 &state->data, state->total_data,
5225 state->max_data_return);
5226 END_PROFILE(Trans2_findfirst);
5227 break;
5230 case TRANSACT2_FINDNEXT:
5232 START_PROFILE(Trans2_findnext);
5233 call_trans2findnext(conn, req,
5234 &state->param, state->total_param,
5235 &state->data, state->total_data,
5236 state->max_data_return);
5237 END_PROFILE(Trans2_findnext);
5238 break;
5241 case TRANSACT2_QFSINFO:
5243 START_PROFILE(Trans2_qfsinfo);
5244 call_trans2qfsinfo(conn, req,
5245 &state->param, state->total_param,
5246 &state->data, state->total_data,
5247 state->max_data_return);
5248 END_PROFILE(Trans2_qfsinfo);
5249 break;
5252 case TRANSACT2_SETFSINFO:
5254 START_PROFILE(Trans2_setfsinfo);
5255 call_trans2setfsinfo(conn, req,
5256 &state->param, state->total_param,
5257 &state->data, state->total_data,
5258 state->max_data_return);
5259 END_PROFILE(Trans2_setfsinfo);
5260 break;
5263 case TRANSACT2_QPATHINFO:
5265 START_PROFILE(Trans2_qpathinfo);
5266 call_trans2qpathinfo(
5267 conn,
5268 req,
5269 &state->param,
5270 state->total_param,
5271 &state->data,
5272 state->total_data,
5273 state->max_data_return);
5274 END_PROFILE(Trans2_qpathinfo);
5275 break;
5278 case TRANSACT2_QFILEINFO:
5280 START_PROFILE(Trans2_qfileinfo);
5281 call_trans2qfileinfo(
5282 conn,
5283 req,
5284 &state->param,
5285 state->total_param,
5286 &state->data,
5287 state->total_data,
5288 state->max_data_return);
5289 END_PROFILE(Trans2_qfileinfo);
5290 break;
5293 case TRANSACT2_SETPATHINFO:
5295 START_PROFILE(Trans2_setpathinfo);
5296 call_trans2setpathinfo(
5297 conn,
5298 req,
5299 &state->param,
5300 state->total_param,
5301 &state->data,
5302 state->total_data,
5303 state->max_data_return);
5304 END_PROFILE(Trans2_setpathinfo);
5305 break;
5308 case TRANSACT2_SETFILEINFO:
5310 START_PROFILE(Trans2_setfileinfo);
5311 call_trans2setfileinfo(
5312 conn,
5313 req,
5314 &state->param,
5315 state->total_param,
5316 &state->data,
5317 state->total_data,
5318 state->max_data_return);
5319 END_PROFILE(Trans2_setfileinfo);
5320 break;
5323 case TRANSACT2_FINDNOTIFYFIRST:
5325 START_PROFILE(Trans2_findnotifyfirst);
5326 call_trans2findnotifyfirst(conn, req,
5327 &state->param, state->total_param,
5328 &state->data, state->total_data,
5329 state->max_data_return);
5330 END_PROFILE(Trans2_findnotifyfirst);
5331 break;
5334 case TRANSACT2_FINDNOTIFYNEXT:
5336 START_PROFILE(Trans2_findnotifynext);
5337 call_trans2findnotifynext(conn, req,
5338 &state->param, state->total_param,
5339 &state->data, state->total_data,
5340 state->max_data_return);
5341 END_PROFILE(Trans2_findnotifynext);
5342 break;
5345 case TRANSACT2_MKDIR:
5347 START_PROFILE(Trans2_mkdir);
5348 call_trans2mkdir(conn, req,
5349 &state->param, state->total_param,
5350 &state->data, state->total_data,
5351 state->max_data_return);
5352 END_PROFILE(Trans2_mkdir);
5353 break;
5356 case TRANSACT2_GET_DFS_REFERRAL:
5358 START_PROFILE(Trans2_get_dfs_referral);
5359 call_trans2getdfsreferral(conn, req,
5360 &state->param, state->total_param,
5361 &state->data, state->total_data,
5362 state->max_data_return);
5363 END_PROFILE(Trans2_get_dfs_referral);
5364 break;
5367 case TRANSACT2_IOCTL:
5369 START_PROFILE(Trans2_ioctl);
5370 call_trans2ioctl(conn, req,
5371 &state->param, state->total_param,
5372 &state->data, state->total_data,
5373 state->max_data_return);
5374 END_PROFILE(Trans2_ioctl);
5375 break;
5378 default:
5379 /* Error in request */
5380 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5381 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5385 /****************************************************************************
5386 Reply to a SMBtrans2.
5387 ****************************************************************************/
5389 void reply_trans2(struct smb_request *req)
5391 connection_struct *conn = req->conn;
5392 unsigned int dsoff;
5393 unsigned int dscnt;
5394 unsigned int psoff;
5395 unsigned int pscnt;
5396 unsigned int tran_call;
5397 struct trans_state *state;
5398 NTSTATUS result;
5400 START_PROFILE(SMBtrans2);
5402 if (req->wct < 14) {
5403 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5404 END_PROFILE(SMBtrans2);
5405 return;
5408 dsoff = SVAL(req->vwv+12, 0);
5409 dscnt = SVAL(req->vwv+11, 0);
5410 psoff = SVAL(req->vwv+10, 0);
5411 pscnt = SVAL(req->vwv+9, 0);
5412 tran_call = SVAL(req->vwv+14, 0);
5414 result = allow_new_trans(conn->pending_trans, req->mid);
5415 if (!NT_STATUS_IS_OK(result)) {
5416 DEBUG(2, ("Got invalid trans2 request: %s\n",
5417 nt_errstr(result)));
5418 reply_nterror(req, result);
5419 END_PROFILE(SMBtrans2);
5420 return;
5423 if (IS_IPC(conn)) {
5424 switch (tran_call) {
5425 /* List the allowed trans2 calls on IPC$ */
5426 case TRANSACT2_OPEN:
5427 case TRANSACT2_GET_DFS_REFERRAL:
5428 case TRANSACT2_QFILEINFO:
5429 case TRANSACT2_QFSINFO:
5430 case TRANSACT2_SETFSINFO:
5431 break;
5432 default:
5433 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5434 END_PROFILE(SMBtrans2);
5435 return;
5439 if ((state = talloc(conn, struct trans_state)) == NULL) {
5440 DEBUG(0, ("talloc failed\n"));
5441 reply_nterror(req, NT_STATUS_NO_MEMORY);
5442 END_PROFILE(SMBtrans2);
5443 return;
5446 state->cmd = SMBtrans2;
5448 state->mid = req->mid;
5449 state->vuid = req->vuid;
5450 state->setup_count = SVAL(req->vwv+13, 0);
5451 state->setup = NULL;
5452 state->total_param = SVAL(req->vwv+0, 0);
5453 state->param = NULL;
5454 state->total_data = SVAL(req->vwv+1, 0);
5455 state->data = NULL;
5456 state->max_param_return = SVAL(req->vwv+2, 0);
5457 state->max_data_return = SVAL(req->vwv+3, 0);
5458 state->max_setup_return = SVAL(req->vwv+4, 0);
5459 state->close_on_completion = BITSETW(req->vwv+5, 0);
5460 state->one_way = BITSETW(req->vwv+5, 1);
5462 state->call = tran_call;
5464 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5465 is so as a sanity check */
5466 if (state->setup_count != 1) {
5468 * Need to have rc=0 for ioctl to get job id for OS/2.
5469 * Network printing will fail if function is not successful.
5470 * Similar function in reply.c will be used if protocol
5471 * is LANMAN1.0 instead of LM1.2X002.
5472 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5473 * outbuf doesn't have to be set(only job id is used).
5475 if ( (state->setup_count == 4)
5476 && (tran_call == TRANSACT2_IOCTL)
5477 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
5478 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
5479 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5480 } else {
5481 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5482 DEBUG(2,("Transaction is %d\n",tran_call));
5483 TALLOC_FREE(state);
5484 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5485 END_PROFILE(SMBtrans2);
5486 return;
5490 if ((dscnt > state->total_data) || (pscnt > state->total_param))
5491 goto bad_param;
5493 if (state->total_data) {
5495 if (smb_buffer_oob(state->total_data, 0, dscnt)
5496 || smb_buffer_oob(smb_len(req->inbuf), dsoff, dscnt)) {
5497 goto bad_param;
5500 /* Can't use talloc here, the core routines do realloc on the
5501 * params and data. */
5502 state->data = (char *)SMB_MALLOC(state->total_data);
5503 if (state->data == NULL) {
5504 DEBUG(0,("reply_trans2: data malloc fail for %u "
5505 "bytes !\n", (unsigned int)state->total_data));
5506 TALLOC_FREE(state);
5507 reply_nterror(req, NT_STATUS_NO_MEMORY);
5508 END_PROFILE(SMBtrans2);
5509 return;
5512 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
5515 if (state->total_param) {
5517 if (smb_buffer_oob(state->total_param, 0, pscnt)
5518 || smb_buffer_oob(smb_len(req->inbuf), psoff, pscnt)) {
5519 goto bad_param;
5522 /* Can't use talloc here, the core routines do realloc on the
5523 * params and data. */
5524 state->param = (char *)SMB_MALLOC(state->total_param);
5525 if (state->param == NULL) {
5526 DEBUG(0,("reply_trans: param malloc fail for %u "
5527 "bytes !\n", (unsigned int)state->total_param));
5528 SAFE_FREE(state->data);
5529 TALLOC_FREE(state);
5530 reply_nterror(req, NT_STATUS_NO_MEMORY);
5531 END_PROFILE(SMBtrans2);
5532 return;
5535 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
5538 state->received_data = dscnt;
5539 state->received_param = pscnt;
5541 if ((state->received_param == state->total_param) &&
5542 (state->received_data == state->total_data)) {
5544 handle_trans2(conn, req, state);
5546 SAFE_FREE(state->data);
5547 SAFE_FREE(state->param);
5548 TALLOC_FREE(state);
5549 END_PROFILE(SMBtrans2);
5550 return;
5553 DLIST_ADD(conn->pending_trans, state);
5555 /* We need to send an interim response then receive the rest
5556 of the parameter/data bytes */
5557 reply_smb1_outbuf(req, 0, 0);
5558 show_msg((char *)req->outbuf);
5559 END_PROFILE(SMBtrans2);
5560 return;
5562 bad_param:
5564 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5565 SAFE_FREE(state->data);
5566 SAFE_FREE(state->param);
5567 TALLOC_FREE(state);
5568 END_PROFILE(SMBtrans2);
5569 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5572 /****************************************************************************
5573 Reply to a SMBtranss2
5574 ****************************************************************************/
5576 void reply_transs2(struct smb_request *req)
5578 connection_struct *conn = req->conn;
5579 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5580 struct trans_state *state;
5582 START_PROFILE(SMBtranss2);
5584 show_msg((const char *)req->inbuf);
5586 /* Windows clients expect all replies to
5587 a transact secondary (SMBtranss2 0x33)
5588 to have a command code of transact
5589 (SMBtrans2 0x32). See bug #8989
5590 and also [MS-CIFS] section 2.2.4.47.2
5591 for details.
5593 req->cmd = SMBtrans2;
5595 if (req->wct < 8) {
5596 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5597 END_PROFILE(SMBtranss2);
5598 return;
5601 for (state = conn->pending_trans; state != NULL;
5602 state = state->next) {
5603 if (state->mid == req->mid) {
5604 break;
5608 if ((state == NULL) || (state->cmd != SMBtrans2)) {
5609 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5610 END_PROFILE(SMBtranss2);
5611 return;
5614 /* Revise state->total_param and state->total_data in case they have
5615 changed downwards */
5617 if (SVAL(req->vwv+0, 0) < state->total_param)
5618 state->total_param = SVAL(req->vwv+0, 0);
5619 if (SVAL(req->vwv+1, 0) < state->total_data)
5620 state->total_data = SVAL(req->vwv+1, 0);
5622 pcnt = SVAL(req->vwv+2, 0);
5623 poff = SVAL(req->vwv+3, 0);
5624 pdisp = SVAL(req->vwv+4, 0);
5626 dcnt = SVAL(req->vwv+5, 0);
5627 doff = SVAL(req->vwv+6, 0);
5628 ddisp = SVAL(req->vwv+7, 0);
5630 state->received_param += pcnt;
5631 state->received_data += dcnt;
5633 if ((state->received_data > state->total_data) ||
5634 (state->received_param > state->total_param))
5635 goto bad_param;
5637 if (pcnt) {
5638 if (smb_buffer_oob(state->total_param, pdisp, pcnt)
5639 || smb_buffer_oob(smb_len(req->inbuf), poff, pcnt)) {
5640 goto bad_param;
5642 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
5645 if (dcnt) {
5646 if (smb_buffer_oob(state->total_data, ddisp, dcnt)
5647 || smb_buffer_oob(smb_len(req->inbuf), doff, dcnt)) {
5648 goto bad_param;
5650 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
5653 if ((state->received_param < state->total_param) ||
5654 (state->received_data < state->total_data)) {
5655 END_PROFILE(SMBtranss2);
5656 return;
5659 handle_trans2(conn, req, state);
5661 DLIST_REMOVE(conn->pending_trans, state);
5662 SAFE_FREE(state->data);
5663 SAFE_FREE(state->param);
5664 TALLOC_FREE(state);
5666 END_PROFILE(SMBtranss2);
5667 return;
5669 bad_param:
5671 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5672 DLIST_REMOVE(conn->pending_trans, state);
5673 SAFE_FREE(state->data);
5674 SAFE_FREE(state->param);
5675 TALLOC_FREE(state);
5676 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5677 END_PROFILE(SMBtranss2);
5678 return;