LCOV - code coverage report
Current view: top level - source3/smbd - smb1_trans2.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 1635 2588 63.2 %
Date: 2024-02-28 12:06:22 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       30496 : 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       30496 :         int data_to_send = datasize;
      76       30496 :         int params_to_send = paramsize;
      77        1172 :         int useable_space;
      78       30496 :         const char *pp = params;
      79       30496 :         const char *pd = pdata;
      80        1172 :         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
      81       30496 :         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
      82       30496 :         int data_alignment_offset = 0;
      83       30496 :         bool overflow = False;
      84       30496 :         struct smbXsrv_connection *xconn = req->xconn;
      85       30496 :         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       30496 :         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       30496 :         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       30496 :         if (((params_to_send % 4) != 0) && (data_to_send != 0))
     128       20697 :                 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       30496 :         useable_space = max_send - (smb_size
     135             :                                     + 2 * 10 /* wct */
     136       29324 :                                     + alignment_offset
     137       30496 :                                     + data_alignment_offset);
     138             : 
     139       30496 :         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       61020 :         while (params_to_send || data_to_send) {
     146             :                 /* Calculate whether we will totally or partially fill this packet */
     147             : 
     148       30524 :                 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       30524 :                 total_sent_thistime = MIN(total_sent_thistime, useable_space);
     159             : 
     160       30524 :                 reply_smb1_outbuf(req, 10, total_sent_thistime + alignment_offset
     161       30524 :                              + data_alignment_offset);
     162             : 
     163             :                 /* Set total params and data to be sent */
     164       30524 :                 SSVAL(req->outbuf,smb_tprcnt,paramsize);
     165       30524 :                 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       30524 :                 params_sent_thistime = MIN(params_to_send,useable_space);
     172       30524 :                 data_sent_thistime = useable_space - params_sent_thistime;
     173       30524 :                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
     174             : 
     175       30524 :                 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       30524 :                 SSVAL(req->outbuf,smb_proff,
     183             :                       ((smb_buf(req->outbuf)+alignment_offset)
     184             :                        - smb_base(req->outbuf)));
     185             : 
     186       30524 :                 if(params_sent_thistime == 0)
     187        3149 :                         SSVAL(req->outbuf,smb_prdisp,0);
     188             :                 else
     189             :                         /* Absolute displacement of param bytes sent in this packet */
     190       27375 :                         SSVAL(req->outbuf,smb_prdisp,pp - params);
     191             : 
     192       30524 :                 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
     193       30524 :                 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       25474 :                         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       25474 :                         SSVAL(req->outbuf,smb_drdisp, pd - pdata);
     204             :                 }
     205             : 
     206             :                 /* Initialize the padding for alignment */
     207             : 
     208       30524 :                 if (alignment_offset != 0) {
     209       30524 :                         memset(smb_buf(req->outbuf), 0, alignment_offset);
     210             :                 }
     211             : 
     212             :                 /* Copy the param bytes into the packet */
     213             : 
     214       30524 :                 if(params_sent_thistime) {
     215       27375 :                         memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
     216             :                                params_sent_thistime);
     217             :                 }
     218             : 
     219             :                 /* Copy in the data bytes */
     220       30524 :                 if(data_sent_thistime) {
     221       25474 :                         if (data_alignment_offset != 0) {
     222       20717 :                                 memset((smb_buf(req->outbuf)+alignment_offset+
     223             :                                         params_sent_thistime), 0,
     224             :                                        data_alignment_offset);
     225             :                         }
     226       26646 :                         memcpy(smb_buf(req->outbuf)+alignment_offset
     227       25474 :                                +params_sent_thistime+data_alignment_offset,
     228             :                                pd,data_sent_thistime);
     229             :                 }
     230             : 
     231       30524 :                 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       30524 :                 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       30524 :                 if (overflow) {
     237           0 :                         error_packet_set((char *)req->outbuf,
     238             :                                          ERRDOS,ERRbufferoverflow,
     239           0 :                                          STATUS_BUFFER_OVERFLOW,
     240             :                                          __LINE__,__FILE__);
     241       30524 :                 } 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       30524 :                 show_msg((char *)req->outbuf);
     252       30524 :                 if (!smb1_srv_send(xconn,
     253       30524 :                                    (char *)req->outbuf,
     254             :                                    true,
     255       30524 :                                    req->seqnum + 1,
     256       30524 :                                    IS_CONN_ENCRYPTED(conn))) {
     257           0 :                         exit_server_cleanly("send_trans2_replies: smb1_srv_send failed.");
     258             :                 }
     259             : 
     260       30524 :                 TALLOC_FREE(req->outbuf);
     261             : 
     262       30524 :                 pp += params_sent_thistime;
     263       30524 :                 pd += data_sent_thistime;
     264             : 
     265       30524 :                 params_to_send -= params_sent_thistime;
     266       30524 :                 data_to_send -= data_sent_thistime;
     267             : 
     268             :                 /* Sanity check */
     269       30524 :                 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       29324 :         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      207176 : 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      207176 :         uint8_t align = 4;
     791      207176 :         const bool do_pad = true;
     792             : 
     793      207176 :         if (info_level >= 1 && info_level <= 3) {
     794             :                 /* No alignment on earlier info levels. */
     795      114822 :                 align = 1;
     796             :         }
     797             : 
     798      207176 :         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        8736 : 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        8736 :         struct smb_filename *smb_dname = NULL;
     824        8736 :         char *params = *pparams;
     825        8736 :         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        8736 :         char *directory = NULL;
     835        8736 :         char *mask = NULL;
     836         175 :         char *p;
     837        8736 :         int last_entry_off=0;
     838        8736 :         int dptr_num = -1;
     839        8736 :         int numentries = 0;
     840         175 :         int i;
     841        8736 :         bool finished = False;
     842        8736 :         bool dont_descend = False;
     843        8736 :         bool out_of_space = False;
     844         175 :         int space_remaining;
     845        8736 :         struct ea_list *ea_list = NULL;
     846        8736 :         NTSTATUS ntstatus = NT_STATUS_OK;
     847         175 :         bool ask_sharemode;
     848        8736 :         struct smbXsrv_connection *xconn = req->xconn;
     849        8736 :         struct smbd_server_connection *sconn = req->sconn;
     850        8736 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
     851        8736 :         bool backup_priv = false;
     852        8736 :         bool as_root = false;
     853        8736 :         files_struct *fsp = NULL;
     854        8736 :         struct files_struct *dirfsp = NULL;
     855         175 :         const struct loadparm_substitution *lp_sub =
     856        8736 :                 loadparm_s3_global_substitution();
     857             : 
     858        8736 :         if (total_params < 13) {
     859           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     860           0 :                 goto out;
     861             :         }
     862             : 
     863        8736 :         dirtype = SVAL(params,0);
     864        8736 :         maxentries = SVAL(params,2);
     865        8736 :         findfirst_flags = SVAL(params,4);
     866        8736 :         close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
     867        8736 :         close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
     868        8736 :         requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
     869        8742 :         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        8736 :         info_level = SVAL(params,6);
     874             : 
     875        8736 :         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        8736 :         if (!maxentries) {
     889             :                 /* W2K3 seems to treat zero as 1. */
     890          12 :                 maxentries = 1;
     891             :         }
     892             : 
     893        8736 :         switch (info_level) {
     894        8545 :                 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        8720 :                         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        8736 :         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        8546 :                 srvstr_get_path(talloc_tos(),
     931             :                                 params,
     932        8546 :                                 req->flags2,
     933             :                                 &directory,
     934        8546 :                                 params+12,
     935        8546 :                                 total_params - 12,
     936             :                                 STR_TERMINATE,
     937             :                                 &ntstatus);
     938             :         }
     939        8736 :         if (!NT_STATUS_IS_OK(ntstatus)) {
     940           0 :                 reply_nterror(req, ntstatus);
     941           0 :                 goto out;
     942             :         }
     943             : 
     944        8736 :         if (backup_priv) {
     945           0 :                 become_root();
     946           0 :                 as_root = true;
     947             :         }
     948        8736 :         ntstatus = smb1_strip_dfs_path(talloc_tos(), &ucf_flags, &directory);
     949        8736 :         if (!NT_STATUS_IS_OK(ntstatus)) {
     950           0 :                 reply_nterror(req, ntstatus);
     951           0 :                 goto out;
     952             :         }
     953             : 
     954        8736 :         ntstatus = filename_convert_smb1_search_path(talloc_tos(),
     955             :                                                      conn,
     956             :                                                      directory,
     957             :                                                      ucf_flags,
     958             :                                                      &dirfsp,
     959             :                                                      &smb_dname,
     960             :                                                      &mask);
     961             : 
     962        8736 :         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        8622 :         TALLOC_FREE(directory);
     973        8622 :         directory = smb_dname->base_name;
     974             : 
     975        8622 :         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
     976             : 
     977        8622 :         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        8622 :         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        8622 :         *ppdata = (char *)SMB_REALLOC(
    1014             :                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
    1015        8622 :         if(*ppdata == NULL ) {
    1016           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    1017           0 :                 goto out;
    1018             :         }
    1019        8622 :         pdata = *ppdata;
    1020        8622 :         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        8622 :         memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
    1026             :         /* Realloc the params space */
    1027        8622 :         *pparams = (char *)SMB_REALLOC(*pparams, 10);
    1028        8622 :         if (*pparams == NULL) {
    1029           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    1030           0 :                 goto out;
    1031             :         }
    1032        8622 :         params = *pparams;
    1033             : 
    1034             :         /*
    1035             :          * Open an fsp on this directory for the dptr.
    1036             :          */
    1037        8622 :         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        8622 :         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        8503 :         ntstatus = dptr_create(conn,
    1070             :                                 req,
    1071             :                                 fsp, /* fsp */
    1072             :                                 False,
    1073             :                                 mask,
    1074             :                                 dirtype,
    1075        8503 :                                 &fsp->dptr);
    1076             : 
    1077        8503 :         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        8503 :         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        8503 :         dptr_num = dptr_dnum(fsp->dptr);
    1095        8503 :         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        8503 :         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
    1101             :                  directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
    1102        8503 :         if (in_list(directory,
    1103        8503 :                     lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
    1104        8503 :                         dptr_case_sensitive(fsp->dptr))) {
    1105           0 :                 dont_descend = True;
    1106             :         }
    1107             : 
    1108        8503 :         p = pdata;
    1109        8503 :         space_remaining = max_data_bytes;
    1110        8503 :         out_of_space = False;
    1111             : 
    1112        8503 :         ask_sharemode = fsp_search_ask_sharemode(fsp);
    1113             : 
    1114       58075 :         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
    1115             : 
    1116       49398 :                 ntstatus = get_lanman2_dir_entry(talloc_tos(),
    1117             :                                                  conn,
    1118       49398 :                                                  fsp->dptr,
    1119       49398 :                                                  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       49398 :                 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       49386 :                 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
    1140           0 :                         out_of_space = true;
    1141             :                 } else {
    1142       49386 :                         finished = !NT_STATUS_IS_OK(ntstatus);
    1143             :                 }
    1144             : 
    1145       49386 :                 if (!finished && !out_of_space) {
    1146       41510 :                         numentries++;
    1147             :                 }
    1148             : 
    1149             :                 /* Ensure space_remaining never goes -ve. */
    1150       49386 :                 if (PTR_DIFF(p,pdata) > max_data_bytes) {
    1151           0 :                         space_remaining = 0;
    1152           0 :                         out_of_space = true;
    1153             :                 } else {
    1154       49386 :                         space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
    1155             :                 }
    1156             :         }
    1157             : 
    1158             :         /* Check if we can close the dirptr */
    1159        8503 :         if(close_after_first || (finished && close_if_end)) {
    1160        8369 :                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
    1161        8369 :                 dptr_num = -1;
    1162        8369 :                 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        8503 :         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        7962 :         SSVAL(params,0,dptr_num);
    1195        7962 :         SSVAL(params,2,numentries);
    1196        7962 :         SSVAL(params,4,finished);
    1197        7962 :         SSVAL(params,6,0); /* Never an EA error */
    1198        7962 :         SSVAL(params,8,last_entry_off);
    1199             : 
    1200        7962 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
    1201             :                             max_data_bytes);
    1202             : 
    1203        7962 :         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        7962 :         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        7962 :         if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
    1223         153 :                 char mangled_name[13];
    1224        7824 :                 name_to_8_3(mask, mangled_name, True, conn->params);
    1225             :         }
    1226         138 :  out:
    1227             : 
    1228        8736 :         if (as_root) {
    1229           0 :                 unbecome_root();
    1230             :         }
    1231             : 
    1232        8736 :         TALLOC_FREE(smb_dname);
    1233        8736 :         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        1375 : 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        1375 :         char *params = *pparams;
    1654           0 :         uint16_t info_level;
    1655        1375 :         int data_len = 0;
    1656           0 :         size_t fixed_portion;
    1657           0 :         NTSTATUS status;
    1658             : 
    1659        1375 :         if (total_params < 2) {
    1660           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1661           0 :                 return;
    1662             :         }
    1663             : 
    1664        1375 :         info_level = SVAL(params,0);
    1665             : 
    1666        1375 :         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        1375 :         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
    1677             : 
    1678        1375 :         status = smbd_do_qfsinfo(req->xconn, conn, req,
    1679             :                                  info_level,
    1680        1375 :                                  req->flags2,
    1681             :                                  max_data_bytes,
    1682             :                                  &fixed_portion,
    1683             :                                  NULL,
    1684             :                                  NULL,
    1685             :                                  ppdata, &data_len);
    1686        1375 :         if (!NT_STATUS_IS_OK(status)) {
    1687           0 :                 reply_nterror(req, status);
    1688           0 :                 return;
    1689             :         }
    1690             : 
    1691        1375 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
    1692             :                             max_data_bytes);
    1693             : 
    1694        1375 :         DEBUG( 4, ( "%s info_level = %d\n",
    1695             :                     smb_fn_name(req->cmd), info_level) );
    1696             : 
    1697        1375 :         return;
    1698             : }
    1699             : 
    1700             : /****************************************************************************
    1701             :  Reply to a TRANS2_SETFSINFO (set filesystem info).
    1702             : ****************************************************************************/
    1703             : 
    1704        1366 : 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        1366 :                 loadparm_s3_global_substitution();
    1712        1366 :         struct smbXsrv_connection *xconn = req->xconn;
    1713        1366 :         char *pdata = *ppdata;
    1714        1366 :         char *params = *pparams;
    1715           0 :         uint16_t info_level;
    1716             : 
    1717        1366 :         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
    1718             :                   lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    1719             : 
    1720             :         /*  */
    1721        1366 :         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        1366 :         info_level = SVAL(params,2);
    1729             : 
    1730        1366 :         if (IS_IPC(conn)) {
    1731         480 :                 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        1366 :         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        1366 :         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         888 :                 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
    1811             :                         {
    1812           0 :                                 NTSTATUS status;
    1813         888 :                                 size_t param_len = 0;
    1814         888 :                                 size_t data_len = total_data;
    1815             : 
    1816         888 :                                 if (!lp_smb1_unix_extensions()) {
    1817           0 :                                         reply_nterror(
    1818             :                                                 req,
    1819             :                                                 NT_STATUS_INVALID_LEVEL);
    1820           0 :                                         return;
    1821             :                                 }
    1822             : 
    1823         888 :                                 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         888 :                                 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         888 :                                 DEBUG( 4,("call_trans2setfsinfo: "
    1842             :                                         "request transport encryption.\n"));
    1843             : 
    1844         888 :                                 status = srv_request_encryption_setup(conn,
    1845             :                                                                 (unsigned char **)ppdata,
    1846             :                                                                 &data_len,
    1847             :                                                                 (unsigned char **)pparams,
    1848             :                                                                 &param_len);
    1849             : 
    1850         888 :                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
    1851         444 :                                                 !NT_STATUS_IS_OK(status)) {
    1852           0 :                                         reply_nterror(req, status);
    1853           0 :                                         return;
    1854             :                                 }
    1855             : 
    1856         888 :                                 send_trans2_replies(conn, req,
    1857         888 :                                                 NT_STATUS_OK,
    1858             :                                                 *pparams,
    1859             :                                                 param_len,
    1860             :                                                 *ppdata,
    1861             :                                                 data_len,
    1862             :                                                 max_data_bytes);
    1863             : 
    1864         888 :                                 if (NT_STATUS_IS_OK(status)) {
    1865             :                                         /* Server-side transport
    1866             :                                          * encryption is now *on*. */
    1867         444 :                                         status = srv_encryption_start(conn);
    1868         444 :                                         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         888 :                                 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 smb_filename *smb_fname,
    2533             :         char **ppdata,
    2534             :         int *ptotal_data)
    2535             : {
    2536           0 :         char buffer[PATH_MAX+1];
    2537           0 :         size_t needed, len;
    2538           0 :         int link_len;
    2539          24 :         char *pdata = NULL;
    2540          24 :         struct smb_filename *parent_fname = NULL;
    2541          24 :         struct smb_filename *base_name = NULL;
    2542           0 :         NTSTATUS status;
    2543             : 
    2544          24 :         DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
    2545             :                   smb_fname_str_dbg(smb_fname));
    2546             : 
    2547          24 :         if (!S_ISLNK(smb_fname->st.st_ex_mode)) {
    2548           0 :                 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
    2549             :         }
    2550             : 
    2551          24 :         status = parent_pathref(
    2552             :                 talloc_tos(),
    2553             :                 conn->cwd_fsp,
    2554             :                 smb_fname,
    2555             :                 &parent_fname,
    2556             :                 &base_name);
    2557             : 
    2558          24 :         if (!NT_STATUS_IS_OK(status)) {
    2559           0 :                 DBG_DEBUG("parent_pathref failed: %s\n", nt_errstr(status));
    2560           0 :                 return status;
    2561             :         }
    2562             : 
    2563          24 :         link_len = SMB_VFS_READLINKAT(
    2564             :                 conn,
    2565             :                 parent_fname->fsp,
    2566             :                 base_name,
    2567             :                 buffer,
    2568             :                 sizeof(buffer)-1);
    2569          24 :         TALLOC_FREE(parent_fname);
    2570             : 
    2571          24 :         if (link_len == -1) {
    2572           0 :                 status = map_nt_error_from_unix(errno);
    2573           0 :                 DBG_DEBUG("READLINKAT failed: %s\n", nt_errstr(status));
    2574           0 :                 return status;
    2575             :         }
    2576          24 :         if (link_len >= sizeof(buffer)) {
    2577           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2578             :         }
    2579          24 :         buffer[link_len] = 0;
    2580             : 
    2581          24 :         needed = (link_len+1)*2;
    2582             : 
    2583          24 :         *ppdata = SMB_REALLOC(*ppdata, needed);
    2584          24 :         if (*ppdata == NULL) {
    2585           0 :                 return NT_STATUS_NO_MEMORY;
    2586             :         }
    2587          24 :         pdata = *ppdata;
    2588             : 
    2589          24 :         status = srvstr_push(
    2590             :                 pdata,
    2591             :                 req->flags2,
    2592             :                 pdata,
    2593             :                 buffer,
    2594             :                 needed,
    2595             :                 STR_TERMINATE,
    2596             :                 &len);
    2597          24 :         if (!NT_STATUS_IS_OK(status)) {
    2598           0 :                 return status;
    2599             :         }
    2600          24 :         *ptotal_data = len;
    2601             : 
    2602          24 :         return NT_STATUS_OK;
    2603             : }
    2604             : 
    2605       10817 : static void call_trans2qpathinfo(
    2606             :         connection_struct *conn,
    2607             :         struct smb_request *req,
    2608             :         char **pparams,
    2609             :         int total_params,
    2610             :         char **ppdata,
    2611             :         int total_data,
    2612             :         unsigned int max_data_bytes)
    2613             : {
    2614       10817 :         char *params = *pparams;
    2615         289 :         uint16_t info_level;
    2616       10817 :         struct smb_filename *smb_fname = NULL;
    2617       10817 :         bool delete_pending = False;
    2618       10817 :         struct timespec write_time_ts = { .tv_sec = 0, };
    2619       10817 :         struct files_struct *dirfsp = NULL;
    2620       10817 :         files_struct *fsp = NULL;
    2621         289 :         struct file_id fileid;
    2622         289 :         uint32_t name_hash;
    2623       10817 :         char *fname = NULL;
    2624       10817 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    2625       10817 :         NTTIME twrp = 0;
    2626         289 :         bool info_level_handled;
    2627       10817 :         NTSTATUS status = NT_STATUS_OK;
    2628         289 :         int ret;
    2629             : 
    2630       10817 :         if (!params) {
    2631           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2632           0 :                 return;
    2633             :         }
    2634             : 
    2635             : 
    2636             :         /* qpathinfo */
    2637       10817 :         if (total_params < 7) {
    2638           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2639           0 :                 return;
    2640             :         }
    2641             : 
    2642       10817 :         info_level = SVAL(params,0);
    2643             : 
    2644       10817 :         DBG_NOTICE("TRANSACT2_QPATHINFO: level = %d\n", info_level);
    2645             : 
    2646       10817 :         if (INFO_LEVEL_IS_UNIX(info_level)) {
    2647         242 :                 if (!lp_smb1_unix_extensions()) {
    2648           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    2649           0 :                         return;
    2650             :                 }
    2651         242 :                 if (!req->posix_pathnames) {
    2652           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    2653           0 :                         return;
    2654             :                 }
    2655             :         }
    2656             : 
    2657       10817 :         if (req->posix_pathnames) {
    2658         450 :                 srvstr_get_path_posix(req,
    2659             :                                       params,
    2660         450 :                                       req->flags2,
    2661             :                                       &fname,
    2662         450 :                                       &params[6],
    2663         450 :                                       total_params - 6,
    2664             :                                       STR_TERMINATE,
    2665             :                                       &status);
    2666             :         } else {
    2667       10367 :                 srvstr_get_path(req,
    2668             :                                 params,
    2669       10367 :                                 req->flags2,
    2670             :                                 &fname,
    2671       10367 :                                 &params[6],
    2672       10367 :                                 total_params - 6,
    2673             :                                 STR_TERMINATE,
    2674             :                                 &status);
    2675             :         }
    2676       10817 :         if (!NT_STATUS_IS_OK(status)) {
    2677           0 :                 reply_nterror(req, status);
    2678           0 :                 return;
    2679             :         }
    2680             : 
    2681       10817 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    2682        3632 :                 extract_snapshot_token(fname, &twrp);
    2683             :         }
    2684       10817 :         status = smb1_strip_dfs_path(req, &ucf_flags, &fname);
    2685       10817 :         if (!NT_STATUS_IS_OK(status)) {
    2686           0 :                 reply_nterror(req, status);
    2687           0 :                 return;
    2688             :         }
    2689       10817 :         status = filename_convert_dirfsp(req,
    2690             :                                          conn,
    2691             :                                          fname,
    2692             :                                          ucf_flags,
    2693             :                                          twrp,
    2694             :                                          &dirfsp,
    2695             :                                          &smb_fname);
    2696       10817 :         if (!NT_STATUS_IS_OK(status)) {
    2697        1758 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    2698        1208 :                         reply_botherror(req,
    2699             :                                         NT_STATUS_PATH_NOT_COVERED,
    2700             :                                         ERRSRV, ERRbadpath);
    2701        1208 :                         return;
    2702             :                 }
    2703         550 :                 reply_nterror(req, status);
    2704         550 :                 return;
    2705             :         }
    2706             : 
    2707             :         /*
    2708             :          * qpathinfo must operate on an existing file, so we
    2709             :          * can exit early if filename_convert_dirfsp() returned the
    2710             :          * "new file" NT_STATUS_OK, !VALID_STAT case.
    2711             :          */
    2712             : 
    2713        9059 :         if (!VALID_STAT(smb_fname->st)) {
    2714         110 :                 reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    2715         110 :                 return;
    2716             :         }
    2717             : 
    2718             :         /*
    2719             :          * smb_fname->fsp may be NULL if smb_fname points at a symlink
    2720             :          * and we're in POSIX context, so be careful when using fsp
    2721             :          * below, it can still be NULL.
    2722             :          */
    2723        8949 :         fsp = smb_fname->fsp;
    2724             : 
    2725             :         /* If this is a stream, check if there is a delete_pending. */
    2726        8949 :         if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
    2727        3069 :             && is_ntfs_stream_smb_fname(smb_fname)) {
    2728           0 :                 struct smb_filename *smb_fname_base;
    2729             : 
    2730             :                 /* Create an smb_filename with stream_name == NULL. */
    2731          60 :                 smb_fname_base = synthetic_smb_fname(
    2732             :                         talloc_tos(),
    2733          60 :                         smb_fname->base_name,
    2734             :                         NULL,
    2735             :                         NULL,
    2736          60 :                         smb_fname->twrp,
    2737          60 :                         smb_fname->flags);
    2738          60 :                 if (smb_fname_base == NULL) {
    2739           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    2740           0 :                         return;
    2741             :                 }
    2742             : 
    2743          60 :                 ret = vfs_stat(conn, smb_fname_base);
    2744          60 :                 if (ret != 0) {
    2745           0 :                         DBG_NOTICE("vfs_stat of %s failed "
    2746             :                                    "(%s)\n",
    2747             :                                    smb_fname_str_dbg(smb_fname_base),
    2748             :                                    strerror(errno));
    2749           0 :                         TALLOC_FREE(smb_fname_base);
    2750           0 :                         reply_nterror(req,
    2751             :                                       map_nt_error_from_unix(errno));
    2752           0 :                         return;
    2753             :                 }
    2754             : 
    2755          60 :                 status = file_name_hash(conn,
    2756             :                                         smb_fname_str_dbg(smb_fname_base),
    2757             :                                         &name_hash);
    2758          60 :                 if (!NT_STATUS_IS_OK(status)) {
    2759           0 :                         TALLOC_FREE(smb_fname_base);
    2760           0 :                         reply_nterror(req, status);
    2761           0 :                         return;
    2762             :                 }
    2763             : 
    2764          60 :                 fileid = vfs_file_id_from_sbuf(conn,
    2765          60 :                                                &smb_fname_base->st);
    2766          60 :                 TALLOC_FREE(smb_fname_base);
    2767          60 :                 get_file_infos(fileid, name_hash, &delete_pending, NULL);
    2768          60 :                 if (delete_pending) {
    2769           4 :                         reply_nterror(req, NT_STATUS_DELETE_PENDING);
    2770           4 :                         return;
    2771             :                 }
    2772             :         }
    2773             : 
    2774        8945 :         status = file_name_hash(conn,
    2775             :                                 smb_fname_str_dbg(smb_fname),
    2776             :                                 &name_hash);
    2777        8945 :         if (!NT_STATUS_IS_OK(status)) {
    2778           0 :                 reply_nterror(req, status);
    2779           0 :                 return;
    2780             :         }
    2781             : 
    2782        8945 :         if (fsp_getinfo_ask_sharemode(fsp)) {
    2783        8945 :                 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
    2784        8945 :                 get_file_infos(fileid, name_hash, &delete_pending,
    2785             :                                &write_time_ts);
    2786             :         }
    2787             : 
    2788        8945 :         if (delete_pending) {
    2789         119 :                 reply_nterror(req, NT_STATUS_DELETE_PENDING);
    2790         119 :                 return;
    2791             :         }
    2792             : 
    2793        8826 :         info_level_handled = true; /* Untouched in switch cases below */
    2794             : 
    2795        8826 :         switch (info_level) {
    2796             : 
    2797        8328 :         default:
    2798        8328 :                 info_level_handled = false;
    2799        8328 :                 break;
    2800             : 
    2801         114 :         case SMB_QUERY_FILE_UNIX_BASIC:
    2802         114 :                 status = smb_q_unix_basic(
    2803             :                         conn,
    2804             :                         req,
    2805             :                         smb_fname,
    2806         114 :                         smb_fname->fsp,
    2807             :                         ppdata,
    2808             :                         &total_data);
    2809         114 :                 break;
    2810             : 
    2811          16 :         case SMB_QUERY_FILE_UNIX_INFO2:
    2812          16 :                 status = smb_q_unix_info2(
    2813             :                         conn,
    2814             :                         req,
    2815             :                         smb_fname,
    2816          16 :                         smb_fname->fsp,
    2817             :                         ppdata,
    2818             :                         &total_data);
    2819          16 :                 break;
    2820             : 
    2821          80 :         case SMB_QUERY_POSIX_ACL:
    2822          80 :                 status = smb_q_posix_acl(
    2823             :                         conn,
    2824             :                         req,
    2825             :                         smb_fname,
    2826          80 :                         smb_fname->fsp,
    2827             :                         ppdata,
    2828             :                         &total_data);
    2829          80 :                 break;
    2830             : 
    2831          24 :         case SMB_QUERY_FILE_UNIX_LINK:
    2832          24 :                 status = smb_q_posix_symlink(
    2833             :                         conn,
    2834             :                         req,
    2835             :                         smb_fname,
    2836             :                         ppdata,
    2837             :                         &total_data);
    2838          24 :                 break;
    2839             :         }
    2840             : 
    2841        8562 :         if (info_level_handled) {
    2842         234 :                 handle_trans2qfilepathinfo_result(
    2843             :                         conn,
    2844             :                         req,
    2845             :                         info_level,
    2846             :                         status,
    2847             :                         *ppdata,
    2848             :                         total_data,
    2849             :                         total_data,
    2850             :                         max_data_bytes);
    2851         234 :                 return;
    2852             :         }
    2853             : 
    2854        8592 :         call_trans2qfilepathinfo(
    2855             :                 conn,
    2856             :                 req,
    2857             :                 TRANSACT2_QPATHINFO,
    2858             :                 info_level,
    2859             :                 smb_fname,
    2860             :                 fsp,
    2861             :                 false,
    2862             :                 write_time_ts,
    2863             :                 pparams,
    2864             :                 total_params,
    2865             :                 ppdata,
    2866             :                 total_data,
    2867             :                 max_data_bytes);
    2868             : }
    2869             : 
    2870           0 : static NTSTATUS smb_q_posix_lock(
    2871             :         struct connection_struct *conn,
    2872             :         struct smb_request *req,
    2873             :         struct files_struct *fsp,
    2874             :         char **ppdata,
    2875             :         int *ptotal_data)
    2876             : {
    2877           0 :         char *pdata = *ppdata;
    2878           0 :         int total_data = *ptotal_data;
    2879           0 :         uint64_t count;
    2880           0 :         uint64_t offset;
    2881           0 :         uint64_t smblctx;
    2882           0 :         enum brl_type lock_type;
    2883           0 :         NTSTATUS status;
    2884             : 
    2885           0 :         if (fsp->fsp_flags.is_pathref || (fsp_get_io_fd(fsp) == -1)) {
    2886           0 :                 return NT_STATUS_INVALID_HANDLE;
    2887             :         }
    2888             : 
    2889           0 :         if (total_data != POSIX_LOCK_DATA_SIZE) {
    2890           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2891             :         }
    2892             : 
    2893           0 :         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
    2894           0 :         case POSIX_LOCK_TYPE_READ:
    2895           0 :                 lock_type = READ_LOCK;
    2896           0 :                 break;
    2897           0 :         case POSIX_LOCK_TYPE_WRITE:
    2898           0 :                 lock_type = WRITE_LOCK;
    2899           0 :                 break;
    2900           0 :         case POSIX_LOCK_TYPE_UNLOCK:
    2901             :         default:
    2902             :                 /* There's no point in asking for an unlock... */
    2903           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2904             :         }
    2905             : 
    2906           0 :         smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
    2907           0 :         offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
    2908           0 :         count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
    2909             : 
    2910           0 :         status = query_lock(
    2911             :                 fsp,
    2912             :                 &smblctx,
    2913             :                 &count,
    2914             :                 &offset,
    2915             :                 &lock_type,
    2916             :                 POSIX_LOCK);
    2917             : 
    2918           0 :         if (NT_STATUS_IS_OK(status)) {
    2919             :                 /*
    2920             :                  * For success we just return a copy of what we sent
    2921             :                  * with the lock type set to POSIX_LOCK_TYPE_UNLOCK.
    2922             :                  */
    2923           0 :                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
    2924           0 :                 return NT_STATUS_OK;
    2925             :         }
    2926             : 
    2927           0 :         if (!ERROR_WAS_LOCK_DENIED(status)) {
    2928           0 :                 DBG_DEBUG("query_lock() failed: %s\n", nt_errstr(status));
    2929           0 :                 return status;
    2930             :         }
    2931             : 
    2932             :         /*
    2933             :          * Here we need to report who has it locked.
    2934             :          */
    2935             : 
    2936           0 :         SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
    2937           0 :         SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
    2938           0 :         SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
    2939           0 :         SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
    2940           0 :         SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
    2941             : 
    2942           0 :         return NT_STATUS_OK;
    2943             : }
    2944             : 
    2945        3617 : static void call_trans2qfileinfo(
    2946             :         connection_struct *conn,
    2947             :         struct smb_request *req,
    2948             :         char **pparams,
    2949             :         int total_params,
    2950             :         char **ppdata,
    2951             :         int total_data,
    2952             :         unsigned int max_data_bytes)
    2953             : {
    2954        3617 :         char *params = *pparams;
    2955         185 :         uint16_t info_level;
    2956        3617 :         struct smb_filename *smb_fname = NULL;
    2957        3617 :         bool delete_pending = False;
    2958        3617 :         struct timespec write_time_ts = { .tv_sec = 0, };
    2959        3617 :         files_struct *fsp = NULL;
    2960         185 :         struct file_id fileid;
    2961         185 :         bool info_level_handled;
    2962        3617 :         NTSTATUS status = NT_STATUS_OK;
    2963         185 :         int ret;
    2964             : 
    2965        3617 :         if (params == NULL) {
    2966           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2967           0 :                 return;
    2968             :         }
    2969             : 
    2970        3617 :         if (total_params < 4) {
    2971           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2972           0 :                 return;
    2973             :         }
    2974             : 
    2975        3617 :         fsp = file_fsp(req, SVAL(params,0));
    2976        3617 :         info_level = SVAL(params,2);
    2977             : 
    2978        3617 :         if (IS_IPC(conn)) {
    2979           0 :                 call_trans2qpipeinfo(
    2980             :                         conn,
    2981             :                         req,
    2982             :                         fsp,
    2983             :                         info_level,
    2984             :                         TRANSACT2_QFILEINFO,
    2985             :                         pparams,
    2986             :                         total_params,
    2987             :                         ppdata,
    2988             :                         total_data,
    2989             :                         max_data_bytes);
    2990           0 :                 return;
    2991             :         }
    2992             : 
    2993        3617 :         DBG_NOTICE("TRANSACT2_QFILEINFO: level = %d\n", info_level);
    2994             : 
    2995        3617 :         if (INFO_LEVEL_IS_UNIX(info_level)) {
    2996           4 :                 if (!lp_smb1_unix_extensions()) {
    2997           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    2998           0 :                         return;
    2999             :                 }
    3000           4 :                 if (!req->posix_pathnames) {
    3001           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    3002           0 :                         return;
    3003             :                 }
    3004             :         }
    3005             : 
    3006             :         /* Initial check for valid fsp ptr. */
    3007        3617 :         if (!check_fsp_open(conn, req, fsp)) {
    3008         144 :                 return;
    3009             :         }
    3010             : 
    3011        3473 :         smb_fname = fsp->fsp_name;
    3012             : 
    3013        3473 :         if(fsp->fake_file_handle) {
    3014             :                 /*
    3015             :                  * This is actually for the QUOTA_FAKE_FILE --metze
    3016             :                  */
    3017             : 
    3018             :                 /* We know this name is ok, it's already passed the checks. */
    3019             : 
    3020        3473 :         } else if(fsp_get_pathref_fd(fsp) == -1) {
    3021             :                 /*
    3022             :                  * This is actually a QFILEINFO on a directory
    3023             :                  * handle (returned from an NT SMB). NT5.0 seems
    3024             :                  * to do this call. JRA.
    3025             :                  */
    3026           0 :                 ret = vfs_stat(conn, smb_fname);
    3027           0 :                 if (ret != 0) {
    3028           0 :                         DBG_NOTICE("vfs_stat of %s failed (%s)\n",
    3029             :                                    smb_fname_str_dbg(smb_fname),
    3030             :                                    strerror(errno));
    3031           0 :                         reply_nterror(req,
    3032             :                                       map_nt_error_from_unix(errno));
    3033           0 :                         return;
    3034             :                 }
    3035             : 
    3036           0 :                 if (fsp_getinfo_ask_sharemode(fsp)) {
    3037           0 :                         fileid = vfs_file_id_from_sbuf(
    3038           0 :                                 conn, &smb_fname->st);
    3039           0 :                         get_file_infos(fileid, fsp->name_hash,
    3040             :                                        &delete_pending,
    3041             :                                        &write_time_ts);
    3042             :                 }
    3043             :         } else {
    3044             :                 /*
    3045             :                  * Original code - this is an open file.
    3046             :                  */
    3047        3473 :                 status = vfs_stat_fsp(fsp);
    3048        3473 :                 if (!NT_STATUS_IS_OK(status)) {
    3049           0 :                         DEBUG(3, ("fstat of %s failed (%s)\n",
    3050             :                                   fsp_fnum_dbg(fsp), nt_errstr(status)));
    3051           0 :                         reply_nterror(req, status);
    3052           0 :                         return;
    3053             :                 }
    3054        3473 :                 if (fsp_getinfo_ask_sharemode(fsp)) {
    3055        3473 :                         fileid = vfs_file_id_from_sbuf(
    3056        3473 :                                 conn, &smb_fname->st);
    3057        3473 :                         get_file_infos(fileid, fsp->name_hash,
    3058             :                                        &delete_pending,
    3059             :                                        &write_time_ts);
    3060             :                 }
    3061             :         }
    3062             : 
    3063        3473 :         info_level_handled = true; /* Untouched in switch cases below */
    3064             : 
    3065        3473 :         switch (info_level) {
    3066             : 
    3067        3284 :         default:
    3068        3284 :                 info_level_handled = false;
    3069        3284 :                 break;
    3070             : 
    3071           0 :         case SMB_QUERY_POSIX_LOCK:
    3072           0 :                 status = smb_q_posix_lock(conn, req, fsp, ppdata, &total_data);
    3073           0 :                 break;
    3074             : 
    3075           0 :         case SMB_QUERY_FILE_UNIX_BASIC:
    3076           0 :                 status = smb_q_unix_basic(
    3077             :                         conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
    3078           0 :                 break;
    3079             : 
    3080           4 :         case SMB_QUERY_FILE_UNIX_INFO2:
    3081           4 :                 status = smb_q_unix_info2(
    3082             :                         conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
    3083           4 :                 break;
    3084             : 
    3085           0 :         case SMB_QUERY_POSIX_ACL:
    3086           0 :                 status = smb_q_posix_acl(
    3087             :                         conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
    3088           0 :                 break;
    3089             :         }
    3090             : 
    3091        3288 :         if (info_level_handled) {
    3092           4 :                 handle_trans2qfilepathinfo_result(
    3093             :                         conn,
    3094             :                         req,
    3095             :                         info_level,
    3096             :                         status,
    3097             :                         *ppdata,
    3098             :                         total_data,
    3099             :                         total_data,
    3100             :                         max_data_bytes);
    3101           4 :                 return;
    3102             :         }
    3103             : 
    3104        3469 :         call_trans2qfilepathinfo(
    3105             :                 conn,
    3106             :                 req,
    3107             :                 TRANSACT2_QFILEINFO,
    3108             :                 info_level,
    3109             :                 smb_fname,
    3110             :                 fsp,
    3111             :                 delete_pending,
    3112             :                 write_time_ts,
    3113             :                 pparams,
    3114             :                 total_params,
    3115             :                 ppdata,
    3116             :                 total_data,
    3117             :                 max_data_bytes);
    3118             : }
    3119             : 
    3120        5607 : static void handle_trans2setfilepathinfo_result(
    3121             :         connection_struct *conn,
    3122             :         struct smb_request *req,
    3123             :         uint16_t info_level,
    3124             :         NTSTATUS status,
    3125             :         char *pdata,
    3126             :         int data_return_size,
    3127             :         unsigned int max_data_bytes)
    3128             : {
    3129        5607 :         char params[2] = { 0, 0, };
    3130             : 
    3131        5607 :         if (NT_STATUS_IS_OK(status)) {
    3132        4680 :                 send_trans2_replies(
    3133             :                         conn,
    3134             :                         req,
    3135        4680 :                         NT_STATUS_OK,
    3136             :                         params,
    3137             :                         2,
    3138             :                         pdata,
    3139             :                         data_return_size,
    3140             :                         max_data_bytes);
    3141        4680 :                 return;
    3142             :         }
    3143             : 
    3144         927 :         if (open_was_deferred(req->xconn, req->mid)) {
    3145             :                 /* We have re-scheduled this call. */
    3146           6 :                 return;
    3147             :         }
    3148             : 
    3149         921 :         if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
    3150          32 :                 bool ok = defer_smb1_sharing_violation(req);
    3151          32 :                 if (ok) {
    3152          16 :                         return;
    3153             :                 }
    3154             :         }
    3155             : 
    3156         905 :         if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
    3157             :                 /* We have re-scheduled this call. */
    3158          28 :                 return;
    3159             :         }
    3160             : 
    3161         877 :         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    3162           0 :                 reply_botherror(
    3163             :                         req,
    3164             :                         NT_STATUS_PATH_NOT_COVERED,
    3165             :                         ERRSRV,
    3166             :                         ERRbadpath);
    3167           0 :                 return;
    3168             :         }
    3169             : 
    3170         877 :         if (info_level == SMB_POSIX_PATH_OPEN) {
    3171          12 :                 reply_openerror(req, status);
    3172          12 :                 return;
    3173             :         }
    3174             : 
    3175         865 :         if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
    3176             :                 /*
    3177             :                  * Invalid EA name needs to return 2 param bytes,
    3178             :                  * not a zero-length error packet.
    3179             :                  */
    3180             : 
    3181         235 :                 send_trans2_replies(
    3182             :                         conn,
    3183             :                         req,
    3184             :                         status,
    3185             :                         params,
    3186             :                         2,
    3187             :                         NULL,
    3188             :                         0,
    3189             :                         max_data_bytes);
    3190         235 :                 return;
    3191             :         }
    3192             : 
    3193         630 :         reply_nterror(req, status);
    3194             : }
    3195             : 
    3196             : /****************************************************************************
    3197             :  Create a directory with POSIX semantics.
    3198             : ****************************************************************************/
    3199             : 
    3200          48 : static NTSTATUS smb_posix_mkdir(connection_struct *conn,
    3201             :                                 struct smb_request *req,
    3202             :                                 char **ppdata,
    3203             :                                 int total_data,
    3204             :                                 struct smb_filename *smb_fname,
    3205             :                                 int *pdata_return_size)
    3206             : {
    3207          48 :         NTSTATUS status = NT_STATUS_OK;
    3208          48 :         uint32_t raw_unixmode = 0;
    3209          48 :         mode_t unixmode = (mode_t)0;
    3210          48 :         files_struct *fsp = NULL;
    3211          48 :         uint16_t info_level_return = 0;
    3212           0 :         int info;
    3213          48 :         char *pdata = *ppdata;
    3214          48 :         struct smb2_create_blobs *posx = NULL;
    3215             : 
    3216          48 :         if (total_data < 18) {
    3217           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3218             :         }
    3219             : 
    3220          48 :         raw_unixmode = IVAL(pdata,8);
    3221             :         /* Next 4 bytes are not yet defined. */
    3222             : 
    3223          48 :         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
    3224             :                                       PERM_NEW_DIR, &unixmode);
    3225          48 :         if (!NT_STATUS_IS_OK(status)) {
    3226           0 :                 return status;
    3227             :         }
    3228             : 
    3229          48 :         status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
    3230          48 :         if (!NT_STATUS_IS_OK(status)) {
    3231           0 :                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
    3232             :                             nt_errstr(status));
    3233           0 :                 return status;
    3234             :         }
    3235             : 
    3236          48 :         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
    3237             :                   smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
    3238             : 
    3239          48 :         status = SMB_VFS_CREATE_FILE(
    3240             :                 conn,                                   /* conn */
    3241             :                 req,                                    /* req */
    3242             :                 NULL,                                   /* dirfsp */
    3243             :                 smb_fname,                              /* fname */
    3244             :                 FILE_READ_ATTRIBUTES,                   /* access_mask */
    3245             :                 FILE_SHARE_NONE,                        /* share_access */
    3246             :                 FILE_CREATE,                            /* create_disposition*/
    3247             :                 FILE_DIRECTORY_FILE,                    /* create_options */
    3248             :                 0,                                      /* file_attributes */
    3249             :                 0,                                      /* oplock_request */
    3250             :                 NULL,                                   /* lease */
    3251             :                 0,                                      /* allocation_size */
    3252             :                 0,                                      /* private_flags */
    3253             :                 NULL,                                   /* sd */
    3254             :                 NULL,                                   /* ea_list */
    3255             :                 &fsp,                                       /* result */
    3256             :                 &info,                                      /* pinfo */
    3257             :                 posx,                                   /* in_context_blobs */
    3258             :                 NULL);                                  /* out_context_blobs */
    3259             : 
    3260          48 :         TALLOC_FREE(posx);
    3261             : 
    3262          48 :         if (NT_STATUS_IS_OK(status)) {
    3263          48 :                 close_file_free(req, &fsp, NORMAL_CLOSE);
    3264             :         }
    3265             : 
    3266          48 :         info_level_return = SVAL(pdata,16);
    3267             : 
    3268          48 :         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
    3269           0 :                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
    3270          48 :         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
    3271           0 :                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
    3272             :         } else {
    3273          48 :                 *pdata_return_size = 12;
    3274             :         }
    3275             : 
    3276             :         /* Realloc the data size */
    3277          48 :         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
    3278          48 :         if (*ppdata == NULL) {
    3279           0 :                 *pdata_return_size = 0;
    3280           0 :                 return NT_STATUS_NO_MEMORY;
    3281             :         }
    3282          48 :         pdata = *ppdata;
    3283             : 
    3284          48 :         SSVAL(pdata,0,NO_OPLOCK_RETURN);
    3285          48 :         SSVAL(pdata,2,0); /* No fnum. */
    3286          48 :         SIVAL(pdata,4,info); /* Was directory created. */
    3287             : 
    3288          48 :         switch (info_level_return) {
    3289           0 :                 case SMB_QUERY_FILE_UNIX_BASIC:
    3290           0 :                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
    3291           0 :                         SSVAL(pdata,10,0); /* Padding. */
    3292           0 :                         store_file_unix_basic(conn, pdata + 12, fsp,
    3293           0 :                                               &smb_fname->st);
    3294           0 :                         break;
    3295           0 :                 case SMB_QUERY_FILE_UNIX_INFO2:
    3296           0 :                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
    3297           0 :                         SSVAL(pdata,10,0); /* Padding. */
    3298           0 :                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
    3299           0 :                                                     &smb_fname->st);
    3300           0 :                         break;
    3301          48 :                 default:
    3302          48 :                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
    3303          48 :                         SSVAL(pdata,10,0); /* Padding. */
    3304          48 :                         break;
    3305             :         }
    3306             : 
    3307          48 :         return status;
    3308             : }
    3309             : 
    3310             : /****************************************************************************
    3311             :  Open/Create a file with POSIX semantics.
    3312             : ****************************************************************************/
    3313             : 
    3314             : #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
    3315             : #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
    3316             : 
    3317         174 : static NTSTATUS smb_posix_open(connection_struct *conn,
    3318             :                                struct smb_request *req,
    3319             :                                char **ppdata,
    3320             :                                int total_data,
    3321             :                                struct files_struct *dirfsp,
    3322             :                                struct smb_filename *smb_fname,
    3323             :                                int *pdata_return_size)
    3324             : {
    3325         174 :         bool extended_oplock_granted = False;
    3326         174 :         char *pdata = *ppdata;
    3327         174 :         uint32_t flags = 0;
    3328         174 :         uint32_t wire_open_mode = 0;
    3329         174 :         uint32_t raw_unixmode = 0;
    3330         174 :         uint32_t attributes = 0;
    3331         174 :         uint32_t create_disp = 0;
    3332         174 :         uint32_t access_mask = 0;
    3333         174 :         uint32_t create_options = FILE_NON_DIRECTORY_FILE;
    3334         174 :         NTSTATUS status = NT_STATUS_OK;
    3335         174 :         mode_t unixmode = (mode_t)0;
    3336         174 :         files_struct *fsp = NULL;
    3337         174 :         int oplock_request = 0;
    3338         174 :         int info = 0;
    3339         174 :         uint16_t info_level_return = 0;
    3340         174 :         struct smb2_create_blobs *posx = NULL;
    3341             : 
    3342         174 :         if (total_data < 18) {
    3343           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3344             :         }
    3345             : 
    3346         174 :         flags = IVAL(pdata,0);
    3347         174 :         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
    3348         174 :         if (oplock_request) {
    3349           0 :                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
    3350             :         }
    3351             : 
    3352         174 :         wire_open_mode = IVAL(pdata,4);
    3353             : 
    3354         174 :         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
    3355          48 :                 return smb_posix_mkdir(conn, req,
    3356             :                                         ppdata,
    3357             :                                         total_data,
    3358             :                                         smb_fname,
    3359             :                                         pdata_return_size);
    3360             :         }
    3361             : 
    3362         126 :         switch (wire_open_mode & SMB_ACCMODE) {
    3363          28 :                 case SMB_O_RDONLY:
    3364          28 :                         access_mask = SMB_O_RDONLY_MAPPING;
    3365          28 :                         break;
    3366           4 :                 case SMB_O_WRONLY:
    3367           4 :                         access_mask = SMB_O_WRONLY_MAPPING;
    3368           4 :                         break;
    3369          94 :                 case SMB_O_RDWR:
    3370          94 :                         access_mask = (SMB_O_RDONLY_MAPPING|
    3371             :                                         SMB_O_WRONLY_MAPPING);
    3372          94 :                         break;
    3373           0 :                 default:
    3374           0 :                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
    3375             :                                 (unsigned int)wire_open_mode ));
    3376           0 :                         return NT_STATUS_INVALID_PARAMETER;
    3377             :         }
    3378             : 
    3379         126 :         wire_open_mode &= ~SMB_ACCMODE;
    3380             : 
    3381             :         /* First take care of O_CREAT|O_EXCL interactions. */
    3382         126 :         switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
    3383          38 :                 case (SMB_O_CREAT | SMB_O_EXCL):
    3384             :                         /* File exists fail. File not exist create. */
    3385          38 :                         create_disp = FILE_CREATE;
    3386          38 :                         break;
    3387          40 :                 case SMB_O_CREAT:
    3388             :                         /* File exists open. File not exist create. */
    3389          40 :                         create_disp = FILE_OPEN_IF;
    3390          40 :                         break;
    3391          48 :                 case SMB_O_EXCL:
    3392             :                         /* O_EXCL on its own without O_CREAT is undefined.
    3393             :                            We deliberately ignore it as some versions of
    3394             :                            Linux CIFSFS can send a bare O_EXCL on the
    3395             :                            wire which other filesystems in the kernel
    3396             :                            ignore. See bug 9519 for details. */
    3397             : 
    3398             :                         /* Fallthrough. */
    3399             : 
    3400             :                 case 0:
    3401             :                         /* File exists open. File not exist fail. */
    3402          48 :                         create_disp = FILE_OPEN;
    3403          48 :                         break;
    3404           0 :                 default:
    3405           0 :                         DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
    3406             :                                 (unsigned int)wire_open_mode ));
    3407           0 :                         return NT_STATUS_INVALID_PARAMETER;
    3408             :         }
    3409             : 
    3410             :         /* Next factor in the effects of O_TRUNC. */
    3411         126 :         wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
    3412             : 
    3413         126 :         if (wire_open_mode & SMB_O_TRUNC) {
    3414           4 :                 switch (create_disp) {
    3415           0 :                         case FILE_CREATE:
    3416             :                                 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
    3417             :                                 /* Leave create_disp alone as
    3418             :                                    (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
    3419             :                                 */
    3420             :                                 /* File exists fail. File not exist create. */
    3421           4 :                                 break;
    3422           0 :                         case FILE_OPEN_IF:
    3423             :                                 /* SMB_O_CREAT | SMB_O_TRUNC */
    3424             :                                 /* File exists overwrite. File not exist create. */
    3425           0 :                                 create_disp = FILE_OVERWRITE_IF;
    3426           0 :                                 break;
    3427           4 :                         case FILE_OPEN:
    3428             :                                 /* SMB_O_TRUNC */
    3429             :                                 /* File exists overwrite. File not exist fail. */
    3430           4 :                                 create_disp = FILE_OVERWRITE;
    3431           4 :                                 break;
    3432           0 :                         default:
    3433             :                                 /* Cannot get here. */
    3434           0 :                                 smb_panic("smb_posix_open: logic error");
    3435             :                                 return NT_STATUS_INVALID_PARAMETER;
    3436             :                 }
    3437             :         }
    3438             : 
    3439         126 :         raw_unixmode = IVAL(pdata,8);
    3440             :         /* Next 4 bytes are not yet defined. */
    3441             : 
    3442         126 :         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
    3443         126 :                                       (VALID_STAT(smb_fname->st) ?
    3444             :                                           PERM_EXISTING_FILE : PERM_NEW_FILE),
    3445             :                                       &unixmode);
    3446             : 
    3447         126 :         if (!NT_STATUS_IS_OK(status)) {
    3448           0 :                 return status;
    3449             :         }
    3450             : 
    3451         126 :         status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
    3452         126 :         if (!NT_STATUS_IS_OK(status)) {
    3453           0 :                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
    3454             :                             nt_errstr(status));
    3455           0 :                 return status;
    3456             :         }
    3457             : 
    3458         126 :         if (wire_open_mode & SMB_O_SYNC) {
    3459           0 :                 create_options |= FILE_WRITE_THROUGH;
    3460             :         }
    3461         126 :         if (wire_open_mode & SMB_O_APPEND) {
    3462           0 :                 access_mask |= FILE_APPEND_DATA;
    3463             :         }
    3464         126 :         if (wire_open_mode & SMB_O_DIRECT) {
    3465             :                 /*
    3466             :                  * BUG: this doesn't work anymore since
    3467             :                  * e0814dc5082dd4ecca8a155e0ce24b073158fd92. But since
    3468             :                  * FILE_FLAG_NO_BUFFERING isn't used at all in the IO codepath,
    3469             :                  * it doesn't really matter.
    3470             :                  */
    3471           0 :                 attributes |= FILE_FLAG_NO_BUFFERING;
    3472             :         }
    3473             : 
    3474         126 :         if ((wire_open_mode & SMB_O_DIRECTORY) ||
    3475         126 :                         VALID_STAT_OF_DIR(smb_fname->st)) {
    3476           8 :                 if (access_mask != SMB_O_RDONLY_MAPPING) {
    3477           4 :                         return NT_STATUS_FILE_IS_A_DIRECTORY;
    3478             :                 }
    3479           4 :                 create_options &= ~FILE_NON_DIRECTORY_FILE;
    3480           4 :                 create_options |= FILE_DIRECTORY_FILE;
    3481             :         }
    3482             : 
    3483         122 :         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
    3484             :                 smb_fname_str_dbg(smb_fname),
    3485             :                 (unsigned int)wire_open_mode,
    3486             :                 (unsigned int)unixmode ));
    3487             : 
    3488         122 :         status = SMB_VFS_CREATE_FILE(
    3489             :                 conn,                                   /* conn */
    3490             :                 req,                                    /* req */
    3491             :                 dirfsp,                                 /* dirfsp */
    3492             :                 smb_fname,                              /* fname */
    3493             :                 access_mask,                            /* access_mask */
    3494             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    3495             :                     FILE_SHARE_DELETE),
    3496             :                 create_disp,                            /* create_disposition*/
    3497             :                 create_options,                         /* create_options */
    3498             :                 attributes,                             /* file_attributes */
    3499             :                 oplock_request,                         /* oplock_request */
    3500             :                 NULL,                                   /* lease */
    3501             :                 0,                                      /* allocation_size */
    3502             :                 0,                                      /* private_flags */
    3503             :                 NULL,                                   /* sd */
    3504             :                 NULL,                                   /* ea_list */
    3505             :                 &fsp,                                       /* result */
    3506             :                 &info,                                      /* pinfo */
    3507             :                 posx,                                   /* in_context_blobs */
    3508             :                 NULL);                                  /* out_context_blobs */
    3509             : 
    3510         122 :         TALLOC_FREE(posx);
    3511             : 
    3512         122 :         if (!NT_STATUS_IS_OK(status)) {
    3513           8 :                 return status;
    3514             :         }
    3515             : 
    3516         114 :         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
    3517           0 :                 extended_oplock_granted = True;
    3518             :         }
    3519             : 
    3520         114 :         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
    3521           0 :                 extended_oplock_granted = True;
    3522             :         }
    3523             : 
    3524         114 :         info_level_return = SVAL(pdata,16);
    3525             : 
    3526             :         /* Allocate the correct return size. */
    3527             : 
    3528         114 :         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
    3529           0 :                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
    3530         114 :         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
    3531           0 :                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
    3532             :         } else {
    3533         114 :                 *pdata_return_size = 12;
    3534             :         }
    3535             : 
    3536             :         /* Realloc the data size */
    3537         114 :         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
    3538         114 :         if (*ppdata == NULL) {
    3539           0 :                 close_file_free(req, &fsp, ERROR_CLOSE);
    3540           0 :                 *pdata_return_size = 0;
    3541           0 :                 return NT_STATUS_NO_MEMORY;
    3542             :         }
    3543         114 :         pdata = *ppdata;
    3544             : 
    3545         114 :         if (extended_oplock_granted) {
    3546           0 :                 if (flags & REQUEST_BATCH_OPLOCK) {
    3547           0 :                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
    3548             :                 } else {
    3549           0 :                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
    3550             :                 }
    3551         114 :         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
    3552           0 :                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
    3553             :         } else {
    3554         114 :                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
    3555             :         }
    3556             : 
    3557         114 :         SSVAL(pdata,2,fsp->fnum);
    3558         114 :         SIVAL(pdata,4,info); /* Was file created etc. */
    3559             : 
    3560         114 :         switch (info_level_return) {
    3561           0 :                 case SMB_QUERY_FILE_UNIX_BASIC:
    3562           0 :                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
    3563           0 :                         SSVAL(pdata,10,0); /* padding. */
    3564           0 :                         store_file_unix_basic(conn, pdata + 12, fsp,
    3565           0 :                                               &smb_fname->st);
    3566           0 :                         break;
    3567           0 :                 case SMB_QUERY_FILE_UNIX_INFO2:
    3568           0 :                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
    3569           0 :                         SSVAL(pdata,10,0); /* padding. */
    3570           0 :                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
    3571           0 :                                                     &smb_fname->st);
    3572           0 :                         break;
    3573         114 :                 default:
    3574         114 :                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
    3575         114 :                         SSVAL(pdata,10,0); /* padding. */
    3576         114 :                         break;
    3577             :         }
    3578         114 :         return NT_STATUS_OK;
    3579             : }
    3580             : 
    3581             : /****************************************************************************
    3582             :  Delete a file with POSIX semantics.
    3583             : ****************************************************************************/
    3584             : 
    3585             : struct smb_posix_unlink_state {
    3586             :         struct smb_filename *smb_fname;
    3587             :         struct files_struct *fsp;
    3588             :         NTSTATUS status;
    3589             : };
    3590             : 
    3591         248 : static void smb_posix_unlink_locked(struct share_mode_lock *lck,
    3592             :                                     void *private_data)
    3593             : {
    3594         248 :         struct smb_posix_unlink_state *state = private_data;
    3595         248 :         char del = 1;
    3596           0 :         bool other_nonposix_opens;
    3597             : 
    3598         248 :         other_nonposix_opens = has_other_nonposix_opens(lck, state->fsp);
    3599         248 :         if (other_nonposix_opens) {
    3600             :                 /* Fail with sharing violation. */
    3601           8 :                 state->status = NT_STATUS_SHARING_VIOLATION;
    3602           8 :                 return;
    3603             :         }
    3604             : 
    3605             :         /*
    3606             :          * Set the delete on close.
    3607             :          */
    3608         240 :         state->status = smb_set_file_disposition_info(state->fsp->conn,
    3609             :                                                       &del,
    3610             :                                                       1,
    3611         240 :                                                       state->fsp,
    3612             :                                                       state->smb_fname);
    3613             : }
    3614             : 
    3615         532 : static NTSTATUS smb_posix_unlink(connection_struct *conn,
    3616             :                                  struct smb_request *req,
    3617             :                                  const char *pdata,
    3618             :                                  int total_data,
    3619             :                                  struct files_struct *dirfsp,
    3620             :                                  struct smb_filename *smb_fname)
    3621             : {
    3622         532 :         struct smb_posix_unlink_state state = {};
    3623         532 :         NTSTATUS status = NT_STATUS_OK;
    3624         532 :         files_struct *fsp = NULL;
    3625         532 :         uint16_t flags = 0;
    3626         532 :         int info = 0;
    3627         532 :         int create_options = FILE_OPEN_REPARSE_POINT;
    3628         532 :         struct smb2_create_blobs *posx = NULL;
    3629             : 
    3630         532 :         if (!CAN_WRITE(conn)) {
    3631           0 :                 return NT_STATUS_DOS(ERRSRV, ERRaccess);
    3632             :         }
    3633             : 
    3634         532 :         if (total_data < 2) {
    3635           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3636             :         }
    3637             : 
    3638         532 :         flags = SVAL(pdata,0);
    3639             : 
    3640         532 :         if (!VALID_STAT(smb_fname->st)) {
    3641         276 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    3642             :         }
    3643             : 
    3644         256 :         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
    3645          40 :                         !VALID_STAT_OF_DIR(smb_fname->st)) {
    3646           0 :                 return NT_STATUS_NOT_A_DIRECTORY;
    3647             :         }
    3648             : 
    3649         256 :         DEBUG(10,("smb_posix_unlink: %s %s\n",
    3650             :                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
    3651             :                 smb_fname_str_dbg(smb_fname)));
    3652             : 
    3653         256 :         if (S_ISDIR(smb_fname->st.st_ex_mode)) {
    3654          44 :                 create_options |= FILE_DIRECTORY_FILE;
    3655             :         }
    3656             : 
    3657         256 :         status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
    3658         256 :         if (!NT_STATUS_IS_OK(status)) {
    3659           0 :                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
    3660             :                             nt_errstr(status));
    3661           0 :                 return status;
    3662             :         }
    3663             : 
    3664         256 :         status = SMB_VFS_CREATE_FILE(
    3665             :                 conn,                                   /* conn */
    3666             :                 req,                                    /* req */
    3667             :                 dirfsp,                                 /* dirfsp */
    3668             :                 smb_fname,                              /* fname */
    3669             :                 DELETE_ACCESS,                          /* access_mask */
    3670             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    3671             :                     FILE_SHARE_DELETE),
    3672             :                 FILE_OPEN,                              /* create_disposition*/
    3673             :                 create_options,                         /* create_options */
    3674             :                 0,                                      /* file_attributes */
    3675             :                 0,                                      /* oplock_request */
    3676             :                 NULL,                                   /* lease */
    3677             :                 0,                                      /* allocation_size */
    3678             :                 0,                                      /* private_flags */
    3679             :                 NULL,                                   /* sd */
    3680             :                 NULL,                                   /* ea_list */
    3681             :                 &fsp,                                       /* result */
    3682             :                 &info,                                      /* pinfo */
    3683             :                 posx,                                   /* in_context_blobs */
    3684             :                 NULL);                                  /* out_context_blobs */
    3685             : 
    3686         256 :         TALLOC_FREE(posx);
    3687             : 
    3688         256 :         if (!NT_STATUS_IS_OK(status)) {
    3689           8 :                 return status;
    3690             :         }
    3691             : 
    3692             :         /*
    3693             :          * Don't lie to client. If we can't really delete due to
    3694             :          * non-POSIX opens return SHARING_VIOLATION.
    3695             :          */
    3696             : 
    3697         248 :         state = (struct smb_posix_unlink_state) {
    3698             :                 .smb_fname = smb_fname,
    3699             :                 .fsp = fsp,
    3700             :         };
    3701             : 
    3702         248 :         status = share_mode_do_locked_vfs_allowed(fsp->file_id,
    3703             :                                                   smb_posix_unlink_locked,
    3704             :                                                   &state);
    3705         248 :         if (!NT_STATUS_IS_OK(status)) {
    3706           0 :                 DBG_ERR("share_mode_do_locked_vfs_allowed(%s) failed - %s\n",
    3707             :                         fsp_str_dbg(fsp), nt_errstr(status));
    3708           0 :                 close_file_free(req, &fsp, NORMAL_CLOSE);
    3709           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3710             :         }
    3711             : 
    3712         248 :         status = state.status;
    3713         248 :         if (!NT_STATUS_IS_OK(status)) {
    3714           8 :                 close_file_free(req, &fsp, NORMAL_CLOSE);
    3715           8 :                 return status;
    3716             :         }
    3717         240 :         return close_file_free(req, &fsp, NORMAL_CLOSE);
    3718             : }
    3719             : 
    3720             : /****************************************************************************
    3721             :  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
    3722             : ****************************************************************************/
    3723             : 
    3724         128 : static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
    3725             :                                        struct smb_request *req,
    3726             :                                        const char *pdata,
    3727             :                                        int total_data,
    3728             :                                        struct smb_filename *new_smb_fname)
    3729             : {
    3730         128 :         char *link_target = NULL;
    3731           0 :         struct smb_filename target_fname;
    3732         128 :         TALLOC_CTX *ctx = talloc_tos();
    3733           0 :         NTSTATUS status;
    3734           0 :         int ret;
    3735         128 :         struct smb_filename *parent_fname = NULL;
    3736         128 :         struct smb_filename *base_name = NULL;
    3737             : 
    3738         128 :         if (!CAN_WRITE(conn)) {
    3739           0 :                 return NT_STATUS_DOS(ERRSRV, ERRaccess);
    3740             :         }
    3741             : 
    3742             :         /* Set a symbolic link. */
    3743             :         /* Don't allow this if follow links is false. */
    3744             : 
    3745         128 :         if (total_data == 0) {
    3746           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3747             :         }
    3748             : 
    3749         128 :         if (!lp_follow_symlinks(SNUM(conn))) {
    3750           0 :                 return NT_STATUS_ACCESS_DENIED;
    3751             :         }
    3752             : 
    3753         128 :         srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
    3754             :                     total_data, STR_TERMINATE);
    3755             : 
    3756         128 :         if (!link_target) {
    3757           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3758             :         }
    3759             : 
    3760         128 :         target_fname = (struct smb_filename) {
    3761             :                 .base_name = link_target,
    3762             :         };
    3763             : 
    3764             :         /* Removes @GMT tokens if any */
    3765         128 :         status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
    3766         128 :         if (!NT_STATUS_IS_OK(status)) {
    3767           0 :                 return status;
    3768             :         }
    3769             : 
    3770         128 :         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
    3771             :                         new_smb_fname->base_name, link_target ));
    3772             : 
    3773         128 :         status = parent_pathref(talloc_tos(),
    3774             :                                 conn->cwd_fsp,
    3775             :                                 new_smb_fname,
    3776             :                                 &parent_fname,
    3777             :                                 &base_name);
    3778         128 :         if (!NT_STATUS_IS_OK(status)) {
    3779           0 :                 return status;
    3780             :         }
    3781             : 
    3782         128 :         ret = SMB_VFS_SYMLINKAT(conn,
    3783             :                         &target_fname,
    3784             :                         parent_fname->fsp,
    3785             :                         base_name);
    3786         128 :         if (ret != 0) {
    3787           8 :                 TALLOC_FREE(parent_fname);
    3788           8 :                 return map_nt_error_from_unix(errno);
    3789             :         }
    3790             : 
    3791         120 :         TALLOC_FREE(parent_fname);
    3792         120 :         return NT_STATUS_OK;
    3793             : }
    3794             : 
    3795             : /****************************************************************************
    3796             :  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
    3797             : ****************************************************************************/
    3798             : 
    3799          16 : static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
    3800             :                                         struct smb_request *req,
    3801             :                                         const char *pdata, int total_data,
    3802             :                                         struct smb_filename *smb_fname_new)
    3803             : {
    3804          16 :         char *oldname = NULL;
    3805          16 :         struct files_struct *src_dirfsp = NULL;
    3806          16 :         struct smb_filename *smb_fname_old = NULL;
    3807          16 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    3808          16 :         NTTIME old_twrp = 0;
    3809          16 :         TALLOC_CTX *ctx = talloc_tos();
    3810          16 :         NTSTATUS status = NT_STATUS_OK;
    3811             : 
    3812          16 :         if (!CAN_WRITE(conn)) {
    3813           0 :                 return NT_STATUS_DOS(ERRSRV, ERRaccess);
    3814             :         }
    3815             : 
    3816             :         /* Set a hard link. */
    3817          16 :         if (total_data == 0) {
    3818           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3819             :         }
    3820             : 
    3821          16 :         if (req->posix_pathnames) {
    3822          16 :                 srvstr_get_path_posix(ctx,
    3823             :                         pdata,
    3824          16 :                         req->flags2,
    3825             :                         &oldname,
    3826             :                         pdata,
    3827             :                         total_data,
    3828             :                         STR_TERMINATE,
    3829             :                         &status);
    3830             :         } else {
    3831           0 :                 srvstr_get_path(ctx,
    3832             :                         pdata,
    3833           0 :                         req->flags2,
    3834             :                         &oldname,
    3835             :                         pdata,
    3836             :                         total_data,
    3837             :                         STR_TERMINATE,
    3838             :                         &status);
    3839             :         }
    3840          16 :         if (!NT_STATUS_IS_OK(status)) {
    3841           0 :                 return status;
    3842             :         }
    3843             : 
    3844          16 :         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
    3845             :                 smb_fname_str_dbg(smb_fname_new), oldname));
    3846             : 
    3847          16 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    3848           0 :                 extract_snapshot_token(oldname, &old_twrp);
    3849             :         }
    3850          16 :         status = smb1_strip_dfs_path(ctx, &ucf_flags, &oldname);
    3851          16 :         if (!NT_STATUS_IS_OK(status)) {
    3852           0 :                 return status;
    3853             :         }
    3854          16 :         status = filename_convert_dirfsp(ctx,
    3855             :                                          conn,
    3856             :                                          oldname,
    3857             :                                          ucf_flags,
    3858             :                                          old_twrp,
    3859             :                                          &src_dirfsp,
    3860             :                                          &smb_fname_old);
    3861          16 :         if (!NT_STATUS_IS_OK(status)) {
    3862           0 :                 return status;
    3863             :         }
    3864             : 
    3865          16 :         return hardlink_internals(ctx,
    3866             :                                   conn,
    3867             :                                   req,
    3868             :                                   false,
    3869             :                                   smb_fname_old,
    3870             :                                   smb_fname_new);
    3871             : }
    3872             : 
    3873             : /****************************************************************************
    3874             :  Allow a UNIX info mknod.
    3875             : ****************************************************************************/
    3876             : 
    3877           2 : static NTSTATUS smb_unix_mknod(connection_struct *conn,
    3878             :                                const char *pdata,
    3879             :                                int total_data,
    3880             :                                struct files_struct *dirfsp,
    3881             :                                const struct smb_filename *smb_fname)
    3882             : {
    3883           2 :         uint32_t file_type = IVAL(pdata,56);
    3884             : #if defined(HAVE_MAKEDEV)
    3885           2 :         uint32_t dev_major = IVAL(pdata,60);
    3886           2 :         uint32_t dev_minor = IVAL(pdata,68);
    3887             : #endif
    3888           2 :         SMB_DEV_T dev = (SMB_DEV_T)0;
    3889           2 :         uint32_t raw_unixmode = IVAL(pdata,84);
    3890           0 :         NTSTATUS status;
    3891           0 :         mode_t unixmode;
    3892           0 :         int ret;
    3893           2 :         struct smb_filename *parent_fname = NULL;
    3894           2 :         struct smb_filename *atname = NULL;
    3895             : 
    3896           2 :         if (total_data < 100) {
    3897           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3898             :         }
    3899             : 
    3900           2 :         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
    3901             :                                       PERM_NEW_FILE, &unixmode);
    3902           2 :         if (!NT_STATUS_IS_OK(status)) {
    3903           0 :                 return status;
    3904             :         }
    3905             : 
    3906             : #if defined(HAVE_MAKEDEV)
    3907           2 :         dev = makedev(dev_major, dev_minor);
    3908             : #endif
    3909             : 
    3910           2 :         switch (file_type) {
    3911             :                 /* We can't create other objects here. */
    3912           0 :                 case UNIX_TYPE_FILE:
    3913             :                 case UNIX_TYPE_DIR:
    3914             :                 case UNIX_TYPE_SYMLINK:
    3915           0 :                         return NT_STATUS_ACCESS_DENIED;
    3916             : #if defined(S_IFIFO)
    3917           1 :                 case UNIX_TYPE_FIFO:
    3918           1 :                         unixmode |= S_IFIFO;
    3919           1 :                         break;
    3920             : #endif
    3921             : #if defined(S_IFSOCK)
    3922           1 :                 case UNIX_TYPE_SOCKET:
    3923           1 :                         unixmode |= S_IFSOCK;
    3924           1 :                         break;
    3925             : #endif
    3926             : #if defined(S_IFCHR)
    3927           0 :                 case UNIX_TYPE_CHARDEV:
    3928             :                         /* This is only allowed for root. */
    3929           0 :                         if (get_current_uid(conn) != sec_initial_uid()) {
    3930           0 :                                 return NT_STATUS_ACCESS_DENIED;
    3931             :                         }
    3932           0 :                         unixmode |= S_IFCHR;
    3933           0 :                         break;
    3934             : #endif
    3935             : #if defined(S_IFBLK)
    3936           0 :                 case UNIX_TYPE_BLKDEV:
    3937           0 :                         if (get_current_uid(conn) != sec_initial_uid()) {
    3938           0 :                                 return NT_STATUS_ACCESS_DENIED;
    3939             :                         }
    3940           0 :                         unixmode |= S_IFBLK;
    3941           0 :                         break;
    3942             : #endif
    3943           0 :                 default:
    3944           0 :                         return NT_STATUS_INVALID_PARAMETER;
    3945             :         }
    3946             : 
    3947           2 :         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
    3948             :                   "%.0f mode 0%o for file %s\n", (double)dev,
    3949             :                   (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
    3950             : 
    3951           2 :         status = SMB_VFS_PARENT_PATHNAME(dirfsp->conn,
    3952             :                                          talloc_tos(),
    3953             :                                          smb_fname,
    3954             :                                          &parent_fname,
    3955             :                                          &atname);
    3956           2 :         if (!NT_STATUS_IS_OK(status)) {
    3957           0 :                 return status;
    3958             :         }
    3959             : 
    3960             :         /* Ok - do the mknod. */
    3961           2 :         ret = SMB_VFS_MKNODAT(conn,
    3962             :                               dirfsp,
    3963             :                               atname,
    3964             :                               unixmode,
    3965             :                               dev);
    3966             : 
    3967           2 :         if (ret != 0) {
    3968           0 :                 TALLOC_FREE(parent_fname);
    3969           0 :                 return map_nt_error_from_unix(errno);
    3970             :         }
    3971             : 
    3972             :         /* If any of the other "set" calls fail we
    3973             :          * don't want to end up with a half-constructed mknod.
    3974             :          */
    3975             : 
    3976           2 :         if (lp_inherit_permissions(SNUM(conn))) {
    3977           0 :                 inherit_access_posix_acl(conn,
    3978             :                                          dirfsp,
    3979             :                                          smb_fname,
    3980             :                                          unixmode);
    3981             :         }
    3982           2 :         TALLOC_FREE(parent_fname);
    3983             : 
    3984           2 :         return NT_STATUS_OK;
    3985             : }
    3986             : 
    3987             : /****************************************************************************
    3988             :  Deal with SMB_SET_FILE_UNIX_BASIC.
    3989             : ****************************************************************************/
    3990             : 
    3991         172 : static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
    3992             :                                         struct smb_request *req,
    3993             :                                         const char *pdata,
    3994             :                                         int total_data,
    3995             :                                         struct files_struct *dirfsp,
    3996             :                                         files_struct *fsp,
    3997             :                                         struct smb_filename *smb_fname)
    3998             : {
    3999           0 :         struct smb_file_time ft;
    4000           0 :         uint32_t raw_unixmode;
    4001           0 :         mode_t unixmode;
    4002         172 :         off_t size = 0;
    4003         172 :         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
    4004         172 :         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
    4005         172 :         NTSTATUS status = NT_STATUS_OK;
    4006           0 :         enum perm_type ptype;
    4007         172 :         files_struct *all_fsps = NULL;
    4008         172 :         bool modify_mtime = true;
    4009           0 :         struct file_id id;
    4010           0 :         SMB_STRUCT_STAT sbuf;
    4011             : 
    4012         172 :         if (!CAN_WRITE(conn)) {
    4013           0 :                 return NT_STATUS_DOS(ERRSRV, ERRaccess);
    4014             :         }
    4015             : 
    4016         172 :         init_smb_file_time(&ft);
    4017             : 
    4018         172 :         if (total_data < 100) {
    4019           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4020             :         }
    4021             : 
    4022         172 :         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
    4023          16 :            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
    4024          16 :                 size=IVAL(pdata,0); /* first 8 Bytes are size */
    4025          16 :                 size |= (((off_t)IVAL(pdata,4)) << 32);
    4026             :         }
    4027             : 
    4028         172 :         ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
    4029         172 :         ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
    4030         172 :         set_owner = (uid_t)IVAL(pdata,40);
    4031         172 :         set_grp = (gid_t)IVAL(pdata,48);
    4032         172 :         raw_unixmode = IVAL(pdata,84);
    4033             : 
    4034         172 :         if (VALID_STAT(smb_fname->st)) {
    4035         170 :                 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
    4036           4 :                         ptype = PERM_EXISTING_DIR;
    4037             :                 } else {
    4038         166 :                         ptype = PERM_EXISTING_FILE;
    4039             :                 }
    4040             :         } else {
    4041           2 :                 ptype = PERM_NEW_FILE;
    4042             :         }
    4043             : 
    4044         172 :         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
    4045             :                                       ptype, &unixmode);
    4046         172 :         if (!NT_STATUS_IS_OK(status)) {
    4047           0 :                 return status;
    4048             :         }
    4049             : 
    4050         172 :         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
    4051             :                   "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
    4052             :                   smb_fname_str_dbg(smb_fname), (double)size,
    4053             :                   (unsigned int)set_owner, (unsigned int)set_grp,
    4054             :                   (int)raw_unixmode));
    4055             : 
    4056         172 :         sbuf = smb_fname->st;
    4057             : 
    4058         172 :         if (!VALID_STAT(sbuf)) {
    4059             :                 /*
    4060             :                  * The only valid use of this is to create character and block
    4061             :                  * devices, and named pipes. This is deprecated (IMHO) and
    4062             :                  * a new info level should be used for mknod. JRA.
    4063             :                  */
    4064             : 
    4065           2 :                 if (dirfsp == NULL) {
    4066           0 :                         return NT_STATUS_INVALID_PARAMETER;
    4067             :                 }
    4068             : 
    4069           2 :                 return smb_unix_mknod(conn,
    4070             :                                       pdata,
    4071             :                                       total_data,
    4072             :                                       dirfsp,
    4073             :                                       smb_fname);
    4074             :         }
    4075             : 
    4076             : #if 1
    4077             :         /* Horrible backwards compatibility hack as an old server bug
    4078             :          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
    4079             :          * */
    4080             : 
    4081         170 :         if (!size) {
    4082         170 :                 size = get_file_size_stat(&sbuf);
    4083             :         }
    4084             : #endif
    4085             : 
    4086             :         /*
    4087             :          * Deal with the UNIX specific mode set.
    4088             :          */
    4089             : 
    4090         170 :         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
    4091           0 :                 int ret;
    4092             : 
    4093          38 :                 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
    4094          24 :                         DBG_WARNING("Can't set mode on symlink %s\n",
    4095             :                                 smb_fname_str_dbg(smb_fname));
    4096          24 :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    4097             :                 }
    4098             : 
    4099          14 :                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
    4100             :                           "setting mode 0%o for file %s\n",
    4101             :                           (unsigned int)unixmode,
    4102             :                           smb_fname_str_dbg(smb_fname)));
    4103          14 :                 ret = SMB_VFS_FCHMOD(fsp, unixmode);
    4104          14 :                 if (ret != 0) {
    4105           2 :                         return map_nt_error_from_unix(errno);
    4106             :                 }
    4107             :         }
    4108             : 
    4109             :         /*
    4110             :          * Deal with the UNIX specific uid set.
    4111             :          */
    4112             : 
    4113         144 :         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
    4114           0 :             (sbuf.st_ex_uid != set_owner)) {
    4115           0 :                 int ret;
    4116             : 
    4117           0 :                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
    4118             :                           "changing owner %u for path %s\n",
    4119             :                           (unsigned int)set_owner,
    4120             :                           smb_fname_str_dbg(smb_fname)));
    4121             : 
    4122           0 :                 if (fsp &&
    4123           0 :                     !fsp->fsp_flags.is_pathref &&
    4124           0 :                     fsp_get_io_fd(fsp) != -1)
    4125             :                 {
    4126           0 :                         ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
    4127             :                 } else {
    4128             :                         /*
    4129             :                          * UNIX extensions calls must always operate
    4130             :                          * on symlinks.
    4131             :                          */
    4132           0 :                         ret = SMB_VFS_LCHOWN(conn, smb_fname,
    4133             :                                              set_owner, (gid_t)-1);
    4134             :                 }
    4135             : 
    4136           0 :                 if (ret != 0) {
    4137           0 :                         status = map_nt_error_from_unix(errno);
    4138           0 :                         return status;
    4139             :                 }
    4140             :         }
    4141             : 
    4142             :         /*
    4143             :          * Deal with the UNIX specific gid set.
    4144             :          */
    4145             : 
    4146         144 :         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
    4147           0 :             (sbuf.st_ex_gid != set_grp)) {
    4148           0 :                 int ret;
    4149             : 
    4150           0 :                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
    4151             :                           "changing group %u for file %s\n",
    4152             :                           (unsigned int)set_grp,
    4153             :                           smb_fname_str_dbg(smb_fname)));
    4154           0 :                 if (fsp &&
    4155           0 :                     !fsp->fsp_flags.is_pathref &&
    4156           0 :                     fsp_get_io_fd(fsp) != -1)
    4157             :                 {
    4158           0 :                         ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
    4159             :                 } else {
    4160             :                         /*
    4161             :                          * UNIX extensions calls must always operate
    4162             :                          * on symlinks.
    4163             :                          */
    4164           0 :                         ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
    4165             :                                   set_grp);
    4166             :                 }
    4167           0 :                 if (ret != 0) {
    4168           0 :                         status = map_nt_error_from_unix(errno);
    4169           0 :                         return status;
    4170             :                 }
    4171             :         }
    4172             : 
    4173             :         /* Deal with any size changes. */
    4174             : 
    4175         144 :         if (S_ISREG(sbuf.st_ex_mode)) {
    4176         140 :                 status = smb_set_file_size(conn, req,
    4177             :                                            fsp,
    4178             :                                            smb_fname,
    4179             :                                            &sbuf,
    4180             :                                            size,
    4181             :                                            false);
    4182         140 :                 if (!NT_STATUS_IS_OK(status)) {
    4183           0 :                         return status;
    4184             :                 }
    4185             :         }
    4186             : 
    4187             :         /* Deal with any time changes. */
    4188         144 :         if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
    4189             :                 /* No change, don't cancel anything. */
    4190         144 :                 return status;
    4191             :         }
    4192             : 
    4193           0 :         id = vfs_file_id_from_sbuf(conn, &sbuf);
    4194           0 :         for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
    4195           0 :                         all_fsps = file_find_di_next(all_fsps, true)) {
    4196             :                 /*
    4197             :                  * We're setting the time explicitly for UNIX.
    4198             :                  * Cancel any pending changes over all handles.
    4199             :                  */
    4200           0 :                 all_fsps->fsp_flags.update_write_time_on_close = false;
    4201           0 :                 TALLOC_FREE(all_fsps->update_write_time_event);
    4202             :         }
    4203             : 
    4204             :         /*
    4205             :          * Override the "setting_write_time"
    4206             :          * parameter here as it almost does what
    4207             :          * we need. Just remember if we modified
    4208             :          * mtime and send the notify ourselves.
    4209             :          */
    4210           0 :         if (is_omit_timespec(&ft.mtime)) {
    4211           0 :                 modify_mtime = false;
    4212             :         }
    4213             : 
    4214           0 :         status = smb_set_file_time(conn,
    4215             :                                 fsp,
    4216             :                                 smb_fname,
    4217             :                                 &ft,
    4218             :                                 false);
    4219           0 :         if (modify_mtime) {
    4220           0 :                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
    4221           0 :                         FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
    4222             :         }
    4223           0 :         return status;
    4224             : }
    4225             : 
    4226             : /****************************************************************************
    4227             :  Deal with SMB_SET_FILE_UNIX_INFO2.
    4228             : ****************************************************************************/
    4229             : 
    4230         140 : static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
    4231             :                                         struct smb_request *req,
    4232             :                                         const char *pdata,
    4233             :                                         int total_data,
    4234             :                                         struct files_struct *dirfsp,
    4235             :                                         files_struct *fsp,
    4236             :                                         struct smb_filename *smb_fname)
    4237             : {
    4238           0 :         NTSTATUS status;
    4239           0 :         uint32_t smb_fflags;
    4240           0 :         uint32_t smb_fmask;
    4241             : 
    4242         140 :         if (!CAN_WRITE(conn)) {
    4243           0 :                 return NT_STATUS_DOS(ERRSRV, ERRaccess);
    4244             :         }
    4245             : 
    4246         140 :         if (total_data < 116) {
    4247           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4248             :         }
    4249             : 
    4250             :         /* Start by setting all the fields that are common between UNIX_BASIC
    4251             :          * and UNIX_INFO2.
    4252             :          */
    4253         140 :         status = smb_set_file_unix_basic(conn,
    4254             :                                          req,
    4255             :                                          pdata,
    4256             :                                          total_data,
    4257             :                                          dirfsp,
    4258             :                                          fsp,
    4259             :                                          smb_fname);
    4260         140 :         if (!NT_STATUS_IS_OK(status)) {
    4261           8 :                 return status;
    4262             :         }
    4263             : 
    4264         132 :         smb_fflags = IVAL(pdata, 108);
    4265         132 :         smb_fmask = IVAL(pdata, 112);
    4266             : 
    4267             :         /* NB: We should only attempt to alter the file flags if the client
    4268             :          * sends a non-zero mask.
    4269             :          */
    4270         132 :         if (smb_fmask != 0) {
    4271         128 :                 int stat_fflags = 0;
    4272             : 
    4273         128 :                 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
    4274             :                                              smb_fmask, &stat_fflags)) {
    4275             :                         /* Client asked to alter a flag we don't understand. */
    4276         128 :                         return NT_STATUS_INVALID_PARAMETER;
    4277             :                 }
    4278             : 
    4279           0 :                 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
    4280           0 :                         DBG_WARNING("Can't change flags on symlink %s\n",
    4281             :                                 smb_fname_str_dbg(smb_fname));
    4282           0 :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    4283             :                 }
    4284           0 :                 if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) {
    4285           0 :                         return map_nt_error_from_unix(errno);
    4286             :                 }
    4287             :         }
    4288             : 
    4289             :         /* XXX: need to add support for changing the create_time here. You
    4290             :          * can do this for paths on Darwin with setattrlist(2). The right way
    4291             :          * to hook this up is probably by extending the VFS utimes interface.
    4292             :          */
    4293             : 
    4294           4 :         return NT_STATUS_OK;
    4295             : }
    4296             : 
    4297             : /****************************************************************************
    4298             :  Deal with SMB_SET_POSIX_ACL.
    4299             : ****************************************************************************/
    4300             : 
    4301          16 : static NTSTATUS smb_set_posix_acl(connection_struct *conn,
    4302             :                                 struct smb_request *req,
    4303             :                                 const char *pdata,
    4304             :                                 int total_data_in,
    4305             :                                 files_struct *fsp,
    4306             :                                 struct smb_filename *smb_fname)
    4307             : {
    4308             : #if !defined(HAVE_POSIX_ACLS)
    4309             :         return NT_STATUS_INVALID_LEVEL;
    4310             : #else
    4311           0 :         uint16_t posix_acl_version;
    4312           0 :         uint16_t num_file_acls;
    4313           0 :         uint16_t num_def_acls;
    4314          16 :         bool valid_file_acls = true;
    4315          16 :         bool valid_def_acls = true;
    4316           0 :         NTSTATUS status;
    4317           0 :         unsigned int size_needed;
    4318           0 :         unsigned int total_data;
    4319          16 :         bool close_fsp = false;
    4320             : 
    4321          16 :         if (total_data_in < 0) {
    4322           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4323           0 :                 goto out;
    4324             :         }
    4325             : 
    4326          16 :         total_data = total_data_in;
    4327             : 
    4328          16 :         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
    4329           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4330           0 :                 goto out;
    4331             :         }
    4332          16 :         posix_acl_version = SVAL(pdata,0);
    4333          16 :         num_file_acls = SVAL(pdata,2);
    4334          16 :         num_def_acls = SVAL(pdata,4);
    4335             : 
    4336          16 :         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
    4337           4 :                 valid_file_acls = false;
    4338           4 :                 num_file_acls = 0;
    4339             :         }
    4340             : 
    4341          16 :         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
    4342           0 :                 valid_def_acls = false;
    4343           0 :                 num_def_acls = 0;
    4344             :         }
    4345             : 
    4346          16 :         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
    4347           8 :                 status = NT_STATUS_INVALID_PARAMETER;
    4348           8 :                 goto out;
    4349             :         }
    4350             : 
    4351             :         /* Wrap checks. */
    4352           0 :         if (num_file_acls + num_def_acls < num_file_acls) {
    4353             :                 status = NT_STATUS_INVALID_PARAMETER;
    4354             :                 goto out;
    4355             :         }
    4356             : 
    4357           8 :         size_needed = num_file_acls + num_def_acls;
    4358             : 
    4359             :         /*
    4360             :          * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
    4361             :          * than UINT_MAX, so check by division.
    4362             :          */
    4363           8 :         if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
    4364           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4365           0 :                 goto out;
    4366             :         }
    4367             : 
    4368           8 :         size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
    4369           8 :         if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
    4370           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4371           0 :                 goto out;
    4372             :         }
    4373           8 :         size_needed += SMB_POSIX_ACL_HEADER_SIZE;
    4374             : 
    4375           8 :         if (total_data < size_needed) {
    4376           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4377           0 :                 goto out;
    4378             :         }
    4379             : 
    4380             :         /*
    4381             :          * Ensure we always operate on a file descriptor, not just
    4382             :          * the filename.
    4383             :          */
    4384           8 :         if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
    4385           8 :                 uint32_t access_mask = SEC_STD_WRITE_OWNER|
    4386             :                                         SEC_STD_WRITE_DAC|
    4387             :                                         SEC_STD_READ_CONTROL|
    4388             :                                         FILE_READ_ATTRIBUTES|
    4389             :                                         FILE_WRITE_ATTRIBUTES;
    4390             : 
    4391           8 :                 status = get_posix_fsp(conn,
    4392             :                                         req,
    4393             :                                         smb_fname,
    4394             :                                         access_mask,
    4395             :                                         &fsp);
    4396             : 
    4397           8 :                 if (!NT_STATUS_IS_OK(status)) {
    4398           4 :                         goto out;
    4399             :                 }
    4400           4 :                 close_fsp = true;
    4401             :         }
    4402             : 
    4403             :         /* Here we know fsp != NULL */
    4404           4 :         SMB_ASSERT(fsp != NULL);
    4405             : 
    4406           4 :         status = refuse_symlink_fsp(fsp);
    4407           4 :         if (!NT_STATUS_IS_OK(status)) {
    4408           0 :                 goto out;
    4409             :         }
    4410             : 
    4411             :         /* If we have a default acl, this *must* be a directory. */
    4412           4 :         if (valid_def_acls && !fsp->fsp_flags.is_directory) {
    4413           0 :                 DBG_INFO("Can't set default acls on "
    4414             :                          "non-directory %s\n",
    4415             :                          fsp_str_dbg(fsp));
    4416           0 :                 return NT_STATUS_INVALID_HANDLE;
    4417             :         }
    4418             : 
    4419           4 :         DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
    4420             :                   "num_def_acls = %"PRIu16"\n",
    4421             :                   fsp_str_dbg(fsp),
    4422             :                   num_file_acls,
    4423             :                   num_def_acls);
    4424             : 
    4425             :         /* Move pdata to the start of the file ACL entries. */
    4426           4 :         pdata += SMB_POSIX_ACL_HEADER_SIZE;
    4427             : 
    4428           4 :         if (valid_file_acls) {
    4429           0 :                 status = set_unix_posix_acl(conn,
    4430             :                                         fsp,
    4431             :                                         num_file_acls,
    4432             :                                         pdata);
    4433           0 :                 if (!NT_STATUS_IS_OK(status)) {
    4434           0 :                         goto out;
    4435             :                 }
    4436             :         }
    4437             : 
    4438             :         /* Move pdata to the start of the default ACL entries. */
    4439           4 :         pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
    4440             : 
    4441           4 :         if (valid_def_acls) {
    4442           4 :                 status = set_unix_posix_default_acl(conn,
    4443             :                                         fsp,
    4444             :                                         num_def_acls,
    4445             :                                         pdata);
    4446           4 :                 if (!NT_STATUS_IS_OK(status)) {
    4447           0 :                         goto out;
    4448             :                 }
    4449             :         }
    4450             : 
    4451           4 :         status = NT_STATUS_OK;
    4452             : 
    4453          16 :   out:
    4454             : 
    4455          16 :         if (close_fsp) {
    4456           4 :                 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
    4457             :         }
    4458          16 :         return status;
    4459             : #endif
    4460             : }
    4461             : 
    4462        1410 : static void call_trans2setpathinfo(
    4463             :         connection_struct *conn,
    4464             :         struct smb_request *req,
    4465             :         char **pparams,
    4466             :         int total_params,
    4467             :         char **ppdata,
    4468             :         int total_data,
    4469             :         unsigned int max_data_bytes)
    4470             : {
    4471          12 :         uint16_t info_level;
    4472        1410 :         struct smb_filename *smb_fname = NULL;
    4473        1410 :         struct files_struct *dirfsp = NULL;
    4474        1410 :         struct files_struct *fsp = NULL;
    4475        1410 :         char *params = *pparams;
    4476        1410 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    4477        1410 :         NTTIME twrp = 0;
    4478        1410 :         char *fname = NULL;
    4479          12 :         bool info_level_handled;
    4480        1410 :         int data_return_size = 0;
    4481          12 :         NTSTATUS status;
    4482             : 
    4483        1410 :         if (params == NULL) {
    4484           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4485           0 :                 return;
    4486             :         }
    4487             : 
    4488             :         /* set path info */
    4489        1410 :         if (total_params < 7) {
    4490           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4491           0 :                 return;
    4492             :         }
    4493             : 
    4494        1410 :         info_level = SVAL(params,0);
    4495             : 
    4496        1410 :         if (INFO_LEVEL_IS_UNIX(info_level)) {
    4497        1112 :                 if (!lp_smb1_unix_extensions()) {
    4498           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    4499           0 :                         return;
    4500             :                 }
    4501        1112 :                 if (!req->posix_pathnames) {
    4502           6 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    4503           6 :                         return;
    4504             :                 }
    4505             :         }
    4506             : 
    4507        1404 :         if (req->posix_pathnames) {
    4508        1210 :                 srvstr_get_path_posix(req,
    4509             :                                       params,
    4510        1210 :                                       req->flags2,
    4511             :                                       &fname,
    4512        1210 :                                       &params[6],
    4513        1210 :                                       total_params - 6,
    4514             :                                       STR_TERMINATE,
    4515             :                                       &status);
    4516             :         } else {
    4517         194 :                 srvstr_get_path(req,
    4518             :                                 params,
    4519         194 :                                 req->flags2,
    4520             :                                 &fname,
    4521         194 :                                 &params[6],
    4522         194 :                                 total_params - 6,
    4523             :                                 STR_TERMINATE,
    4524             :                                 &status);
    4525             :         }
    4526        1404 :         if (!NT_STATUS_IS_OK(status)) {
    4527           0 :                 reply_nterror(req, status);
    4528           0 :                 return;
    4529             :         }
    4530             : 
    4531        1404 :         DBG_NOTICE("fname=%s info_level=%d totdata=%d\n",
    4532             :                    fname,
    4533             :                    info_level,
    4534             :                    total_data);
    4535             : 
    4536        1404 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    4537           0 :                 extract_snapshot_token(fname, &twrp);
    4538             :         }
    4539        1404 :         status = smb1_strip_dfs_path(req, &ucf_flags, &fname);
    4540        1404 :         if (!NT_STATUS_IS_OK(status)) {
    4541           0 :                 reply_nterror(req, status);
    4542           0 :                 return;
    4543             :         }
    4544        1404 :         status = filename_convert_dirfsp(req,
    4545             :                                          conn,
    4546             :                                          fname,
    4547             :                                          ucf_flags,
    4548             :                                          twrp,
    4549             :                                          &dirfsp,
    4550             :                                          &smb_fname);
    4551        1404 :         if (!NT_STATUS_IS_OK(status)) {
    4552          60 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    4553           0 :                         reply_botherror(req,
    4554             :                                         NT_STATUS_PATH_NOT_COVERED,
    4555             :                                         ERRSRV, ERRbadpath);
    4556           0 :                         return;
    4557             :                 }
    4558          60 :                 reply_nterror(req, status);
    4559          60 :                 return;
    4560             :         }
    4561             : 
    4562        1344 :         info_level_handled = true; /* Untouched in switch cases below */
    4563             : 
    4564        1344 :         switch (info_level) {
    4565             : 
    4566         294 :         default:
    4567         294 :                 info_level_handled = false;
    4568         294 :                 break;
    4569             : 
    4570         174 :         case SMB_POSIX_PATH_OPEN:
    4571         174 :                 status = smb_posix_open(conn,
    4572             :                                         req,
    4573             :                                         ppdata,
    4574             :                                         total_data,
    4575             :                                         dirfsp,
    4576             :                                         smb_fname,
    4577             :                                         &data_return_size);
    4578         174 :                 break;
    4579             : 
    4580         532 :         case SMB_POSIX_PATH_UNLINK:
    4581         532 :                 status = smb_posix_unlink(conn,
    4582             :                                           req,
    4583             :                                           *ppdata,
    4584             :                                           total_data,
    4585             :                                           dirfsp,
    4586             :                                           smb_fname);
    4587         532 :                 break;
    4588             : 
    4589         128 :         case SMB_SET_FILE_UNIX_LINK:
    4590         128 :                 status = smb_set_file_unix_link(
    4591             :                         conn, req, *ppdata, total_data, smb_fname);
    4592         128 :                 break;
    4593             : 
    4594          16 :         case SMB_SET_FILE_UNIX_HLINK:
    4595          16 :                 status = smb_set_file_unix_hlink(
    4596             :                         conn, req, *ppdata, total_data, smb_fname);
    4597          16 :                 break;
    4598             : 
    4599          32 :         case SMB_SET_FILE_UNIX_BASIC:
    4600          32 :                 status = smb_set_file_unix_basic(conn,
    4601             :                                                  req,
    4602             :                                                  *ppdata,
    4603             :                                                  total_data,
    4604             :                                                  dirfsp,
    4605          32 :                                                  smb_fname->fsp,
    4606             :                                                  smb_fname);
    4607          32 :                 break;
    4608             : 
    4609         140 :         case SMB_SET_FILE_UNIX_INFO2:
    4610         140 :                 status = smb_set_file_unix_info2(conn,
    4611             :                                                  req,
    4612             :                                                  *ppdata,
    4613             :                                                  total_data,
    4614             :                                                  dirfsp,
    4615         140 :                                                  smb_fname->fsp,
    4616             :                                                  smb_fname);
    4617         140 :                 break;
    4618          16 :         case SMB_SET_POSIX_ACL:
    4619          16 :                 status = smb_set_posix_acl(
    4620             :                         conn, req, *ppdata, total_data, NULL, smb_fname);
    4621          16 :                 break;
    4622             :         }
    4623             : 
    4624        1332 :         if (info_level_handled) {
    4625        1038 :                 handle_trans2setfilepathinfo_result(
    4626             :                         conn,
    4627             :                         req,
    4628             :                         info_level,
    4629             :                         status,
    4630             :                         *ppdata,
    4631             :                         data_return_size,
    4632             :                         max_data_bytes);
    4633        1038 :                 return;
    4634             :         }
    4635             : 
    4636             :         /*
    4637             :          * smb_fname->fsp may be NULL if smb_fname points at a symlink
    4638             :          * and we're in POSIX context, so be careful when using fsp
    4639             :          * below, it can still be NULL.
    4640             :          */
    4641         306 :         fsp = smb_fname->fsp;
    4642             : 
    4643         306 :         status = smbd_do_setfilepathinfo(
    4644             :                 conn,
    4645             :                 req,
    4646             :                 req,
    4647             :                 info_level,
    4648             :                 fsp,
    4649             :                 smb_fname,
    4650             :                 ppdata,
    4651             :                 total_data,
    4652             :                 &data_return_size);
    4653             : 
    4654         306 :         handle_trans2setfilepathinfo_result(
    4655             :                 conn,
    4656             :                 req,
    4657             :                 info_level,
    4658             :                 status,
    4659             :                 *ppdata,
    4660             :                 data_return_size,
    4661             :                 max_data_bytes);
    4662             : }
    4663             : 
    4664        4265 : static void call_trans2setfileinfo(
    4665             :         connection_struct *conn,
    4666             :         struct smb_request *req,
    4667             :         char **pparams,
    4668             :         int total_params,
    4669             :         char **ppdata,
    4670             :         int total_data,
    4671             :         unsigned int max_data_bytes)
    4672             : {
    4673        4265 :         char *pdata = *ppdata;
    4674         537 :         uint16_t info_level;
    4675        4265 :         struct smb_filename *smb_fname = NULL;
    4676        4265 :         struct files_struct *fsp = NULL;
    4677        4265 :         char *params = *pparams;
    4678        4265 :         int data_return_size = 0;
    4679         537 :         bool info_level_handled;
    4680         537 :         NTSTATUS status;
    4681         537 :         int ret;
    4682             : 
    4683        4265 :         if (params == NULL) {
    4684           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4685           0 :                 return;
    4686             :         }
    4687        4265 :         if (total_params < 4) {
    4688           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4689           0 :                 return;
    4690             :         }
    4691             : 
    4692        4265 :         fsp = file_fsp(req, SVAL(params,0));
    4693             :         /* Basic check for non-null fsp. */
    4694        4265 :         if (!check_fsp_open(conn, req, fsp)) {
    4695           0 :                 return;
    4696             :         }
    4697        4265 :         info_level = SVAL(params,2);
    4698             : 
    4699        4265 :         if (INFO_LEVEL_IS_UNIX(info_level)) {
    4700          36 :                 if (!lp_smb1_unix_extensions()) {
    4701           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    4702           0 :                         return;
    4703             :                 }
    4704          36 :                 if (!req->posix_pathnames) {
    4705           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    4706           0 :                         return;
    4707             :                 }
    4708             :         }
    4709             : 
    4710        4265 :         smb_fname = fsp->fsp_name;
    4711             : 
    4712        4265 :         DBG_NOTICE("fnum=%s fname=%s info_level=%d totdata=%d\n",
    4713             :                    fsp_fnum_dbg(fsp),
    4714             :                    fsp_str_dbg(fsp),
    4715             :                    info_level,
    4716             :                    total_data);
    4717             : 
    4718        4265 :         if (fsp_get_pathref_fd(fsp) == -1) {
    4719             :                 /*
    4720             :                  * This is actually a SETFILEINFO on a directory
    4721             :                  * handle (returned from an NT SMB). NT5.0 seems
    4722             :                  * to do this call. JRA.
    4723             :                  */
    4724           0 :                 ret = vfs_stat(conn, smb_fname);
    4725           0 :                 if (ret != 0) {
    4726           0 :                         DBG_NOTICE("vfs_stat of %s failed (%s)\n",
    4727             :                                    smb_fname_str_dbg(smb_fname),
    4728             :                                    strerror(errno));
    4729           0 :                         reply_nterror(req, map_nt_error_from_unix(errno));
    4730           0 :                         return;
    4731             :                 }
    4732        4265 :         } else if (fsp->print_file) {
    4733             :                 /*
    4734             :                  * Doing a DELETE_ON_CLOSE should cancel a print job.
    4735             :                  */
    4736           2 :                 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) &&
    4737           2 :                     CVAL(pdata,0)) {
    4738             : 
    4739           2 :                         fsp->fsp_flags.delete_on_close = true;
    4740             : 
    4741           2 :                         DBG_NOTICE("Cancelling print job (%s)\n",
    4742             :                                    fsp_str_dbg(fsp));
    4743             : 
    4744           2 :                         SSVAL(params,0,0);
    4745           2 :                         send_trans2_replies(
    4746             :                                 conn,
    4747             :                                 req,
    4748           2 :                                 NT_STATUS_OK,
    4749             :                                 params,
    4750             :                                 2,
    4751             :                                 *ppdata, 0,
    4752             :                                 max_data_bytes);
    4753           2 :                         return;
    4754             :                 } else {
    4755           0 :                         reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
    4756           0 :                         return;
    4757             :                 }
    4758             :         } else {
    4759             :                 /*
    4760             :                  * Original code - this is an open file.
    4761             :                  */
    4762        4263 :                 status = vfs_stat_fsp(fsp);
    4763        4263 :                 if (!NT_STATUS_IS_OK(status)) {
    4764           0 :                         DBG_NOTICE("fstat of %s failed (%s)\n",
    4765             :                                    fsp_fnum_dbg(fsp),
    4766             :                                    nt_errstr(status));
    4767           0 :                         reply_nterror(req, status);
    4768           0 :                         return;
    4769             :                 }
    4770             :         }
    4771             : 
    4772        4263 :         info_level_handled = true; /* Untouched in switch cases below */
    4773             : 
    4774        4263 :         switch (info_level) {
    4775             : 
    4776        3690 :         default:
    4777        3690 :                 info_level_handled = false;
    4778        3690 :                 break;
    4779             : 
    4780           0 :         case SMB_SET_FILE_UNIX_BASIC:
    4781           0 :                 status = smb_set_file_unix_basic(conn,
    4782             :                                                  req,
    4783             :                                                  pdata,
    4784             :                                                  total_data,
    4785             :                                                  NULL,
    4786             :                                                  fsp,
    4787             :                                                  smb_fname);
    4788           0 :                 break;
    4789             : 
    4790           0 :         case SMB_SET_FILE_UNIX_INFO2:
    4791           0 :                 status = smb_set_file_unix_info2(conn,
    4792             :                                                  req,
    4793             :                                                  pdata,
    4794             :                                                  total_data,
    4795             :                                                  NULL,
    4796             :                                                  fsp,
    4797             :                                                  smb_fname);
    4798           0 :                 break;
    4799             : 
    4800          36 :         case SMB_SET_POSIX_LOCK:
    4801          36 :                 status = smb_set_posix_lock(
    4802             :                         conn, req, *ppdata, total_data, fsp);
    4803          36 :                 break;
    4804             :         }
    4805             : 
    4806        3726 :         if (info_level_handled) {
    4807          36 :                 handle_trans2setfilepathinfo_result(
    4808             :                         conn,
    4809             :                         req,
    4810             :                         info_level,
    4811             :                         status,
    4812             :                         *ppdata,
    4813             :                         data_return_size,
    4814             :                         max_data_bytes);
    4815          36 :                 return;
    4816             :         }
    4817             : 
    4818        4227 :         status = smbd_do_setfilepathinfo(
    4819             :                 conn,
    4820             :                 req,
    4821             :                 req,
    4822             :                 info_level,
    4823             :                 fsp,
    4824             :                 smb_fname,
    4825             :                 ppdata,
    4826             :                 total_data,
    4827             :                 &data_return_size);
    4828             : 
    4829        4227 :         handle_trans2setfilepathinfo_result(
    4830             :                 conn,
    4831             :                 req,
    4832             :                 info_level,
    4833             :                 status,
    4834             :                 *ppdata,
    4835             :                 data_return_size,
    4836             :                 max_data_bytes);
    4837             : }
    4838             : 
    4839             : /****************************************************************************
    4840             :  Reply to a TRANS2_MKDIR (make directory with extended attributes).
    4841             : ****************************************************************************/
    4842             : 
    4843          23 : static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
    4844             :                              char **pparams, int total_params,
    4845             :                              char **ppdata, int total_data,
    4846             :                              unsigned int max_data_bytes)
    4847             : {
    4848          23 :         struct files_struct *dirfsp = NULL;
    4849          23 :         struct files_struct *fsp = NULL;
    4850          23 :         struct smb_filename *smb_dname = NULL;
    4851          23 :         char *params = *pparams;
    4852          23 :         char *pdata = *ppdata;
    4853          23 :         char *directory = NULL;
    4854          23 :         NTSTATUS status = NT_STATUS_OK;
    4855          23 :         struct ea_list *ea_list = NULL;
    4856          23 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    4857          23 :         NTTIME twrp = 0;
    4858          23 :         TALLOC_CTX *ctx = talloc_tos();
    4859             : 
    4860          23 :         if (!CAN_WRITE(conn)) {
    4861           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    4862           0 :                 return;
    4863             :         }
    4864             : 
    4865          23 :         if (total_params < 5) {
    4866           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4867           0 :                 return;
    4868             :         }
    4869             : 
    4870          23 :         if (req->posix_pathnames) {
    4871           0 :                 srvstr_get_path_posix(ctx,
    4872             :                         params,
    4873           0 :                         req->flags2,
    4874             :                         &directory,
    4875           0 :                         &params[4],
    4876           0 :                         total_params - 4,
    4877             :                         STR_TERMINATE,
    4878             :                         &status);
    4879             :         } else {
    4880          23 :                 srvstr_get_path(ctx,
    4881             :                         params,
    4882          23 :                         req->flags2,
    4883             :                         &directory,
    4884          23 :                         &params[4],
    4885          23 :                         total_params - 4,
    4886             :                         STR_TERMINATE,
    4887             :                         &status);
    4888             :         }
    4889          23 :         if (!NT_STATUS_IS_OK(status)) {
    4890           0 :                 reply_nterror(req, status);
    4891           0 :                 return;
    4892             :         }
    4893             : 
    4894          23 :         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
    4895             : 
    4896          23 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    4897           0 :                 extract_snapshot_token(directory, &twrp);
    4898             :         }
    4899          23 :         status = smb1_strip_dfs_path(ctx, &ucf_flags, &directory);
    4900          23 :         if (!NT_STATUS_IS_OK(status)) {
    4901           0 :                 reply_nterror(req, status);
    4902           0 :                 goto out;
    4903             :         }
    4904          23 :         status = filename_convert_dirfsp(ctx,
    4905             :                                          conn,
    4906             :                                          directory,
    4907             :                                          ucf_flags,
    4908             :                                          twrp,
    4909             :                                          &dirfsp,
    4910             :                                          &smb_dname);
    4911          23 :         if (!NT_STATUS_IS_OK(status)) {
    4912           5 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    4913           0 :                         reply_botherror(req,
    4914             :                                 NT_STATUS_PATH_NOT_COVERED,
    4915             :                                 ERRSRV, ERRbadpath);
    4916           0 :                         return;
    4917             :                 }
    4918           5 :                 reply_nterror(req, status);
    4919           5 :                 return;
    4920             :         }
    4921             : 
    4922             :         /*
    4923             :          * OS/2 workplace shell seems to send SET_EA requests of "null"
    4924             :          * length (4 bytes containing IVAL 4).
    4925             :          * They seem to have no effect. Bug #3212. JRA.
    4926             :          */
    4927             : 
    4928          18 :         if (total_data && (total_data != 4)) {
    4929             :                 /* Any data in this call is an EA list. */
    4930           5 :                 if (total_data < 10) {
    4931           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4932           0 :                         goto out;
    4933             :                 }
    4934             : 
    4935           5 :                 if (IVAL(pdata,0) > total_data) {
    4936           0 :                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
    4937             :                                 IVAL(pdata,0), (unsigned int)total_data));
    4938           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4939           0 :                         goto out;
    4940             :                 }
    4941             : 
    4942           5 :                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
    4943           5 :                                        total_data - 4);
    4944           5 :                 if (!ea_list) {
    4945           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4946           0 :                         goto out;
    4947             :                 }
    4948             : 
    4949           5 :                 if (!lp_ea_support(SNUM(conn))) {
    4950           0 :                         reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
    4951           0 :                         goto out;
    4952             :                 }
    4953             :         }
    4954             :         /* If total_data == 4 Windows doesn't care what values
    4955             :          * are placed in that field, it just ignores them.
    4956             :          * The System i QNTC IBM SMB client puts bad values here,
    4957             :          * so ignore them. */
    4958             : 
    4959          18 :         status = SMB_VFS_CREATE_FILE(
    4960             :                 conn,                                   /* conn */
    4961             :                 req,                                    /* req */
    4962             :                 dirfsp,                                 /* dirfsp */
    4963             :                 smb_dname,                              /* fname */
    4964             :                 MAXIMUM_ALLOWED_ACCESS,                 /* access_mask */
    4965             :                 FILE_SHARE_NONE,                        /* share_access */
    4966             :                 FILE_CREATE,                            /* create_disposition*/
    4967             :                 FILE_DIRECTORY_FILE,                    /* create_options */
    4968             :                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
    4969             :                 0,                                      /* oplock_request */
    4970             :                 NULL,                                   /* lease */
    4971             :                 0,                                      /* allocation_size */
    4972             :                 0,                                      /* private_flags */
    4973             :                 NULL,                                   /* sd */
    4974             :                 NULL,                                   /* ea_list */
    4975             :                 &fsp,                                       /* result */
    4976             :                 NULL,                                   /* pinfo */
    4977             :                 NULL, NULL);                            /* create context */
    4978          18 :         if (!NT_STATUS_IS_OK(status)) {
    4979           8 :                 reply_nterror(req, status);
    4980           8 :                 goto out;
    4981             :         }
    4982             : 
    4983             :         /* Try and set any given EA. */
    4984          10 :         if (ea_list) {
    4985           5 :                 status = set_ea(conn, fsp, ea_list);
    4986           5 :                 if (!NT_STATUS_IS_OK(status)) {
    4987           0 :                         reply_nterror(req, status);
    4988           0 :                         goto out;
    4989             :                 }
    4990             :         }
    4991             : 
    4992             :         /* Realloc the parameter and data sizes */
    4993          10 :         *pparams = (char *)SMB_REALLOC(*pparams,2);
    4994          10 :         if(*pparams == NULL) {
    4995           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    4996           0 :                 goto out;
    4997             :         }
    4998          10 :         params = *pparams;
    4999             : 
    5000          10 :         SSVAL(params,0,0);
    5001             : 
    5002          10 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
    5003             : 
    5004          18 :  out:
    5005          18 :         if (fsp != NULL) {
    5006          10 :                 close_file_free(NULL, &fsp, NORMAL_CLOSE);
    5007             :         }
    5008          18 :         TALLOC_FREE(smb_dname);
    5009             : }
    5010             : 
    5011             : /****************************************************************************
    5012             :  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
    5013             :  We don't actually do this - we just send a null response.
    5014             : ****************************************************************************/
    5015             : 
    5016           0 : static void call_trans2findnotifyfirst(connection_struct *conn,
    5017             :                                        struct smb_request *req,
    5018             :                                        char **pparams, int total_params,
    5019             :                                        char **ppdata, int total_data,
    5020             :                                        unsigned int max_data_bytes)
    5021             : {
    5022           0 :         char *params = *pparams;
    5023           0 :         uint16_t info_level;
    5024             : 
    5025           0 :         if (total_params < 6) {
    5026           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5027           0 :                 return;
    5028             :         }
    5029             : 
    5030           0 :         info_level = SVAL(params,4);
    5031           0 :         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
    5032             : 
    5033           0 :         switch (info_level) {
    5034           0 :                 case 1:
    5035             :                 case 2:
    5036           0 :                         break;
    5037           0 :                 default:
    5038           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    5039           0 :                         return;
    5040             :         }
    5041             : 
    5042             :         /* Realloc the parameter and data sizes */
    5043           0 :         *pparams = (char *)SMB_REALLOC(*pparams,6);
    5044           0 :         if (*pparams == NULL) {
    5045           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    5046           0 :                 return;
    5047             :         }
    5048           0 :         params = *pparams;
    5049             : 
    5050           0 :         SSVAL(params,0,fnf_handle);
    5051           0 :         SSVAL(params,2,0); /* No changes */
    5052           0 :         SSVAL(params,4,0); /* No EA errors */
    5053             : 
    5054           0 :         fnf_handle++;
    5055             : 
    5056           0 :         if(fnf_handle == 0)
    5057           0 :                 fnf_handle = 257;
    5058             : 
    5059           0 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
    5060             : }
    5061             : 
    5062             : /****************************************************************************
    5063             :  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
    5064             :  changes). Currently this does nothing.
    5065             : ****************************************************************************/
    5066             : 
    5067           0 : static void call_trans2findnotifynext(connection_struct *conn,
    5068             :                                       struct smb_request *req,
    5069             :                                       char **pparams, int total_params,
    5070             :                                       char **ppdata, int total_data,
    5071             :                                       unsigned int max_data_bytes)
    5072             : {
    5073           0 :         char *params = *pparams;
    5074             : 
    5075           0 :         DEBUG(3,("call_trans2findnotifynext\n"));
    5076             : 
    5077             :         /* Realloc the parameter and data sizes */
    5078           0 :         *pparams = (char *)SMB_REALLOC(*pparams,4);
    5079           0 :         if (*pparams == NULL) {
    5080           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    5081           0 :                 return;
    5082             :         }
    5083           0 :         params = *pparams;
    5084             : 
    5085           0 :         SSVAL(params,0,0); /* No changes */
    5086           0 :         SSVAL(params,2,0); /* No EA errors */
    5087             : 
    5088           0 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
    5089             : }
    5090             : 
    5091             : /****************************************************************************
    5092             :  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
    5093             : ****************************************************************************/
    5094             : 
    5095        4372 : static void call_trans2getdfsreferral(connection_struct *conn,
    5096             :                                       struct smb_request *req,
    5097             :                                       char **pparams, int total_params,
    5098             :                                       char **ppdata, int total_data,
    5099             :                                       unsigned int max_data_bytes)
    5100             : {
    5101        4372 :         char *params = *pparams;
    5102        4372 :         char *pathname = NULL;
    5103        4372 :         int reply_size = 0;
    5104           0 :         int max_referral_level;
    5105        4372 :         NTSTATUS status = NT_STATUS_OK;
    5106        4372 :         TALLOC_CTX *ctx = talloc_tos();
    5107             : 
    5108        4372 :         DEBUG(10,("call_trans2getdfsreferral\n"));
    5109             : 
    5110        4372 :         if (!IS_IPC(conn)) {
    5111           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    5112           0 :                 return;
    5113             :         }
    5114             : 
    5115        4372 :         if (total_params < 3) {
    5116           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5117           0 :                 return;
    5118             :         }
    5119             : 
    5120        4372 :         max_referral_level = SVAL(params,0);
    5121             : 
    5122        4372 :         if(!lp_host_msdfs()) {
    5123           0 :                 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
    5124           0 :                 return;
    5125             :         }
    5126             : 
    5127        4372 :         srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
    5128             :                     total_params - 2, STR_TERMINATE);
    5129        4372 :         if (!pathname) {
    5130           0 :                 reply_nterror(req, NT_STATUS_NOT_FOUND);
    5131           0 :                 return;
    5132             :         }
    5133        4372 :         reply_size = setup_dfs_referral(
    5134             :                 conn, pathname, max_referral_level, ppdata, &status);
    5135        4372 :         if (reply_size < 0) {
    5136        3070 :                 reply_nterror(req, status);
    5137        3070 :                 return;
    5138             :         }
    5139             : 
    5140        1302 :         SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
    5141             :               SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
    5142        1302 :         send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
    5143             : }
    5144             : 
    5145             : #define LMCAT_SPL       0x53
    5146             : #define LMFUNC_GETJOBID 0x60
    5147             : 
    5148             : /****************************************************************************
    5149             :  Reply to a TRANS2_IOCTL - used for OS/2 printing.
    5150             : ****************************************************************************/
    5151             : 
    5152           0 : static void call_trans2ioctl(connection_struct *conn,
    5153             :                              struct smb_request *req,
    5154             :                              char **pparams, int total_params,
    5155             :                              char **ppdata, int total_data,
    5156             :                              unsigned int max_data_bytes)
    5157             : {
    5158           0 :         const struct loadparm_substitution *lp_sub =
    5159           0 :                 loadparm_s3_global_substitution();
    5160           0 :         char *pdata = *ppdata;
    5161           0 :         files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
    5162           0 :         NTSTATUS status;
    5163           0 :         size_t len = 0;
    5164             : 
    5165             :         /* check for an invalid fid before proceeding */
    5166             : 
    5167           0 :         if (!fsp) {
    5168           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
    5169           0 :                 return;
    5170             :         }
    5171             : 
    5172           0 :         if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
    5173           0 :             && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
    5174           0 :                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
    5175           0 :                 if (*ppdata == NULL) {
    5176           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    5177           0 :                         return;
    5178             :                 }
    5179           0 :                 pdata = *ppdata;
    5180             : 
    5181             :                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
    5182             :                         CAN ACCEPT THIS IN UNICODE. JRA. */
    5183             : 
    5184             :                 /* Job number */
    5185           0 :                 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
    5186             : 
    5187           0 :                 status = srvstr_push(pdata, req->flags2, pdata + 2,
    5188             :                             lp_netbios_name(), 15,
    5189             :                             STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
    5190           0 :                 if (!NT_STATUS_IS_OK(status)) {
    5191           0 :                         reply_nterror(req, status);
    5192           0 :                         return;
    5193             :                 }
    5194           0 :                 status = srvstr_push(pdata, req->flags2, pdata+18,
    5195             :                             lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
    5196             :                             STR_ASCII|STR_TERMINATE, &len); /* Service name */
    5197           0 :                 if (!NT_STATUS_IS_OK(status)) {
    5198           0 :                         reply_nterror(req, status);
    5199           0 :                         return;
    5200             :                 }
    5201           0 :                 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
    5202             :                                     max_data_bytes);
    5203           0 :                 return;
    5204             :         }
    5205             : 
    5206           0 :         DEBUG(2,("Unknown TRANS2_IOCTL\n"));
    5207           0 :         reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
    5208             : }
    5209             : 
    5210       37803 : static void handle_trans2(connection_struct *conn, struct smb_request *req,
    5211             :                           struct trans_state *state)
    5212             : {
    5213       37803 :         struct smbXsrv_connection *xconn = req->xconn;
    5214             : 
    5215       37803 :         if (xconn->protocol >= PROTOCOL_NT1) {
    5216       37801 :                 req->flags2 |= 0x40; /* IS_LONG_NAME */
    5217       37801 :                 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
    5218             :         }
    5219             : 
    5220       37803 :         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
    5221           0 :                 if (state->call != TRANSACT2_QFSINFO &&
    5222           0 :                     state->call != TRANSACT2_SETFSINFO) {
    5223           0 :                         DEBUG(0,("handle_trans2: encryption required "
    5224             :                                 "with call 0x%x\n",
    5225             :                                 (unsigned int)state->call));
    5226           0 :                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    5227           0 :                         return;
    5228             :                 }
    5229             :         }
    5230             : 
    5231             :         /* Now we must call the relevant TRANS2 function */
    5232       37803 :         switch(state->call)  {
    5233          98 :         case TRANSACT2_OPEN:
    5234             :         {
    5235          98 :                 START_PROFILE(Trans2_open);
    5236          98 :                 call_trans2open(conn, req,
    5237          98 :                                 &state->param, state->total_param,
    5238          98 :                                 &state->data, state->total_data,
    5239             :                                 state->max_data_return);
    5240          98 :                 END_PROFILE(Trans2_open);
    5241          80 :                 break;
    5242             :         }
    5243             : 
    5244        8736 :         case TRANSACT2_FINDFIRST:
    5245             :         {
    5246        8736 :                 START_PROFILE(Trans2_findfirst);
    5247        8736 :                 call_trans2findfirst(conn, req,
    5248        8736 :                                      &state->param, state->total_param,
    5249        8736 :                                      &state->data, state->total_data,
    5250             :                                      state->max_data_return);
    5251        8736 :                 END_PROFILE(Trans2_findfirst);
    5252        8561 :                 break;
    5253             :         }
    5254             : 
    5255        1724 :         case TRANSACT2_FINDNEXT:
    5256             :         {
    5257        1724 :                 START_PROFILE(Trans2_findnext);
    5258        1724 :                 call_trans2findnext(conn, req,
    5259        1724 :                                     &state->param, state->total_param,
    5260        1724 :                                     &state->data, state->total_data,
    5261             :                                     state->max_data_return);
    5262        1724 :                 END_PROFILE(Trans2_findnext);
    5263        1724 :                 break;
    5264             :         }
    5265             : 
    5266        1375 :         case TRANSACT2_QFSINFO:
    5267             :         {
    5268        1375 :                 START_PROFILE(Trans2_qfsinfo);
    5269        1375 :                 call_trans2qfsinfo(conn, req,
    5270        1375 :                                    &state->param, state->total_param,
    5271        1375 :                                    &state->data, state->total_data,
    5272             :                                    state->max_data_return);
    5273        1375 :                 END_PROFILE(Trans2_qfsinfo);
    5274        1375 :             break;
    5275             :         }
    5276             : 
    5277        1366 :         case TRANSACT2_SETFSINFO:
    5278             :         {
    5279        1366 :                 START_PROFILE(Trans2_setfsinfo);
    5280        1366 :                 call_trans2setfsinfo(conn, req,
    5281        1366 :                                      &state->param, state->total_param,
    5282        1366 :                                      &state->data, state->total_data,
    5283             :                                      state->max_data_return);
    5284        1366 :                 END_PROFILE(Trans2_setfsinfo);
    5285        1366 :                 break;
    5286             :         }
    5287             : 
    5288       10817 :         case TRANSACT2_QPATHINFO:
    5289             :         {
    5290       10817 :                 START_PROFILE(Trans2_qpathinfo);
    5291       10817 :                 call_trans2qpathinfo(
    5292             :                         conn,
    5293             :                         req,
    5294             :                         &state->param,
    5295       10817 :                         state->total_param,
    5296             :                         &state->data,
    5297       10817 :                         state->total_data,
    5298             :                         state->max_data_return);
    5299       10817 :                 END_PROFILE(Trans2_qpathinfo);
    5300       10528 :                 break;
    5301             :         }
    5302             : 
    5303        3617 :         case TRANSACT2_QFILEINFO:
    5304             :         {
    5305        3617 :                 START_PROFILE(Trans2_qfileinfo);
    5306        3617 :                 call_trans2qfileinfo(
    5307             :                         conn,
    5308             :                         req,
    5309             :                         &state->param,
    5310        3617 :                         state->total_param,
    5311             :                         &state->data,
    5312        3617 :                         state->total_data,
    5313             :                         state->max_data_return);
    5314        3617 :                 END_PROFILE(Trans2_qfileinfo);
    5315        3432 :                 break;
    5316             :         }
    5317             : 
    5318        1410 :         case TRANSACT2_SETPATHINFO:
    5319             :         {
    5320        1410 :                 START_PROFILE(Trans2_setpathinfo);
    5321        1410 :                 call_trans2setpathinfo(
    5322             :                         conn,
    5323             :                         req,
    5324             :                         &state->param,
    5325        1410 :                         state->total_param,
    5326             :                         &state->data,
    5327        1410 :                         state->total_data,
    5328             :                         state->max_data_return);
    5329        1410 :                 END_PROFILE(Trans2_setpathinfo);
    5330        1398 :                 break;
    5331             :         }
    5332             : 
    5333        4265 :         case TRANSACT2_SETFILEINFO:
    5334             :         {
    5335        4265 :                 START_PROFILE(Trans2_setfileinfo);
    5336        4265 :                 call_trans2setfileinfo(
    5337             :                         conn,
    5338             :                         req,
    5339             :                         &state->param,
    5340        4265 :                         state->total_param,
    5341             :                         &state->data,
    5342        4265 :                         state->total_data,
    5343             :                         state->max_data_return);
    5344        4265 :                 END_PROFILE(Trans2_setfileinfo);
    5345        3728 :                 break;
    5346             :         }
    5347             : 
    5348           0 :         case TRANSACT2_FINDNOTIFYFIRST:
    5349             :         {
    5350           0 :                 START_PROFILE(Trans2_findnotifyfirst);
    5351           0 :                 call_trans2findnotifyfirst(conn, req,
    5352           0 :                                            &state->param, state->total_param,
    5353           0 :                                            &state->data, state->total_data,
    5354             :                                            state->max_data_return);
    5355           0 :                 END_PROFILE(Trans2_findnotifyfirst);
    5356           0 :                 break;
    5357             :         }
    5358             : 
    5359           0 :         case TRANSACT2_FINDNOTIFYNEXT:
    5360             :         {
    5361           0 :                 START_PROFILE(Trans2_findnotifynext);
    5362           0 :                 call_trans2findnotifynext(conn, req,
    5363           0 :                                           &state->param, state->total_param,
    5364           0 :                                           &state->data, state->total_data,
    5365             :                                           state->max_data_return);
    5366           0 :                 END_PROFILE(Trans2_findnotifynext);
    5367           0 :                 break;
    5368             :         }
    5369             : 
    5370          23 :         case TRANSACT2_MKDIR:
    5371             :         {
    5372          23 :                 START_PROFILE(Trans2_mkdir);
    5373          23 :                 call_trans2mkdir(conn, req,
    5374          23 :                                  &state->param, state->total_param,
    5375          23 :                                  &state->data, state->total_data,
    5376             :                                  state->max_data_return);
    5377          23 :                 END_PROFILE(Trans2_mkdir);
    5378          20 :                 break;
    5379             :         }
    5380             : 
    5381        4372 :         case TRANSACT2_GET_DFS_REFERRAL:
    5382             :         {
    5383        4372 :                 START_PROFILE(Trans2_get_dfs_referral);
    5384        4372 :                 call_trans2getdfsreferral(conn, req,
    5385        4372 :                                           &state->param, state->total_param,
    5386        4372 :                                           &state->data, state->total_data,
    5387             :                                           state->max_data_return);
    5388        4372 :                 END_PROFILE(Trans2_get_dfs_referral);
    5389        4372 :                 break;
    5390             :         }
    5391             : 
    5392           0 :         case TRANSACT2_IOCTL:
    5393             :         {
    5394           0 :                 START_PROFILE(Trans2_ioctl);
    5395           0 :                 call_trans2ioctl(conn, req,
    5396           0 :                                  &state->param, state->total_param,
    5397           0 :                                  &state->data, state->total_data,
    5398             :                                  state->max_data_return);
    5399           0 :                 END_PROFILE(Trans2_ioctl);
    5400           0 :                 break;
    5401             :         }
    5402             : 
    5403           0 :         default:
    5404             :                 /* Error in request */
    5405           0 :                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
    5406           0 :                 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
    5407             :         }
    5408             : }
    5409             : 
    5410             : /****************************************************************************
    5411             :  Reply to a SMBtrans2.
    5412             :  ****************************************************************************/
    5413             : 
    5414       37803 : void reply_trans2(struct smb_request *req)
    5415             : {
    5416       37803 :         connection_struct *conn = req->conn;
    5417        1219 :         unsigned int dsoff;
    5418        1219 :         unsigned int dscnt;
    5419        1219 :         unsigned int psoff;
    5420        1219 :         unsigned int pscnt;
    5421        1219 :         unsigned int tran_call;
    5422        1219 :         struct trans_state *state;
    5423        1219 :         NTSTATUS result;
    5424             : 
    5425       37803 :         START_PROFILE(SMBtrans2);
    5426             : 
    5427       37803 :         if (req->wct < 14) {
    5428           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5429           0 :                 END_PROFILE(SMBtrans2);
    5430           0 :                 return;
    5431             :         }
    5432             : 
    5433       37803 :         dsoff = SVAL(req->vwv+12, 0);
    5434       37803 :         dscnt = SVAL(req->vwv+11, 0);
    5435       37803 :         psoff = SVAL(req->vwv+10, 0);
    5436       37803 :         pscnt = SVAL(req->vwv+9, 0);
    5437       37803 :         tran_call = SVAL(req->vwv+14, 0);
    5438             : 
    5439       37803 :         result = allow_new_trans(conn->pending_trans, req->mid);
    5440       37803 :         if (!NT_STATUS_IS_OK(result)) {
    5441           0 :                 DEBUG(2, ("Got invalid trans2 request: %s\n",
    5442             :                           nt_errstr(result)));
    5443           0 :                 reply_nterror(req, result);
    5444           0 :                 END_PROFILE(SMBtrans2);
    5445           0 :                 return;
    5446             :         }
    5447             : 
    5448       37803 :         if (IS_IPC(conn)) {
    5449        5092 :                 switch (tran_call) {
    5450             :                 /* List the allowed trans2 calls on IPC$ */
    5451        5092 :                 case TRANSACT2_OPEN:
    5452             :                 case TRANSACT2_GET_DFS_REFERRAL:
    5453             :                 case TRANSACT2_QFILEINFO:
    5454             :                 case TRANSACT2_QFSINFO:
    5455             :                 case TRANSACT2_SETFSINFO:
    5456        5092 :                         break;
    5457           0 :                 default:
    5458           0 :                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    5459           0 :                         END_PROFILE(SMBtrans2);
    5460           0 :                         return;
    5461             :                 }
    5462             :         }
    5463             : 
    5464       37803 :         if ((state = talloc(conn, struct trans_state)) == NULL) {
    5465           0 :                 DEBUG(0, ("talloc failed\n"));
    5466           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    5467           0 :                 END_PROFILE(SMBtrans2);
    5468           0 :                 return;
    5469             :         }
    5470             : 
    5471       37803 :         state->cmd = SMBtrans2;
    5472             : 
    5473       37803 :         state->mid = req->mid;
    5474       37803 :         state->vuid = req->vuid;
    5475       37803 :         state->setup_count = SVAL(req->vwv+13, 0);
    5476       37803 :         state->setup = NULL;
    5477       37803 :         state->total_param = SVAL(req->vwv+0, 0);
    5478       37803 :         state->param = NULL;
    5479       37803 :         state->total_data =  SVAL(req->vwv+1, 0);
    5480       37803 :         state->data = NULL;
    5481       37803 :         state->max_param_return = SVAL(req->vwv+2, 0);
    5482       37803 :         state->max_data_return  = SVAL(req->vwv+3, 0);
    5483       37803 :         state->max_setup_return = SVAL(req->vwv+4, 0);
    5484       37803 :         state->close_on_completion = BITSETW(req->vwv+5, 0);
    5485       37803 :         state->one_way = BITSETW(req->vwv+5, 1);
    5486             : 
    5487       37803 :         state->call = tran_call;
    5488             : 
    5489             :         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
    5490             :            is so as a sanity check */
    5491       37803 :         if (state->setup_count != 1) {
    5492             :                 /*
    5493             :                  * Need to have rc=0 for ioctl to get job id for OS/2.
    5494             :                  *  Network printing will fail if function is not successful.
    5495             :                  *  Similar function in reply.c will be used if protocol
    5496             :                  *  is LANMAN1.0 instead of LM1.2X002.
    5497             :                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
    5498             :                  *  outbuf doesn't have to be set(only job id is used).
    5499             :                  */
    5500           0 :                 if ( (state->setup_count == 4)
    5501           0 :                      && (tran_call == TRANSACT2_IOCTL)
    5502           0 :                      && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
    5503           0 :                      && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
    5504           0 :                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
    5505             :                 } else {
    5506           0 :                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
    5507           0 :                         DEBUG(2,("Transaction is %d\n",tran_call));
    5508           0 :                         TALLOC_FREE(state);
    5509           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5510           0 :                         END_PROFILE(SMBtrans2);
    5511           0 :                         return;
    5512             :                 }
    5513             :         }
    5514             : 
    5515       37803 :         if ((dscnt > state->total_data) || (pscnt > state->total_param))
    5516           0 :                 goto bad_param;
    5517             : 
    5518       37803 :         if (state->total_data) {
    5519             : 
    5520        7326 :                 if (smb_buffer_oob(state->total_data, 0, dscnt)
    5521        7326 :                     || smb_buffer_oob(smb_len(req->inbuf), dsoff, dscnt)) {
    5522           0 :                         goto bad_param;
    5523             :                 }
    5524             : 
    5525             :                 /* Can't use talloc here, the core routines do realloc on the
    5526             :                  * params and data. */
    5527        7326 :                 state->data = (char *)SMB_MALLOC(state->total_data);
    5528        7326 :                 if (state->data == NULL) {
    5529           0 :                         DEBUG(0,("reply_trans2: data malloc fail for %u "
    5530             :                                  "bytes !\n", (unsigned int)state->total_data));
    5531           0 :                         TALLOC_FREE(state);
    5532           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    5533           0 :                         END_PROFILE(SMBtrans2);
    5534           0 :                         return;
    5535             :                 }
    5536             : 
    5537        7326 :                 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
    5538             :         }
    5539             : 
    5540       37803 :         if (state->total_param) {
    5541             : 
    5542       37803 :                 if (smb_buffer_oob(state->total_param, 0, pscnt)
    5543       37803 :                     || smb_buffer_oob(smb_len(req->inbuf), psoff, pscnt)) {
    5544           0 :                         goto bad_param;
    5545             :                 }
    5546             : 
    5547             :                 /* Can't use talloc here, the core routines do realloc on the
    5548             :                  * params and data. */
    5549       37803 :                 state->param = (char *)SMB_MALLOC(state->total_param);
    5550       37803 :                 if (state->param == NULL) {
    5551           0 :                         DEBUG(0,("reply_trans: param malloc fail for %u "
    5552             :                                  "bytes !\n", (unsigned int)state->total_param));
    5553           0 :                         SAFE_FREE(state->data);
    5554           0 :                         TALLOC_FREE(state);
    5555           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    5556           0 :                         END_PROFILE(SMBtrans2);
    5557           0 :                         return;
    5558             :                 }
    5559             : 
    5560       37803 :                 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
    5561             :         }
    5562             : 
    5563       37803 :         state->received_data  = dscnt;
    5564       37803 :         state->received_param = pscnt;
    5565             : 
    5566       37803 :         if ((state->received_param == state->total_param) &&
    5567       37803 :             (state->received_data == state->total_data)) {
    5568             : 
    5569       37803 :                 handle_trans2(conn, req, state);
    5570             : 
    5571       37803 :                 SAFE_FREE(state->data);
    5572       37803 :                 SAFE_FREE(state->param);
    5573       37803 :                 TALLOC_FREE(state);
    5574       37803 :                 END_PROFILE(SMBtrans2);
    5575       37803 :                 return;
    5576             :         }
    5577             : 
    5578           0 :         DLIST_ADD(conn->pending_trans, state);
    5579             : 
    5580             :         /* We need to send an interim response then receive the rest
    5581             :            of the parameter/data bytes */
    5582           0 :         reply_smb1_outbuf(req, 0, 0);
    5583           0 :         show_msg((char *)req->outbuf);
    5584           0 :         END_PROFILE(SMBtrans2);
    5585           0 :         return;
    5586             : 
    5587           0 :   bad_param:
    5588             : 
    5589           0 :         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
    5590           0 :         SAFE_FREE(state->data);
    5591           0 :         SAFE_FREE(state->param);
    5592           0 :         TALLOC_FREE(state);
    5593           0 :         END_PROFILE(SMBtrans2);
    5594           0 :         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5595             : }
    5596             : 
    5597             : /****************************************************************************
    5598             :  Reply to a SMBtranss2
    5599             :  ****************************************************************************/
    5600             : 
    5601           0 : void reply_transs2(struct smb_request *req)
    5602             : {
    5603           0 :         connection_struct *conn = req->conn;
    5604           0 :         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
    5605           0 :         struct trans_state *state;
    5606             : 
    5607           0 :         START_PROFILE(SMBtranss2);
    5608             : 
    5609           0 :         show_msg((const char *)req->inbuf);
    5610             : 
    5611             :         /* Windows clients expect all replies to
    5612             :            a transact secondary (SMBtranss2 0x33)
    5613             :            to have a command code of transact
    5614             :            (SMBtrans2 0x32). See bug #8989
    5615             :            and also [MS-CIFS] section 2.2.4.47.2
    5616             :            for details.
    5617             :         */
    5618           0 :         req->cmd = SMBtrans2;
    5619             : 
    5620           0 :         if (req->wct < 8) {
    5621           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5622           0 :                 END_PROFILE(SMBtranss2);
    5623           0 :                 return;
    5624             :         }
    5625             : 
    5626           0 :         for (state = conn->pending_trans; state != NULL;
    5627           0 :              state = state->next) {
    5628           0 :                 if (state->mid == req->mid) {
    5629           0 :                         break;
    5630             :                 }
    5631             :         }
    5632             : 
    5633           0 :         if ((state == NULL) || (state->cmd != SMBtrans2)) {
    5634           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5635           0 :                 END_PROFILE(SMBtranss2);
    5636           0 :                 return;
    5637             :         }
    5638             : 
    5639             :         /* Revise state->total_param and state->total_data in case they have
    5640             :            changed downwards */
    5641             : 
    5642           0 :         if (SVAL(req->vwv+0, 0) < state->total_param)
    5643           0 :                 state->total_param = SVAL(req->vwv+0, 0);
    5644           0 :         if (SVAL(req->vwv+1, 0) < state->total_data)
    5645           0 :                 state->total_data = SVAL(req->vwv+1, 0);
    5646             : 
    5647           0 :         pcnt = SVAL(req->vwv+2, 0);
    5648           0 :         poff = SVAL(req->vwv+3, 0);
    5649           0 :         pdisp = SVAL(req->vwv+4, 0);
    5650             : 
    5651           0 :         dcnt = SVAL(req->vwv+5, 0);
    5652           0 :         doff = SVAL(req->vwv+6, 0);
    5653           0 :         ddisp = SVAL(req->vwv+7, 0);
    5654             : 
    5655           0 :         state->received_param += pcnt;
    5656           0 :         state->received_data += dcnt;
    5657             : 
    5658           0 :         if ((state->received_data > state->total_data) ||
    5659           0 :             (state->received_param > state->total_param))
    5660           0 :                 goto bad_param;
    5661             : 
    5662           0 :         if (pcnt) {
    5663           0 :                 if (smb_buffer_oob(state->total_param, pdisp, pcnt)
    5664           0 :                     || smb_buffer_oob(smb_len(req->inbuf), poff, pcnt)) {
    5665           0 :                         goto bad_param;
    5666             :                 }
    5667           0 :                 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
    5668             :         }
    5669             : 
    5670           0 :         if (dcnt) {
    5671           0 :                 if (smb_buffer_oob(state->total_data, ddisp, dcnt)
    5672           0 :                     || smb_buffer_oob(smb_len(req->inbuf), doff, dcnt)) {
    5673           0 :                         goto bad_param;
    5674             :                 }
    5675           0 :                 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
    5676             :         }
    5677             : 
    5678           0 :         if ((state->received_param < state->total_param) ||
    5679           0 :             (state->received_data < state->total_data)) {
    5680           0 :                 END_PROFILE(SMBtranss2);
    5681           0 :                 return;
    5682             :         }
    5683             : 
    5684           0 :         handle_trans2(conn, req, state);
    5685             : 
    5686           0 :         DLIST_REMOVE(conn->pending_trans, state);
    5687           0 :         SAFE_FREE(state->data);
    5688           0 :         SAFE_FREE(state->param);
    5689           0 :         TALLOC_FREE(state);
    5690             : 
    5691           0 :         END_PROFILE(SMBtranss2);
    5692           0 :         return;
    5693             : 
    5694           0 :   bad_param:
    5695             : 
    5696           0 :         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
    5697           0 :         DLIST_REMOVE(conn->pending_trans, state);
    5698           0 :         SAFE_FREE(state->data);
    5699           0 :         SAFE_FREE(state->param);
    5700           0 :         TALLOC_FREE(state);
    5701           0 :         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5702           0 :         END_PROFILE(SMBtranss2);
    5703             : }

Generated by: LCOV version 1.14