LCOV - code coverage report
Current view: top level - source3/smbd - smb1_trans2.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 1618 2554 63.4 %
Date: 2024-05-31 13:13:24 Functions: 39 45 86.7 %

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

Generated by: LCOV version 1.14