LCOV - code coverage report
Current view: top level - source3/smbd - smb1_trans2.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 132 2425 5.4 %
Date: 2024-02-14 10:14:15 Functions: 4 44 9.1 %

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

Generated by: LCOV version 1.14