LCOV - code coverage report
Current view: top level - source3/smbd - smb1_trans2.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 1635 2589 63.2 %
Date: 2023-11-21 12:31:41 Functions: 39 45 86.7 %

          Line data    Source code
       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
       9             : 
      10             :    Extensively modified by Andrew Tridgell, 1995
      11             : 
      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.
      16             : 
      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.
      21             : 
      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/>.
      24             : */
      25             : 
      26             : #include "includes.h"
      27             : #include "ntioctl.h"
      28             : #include "system/filesys.h"
      29             : #include "lib/util/time_basic.h"
      30             : #include "version.h"
      31             : #include "smbd/smbd.h"
      32             : #include "smbd/globals.h"
      33             : #include "../libcli/auth/libcli_auth.h"
      34             : #include "../librpc/gen_ndr/xattr.h"
      35             : #include "../librpc/gen_ndr/ndr_security.h"
      36             : #include "libcli/security/security.h"
      37             : #include "trans2.h"
      38             : #include "auth.h"
      39             : #include "smbprofile.h"
      40             : #include "rpc_server/srv_pipe_hnd.h"
      41             : #include "printing.h"
      42             : #include "lib/util_ea.h"
      43             : #include "lib/readdir_attr.h"
      44             : #include "messages.h"
      45             : #include "libcli/smb/smb2_posix.h"
      46             : #include "lib/util/string_wrappers.h"
      47             : #include "source3/lib/substitute.h"
      48             : #include "source3/lib/adouble.h"
      49             : 
      50             : #define DIR_ENTRY_SAFETY_MARGIN 4096
      51             : 
      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             : ****************************************************************************/
      58             : 
      59       29486 : 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)
      67             : {
      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 */
      73             : 
      74       29486 :         int data_to_send = datasize;
      75       29486 :         int params_to_send = paramsize;
      76        1172 :         int useable_space;
      77       29486 :         const char *pp = params;
      78       29486 :         const char *pd = pdata;
      79        1172 :         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
      80       29486 :         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
      81       29486 :         int data_alignment_offset = 0;
      82       29486 :         bool overflow = False;
      83       29486 :         struct smbXsrv_connection *xconn = req->xconn;
      84       29486 :         int max_send = xconn->smb1.sessions.max_send;
      85             : 
      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. */
      90             : 
      91       29486 :         if (max_data_bytes > 0 && datasize > max_data_bytes) {
      92           0 :                 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
      93             :                         max_data_bytes, datasize ));
      94           0 :                 datasize = data_to_send = max_data_bytes;
      95           0 :                 overflow = True;
      96             :         }
      97             : 
      98             :         /* If there genuinely are no parameters or data to send just send the empty packet */
      99             : 
     100       29486 :         if(params_to_send == 0 && data_to_send == 0) {
     101           0 :                 reply_smb1_outbuf(req, 10, 0);
     102           0 :                 if (NT_STATUS_V(status)) {
     103           0 :                         uint8_t eclass;
     104           0 :                         uint32_t ecode;
     105           0 :                         ntstatus_to_dos(status, &eclass, &ecode);
     106           0 :                         error_packet_set((char *)req->outbuf,
     107             :                                         eclass, ecode, status,
     108             :                                         __LINE__,__FILE__);
     109             :                 }
     110           0 :                 show_msg((char *)req->outbuf);
     111           0 :                 if (!smb1_srv_send(xconn,
     112           0 :                                    (char *)req->outbuf,
     113             :                                    true,
     114           0 :                                    req->seqnum + 1,
     115           0 :                                    IS_CONN_ENCRYPTED(conn))) {
     116           0 :                         exit_server_cleanly("send_trans2_replies: smb1_srv_send failed.");
     117             :                 }
     118           0 :                 TALLOC_FREE(req->outbuf);
     119           0 :                 return;
     120             :         }
     121             : 
     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. */
     125             : 
     126       29486 :         if (((params_to_send % 4) != 0) && (data_to_send != 0))
     127       19725 :                 data_alignment_offset = 4 - (params_to_send % 4);
     128             : 
     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. */
     132             : 
     133       29486 :         useable_space = max_send - (smb_size
     134             :                                     + 2 * 10 /* wct */
     135       28314 :                                     + alignment_offset
     136       29486 :                                     + data_alignment_offset);
     137             : 
     138       29486 :         if (useable_space < 0) {
     139           0 :                 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
     140             :                           "= %d!!!\n", useable_space));
     141           0 :                 exit_server_cleanly("send_trans2_replies: Not enough space");
     142             :         }
     143             : 
     144       59000 :         while (params_to_send || data_to_send) {
     145             :                 /* Calculate whether we will totally or partially fill this packet */
     146             : 
     147       29514 :                 total_sent_thistime = params_to_send + data_to_send;
     148             : 
     149             :                 /* We can never send more than useable_space */
     150             :                 /*
     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.
     155             :                  */
     156             : 
     157       29514 :                 total_sent_thistime = MIN(total_sent_thistime, useable_space);
     158             : 
     159       29514 :                 reply_smb1_outbuf(req, 10, total_sent_thistime + alignment_offset
     160       29514 :                              + data_alignment_offset);
     161             : 
     162             :                 /* Set total params and data to be sent */
     163       29514 :                 SSVAL(req->outbuf,smb_tprcnt,paramsize);
     164       29514 :                 SSVAL(req->outbuf,smb_tdrcnt,datasize);
     165             : 
     166             :                 /* Calculate how many parameters and data we can fit into
     167             :                  * this packet. Parameters get precedence
     168             :                  */
     169             : 
     170       29514 :                 params_sent_thistime = MIN(params_to_send,useable_space);
     171       29514 :                 data_sent_thistime = useable_space - params_sent_thistime;
     172       29514 :                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
     173             : 
     174       29514 :                 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
     175             : 
     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 */
     180             : 
     181       29514 :                 SSVAL(req->outbuf,smb_proff,
     182             :                       ((smb_buf(req->outbuf)+alignment_offset)
     183             :                        - smb_base(req->outbuf)));
     184             : 
     185       29514 :                 if(params_sent_thistime == 0)
     186        3111 :                         SSVAL(req->outbuf,smb_prdisp,0);
     187             :                 else
     188             :                         /* Absolute displacement of param bytes sent in this packet */
     189       26403 :                         SSVAL(req->outbuf,smb_prdisp,pp - params);
     190             : 
     191       29514 :                 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
     192       29514 :                 if(data_sent_thistime == 0) {
     193        5050 :                         SSVAL(req->outbuf,smb_droff,0);
     194        5050 :                         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       24464 :                         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       24464 :                         SSVAL(req->outbuf,smb_drdisp, pd - pdata);
     203             :                 }
     204             : 
     205             :                 /* Initialize the padding for alignment */
     206             : 
     207       29514 :                 if (alignment_offset != 0) {
     208       29514 :                         memset(smb_buf(req->outbuf), 0, alignment_offset);
     209             :                 }
     210             : 
     211             :                 /* Copy the param bytes into the packet */
     212             : 
     213       29514 :                 if(params_sent_thistime) {
     214       26403 :                         memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
     215             :                                params_sent_thistime);
     216             :                 }
     217             : 
     218             :                 /* Copy in the data bytes */
     219       29514 :                 if(data_sent_thistime) {
     220       24464 :                         if (data_alignment_offset != 0) {
     221       19745 :                                 memset((smb_buf(req->outbuf)+alignment_offset+
     222             :                                         params_sent_thistime), 0,
     223             :                                        data_alignment_offset);
     224             :                         }
     225       25636 :                         memcpy(smb_buf(req->outbuf)+alignment_offset
     226       24464 :                                +params_sent_thistime+data_alignment_offset,
     227             :                                pd,data_sent_thistime);
     228             :                 }
     229             : 
     230       29514 :                 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       29514 :                 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));
     234             : 
     235       29514 :                 if (overflow) {
     236           0 :                         error_packet_set((char *)req->outbuf,
     237             :                                          ERRDOS,ERRbufferoverflow,
     238           0 :                                          STATUS_BUFFER_OVERFLOW,
     239             :                                          __LINE__,__FILE__);
     240       29514 :                 } else if (NT_STATUS_V(status)) {
     241          47 :                         uint8_t eclass;
     242          47 :                         uint32_t ecode;
     243         235 :                         ntstatus_to_dos(status, &eclass, &ecode);
     244         235 :                         error_packet_set((char *)req->outbuf,
     245             :                                         eclass, ecode, status,
     246             :                                         __LINE__,__FILE__);
     247             :                 }
     248             : 
     249             :                 /* Send the packet */
     250       29514 :                 show_msg((char *)req->outbuf);
     251       29514 :                 if (!smb1_srv_send(xconn,
     252       29514 :                                    (char *)req->outbuf,
     253             :                                    true,
     254       29514 :                                    req->seqnum + 1,
     255       29514 :                                    IS_CONN_ENCRYPTED(conn))) {
     256           0 :                         exit_server_cleanly("send_trans2_replies: smb1_srv_send failed.");
     257             :                 }
     258             : 
     259       29514 :                 TALLOC_FREE(req->outbuf);
     260             : 
     261       29514 :                 pp += params_sent_thistime;
     262       29514 :                 pd += data_sent_thistime;
     263             : 
     264       29514 :                 params_to_send -= params_sent_thistime;
     265       29514 :                 data_to_send -= data_sent_thistime;
     266             : 
     267             :                 /* Sanity check */
     268       29514 :                 if(params_to_send < 0 || data_to_send < 0) {
     269           0 :                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
     270             :                                 params_to_send, data_to_send));
     271           0 :                         return;
     272             :                 }
     273             :         }
     274             : 
     275       28314 :         return;
     276             : }
     277             : 
     278             : /****************************************************************************
     279             :  Deal with SMB_SET_POSIX_LOCK.
     280             : ****************************************************************************/
     281             : 
     282             : static void smb_set_posix_lock_done(struct tevent_req *subreq);
     283             : 
     284          36 : 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)
     289             : {
     290          36 :         struct tevent_req *subreq = NULL;
     291          36 :         struct smbd_lock_element *lck = NULL;
     292           0 :         uint64_t count;
     293           0 :         uint64_t offset;
     294           0 :         uint64_t smblctx;
     295          36 :         bool blocking_lock = False;
     296           0 :         enum brl_type lock_type;
     297             : 
     298          36 :         NTSTATUS status = NT_STATUS_OK;
     299             : 
     300          36 :         if (!CAN_WRITE(conn)) {
     301           0 :                 return NT_STATUS_DOS(ERRSRV, ERRaccess);
     302             :         }
     303             : 
     304          36 :         if (fsp == NULL ||
     305          36 :             fsp->fsp_flags.is_pathref ||
     306          36 :             fsp_get_io_fd(fsp) == -1)
     307             :         {
     308           0 :                 return NT_STATUS_INVALID_HANDLE;
     309             :         }
     310             : 
     311          36 :         if (total_data != POSIX_LOCK_DATA_SIZE) {
     312           0 :                 return NT_STATUS_INVALID_PARAMETER;
     313             :         }
     314             : 
     315          36 :         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
     316           4 :                 case POSIX_LOCK_TYPE_READ:
     317           4 :                         lock_type = READ_LOCK;
     318           4 :                         break;
     319          24 :                 case POSIX_LOCK_TYPE_WRITE:
     320             :                         /* Return the right POSIX-mappable error code for files opened read-only. */
     321          24 :                         if (!fsp->fsp_flags.can_write) {
     322           0 :                                 return NT_STATUS_INVALID_HANDLE;
     323             :                         }
     324          24 :                         lock_type = WRITE_LOCK;
     325          24 :                         break;
     326           8 :                 case POSIX_LOCK_TYPE_UNLOCK:
     327           8 :                         lock_type = UNLOCK_LOCK;
     328           8 :                         break;
     329           0 :                 default:
     330           0 :                         return NT_STATUS_INVALID_PARAMETER;
     331             :         }
     332             : 
     333          36 :         switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
     334          28 :         case POSIX_LOCK_FLAG_NOWAIT:
     335          28 :                 blocking_lock = false;
     336          28 :                 break;
     337           8 :         case POSIX_LOCK_FLAG_WAIT:
     338           8 :                 blocking_lock = true;
     339           8 :                 break;
     340           0 :         default:
     341           0 :                 return NT_STATUS_INVALID_PARAMETER;
     342             :         }
     343             : 
     344          36 :         if (!lp_blocking_locks(SNUM(conn))) {
     345           0 :                 blocking_lock = False;
     346             :         }
     347             : 
     348          36 :         smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
     349          36 :         offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
     350          36 :                         ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
     351          36 :         count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
     352          36 :                         ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
     353             : 
     354          36 :         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);
     361             : 
     362          36 :         if (lock_type == UNLOCK_LOCK) {
     363           8 :                 struct smbd_lock_element l = {
     364           8 :                         .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,
     370             :                 };
     371           8 :                 status = smbd_do_unlocking(req, fsp, 1, &l);
     372           8 :                 return status;
     373             :         }
     374             : 
     375          28 :         lck = talloc(req, struct smbd_lock_element);
     376          28 :         if (lck == NULL) {
     377           0 :                 return NT_STATUS_NO_MEMORY;
     378             :         }
     379             : 
     380          28 :         *lck = (struct smbd_lock_element) {
     381          28 :                 .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,
     387             :         };
     388             : 
     389          28 :         subreq = smbd_smb1_do_locks_send(
     390             :                 fsp,
     391          28 :                 req->sconn->ev_ctx,
     392             :                 &req,
     393             :                 fsp,
     394             :                 blocking_lock ? UINT32_MAX : 0,
     395             :                 true,           /* large_offset */
     396             :                 1,
     397             :                 lck);
     398          28 :         if (subreq == NULL) {
     399           0 :                 TALLOC_FREE(lck);
     400           0 :                 return NT_STATUS_NO_MEMORY;
     401             :         }
     402          28 :         tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
     403          28 :         return NT_STATUS_EVENT_PENDING;
     404             : }
     405             : 
     406          28 : static void smb_set_posix_lock_done(struct tevent_req *subreq)
     407             : {
     408          28 :         struct smb_request *req = NULL;
     409           0 :         NTSTATUS status;
     410           0 :         bool ok;
     411             : 
     412          28 :         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
     413          28 :         SMB_ASSERT(ok);
     414             : 
     415          28 :         status = smbd_smb1_do_locks_recv(subreq);
     416          28 :         TALLOC_FREE(subreq);
     417             : 
     418          28 :         if (NT_STATUS_IS_OK(status)) {
     419          24 :                 char params[2] = {0};
     420             :                 /* Fake up max_data_bytes here - we know it fits. */
     421          24 :                 send_trans2_replies(
     422          24 :                         req->conn,
     423             :                         req,
     424          24 :                         NT_STATUS_OK,
     425             :                         params,
     426             :                         2,
     427             :                         NULL,
     428             :                         0,
     429             :                         0xffff);
     430             :         } else {
     431           4 :                 reply_nterror(req, status);
     432           4 :                 ok = smb1_srv_send(req->xconn,
     433           4 :                                    (char *)req->outbuf,
     434             :                                    true,
     435           4 :                                    req->seqnum + 1,
     436           4 :                                    IS_CONN_ENCRYPTED(req->conn));
     437           4 :                 if (!ok) {
     438           0 :                         exit_server_cleanly("smb_set_posix_lock_done: "
     439             :                                             "smb1_srv_send failed.");
     440             :                 }
     441             :         }
     442             : 
     443          28 :         TALLOC_FREE(req);
     444          28 :         return;
     445             : }
     446             : 
     447             : /****************************************************************************
     448             :  Read a list of EA names from an incoming data buffer. Create an ea_list with them.
     449             : ****************************************************************************/
     450             : 
     451         164 : static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
     452             : {
     453         164 :         struct ea_list *ea_list_head = NULL;
     454         164 :         size_t converted_size, offset = 0;
     455             : 
     456         340 :         while (offset + 2 < data_size) {
     457         176 :                 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
     458         176 :                 unsigned int namelen = CVAL(pdata,offset);
     459             : 
     460         176 :                 offset++; /* Go past the namelen byte. */
     461             : 
     462             :                 /* integer wrap paranioa. */
     463         176 :                 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
     464         176 :                                 (offset > data_size) || (namelen > data_size) ||
     465         148 :                                 (offset + namelen >= data_size)) {
     466             :                         break;
     467             :                 }
     468             :                 /* Ensure the name is null terminated. */
     469         176 :                 if (pdata[offset + namelen] != '\0') {
     470           0 :                         return NULL;
     471             :                 }
     472         176 :                 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
     473             :                                        &converted_size)) {
     474           0 :                         DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
     475             :                                  "failed: %s\n", strerror(errno)));
     476             :                 }
     477         176 :                 if (!eal->ea.name) {
     478           0 :                         return NULL;
     479             :                 }
     480             : 
     481         176 :                 offset += (namelen + 1); /* Go past the name + terminating zero. */
     482         176 :                 DLIST_ADD_END(ea_list_head, eal);
     483         176 :                 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
     484             :         }
     485             : 
     486         136 :         return ea_list_head;
     487             : }
     488             : 
     489             : /****************************************************************************
     490             :  Reply to a TRANSACT2_OPEN.
     491             : ****************************************************************************/
     492             : 
     493          98 : 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)
     498             : {
     499          98 :         struct smb_filename *smb_fname = NULL;
     500          98 :         char *params = *pparams;
     501          98 :         char *pdata = *ppdata;
     502          18 :         int deny_mode;
     503          18 :         int32_t open_attr;
     504          18 :         bool oplock_request;
     505             : #if 0
     506             :         bool return_additional_info;
     507             :         int16 open_sattr;
     508             :         time_t open_time;
     509             : #endif
     510          18 :         int open_ofun;
     511          18 :         uint32_t open_size;
     512          18 :         char *pname;
     513          98 :         char *fname = NULL;
     514          98 :         off_t size=0;
     515          98 :         int fattr=0,mtime=0;
     516          98 :         SMB_INO_T inode = 0;
     517          98 :         int smb_action = 0;
     518          98 :         struct files_struct *dirfsp = NULL;
     519          18 :         files_struct *fsp;
     520          98 :         struct ea_list *ea_list = NULL;
     521          98 :         uint16_t flags = 0;
     522          18 :         NTSTATUS status;
     523          18 :         uint32_t access_mask;
     524          18 :         uint32_t share_mode;
     525          18 :         uint32_t create_disposition;
     526          98 :         uint32_t create_options = 0;
     527          98 :         uint32_t private_flags = 0;
     528          98 :         NTTIME twrp = 0;
     529          98 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
     530          98 :         TALLOC_CTX *ctx = talloc_tos();
     531             : 
     532             :         /*
     533             :          * Ensure we have enough parameters to perform the operation.
     534             :          */
     535             : 
     536          98 :         if (total_params < 29) {
     537           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     538           0 :                 goto out;
     539             :         }
     540             : 
     541          98 :         flags = SVAL(params, 0);
     542          98 :         deny_mode = SVAL(params, 2);
     543          98 :         open_attr = SVAL(params,6);
     544          98 :         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
     545          98 :         if (oplock_request) {
     546           0 :                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
     547             :         }
     548             : 
     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          98 :         open_ofun = SVAL(params,12);
     555          98 :         open_size = IVAL(params,14);
     556          98 :         pname = &params[28];
     557             : 
     558          98 :         if (IS_IPC(conn)) {
     559           0 :                 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
     560           0 :                 goto out;
     561             :         }
     562             : 
     563          98 :         if (req->posix_pathnames) {
     564           0 :                 srvstr_get_path_posix(ctx,
     565             :                         params,
     566           0 :                         req->flags2,
     567             :                         &fname,
     568             :                         pname,
     569           0 :                         total_params - 28,
     570             :                         STR_TERMINATE,
     571             :                         &status);
     572             :         } else {
     573          98 :                 srvstr_get_path(ctx,
     574             :                         params,
     575          98 :                         req->flags2,
     576             :                         &fname,
     577             :                         pname,
     578          98 :                         total_params - 28,
     579             :                         STR_TERMINATE,
     580             :                         &status);
     581             :         }
     582          98 :         if (!NT_STATUS_IS_OK(status)) {
     583           0 :                 reply_nterror(req, status);
     584           0 :                 goto out;
     585             :         }
     586             : 
     587          98 :         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));
     590             : 
     591          98 :         if (ucf_flags & UCF_GMT_PATHNAME) {
     592           0 :                 extract_snapshot_token(fname, &twrp);
     593             :         }
     594          98 :         status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
     595          98 :         if (!NT_STATUS_IS_OK(status)) {
     596           0 :                 reply_nterror(req, status);
     597           0 :                 goto out;
     598             :         }
     599          98 :         status = filename_convert_dirfsp(ctx,
     600             :                                          conn,
     601             :                                          fname,
     602             :                                          ucf_flags,
     603             :                                          twrp,
     604             :                                          &dirfsp,
     605             :                                          &smb_fname);
     606          98 :         if (!NT_STATUS_IS_OK(status)) {
     607           0 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
     608           0 :                         reply_botherror(req,
     609             :                                 NT_STATUS_PATH_NOT_COVERED,
     610             :                                 ERRSRV, ERRbadpath);
     611           0 :                         goto out;
     612             :                 }
     613           0 :                 reply_nterror(req, status);
     614           0 :                 goto out;
     615             :         }
     616             : 
     617          98 :         if (open_ofun == 0) {
     618          10 :                 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
     619          10 :                 goto out;
     620             :         }
     621             : 
     622          88 :         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           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
     629           0 :                 goto out;
     630             :         }
     631             : 
     632             :         /* Any data in this call is an EA list. */
     633          88 :         if (total_data && (total_data != 4)) {
     634          88 :                 if (total_data < 10) {
     635           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     636           0 :                         goto out;
     637             :                 }
     638             : 
     639          88 :                 if (IVAL(pdata,0) > total_data) {
     640           0 :                         DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
     641             :                                 IVAL(pdata,0), (unsigned int)total_data));
     642           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     643           0 :                         goto out;
     644             :                 }
     645             : 
     646          88 :                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
     647          88 :                                        total_data - 4);
     648          88 :                 if (!ea_list) {
     649           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     650           0 :                         goto out;
     651             :                 }
     652             : 
     653          88 :                 if (!lp_ea_support(SNUM(conn))) {
     654           0 :                         reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
     655           0 :                         goto out;
     656             :                 }
     657             : 
     658         176 :                 if (!req->posix_pathnames &&
     659          88 :                                 ea_list_has_invalid_name(ea_list)) {
     660           0 :                         int param_len = 30;
     661           0 :                         *pparams = (char *)SMB_REALLOC(*pparams, param_len);
     662           0 :                         if(*pparams == NULL ) {
     663           0 :                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     664           0 :                                 goto out;
     665             :                         }
     666           0 :                         params = *pparams;
     667           0 :                         memset(params, '\0', param_len);
     668           0 :                         send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
     669             :                                 params, param_len, NULL, 0, max_data_bytes);
     670           0 :                         goto out;
     671             :                 }
     672             :         }
     673             : 
     674          88 :         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 */
     693             : 
     694          88 :         if (!NT_STATUS_IS_OK(status)) {
     695          33 :                 if (open_was_deferred(req->xconn, req->mid)) {
     696             :                         /* We have re-scheduled this call. */
     697           0 :                         goto out;
     698             :                 }
     699             : 
     700          33 :                 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
     701          23 :                         reply_openerror(req, status);
     702          23 :                         goto out;
     703             :                 }
     704             : 
     705          10 :                 fsp = fcb_or_dos_open(
     706             :                         req,
     707             :                         smb_fname,
     708             :                         access_mask,
     709             :                         create_options,
     710             :                         private_flags);
     711          10 :                 if (fsp == NULL) {
     712          10 :                         bool ok = defer_smb1_sharing_violation(req);
     713          10 :                         if (ok) {
     714           5 :                                 goto out;
     715             :                         }
     716           5 :                         reply_openerror(req, status);
     717           5 :                         goto out;
     718             :                 }
     719             : 
     720           0 :                 smb_action = FILE_WAS_OPENED;
     721             :         }
     722             : 
     723          55 :         size = get_file_size_stat(&smb_fname->st);
     724          55 :         fattr = fdos_mode(fsp);
     725          55 :         mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
     726          55 :         inode = smb_fname->st.st_ex_ino;
     727          55 :         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
     728           0 :                 close_file_free(req, &fsp, ERROR_CLOSE);
     729           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
     730           0 :                 goto out;
     731             :         }
     732             : 
     733             :         /* Realloc the size of parameters and data we will return */
     734          55 :         *pparams = (char *)SMB_REALLOC(*pparams, 30);
     735          55 :         if(*pparams == NULL ) {
     736           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     737           0 :                 goto out;
     738             :         }
     739          55 :         params = *pparams;
     740             : 
     741          55 :         SSVAL(params,0,fsp->fnum);
     742          55 :         SSVAL(params,2,fattr);
     743          55 :         srv_put_dos_date2(params,4, mtime);
     744          55 :         SIVAL(params,8, (uint32_t)size);
     745          55 :         SSVAL(params,12,deny_mode);
     746          55 :         SSVAL(params,14,0); /* open_type - file or directory. */
     747          55 :         SSVAL(params,16,0); /* open_state - only valid for IPC device. */
     748             : 
     749          55 :         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
     750           0 :                 smb_action |= EXTENDED_OPLOCK_GRANTED;
     751             :         }
     752             : 
     753          55 :         SSVAL(params,18,smb_action);
     754             : 
     755             :         /*
     756             :          * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
     757             :          */
     758          55 :         SIVAL(params,20,inode);
     759          55 :         SSVAL(params,24,0); /* Padding. */
     760          55 :         if (flags & 8) {
     761           0 :                 uint32_t ea_size = estimate_ea_size(smb_fname->fsp);
     762           0 :                 SIVAL(params, 26, ea_size);
     763             :         } else {
     764          55 :                 SIVAL(params, 26, 0);
     765             :         }
     766             : 
     767             :         /* Send the required number of replies */
     768          55 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
     769          98 :  out:
     770          98 :         TALLOC_FREE(smb_fname);
     771          98 : }
     772             : 
     773      206885 : 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)
     789             : {
     790      206885 :         uint8_t align = 4;
     791      206885 :         const bool do_pad = true;
     792             : 
     793      206885 :         if (info_level >= 1 && info_level <= 3) {
     794             :                 /* No alignment on earlier info levels. */
     795      114822 :                 align = 1;
     796             :         }
     797             : 
     798      206885 :         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);
     806             : }
     807             : 
     808             : /****************************************************************************
     809             :  Reply to a TRANS2_FINDFIRST.
     810             : ****************************************************************************/
     811             : 
     812        8712 : 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)
     817             : {
     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        8712 :         struct smb_filename *smb_dname = NULL;
     824        8712 :         char *params = *pparams;
     825        8712 :         char *pdata = *ppdata;
     826         175 :         char *data_end;
     827         175 :         uint32_t dirtype;
     828         175 :         int maxentries;
     829         175 :         uint16_t findfirst_flags;
     830         175 :         bool close_after_first;
     831         175 :         bool close_if_end;
     832         175 :         bool requires_resume_key;
     833         175 :         int info_level;
     834        8712 :         char *directory = NULL;
     835        8712 :         char *mask = NULL;
     836         175 :         char *p;
     837        8712 :         int last_entry_off=0;
     838        8712 :         int dptr_num = -1;
     839        8712 :         int numentries = 0;
     840         175 :         int i;
     841        8712 :         bool finished = False;
     842        8712 :         bool dont_descend = False;
     843        8712 :         bool out_of_space = False;
     844         175 :         int space_remaining;
     845        8712 :         struct ea_list *ea_list = NULL;
     846        8712 :         NTSTATUS ntstatus = NT_STATUS_OK;
     847         175 :         bool ask_sharemode;
     848        8712 :         struct smbXsrv_connection *xconn = req->xconn;
     849        8712 :         struct smbd_server_connection *sconn = req->sconn;
     850        8712 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
     851        8712 :         bool backup_priv = false;
     852        8712 :         bool as_root = false;
     853        8712 :         files_struct *fsp = NULL;
     854        8712 :         struct files_struct *dirfsp = NULL;
     855         175 :         const struct loadparm_substitution *lp_sub =
     856        8712 :                 loadparm_s3_global_substitution();
     857             : 
     858        8712 :         if (total_params < 13) {
     859           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     860           0 :                 goto out;
     861             :         }
     862             : 
     863        8712 :         dirtype = SVAL(params,0);
     864        8712 :         maxentries = SVAL(params,2);
     865        8712 :         findfirst_flags = SVAL(params,4);
     866        8712 :         close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
     867        8712 :         close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
     868        8712 :         requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
     869        8718 :         backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
     870           6 :                                 security_token_has_privilege(get_current_nttok(conn),
     871             :                                                 SEC_PRIV_BACKUP));
     872             : 
     873        8712 :         info_level = SVAL(params,6);
     874             : 
     875        8712 :         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);
     887             : 
     888        8712 :         if (!maxentries) {
     889             :                 /* W2K3 seems to treat zero as 1. */
     890          12 :                 maxentries = 1;
     891             :         }
     892             : 
     893        8712 :         switch (info_level) {
     894        8521 :                 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        8696 :                         break;
     904          16 :                 case SMB_FIND_FILE_UNIX:
     905             :                 case SMB_FIND_FILE_UNIX_INFO2:
     906          16 :                         if (!lp_smb1_unix_extensions()) {
     907           0 :                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
     908           0 :                                 goto out;
     909             :                         }
     910          16 :                         if (!req->posix_pathnames) {
     911           0 :                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
     912           0 :                                 goto out;
     913             :                         }
     914          16 :                         break;
     915           0 :                 default:
     916           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
     917           0 :                         goto out;
     918             :         }
     919             : 
     920        8712 :         if (req->posix_pathnames) {
     921         186 :                 srvstr_get_path_posix(talloc_tos(),
     922             :                                 params,
     923         186 :                                 req->flags2,
     924             :                                 &directory,
     925         186 :                                 params+12,
     926         186 :                                 total_params - 12,
     927             :                                 STR_TERMINATE,
     928             :                                 &ntstatus);
     929             :         } else {
     930        8526 :                 srvstr_get_path(talloc_tos(),
     931             :                                 params,
     932        8526 :                                 req->flags2,
     933             :                                 &directory,
     934        8526 :                                 params+12,
     935        8526 :                                 total_params - 12,
     936             :                                 STR_TERMINATE,
     937             :                                 &ntstatus);
     938             :         }
     939        8712 :         if (!NT_STATUS_IS_OK(ntstatus)) {
     940           0 :                 reply_nterror(req, ntstatus);
     941           0 :                 goto out;
     942             :         }
     943             : 
     944        8712 :         if (backup_priv) {
     945           0 :                 become_root();
     946           0 :                 as_root = true;
     947             :         }
     948        8712 :         ntstatus = smb1_strip_dfs_path(talloc_tos(), &ucf_flags, &directory);
     949        8712 :         if (!NT_STATUS_IS_OK(ntstatus)) {
     950           0 :                 reply_nterror(req, ntstatus);
     951           0 :                 goto out;
     952             :         }
     953             : 
     954        8712 :         ntstatus = filename_convert_smb1_search_path(talloc_tos(),
     955             :                                                      conn,
     956             :                                                      directory,
     957             :                                                      ucf_flags,
     958             :                                                      &dirfsp,
     959             :                                                      &smb_dname,
     960             :                                                      &mask);
     961             : 
     962        8712 :         if (!NT_STATUS_IS_OK(ntstatus)) {
     963         114 :                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
     964           0 :                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
     965             :                                         ERRSRV, ERRbadpath);
     966           0 :                         goto out;
     967             :                 }
     968         114 :                 reply_nterror(req, ntstatus);
     969         114 :                 goto out;
     970             :         }
     971             : 
     972        8598 :         TALLOC_FREE(directory);
     973        8598 :         directory = smb_dname->base_name;
     974             : 
     975        8598 :         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
     976             : 
     977        8598 :         if (info_level == SMB_FIND_EA_LIST) {
     978           0 :                 uint32_t ea_size;
     979             : 
     980           6 :                 if (total_data < 4) {
     981           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     982           0 :                         goto out;
     983             :                 }
     984             : 
     985           6 :                 ea_size = IVAL(pdata,0);
     986           6 :                 if (ea_size != total_data) {
     987           0 :                         DBG_NOTICE("Rejecting EA request with incorrect "
     988             :                                    "total_data=%d (should be %" PRIu32 ")\n",
     989             :                                    total_data,
     990             :                                    ea_size);
     991           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     992           0 :                         goto out;
     993             :                 }
     994             : 
     995           6 :                 if (!lp_ea_support(SNUM(conn))) {
     996           0 :                         reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
     997           0 :                         goto out;
     998             :                 }
     999             : 
    1000             :                 /* Pull out the list of names. */
    1001           6 :                 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
    1002           6 :                 if (!ea_list) {
    1003           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1004           0 :                         goto out;
    1005             :                 }
    1006             :         }
    1007             : 
    1008        8598 :         if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
    1009           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1010           0 :                 goto out;
    1011             :         }
    1012             : 
    1013        8598 :         *ppdata = (char *)SMB_REALLOC(
    1014             :                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
    1015        8598 :         if(*ppdata == NULL ) {
    1016           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    1017           0 :                 goto out;
    1018             :         }
    1019        8598 :         pdata = *ppdata;
    1020        8598 :         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
    1021             :         /*
    1022             :          * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
    1023             :          * error.
    1024             :          */
    1025        8598 :         memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
    1026             :         /* Realloc the params space */
    1027        8598 :         *pparams = (char *)SMB_REALLOC(*pparams, 10);
    1028        8598 :         if (*pparams == NULL) {
    1029           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    1030           0 :                 goto out;
    1031             :         }
    1032        8598 :         params = *pparams;
    1033             : 
    1034             :         /*
    1035             :          * Open an fsp on this directory for the dptr.
    1036             :          */
    1037        8598 :         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 */
    1058             : 
    1059        8598 :         if (!NT_STATUS_IS_OK(ntstatus)) {
    1060         119 :                 DBG_ERR("failed to open directory %s\n",
    1061             :                         smb_fname_str_dbg(smb_dname));
    1062         119 :                 reply_nterror(req, ntstatus);
    1063         119 :                 goto out;
    1064             :         }
    1065             : 
    1066             :         /* Save the wildcard match and attribs we are using on this directory -
    1067             :                 needed as lanman2 assumes these are being saved between calls */
    1068             : 
    1069        8479 :         ntstatus = dptr_create(conn,
    1070             :                                 req,
    1071             :                                 fsp, /* fsp */
    1072             :                                 False,
    1073             :                                 mask,
    1074             :                                 dirtype,
    1075        8479 :                                 &fsp->dptr);
    1076             : 
    1077        8479 :         if (!NT_STATUS_IS_OK(ntstatus)) {
    1078             :                 /*
    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.
    1082             :                  */
    1083           0 :                 close_file_free(NULL, &fsp, NORMAL_CLOSE);
    1084           0 :                 reply_nterror(req, ntstatus);
    1085           0 :                 goto out;
    1086             :         }
    1087             : 
    1088        8479 :         if (backup_priv) {
    1089             :                 /* Remember this in case we have
    1090             :                    to do a findnext. */
    1091           0 :                 dptr_set_priv(fsp->dptr);
    1092             :         }
    1093             : 
    1094        8479 :         dptr_num = dptr_dnum(fsp->dptr);
    1095        8479 :         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
    1096             : 
    1097             :         /* We don't need to check for VOL here as this is returned by
    1098             :                 a different TRANS2 call. */
    1099             : 
    1100        8479 :         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
    1101             :                  directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
    1102        8479 :         if (in_list(directory,
    1103        8479 :                     lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
    1104        8479 :                         dptr_case_sensitive(fsp->dptr))) {
    1105           0 :                 dont_descend = True;
    1106             :         }
    1107             : 
    1108        8479 :         p = pdata;
    1109        8479 :         space_remaining = max_data_bytes;
    1110        8479 :         out_of_space = False;
    1111             : 
    1112        8479 :         ask_sharemode = fsp_search_ask_sharemode(fsp);
    1113             : 
    1114       57760 :         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
    1115             : 
    1116       49107 :                 ntstatus = get_lanman2_dir_entry(talloc_tos(),
    1117             :                                                  conn,
    1118       49107 :                                                  fsp->dptr,
    1119       49107 :                                                  req->flags2,
    1120             :                                                  mask,
    1121             :                                                  dirtype,
    1122             :                                                  info_level,
    1123             :                                                  requires_resume_key,
    1124             :                                                  dont_descend,
    1125             :                                                  ask_sharemode,
    1126             :                                                  &p,
    1127             :                                                  pdata,
    1128             :                                                  data_end,
    1129             :                                                  space_remaining,
    1130             :                                                  &last_entry_off,
    1131             :                                                  ea_list);
    1132       49107 :                 if (NT_STATUS_EQUAL(ntstatus, NT_STATUS_ILLEGAL_CHARACTER)) {
    1133             :                         /*
    1134             :                          * Bad character conversion on name. Ignore
    1135             :                          * this entry.
    1136             :                          */
    1137          12 :                         continue;
    1138             :                 }
    1139       49095 :                 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
    1140           0 :                         out_of_space = true;
    1141             :                 } else {
    1142       49095 :                         finished = !NT_STATUS_IS_OK(ntstatus);
    1143             :                 }
    1144             : 
    1145       49095 :                 if (!finished && !out_of_space) {
    1146       41243 :                         numentries++;
    1147             :                 }
    1148             : 
    1149             :                 /* Ensure space_remaining never goes -ve. */
    1150       49095 :                 if (PTR_DIFF(p,pdata) > max_data_bytes) {
    1151           0 :                         space_remaining = 0;
    1152           0 :                         out_of_space = true;
    1153             :                 } else {
    1154       49095 :                         space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
    1155             :                 }
    1156             :         }
    1157             : 
    1158             :         /* Check if we can close the dirptr */
    1159        8479 :         if(close_after_first || (finished && close_if_end)) {
    1160        8345 :                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
    1161        8345 :                 dptr_num = -1;
    1162        8345 :                 close_file_free(NULL, &fsp, NORMAL_CLOSE);
    1163             :         }
    1164             : 
    1165             :         /*
    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.
    1170             :          */
    1171             : 
    1172        8479 :         if(numentries == 0) {
    1173         541 :                 dptr_num = -1;
    1174             :                 /*
    1175             :                  * We may have already closed the file in the
    1176             :                  * close_after_first or finished case above.
    1177             :                  */
    1178         541 :                 if (fsp != NULL) {
    1179           0 :                         close_file_free(NULL, &fsp, NORMAL_CLOSE);
    1180             :                 }
    1181         541 :                 if (xconn->protocol < PROTOCOL_NT1) {
    1182           0 :                         reply_force_doserror(req, ERRDOS, ERRnofiles);
    1183           0 :                         goto out;
    1184             :                 } else {
    1185         541 :                         reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
    1186             :                                         ERRDOS, ERRbadfile);
    1187         541 :                         goto out;
    1188             :                 }
    1189             :         }
    1190             : 
    1191             :         /* At this point pdata points to numentries directory entries. */
    1192             : 
    1193             :         /* Set up the return parameter block */
    1194        7938 :         SSVAL(params,0,dptr_num);
    1195        7938 :         SSVAL(params,2,numentries);
    1196        7938 :         SSVAL(params,4,finished);
    1197        7938 :         SSVAL(params,6,0); /* Never an EA error */
    1198        7938 :         SSVAL(params,8,last_entry_off);
    1199             : 
    1200        7938 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
    1201             :                             max_data_bytes);
    1202             : 
    1203        7938 :         if ((! *directory) && dptr_path(sconn, dptr_num)) {
    1204           0 :                 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
    1205           0 :                 if (!directory) {
    1206           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    1207             :                 }
    1208             :         }
    1209             : 
    1210        7938 :         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
    1211             :                 smb_fn_name(req->cmd),
    1212             :                 mask, directory, dirtype, numentries ) );
    1213             : 
    1214             :         /*
    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.
    1220             :          */
    1221             : 
    1222        7938 :         if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
    1223         153 :                 char mangled_name[13];
    1224        7800 :                 name_to_8_3(mask, mangled_name, True, conn->params);
    1225             :         }
    1226         138 :  out:
    1227             : 
    1228        8712 :         if (as_root) {
    1229           0 :                 unbecome_root();
    1230             :         }
    1231             : 
    1232        8712 :         TALLOC_FREE(smb_dname);
    1233        8712 :         return;
    1234             : }
    1235             : 
    1236      368918 : static bool smbd_dptr_name_equal(struct dptr_struct *dptr,
    1237             :                                  const char *name1,
    1238             :                                  const char *name2)
    1239             : {
    1240           0 :         bool equal;
    1241             : 
    1242      368918 :         if (dptr_case_sensitive(dptr)) {
    1243           0 :                 equal = (strcmp(name1, name2) == 0);
    1244             :         } else {
    1245      368918 :                 equal = strequal(name1, name2);
    1246             :         }
    1247             : 
    1248      368918 :         return equal;
    1249             : }
    1250             : 
    1251             : /****************************************************************************
    1252             :  Reply to a TRANS2_FINDNEXT.
    1253             : ****************************************************************************/
    1254             : 
    1255        1724 : 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)
    1260             : {
    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        1724 :         char *params = *pparams;
    1267        1724 :         char *pdata = *ppdata;
    1268           0 :         char *data_end;
    1269           0 :         int dptr_num;
    1270           0 :         int maxentries;
    1271           0 :         uint16_t info_level;
    1272           0 :         uint32_t resume_key;
    1273           0 :         uint16_t findnext_flags;
    1274           0 :         bool close_after_request;
    1275           0 :         bool close_if_end;
    1276           0 :         bool requires_resume_key;
    1277           0 :         bool continue_bit;
    1278        1724 :         char *resume_name = NULL;
    1279        1724 :         const char *mask = NULL;
    1280        1724 :         const char *directory = NULL;
    1281        1724 :         char *p = NULL;
    1282           0 :         uint16_t dirtype;
    1283        1724 :         int numentries = 0;
    1284        1724 :         int i, last_entry_off=0;
    1285        1724 :         bool finished = False;
    1286        1724 :         bool dont_descend = False;
    1287        1724 :         bool out_of_space = False;
    1288           0 :         int space_remaining;
    1289        1724 :         struct ea_list *ea_list = NULL;
    1290        1724 :         NTSTATUS ntstatus = NT_STATUS_OK;
    1291           0 :         bool ask_sharemode;
    1292        1724 :         TALLOC_CTX *ctx = talloc_tos();
    1293        1724 :         struct smbd_server_connection *sconn = req->sconn;
    1294        1724 :         bool backup_priv = false;
    1295        1724 :         bool as_root = false;
    1296        1724 :         files_struct *fsp = NULL;
    1297           0 :         const struct loadparm_substitution *lp_sub =
    1298        1724 :                 loadparm_s3_global_substitution();
    1299             : 
    1300        1724 :         if (total_params < 13) {
    1301           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1302           0 :                 return;
    1303             :         }
    1304             : 
    1305        1724 :         dptr_num = SVAL(params,0);
    1306        1724 :         maxentries = SVAL(params,2);
    1307        1724 :         info_level = SVAL(params,4);
    1308        1724 :         resume_key = IVAL(params,6);
    1309        1724 :         findnext_flags = SVAL(params,10);
    1310        1724 :         close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
    1311        1724 :         close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
    1312        1724 :         requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
    1313        1724 :         continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
    1314             : 
    1315        1724 :         if (!continue_bit) {
    1316             :                 /* We only need resume_name if continue_bit is zero. */
    1317        1424 :                 if (req->posix_pathnames) {
    1318           0 :                         srvstr_get_path_posix(ctx,
    1319             :                                 params,
    1320           0 :                                 req->flags2,
    1321             :                                 &resume_name,
    1322           0 :                                 params+12,
    1323           0 :                                 total_params - 12,
    1324             :                                 STR_TERMINATE,
    1325             :                                 &ntstatus);
    1326             :                 } else {
    1327        1424 :                         srvstr_get_path(ctx,
    1328             :                                 params,
    1329        1424 :                                 req->flags2,
    1330             :                                 &resume_name,
    1331        1424 :                                 params+12,
    1332        1424 :                                 total_params - 12,
    1333             :                                 STR_TERMINATE,
    1334             :                                 &ntstatus);
    1335             :                 }
    1336        1424 :                 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           0 :                         srvstr_pull_talloc(ctx, params, req->flags2,
    1342             :                                 &resume_name, params+12,
    1343             :                                 total_params - 12,
    1344             :                                 STR_TERMINATE);
    1345             : 
    1346           0 :                         if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
    1347           0 :                                 reply_nterror(req, ntstatus);
    1348           0 :                                 return;
    1349             :                         }
    1350             :                 }
    1351             :         }
    1352             : 
    1353        1724 :         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);
    1367             : 
    1368        1724 :         if (!maxentries) {
    1369             :                 /* W2K3 seems to treat zero as 1. */
    1370           0 :                 maxentries = 1;
    1371             :         }
    1372             : 
    1373        1724 :         switch (info_level) {
    1374        1724 :                 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        1724 :                         break;
    1384           0 :                 case SMB_FIND_FILE_UNIX:
    1385             :                 case SMB_FIND_FILE_UNIX_INFO2:
    1386           0 :                         if (!lp_smb1_unix_extensions()) {
    1387           0 :                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    1388           0 :                                 return;
    1389             :                         }
    1390           0 :                         if (!req->posix_pathnames) {
    1391           0 :                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    1392           0 :                                 return;
    1393             :                         }
    1394           0 :                         break;
    1395           0 :                 default:
    1396           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    1397           0 :                         return;
    1398             :         }
    1399             : 
    1400        1724 :         if (info_level == SMB_FIND_EA_LIST) {
    1401           0 :                 uint32_t ea_size;
    1402             : 
    1403           6 :                 if (total_data < 4) {
    1404           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1405           0 :                         return;
    1406             :                 }
    1407             : 
    1408           6 :                 ea_size = IVAL(pdata,0);
    1409           6 :                 if (ea_size != total_data) {
    1410           0 :                         DBG_NOTICE("Rejecting EA request with incorrect "
    1411             :                                    "total_data=%d (should be %" PRIu32 ")\n",
    1412             :                                    total_data,
    1413             :                                    ea_size);
    1414           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1415           0 :                         return;
    1416             :                 }
    1417             : 
    1418           6 :                 if (!lp_ea_support(SNUM(conn))) {
    1419           0 :                         reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
    1420           0 :                         return;
    1421             :                 }
    1422             : 
    1423             :                 /* Pull out the list of names. */
    1424           6 :                 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
    1425           6 :                 if (!ea_list) {
    1426           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1427           0 :                         return;
    1428             :                 }
    1429             :         }
    1430             : 
    1431        1724 :         if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
    1432           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1433           0 :                 return;
    1434             :         }
    1435             : 
    1436        1724 :         *ppdata = (char *)SMB_REALLOC(
    1437             :                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
    1438        1724 :         if(*ppdata == NULL) {
    1439           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    1440           0 :                 return;
    1441             :         }
    1442             : 
    1443        1724 :         pdata = *ppdata;
    1444        1724 :         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
    1445             : 
    1446             :         /*
    1447             :          * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
    1448             :          * error.
    1449             :          */
    1450        1724 :         memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
    1451             :         /* Realloc the params space */
    1452        1724 :         *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
    1453        1724 :         if(*pparams == NULL ) {
    1454           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    1455           0 :                 return;
    1456             :         }
    1457             : 
    1458        1724 :         params = *pparams;
    1459             : 
    1460             :         /* Check that the dptr is valid */
    1461        1724 :         fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
    1462        1724 :         if (fsp == NULL) {
    1463           0 :                 reply_nterror(req, STATUS_NO_MORE_FILES);
    1464           0 :                 return;
    1465             :         }
    1466             : 
    1467        1724 :         directory = dptr_path(sconn, dptr_num);
    1468             : 
    1469             :         /* Get the wildcard mask from the dptr */
    1470        1724 :         if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
    1471           0 :                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
    1472           0 :                 reply_nterror(req, STATUS_NO_MORE_FILES);
    1473           0 :                 return;
    1474             :         }
    1475             : 
    1476             :         /* Get the attr mask from the dptr */
    1477        1724 :         dirtype = dptr_attr(sconn, dptr_num);
    1478             : 
    1479        1724 :         backup_priv = dptr_get_priv(fsp->dptr);
    1480             : 
    1481        1724 :         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));
    1486             : 
    1487             :         /* We don't need to check for VOL here as this is returned by
    1488             :                 a different TRANS2 call. */
    1489             : 
    1490        1724 :         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
    1491             :                  directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
    1492        1724 :         if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),
    1493        1724 :                         dptr_case_sensitive(fsp->dptr)))
    1494           0 :                 dont_descend = True;
    1495             : 
    1496        1724 :         p = pdata;
    1497        1724 :         space_remaining = max_data_bytes;
    1498        1724 :         out_of_space = False;
    1499             : 
    1500        1724 :         if (backup_priv) {
    1501           0 :                 become_root();
    1502           0 :                 as_root = true;
    1503             :         }
    1504             : 
    1505             :         /*
    1506             :          * Seek to the correct position. We no longer use the resume key but
    1507             :          * depend on the last file name instead.
    1508             :          */
    1509             : 
    1510        1724 :         if(!continue_bit && resume_name && *resume_name) {
    1511        1424 :                 bool posix_open = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN);
    1512        1424 :                 char *last_name_sent = NULL;
    1513           0 :                 bool sequential;
    1514             : 
    1515             :                 /*
    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.
    1519             :                  */
    1520             : 
    1521        2848 :                 if (!posix_open &&
    1522        1424 :                                 mangle_is_mangled(resume_name, conn->params)) {
    1523           0 :                         char *new_resume_name = NULL;
    1524           0 :                         mangle_lookup_name_from_8_3(ctx,
    1525             :                                                 resume_name,
    1526             :                                                 &new_resume_name,
    1527           0 :                                                 conn->params);
    1528           0 :                         if (new_resume_name) {
    1529           0 :                                 resume_name = new_resume_name;
    1530             :                         }
    1531             :                 }
    1532             : 
    1533             :                 /*
    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.
    1540             :                  */
    1541             : 
    1542        1424 :                 last_name_sent = smbd_dirptr_get_last_name_sent(fsp->dptr);
    1543        1424 :                 sequential = smbd_dptr_name_equal(fsp->dptr,
    1544             :                                                   resume_name,
    1545             :                                                   last_name_sent);
    1546        1424 :                 if (!sequential) {
    1547        1050 :                         char *name = NULL;
    1548        1050 :                         bool found = false;
    1549             : 
    1550        1050 :                         dptr_RewindDir(fsp->dptr);
    1551             : 
    1552      369588 :                         while ((name = dptr_ReadDirName(talloc_tos(),
    1553      737076 :                                                         fsp->dptr)) != NULL) {
    1554      367494 :                                 found = smbd_dptr_name_equal(fsp->dptr,
    1555             :                                                              resume_name,
    1556             :                                                              name);
    1557      367494 :                                 TALLOC_FREE(name);
    1558      367494 :                                 if (found) {
    1559           6 :                                         break;
    1560             :                                 }
    1561             :                         }
    1562             : 
    1563        1050 :                         if (!found) {
    1564             :                                 /*
    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.
    1570             :                                  */
    1571        1044 :                                 dptr_RewindDir(fsp->dptr);
    1572             :                         }
    1573             :                 }
    1574             :         } /* end if resume_name && !continue_bit */
    1575             : 
    1576        1724 :         ask_sharemode = fsp_search_ask_sharemode(fsp);
    1577             : 
    1578      159502 :         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
    1579             : 
    1580      157778 :                 ntstatus = get_lanman2_dir_entry(ctx,
    1581             :                                                  conn,
    1582      157778 :                                                  fsp->dptr,
    1583      157778 :                                                  req->flags2,
    1584             :                                                  mask,
    1585             :                                                  dirtype,
    1586             :                                                  info_level,
    1587             :                                                  requires_resume_key,
    1588             :                                                  dont_descend,
    1589             :                                                  ask_sharemode,
    1590             :                                                  &p,
    1591             :                                                  pdata,
    1592             :                                                  data_end,
    1593             :                                                  space_remaining,
    1594             :                                                  &last_entry_off,
    1595             :                                                  ea_list);
    1596      157778 :                 if (NT_STATUS_EQUAL(ntstatus, NT_STATUS_ILLEGAL_CHARACTER)) {
    1597             :                         /*
    1598             :                          * Bad character conversion on name. Ignore
    1599             :                          * this entry.
    1600             :                          */
    1601           0 :                         continue;
    1602             :                 }
    1603      157778 :                 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
    1604           0 :                         out_of_space = true;
    1605             :                 } else {
    1606      157778 :                         finished = !NT_STATUS_IS_OK(ntstatus);
    1607             :                 }
    1608             : 
    1609      157778 :                 if (!finished && !out_of_space) {
    1610      157506 :                         numentries++;
    1611             :                 }
    1612             : 
    1613      157778 :                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
    1614             :         }
    1615             : 
    1616        1724 :         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
    1617             :                 smb_fn_name(req->cmd),
    1618             :                 mask, directory, dirtype, numentries ) );
    1619             : 
    1620             :         /* Check if we can close the fsp->dptr */
    1621        1724 :         if(close_after_request || (finished && close_if_end)) {
    1622         110 :                 DBG_INFO("closing dptr_num = %d\n", dptr_num);
    1623         110 :                 dptr_num = -1;
    1624         110 :                 close_file_free(NULL, &fsp, NORMAL_CLOSE);
    1625             :         }
    1626             : 
    1627        1724 :         if (as_root) {
    1628           0 :                 unbecome_root();
    1629             :         }
    1630             : 
    1631             :         /* Set up the return parameter block */
    1632        1724 :         SSVAL(params,0,numentries);
    1633        1724 :         SSVAL(params,2,finished);
    1634        1724 :         SSVAL(params,4,0); /* Never an EA error */
    1635        1724 :         SSVAL(params,6,last_entry_off);
    1636             : 
    1637        1724 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
    1638             :                             max_data_bytes);
    1639             : 
    1640        1724 :         return;
    1641             : }
    1642             : 
    1643             : /****************************************************************************
    1644             :  Reply to a TRANS2_QFSINFO (query filesystem info).
    1645             : ****************************************************************************/
    1646             : 
    1647        1373 : 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)
    1652             : {
    1653        1373 :         char *params = *pparams;
    1654           0 :         uint16_t info_level;
    1655        1373 :         int data_len = 0;
    1656           0 :         size_t fixed_portion;
    1657           0 :         NTSTATUS status;
    1658             : 
    1659        1373 :         if (total_params < 2) {
    1660           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1661           0 :                 return;
    1662             :         }
    1663             : 
    1664        1373 :         info_level = SVAL(params,0);
    1665             : 
    1666        1373 :         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
    1667           0 :                 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
    1668           0 :                         DEBUG(0,("call_trans2qfsinfo: encryption required "
    1669             :                                 "and info level 0x%x sent.\n",
    1670             :                                 (unsigned int)info_level));
    1671           0 :                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    1672           0 :                         return;
    1673             :                 }
    1674             :         }
    1675             : 
    1676        1373 :         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
    1677             : 
    1678        1373 :         status = smbd_do_qfsinfo(req->xconn, conn, req,
    1679             :                                  info_level,
    1680        1373 :                                  req->flags2,
    1681             :                                  max_data_bytes,
    1682             :                                  &fixed_portion,
    1683             :                                  NULL,
    1684             :                                  ppdata, &data_len);
    1685        1373 :         if (!NT_STATUS_IS_OK(status)) {
    1686           0 :                 reply_nterror(req, status);
    1687           0 :                 return;
    1688             :         }
    1689             : 
    1690        1373 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
    1691             :                             max_data_bytes);
    1692             : 
    1693        1373 :         DEBUG( 4, ( "%s info_level = %d\n",
    1694             :                     smb_fn_name(req->cmd), info_level) );
    1695             : 
    1696        1373 :         return;
    1697             : }
    1698             : 
    1699             : /****************************************************************************
    1700             :  Reply to a TRANS2_SETFSINFO (set filesystem info).
    1701             : ****************************************************************************/
    1702             : 
    1703        1364 : 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)
    1708             : {
    1709           0 :         const struct loadparm_substitution *lp_sub =
    1710        1364 :                 loadparm_s3_global_substitution();
    1711        1364 :         struct smbXsrv_connection *xconn = req->xconn;
    1712        1364 :         char *pdata = *ppdata;
    1713        1364 :         char *params = *pparams;
    1714           0 :         uint16_t info_level;
    1715             : 
    1716        1364 :         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
    1717             :                   lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    1718             : 
    1719             :         /*  */
    1720        1364 :         if (total_params < 4) {
    1721           0 :                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
    1722             :                         total_params));
    1723           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1724           0 :                 return;
    1725             :         }
    1726             : 
    1727        1364 :         info_level = SVAL(params,2);
    1728             : 
    1729        1364 :         if (IS_IPC(conn)) {
    1730         480 :                 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
    1731           0 :                                 info_level != SMB_SET_CIFS_UNIX_INFO) {
    1732           0 :                         DEBUG(0,("call_trans2setfsinfo: not an allowed "
    1733             :                                 "info level (0x%x) on IPC$.\n",
    1734             :                                 (unsigned int)info_level));
    1735           0 :                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    1736           0 :                         return;
    1737             :                 }
    1738             :         }
    1739             : 
    1740        1364 :         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
    1741           0 :                 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
    1742           0 :                         DEBUG(0,("call_trans2setfsinfo: encryption required "
    1743             :                                 "and info level 0x%x sent.\n",
    1744             :                                 (unsigned int)info_level));
    1745           0 :                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    1746           0 :                         return;
    1747             :                 }
    1748             :         }
    1749             : 
    1750        1364 :         switch(info_level) {
    1751         476 :                 case SMB_SET_CIFS_UNIX_INFO:
    1752         476 :                         if (!lp_smb1_unix_extensions()) {
    1753           0 :                                 DEBUG(2,("call_trans2setfsinfo: "
    1754             :                                         "SMB_SET_CIFS_UNIX_INFO is invalid with "
    1755             :                                         "unix extensions off\n"));
    1756           0 :                                 reply_nterror(req,
    1757             :                                               NT_STATUS_INVALID_LEVEL);
    1758           0 :                                 return;
    1759             :                         }
    1760             : 
    1761             :                         /* There should be 12 bytes of capabilities set. */
    1762         476 :                         if (total_data < 12) {
    1763           0 :                                 reply_nterror(
    1764             :                                         req,
    1765             :                                         NT_STATUS_INVALID_PARAMETER);
    1766           0 :                                 return;
    1767             :                         }
    1768         476 :                         xconn->smb1.unix_info.client_major = SVAL(pdata,0);
    1769         476 :                         xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
    1770         476 :                         xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
    1771         476 :                         xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
    1772             : 
    1773             :                         /* Just print these values for now. */
    1774         476 :                         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);
    1782             : 
    1783             :                         /*
    1784             :                          * Here is where we must switch to posix
    1785             :                          * pathname processing...
    1786             :                          */
    1787         476 :                         if (xconn->smb1.unix_info.client_cap_low &
    1788             :                             CIFS_UNIX_POSIX_PATHNAMES_CAP)
    1789             :                         {
    1790         476 :                                 lp_set_posix_pathnames();
    1791         476 :                                 mangle_change_to_posix();
    1792             :                         }
    1793             : 
    1794         476 :                         if ((xconn->smb1.unix_info.client_cap_low &
    1795         476 :                              CIFS_UNIX_FCNTL_LOCKS_CAP) &&
    1796         476 :                             !(xconn->smb1.unix_info.client_cap_low &
    1797             :                               CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP))
    1798             :                         {
    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. */
    1802             : 
    1803           0 :                                 lp_set_posix_default_cifsx_readwrite_locktype(
    1804             :                                         POSIX_LOCK);
    1805             : 
    1806             :                         }
    1807         476 :                         break;
    1808             : 
    1809         888 :                 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
    1810             :                         {
    1811           0 :                                 NTSTATUS status;
    1812         888 :                                 size_t param_len = 0;
    1813         888 :                                 size_t data_len = total_data;
    1814             : 
    1815         888 :                                 if (!lp_smb1_unix_extensions()) {
    1816           0 :                                         reply_nterror(
    1817             :                                                 req,
    1818             :                                                 NT_STATUS_INVALID_LEVEL);
    1819           0 :                                         return;
    1820             :                                 }
    1821             : 
    1822         888 :                                 if (lp_server_smb_encrypt(SNUM(conn)) ==
    1823             :                                     SMB_ENCRYPTION_OFF) {
    1824           0 :                                         reply_nterror(
    1825             :                                                 req,
    1826             :                                                 NT_STATUS_NOT_SUPPORTED);
    1827           0 :                                         return;
    1828             :                                 }
    1829             : 
    1830         888 :                                 if (xconn->smb1.echo_handler.trusted_fde) {
    1831           0 :                                         DEBUG( 2,("call_trans2setfsinfo: "
    1832             :                                                 "request transport encryption disabled"
    1833             :                                                 "with 'fork echo handler = yes'\n"));
    1834           0 :                                         reply_nterror(
    1835             :                                                 req,
    1836             :                                                 NT_STATUS_NOT_SUPPORTED);
    1837           0 :                                         return;
    1838             :                                 }
    1839             : 
    1840         888 :                                 DEBUG( 4,("call_trans2setfsinfo: "
    1841             :                                         "request transport encryption.\n"));
    1842             : 
    1843         888 :                                 status = srv_request_encryption_setup(conn,
    1844             :                                                                 (unsigned char **)ppdata,
    1845             :                                                                 &data_len,
    1846             :                                                                 (unsigned char **)pparams,
    1847             :                                                                 &param_len);
    1848             : 
    1849         888 :                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
    1850         444 :                                                 !NT_STATUS_IS_OK(status)) {
    1851           0 :                                         reply_nterror(req, status);
    1852           0 :                                         return;
    1853             :                                 }
    1854             : 
    1855         888 :                                 send_trans2_replies(conn, req,
    1856         888 :                                                 NT_STATUS_OK,
    1857             :                                                 *pparams,
    1858             :                                                 param_len,
    1859             :                                                 *ppdata,
    1860             :                                                 data_len,
    1861             :                                                 max_data_bytes);
    1862             : 
    1863         888 :                                 if (NT_STATUS_IS_OK(status)) {
    1864             :                                         /* Server-side transport
    1865             :                                          * encryption is now *on*. */
    1866         444 :                                         status = srv_encryption_start(conn);
    1867         444 :                                         if (!NT_STATUS_IS_OK(status)) {
    1868           0 :                                                 char *reason = talloc_asprintf(talloc_tos(),
    1869             :                                                                                "Failure in setting "
    1870             :                                                                                "up encrypted transport: %s",
    1871             :                                                                                nt_errstr(status));
    1872           0 :                                                 exit_server_cleanly(reason);
    1873             :                                         }
    1874             :                                 }
    1875         888 :                                 return;
    1876             :                         }
    1877             : 
    1878           0 :                 case SMB_FS_QUOTA_INFORMATION:
    1879             :                         {
    1880           0 :                                 NTSTATUS status;
    1881           0 :                                 DATA_BLOB qdata = {
    1882             :                                                 .data = (uint8_t *)pdata,
    1883             :                                                 .length = total_data
    1884             :                                 };
    1885           0 :                                 files_struct *fsp = NULL;
    1886           0 :                                 fsp = file_fsp(req, SVAL(params,0));
    1887             : 
    1888           0 :                                 status = smb_set_fsquota(conn,
    1889             :                                                         req,
    1890             :                                                         fsp,
    1891             :                                                         &qdata);
    1892           0 :                                 if (!NT_STATUS_IS_OK(status)) {
    1893           0 :                                         reply_nterror(req, status);
    1894           0 :                                         return;
    1895             :                                 }
    1896           0 :                                 break;
    1897             :                         }
    1898           0 :                 default:
    1899           0 :                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
    1900             :                                 info_level));
    1901           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    1902           0 :                         return;
    1903           0 :                         break;
    1904             :         }
    1905             : 
    1906             :         /*
    1907             :          * sending this reply works fine,
    1908             :          * but I'm not sure it's the same
    1909             :          * like windows do...
    1910             :          * --metze
    1911             :          */
    1912         476 :         reply_smb1_outbuf(req, 10, 0);
    1913             : }
    1914             : 
    1915             : /****************************************************************************
    1916             :  Reply to a TRANSACT2_QFILEINFO on a PIPE !
    1917             : ****************************************************************************/
    1918             : 
    1919           0 : 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)
    1927             : {
    1928           0 :         char *params = *pparams;
    1929           0 :         char *pdata = *ppdata;
    1930           0 :         unsigned int data_size = 0;
    1931           0 :         unsigned int param_size = 2;
    1932             : 
    1933           0 :         if (!fsp_is_np(fsp)) {
    1934           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
    1935           0 :                 return;
    1936             :         }
    1937             : 
    1938           0 :         *pparams = (char *)SMB_REALLOC(*pparams,2);
    1939           0 :         if (*pparams == NULL) {
    1940           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    1941           0 :                 return;
    1942             :         }
    1943           0 :         params = *pparams;
    1944           0 :         SSVAL(params,0,0);
    1945           0 :         if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
    1946           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1947           0 :                 return;
    1948             :         }
    1949           0 :         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
    1950           0 :         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
    1951           0 :         if (*ppdata == NULL ) {
    1952           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    1953           0 :                 return;
    1954             :         }
    1955           0 :         pdata = *ppdata;
    1956             : 
    1957           0 :         switch (info_level) {
    1958           0 :                 case SMB_FILE_STANDARD_INFORMATION:
    1959           0 :                         memset(pdata,0,24);
    1960           0 :                         SOFF_T(pdata,0,4096LL);
    1961           0 :                         SIVAL(pdata,16,1);
    1962           0 :                         SIVAL(pdata,20,1);
    1963           0 :                         data_size = 24;
    1964           0 :                         break;
    1965             : 
    1966           0 :                 default:
    1967           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    1968           0 :                         return;
    1969             :         }
    1970             : 
    1971           0 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
    1972             :                             max_data_bytes);
    1973             : }
    1974             : 
    1975       11351 : static void handle_trans2qfilepathinfo_result(
    1976             :         connection_struct *conn,
    1977             :         struct smb_request *req,
    1978             :         uint16_t info_level,
    1979             :         NTSTATUS status,
    1980             :         char *pdata,
    1981             :         int data_return_size,
    1982             :         size_t fixed_portion,
    1983             :         unsigned int max_data_bytes)
    1984             : {
    1985       11351 :         char params[2] = { 0, 0, };
    1986       11351 :         int param_size = 2;
    1987             : 
    1988             :         /*
    1989             :          * draft-leach-cifs-v1-spec-02.txt
    1990             :          * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
    1991             :          * says:
    1992             :          *
    1993             :          *  The requested information is placed in the Data portion of the
    1994             :          *  transaction response. For the information levels greater than 0x100,
    1995             :          *  the transaction response has 1 parameter word which should be
    1996             :          *  ignored by the client.
    1997             :          *
    1998             :          * However Windows only follows this rule for the IS_NAME_VALID call.
    1999             :          */
    2000       11351 :         switch (info_level) {
    2001           8 :         case SMB_INFO_IS_NAME_VALID:
    2002           8 :                 param_size = 0;
    2003           8 :                 break;
    2004             :         }
    2005             : 
    2006       11351 :         if (!NT_STATUS_IS_OK(status)) {
    2007          60 :                 if (open_was_deferred(req->xconn, req->mid)) {
    2008             :                         /* We have re-scheduled this call. */
    2009          60 :                         return;
    2010             :                 }
    2011          56 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
    2012           0 :                         bool ok = defer_smb1_sharing_violation(req);
    2013           0 :                         if (ok) {
    2014           0 :                                 return;
    2015             :                         }
    2016             :                 }
    2017          56 :                 reply_nterror(req, status);
    2018          56 :                 return;
    2019             :         }
    2020             : 
    2021       11291 :         if (fixed_portion > max_data_bytes) {
    2022           0 :                 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
    2023           0 :                 return;
    2024             :         }
    2025             : 
    2026       11291 :         send_trans2_replies(
    2027             :                 conn,
    2028             :                 req,
    2029       11291 :                 NT_STATUS_OK,
    2030             :                 params,
    2031             :                 param_size,
    2032             :                 pdata,
    2033             :                 data_return_size,
    2034             :                 max_data_bytes);
    2035             : }
    2036             : 
    2037             : /****************************************************************************
    2038             :  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
    2039             :  file name or file id).
    2040             : ****************************************************************************/
    2041             : 
    2042       11113 : static void call_trans2qfilepathinfo(connection_struct *conn,
    2043             :                                      struct smb_request *req,
    2044             :                                      unsigned int tran_call,
    2045             :                                      uint16_t info_level,
    2046             :                                      struct smb_filename *smb_fname,
    2047             :                                      struct files_struct *fsp,
    2048             :                                      bool delete_pending,
    2049             :                                      struct timespec write_time_ts,
    2050             :                                      char **pparams, int total_params,
    2051             :                                      char **ppdata, int total_data,
    2052             :                                      unsigned int max_data_bytes)
    2053             : {
    2054       11113 :         char *params = *pparams;
    2055       11113 :         char *pdata = *ppdata;
    2056       11113 :         unsigned int data_size = 0;
    2057       11113 :         struct ea_list *ea_list = NULL;
    2058         449 :         size_t fixed_portion;
    2059       11113 :         NTSTATUS status = NT_STATUS_OK;
    2060             : 
    2061       11113 :         DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
    2062             :                  "total_data=%d\n", smb_fname_str_dbg(smb_fname),
    2063             :                  fsp_fnum_dbg(fsp),
    2064             :                  info_level,tran_call,total_data));
    2065             : 
    2066             :         /* Pull out any data sent here before we realloc. */
    2067       11113 :         switch (info_level) {
    2068         152 :                 case SMB_INFO_QUERY_EAS_FROM_LIST:
    2069             :                 {
    2070             :                         /* Pull any EA list from the data portion. */
    2071          28 :                         uint32_t ea_size;
    2072             : 
    2073         152 :                         if (total_data < 4) {
    2074           0 :                                 reply_nterror(
    2075             :                                         req, NT_STATUS_INVALID_PARAMETER);
    2076           0 :                                 return;
    2077             :                         }
    2078         152 :                         ea_size = IVAL(pdata,0);
    2079             : 
    2080         152 :                         if (total_data > 0 && ea_size != total_data) {
    2081           0 :                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
    2082             : total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
    2083           0 :                                 reply_nterror(
    2084             :                                         req, NT_STATUS_INVALID_PARAMETER);
    2085           0 :                                 return;
    2086             :                         }
    2087             : 
    2088         152 :                         if (!lp_ea_support(SNUM(conn))) {
    2089           0 :                                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
    2090           0 :                                 return;
    2091             :                         }
    2092             : 
    2093             :                         /* Pull out the list of names. */
    2094         152 :                         ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
    2095         152 :                         if (!ea_list) {
    2096           0 :                                 reply_nterror(
    2097             :                                         req, NT_STATUS_INVALID_PARAMETER);
    2098           0 :                                 return;
    2099             :                         }
    2100         124 :                         break;
    2101             :                 }
    2102             : 
    2103       10540 :                 default:
    2104       10540 :                         break;
    2105             :         }
    2106             : 
    2107       11113 :         *pparams = (char *)SMB_REALLOC(*pparams,2);
    2108       11113 :         if (*pparams == NULL) {
    2109           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    2110           0 :                 return;
    2111             :         }
    2112       11113 :         params = *pparams;
    2113       11113 :         SSVAL(params,0,0);
    2114             : 
    2115       11113 :         if ((info_level & SMB2_INFO_SPECIAL) == SMB2_INFO_SPECIAL) {
    2116             :                 /*
    2117             :                  * We use levels that start with 0xFF00
    2118             :                  * internally to represent SMB2 specific levels
    2119             :                  */
    2120           0 :                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    2121           0 :                 return;
    2122             :         }
    2123             : 
    2124       11113 :         status = smbd_do_qfilepathinfo(conn, req, req, info_level,
    2125             :                                        fsp, smb_fname,
    2126             :                                        delete_pending, write_time_ts,
    2127             :                                        ea_list,
    2128       11113 :                                        req->flags2, max_data_bytes,
    2129             :                                        &fixed_portion,
    2130             :                                        ppdata, &data_size);
    2131             : 
    2132       11113 :         handle_trans2qfilepathinfo_result(
    2133             :                 conn,
    2134             :                 req,
    2135             :                 info_level,
    2136             :                 status,
    2137             :                 *ppdata,
    2138             :                 data_size,
    2139             :                 fixed_portion,
    2140             :                 max_data_bytes);
    2141             : }
    2142             : 
    2143         114 : static NTSTATUS smb_q_unix_basic(
    2144             :         struct connection_struct *conn,
    2145             :         struct smb_request *req,
    2146             :         struct smb_filename *smb_fname,
    2147             :         struct files_struct *fsp,
    2148             :         char **ppdata,
    2149             :         int *ptotal_data)
    2150             : {
    2151         114 :         const int total_data = 100;
    2152             : 
    2153         114 :         *ppdata = SMB_REALLOC(*ppdata, total_data);
    2154         114 :         if (*ppdata == NULL) {
    2155           0 :                 return NT_STATUS_NO_MEMORY;
    2156             :         }
    2157         114 :         store_file_unix_basic(conn, *ppdata, fsp, &smb_fname->st);
    2158             : 
    2159         114 :         *ptotal_data = total_data;
    2160             : 
    2161         114 :         return NT_STATUS_OK;
    2162             : }
    2163             : 
    2164          20 : static NTSTATUS smb_q_unix_info2(
    2165             :         struct connection_struct *conn,
    2166             :         struct smb_request *req,
    2167             :         struct smb_filename *smb_fname,
    2168             :         struct files_struct *fsp,
    2169             :         char **ppdata,
    2170             :         int *ptotal_data)
    2171             : {
    2172          20 :         const int total_data = 116;
    2173             : 
    2174          20 :         *ppdata = SMB_REALLOC(*ppdata, total_data);
    2175          20 :         if (*ppdata == NULL) {
    2176           0 :                 return NT_STATUS_NO_MEMORY;
    2177             :         }
    2178          20 :         store_file_unix_basic_info2(conn, *ppdata, fsp, &smb_fname->st);
    2179             : 
    2180          20 :         *ptotal_data = total_data;
    2181             : 
    2182          20 :         return NT_STATUS_OK;
    2183             : }
    2184             : 
    2185             : #if defined(HAVE_POSIX_ACLS)
    2186             : /****************************************************************************
    2187             :  Utility function to open a fsp for a POSIX handle operation.
    2188             : ****************************************************************************/
    2189             : 
    2190          88 : static NTSTATUS get_posix_fsp(connection_struct *conn,
    2191             :                               struct smb_request *req,
    2192             :                               struct smb_filename *smb_fname,
    2193             :                               uint32_t access_mask,
    2194             :                               files_struct **ret_fsp)
    2195             : {
    2196           0 :         NTSTATUS status;
    2197          88 :         uint32_t create_disposition = FILE_OPEN;
    2198          88 :         uint32_t share_access = FILE_SHARE_READ|
    2199             :                                 FILE_SHARE_WRITE|
    2200             :                                 FILE_SHARE_DELETE;
    2201          88 :         struct smb2_create_blobs *posx = NULL;
    2202             : 
    2203             :         /*
    2204             :          * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
    2205             :          * but set reasonable defaults.
    2206             :          */
    2207          88 :         uint32_t file_attributes = 0664;
    2208          88 :         uint32_t oplock = NO_OPLOCK;
    2209          88 :         uint32_t create_options = FILE_NON_DIRECTORY_FILE;
    2210             : 
    2211             :         /* File or directory must exist. */
    2212          88 :         if (!VALID_STAT(smb_fname->st)) {
    2213           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    2214             :         }
    2215             :         /* Cannot be a symlink. */
    2216          88 :         if (S_ISLNK(smb_fname->st.st_ex_mode)) {
    2217          16 :                 return NT_STATUS_ACCESS_DENIED;
    2218             :         }
    2219             :         /* Set options correctly for directory open. */
    2220          72 :         if (S_ISDIR(smb_fname->st.st_ex_mode)) {
    2221             :                 /*
    2222             :                  * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
    2223             :                  * directories, but set reasonable defaults.
    2224             :                  */
    2225          24 :                 file_attributes = 0775;
    2226          24 :                 create_options = FILE_DIRECTORY_FILE;
    2227             :         }
    2228             : 
    2229          72 :         status = make_smb2_posix_create_ctx(
    2230             :                 talloc_tos(), &posx, file_attributes);
    2231          72 :         if (!NT_STATUS_IS_OK(status)) {
    2232           0 :                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
    2233             :                             nt_errstr(status));
    2234           0 :                 goto done;
    2235             :         }
    2236             : 
    2237          72 :         status = SMB_VFS_CREATE_FILE(
    2238             :                 conn,           /* conn */
    2239             :                 req,            /* req */
    2240             :                 NULL,           /* dirfsp */
    2241             :                 smb_fname,      /* fname */
    2242             :                 access_mask,    /* access_mask */
    2243             :                 share_access,   /* share_access */
    2244             :                 create_disposition,/* create_disposition*/
    2245             :                 create_options, /* create_options */
    2246             :                 file_attributes,/* file_attributes */
    2247             :                 oplock,         /* oplock_request */
    2248             :                 NULL,           /* lease */
    2249             :                 0,              /* allocation_size */
    2250             :                 0,              /* private_flags */
    2251             :                 NULL,           /* sd */
    2252             :                 NULL,           /* ea_list */
    2253             :                 ret_fsp,        /* result */
    2254             :                 NULL,           /* pinfo */
    2255             :                 posx,           /* in_context */
    2256             :                 NULL);          /* out_context */
    2257             : 
    2258          72 : done:
    2259          72 :         TALLOC_FREE(posx);
    2260          72 :         return status;
    2261             : }
    2262             : 
    2263             : /****************************************************************************
    2264             :  Utility function to count the number of entries in a POSIX acl.
    2265             : ****************************************************************************/
    2266             : 
    2267         128 : static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
    2268             : {
    2269         128 :         unsigned int ace_count = 0;
    2270         128 :         int entry_id = SMB_ACL_FIRST_ENTRY;
    2271           0 :         SMB_ACL_ENTRY_T entry;
    2272             : 
    2273         396 :         while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
    2274         268 :                 entry_id = SMB_ACL_NEXT_ENTRY;
    2275         268 :                 ace_count++;
    2276             :         }
    2277         128 :         return ace_count;
    2278             : }
    2279             : 
    2280             : /****************************************************************************
    2281             :  Utility function to marshall a POSIX acl into wire format.
    2282             : ****************************************************************************/
    2283             : 
    2284         128 : static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
    2285             : {
    2286         128 :         int entry_id = SMB_ACL_FIRST_ENTRY;
    2287           0 :         SMB_ACL_ENTRY_T entry;
    2288             : 
    2289         396 :         while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
    2290           0 :                 SMB_ACL_TAG_T tagtype;
    2291           0 :                 SMB_ACL_PERMSET_T permset;
    2292         268 :                 unsigned char perms = 0;
    2293           0 :                 unsigned int own_grp;
    2294             : 
    2295         268 :                 entry_id = SMB_ACL_NEXT_ENTRY;
    2296             : 
    2297         268 :                 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
    2298           0 :                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
    2299           0 :                         return False;
    2300             :                 }
    2301             : 
    2302         268 :                 if (sys_acl_get_permset(entry, &permset) == -1) {
    2303           0 :                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
    2304           0 :                         return False;
    2305             :                 }
    2306             : 
    2307         268 :                 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
    2308         268 :                 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
    2309         268 :                 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
    2310             : 
    2311         268 :                 SCVAL(pdata,1,perms);
    2312             : 
    2313         268 :                 switch (tagtype) {
    2314          52 :                         case SMB_ACL_USER_OBJ:
    2315          52 :                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
    2316          52 :                                 own_grp = (unsigned int)pst->st_ex_uid;
    2317          52 :                                 SIVAL(pdata,2,own_grp);
    2318          52 :                                 SIVAL(pdata,6,0);
    2319          52 :                                 break;
    2320          40 :                         case SMB_ACL_USER:
    2321             :                                 {
    2322          40 :                                         uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
    2323          40 :                                         if (!puid) {
    2324           0 :                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
    2325           0 :                                                 return False;
    2326             :                                         }
    2327          40 :                                         own_grp = (unsigned int)*puid;
    2328          40 :                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
    2329          40 :                                         SIVAL(pdata,2,own_grp);
    2330          40 :                                         SIVAL(pdata,6,0);
    2331          40 :                                         break;
    2332             :                                 }
    2333          52 :                         case SMB_ACL_GROUP_OBJ:
    2334          52 :                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
    2335          52 :                                 own_grp = (unsigned int)pst->st_ex_gid;
    2336          52 :                                 SIVAL(pdata,2,own_grp);
    2337          52 :                                 SIVAL(pdata,6,0);
    2338          52 :                                 break;
    2339          36 :                         case SMB_ACL_GROUP:
    2340             :                                 {
    2341          36 :                                         gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
    2342          36 :                                         if (!pgid) {
    2343           0 :                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
    2344           0 :                                                 return False;
    2345             :                                         }
    2346          36 :                                         own_grp = (unsigned int)*pgid;
    2347          36 :                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
    2348          36 :                                         SIVAL(pdata,2,own_grp);
    2349          36 :                                         SIVAL(pdata,6,0);
    2350          36 :                                         break;
    2351             :                                 }
    2352          36 :                         case SMB_ACL_MASK:
    2353          36 :                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
    2354          36 :                                 SIVAL(pdata,2,0xFFFFFFFF);
    2355          36 :                                 SIVAL(pdata,6,0xFFFFFFFF);
    2356          36 :                                 break;
    2357          52 :                         case SMB_ACL_OTHER:
    2358          52 :                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
    2359          52 :                                 SIVAL(pdata,2,0xFFFFFFFF);
    2360          52 :                                 SIVAL(pdata,6,0xFFFFFFFF);
    2361          52 :                                 break;
    2362           0 :                         default:
    2363           0 :                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
    2364           0 :                                 return False;
    2365             :                 }
    2366         268 :                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
    2367             :         }
    2368             : 
    2369         128 :         return True;
    2370             : }
    2371             : #endif
    2372             : 
    2373          80 : static NTSTATUS smb_q_posix_acl(
    2374             :         struct connection_struct *conn,
    2375             :         struct smb_request *req,
    2376             :         struct smb_filename *smb_fname,
    2377             :         struct files_struct *fsp,
    2378             :         char **ppdata,
    2379             :         int *ptotal_data)
    2380             : {
    2381             : #if !defined(HAVE_POSIX_ACLS)
    2382             :         return NT_STATUS_INVALID_LEVEL;
    2383             : #else
    2384          80 :         char *pdata = NULL;
    2385          80 :         SMB_ACL_T file_acl = NULL;
    2386          80 :         SMB_ACL_T def_acl = NULL;
    2387          80 :         uint16_t num_file_acls = 0;
    2388          80 :         uint16_t num_def_acls = 0;
    2389          80 :         unsigned int size_needed = 0;
    2390           0 :         NTSTATUS status;
    2391           0 :         bool ok;
    2392          80 :         bool close_fsp = false;
    2393             : 
    2394             :         /*
    2395             :          * Ensure we always operate on a file descriptor, not just
    2396             :          * the filename.
    2397             :          */
    2398          80 :         if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
    2399          80 :                 uint32_t access_mask = SEC_STD_READ_CONTROL|
    2400             :                                         FILE_READ_ATTRIBUTES|
    2401             :                                         FILE_WRITE_ATTRIBUTES;
    2402             : 
    2403          80 :                 status = get_posix_fsp(conn,
    2404             :                                         req,
    2405             :                                         smb_fname,
    2406             :                                         access_mask,
    2407             :                                         &fsp);
    2408             : 
    2409          80 :                 if (!NT_STATUS_IS_OK(status)) {
    2410          16 :                         goto out;
    2411             :                 }
    2412          64 :                 close_fsp = true;
    2413             :         }
    2414             : 
    2415          64 :         SMB_ASSERT(fsp != NULL);
    2416             : 
    2417          64 :         status = refuse_symlink_fsp(fsp);
    2418          64 :         if (!NT_STATUS_IS_OK(status)) {
    2419           0 :                 goto out;
    2420             :         }
    2421             : 
    2422          64 :         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, SMB_ACL_TYPE_ACCESS,
    2423             :                                         talloc_tos());
    2424             : 
    2425          64 :         if (file_acl == NULL && no_acl_syscall_error(errno)) {
    2426           0 :                 DBG_INFO("ACLs not implemented on "
    2427             :                         "filesystem containing %s\n",
    2428             :                         fsp_str_dbg(fsp));
    2429           0 :                 status = NT_STATUS_NOT_IMPLEMENTED;
    2430           0 :                 goto out;
    2431             :         }
    2432             : 
    2433          64 :         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
    2434             :                 /*
    2435             :                  * We can only have default POSIX ACLs on
    2436             :                  * directories.
    2437             :                  */
    2438          20 :                 if (!fsp->fsp_flags.is_directory) {
    2439           0 :                         DBG_INFO("Non-directory open %s\n",
    2440             :                                 fsp_str_dbg(fsp));
    2441           0 :                         status = NT_STATUS_INVALID_HANDLE;
    2442           0 :                         goto out;
    2443             :                 }
    2444          20 :                 def_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
    2445             :                                         SMB_ACL_TYPE_DEFAULT,
    2446             :                                         talloc_tos());
    2447          20 :                 def_acl = free_empty_sys_acl(conn, def_acl);
    2448             :         }
    2449             : 
    2450          64 :         num_file_acls = count_acl_entries(conn, file_acl);
    2451          64 :         num_def_acls = count_acl_entries(conn, def_acl);
    2452             : 
    2453             :         /* Wrap checks. */
    2454           0 :         if (num_file_acls + num_def_acls < num_file_acls) {
    2455             :                 status = NT_STATUS_INVALID_PARAMETER;
    2456             :                 goto out;
    2457             :         }
    2458             : 
    2459          64 :         size_needed = num_file_acls + num_def_acls;
    2460             : 
    2461             :         /*
    2462             :          * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
    2463             :          * than UINT_MAX, so check by division.
    2464             :          */
    2465          64 :         if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
    2466           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    2467           0 :                 goto out;
    2468             :         }
    2469             : 
    2470          64 :         size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
    2471          64 :         if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
    2472           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    2473           0 :                 goto out;
    2474             :         }
    2475          64 :         size_needed += SMB_POSIX_ACL_HEADER_SIZE;
    2476             : 
    2477          64 :         *ppdata = SMB_REALLOC(*ppdata, size_needed);
    2478          64 :         if (*ppdata == NULL) {
    2479           0 :                 status = NT_STATUS_NO_MEMORY;
    2480           0 :                 goto out;
    2481             :         }
    2482          64 :         pdata = *ppdata;
    2483             : 
    2484          64 :         SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
    2485          64 :         SSVAL(pdata,2,num_file_acls);
    2486          64 :         SSVAL(pdata,4,num_def_acls);
    2487          64 :         pdata += SMB_POSIX_ACL_HEADER_SIZE;
    2488             : 
    2489          64 :         ok = marshall_posix_acl(conn,
    2490             :                         pdata,
    2491          64 :                         &fsp->fsp_name->st,
    2492             :                         file_acl);
    2493          64 :         if (!ok) {
    2494           0 :                 status = NT_STATUS_INTERNAL_ERROR;
    2495           0 :                 goto out;
    2496             :         }
    2497          64 :         pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
    2498             : 
    2499          64 :         ok = marshall_posix_acl(conn,
    2500             :                         pdata,
    2501          64 :                         &fsp->fsp_name->st,
    2502             :                         def_acl);
    2503          64 :         if (!ok) {
    2504           0 :                 status = NT_STATUS_INTERNAL_ERROR;
    2505           0 :                 goto out;
    2506             :         }
    2507             : 
    2508          64 :         *ptotal_data = size_needed;
    2509          64 :         status = NT_STATUS_OK;
    2510             : 
    2511          80 :   out:
    2512             : 
    2513          80 :         if (close_fsp) {
    2514             :                 /*
    2515             :                  * Ensure the stat struct in smb_fname is up to
    2516             :                  * date. Structure copy.
    2517             :                  */
    2518          64 :                 smb_fname->st = fsp->fsp_name->st;
    2519          64 :                 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
    2520             :         }
    2521             : 
    2522          80 :         TALLOC_FREE(file_acl);
    2523          80 :         TALLOC_FREE(def_acl);
    2524          80 :         return status;
    2525             : #endif
    2526             : }
    2527             : 
    2528          24 : static NTSTATUS smb_q_posix_symlink(
    2529             :         struct connection_struct *conn,
    2530             :         struct smb_request *req,
    2531             :         struct smb_filename *smb_fname,
    2532             :         char **ppdata,
    2533             :         int *ptotal_data)
    2534             : {
    2535           0 :         char buffer[PATH_MAX+1];
    2536           0 :         size_t needed, len;
    2537           0 :         int link_len;
    2538          24 :         char *pdata = NULL;
    2539          24 :         struct smb_filename *parent_fname = NULL;
    2540          24 :         struct smb_filename *base_name = NULL;
    2541           0 :         NTSTATUS status;
    2542             : 
    2543          24 :         DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
    2544             :                   smb_fname_str_dbg(smb_fname));
    2545             : 
    2546          24 :         if (!S_ISLNK(smb_fname->st.st_ex_mode)) {
    2547           0 :                 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
    2548             :         }
    2549             : 
    2550          24 :         status = parent_pathref(
    2551             :                 talloc_tos(),
    2552             :                 conn->cwd_fsp,
    2553             :                 smb_fname,
    2554             :                 &parent_fname,
    2555             :                 &base_name);
    2556             : 
    2557          24 :         if (!NT_STATUS_IS_OK(status)) {
    2558           0 :                 DBG_DEBUG("parent_pathref failed: %s\n", nt_errstr(status));
    2559           0 :                 return status;
    2560             :         }
    2561             : 
    2562          24 :         link_len = SMB_VFS_READLINKAT(
    2563             :                 conn,
    2564             :                 parent_fname->fsp,
    2565             :                 base_name,
    2566             :                 buffer,
    2567             :                 sizeof(buffer)-1);
    2568          24 :         TALLOC_FREE(parent_fname);
    2569             : 
    2570          24 :         if (link_len == -1) {
    2571           0 :                 status = map_nt_error_from_unix(errno);
    2572           0 :                 DBG_DEBUG("READLINKAT failed: %s\n", nt_errstr(status));
    2573           0 :                 return status;
    2574             :         }
    2575          24 :         if (link_len >= sizeof(buffer)) {
    2576           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2577             :         }
    2578          24 :         buffer[link_len] = 0;
    2579             : 
    2580          24 :         needed = (link_len+1)*2;
    2581             : 
    2582          24 :         *ppdata = SMB_REALLOC(*ppdata, needed);
    2583          24 :         if (*ppdata == NULL) {
    2584           0 :                 return NT_STATUS_NO_MEMORY;
    2585             :         }
    2586          24 :         pdata = *ppdata;
    2587             : 
    2588          24 :         status = srvstr_push(
    2589             :                 pdata,
    2590             :                 req->flags2,
    2591             :                 pdata,
    2592             :                 buffer,
    2593             :                 needed,
    2594             :                 STR_TERMINATE,
    2595             :                 &len);
    2596          24 :         if (!NT_STATUS_IS_OK(status)) {
    2597           0 :                 return status;
    2598             :         }
    2599          24 :         *ptotal_data = len;
    2600             : 
    2601          24 :         return NT_STATUS_OK;
    2602             : }
    2603             : 
    2604        9901 : static void call_trans2qpathinfo(
    2605             :         connection_struct *conn,
    2606             :         struct smb_request *req,
    2607             :         char **pparams,
    2608             :         int total_params,
    2609             :         char **ppdata,
    2610             :         int total_data,
    2611             :         unsigned int max_data_bytes)
    2612             : {
    2613        9901 :         char *params = *pparams;
    2614         289 :         uint16_t info_level;
    2615        9901 :         struct smb_filename *smb_fname = NULL;
    2616        9901 :         bool delete_pending = False;
    2617        9901 :         struct timespec write_time_ts = { .tv_sec = 0, };
    2618        9901 :         struct files_struct *dirfsp = NULL;
    2619        9901 :         files_struct *fsp = NULL;
    2620         289 :         struct file_id fileid;
    2621         289 :         uint32_t name_hash;
    2622        9901 :         char *fname = NULL;
    2623        9901 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    2624        9901 :         NTTIME twrp = 0;
    2625         289 :         bool info_level_handled;
    2626        9901 :         NTSTATUS status = NT_STATUS_OK;
    2627         289 :         int ret;
    2628             : 
    2629        9901 :         if (!params) {
    2630           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2631           0 :                 return;
    2632             :         }
    2633             : 
    2634             : 
    2635             :         /* qpathinfo */
    2636        9901 :         if (total_params < 7) {
    2637           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2638           0 :                 return;
    2639             :         }
    2640             : 
    2641        9901 :         info_level = SVAL(params,0);
    2642             : 
    2643        9901 :         DBG_NOTICE("TRANSACT2_QPATHINFO: level = %d\n", info_level);
    2644             : 
    2645        9901 :         if (INFO_LEVEL_IS_UNIX(info_level)) {
    2646         242 :                 if (!lp_smb1_unix_extensions()) {
    2647           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    2648           0 :                         return;
    2649             :                 }
    2650         242 :                 if (!req->posix_pathnames) {
    2651           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    2652           0 :                         return;
    2653             :                 }
    2654             :         }
    2655             : 
    2656        9901 :         if (req->posix_pathnames) {
    2657         450 :                 srvstr_get_path_posix(req,
    2658             :                                       params,
    2659         450 :                                       req->flags2,
    2660             :                                       &fname,
    2661         450 :                                       &params[6],
    2662         450 :                                       total_params - 6,
    2663             :                                       STR_TERMINATE,
    2664             :                                       &status);
    2665             :         } else {
    2666        9451 :                 srvstr_get_path(req,
    2667             :                                 params,
    2668        9451 :                                 req->flags2,
    2669             :                                 &fname,
    2670        9451 :                                 &params[6],
    2671        9451 :                                 total_params - 6,
    2672             :                                 STR_TERMINATE,
    2673             :                                 &status);
    2674             :         }
    2675        9901 :         if (!NT_STATUS_IS_OK(status)) {
    2676           0 :                 reply_nterror(req, status);
    2677           0 :                 return;
    2678             :         }
    2679             : 
    2680        9901 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    2681        3104 :                 extract_snapshot_token(fname, &twrp);
    2682             :         }
    2683        9901 :         status = smb1_strip_dfs_path(req, &ucf_flags, &fname);
    2684        9901 :         if (!NT_STATUS_IS_OK(status)) {
    2685           0 :                 reply_nterror(req, status);
    2686           0 :                 return;
    2687             :         }
    2688        9901 :         status = filename_convert_dirfsp(req,
    2689             :                                          conn,
    2690             :                                          fname,
    2691             :                                          ucf_flags,
    2692             :                                          twrp,
    2693             :                                          &dirfsp,
    2694             :                                          &smb_fname);
    2695        9901 :         if (!NT_STATUS_IS_OK(status)) {
    2696        1722 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    2697        1172 :                         reply_botherror(req,
    2698             :                                         NT_STATUS_PATH_NOT_COVERED,
    2699             :                                         ERRSRV, ERRbadpath);
    2700        1172 :                         return;
    2701             :                 }
    2702         550 :                 reply_nterror(req, status);
    2703         550 :                 return;
    2704             :         }
    2705             : 
    2706             :         /*
    2707             :          * qpathinfo must operate on an existing file, so we
    2708             :          * can exit early if filename_convert_dirfsp() returned the
    2709             :          * "new file" NT_STATUS_OK, !VALID_STAT case.
    2710             :          */
    2711             : 
    2712        8179 :         if (!VALID_STAT(smb_fname->st)) {
    2713         110 :                 reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    2714         110 :                 return;
    2715             :         }
    2716             : 
    2717             :         /*
    2718             :          * smb_fname->fsp may be NULL if smb_fname points at a symlink
    2719             :          * and we're in POSIX context, so be careful when using fsp
    2720             :          * below, it can still be NULL.
    2721             :          */
    2722        8069 :         fsp = smb_fname->fsp;
    2723             : 
    2724             :         /* If this is a stream, check if there is a delete_pending. */
    2725        8069 :         if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
    2726        3069 :             && is_ntfs_stream_smb_fname(smb_fname)) {
    2727           0 :                 struct smb_filename *smb_fname_base;
    2728             : 
    2729             :                 /* Create an smb_filename with stream_name == NULL. */
    2730          60 :                 smb_fname_base = synthetic_smb_fname(
    2731             :                         talloc_tos(),
    2732          60 :                         smb_fname->base_name,
    2733             :                         NULL,
    2734             :                         NULL,
    2735          60 :                         smb_fname->twrp,
    2736          60 :                         smb_fname->flags);
    2737          60 :                 if (smb_fname_base == NULL) {
    2738           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    2739           0 :                         return;
    2740             :                 }
    2741             : 
    2742          60 :                 ret = vfs_stat(conn, smb_fname_base);
    2743          60 :                 if (ret != 0) {
    2744           0 :                         DBG_NOTICE("vfs_stat of %s failed "
    2745             :                                    "(%s)\n",
    2746             :                                    smb_fname_str_dbg(smb_fname_base),
    2747             :                                    strerror(errno));
    2748           0 :                         TALLOC_FREE(smb_fname_base);
    2749           0 :                         reply_nterror(req,
    2750             :                                       map_nt_error_from_unix(errno));
    2751           0 :                         return;
    2752             :                 }
    2753             : 
    2754          60 :                 status = file_name_hash(conn,
    2755             :                                         smb_fname_str_dbg(smb_fname_base),
    2756             :                                         &name_hash);
    2757          60 :                 if (!NT_STATUS_IS_OK(status)) {
    2758           0 :                         TALLOC_FREE(smb_fname_base);
    2759           0 :                         reply_nterror(req, status);
    2760           0 :                         return;
    2761             :                 }
    2762             : 
    2763          60 :                 fileid = vfs_file_id_from_sbuf(conn,
    2764          60 :                                                &smb_fname_base->st);
    2765          60 :                 TALLOC_FREE(smb_fname_base);
    2766          60 :                 get_file_infos(fileid, name_hash, &delete_pending, NULL);
    2767          60 :                 if (delete_pending) {
    2768           4 :                         reply_nterror(req, NT_STATUS_DELETE_PENDING);
    2769           4 :                         return;
    2770             :                 }
    2771             :         }
    2772             : 
    2773        8065 :         status = file_name_hash(conn,
    2774             :                                 smb_fname_str_dbg(smb_fname),
    2775             :                                 &name_hash);
    2776        8065 :         if (!NT_STATUS_IS_OK(status)) {
    2777           0 :                 reply_nterror(req, status);
    2778           0 :                 return;
    2779             :         }
    2780             : 
    2781        8065 :         if (fsp_getinfo_ask_sharemode(fsp)) {
    2782        8065 :                 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
    2783        8065 :                 get_file_infos(fileid, name_hash, &delete_pending,
    2784             :                                &write_time_ts);
    2785             :         }
    2786             : 
    2787        8065 :         if (delete_pending) {
    2788         119 :                 reply_nterror(req, NT_STATUS_DELETE_PENDING);
    2789         119 :                 return;
    2790             :         }
    2791             : 
    2792        7946 :         info_level_handled = true; /* Untouched in switch cases below */
    2793             : 
    2794        7946 :         switch (info_level) {
    2795             : 
    2796        7448 :         default:
    2797        7448 :                 info_level_handled = false;
    2798        7448 :                 break;
    2799             : 
    2800         114 :         case SMB_QUERY_FILE_UNIX_BASIC:
    2801         114 :                 status = smb_q_unix_basic(
    2802             :                         conn,
    2803             :                         req,
    2804             :                         smb_fname,
    2805         114 :                         smb_fname->fsp,
    2806             :                         ppdata,
    2807             :                         &total_data);
    2808         114 :                 break;
    2809             : 
    2810          16 :         case SMB_QUERY_FILE_UNIX_INFO2:
    2811          16 :                 status = smb_q_unix_info2(
    2812             :                         conn,
    2813             :                         req,
    2814             :                         smb_fname,
    2815          16 :                         smb_fname->fsp,
    2816             :                         ppdata,
    2817             :                         &total_data);
    2818          16 :                 break;
    2819             : 
    2820          80 :         case SMB_QUERY_POSIX_ACL:
    2821          80 :                 status = smb_q_posix_acl(
    2822             :                         conn,
    2823             :                         req,
    2824             :                         smb_fname,
    2825          80 :                         smb_fname->fsp,
    2826             :                         ppdata,
    2827             :                         &total_data);
    2828          80 :                 break;
    2829             : 
    2830          24 :         case SMB_QUERY_FILE_UNIX_LINK:
    2831          24 :                 status = smb_q_posix_symlink(
    2832             :                         conn,
    2833             :                         req,
    2834             :                         smb_fname,
    2835             :                         ppdata,
    2836             :                         &total_data);
    2837          24 :                 break;
    2838             :         }
    2839             : 
    2840        7682 :         if (info_level_handled) {
    2841         234 :                 handle_trans2qfilepathinfo_result(
    2842             :                         conn,
    2843             :                         req,
    2844             :                         info_level,
    2845             :                         status,
    2846             :                         *ppdata,
    2847             :                         total_data,
    2848             :                         total_data,
    2849             :                         max_data_bytes);
    2850         234 :                 return;
    2851             :         }
    2852             : 
    2853        7712 :         call_trans2qfilepathinfo(
    2854             :                 conn,
    2855             :                 req,
    2856             :                 TRANSACT2_QPATHINFO,
    2857             :                 info_level,
    2858             :                 smb_fname,
    2859             :                 fsp,
    2860             :                 false,
    2861             :                 write_time_ts,
    2862             :                 pparams,
    2863             :                 total_params,
    2864             :                 ppdata,
    2865             :                 total_data,
    2866             :                 max_data_bytes);
    2867             : }
    2868             : 
    2869           0 : static NTSTATUS smb_q_posix_lock(
    2870             :         struct connection_struct *conn,
    2871             :         struct smb_request *req,
    2872             :         struct files_struct *fsp,
    2873             :         char **ppdata,
    2874             :         int *ptotal_data)
    2875             : {
    2876           0 :         char *pdata = *ppdata;
    2877           0 :         int total_data = *ptotal_data;
    2878           0 :         uint64_t count;
    2879           0 :         uint64_t offset;
    2880           0 :         uint64_t smblctx;
    2881           0 :         enum brl_type lock_type;
    2882           0 :         NTSTATUS status;
    2883             : 
    2884           0 :         if (fsp->fsp_flags.is_pathref || (fsp_get_io_fd(fsp) == -1)) {
    2885           0 :                 return NT_STATUS_INVALID_HANDLE;
    2886             :         }
    2887             : 
    2888           0 :         if (total_data != POSIX_LOCK_DATA_SIZE) {
    2889           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2890             :         }
    2891             : 
    2892           0 :         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
    2893           0 :         case POSIX_LOCK_TYPE_READ:
    2894           0 :                 lock_type = READ_LOCK;
    2895           0 :                 break;
    2896           0 :         case POSIX_LOCK_TYPE_WRITE:
    2897           0 :                 lock_type = WRITE_LOCK;
    2898           0 :                 break;
    2899           0 :         case POSIX_LOCK_TYPE_UNLOCK:
    2900             :         default:
    2901             :                 /* There's no point in asking for an unlock... */
    2902           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2903             :         }
    2904             : 
    2905           0 :         smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
    2906           0 :         offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
    2907           0 :         count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
    2908             : 
    2909           0 :         status = query_lock(
    2910             :                 fsp,
    2911             :                 &smblctx,
    2912             :                 &count,
    2913             :                 &offset,
    2914             :                 &lock_type,
    2915             :                 POSIX_LOCK);
    2916             : 
    2917           0 :         if (NT_STATUS_IS_OK(status)) {
    2918             :                 /*
    2919             :                  * For success we just return a copy of what we sent
    2920             :                  * with the lock type set to POSIX_LOCK_TYPE_UNLOCK.
    2921             :                  */
    2922           0 :                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
    2923           0 :                 return NT_STATUS_OK;
    2924             :         }
    2925             : 
    2926           0 :         if (!ERROR_WAS_LOCK_DENIED(status)) {
    2927           0 :                 DBG_DEBUG("query_lock() failed: %s\n", nt_errstr(status));
    2928           0 :                 return status;
    2929             :         }
    2930             : 
    2931             :         /*
    2932             :          * Here we need to report who has it locked.
    2933             :          */
    2934             : 
    2935           0 :         SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
    2936           0 :         SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
    2937           0 :         SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
    2938           0 :         SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
    2939           0 :         SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
    2940             : 
    2941           0 :         return NT_STATUS_OK;
    2942             : }
    2943             : 
    2944        3549 : static void call_trans2qfileinfo(
    2945             :         connection_struct *conn,
    2946             :         struct smb_request *req,
    2947             :         char **pparams,
    2948             :         int total_params,
    2949             :         char **ppdata,
    2950             :         int total_data,
    2951             :         unsigned int max_data_bytes)
    2952             : {
    2953        3549 :         char *params = *pparams;
    2954         185 :         uint16_t info_level;
    2955        3549 :         struct smb_filename *smb_fname = NULL;
    2956        3549 :         bool delete_pending = False;
    2957        3549 :         struct timespec write_time_ts = { .tv_sec = 0, };
    2958        3549 :         files_struct *fsp = NULL;
    2959         185 :         struct file_id fileid;
    2960         185 :         bool info_level_handled;
    2961        3549 :         NTSTATUS status = NT_STATUS_OK;
    2962         185 :         int ret;
    2963             : 
    2964        3549 :         if (params == NULL) {
    2965           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2966           0 :                 return;
    2967             :         }
    2968             : 
    2969        3549 :         if (total_params < 4) {
    2970           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2971           0 :                 return;
    2972             :         }
    2973             : 
    2974        3549 :         fsp = file_fsp(req, SVAL(params,0));
    2975        3549 :         info_level = SVAL(params,2);
    2976             : 
    2977        3549 :         if (IS_IPC(conn)) {
    2978           0 :                 call_trans2qpipeinfo(
    2979             :                         conn,
    2980             :                         req,
    2981             :                         fsp,
    2982             :                         info_level,
    2983             :                         TRANSACT2_QFILEINFO,
    2984             :                         pparams,
    2985             :                         total_params,
    2986             :                         ppdata,
    2987             :                         total_data,
    2988             :                         max_data_bytes);
    2989           0 :                 return;
    2990             :         }
    2991             : 
    2992        3549 :         DBG_NOTICE("TRANSACT2_QFILEINFO: level = %d\n", info_level);
    2993             : 
    2994        3549 :         if (INFO_LEVEL_IS_UNIX(info_level)) {
    2995           4 :                 if (!lp_smb1_unix_extensions()) {
    2996           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    2997           0 :                         return;
    2998             :                 }
    2999           4 :                 if (!req->posix_pathnames) {
    3000           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    3001           0 :                         return;
    3002             :                 }
    3003             :         }
    3004             : 
    3005             :         /* Initial check for valid fsp ptr. */
    3006        3549 :         if (!check_fsp_open(conn, req, fsp)) {
    3007         144 :                 return;
    3008             :         }
    3009             : 
    3010        3405 :         smb_fname = fsp->fsp_name;
    3011             : 
    3012        3405 :         if(fsp->fake_file_handle) {
    3013             :                 /*
    3014             :                  * This is actually for the QUOTA_FAKE_FILE --metze
    3015             :                  */
    3016             : 
    3017             :                 /* We know this name is ok, it's already passed the checks. */
    3018             : 
    3019        3405 :         } else if(fsp_get_pathref_fd(fsp) == -1) {
    3020             :                 /*
    3021             :                  * This is actually a QFILEINFO on a directory
    3022             :                  * handle (returned from an NT SMB). NT5.0 seems
    3023             :                  * to do this call. JRA.
    3024             :                  */
    3025           0 :                 ret = vfs_stat(conn, smb_fname);
    3026           0 :                 if (ret != 0) {
    3027           0 :                         DBG_NOTICE("vfs_stat of %s failed (%s)\n",
    3028             :                                    smb_fname_str_dbg(smb_fname),
    3029             :                                    strerror(errno));
    3030           0 :                         reply_nterror(req,
    3031             :                                       map_nt_error_from_unix(errno));
    3032           0 :                         return;
    3033             :                 }
    3034             : 
    3035           0 :                 if (fsp_getinfo_ask_sharemode(fsp)) {
    3036           0 :                         fileid = vfs_file_id_from_sbuf(
    3037           0 :                                 conn, &smb_fname->st);
    3038           0 :                         get_file_infos(fileid, fsp->name_hash,
    3039             :                                        &delete_pending,
    3040             :                                        &write_time_ts);
    3041             :                 }
    3042             :         } else {
    3043             :                 /*
    3044             :                  * Original code - this is an open file.
    3045             :                  */
    3046        3405 :                 status = vfs_stat_fsp(fsp);
    3047        3405 :                 if (!NT_STATUS_IS_OK(status)) {
    3048           0 :                         DEBUG(3, ("fstat of %s failed (%s)\n",
    3049             :                                   fsp_fnum_dbg(fsp), nt_errstr(status)));
    3050           0 :                         reply_nterror(req, status);
    3051           0 :                         return;
    3052             :                 }
    3053        3405 :                 if (fsp_getinfo_ask_sharemode(fsp)) {
    3054        3405 :                         fileid = vfs_file_id_from_sbuf(
    3055        3405 :                                 conn, &smb_fname->st);
    3056        3405 :                         get_file_infos(fileid, fsp->name_hash,
    3057             :                                        &delete_pending,
    3058             :                                        &write_time_ts);
    3059             :                 }
    3060             :         }
    3061             : 
    3062        3405 :         info_level_handled = true; /* Untouched in switch cases below */
    3063             : 
    3064        3405 :         switch (info_level) {
    3065             : 
    3066        3216 :         default:
    3067        3216 :                 info_level_handled = false;
    3068        3216 :                 break;
    3069             : 
    3070           0 :         case SMB_QUERY_POSIX_LOCK:
    3071           0 :                 status = smb_q_posix_lock(conn, req, fsp, ppdata, &total_data);
    3072           0 :                 break;
    3073             : 
    3074           0 :         case SMB_QUERY_FILE_UNIX_BASIC:
    3075           0 :                 status = smb_q_unix_basic(
    3076             :                         conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
    3077           0 :                 break;
    3078             : 
    3079           4 :         case SMB_QUERY_FILE_UNIX_INFO2:
    3080           4 :                 status = smb_q_unix_info2(
    3081             :                         conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
    3082           4 :                 break;
    3083             : 
    3084           0 :         case SMB_QUERY_POSIX_ACL:
    3085           0 :                 status = smb_q_posix_acl(
    3086             :                         conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
    3087           0 :                 break;
    3088             :         }
    3089             : 
    3090        3220 :         if (info_level_handled) {
    3091           4 :                 handle_trans2qfilepathinfo_result(
    3092             :                         conn,
    3093             :                         req,
    3094             :                         info_level,
    3095             :                         status,
    3096             :                         *ppdata,
    3097             :                         total_data,
    3098             :                         total_data,
    3099             :                         max_data_bytes);
    3100           4 :                 return;
    3101             :         }
    3102             : 
    3103        3401 :         call_trans2qfilepathinfo(
    3104             :                 conn,
    3105             :                 req,
    3106             :                 TRANSACT2_QFILEINFO,
    3107             :                 info_level,
    3108             :                 smb_fname,
    3109             :                 fsp,
    3110             :                 delete_pending,
    3111             :                 write_time_ts,
    3112             :                 pparams,
    3113             :                 total_params,
    3114             :                 ppdata,
    3115             :                 total_data,
    3116             :                 max_data_bytes);
    3117             : }
    3118             : 
    3119        5605 : static void handle_trans2setfilepathinfo_result(
    3120             :         connection_struct *conn,
    3121             :         struct smb_request *req,
    3122             :         uint16_t info_level,
    3123             :         NTSTATUS status,
    3124             :         char *pdata,
    3125             :         int data_return_size,
    3126             :         unsigned int max_data_bytes)
    3127             : {
    3128        5605 :         char params[2] = { 0, 0, };
    3129             : 
    3130        5605 :         if (NT_STATUS_IS_OK(status)) {
    3131        4680 :                 send_trans2_replies(
    3132             :                         conn,
    3133             :                         req,
    3134        4680 :                         NT_STATUS_OK,
    3135             :                         params,
    3136             :                         2,
    3137             :                         pdata,
    3138             :                         data_return_size,
    3139             :                         max_data_bytes);
    3140        4680 :                 return;
    3141             :         }
    3142             : 
    3143         925 :         if (open_was_deferred(req->xconn, req->mid)) {
    3144             :                 /* We have re-scheduled this call. */
    3145           6 :                 return;
    3146             :         }
    3147             : 
    3148         919 :         if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
    3149          32 :                 bool ok = defer_smb1_sharing_violation(req);
    3150          32 :                 if (ok) {
    3151          16 :                         return;
    3152             :                 }
    3153             :         }
    3154             : 
    3155         903 :         if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
    3156             :                 /* We have re-scheduled this call. */
    3157          28 :                 return;
    3158             :         }
    3159             : 
    3160         875 :         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    3161           0 :                 reply_botherror(
    3162             :                         req,
    3163             :                         NT_STATUS_PATH_NOT_COVERED,
    3164             :                         ERRSRV,
    3165             :                         ERRbadpath);
    3166           0 :                 return;
    3167             :         }
    3168             : 
    3169         875 :         if (info_level == SMB_POSIX_PATH_OPEN) {
    3170          12 :                 reply_openerror(req, status);
    3171          12 :                 return;
    3172             :         }
    3173             : 
    3174         863 :         if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
    3175             :                 /*
    3176             :                  * Invalid EA name needs to return 2 param bytes,
    3177             :                  * not a zero-length error packet.
    3178             :                  */
    3179             : 
    3180         235 :                 send_trans2_replies(
    3181             :                         conn,
    3182             :                         req,
    3183             :                         status,
    3184             :                         params,
    3185             :                         2,
    3186             :                         NULL,
    3187             :                         0,
    3188             :                         max_data_bytes);
    3189         235 :                 return;
    3190             :         }
    3191             : 
    3192         628 :         reply_nterror(req, status);
    3193             : }
    3194             : 
    3195             : /****************************************************************************
    3196             :  Create a directory with POSIX semantics.
    3197             : ****************************************************************************/
    3198             : 
    3199          48 : static NTSTATUS smb_posix_mkdir(connection_struct *conn,
    3200             :                                 struct smb_request *req,
    3201             :                                 char **ppdata,
    3202             :                                 int total_data,
    3203             :                                 struct smb_filename *smb_fname,
    3204             :                                 int *pdata_return_size)
    3205             : {
    3206          48 :         NTSTATUS status = NT_STATUS_OK;
    3207          48 :         uint32_t raw_unixmode = 0;
    3208          48 :         mode_t unixmode = (mode_t)0;
    3209          48 :         files_struct *fsp = NULL;
    3210          48 :         uint16_t info_level_return = 0;
    3211           0 :         int info;
    3212          48 :         char *pdata = *ppdata;
    3213          48 :         struct smb2_create_blobs *posx = NULL;
    3214             : 
    3215          48 :         if (total_data < 18) {
    3216           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3217             :         }
    3218             : 
    3219          48 :         raw_unixmode = IVAL(pdata,8);
    3220             :         /* Next 4 bytes are not yet defined. */
    3221             : 
    3222          48 :         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
    3223             :                                       PERM_NEW_DIR, &unixmode);
    3224          48 :         if (!NT_STATUS_IS_OK(status)) {
    3225           0 :                 return status;
    3226             :         }
    3227             : 
    3228          48 :         status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
    3229          48 :         if (!NT_STATUS_IS_OK(status)) {
    3230           0 :                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
    3231             :                             nt_errstr(status));
    3232           0 :                 return status;
    3233             :         }
    3234             : 
    3235          48 :         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
    3236             :                   smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
    3237             : 
    3238          48 :         status = SMB_VFS_CREATE_FILE(
    3239             :                 conn,                                   /* conn */
    3240             :                 req,                                    /* req */
    3241             :                 NULL,                                   /* dirfsp */
    3242             :                 smb_fname,                              /* fname */
    3243             :                 FILE_READ_ATTRIBUTES,                   /* access_mask */
    3244             :                 FILE_SHARE_NONE,                        /* share_access */
    3245             :                 FILE_CREATE,                            /* create_disposition*/
    3246             :                 FILE_DIRECTORY_FILE,                    /* create_options */
    3247             :                 0,                                      /* file_attributes */
    3248             :                 0,                                      /* oplock_request */
    3249             :                 NULL,                                   /* lease */
    3250             :                 0,                                      /* allocation_size */
    3251             :                 0,                                      /* private_flags */
    3252             :                 NULL,                                   /* sd */
    3253             :                 NULL,                                   /* ea_list */
    3254             :                 &fsp,                                       /* result */
    3255             :                 &info,                                      /* pinfo */
    3256             :                 posx,                                   /* in_context_blobs */
    3257             :                 NULL);                                  /* out_context_blobs */
    3258             : 
    3259          48 :         TALLOC_FREE(posx);
    3260             : 
    3261          48 :         if (NT_STATUS_IS_OK(status)) {
    3262          48 :                 close_file_free(req, &fsp, NORMAL_CLOSE);
    3263             :         }
    3264             : 
    3265          48 :         info_level_return = SVAL(pdata,16);
    3266             : 
    3267          48 :         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
    3268           0 :                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
    3269          48 :         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
    3270           0 :                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
    3271             :         } else {
    3272          48 :                 *pdata_return_size = 12;
    3273             :         }
    3274             : 
    3275             :         /* Realloc the data size */
    3276          48 :         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
    3277          48 :         if (*ppdata == NULL) {
    3278           0 :                 *pdata_return_size = 0;
    3279           0 :                 return NT_STATUS_NO_MEMORY;
    3280             :         }
    3281          48 :         pdata = *ppdata;
    3282             : 
    3283          48 :         SSVAL(pdata,0,NO_OPLOCK_RETURN);
    3284          48 :         SSVAL(pdata,2,0); /* No fnum. */
    3285          48 :         SIVAL(pdata,4,info); /* Was directory created. */
    3286             : 
    3287          48 :         switch (info_level_return) {
    3288           0 :                 case SMB_QUERY_FILE_UNIX_BASIC:
    3289           0 :                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
    3290           0 :                         SSVAL(pdata,10,0); /* Padding. */
    3291           0 :                         store_file_unix_basic(conn, pdata + 12, fsp,
    3292           0 :                                               &smb_fname->st);
    3293           0 :                         break;
    3294           0 :                 case SMB_QUERY_FILE_UNIX_INFO2:
    3295           0 :                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
    3296           0 :                         SSVAL(pdata,10,0); /* Padding. */
    3297           0 :                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
    3298           0 :                                                     &smb_fname->st);
    3299           0 :                         break;
    3300          48 :                 default:
    3301          48 :                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
    3302          48 :                         SSVAL(pdata,10,0); /* Padding. */
    3303          48 :                         break;
    3304             :         }
    3305             : 
    3306          48 :         return status;
    3307             : }
    3308             : 
    3309             : /****************************************************************************
    3310             :  Open/Create a file with POSIX semantics.
    3311             : ****************************************************************************/
    3312             : 
    3313             : #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
    3314             : #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
    3315             : 
    3316         174 : static NTSTATUS smb_posix_open(connection_struct *conn,
    3317             :                                struct smb_request *req,
    3318             :                                char **ppdata,
    3319             :                                int total_data,
    3320             :                                struct files_struct *dirfsp,
    3321             :                                struct smb_filename *smb_fname,
    3322             :                                int *pdata_return_size)
    3323             : {
    3324         174 :         bool extended_oplock_granted = False;
    3325         174 :         char *pdata = *ppdata;
    3326         174 :         uint32_t flags = 0;
    3327         174 :         uint32_t wire_open_mode = 0;
    3328         174 :         uint32_t raw_unixmode = 0;
    3329         174 :         uint32_t attributes = 0;
    3330         174 :         uint32_t create_disp = 0;
    3331         174 :         uint32_t access_mask = 0;
    3332         174 :         uint32_t create_options = FILE_NON_DIRECTORY_FILE;
    3333         174 :         NTSTATUS status = NT_STATUS_OK;
    3334         174 :         mode_t unixmode = (mode_t)0;
    3335         174 :         files_struct *fsp = NULL;
    3336         174 :         int oplock_request = 0;
    3337         174 :         int info = 0;
    3338         174 :         uint16_t info_level_return = 0;
    3339         174 :         struct smb2_create_blobs *posx = NULL;
    3340             : 
    3341         174 :         if (total_data < 18) {
    3342           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3343             :         }
    3344             : 
    3345         174 :         flags = IVAL(pdata,0);
    3346         174 :         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
    3347         174 :         if (oplock_request) {
    3348           0 :                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
    3349             :         }
    3350             : 
    3351         174 :         wire_open_mode = IVAL(pdata,4);
    3352             : 
    3353         174 :         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
    3354          48 :                 return smb_posix_mkdir(conn, req,
    3355             :                                         ppdata,
    3356             :                                         total_data,
    3357             :                                         smb_fname,
    3358             :                                         pdata_return_size);
    3359             :         }
    3360             : 
    3361         126 :         switch (wire_open_mode & SMB_ACCMODE) {
    3362          28 :                 case SMB_O_RDONLY:
    3363          28 :                         access_mask = SMB_O_RDONLY_MAPPING;
    3364          28 :                         break;
    3365           4 :                 case SMB_O_WRONLY:
    3366           4 :                         access_mask = SMB_O_WRONLY_MAPPING;
    3367           4 :                         break;
    3368          94 :                 case SMB_O_RDWR:
    3369          94 :                         access_mask = (SMB_O_RDONLY_MAPPING|
    3370             :                                         SMB_O_WRONLY_MAPPING);
    3371          94 :                         break;
    3372           0 :                 default:
    3373           0 :                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
    3374             :                                 (unsigned int)wire_open_mode ));
    3375           0 :                         return NT_STATUS_INVALID_PARAMETER;
    3376             :         }
    3377             : 
    3378         126 :         wire_open_mode &= ~SMB_ACCMODE;
    3379             : 
    3380             :         /* First take care of O_CREAT|O_EXCL interactions. */
    3381         126 :         switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
    3382          38 :                 case (SMB_O_CREAT | SMB_O_EXCL):
    3383             :                         /* File exists fail. File not exist create. */
    3384          38 :                         create_disp = FILE_CREATE;
    3385          38 :                         break;
    3386          40 :                 case SMB_O_CREAT:
    3387             :                         /* File exists open. File not exist create. */
    3388          40 :                         create_disp = FILE_OPEN_IF;
    3389          40 :                         break;
    3390          48 :                 case SMB_O_EXCL:
    3391             :                         /* O_EXCL on its own without O_CREAT is undefined.
    3392             :                            We deliberately ignore it as some versions of
    3393             :                            Linux CIFSFS can send a bare O_EXCL on the
    3394             :                            wire which other filesystems in the kernel
    3395             :                            ignore. See bug 9519 for details. */
    3396             : 
    3397             :                         /* Fallthrough. */
    3398             : 
    3399             :                 case 0:
    3400             :                         /* File exists open. File not exist fail. */
    3401          48 :                         create_disp = FILE_OPEN;
    3402          48 :                         break;
    3403           0 :                 default:
    3404           0 :                         DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
    3405             :                                 (unsigned int)wire_open_mode ));
    3406           0 :                         return NT_STATUS_INVALID_PARAMETER;
    3407             :         }
    3408             : 
    3409             :         /* Next factor in the effects of O_TRUNC. */
    3410         126 :         wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
    3411             : 
    3412         126 :         if (wire_open_mode & SMB_O_TRUNC) {
    3413           4 :                 switch (create_disp) {
    3414           0 :                         case FILE_CREATE:
    3415             :                                 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
    3416             :                                 /* Leave create_disp alone as
    3417             :                                    (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
    3418             :                                 */
    3419             :                                 /* File exists fail. File not exist create. */
    3420           4 :                                 break;
    3421           0 :                         case FILE_OPEN_IF:
    3422             :                                 /* SMB_O_CREAT | SMB_O_TRUNC */
    3423             :                                 /* File exists overwrite. File not exist create. */
    3424           0 :                                 create_disp = FILE_OVERWRITE_IF;
    3425           0 :                                 break;
    3426           4 :                         case FILE_OPEN:
    3427             :                                 /* SMB_O_TRUNC */
    3428             :                                 /* File exists overwrite. File not exist fail. */
    3429           4 :                                 create_disp = FILE_OVERWRITE;
    3430           4 :                                 break;
    3431           0 :                         default:
    3432             :                                 /* Cannot get here. */
    3433           0 :                                 smb_panic("smb_posix_open: logic error");
    3434             :                                 return NT_STATUS_INVALID_PARAMETER;
    3435             :                 }
    3436             :         }
    3437             : 
    3438         126 :         raw_unixmode = IVAL(pdata,8);
    3439             :         /* Next 4 bytes are not yet defined. */
    3440             : 
    3441         126 :         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
    3442         126 :                                       (VALID_STAT(smb_fname->st) ?
    3443             :                                           PERM_EXISTING_FILE : PERM_NEW_FILE),
    3444             :                                       &unixmode);
    3445             : 
    3446         126 :         if (!NT_STATUS_IS_OK(status)) {
    3447           0 :                 return status;
    3448             :         }
    3449             : 
    3450         126 :         status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
    3451         126 :         if (!NT_STATUS_IS_OK(status)) {
    3452           0 :                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
    3453             :                             nt_errstr(status));
    3454           0 :                 return status;
    3455             :         }
    3456             : 
    3457         126 :         if (wire_open_mode & SMB_O_SYNC) {
    3458           0 :                 create_options |= FILE_WRITE_THROUGH;
    3459             :         }
    3460         126 :         if (wire_open_mode & SMB_O_APPEND) {
    3461           0 :                 access_mask |= FILE_APPEND_DATA;
    3462             :         }
    3463         126 :         if (wire_open_mode & SMB_O_DIRECT) {
    3464           0 :                 attributes |= FILE_FLAG_NO_BUFFERING;
    3465             :         }
    3466             : 
    3467         126 :         if ((wire_open_mode & SMB_O_DIRECTORY) ||
    3468         126 :                         VALID_STAT_OF_DIR(smb_fname->st)) {
    3469           8 :                 if (access_mask != SMB_O_RDONLY_MAPPING) {
    3470           4 :                         return NT_STATUS_FILE_IS_A_DIRECTORY;
    3471             :                 }
    3472           4 :                 create_options &= ~FILE_NON_DIRECTORY_FILE;
    3473           4 :                 create_options |= FILE_DIRECTORY_FILE;
    3474             :         }
    3475             : 
    3476         122 :         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
    3477             :                 smb_fname_str_dbg(smb_fname),
    3478             :                 (unsigned int)wire_open_mode,
    3479             :                 (unsigned int)unixmode ));
    3480             : 
    3481         122 :         status = SMB_VFS_CREATE_FILE(
    3482             :                 conn,                                   /* conn */
    3483             :                 req,                                    /* req */
    3484             :                 dirfsp,                                 /* dirfsp */
    3485             :                 smb_fname,                              /* fname */
    3486             :                 access_mask,                            /* access_mask */
    3487             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    3488             :                     FILE_SHARE_DELETE),
    3489             :                 create_disp,                            /* create_disposition*/
    3490             :                 create_options,                         /* create_options */
    3491             :                 attributes,                             /* file_attributes */
    3492             :                 oplock_request,                         /* oplock_request */
    3493             :                 NULL,                                   /* lease */
    3494             :                 0,                                      /* allocation_size */
    3495             :                 0,                                      /* private_flags */
    3496             :                 NULL,                                   /* sd */
    3497             :                 NULL,                                   /* ea_list */
    3498             :                 &fsp,                                       /* result */
    3499             :                 &info,                                      /* pinfo */
    3500             :                 posx,                                   /* in_context_blobs */
    3501             :                 NULL);                                  /* out_context_blobs */
    3502             : 
    3503         122 :         TALLOC_FREE(posx);
    3504             : 
    3505         122 :         if (!NT_STATUS_IS_OK(status)) {
    3506           8 :                 return status;
    3507             :         }
    3508             : 
    3509         114 :         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
    3510           0 :                 extended_oplock_granted = True;
    3511             :         }
    3512             : 
    3513         114 :         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
    3514           0 :                 extended_oplock_granted = True;
    3515             :         }
    3516             : 
    3517         114 :         info_level_return = SVAL(pdata,16);
    3518             : 
    3519             :         /* Allocate the correct return size. */
    3520             : 
    3521         114 :         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
    3522           0 :                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
    3523         114 :         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
    3524           0 :                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
    3525             :         } else {
    3526         114 :                 *pdata_return_size = 12;
    3527             :         }
    3528             : 
    3529             :         /* Realloc the data size */
    3530         114 :         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
    3531         114 :         if (*ppdata == NULL) {
    3532           0 :                 close_file_free(req, &fsp, ERROR_CLOSE);
    3533           0 :                 *pdata_return_size = 0;
    3534           0 :                 return NT_STATUS_NO_MEMORY;
    3535             :         }
    3536         114 :         pdata = *ppdata;
    3537             : 
    3538         114 :         if (extended_oplock_granted) {
    3539           0 :                 if (flags & REQUEST_BATCH_OPLOCK) {
    3540           0 :                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
    3541             :                 } else {
    3542           0 :                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
    3543             :                 }
    3544         114 :         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
    3545           0 :                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
    3546             :         } else {
    3547         114 :                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
    3548             :         }
    3549             : 
    3550         114 :         SSVAL(pdata,2,fsp->fnum);
    3551         114 :         SIVAL(pdata,4,info); /* Was file created etc. */
    3552             : 
    3553         114 :         switch (info_level_return) {
    3554           0 :                 case SMB_QUERY_FILE_UNIX_BASIC:
    3555           0 :                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
    3556           0 :                         SSVAL(pdata,10,0); /* padding. */
    3557           0 :                         store_file_unix_basic(conn, pdata + 12, fsp,
    3558           0 :                                               &smb_fname->st);
    3559           0 :                         break;
    3560           0 :                 case SMB_QUERY_FILE_UNIX_INFO2:
    3561           0 :                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
    3562           0 :                         SSVAL(pdata,10,0); /* padding. */
    3563           0 :                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
    3564           0 :                                                     &smb_fname->st);
    3565           0 :                         break;
    3566         114 :                 default:
    3567         114 :                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
    3568         114 :                         SSVAL(pdata,10,0); /* padding. */
    3569         114 :                         break;
    3570             :         }
    3571         114 :         return NT_STATUS_OK;
    3572             : }
    3573             : 
    3574             : /****************************************************************************
    3575             :  Delete a file with POSIX semantics.
    3576             : ****************************************************************************/
    3577             : 
    3578             : struct smb_posix_unlink_state {
    3579             :         struct smb_filename *smb_fname;
    3580             :         struct files_struct *fsp;
    3581             :         NTSTATUS status;
    3582             : };
    3583             : 
    3584         248 : static void smb_posix_unlink_locked(struct share_mode_lock *lck,
    3585             :                                     void *private_data)
    3586             : {
    3587         248 :         struct smb_posix_unlink_state *state = private_data;
    3588         248 :         char del = 1;
    3589           0 :         bool other_nonposix_opens;
    3590             : 
    3591         248 :         other_nonposix_opens = has_other_nonposix_opens(lck, state->fsp);
    3592         248 :         if (other_nonposix_opens) {
    3593             :                 /* Fail with sharing violation. */
    3594           8 :                 state->status = NT_STATUS_SHARING_VIOLATION;
    3595           8 :                 return;
    3596             :         }
    3597             : 
    3598             :         /*
    3599             :          * Set the delete on close.
    3600             :          */
    3601         240 :         state->status = smb_set_file_disposition_info(state->fsp->conn,
    3602             :                                                       &del,
    3603             :                                                       1,
    3604         240 :                                                       state->fsp,
    3605             :                                                       state->smb_fname);
    3606             : }
    3607             : 
    3608         532 : static NTSTATUS smb_posix_unlink(connection_struct *conn,
    3609             :                                  struct smb_request *req,
    3610             :                                  const char *pdata,
    3611             :                                  int total_data,
    3612             :                                  struct files_struct *dirfsp,
    3613             :                                  struct smb_filename *smb_fname)
    3614             : {
    3615         532 :         struct smb_posix_unlink_state state = {};
    3616         532 :         NTSTATUS status = NT_STATUS_OK;
    3617         532 :         files_struct *fsp = NULL;
    3618         532 :         uint16_t flags = 0;
    3619         532 :         int info = 0;
    3620         532 :         int create_options = FILE_OPEN_REPARSE_POINT;
    3621         532 :         struct smb2_create_blobs *posx = NULL;
    3622             : 
    3623         532 :         if (!CAN_WRITE(conn)) {
    3624           0 :                 return NT_STATUS_DOS(ERRSRV, ERRaccess);
    3625             :         }
    3626             : 
    3627         532 :         if (total_data < 2) {
    3628           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3629             :         }
    3630             : 
    3631         532 :         flags = SVAL(pdata,0);
    3632             : 
    3633         532 :         if (!VALID_STAT(smb_fname->st)) {
    3634         276 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    3635             :         }
    3636             : 
    3637         256 :         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
    3638          40 :                         !VALID_STAT_OF_DIR(smb_fname->st)) {
    3639           0 :                 return NT_STATUS_NOT_A_DIRECTORY;
    3640             :         }
    3641             : 
    3642         256 :         DEBUG(10,("smb_posix_unlink: %s %s\n",
    3643             :                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
    3644             :                 smb_fname_str_dbg(smb_fname)));
    3645             : 
    3646         256 :         if (S_ISDIR(smb_fname->st.st_ex_mode)) {
    3647          44 :                 create_options |= FILE_DIRECTORY_FILE;
    3648             :         }
    3649             : 
    3650         256 :         status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
    3651         256 :         if (!NT_STATUS_IS_OK(status)) {
    3652           0 :                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
    3653             :                             nt_errstr(status));
    3654           0 :                 return status;
    3655             :         }
    3656             : 
    3657         256 :         status = SMB_VFS_CREATE_FILE(
    3658             :                 conn,                                   /* conn */
    3659             :                 req,                                    /* req */
    3660             :                 dirfsp,                                 /* 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 */
    3678             : 
    3679         256 :         TALLOC_FREE(posx);
    3680             : 
    3681         256 :         if (!NT_STATUS_IS_OK(status)) {
    3682           8 :                 return status;
    3683             :         }
    3684             : 
    3685             :         /*
    3686             :          * Don't lie to client. If we can't really delete due to
    3687             :          * non-POSIX opens return SHARING_VIOLATION.
    3688             :          */
    3689             : 
    3690         248 :         state = (struct smb_posix_unlink_state) {
    3691             :                 .smb_fname = smb_fname,
    3692             :                 .fsp = fsp,
    3693             :         };
    3694             : 
    3695         248 :         status = share_mode_do_locked_vfs_allowed(fsp->file_id,
    3696             :                                                   smb_posix_unlink_locked,
    3697             :                                                   &state);
    3698         248 :         if (!NT_STATUS_IS_OK(status)) {
    3699           0 :                 DBG_ERR("share_mode_do_locked_vfs_allowed(%s) failed - %s\n",
    3700             :                         fsp_str_dbg(fsp), nt_errstr(status));
    3701           0 :                 close_file_free(req, &fsp, NORMAL_CLOSE);
    3702           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3703             :         }
    3704             : 
    3705         248 :         status = state.status;
    3706         248 :         if (!NT_STATUS_IS_OK(status)) {
    3707           8 :                 close_file_free(req, &fsp, NORMAL_CLOSE);
    3708           8 :                 return status;
    3709             :         }
    3710         240 :         return close_file_free(req, &fsp, NORMAL_CLOSE);
    3711             : }
    3712             : 
    3713             : /****************************************************************************
    3714             :  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
    3715             : ****************************************************************************/
    3716             : 
    3717         128 : 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)
    3722             : {
    3723         128 :         char *link_target = NULL;
    3724           0 :         struct smb_filename target_fname;
    3725         128 :         TALLOC_CTX *ctx = talloc_tos();
    3726           0 :         NTSTATUS status;
    3727           0 :         int ret;
    3728         128 :         struct smb_filename *parent_fname = NULL;
    3729         128 :         struct smb_filename *base_name = NULL;
    3730             : 
    3731         128 :         if (!CAN_WRITE(conn)) {
    3732           0 :                 return NT_STATUS_DOS(ERRSRV, ERRaccess);
    3733             :         }
    3734             : 
    3735             :         /* Set a symbolic link. */
    3736             :         /* Don't allow this if follow links is false. */
    3737             : 
    3738         128 :         if (total_data == 0) {
    3739           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3740             :         }
    3741             : 
    3742         128 :         if (!lp_follow_symlinks(SNUM(conn))) {
    3743           0 :                 return NT_STATUS_ACCESS_DENIED;
    3744             :         }
    3745             : 
    3746         128 :         srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
    3747             :                     total_data, STR_TERMINATE);
    3748             : 
    3749         128 :         if (!link_target) {
    3750           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3751             :         }
    3752             : 
    3753         128 :         target_fname = (struct smb_filename) {
    3754             :                 .base_name = link_target,
    3755             :         };
    3756             : 
    3757             :         /* Removes @GMT tokens if any */
    3758         128 :         status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
    3759         128 :         if (!NT_STATUS_IS_OK(status)) {
    3760           0 :                 return status;
    3761             :         }
    3762             : 
    3763         128 :         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 ));
    3765             : 
    3766         128 :         status = parent_pathref(talloc_tos(),
    3767             :                                 conn->cwd_fsp,
    3768             :                                 new_smb_fname,
    3769             :                                 &parent_fname,
    3770             :                                 &base_name);
    3771         128 :         if (!NT_STATUS_IS_OK(status)) {
    3772           0 :                 return status;
    3773             :         }
    3774             : 
    3775         128 :         ret = SMB_VFS_SYMLINKAT(conn,
    3776             :                         &target_fname,
    3777             :                         parent_fname->fsp,
    3778             :                         base_name);
    3779         128 :         if (ret != 0) {
    3780           8 :                 TALLOC_FREE(parent_fname);
    3781           8 :                 return map_nt_error_from_unix(errno);
    3782             :         }
    3783             : 
    3784         120 :         TALLOC_FREE(parent_fname);
    3785         120 :         return NT_STATUS_OK;
    3786             : }
    3787             : 
    3788             : /****************************************************************************
    3789             :  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
    3790             : ****************************************************************************/
    3791             : 
    3792          16 : 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)
    3796             : {
    3797          16 :         char *oldname = NULL;
    3798          16 :         struct files_struct *src_dirfsp = NULL;
    3799          16 :         struct smb_filename *smb_fname_old = NULL;
    3800          16 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    3801          16 :         NTTIME old_twrp = 0;
    3802          16 :         TALLOC_CTX *ctx = talloc_tos();
    3803          16 :         NTSTATUS status = NT_STATUS_OK;
    3804             : 
    3805          16 :         if (!CAN_WRITE(conn)) {
    3806           0 :                 return NT_STATUS_DOS(ERRSRV, ERRaccess);
    3807             :         }
    3808             : 
    3809             :         /* Set a hard link. */
    3810          16 :         if (total_data == 0) {
    3811           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3812             :         }
    3813             : 
    3814          16 :         if (req->posix_pathnames) {
    3815          16 :                 srvstr_get_path_posix(ctx,
    3816             :                         pdata,
    3817          16 :                         req->flags2,
    3818             :                         &oldname,
    3819             :                         pdata,
    3820             :                         total_data,
    3821             :                         STR_TERMINATE,
    3822             :                         &status);
    3823             :         } else {
    3824           0 :                 srvstr_get_path(ctx,
    3825             :                         pdata,
    3826           0 :                         req->flags2,
    3827             :                         &oldname,
    3828             :                         pdata,
    3829             :                         total_data,
    3830             :                         STR_TERMINATE,
    3831             :                         &status);
    3832             :         }
    3833          16 :         if (!NT_STATUS_IS_OK(status)) {
    3834           0 :                 return status;
    3835             :         }
    3836             : 
    3837          16 :         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));
    3839             : 
    3840          16 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    3841           0 :                 extract_snapshot_token(oldname, &old_twrp);
    3842             :         }
    3843          16 :         status = smb1_strip_dfs_path(ctx, &ucf_flags, &oldname);
    3844          16 :         if (!NT_STATUS_IS_OK(status)) {
    3845           0 :                 return status;
    3846             :         }
    3847          16 :         status = filename_convert_dirfsp(ctx,
    3848             :                                          conn,
    3849             :                                          oldname,
    3850             :                                          ucf_flags,
    3851             :                                          old_twrp,
    3852             :                                          &src_dirfsp,
    3853             :                                          &smb_fname_old);
    3854          16 :         if (!NT_STATUS_IS_OK(status)) {
    3855           0 :                 return status;
    3856             :         }
    3857             : 
    3858          16 :         return hardlink_internals(ctx,
    3859             :                                   conn,
    3860             :                                   req,
    3861             :                                   false,
    3862             :                                   smb_fname_old,
    3863             :                                   smb_fname_new);
    3864             : }
    3865             : 
    3866             : /****************************************************************************
    3867             :  Allow a UNIX info mknod.
    3868             : ****************************************************************************/
    3869             : 
    3870           2 : static NTSTATUS smb_unix_mknod(connection_struct *conn,
    3871             :                                const char *pdata,
    3872             :                                int total_data,
    3873             :                                struct files_struct *dirfsp,
    3874             :                                const struct smb_filename *smb_fname)
    3875             : {
    3876           2 :         uint32_t file_type = IVAL(pdata,56);
    3877             : #if defined(HAVE_MAKEDEV)
    3878           2 :         uint32_t dev_major = IVAL(pdata,60);
    3879           2 :         uint32_t dev_minor = IVAL(pdata,68);
    3880             : #endif
    3881           2 :         SMB_DEV_T dev = (SMB_DEV_T)0;
    3882           2 :         uint32_t raw_unixmode = IVAL(pdata,84);
    3883           0 :         NTSTATUS status;
    3884           0 :         mode_t unixmode;
    3885           0 :         int ret;
    3886           2 :         struct smb_filename *parent_fname = NULL;
    3887           2 :         struct smb_filename *atname = NULL;
    3888             : 
    3889           2 :         if (total_data < 100) {
    3890           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3891             :         }
    3892             : 
    3893           2 :         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
    3894             :                                       PERM_NEW_FILE, &unixmode);
    3895           2 :         if (!NT_STATUS_IS_OK(status)) {
    3896           0 :                 return status;
    3897             :         }
    3898             : 
    3899             : #if defined(HAVE_MAKEDEV)
    3900           2 :         dev = makedev(dev_major, dev_minor);
    3901             : #endif
    3902             : 
    3903           2 :         switch (file_type) {
    3904             :                 /* We can't create other objects here. */
    3905           0 :                 case UNIX_TYPE_FILE:
    3906             :                 case UNIX_TYPE_DIR:
    3907             :                 case UNIX_TYPE_SYMLINK:
    3908           0 :                         return NT_STATUS_ACCESS_DENIED;
    3909             : #if defined(S_IFIFO)
    3910           1 :                 case UNIX_TYPE_FIFO:
    3911           1 :                         unixmode |= S_IFIFO;
    3912           1 :                         break;
    3913             : #endif
    3914             : #if defined(S_IFSOCK)
    3915           1 :                 case UNIX_TYPE_SOCKET:
    3916           1 :                         unixmode |= S_IFSOCK;
    3917           1 :                         break;
    3918             : #endif
    3919             : #if defined(S_IFCHR)
    3920           0 :                 case UNIX_TYPE_CHARDEV:
    3921             :                         /* This is only allowed for root. */
    3922           0 :                         if (get_current_uid(conn) != sec_initial_uid()) {
    3923           0 :                                 return NT_STATUS_ACCESS_DENIED;
    3924             :                         }
    3925           0 :                         unixmode |= S_IFCHR;
    3926           0 :                         break;
    3927             : #endif
    3928             : #if defined(S_IFBLK)
    3929           0 :                 case UNIX_TYPE_BLKDEV:
    3930           0 :                         if (get_current_uid(conn) != sec_initial_uid()) {
    3931           0 :                                 return NT_STATUS_ACCESS_DENIED;
    3932             :                         }
    3933           0 :                         unixmode |= S_IFBLK;
    3934           0 :                         break;
    3935             : #endif
    3936           0 :                 default:
    3937           0 :                         return NT_STATUS_INVALID_PARAMETER;
    3938             :         }
    3939             : 
    3940           2 :         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
    3941             :                   "%.0f mode 0%o for file %s\n", (double)dev,
    3942             :                   (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
    3943             : 
    3944           2 :         status = SMB_VFS_PARENT_PATHNAME(dirfsp->conn,
    3945             :                                          talloc_tos(),
    3946             :                                          smb_fname,
    3947             :                                          &parent_fname,
    3948             :                                          &atname);
    3949           2 :         if (!NT_STATUS_IS_OK(status)) {
    3950           0 :                 return status;
    3951             :         }
    3952             : 
    3953             :         /* Ok - do the mknod. */
    3954           2 :         ret = SMB_VFS_MKNODAT(conn,
    3955             :                               dirfsp,
    3956             :                               atname,
    3957             :                               unixmode,
    3958             :                               dev);
    3959             : 
    3960           2 :         if (ret != 0) {
    3961           0 :                 TALLOC_FREE(parent_fname);
    3962           0 :                 return map_nt_error_from_unix(errno);
    3963             :         }
    3964             : 
    3965             :         /* If any of the other "set" calls fail we
    3966             :          * don't want to end up with a half-constructed mknod.
    3967             :          */
    3968             : 
    3969           2 :         if (lp_inherit_permissions(SNUM(conn))) {
    3970           0 :                 inherit_access_posix_acl(conn,
    3971             :                                          dirfsp,
    3972             :                                          smb_fname,
    3973             :                                          unixmode);
    3974             :         }
    3975           2 :         TALLOC_FREE(parent_fname);
    3976             : 
    3977           2 :         return NT_STATUS_OK;
    3978             : }
    3979             : 
    3980             : /****************************************************************************
    3981             :  Deal with SMB_SET_FILE_UNIX_BASIC.
    3982             : ****************************************************************************/
    3983             : 
    3984         170 : static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
    3985             :                                         struct smb_request *req,
    3986             :                                         const char *pdata,
    3987             :                                         int total_data,
    3988             :                                         struct files_struct *dirfsp,
    3989             :                                         files_struct *fsp,
    3990             :                                         struct smb_filename *smb_fname)
    3991             : {
    3992           0 :         struct smb_file_time ft;
    3993           0 :         uint32_t raw_unixmode;
    3994           0 :         mode_t unixmode;
    3995         170 :         off_t size = 0;
    3996         170 :         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
    3997         170 :         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
    3998         170 :         NTSTATUS status = NT_STATUS_OK;
    3999           0 :         enum perm_type ptype;
    4000         170 :         files_struct *all_fsps = NULL;
    4001         170 :         bool modify_mtime = true;
    4002           0 :         struct file_id id;
    4003           0 :         SMB_STRUCT_STAT sbuf;
    4004             : 
    4005         170 :         if (!CAN_WRITE(conn)) {
    4006           0 :                 return NT_STATUS_DOS(ERRSRV, ERRaccess);
    4007             :         }
    4008             : 
    4009         170 :         init_smb_file_time(&ft);
    4010             : 
    4011         170 :         if (total_data < 100) {
    4012           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4013             :         }
    4014             : 
    4015         170 :         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
    4016          16 :            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
    4017          16 :                 size=IVAL(pdata,0); /* first 8 Bytes are size */
    4018          16 :                 size |= (((off_t)IVAL(pdata,4)) << 32);
    4019             :         }
    4020             : 
    4021         170 :         ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
    4022         170 :         ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
    4023         170 :         set_owner = (uid_t)IVAL(pdata,40);
    4024         170 :         set_grp = (gid_t)IVAL(pdata,48);
    4025         170 :         raw_unixmode = IVAL(pdata,84);
    4026             : 
    4027         170 :         if (VALID_STAT(smb_fname->st)) {
    4028         168 :                 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
    4029           4 :                         ptype = PERM_EXISTING_DIR;
    4030             :                 } else {
    4031         164 :                         ptype = PERM_EXISTING_FILE;
    4032             :                 }
    4033             :         } else {
    4034           2 :                 ptype = PERM_NEW_FILE;
    4035             :         }
    4036             : 
    4037         170 :         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
    4038             :                                       ptype, &unixmode);
    4039         170 :         if (!NT_STATUS_IS_OK(status)) {
    4040           0 :                 return status;
    4041             :         }
    4042             : 
    4043         170 :         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));
    4048             : 
    4049         170 :         sbuf = smb_fname->st;
    4050             : 
    4051         170 :         if (!VALID_STAT(sbuf)) {
    4052             :                 /*
    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.
    4056             :                  */
    4057             : 
    4058           2 :                 if (dirfsp == NULL) {
    4059           0 :                         return NT_STATUS_INVALID_PARAMETER;
    4060             :                 }
    4061             : 
    4062           2 :                 return smb_unix_mknod(conn,
    4063             :                                       pdata,
    4064             :                                       total_data,
    4065             :                                       dirfsp,
    4066             :                                       smb_fname);
    4067             :         }
    4068             : 
    4069             : #if 1
    4070             :         /* Horrible backwards compatibility hack as an old server bug
    4071             :          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
    4072             :          * */
    4073             : 
    4074         168 :         if (!size) {
    4075         168 :                 size = get_file_size_stat(&sbuf);
    4076             :         }
    4077             : #endif
    4078             : 
    4079             :         /*
    4080             :          * Deal with the UNIX specific mode set.
    4081             :          */
    4082             : 
    4083         168 :         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
    4084           0 :                 int ret;
    4085             : 
    4086          36 :                 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
    4087          24 :                         DBG_WARNING("Can't set mode on symlink %s\n",
    4088             :                                 smb_fname_str_dbg(smb_fname));
    4089          24 :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    4090             :                 }
    4091             : 
    4092          12 :                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
    4093             :                           "setting mode 0%o for file %s\n",
    4094             :                           (unsigned int)unixmode,
    4095             :                           smb_fname_str_dbg(smb_fname)));
    4096          12 :                 ret = SMB_VFS_FCHMOD(fsp, unixmode);
    4097          12 :                 if (ret != 0) {
    4098           0 :                         return map_nt_error_from_unix(errno);
    4099             :                 }
    4100             :         }
    4101             : 
    4102             :         /*
    4103             :          * Deal with the UNIX specific uid set.
    4104             :          */
    4105             : 
    4106         144 :         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
    4107           0 :             (sbuf.st_ex_uid != set_owner)) {
    4108           0 :                 int ret;
    4109             : 
    4110           0 :                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
    4111             :                           "changing owner %u for path %s\n",
    4112             :                           (unsigned int)set_owner,
    4113             :                           smb_fname_str_dbg(smb_fname)));
    4114             : 
    4115           0 :                 if (fsp &&
    4116           0 :                     !fsp->fsp_flags.is_pathref &&
    4117           0 :                     fsp_get_io_fd(fsp) != -1)
    4118             :                 {
    4119           0 :                         ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
    4120             :                 } else {
    4121             :                         /*
    4122             :                          * UNIX extensions calls must always operate
    4123             :                          * on symlinks.
    4124             :                          */
    4125           0 :                         ret = SMB_VFS_LCHOWN(conn, smb_fname,
    4126             :                                              set_owner, (gid_t)-1);
    4127             :                 }
    4128             : 
    4129           0 :                 if (ret != 0) {
    4130           0 :                         status = map_nt_error_from_unix(errno);
    4131           0 :                         return status;
    4132             :                 }
    4133             :         }
    4134             : 
    4135             :         /*
    4136             :          * Deal with the UNIX specific gid set.
    4137             :          */
    4138             : 
    4139         144 :         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
    4140           0 :             (sbuf.st_ex_gid != set_grp)) {
    4141           0 :                 int ret;
    4142             : 
    4143           0 :                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
    4144             :                           "changing group %u for file %s\n",
    4145             :                           (unsigned int)set_grp,
    4146             :                           smb_fname_str_dbg(smb_fname)));
    4147           0 :                 if (fsp &&
    4148           0 :                     !fsp->fsp_flags.is_pathref &&
    4149           0 :                     fsp_get_io_fd(fsp) != -1)
    4150             :                 {
    4151           0 :                         ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
    4152             :                 } else {
    4153             :                         /*
    4154             :                          * UNIX extensions calls must always operate
    4155             :                          * on symlinks.
    4156             :                          */
    4157           0 :                         ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
    4158             :                                   set_grp);
    4159             :                 }
    4160           0 :                 if (ret != 0) {
    4161           0 :                         status = map_nt_error_from_unix(errno);
    4162           0 :                         return status;
    4163             :                 }
    4164             :         }
    4165             : 
    4166             :         /* Deal with any size changes. */
    4167             : 
    4168         144 :         if (S_ISREG(sbuf.st_ex_mode)) {
    4169         140 :                 status = smb_set_file_size(conn, req,
    4170             :                                            fsp,
    4171             :                                            smb_fname,
    4172             :                                            &sbuf,
    4173             :                                            size,
    4174             :                                            false);
    4175         140 :                 if (!NT_STATUS_IS_OK(status)) {
    4176           0 :                         return status;
    4177             :                 }
    4178             :         }
    4179             : 
    4180             :         /* Deal with any time changes. */
    4181         144 :         if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
    4182             :                 /* No change, don't cancel anything. */
    4183         144 :                 return status;
    4184             :         }
    4185             : 
    4186           0 :         id = vfs_file_id_from_sbuf(conn, &sbuf);
    4187           0 :         for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
    4188           0 :                         all_fsps = file_find_di_next(all_fsps, true)) {
    4189             :                 /*
    4190             :                  * We're setting the time explicitly for UNIX.
    4191             :                  * Cancel any pending changes over all handles.
    4192             :                  */
    4193           0 :                 all_fsps->fsp_flags.update_write_time_on_close = false;
    4194           0 :                 TALLOC_FREE(all_fsps->update_write_time_event);
    4195             :         }
    4196             : 
    4197             :         /*
    4198             :          * Override the "setting_write_time"
    4199             :          * parameter here as it almost does what
    4200             :          * we need. Just remember if we modified
    4201             :          * mtime and send the notify ourselves.
    4202             :          */
    4203           0 :         if (is_omit_timespec(&ft.mtime)) {
    4204           0 :                 modify_mtime = false;
    4205             :         }
    4206             : 
    4207           0 :         status = smb_set_file_time(conn,
    4208             :                                 fsp,
    4209             :                                 smb_fname,
    4210             :                                 &ft,
    4211             :                                 false);
    4212           0 :         if (modify_mtime) {
    4213           0 :                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
    4214           0 :                         FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
    4215             :         }
    4216           0 :         return status;
    4217             : }
    4218             : 
    4219             : /****************************************************************************
    4220             :  Deal with SMB_SET_FILE_UNIX_INFO2.
    4221             : ****************************************************************************/
    4222             : 
    4223         140 : static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
    4224             :                                         struct smb_request *req,
    4225             :                                         const char *pdata,
    4226             :                                         int total_data,
    4227             :                                         struct files_struct *dirfsp,
    4228             :                                         files_struct *fsp,
    4229             :                                         struct smb_filename *smb_fname)
    4230             : {
    4231           0 :         NTSTATUS status;
    4232           0 :         uint32_t smb_fflags;
    4233           0 :         uint32_t smb_fmask;
    4234             : 
    4235         140 :         if (!CAN_WRITE(conn)) {
    4236           0 :                 return NT_STATUS_DOS(ERRSRV, ERRaccess);
    4237             :         }
    4238             : 
    4239         140 :         if (total_data < 116) {
    4240           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4241             :         }
    4242             : 
    4243             :         /* Start by setting all the fields that are common between UNIX_BASIC
    4244             :          * and UNIX_INFO2.
    4245             :          */
    4246         140 :         status = smb_set_file_unix_basic(conn,
    4247             :                                          req,
    4248             :                                          pdata,
    4249             :                                          total_data,
    4250             :                                          dirfsp,
    4251             :                                          fsp,
    4252             :                                          smb_fname);
    4253         140 :         if (!NT_STATUS_IS_OK(status)) {
    4254           8 :                 return status;
    4255             :         }
    4256             : 
    4257         132 :         smb_fflags = IVAL(pdata, 108);
    4258         132 :         smb_fmask = IVAL(pdata, 112);
    4259             : 
    4260             :         /* NB: We should only attempt to alter the file flags if the client
    4261             :          * sends a non-zero mask.
    4262             :          */
    4263         132 :         if (smb_fmask != 0) {
    4264         128 :                 int stat_fflags = 0;
    4265             : 
    4266         128 :                 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
    4267             :                                              smb_fmask, &stat_fflags)) {
    4268             :                         /* Client asked to alter a flag we don't understand. */
    4269         128 :                         return NT_STATUS_INVALID_PARAMETER;
    4270             :                 }
    4271             : 
    4272           0 :                 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
    4273           0 :                         DBG_WARNING("Can't change flags on symlink %s\n",
    4274             :                                 smb_fname_str_dbg(smb_fname));
    4275           0 :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    4276             :                 }
    4277           0 :                 if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) {
    4278           0 :                         return map_nt_error_from_unix(errno);
    4279             :                 }
    4280             :         }
    4281             : 
    4282             :         /* XXX: need to add support for changing the create_time here. You
    4283             :          * can do this for paths on Darwin with setattrlist(2). The right way
    4284             :          * to hook this up is probably by extending the VFS utimes interface.
    4285             :          */
    4286             : 
    4287           4 :         return NT_STATUS_OK;
    4288             : }
    4289             : 
    4290             : /****************************************************************************
    4291             :  Deal with SMB_SET_POSIX_ACL.
    4292             : ****************************************************************************/
    4293             : 
    4294          16 : static NTSTATUS smb_set_posix_acl(connection_struct *conn,
    4295             :                                 struct smb_request *req,
    4296             :                                 const char *pdata,
    4297             :                                 int total_data_in,
    4298             :                                 files_struct *fsp,
    4299             :                                 struct smb_filename *smb_fname)
    4300             : {
    4301             : #if !defined(HAVE_POSIX_ACLS)
    4302             :         return NT_STATUS_INVALID_LEVEL;
    4303             : #else
    4304           0 :         uint16_t posix_acl_version;
    4305           0 :         uint16_t num_file_acls;
    4306           0 :         uint16_t num_def_acls;
    4307          16 :         bool valid_file_acls = true;
    4308          16 :         bool valid_def_acls = true;
    4309           0 :         NTSTATUS status;
    4310           0 :         unsigned int size_needed;
    4311           0 :         unsigned int total_data;
    4312          16 :         bool close_fsp = false;
    4313             : 
    4314          16 :         if (total_data_in < 0) {
    4315           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4316           0 :                 goto out;
    4317             :         }
    4318             : 
    4319          16 :         total_data = total_data_in;
    4320             : 
    4321          16 :         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
    4322           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4323           0 :                 goto out;
    4324             :         }
    4325          16 :         posix_acl_version = SVAL(pdata,0);
    4326          16 :         num_file_acls = SVAL(pdata,2);
    4327          16 :         num_def_acls = SVAL(pdata,4);
    4328             : 
    4329          16 :         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
    4330           4 :                 valid_file_acls = false;
    4331           4 :                 num_file_acls = 0;
    4332             :         }
    4333             : 
    4334          16 :         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
    4335           0 :                 valid_def_acls = false;
    4336           0 :                 num_def_acls = 0;
    4337             :         }
    4338             : 
    4339          16 :         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
    4340           8 :                 status = NT_STATUS_INVALID_PARAMETER;
    4341           8 :                 goto out;
    4342             :         }
    4343             : 
    4344             :         /* Wrap checks. */
    4345           0 :         if (num_file_acls + num_def_acls < num_file_acls) {
    4346             :                 status = NT_STATUS_INVALID_PARAMETER;
    4347             :                 goto out;
    4348             :         }
    4349             : 
    4350           8 :         size_needed = num_file_acls + num_def_acls;
    4351             : 
    4352             :         /*
    4353             :          * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
    4354             :          * than UINT_MAX, so check by division.
    4355             :          */
    4356           8 :         if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
    4357           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4358           0 :                 goto out;
    4359             :         }
    4360             : 
    4361           8 :         size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
    4362           8 :         if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
    4363           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4364           0 :                 goto out;
    4365             :         }
    4366           8 :         size_needed += SMB_POSIX_ACL_HEADER_SIZE;
    4367             : 
    4368           8 :         if (total_data < size_needed) {
    4369           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4370           0 :                 goto out;
    4371             :         }
    4372             : 
    4373             :         /*
    4374             :          * Ensure we always operate on a file descriptor, not just
    4375             :          * the filename.
    4376             :          */
    4377           8 :         if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
    4378           8 :                 uint32_t access_mask = SEC_STD_WRITE_OWNER|
    4379             :                                         SEC_STD_WRITE_DAC|
    4380             :                                         SEC_STD_READ_CONTROL|
    4381             :                                         FILE_READ_ATTRIBUTES|
    4382             :                                         FILE_WRITE_ATTRIBUTES;
    4383             : 
    4384           8 :                 status = get_posix_fsp(conn,
    4385             :                                         req,
    4386             :                                         smb_fname,
    4387             :                                         access_mask,
    4388             :                                         &fsp);
    4389             : 
    4390           8 :                 if (!NT_STATUS_IS_OK(status)) {
    4391           4 :                         goto out;
    4392             :                 }
    4393           4 :                 close_fsp = true;
    4394             :         }
    4395             : 
    4396             :         /* Here we know fsp != NULL */
    4397           4 :         SMB_ASSERT(fsp != NULL);
    4398             : 
    4399           4 :         status = refuse_symlink_fsp(fsp);
    4400           4 :         if (!NT_STATUS_IS_OK(status)) {
    4401           0 :                 goto out;
    4402             :         }
    4403             : 
    4404             :         /* If we have a default acl, this *must* be a directory. */
    4405           4 :         if (valid_def_acls && !fsp->fsp_flags.is_directory) {
    4406           0 :                 DBG_INFO("Can't set default acls on "
    4407             :                          "non-directory %s\n",
    4408             :                          fsp_str_dbg(fsp));
    4409           0 :                 return NT_STATUS_INVALID_HANDLE;
    4410             :         }
    4411             : 
    4412           4 :         DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
    4413             :                   "num_def_acls = %"PRIu16"\n",
    4414             :                   fsp_str_dbg(fsp),
    4415             :                   num_file_acls,
    4416             :                   num_def_acls);
    4417             : 
    4418             :         /* Move pdata to the start of the file ACL entries. */
    4419           4 :         pdata += SMB_POSIX_ACL_HEADER_SIZE;
    4420             : 
    4421           4 :         if (valid_file_acls) {
    4422           0 :                 status = set_unix_posix_acl(conn,
    4423             :                                         fsp,
    4424             :                                         num_file_acls,
    4425             :                                         pdata);
    4426           0 :                 if (!NT_STATUS_IS_OK(status)) {
    4427           0 :                         goto out;
    4428             :                 }
    4429             :         }
    4430             : 
    4431             :         /* Move pdata to the start of the default ACL entries. */
    4432           4 :         pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
    4433             : 
    4434           4 :         if (valid_def_acls) {
    4435           4 :                 status = set_unix_posix_default_acl(conn,
    4436             :                                         fsp,
    4437             :                                         num_def_acls,
    4438             :                                         pdata);
    4439           4 :                 if (!NT_STATUS_IS_OK(status)) {
    4440           0 :                         goto out;
    4441             :                 }
    4442             :         }
    4443             : 
    4444           4 :         status = NT_STATUS_OK;
    4445             : 
    4446          16 :   out:
    4447             : 
    4448          16 :         if (close_fsp) {
    4449           4 :                 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
    4450             :         }
    4451          16 :         return status;
    4452             : #endif
    4453             : }
    4454             : 
    4455        1408 : static void call_trans2setpathinfo(
    4456             :         connection_struct *conn,
    4457             :         struct smb_request *req,
    4458             :         char **pparams,
    4459             :         int total_params,
    4460             :         char **ppdata,
    4461             :         int total_data,
    4462             :         unsigned int max_data_bytes)
    4463             : {
    4464          12 :         uint16_t info_level;
    4465        1408 :         struct smb_filename *smb_fname = NULL;
    4466        1408 :         struct files_struct *dirfsp = NULL;
    4467        1408 :         struct files_struct *fsp = NULL;
    4468        1408 :         char *params = *pparams;
    4469        1408 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    4470        1408 :         NTTIME twrp = 0;
    4471        1408 :         char *fname = NULL;
    4472          12 :         bool info_level_handled;
    4473        1408 :         int data_return_size = 0;
    4474          12 :         NTSTATUS status;
    4475             : 
    4476        1408 :         if (params == NULL) {
    4477           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4478           0 :                 return;
    4479             :         }
    4480             : 
    4481             :         /* set path info */
    4482        1408 :         if (total_params < 7) {
    4483           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4484           0 :                 return;
    4485             :         }
    4486             : 
    4487        1408 :         info_level = SVAL(params,0);
    4488             : 
    4489        1408 :         if (INFO_LEVEL_IS_UNIX(info_level)) {
    4490        1110 :                 if (!lp_smb1_unix_extensions()) {
    4491           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    4492           0 :                         return;
    4493             :                 }
    4494        1110 :                 if (!req->posix_pathnames) {
    4495           6 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    4496           6 :                         return;
    4497             :                 }
    4498             :         }
    4499             : 
    4500        1402 :         if (req->posix_pathnames) {
    4501        1208 :                 srvstr_get_path_posix(req,
    4502             :                                       params,
    4503        1208 :                                       req->flags2,
    4504             :                                       &fname,
    4505        1208 :                                       &params[6],
    4506        1208 :                                       total_params - 6,
    4507             :                                       STR_TERMINATE,
    4508             :                                       &status);
    4509             :         } else {
    4510         194 :                 srvstr_get_path(req,
    4511             :                                 params,
    4512         194 :                                 req->flags2,
    4513             :                                 &fname,
    4514         194 :                                 &params[6],
    4515         194 :                                 total_params - 6,
    4516             :                                 STR_TERMINATE,
    4517             :                                 &status);
    4518             :         }
    4519        1402 :         if (!NT_STATUS_IS_OK(status)) {
    4520           0 :                 reply_nterror(req, status);
    4521           0 :                 return;
    4522             :         }
    4523             : 
    4524        1402 :         DBG_NOTICE("fname=%s info_level=%d totdata=%d\n",
    4525             :                    fname,
    4526             :                    info_level,
    4527             :                    total_data);
    4528             : 
    4529        1402 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    4530           0 :                 extract_snapshot_token(fname, &twrp);
    4531             :         }
    4532        1402 :         status = smb1_strip_dfs_path(req, &ucf_flags, &fname);
    4533        1402 :         if (!NT_STATUS_IS_OK(status)) {
    4534           0 :                 reply_nterror(req, status);
    4535           0 :                 return;
    4536             :         }
    4537        1402 :         status = filename_convert_dirfsp(req,
    4538             :                                          conn,
    4539             :                                          fname,
    4540             :                                          ucf_flags,
    4541             :                                          twrp,
    4542             :                                          &dirfsp,
    4543             :                                          &smb_fname);
    4544        1402 :         if (!NT_STATUS_IS_OK(status)) {
    4545          60 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    4546           0 :                         reply_botherror(req,
    4547             :                                         NT_STATUS_PATH_NOT_COVERED,
    4548             :                                         ERRSRV, ERRbadpath);
    4549           0 :                         return;
    4550             :                 }
    4551          60 :                 reply_nterror(req, status);
    4552          60 :                 return;
    4553             :         }
    4554             : 
    4555        1342 :         info_level_handled = true; /* Untouched in switch cases below */
    4556             : 
    4557        1342 :         switch (info_level) {
    4558             : 
    4559         294 :         default:
    4560         294 :                 info_level_handled = false;
    4561         294 :                 break;
    4562             : 
    4563         174 :         case SMB_POSIX_PATH_OPEN:
    4564         174 :                 status = smb_posix_open(conn,
    4565             :                                         req,
    4566             :                                         ppdata,
    4567             :                                         total_data,
    4568             :                                         dirfsp,
    4569             :                                         smb_fname,
    4570             :                                         &data_return_size);
    4571         174 :                 break;
    4572             : 
    4573         532 :         case SMB_POSIX_PATH_UNLINK:
    4574         532 :                 status = smb_posix_unlink(conn,
    4575             :                                           req,
    4576             :                                           *ppdata,
    4577             :                                           total_data,
    4578             :                                           dirfsp,
    4579             :                                           smb_fname);
    4580         532 :                 break;
    4581             : 
    4582         128 :         case SMB_SET_FILE_UNIX_LINK:
    4583         128 :                 status = smb_set_file_unix_link(
    4584             :                         conn, req, *ppdata, total_data, smb_fname);
    4585         128 :                 break;
    4586             : 
    4587          16 :         case SMB_SET_FILE_UNIX_HLINK:
    4588          16 :                 status = smb_set_file_unix_hlink(
    4589             :                         conn, req, *ppdata, total_data, smb_fname);
    4590          16 :                 break;
    4591             : 
    4592          30 :         case SMB_SET_FILE_UNIX_BASIC:
    4593          30 :                 status = smb_set_file_unix_basic(conn,
    4594             :                                                  req,
    4595             :                                                  *ppdata,
    4596             :                                                  total_data,
    4597             :                                                  dirfsp,
    4598          30 :                                                  smb_fname->fsp,
    4599             :                                                  smb_fname);
    4600          30 :                 break;
    4601             : 
    4602         140 :         case SMB_SET_FILE_UNIX_INFO2:
    4603         140 :                 status = smb_set_file_unix_info2(conn,
    4604             :                                                  req,
    4605             :                                                  *ppdata,
    4606             :                                                  total_data,
    4607             :                                                  dirfsp,
    4608         140 :                                                  smb_fname->fsp,
    4609             :                                                  smb_fname);
    4610         140 :                 break;
    4611          16 :         case SMB_SET_POSIX_ACL:
    4612          16 :                 status = smb_set_posix_acl(
    4613             :                         conn, req, *ppdata, total_data, NULL, smb_fname);
    4614          16 :                 break;
    4615             :         }
    4616             : 
    4617        1330 :         if (info_level_handled) {
    4618        1036 :                 handle_trans2setfilepathinfo_result(
    4619             :                         conn,
    4620             :                         req,
    4621             :                         info_level,
    4622             :                         status,
    4623             :                         *ppdata,
    4624             :                         data_return_size,
    4625             :                         max_data_bytes);
    4626        1036 :                 return;
    4627             :         }
    4628             : 
    4629             :         /*
    4630             :          * smb_fname->fsp may be NULL if smb_fname points at a symlink
    4631             :          * and we're in POSIX context, so be careful when using fsp
    4632             :          * below, it can still be NULL.
    4633             :          */
    4634         306 :         fsp = smb_fname->fsp;
    4635             : 
    4636         306 :         status = smbd_do_setfilepathinfo(
    4637             :                 conn,
    4638             :                 req,
    4639             :                 req,
    4640             :                 info_level,
    4641             :                 fsp,
    4642             :                 smb_fname,
    4643             :                 ppdata,
    4644             :                 total_data,
    4645             :                 &data_return_size);
    4646             : 
    4647         306 :         handle_trans2setfilepathinfo_result(
    4648             :                 conn,
    4649             :                 req,
    4650             :                 info_level,
    4651             :                 status,
    4652             :                 *ppdata,
    4653             :                 data_return_size,
    4654             :                 max_data_bytes);
    4655             : }
    4656             : 
    4657        4265 : static void call_trans2setfileinfo(
    4658             :         connection_struct *conn,
    4659             :         struct smb_request *req,
    4660             :         char **pparams,
    4661             :         int total_params,
    4662             :         char **ppdata,
    4663             :         int total_data,
    4664             :         unsigned int max_data_bytes)
    4665             : {
    4666        4265 :         char *pdata = *ppdata;
    4667         537 :         uint16_t info_level;
    4668        4265 :         struct smb_filename *smb_fname = NULL;
    4669        4265 :         struct files_struct *fsp = NULL;
    4670        4265 :         char *params = *pparams;
    4671        4265 :         int data_return_size = 0;
    4672         537 :         bool info_level_handled;
    4673         537 :         NTSTATUS status;
    4674         537 :         int ret;
    4675             : 
    4676        4265 :         if (params == NULL) {
    4677           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4678           0 :                 return;
    4679             :         }
    4680        4265 :         if (total_params < 4) {
    4681           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4682           0 :                 return;
    4683             :         }
    4684             : 
    4685        4265 :         fsp = file_fsp(req, SVAL(params,0));
    4686             :         /* Basic check for non-null fsp. */
    4687        4265 :         if (!check_fsp_open(conn, req, fsp)) {
    4688           0 :                 return;
    4689             :         }
    4690        4265 :         info_level = SVAL(params,2);
    4691             : 
    4692        4265 :         if (INFO_LEVEL_IS_UNIX(info_level)) {
    4693          36 :                 if (!lp_smb1_unix_extensions()) {
    4694           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    4695           0 :                         return;
    4696             :                 }
    4697          36 :                 if (!req->posix_pathnames) {
    4698           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    4699           0 :                         return;
    4700             :                 }
    4701             :         }
    4702             : 
    4703        4265 :         smb_fname = fsp->fsp_name;
    4704             : 
    4705        4265 :         DBG_NOTICE("fnum=%s fname=%s info_level=%d totdata=%d\n",
    4706             :                    fsp_fnum_dbg(fsp),
    4707             :                    fsp_str_dbg(fsp),
    4708             :                    info_level,
    4709             :                    total_data);
    4710             : 
    4711        4265 :         if (fsp_get_pathref_fd(fsp) == -1) {
    4712             :                 /*
    4713             :                  * This is actually a SETFILEINFO on a directory
    4714             :                  * handle (returned from an NT SMB). NT5.0 seems
    4715             :                  * to do this call. JRA.
    4716             :                  */
    4717           0 :                 ret = vfs_stat(conn, smb_fname);
    4718           0 :                 if (ret != 0) {
    4719           0 :                         DBG_NOTICE("vfs_stat of %s failed (%s)\n",
    4720             :                                    smb_fname_str_dbg(smb_fname),
    4721             :                                    strerror(errno));
    4722           0 :                         reply_nterror(req, map_nt_error_from_unix(errno));
    4723           0 :                         return;
    4724             :                 }
    4725        4265 :         } else if (fsp->print_file) {
    4726             :                 /*
    4727             :                  * Doing a DELETE_ON_CLOSE should cancel a print job.
    4728             :                  */
    4729           2 :                 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) &&
    4730           2 :                     CVAL(pdata,0)) {
    4731             : 
    4732           2 :                         fsp->fsp_flags.delete_on_close = true;
    4733             : 
    4734           2 :                         DBG_NOTICE("Cancelling print job (%s)\n",
    4735             :                                    fsp_str_dbg(fsp));
    4736             : 
    4737           2 :                         SSVAL(params,0,0);
    4738           2 :                         send_trans2_replies(
    4739             :                                 conn,
    4740             :                                 req,
    4741           2 :                                 NT_STATUS_OK,
    4742             :                                 params,
    4743             :                                 2,
    4744             :                                 *ppdata, 0,
    4745             :                                 max_data_bytes);
    4746           2 :                         return;
    4747             :                 } else {
    4748           0 :                         reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
    4749           0 :                         return;
    4750             :                 }
    4751             :         } else {
    4752             :                 /*
    4753             :                  * Original code - this is an open file.
    4754             :                  */
    4755        4263 :                 status = vfs_stat_fsp(fsp);
    4756        4263 :                 if (!NT_STATUS_IS_OK(status)) {
    4757           0 :                         DBG_NOTICE("fstat of %s failed (%s)\n",
    4758             :                                    fsp_fnum_dbg(fsp),
    4759             :                                    nt_errstr(status));
    4760           0 :                         reply_nterror(req, status);
    4761           0 :                         return;
    4762             :                 }
    4763             :         }
    4764             : 
    4765        4263 :         info_level_handled = true; /* Untouched in switch cases below */
    4766             : 
    4767        4263 :         switch (info_level) {
    4768             : 
    4769        3690 :         default:
    4770        3690 :                 info_level_handled = false;
    4771        3690 :                 break;
    4772             : 
    4773           0 :         case SMB_SET_FILE_UNIX_BASIC:
    4774           0 :                 status = smb_set_file_unix_basic(conn,
    4775             :                                                  req,
    4776             :                                                  pdata,
    4777             :                                                  total_data,
    4778             :                                                  NULL,
    4779             :                                                  fsp,
    4780             :                                                  smb_fname);
    4781           0 :                 break;
    4782             : 
    4783           0 :         case SMB_SET_FILE_UNIX_INFO2:
    4784           0 :                 status = smb_set_file_unix_info2(conn,
    4785             :                                                  req,
    4786             :                                                  pdata,
    4787             :                                                  total_data,
    4788             :                                                  NULL,
    4789             :                                                  fsp,
    4790             :                                                  smb_fname);
    4791           0 :                 break;
    4792             : 
    4793          36 :         case SMB_SET_POSIX_LOCK:
    4794          36 :                 status = smb_set_posix_lock(
    4795             :                         conn, req, *ppdata, total_data, fsp);
    4796          36 :                 break;
    4797             :         }
    4798             : 
    4799        3726 :         if (info_level_handled) {
    4800          36 :                 handle_trans2setfilepathinfo_result(
    4801             :                         conn,
    4802             :                         req,
    4803             :                         info_level,
    4804             :                         status,
    4805             :                         *ppdata,
    4806             :                         data_return_size,
    4807             :                         max_data_bytes);
    4808          36 :                 return;
    4809             :         }
    4810             : 
    4811        4227 :         status = smbd_do_setfilepathinfo(
    4812             :                 conn,
    4813             :                 req,
    4814             :                 req,
    4815             :                 info_level,
    4816             :                 fsp,
    4817             :                 smb_fname,
    4818             :                 ppdata,
    4819             :                 total_data,
    4820             :                 &data_return_size);
    4821             : 
    4822        4227 :         handle_trans2setfilepathinfo_result(
    4823             :                 conn,
    4824             :                 req,
    4825             :                 info_level,
    4826             :                 status,
    4827             :                 *ppdata,
    4828             :                 data_return_size,
    4829             :                 max_data_bytes);
    4830             : }
    4831             : 
    4832             : /****************************************************************************
    4833             :  Reply to a TRANS2_MKDIR (make directory with extended attributes).
    4834             : ****************************************************************************/
    4835             : 
    4836          23 : static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
    4837             :                              char **pparams, int total_params,
    4838             :                              char **ppdata, int total_data,
    4839             :                              unsigned int max_data_bytes)
    4840             : {
    4841          23 :         struct files_struct *dirfsp = NULL;
    4842          23 :         struct files_struct *fsp = NULL;
    4843          23 :         struct smb_filename *smb_dname = NULL;
    4844          23 :         char *params = *pparams;
    4845          23 :         char *pdata = *ppdata;
    4846          23 :         char *directory = NULL;
    4847          23 :         NTSTATUS status = NT_STATUS_OK;
    4848          23 :         struct ea_list *ea_list = NULL;
    4849          23 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    4850          23 :         NTTIME twrp = 0;
    4851          23 :         TALLOC_CTX *ctx = talloc_tos();
    4852             : 
    4853          23 :         if (!CAN_WRITE(conn)) {
    4854           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    4855           0 :                 return;
    4856             :         }
    4857             : 
    4858          23 :         if (total_params < 5) {
    4859           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4860           0 :                 return;
    4861             :         }
    4862             : 
    4863          23 :         if (req->posix_pathnames) {
    4864           0 :                 srvstr_get_path_posix(ctx,
    4865             :                         params,
    4866           0 :                         req->flags2,
    4867             :                         &directory,
    4868           0 :                         &params[4],
    4869           0 :                         total_params - 4,
    4870             :                         STR_TERMINATE,
    4871             :                         &status);
    4872             :         } else {
    4873          23 :                 srvstr_get_path(ctx,
    4874             :                         params,
    4875          23 :                         req->flags2,
    4876             :                         &directory,
    4877          23 :                         &params[4],
    4878          23 :                         total_params - 4,
    4879             :                         STR_TERMINATE,
    4880             :                         &status);
    4881             :         }
    4882          23 :         if (!NT_STATUS_IS_OK(status)) {
    4883           0 :                 reply_nterror(req, status);
    4884           0 :                 return;
    4885             :         }
    4886             : 
    4887          23 :         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
    4888             : 
    4889          23 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    4890           0 :                 extract_snapshot_token(directory, &twrp);
    4891             :         }
    4892          23 :         status = smb1_strip_dfs_path(ctx, &ucf_flags, &directory);
    4893          23 :         if (!NT_STATUS_IS_OK(status)) {
    4894           0 :                 reply_nterror(req, status);
    4895           0 :                 goto out;
    4896             :         }
    4897          23 :         status = filename_convert_dirfsp(ctx,
    4898             :                                          conn,
    4899             :                                          directory,
    4900             :                                          ucf_flags,
    4901             :                                          twrp,
    4902             :                                          &dirfsp,
    4903             :                                          &smb_dname);
    4904          23 :         if (!NT_STATUS_IS_OK(status)) {
    4905           5 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    4906           0 :                         reply_botherror(req,
    4907             :                                 NT_STATUS_PATH_NOT_COVERED,
    4908             :                                 ERRSRV, ERRbadpath);
    4909           0 :                         return;
    4910             :                 }
    4911           5 :                 reply_nterror(req, status);
    4912           5 :                 return;
    4913             :         }
    4914             : 
    4915             :         /*
    4916             :          * OS/2 workplace shell seems to send SET_EA requests of "null"
    4917             :          * length (4 bytes containing IVAL 4).
    4918             :          * They seem to have no effect. Bug #3212. JRA.
    4919             :          */
    4920             : 
    4921          18 :         if (total_data && (total_data != 4)) {
    4922             :                 /* Any data in this call is an EA list. */
    4923           5 :                 if (total_data < 10) {
    4924           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4925           0 :                         goto out;
    4926             :                 }
    4927             : 
    4928           5 :                 if (IVAL(pdata,0) > total_data) {
    4929           0 :                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
    4930             :                                 IVAL(pdata,0), (unsigned int)total_data));
    4931           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4932           0 :                         goto out;
    4933             :                 }
    4934             : 
    4935           5 :                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
    4936           5 :                                        total_data - 4);
    4937           5 :                 if (!ea_list) {
    4938           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4939           0 :                         goto out;
    4940             :                 }
    4941             : 
    4942           5 :                 if (!lp_ea_support(SNUM(conn))) {
    4943           0 :                         reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
    4944           0 :                         goto out;
    4945             :                 }
    4946             :         }
    4947             :         /* If total_data == 4 Windows doesn't care what values
    4948             :          * are placed in that field, it just ignores them.
    4949             :          * The System i QNTC IBM SMB client puts bad values here,
    4950             :          * so ignore them. */
    4951             : 
    4952          18 :         status = SMB_VFS_CREATE_FILE(
    4953             :                 conn,                                   /* conn */
    4954             :                 req,                                    /* req */
    4955             :                 dirfsp,                                 /* dirfsp */
    4956             :                 smb_dname,                              /* fname */
    4957             :                 MAXIMUM_ALLOWED_ACCESS,                 /* access_mask */
    4958             :                 FILE_SHARE_NONE,                        /* share_access */
    4959             :                 FILE_CREATE,                            /* create_disposition*/
    4960             :                 FILE_DIRECTORY_FILE,                    /* create_options */
    4961             :                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
    4962             :                 0,                                      /* oplock_request */
    4963             :                 NULL,                                   /* lease */
    4964             :                 0,                                      /* allocation_size */
    4965             :                 0,                                      /* private_flags */
    4966             :                 NULL,                                   /* sd */
    4967             :                 NULL,                                   /* ea_list */
    4968             :                 &fsp,                                       /* result */
    4969             :                 NULL,                                   /* pinfo */
    4970             :                 NULL, NULL);                            /* create context */
    4971          18 :         if (!NT_STATUS_IS_OK(status)) {
    4972           8 :                 reply_nterror(req, status);
    4973           8 :                 goto out;
    4974             :         }
    4975             : 
    4976             :         /* Try and set any given EA. */
    4977          10 :         if (ea_list) {
    4978           5 :                 status = set_ea(conn, fsp, ea_list);
    4979           5 :                 if (!NT_STATUS_IS_OK(status)) {
    4980           0 :                         reply_nterror(req, status);
    4981           0 :                         goto out;
    4982             :                 }
    4983             :         }
    4984             : 
    4985             :         /* Realloc the parameter and data sizes */
    4986          10 :         *pparams = (char *)SMB_REALLOC(*pparams,2);
    4987          10 :         if(*pparams == NULL) {
    4988           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    4989           0 :                 goto out;
    4990             :         }
    4991          10 :         params = *pparams;
    4992             : 
    4993          10 :         SSVAL(params,0,0);
    4994             : 
    4995          10 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
    4996             : 
    4997          18 :  out:
    4998          18 :         if (fsp != NULL) {
    4999          10 :                 close_file_free(NULL, &fsp, NORMAL_CLOSE);
    5000             :         }
    5001          18 :         TALLOC_FREE(smb_dname);
    5002             : }
    5003             : 
    5004             : /****************************************************************************
    5005             :  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
    5006             :  We don't actually do this - we just send a null response.
    5007             : ****************************************************************************/
    5008             : 
    5009           0 : static void call_trans2findnotifyfirst(connection_struct *conn,
    5010             :                                        struct smb_request *req,
    5011             :                                        char **pparams, int total_params,
    5012             :                                        char **ppdata, int total_data,
    5013             :                                        unsigned int max_data_bytes)
    5014             : {
    5015           0 :         char *params = *pparams;
    5016           0 :         uint16_t info_level;
    5017             : 
    5018           0 :         if (total_params < 6) {
    5019           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5020           0 :                 return;
    5021             :         }
    5022             : 
    5023           0 :         info_level = SVAL(params,4);
    5024           0 :         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
    5025             : 
    5026           0 :         switch (info_level) {
    5027           0 :                 case 1:
    5028             :                 case 2:
    5029           0 :                         break;
    5030           0 :                 default:
    5031           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    5032           0 :                         return;
    5033             :         }
    5034             : 
    5035             :         /* Realloc the parameter and data sizes */
    5036           0 :         *pparams = (char *)SMB_REALLOC(*pparams,6);
    5037           0 :         if (*pparams == NULL) {
    5038           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    5039           0 :                 return;
    5040             :         }
    5041           0 :         params = *pparams;
    5042             : 
    5043           0 :         SSVAL(params,0,fnf_handle);
    5044           0 :         SSVAL(params,2,0); /* No changes */
    5045           0 :         SSVAL(params,4,0); /* No EA errors */
    5046             : 
    5047           0 :         fnf_handle++;
    5048             : 
    5049           0 :         if(fnf_handle == 0)
    5050           0 :                 fnf_handle = 257;
    5051             : 
    5052           0 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
    5053             : }
    5054             : 
    5055             : /****************************************************************************
    5056             :  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
    5057             :  changes). Currently this does nothing.
    5058             : ****************************************************************************/
    5059             : 
    5060           0 : static void call_trans2findnotifynext(connection_struct *conn,
    5061             :                                       struct smb_request *req,
    5062             :                                       char **pparams, int total_params,
    5063             :                                       char **ppdata, int total_data,
    5064             :                                       unsigned int max_data_bytes)
    5065             : {
    5066           0 :         char *params = *pparams;
    5067             : 
    5068           0 :         DEBUG(3,("call_trans2findnotifynext\n"));
    5069             : 
    5070             :         /* Realloc the parameter and data sizes */
    5071           0 :         *pparams = (char *)SMB_REALLOC(*pparams,4);
    5072           0 :         if (*pparams == NULL) {
    5073           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    5074           0 :                 return;
    5075             :         }
    5076           0 :         params = *pparams;
    5077             : 
    5078           0 :         SSVAL(params,0,0); /* No changes */
    5079           0 :         SSVAL(params,2,0); /* No EA errors */
    5080             : 
    5081           0 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
    5082             : }
    5083             : 
    5084             : /****************************************************************************
    5085             :  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
    5086             : ****************************************************************************/
    5087             : 
    5088        4177 : static void call_trans2getdfsreferral(connection_struct *conn,
    5089             :                                       struct smb_request *req,
    5090             :                                       char **pparams, int total_params,
    5091             :                                       char **ppdata, int total_data,
    5092             :                                       unsigned int max_data_bytes)
    5093             : {
    5094        4177 :         char *params = *pparams;
    5095        4177 :         char *pathname = NULL;
    5096        4177 :         int reply_size = 0;
    5097           0 :         int max_referral_level;
    5098        4177 :         NTSTATUS status = NT_STATUS_OK;
    5099        4177 :         TALLOC_CTX *ctx = talloc_tos();
    5100             : 
    5101        4177 :         DEBUG(10,("call_trans2getdfsreferral\n"));
    5102             : 
    5103        4177 :         if (!IS_IPC(conn)) {
    5104           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    5105           0 :                 return;
    5106             :         }
    5107             : 
    5108        4177 :         if (total_params < 3) {
    5109           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5110           0 :                 return;
    5111             :         }
    5112             : 
    5113        4177 :         max_referral_level = SVAL(params,0);
    5114             : 
    5115        4177 :         if(!lp_host_msdfs()) {
    5116           0 :                 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
    5117           0 :                 return;
    5118             :         }
    5119             : 
    5120        4177 :         srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
    5121             :                     total_params - 2, STR_TERMINATE);
    5122        4177 :         if (!pathname) {
    5123           0 :                 reply_nterror(req, NT_STATUS_NOT_FOUND);
    5124           0 :                 return;
    5125             :         }
    5126        4177 :         reply_size = setup_dfs_referral(
    5127             :                 conn, pathname, max_referral_level, ppdata, &status);
    5128        4177 :         if (reply_size < 0) {
    5129        2911 :                 reply_nterror(req, status);
    5130        2911 :                 return;
    5131             :         }
    5132             : 
    5133        1266 :         SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
    5134             :               SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
    5135        1266 :         send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
    5136             : }
    5137             : 
    5138             : #define LMCAT_SPL       0x53
    5139             : #define LMFUNC_GETJOBID 0x60
    5140             : 
    5141             : /****************************************************************************
    5142             :  Reply to a TRANS2_IOCTL - used for OS/2 printing.
    5143             : ****************************************************************************/
    5144             : 
    5145           0 : static void call_trans2ioctl(connection_struct *conn,
    5146             :                              struct smb_request *req,
    5147             :                              char **pparams, int total_params,
    5148             :                              char **ppdata, int total_data,
    5149             :                              unsigned int max_data_bytes)
    5150             : {
    5151           0 :         const struct loadparm_substitution *lp_sub =
    5152           0 :                 loadparm_s3_global_substitution();
    5153           0 :         char *pdata = *ppdata;
    5154           0 :         files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
    5155           0 :         NTSTATUS status;
    5156           0 :         size_t len = 0;
    5157             : 
    5158             :         /* check for an invalid fid before proceeding */
    5159             : 
    5160           0 :         if (!fsp) {
    5161           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
    5162           0 :                 return;
    5163             :         }
    5164             : 
    5165           0 :         if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
    5166           0 :             && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
    5167           0 :                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
    5168           0 :                 if (*ppdata == NULL) {
    5169           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    5170           0 :                         return;
    5171             :                 }
    5172           0 :                 pdata = *ppdata;
    5173             : 
    5174             :                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
    5175             :                         CAN ACCEPT THIS IN UNICODE. JRA. */
    5176             : 
    5177             :                 /* Job number */
    5178           0 :                 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
    5179             : 
    5180           0 :                 status = srvstr_push(pdata, req->flags2, pdata + 2,
    5181             :                             lp_netbios_name(), 15,
    5182             :                             STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
    5183           0 :                 if (!NT_STATUS_IS_OK(status)) {
    5184           0 :                         reply_nterror(req, status);
    5185           0 :                         return;
    5186             :                 }
    5187           0 :                 status = srvstr_push(pdata, req->flags2, pdata+18,
    5188             :                             lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
    5189             :                             STR_ASCII|STR_TERMINATE, &len); /* Service name */
    5190           0 :                 if (!NT_STATUS_IS_OK(status)) {
    5191           0 :                         reply_nterror(req, status);
    5192           0 :                         return;
    5193             :                 }
    5194           0 :                 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
    5195             :                                     max_data_bytes);
    5196           0 :                 return;
    5197             :         }
    5198             : 
    5199           0 :         DEBUG(2,("Unknown TRANS2_IOCTL\n"));
    5200           0 :         reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
    5201             : }
    5202             : 
    5203       36594 : static void handle_trans2(connection_struct *conn, struct smb_request *req,
    5204             :                           struct trans_state *state)
    5205             : {
    5206       36594 :         struct smbXsrv_connection *xconn = req->xconn;
    5207             : 
    5208       36594 :         if (xconn->protocol >= PROTOCOL_NT1) {
    5209       36592 :                 req->flags2 |= 0x40; /* IS_LONG_NAME */
    5210       36592 :                 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
    5211             :         }
    5212             : 
    5213       36594 :         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
    5214           0 :                 if (state->call != TRANSACT2_QFSINFO &&
    5215           0 :                     state->call != TRANSACT2_SETFSINFO) {
    5216           0 :                         DEBUG(0,("handle_trans2: encryption required "
    5217             :                                 "with call 0x%x\n",
    5218             :                                 (unsigned int)state->call));
    5219           0 :                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    5220           0 :                         return;
    5221             :                 }
    5222             :         }
    5223             : 
    5224             :         /* Now we must call the relevant TRANS2 function */
    5225       36594 :         switch(state->call)  {
    5226          98 :         case TRANSACT2_OPEN:
    5227             :         {
    5228          98 :                 START_PROFILE(Trans2_open);
    5229          98 :                 call_trans2open(conn, req,
    5230          98 :                                 &state->param, state->total_param,
    5231          98 :                                 &state->data, state->total_data,
    5232             :                                 state->max_data_return);
    5233          98 :                 END_PROFILE(Trans2_open);
    5234          80 :                 break;
    5235             :         }
    5236             : 
    5237        8712 :         case TRANSACT2_FINDFIRST:
    5238             :         {
    5239        8712 :                 START_PROFILE(Trans2_findfirst);
    5240        8712 :                 call_trans2findfirst(conn, req,
    5241        8712 :                                      &state->param, state->total_param,
    5242        8712 :                                      &state->data, state->total_data,
    5243             :                                      state->max_data_return);
    5244        8712 :                 END_PROFILE(Trans2_findfirst);
    5245        8537 :                 break;
    5246             :         }
    5247             : 
    5248        1724 :         case TRANSACT2_FINDNEXT:
    5249             :         {
    5250        1724 :                 START_PROFILE(Trans2_findnext);
    5251        1724 :                 call_trans2findnext(conn, req,
    5252        1724 :                                     &state->param, state->total_param,
    5253        1724 :                                     &state->data, state->total_data,
    5254             :                                     state->max_data_return);
    5255        1724 :                 END_PROFILE(Trans2_findnext);
    5256        1724 :                 break;
    5257             :         }
    5258             : 
    5259        1373 :         case TRANSACT2_QFSINFO:
    5260             :         {
    5261        1373 :                 START_PROFILE(Trans2_qfsinfo);
    5262        1373 :                 call_trans2qfsinfo(conn, req,
    5263        1373 :                                    &state->param, state->total_param,
    5264        1373 :                                    &state->data, state->total_data,
    5265             :                                    state->max_data_return);
    5266        1373 :                 END_PROFILE(Trans2_qfsinfo);
    5267        1373 :             break;
    5268             :         }
    5269             : 
    5270        1364 :         case TRANSACT2_SETFSINFO:
    5271             :         {
    5272        1364 :                 START_PROFILE(Trans2_setfsinfo);
    5273        1364 :                 call_trans2setfsinfo(conn, req,
    5274        1364 :                                      &state->param, state->total_param,
    5275        1364 :                                      &state->data, state->total_data,
    5276             :                                      state->max_data_return);
    5277        1364 :                 END_PROFILE(Trans2_setfsinfo);
    5278        1364 :                 break;
    5279             :         }
    5280             : 
    5281        9901 :         case TRANSACT2_QPATHINFO:
    5282             :         {
    5283        9901 :                 START_PROFILE(Trans2_qpathinfo);
    5284        9901 :                 call_trans2qpathinfo(
    5285             :                         conn,
    5286             :                         req,
    5287             :                         &state->param,
    5288        9901 :                         state->total_param,
    5289             :                         &state->data,
    5290        9901 :                         state->total_data,
    5291             :                         state->max_data_return);
    5292        9901 :                 END_PROFILE(Trans2_qpathinfo);
    5293        9612 :                 break;
    5294             :         }
    5295             : 
    5296        3549 :         case TRANSACT2_QFILEINFO:
    5297             :         {
    5298        3549 :                 START_PROFILE(Trans2_qfileinfo);
    5299        3549 :                 call_trans2qfileinfo(
    5300             :                         conn,
    5301             :                         req,
    5302             :                         &state->param,
    5303        3549 :                         state->total_param,
    5304             :                         &state->data,
    5305        3549 :                         state->total_data,
    5306             :                         state->max_data_return);
    5307        3549 :                 END_PROFILE(Trans2_qfileinfo);
    5308        3364 :                 break;
    5309             :         }
    5310             : 
    5311        1408 :         case TRANSACT2_SETPATHINFO:
    5312             :         {
    5313        1408 :                 START_PROFILE(Trans2_setpathinfo);
    5314        1408 :                 call_trans2setpathinfo(
    5315             :                         conn,
    5316             :                         req,
    5317             :                         &state->param,
    5318        1408 :                         state->total_param,
    5319             :                         &state->data,
    5320        1408 :                         state->total_data,
    5321             :                         state->max_data_return);
    5322        1408 :                 END_PROFILE(Trans2_setpathinfo);
    5323        1396 :                 break;
    5324             :         }
    5325             : 
    5326        4265 :         case TRANSACT2_SETFILEINFO:
    5327             :         {
    5328        4265 :                 START_PROFILE(Trans2_setfileinfo);
    5329        4265 :                 call_trans2setfileinfo(
    5330             :                         conn,
    5331             :                         req,
    5332             :                         &state->param,
    5333        4265 :                         state->total_param,
    5334             :                         &state->data,
    5335        4265 :                         state->total_data,
    5336             :                         state->max_data_return);
    5337        4265 :                 END_PROFILE(Trans2_setfileinfo);
    5338        3728 :                 break;
    5339             :         }
    5340             : 
    5341           0 :         case TRANSACT2_FINDNOTIFYFIRST:
    5342             :         {
    5343           0 :                 START_PROFILE(Trans2_findnotifyfirst);
    5344           0 :                 call_trans2findnotifyfirst(conn, req,
    5345           0 :                                            &state->param, state->total_param,
    5346           0 :                                            &state->data, state->total_data,
    5347             :                                            state->max_data_return);
    5348           0 :                 END_PROFILE(Trans2_findnotifyfirst);
    5349           0 :                 break;
    5350             :         }
    5351             : 
    5352           0 :         case TRANSACT2_FINDNOTIFYNEXT:
    5353             :         {
    5354           0 :                 START_PROFILE(Trans2_findnotifynext);
    5355           0 :                 call_trans2findnotifynext(conn, req,
    5356           0 :                                           &state->param, state->total_param,
    5357           0 :                                           &state->data, state->total_data,
    5358             :                                           state->max_data_return);
    5359           0 :                 END_PROFILE(Trans2_findnotifynext);
    5360           0 :                 break;
    5361             :         }
    5362             : 
    5363          23 :         case TRANSACT2_MKDIR:
    5364             :         {
    5365          23 :                 START_PROFILE(Trans2_mkdir);
    5366          23 :                 call_trans2mkdir(conn, req,
    5367          23 :                                  &state->param, state->total_param,
    5368          23 :                                  &state->data, state->total_data,
    5369             :                                  state->max_data_return);
    5370          23 :                 END_PROFILE(Trans2_mkdir);
    5371          20 :                 break;
    5372             :         }
    5373             : 
    5374        4177 :         case TRANSACT2_GET_DFS_REFERRAL:
    5375             :         {
    5376        4177 :                 START_PROFILE(Trans2_get_dfs_referral);
    5377        4177 :                 call_trans2getdfsreferral(conn, req,
    5378        4177 :                                           &state->param, state->total_param,
    5379        4177 :                                           &state->data, state->total_data,
    5380             :                                           state->max_data_return);
    5381        4177 :                 END_PROFILE(Trans2_get_dfs_referral);
    5382        4177 :                 break;
    5383             :         }
    5384             : 
    5385           0 :         case TRANSACT2_IOCTL:
    5386             :         {
    5387           0 :                 START_PROFILE(Trans2_ioctl);
    5388           0 :                 call_trans2ioctl(conn, req,
    5389           0 :                                  &state->param, state->total_param,
    5390           0 :                                  &state->data, state->total_data,
    5391             :                                  state->max_data_return);
    5392           0 :                 END_PROFILE(Trans2_ioctl);
    5393           0 :                 break;
    5394             :         }
    5395             : 
    5396           0 :         default:
    5397             :                 /* Error in request */
    5398           0 :                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
    5399           0 :                 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
    5400             :         }
    5401             : }
    5402             : 
    5403             : /****************************************************************************
    5404             :  Reply to a SMBtrans2.
    5405             :  ****************************************************************************/
    5406             : 
    5407       36594 : void reply_trans2(struct smb_request *req)
    5408             : {
    5409       36594 :         connection_struct *conn = req->conn;
    5410        1219 :         unsigned int dsoff;
    5411        1219 :         unsigned int dscnt;
    5412        1219 :         unsigned int psoff;
    5413        1219 :         unsigned int pscnt;
    5414        1219 :         unsigned int tran_call;
    5415        1219 :         struct trans_state *state;
    5416        1219 :         NTSTATUS result;
    5417             : 
    5418       36594 :         START_PROFILE(SMBtrans2);
    5419             : 
    5420       36594 :         if (req->wct < 14) {
    5421           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5422           0 :                 END_PROFILE(SMBtrans2);
    5423           0 :                 return;
    5424             :         }
    5425             : 
    5426       36594 :         dsoff = SVAL(req->vwv+12, 0);
    5427       36594 :         dscnt = SVAL(req->vwv+11, 0);
    5428       36594 :         psoff = SVAL(req->vwv+10, 0);
    5429       36594 :         pscnt = SVAL(req->vwv+9, 0);
    5430       36594 :         tran_call = SVAL(req->vwv+14, 0);
    5431             : 
    5432       36594 :         result = allow_new_trans(conn->pending_trans, req->mid);
    5433       36594 :         if (!NT_STATUS_IS_OK(result)) {
    5434           0 :                 DEBUG(2, ("Got invalid trans2 request: %s\n",
    5435             :                           nt_errstr(result)));
    5436           0 :                 reply_nterror(req, result);
    5437           0 :                 END_PROFILE(SMBtrans2);
    5438           0 :                 return;
    5439             :         }
    5440             : 
    5441       36594 :         if (IS_IPC(conn)) {
    5442        4897 :                 switch (tran_call) {
    5443             :                 /* List the allowed trans2 calls on IPC$ */
    5444        4897 :                 case TRANSACT2_OPEN:
    5445             :                 case TRANSACT2_GET_DFS_REFERRAL:
    5446             :                 case TRANSACT2_QFILEINFO:
    5447             :                 case TRANSACT2_QFSINFO:
    5448             :                 case TRANSACT2_SETFSINFO:
    5449        4897 :                         break;
    5450           0 :                 default:
    5451           0 :                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    5452           0 :                         END_PROFILE(SMBtrans2);
    5453           0 :                         return;
    5454             :                 }
    5455             :         }
    5456             : 
    5457       36594 :         if ((state = talloc(conn, struct trans_state)) == NULL) {
    5458           0 :                 DEBUG(0, ("talloc failed\n"));
    5459           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    5460           0 :                 END_PROFILE(SMBtrans2);
    5461           0 :                 return;
    5462             :         }
    5463             : 
    5464       36594 :         state->cmd = SMBtrans2;
    5465             : 
    5466       36594 :         state->mid = req->mid;
    5467       36594 :         state->vuid = req->vuid;
    5468       36594 :         state->setup_count = SVAL(req->vwv+13, 0);
    5469       36594 :         state->setup = NULL;
    5470       36594 :         state->total_param = SVAL(req->vwv+0, 0);
    5471       36594 :         state->param = NULL;
    5472       36594 :         state->total_data =  SVAL(req->vwv+1, 0);
    5473       36594 :         state->data = NULL;
    5474       36594 :         state->max_param_return = SVAL(req->vwv+2, 0);
    5475       36594 :         state->max_data_return  = SVAL(req->vwv+3, 0);
    5476       36594 :         state->max_setup_return = SVAL(req->vwv+4, 0);
    5477       36594 :         state->close_on_completion = BITSETW(req->vwv+5, 0);
    5478       36594 :         state->one_way = BITSETW(req->vwv+5, 1);
    5479             : 
    5480       36594 :         state->call = tran_call;
    5481             : 
    5482             :         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
    5483             :            is so as a sanity check */
    5484       36594 :         if (state->setup_count != 1) {
    5485             :                 /*
    5486             :                  * Need to have rc=0 for ioctl to get job id for OS/2.
    5487             :                  *  Network printing will fail if function is not successful.
    5488             :                  *  Similar function in reply.c will be used if protocol
    5489             :                  *  is LANMAN1.0 instead of LM1.2X002.
    5490             :                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
    5491             :                  *  outbuf doesn't have to be set(only job id is used).
    5492             :                  */
    5493           0 :                 if ( (state->setup_count == 4)
    5494           0 :                      && (tran_call == TRANSACT2_IOCTL)
    5495           0 :                      && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
    5496           0 :                      && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
    5497           0 :                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
    5498             :                 } else {
    5499           0 :                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
    5500           0 :                         DEBUG(2,("Transaction is %d\n",tran_call));
    5501           0 :                         TALLOC_FREE(state);
    5502           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5503           0 :                         END_PROFILE(SMBtrans2);
    5504           0 :                         return;
    5505             :                 }
    5506             :         }
    5507             : 
    5508       36594 :         if ((dscnt > state->total_data) || (pscnt > state->total_param))
    5509           0 :                 goto bad_param;
    5510             : 
    5511       36594 :         if (state->total_data) {
    5512             : 
    5513        7322 :                 if (smb_buffer_oob(state->total_data, 0, dscnt)
    5514        7322 :                     || smb_buffer_oob(smb_len(req->inbuf), dsoff, dscnt)) {
    5515           0 :                         goto bad_param;
    5516             :                 }
    5517             : 
    5518             :                 /* Can't use talloc here, the core routines do realloc on the
    5519             :                  * params and data. */
    5520        7322 :                 state->data = (char *)SMB_MALLOC(state->total_data);
    5521        7322 :                 if (state->data == NULL) {
    5522           0 :                         DEBUG(0,("reply_trans2: data malloc fail for %u "
    5523             :                                  "bytes !\n", (unsigned int)state->total_data));
    5524           0 :                         TALLOC_FREE(state);
    5525           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    5526           0 :                         END_PROFILE(SMBtrans2);
    5527           0 :                         return;
    5528             :                 }
    5529             : 
    5530        7322 :                 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
    5531             :         }
    5532             : 
    5533       36594 :         if (state->total_param) {
    5534             : 
    5535       36594 :                 if (smb_buffer_oob(state->total_param, 0, pscnt)
    5536       36594 :                     || smb_buffer_oob(smb_len(req->inbuf), psoff, pscnt)) {
    5537           0 :                         goto bad_param;
    5538             :                 }
    5539             : 
    5540             :                 /* Can't use talloc here, the core routines do realloc on the
    5541             :                  * params and data. */
    5542       36594 :                 state->param = (char *)SMB_MALLOC(state->total_param);
    5543       36594 :                 if (state->param == NULL) {
    5544           0 :                         DEBUG(0,("reply_trans: param malloc fail for %u "
    5545             :                                  "bytes !\n", (unsigned int)state->total_param));
    5546           0 :                         SAFE_FREE(state->data);
    5547           0 :                         TALLOC_FREE(state);
    5548           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    5549           0 :                         END_PROFILE(SMBtrans2);
    5550           0 :                         return;
    5551             :                 }
    5552             : 
    5553       36594 :                 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
    5554             :         }
    5555             : 
    5556       36594 :         state->received_data  = dscnt;
    5557       36594 :         state->received_param = pscnt;
    5558             : 
    5559       36594 :         if ((state->received_param == state->total_param) &&
    5560       36594 :             (state->received_data == state->total_data)) {
    5561             : 
    5562       36594 :                 handle_trans2(conn, req, state);
    5563             : 
    5564       36594 :                 SAFE_FREE(state->data);
    5565       36594 :                 SAFE_FREE(state->param);
    5566       36594 :                 TALLOC_FREE(state);
    5567       36594 :                 END_PROFILE(SMBtrans2);
    5568       36594 :                 return;
    5569             :         }
    5570             : 
    5571           0 :         DLIST_ADD(conn->pending_trans, state);
    5572             : 
    5573             :         /* We need to send an interim response then receive the rest
    5574             :            of the parameter/data bytes */
    5575           0 :         reply_smb1_outbuf(req, 0, 0);
    5576           0 :         show_msg((char *)req->outbuf);
    5577           0 :         END_PROFILE(SMBtrans2);
    5578           0 :         return;
    5579             : 
    5580           0 :   bad_param:
    5581             : 
    5582           0 :         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
    5583           0 :         SAFE_FREE(state->data);
    5584           0 :         SAFE_FREE(state->param);
    5585           0 :         TALLOC_FREE(state);
    5586           0 :         END_PROFILE(SMBtrans2);
    5587           0 :         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5588             : }
    5589             : 
    5590             : /****************************************************************************
    5591             :  Reply to a SMBtranss2
    5592             :  ****************************************************************************/
    5593             : 
    5594           0 : void reply_transs2(struct smb_request *req)
    5595             : {
    5596           0 :         connection_struct *conn = req->conn;
    5597           0 :         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
    5598           0 :         struct trans_state *state;
    5599             : 
    5600           0 :         START_PROFILE(SMBtranss2);
    5601             : 
    5602           0 :         show_msg((const char *)req->inbuf);
    5603             : 
    5604             :         /* Windows clients expect all replies to
    5605             :            a transact secondary (SMBtranss2 0x33)
    5606             :            to have a command code of transact
    5607             :            (SMBtrans2 0x32). See bug #8989
    5608             :            and also [MS-CIFS] section 2.2.4.47.2
    5609             :            for details.
    5610             :         */
    5611           0 :         req->cmd = SMBtrans2;
    5612             : 
    5613           0 :         if (req->wct < 8) {
    5614           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5615           0 :                 END_PROFILE(SMBtranss2);
    5616           0 :                 return;
    5617             :         }
    5618             : 
    5619           0 :         for (state = conn->pending_trans; state != NULL;
    5620           0 :              state = state->next) {
    5621           0 :                 if (state->mid == req->mid) {
    5622           0 :                         break;
    5623             :                 }
    5624             :         }
    5625             : 
    5626           0 :         if ((state == NULL) || (state->cmd != SMBtrans2)) {
    5627           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5628           0 :                 END_PROFILE(SMBtranss2);
    5629           0 :                 return;
    5630             :         }
    5631             : 
    5632             :         /* Revise state->total_param and state->total_data in case they have
    5633             :            changed downwards */
    5634             : 
    5635           0 :         if (SVAL(req->vwv+0, 0) < state->total_param)
    5636           0 :                 state->total_param = SVAL(req->vwv+0, 0);
    5637           0 :         if (SVAL(req->vwv+1, 0) < state->total_data)
    5638           0 :                 state->total_data = SVAL(req->vwv+1, 0);
    5639             : 
    5640           0 :         pcnt = SVAL(req->vwv+2, 0);
    5641           0 :         poff = SVAL(req->vwv+3, 0);
    5642           0 :         pdisp = SVAL(req->vwv+4, 0);
    5643             : 
    5644           0 :         dcnt = SVAL(req->vwv+5, 0);
    5645           0 :         doff = SVAL(req->vwv+6, 0);
    5646           0 :         ddisp = SVAL(req->vwv+7, 0);
    5647             : 
    5648           0 :         state->received_param += pcnt;
    5649           0 :         state->received_data += dcnt;
    5650             : 
    5651           0 :         if ((state->received_data > state->total_data) ||
    5652           0 :             (state->received_param > state->total_param))
    5653           0 :                 goto bad_param;
    5654             : 
    5655           0 :         if (pcnt) {
    5656           0 :                 if (smb_buffer_oob(state->total_param, pdisp, pcnt)
    5657           0 :                     || smb_buffer_oob(smb_len(req->inbuf), poff, pcnt)) {
    5658           0 :                         goto bad_param;
    5659             :                 }
    5660           0 :                 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
    5661             :         }
    5662             : 
    5663           0 :         if (dcnt) {
    5664           0 :                 if (smb_buffer_oob(state->total_data, ddisp, dcnt)
    5665           0 :                     || smb_buffer_oob(smb_len(req->inbuf), doff, dcnt)) {
    5666           0 :                         goto bad_param;
    5667             :                 }
    5668           0 :                 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
    5669             :         }
    5670             : 
    5671           0 :         if ((state->received_param < state->total_param) ||
    5672           0 :             (state->received_data < state->total_data)) {
    5673           0 :                 END_PROFILE(SMBtranss2);
    5674           0 :                 return;
    5675             :         }
    5676             : 
    5677           0 :         handle_trans2(conn, req, state);
    5678             : 
    5679           0 :         DLIST_REMOVE(conn->pending_trans, state);
    5680           0 :         SAFE_FREE(state->data);
    5681           0 :         SAFE_FREE(state->param);
    5682           0 :         TALLOC_FREE(state);
    5683             : 
    5684           0 :         END_PROFILE(SMBtranss2);
    5685           0 :         return;
    5686             : 
    5687           0 :   bad_param:
    5688             : 
    5689           0 :         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
    5690           0 :         DLIST_REMOVE(conn->pending_trans, state);
    5691           0 :         SAFE_FREE(state->data);
    5692           0 :         SAFE_FREE(state->param);
    5693           0 :         TALLOC_FREE(state);
    5694           0 :         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5695           0 :         END_PROFILE(SMBtranss2);
    5696             : }

Generated by: LCOV version 1.14