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

Generated by: LCOV version 1.14